From 5a1c1ca62940aabf2be5b8f3808d1cd1d58f5389 Mon Sep 17 00:00:00 2001 From: tegwick Date: Mon, 22 Jun 2026 23:16:28 +0200 Subject: [PATCH 01/10] 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 --- .claude/rules/agents.md | 20 +++ .claude/rules/architecture.md | 8 + .claude/rules/first-session.md | 38 +++++ .claude/rules/repo-boundary.md | 8 + .claude/rules/repo-identity.md | 5 + .claude/rules/session-protocol.md | 85 +++++++++++ .claude/rules/stack-and-commands.md | 19 +++ .claude/rules/workplan-convention.md | 40 +++++ AGENTS.md | 138 ++++++++---------- CLAUDE.md | 12 ++ .../FORGE-WP-0001-repository-foundation.md | 2 +- ...-WP-0002-registry-docs-and-readonly-ops.md | 2 +- .../FORGE-WP-0003-actions-runner-substrate.md | 2 +- ...ORGE-WP-0004-public-gitea-root-endpoint.md | 2 +- ...WP-0005-remove-gitea-nodeport-side-door.md | 2 +- 15 files changed, 297 insertions(+), 86 deletions(-) create mode 100644 .claude/rules/agents.md create mode 100644 .claude/rules/architecture.md create mode 100644 .claude/rules/first-session.md create mode 100644 .claude/rules/repo-boundary.md create mode 100644 .claude/rules/repo-identity.md create mode 100644 .claude/rules/session-protocol.md create mode 100644 .claude/rules/stack-and-commands.md create mode 100644 .claude/rules/workplan-convention.md create mode 100644 CLAUDE.md diff --git a/.claude/rules/agents.md b/.claude/rules/agents.md new file mode 100644 index 0000000..0e8a5d9 --- /dev/null +++ b/.claude/rules/agents.md @@ -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. diff --git a/.claude/rules/architecture.md b/.claude/rules/architecture.md new file mode 100644 index 0000000..7c2a645 --- /dev/null +++ b/.claude/rules/architecture.md @@ -0,0 +1,8 @@ +## Architecture + + + +## Quick Reference + +`~/state-hub/mcp_server/TOOLS.md` — MCP tool reference diff --git a/.claude/rules/first-session.md b/.claude/rules/first-session.md new file mode 100644 index 0000000..47cd872 --- /dev/null +++ b/.claude/rules/first-session.md @@ -0,0 +1,38 @@ +## First Session Protocol + +Triggered when `get_domain_summary("financials")` shows **no workstreams**. +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 workstreams to Bernd** +Propose 1–3 workstreams — each a coherent strand, weeks to months, anchored to a +roadmap phase. **Wait for approval before creating.** + +**Step 4 — Create workplan file first, then DB record (ADR-001)** +``` +workplans/FORGE-WP-NNNN-.md ← write this first +``` +Then register in the hub: +``` +create_workstream(topic_id="ca369340-a64e-442e-98f1-a4fa7dc74a38", title="...", owner="...", description="...") +create_task(workstream_id="", title="...", priority="high|medium|low") +``` + +**Step 5 — Record the setup** +``` +add_progress_event( + summary="First session: structured financials into N workstreams, M tasks", + event_type="milestone", + topic_id="ca369340-a64e-442e-98f1-a4fa7dc74a38", + detail={"workstreams": [...], "tasks_created": M} +) +``` + + diff --git a/.claude/rules/repo-boundary.md b/.claude/rules/repo-boundary.md new file mode 100644 index 0000000..c285418 --- /dev/null +++ b/.claude/rules/repo-boundary.md @@ -0,0 +1,8 @@ +## Repo boundary + +This repo owns **railiance-forge** only. It does not own: + + diff --git a/.claude/rules/repo-identity.md b/.claude/rules/repo-identity.md new file mode 100644 index 0000000..84122df --- /dev/null +++ b/.claude/rules/repo-identity.md @@ -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 diff --git a/.claude/rules/session-protocol.md b/.claude/rules/session-protocol.md new file mode 100644 index 0000000..fe2f48d --- /dev/null +++ b/.claude/rules/session-protocol.md @@ -0,0 +1,85 @@ +## 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//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 workstreams** 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 workstreams: follow First Session Protocol (`first-session.md`). + +**During work:** `record_decision()` · `add_progress_event()` · `resolve_decision()` + +> State Hub is a *read model*. Bootstrap tools (`create_workstream`, `create_task`) +> are First Session Protocol only. Work structure belongs in repo files (ADR-001). + +**Session close:** +With MCP tools: +``` +add_progress_event(summary="...", topic_id="ca369340-a64e-442e-98f1-a4fa7dc74a38", workstream_id="") +``` +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","workstream_id":"","event_type":"note","summary":"what changed","author":"codex"}' +``` +If workplan files were modified, ensure the local copy is up to date first: +```bash +git -C pull --ff-only +cd ~/state-hub && make fix-consistency REPO=railiance-forge +``` +For repos where implementation runs on a remote machine (e.g. CoulombCore), +use the combined target which pulls before fixing: +```bash +cd ~/state-hub && make fix-consistency-remote REPO=railiance-forge +``` +**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. diff --git a/.claude/rules/stack-and-commands.md b/.claude/rules/stack-and-commands.md new file mode 100644 index 0000000..dc53ac6 --- /dev/null +++ b/.claude/rules/stack-and-commands.md @@ -0,0 +1,19 @@ +## Stack + + +- **Language:** +- **Key deps:** + +## Dev Commands + +```bash +# TODO: Fill in the standard commands for this repo + +# Install dependencies + +# Run tests + +# Lint / type check + +# Build / package (if applicable) +``` diff --git a/.claude/rules/workplan-convention.md b/.claude/rules/workplan-convention.md new file mode 100644 index 0000000..dcd3bb9 --- /dev/null +++ b/.claude/rules/workplan-convention.md @@ -0,0 +1,40 @@ +## Workplan Convention (ADR-001) + +File location: `workplans/FORGE-WP-NNNN-.md` +ID prefix: `FORGE-WP-` + +Work items originate as files in this repo **before** being registered in the hub. + +Canonical workplan/workstream 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-FORGE-WP-NNNN-.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`, workstream 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, then registering +the workstream. + +Task blocks use this shape: + +```task +id: FORGE-WP-NNNN-T01 +status: wait | todo | progress | done | cancel +priority: high | medium | low +state_hub_task_id: "" # 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. + + diff --git a/AGENTS.md b/AGENTS.md index 3a89c44..ed75642 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,12 +1,10 @@ -# 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-` @@ -15,7 +13,7 @@ and future Forgejo migration. ## 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 | @@ -26,23 +24,25 @@ there is no MCP server for Codex agents. ### Orient at session start ```bash +# Offline brief — works without hub connection cat .custodian-brief.md +# Active workstreams for this domain curl -s "http://127.0.0.1:8000/workstreams/?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//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/ \ @@ -64,10 +64,9 @@ Omit `workstream_id` / `task_id` when not applicable. curl -s -X PATCH "http://127.0.0.1:8000/tasks/" \ -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 +80,24 @@ curl -s -X PATCH "http://127.0.0.1:8000/tasks/" \ ## 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 workstreams (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. Note for the custodian operator: after workplan file changes, run from + `~/state-hub`: ```bash make fix-consistency REPO=railiance-forge ``` + This syncs task status from files into the hub DB. --- @@ -174,70 +151,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` + + + + --- -## 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-.md` +**File location:** `workplans/RAILIANCE-WP-NNNN-.md` -**Archived location:** `workplans/archived/YYMMDD-FORGE-WP-NNNN-.md` +**Archived location:** finished workplans may move to +`workplans/archived/YYMMDD-RAILIANCE-WP-NNNN-.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: "" # written by fix-consistency - do not edit +state_hub_workstream_id: "" # 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: "" # written by fix-consistency - do not edit -``` +state_hub_task_id: "" # 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/`) diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..aa1d61e --- /dev/null +++ b/CLAUDE.md @@ -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 diff --git a/workplans/FORGE-WP-0001-repository-foundation.md b/workplans/FORGE-WP-0001-repository-foundation.md index b34676e..7cb765c 100644 --- a/workplans/FORGE-WP-0001-repository-foundation.md +++ b/workplans/FORGE-WP-0001-repository-foundation.md @@ -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 diff --git a/workplans/FORGE-WP-0002-registry-docs-and-readonly-ops.md b/workplans/FORGE-WP-0002-registry-docs-and-readonly-ops.md index bf21513..c97127a 100644 --- a/workplans/FORGE-WP-0002-registry-docs-and-readonly-ops.md +++ b/workplans/FORGE-WP-0002-registry-docs-and-readonly-ops.md @@ -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 diff --git a/workplans/FORGE-WP-0003-actions-runner-substrate.md b/workplans/FORGE-WP-0003-actions-runner-substrate.md index 16779fc..9a28b1b 100644 --- a/workplans/FORGE-WP-0003-actions-runner-substrate.md +++ b/workplans/FORGE-WP-0003-actions-runner-substrate.md @@ -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 diff --git a/workplans/FORGE-WP-0004-public-gitea-root-endpoint.md b/workplans/FORGE-WP-0004-public-gitea-root-endpoint.md index cf86955..b510fa9 100644 --- a/workplans/FORGE-WP-0004-public-gitea-root-endpoint.md +++ b/workplans/FORGE-WP-0004-public-gitea-root-endpoint.md @@ -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 diff --git a/workplans/FORGE-WP-0005-remove-gitea-nodeport-side-door.md b/workplans/FORGE-WP-0005-remove-gitea-nodeport-side-door.md index f2cfb1d..a914b86 100644 --- a/workplans/FORGE-WP-0005-remove-gitea-nodeport-side-door.md +++ b/workplans/FORGE-WP-0005-remove-gitea-nodeport-side-door.md @@ -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 From a858daf90aa53d13cd0890bb938aa80b54bab956 Mon Sep 17 00:00:00 2001 From: tegwick Date: Thu, 2 Jul 2026 00:21:49 +0200 Subject: [PATCH 02/10] 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 --- .claude/rules/stack-and-commands.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/.claude/rules/stack-and-commands.md b/.claude/rules/stack-and-commands.md index dc53ac6..d3683f6 100644 --- a/.claude/rules/stack-and-commands.md +++ b/.claude/rules/stack-and-commands.md @@ -1,19 +1,18 @@ ## Stack - -- **Language:** -- **Key deps:** +- **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 -# TODO: Fill in the standard commands for this repo - -# Install dependencies - -# Run tests - -# Lint / type check - -# Build / package (if applicable) +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. From effe568e07b77dbb533845b06ad228e43b0b8c6b Mon Sep 17 00:00:00 2001 From: tegwick Date: Thu, 2 Jul 2026 00:24:25 +0200 Subject: [PATCH 03/10] chore(consistency): sync task status from DB [auto] Updated by fix-consistency on 2026-07-02: - update .custodian-brief.md for railiance-forge --- .custodian-brief.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.custodian-brief.md b/.custodian-brief.md index 79c84b3..e3659fc 100644 --- a/.custodian-brief.md +++ b/.custodian-brief.md @@ -1,8 +1,8 @@ # 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. From acaef67f4d8b707e497374593ebbb25af3b2bbe6 Mon Sep 17 00:00:00 2001 From: tegwick Date: Thu, 2 Jul 2026 00:25:42 +0200 Subject: [PATCH 04/10] Archive closed workplans to workplans/archived/ (ADR-001) Co-Authored-By: Claude Fable 5 --- .../260702-FORGE-WP-0001-repository-foundation.md} | 0 .../260702-FORGE-WP-0002-registry-docs-and-readonly-ops.md} | 0 .../260702-FORGE-WP-0003-actions-runner-substrate.md} | 0 .../260702-FORGE-WP-0004-public-gitea-root-endpoint.md} | 0 .../260702-FORGE-WP-0005-remove-gitea-nodeport-side-door.md} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename workplans/{FORGE-WP-0001-repository-foundation.md => archived/260702-FORGE-WP-0001-repository-foundation.md} (100%) rename workplans/{FORGE-WP-0002-registry-docs-and-readonly-ops.md => archived/260702-FORGE-WP-0002-registry-docs-and-readonly-ops.md} (100%) rename workplans/{FORGE-WP-0003-actions-runner-substrate.md => archived/260702-FORGE-WP-0003-actions-runner-substrate.md} (100%) rename workplans/{FORGE-WP-0004-public-gitea-root-endpoint.md => archived/260702-FORGE-WP-0004-public-gitea-root-endpoint.md} (100%) rename workplans/{FORGE-WP-0005-remove-gitea-nodeport-side-door.md => archived/260702-FORGE-WP-0005-remove-gitea-nodeport-side-door.md} (100%) diff --git a/workplans/FORGE-WP-0001-repository-foundation.md b/workplans/archived/260702-FORGE-WP-0001-repository-foundation.md similarity index 100% rename from workplans/FORGE-WP-0001-repository-foundation.md rename to workplans/archived/260702-FORGE-WP-0001-repository-foundation.md diff --git a/workplans/FORGE-WP-0002-registry-docs-and-readonly-ops.md b/workplans/archived/260702-FORGE-WP-0002-registry-docs-and-readonly-ops.md similarity index 100% rename from workplans/FORGE-WP-0002-registry-docs-and-readonly-ops.md rename to workplans/archived/260702-FORGE-WP-0002-registry-docs-and-readonly-ops.md diff --git a/workplans/FORGE-WP-0003-actions-runner-substrate.md b/workplans/archived/260702-FORGE-WP-0003-actions-runner-substrate.md similarity index 100% rename from workplans/FORGE-WP-0003-actions-runner-substrate.md rename to workplans/archived/260702-FORGE-WP-0003-actions-runner-substrate.md diff --git a/workplans/FORGE-WP-0004-public-gitea-root-endpoint.md b/workplans/archived/260702-FORGE-WP-0004-public-gitea-root-endpoint.md similarity index 100% rename from workplans/FORGE-WP-0004-public-gitea-root-endpoint.md rename to workplans/archived/260702-FORGE-WP-0004-public-gitea-root-endpoint.md diff --git a/workplans/FORGE-WP-0005-remove-gitea-nodeport-side-door.md b/workplans/archived/260702-FORGE-WP-0005-remove-gitea-nodeport-side-door.md similarity index 100% rename from workplans/FORGE-WP-0005-remove-gitea-nodeport-side-door.md rename to workplans/archived/260702-FORGE-WP-0005-remove-gitea-nodeport-side-door.md From 36a3030f7896f9e66ac17f3eae4e5309f26b2516 Mon Sep 17 00:00:00 2001 From: tegwick Date: Thu, 2 Jul 2026 01:47:46 +0200 Subject: [PATCH 05/10] 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 --- .claude/rules/credential-routing.md | 2 +- .claude/rules/first-session.md | 26 +++++++++++++---------- .claude/rules/session-protocol.md | 31 ++++++++++++++++++---------- .claude/rules/workplan-convention.md | 21 ++++++++++++------- AGENTS.md | 28 +++++++++++++++---------- 5 files changed, 66 insertions(+), 42 deletions(-) diff --git a/.claude/rules/credential-routing.md b/.claude/rules/credential-routing.md index b3d8073..adb56b9 100644 --- a/.claude/rules/credential-routing.md +++ b/.claude/rules/credential-routing.md @@ -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 diff --git a/.claude/rules/first-session.md b/.claude/rules/first-session.md index 47cd872..e4edf87 100644 --- a/.claude/rules/first-session.md +++ b/.claude/rules/first-session.md @@ -1,6 +1,6 @@ ## First Session Protocol -Triggered when `get_domain_summary("financials")` shows **no workstreams**. +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** @@ -11,27 +11,31 @@ The project is registered but work has not yet been structured. **Step 2 — Survey in-progress work** Look for TODOs, open branches, half-finished files. Note done vs. started but incomplete. -**Step 3 — Propose workstreams to Bernd** -Propose 1–3 workstreams — each a coherent strand, weeks to months, anchored to a +**Step 3 — Propose workplans to Bernd** +Propose 1–3 workplans — each a coherent strand, weeks to months, anchored to a roadmap phase. **Wait for approval before creating.** -**Step 4 — Create workplan file first, then DB record (ADR-001)** +**Step 4 — Write the workplan file; fix-consistency registers it (ADR-001)** ``` -workplans/FORGE-WP-NNNN-.md ← write this first +workplans/RAILIANCE-WP-NNNN-.md ← write this, commit it ``` -Then register in the hub: -``` -create_workstream(topic_id="ca369340-a64e-442e-98f1-a4fa7dc74a38", title="...", owner="...", description="...") -create_task(workstream_id="", title="...", priority="high|medium|low") +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 workstreams, M tasks", + summary="First session: structured financials into N workplans, M tasks", event_type="milestone", topic_id="ca369340-a64e-442e-98f1-a4fa7dc74a38", - detail={"workstreams": [...], "tasks_created": M} + detail={"workplans": [...], "tasks_created": M} ) ``` diff --git a/.claude/rules/session-protocol.md b/.claude/rules/session-protocol.md index fe2f48d..7e966dc 100644 --- a/.claude/rules/session-protocol.md +++ b/.claude/rules/session-protocol.md @@ -44,7 +44,7 @@ For each file with `status: ready`, `active`, or `blocked`, note pending **Step 4 — Present brief** -1. **Active workstreams** for `financials` — title, task counts, blocking decisions +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"* @@ -52,33 +52,42 @@ For each file with `status: ready`, `active`, or `blocked`, note pending 4. **Suggested next action** — highest-priority open item 5. **SBOM status** — flag if `last_sbom_at` is unset for this repo -If no workstreams: follow First Session Protocol (`first-session.md`). +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*. Bootstrap tools (`create_workstream`, `create_task`) -> are First Session Protocol only. Work structure belongs in repo files (ADR-001). +> 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", workstream_id="") +add_progress_event(summary="...", topic_id="ca369340-a64e-442e-98f1-a4fa7dc74a38", workplan_id="") ``` 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","workstream_id":"","event_type":"note","summary":"what changed","author":"codex"}' + -d '{"topic_id":"ca369340-a64e-442e-98f1-a4fa7dc74a38","workplan_id":"","event_type":"note","summary":"what changed","author":"codex"}' ``` -If workplan files were modified, ensure the local copy is up to date first: +If workplan files were modified, ensure the local copy is up to date first, +then sync from the repo checkout: ```bash -git -C pull --ff-only -cd ~/state-hub && make fix-consistency REPO=railiance-forge +git pull --ff-only +statehub fix-consistency ``` For repos where implementation runs on a remote machine (e.g. CoulombCore), -use the combined target which pulls before fixing: +use the pull-before-fix mode from any shell with the State Hub CLI: ```bash -cd ~/state-hub && make fix-consistency-remote REPO=railiance-forge +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 diff --git a/.claude/rules/workplan-convention.md b/.claude/rules/workplan-convention.md index dcd3bb9..1f4b616 100644 --- a/.claude/rules/workplan-convention.md +++ b/.claude/rules/workplan-convention.md @@ -1,34 +1,35 @@ ## Workplan Convention (ADR-001) -File location: `workplans/FORGE-WP-NNNN-.md` -ID prefix: `FORGE-WP-` +File location: `workplans/RAILIANCE-WP-NNNN-.md` +ID prefix: `RAILIANCE-WP-` Work items originate as files in this repo **before** being registered in the hub. -Canonical workplan/workstream frontmatter statuses are: +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-FORGE-WP-NNNN-.md`. The frontmatter id remains +prefix: `YYMMDD-RAILIANCE-WP-NNNN-.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`, workstream slug `adhoc-YYYY-MM-DD`, and task ids +`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, then registering -the workstream. +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: FORGE-WP-NNNN-T01 +id: RAILIANCE-WP-NNNN-T01 status: wait | todo | progress | done | cancel priority: high | medium | low state_hub_task_id: "" # written by fix-consistency — do not edit @@ -37,4 +38,8 @@ state_hub_task_id: "" # 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. + diff --git a/AGENTS.md b/AGENTS.md index ed75642..e3e32fe 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,7 +7,7 @@ **Domain:** financials **Repo slug:** railiance-forge **Topic ID:** `ca369340-a64e-442e-98f1-a4fa7dc74a38` -**Workplan prefix:** `FORGE-WP-` +**Workplan prefix:** `RAILIANCE-WP-` --- @@ -20,6 +20,12 @@ there is no MCP server for Codex agents. |---------|-----| | 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 @@ -27,8 +33,8 @@ there is no MCP server for Codex agents. # Offline brief — works without hub connection cat .custodian-brief.md -# Active workstreams for this domain -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 @@ -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": "", + "workplan_id": "", "task_id": "" }' ``` -Omit `workstream_id` / `task_id` when not applicable. +Omit `workplan_id` / `task_id` when not applicable. ### Update task status @@ -80,7 +86,7 @@ curl -s -X PATCH "http://127.0.0.1:8000/tasks/" \ ## Session Protocol **Start:** -1. `cat .custodian-brief.md` — domain goal and open workstreams (offline-safe) +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` @@ -92,12 +98,12 @@ curl -s -X PATCH "http://127.0.0.1:8000/tasks/" \ **Close:** 1. Update workplan file task statuses to reflect progress 2. Log: `POST /progress/` with a summary of what changed -3. Note for the custodian operator: after workplan file changes, run from - `~/state-hub`: +3. After workplan file changes, run: ```bash - make fix-consistency REPO=railiance-forge + statehub fix-consistency ``` - This syncs task status from files into the hub DB. + 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. --- @@ -123,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 From 7aae00e9334243fb583032f8aeb3deb41385561d Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 3 Jul 2026 21:44:57 +0200 Subject: [PATCH 06/10] 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. --- Makefile | 5 +- docs/forgejo-actions-runner-substrate.md | 76 ++++++++++++++++++++++++ tools/forgejo-runner-status.sh | 46 ++++++++++++++ 3 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 docs/forgejo-actions-runner-substrate.md create mode 100755 tools/forgejo-runner-status.sh diff --git a/Makefile b/Makefile index f847034..a3e0f9d 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/docs/forgejo-actions-runner-substrate.md b/docs/forgejo-actions-runner-substrate.md new file mode 100644 index 0000000..0e381b8 --- /dev/null +++ b/docs/forgejo-actions-runner-substrate.md @@ -0,0 +1,76 @@ +# Forgejo Actions Runner Substrate + +Last reviewed: 2026-07-03 + +Status: first supported runner on coulombcore (interim). Forgejo instance runs on +railiance01; runner host is intentionally separate per Forgejo security guidance. + +## Purpose + +Provide a forge-owned Actions runner for `https://forgejo.coulomb.social` so +repos in the `coulomb` organization can build and publish without workstation +involvement. Mirrors the Gitea runner contract in +`docs/gitea-actions-runner-substrate.md`. + +## First Supported Runner + +| Field | Value | +| --- | --- | +| Runner name | `railiance-coulombcore-build-01` | +| Runner scope | `coulomb` organization | +| Host | coulombcore (`92.205.130.254`) | +| Instance | `https://forgejo.coulomb.social/` | +| Binary | `forgejo-runner` v6.3.1 | +| Runtime | Host mode (Docker not installed on host yet) | +| Cluster deploy authority | Not included | + +### Labels + +```text +self-hosted:host,linux:host,linux_amd64:host,container-build:host,registry-publish:host,railiance01:host +``` + +`self-hosted` preserves compatibility with existing Gitea workflow `runs-on` +values during migration. Container image builds require Docker on the runner +host — install before cutover of image-publishing workflows. + +## Service Layout + +| Path | Purpose | +| --- | --- | +| `/usr/local/bin/forgejo-runner` | Runner binary | +| `/var/lib/forgejo-runner/config.yaml` | Generated config | +| `/var/lib/forgejo-runner/.runner` | Registration state (secret) | +| `/etc/systemd/system/forgejo-runner.service` | systemd unit | + +## Probe Evidence (2026-07-03) + +- Org `coulomb` created on Forgejo. +- Runner registered and `systemctl is-active forgejo-runner` → `active`. +- Repo `coulomb/forgejo-actions-probe` workflow `probe.yaml` (`runs-on: self-hosted`) + completed with `status: success` (API: `/api/v1/repos/coulomb/forgejo-actions-probe/actions/tasks`). + +## Operator Commands + +```bash +# Runner health (from railiance-forge) +RUNNER_HOST=coulombcore make forgejo-runner-status + +# Forgejo app smoke (from railiance-apps) +make -C ~/railiance-apps forgejo-smoke + +# Generate a new org registration token (in cluster, no token in logs) +KUBECONFIG=~/.kube/config-hosteurope kubectl exec -n forgejo deploy/forgejo-gitea -- \ + forgejo actions generate-runner-token --scope coulomb +``` + +## Secret Boundaries + +Same as Gitea runner substrate: registration tokens and `.runner` files stay +off Git. Use approved secret paths on the runner host only. + +## Follow-On + +1. Install Docker on the approved runner host for `container-build` jobs. +2. Move runner to a non-legacy host before coulombcore decommission (T03 drain). +3. Add repo-scoped registry credentials in Forgejo org secrets for image push. \ No newline at end of file diff --git a/tools/forgejo-runner-status.sh b/tools/forgejo-runner-status.sh new file mode 100755 index 0000000..97e2094 --- /dev/null +++ b/tools/forgejo-runner-status.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +set -u + +FORGEJO_URL="${FORGEJO_URL:-https://forgejo.coulomb.social}" +RUNNER_HOST="${RUNNER_HOST:-coulombcore}" +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 "Runner host probe" +if 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 + ' +else + echo "ssh missing; skipping runner host probe" +fi \ No newline at end of file From dc341d7cc632c874c48b78e76b4f1e5bc0370b6a Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 3 Jul 2026 22:29:28 +0200 Subject: [PATCH 07/10] Point Forgejo runner substrate at in-cluster railiance01 (ADR-004) Status probe checks k8s runner first; documents retirement of coulombcore interim host runner. --- docs/forgejo-actions-runner-substrate.md | 88 ++++++++++++------------ tools/forgejo-runner-status.sh | 19 +++-- 2 files changed, 58 insertions(+), 49 deletions(-) diff --git a/docs/forgejo-actions-runner-substrate.md b/docs/forgejo-actions-runner-substrate.md index 0e381b8..f8778f7 100644 --- a/docs/forgejo-actions-runner-substrate.md +++ b/docs/forgejo-actions-runner-substrate.md @@ -2,75 +2,73 @@ Last reviewed: 2026-07-03 -Status: first supported runner on coulombcore (interim). Forgejo instance runs on -railiance01; runner host is intentionally separate per Forgejo security guidance. +Status: **in-cluster runner on railiance01** (ADR-004). Supersedes interim coulombcore +host runner. ## Purpose -Provide a forge-owned Actions runner for `https://forgejo.coulomb.social` so -repos in the `coulomb` organization can build and publish without workstation -involvement. Mirrors the Gitea runner contract in -`docs/gitea-actions-runner-substrate.md`. +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`. -## First Supported Runner +## Production Runner (ADR-004) | Field | Value | | --- | --- | -| Runner name | `railiance-coulombcore-build-01` | -| Runner scope | `coulomb` organization | -| Host | coulombcore (`92.205.130.254`) | -| Instance | `https://forgejo.coulomb.social/` | -| Binary | `forgejo-runner` v6.3.1 | -| Runtime | Host mode (Docker not installed on host yet) | +| 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 +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 ``` -`self-hosted` preserves compatibility with existing Gitea workflow `runs-on` -values during migration. Container image builds require Docker on the runner -host — install before cutover of image-publishing workflows. - -## Service Layout - -| Path | Purpose | -| --- | --- | -| `/usr/local/bin/forgejo-runner` | Runner binary | -| `/var/lib/forgejo-runner/config.yaml` | Generated config | -| `/var/lib/forgejo-runner/.runner` | Registration state (secret) | -| `/etc/systemd/system/forgejo-runner.service` | systemd unit | - -## Probe Evidence (2026-07-03) - -- Org `coulomb` created on Forgejo. -- Runner registered and `systemctl is-active forgejo-runner` → `active`. -- Repo `coulomb/forgejo-actions-probe` workflow `probe.yaml` (`runs-on: self-hosted`) - completed with `status: success` (API: `/api/v1/repos/coulomb/forgejo-actions-probe/actions/tasks`). - ## Operator Commands ```bash -# Runner health (from railiance-forge) -RUNNER_HOST=coulombcore make forgejo-runner-status +# S5 deploy (railiance-apps) +cd ~/railiance-apps +make forgejo-runner-registration-deploy # after SOPS encrypt +make forgejo-runner-deploy +make forgejo-runner-status -# Forgejo app smoke (from railiance-apps) -make -C ~/railiance-apps forgejo-smoke +# Endpoint smoke +make forgejo-smoke -# Generate a new org registration token (in cluster, no token in logs) +# 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 -Same as Gitea runner substrate: registration tokens and `.runner` files stay -off Git. Use approved secret paths on the runner host only. +- `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. -## Follow-On +## Retired: Interim coulombcore Host Runner -1. Install Docker on the approved runner host for `container-build` jobs. -2. Move runner to a non-legacy host before coulombcore decommission (T03 drain). -3. Add repo-scoped registry credentials in Forgejo org secrets for image push. \ No newline at end of file +`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: verify with `make forgejo-runner-status` and a container `runs-on: ubuntu-latest` job. + +## 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/) \ No newline at end of file diff --git a/tools/forgejo-runner-status.sh b/tools/forgejo-runner-status.sh index 97e2094..70a0f9f 100755 --- a/tools/forgejo-runner-status.sh +++ b/tools/forgejo-runner-status.sh @@ -2,7 +2,8 @@ set -u FORGEJO_URL="${FORGEJO_URL:-https://forgejo.coulomb.social}" -RUNNER_HOST="${RUNNER_HOST:-coulombcore}" +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}" @@ -25,8 +26,16 @@ else echo "curl missing; skipping endpoint checks" fi -section "Runner host probe" -if have ssh; then +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}") @@ -41,6 +50,8 @@ if have ssh; then 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 "ssh missing; skipping runner host probe" + echo "RUNNER_HOST unset; skipping legacy host probe" fi \ No newline at end of file From 8d4f9ad58727cd05b857f8f12c4896b9ad2fe312 Mon Sep 17 00:00:00 2001 From: tegwick Date: Sat, 4 Jul 2026 00:47:47 +0200 Subject: [PATCH 08/10] 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. --- docs/forgejo-actions-runner-substrate.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/forgejo-actions-runner-substrate.md b/docs/forgejo-actions-runner-substrate.md index f8778f7..3b5586f 100644 --- a/docs/forgejo-actions-runner-substrate.md +++ b/docs/forgejo-actions-runner-substrate.md @@ -66,7 +66,13 @@ ssh coulombcore 'sudo systemctl disable --now forgejo-runner' ## Evidence - Host probe (2026-07-03): `coulomb/forgejo-actions-probe` workflow `success`. -- In-cluster: verify with `make forgejo-runner-status` and a container `runs-on: ubuntu-latest` job. +- 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 From 401e7f9f6b1d7ce37ca7d8db92eb0f26d7f70f5b Mon Sep 17 00:00:00 2001 From: tegwick Date: Mon, 6 Jul 2026 19:50:53 +0200 Subject: [PATCH 09/10] 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 --- ...pability.railiance.forge-infrastructure.md | 129 ++++++++++++++++++ registry/indexes/capabilities.yaml | 22 ++- 2 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 registry/capabilities/capability.railiance.forge-infrastructure.md diff --git a/registry/capabilities/capability.railiance.forge-infrastructure.md b/registry/capabilities/capability.railiance.forge-infrastructure.md new file mode 100644 index 0000000..9dc21e2 --- /dev/null +++ b/registry/capabilities/capability.railiance.forge-infrastructure.md @@ -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..` 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` diff --git a/registry/indexes/capabilities.yaml b/registry/indexes/capabilities.yaml index f944e47..6437991 100644 --- a/registry/indexes/capabilities.yaml +++ b/registry/indexes/capabilities.yaml @@ -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 From eb817e95392340859e940a1f39882eeecaddc30a Mon Sep 17 00:00:00 2001 From: tegwick Date: Wed, 8 Jul 2026 12:35:48 +0200 Subject: [PATCH 10/10] Add Forgejo CI smoke workflow (enablement template) --- .forgejo/workflows/ci-smoke.yaml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .forgejo/workflows/ci-smoke.yaml diff --git a/.forgejo/workflows/ci-smoke.yaml b/.forgejo/workflows/ci-smoke.yaml new file mode 100644 index 0000000..bd44c56 --- /dev/null +++ b/.forgejo/workflows/ci-smoke.yaml @@ -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}" \ No newline at end of file