From a9301a009c82467e97479f847e2034b71b07f180 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 5 Jun 2026 00:56:34 +0200 Subject: [PATCH 01/10] Add enablement intent --- INTENT.md | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 INTENT.md diff --git a/INTENT.md b/INTENT.md new file mode 100644 index 0000000..93d1f46 --- /dev/null +++ b/INTENT.md @@ -0,0 +1,136 @@ +# INTENT + +> This file captures **why this repository exists**, +> the **direction it is moving toward**, and +> the **kind of system it is meant to become**. +> It is intentionally **aspirational and stable**, not a description of current implementation. + +--- + +## One-liner + +**The developer enablement layer - turning Railiance platform capabilities into paved paths for building, testing, packaging, and promoting workloads.** + +--- + +## Why This Exists + +A healthy platform does not automatically make delivery easy. +Developers and operators still need repeatable ways to build workloads, test +them, package them, route them through review, and hand them to application +release surfaces without inventing those paths from scratch each time. + +Without a disciplined enablement layer: + +* every workload invents a different pipeline, +* build and deployment templates drift, +* platform capabilities are hard to consume correctly, +* and application releases depend on undocumented operator memory. + +This layer exists to provide **paved delivery paths**: shared automation, +templates, SDKs, build conventions, and self-service workflows that let +Railiance evolve faster without dissolving its layer boundaries. + +--- + +## The Mission + +> *Where we are going.* + +To become the **canonical home for developer and delivery enablement** - +CI/CD pipelines, GitOps workflows, workload templates, SDKs, buildpacks, +developer portal surfaces, and promotion conventions that help source repos +move safely toward S5 application releases. + +This means: + +* Common delivery paths are **automated and reusable** +* Build and deployment templates encode **Railiance platform expectations** +* Developers get fast feedback through **standard checks and pipelines** +* S5 can consume release artifacts through **clear handoff contracts** +* Enablement improves delivery without taking ownership of app runtime + operation + +--- + +## Core Principles + +### 1. Paved Paths, Not One-Off Pipelines + +The default way to build, test, package, and promote a workload should be +shared, documented, and easy to reuse. + +### 2. Enablement, Not Applications + +This layer helps applications reach production; it does not own their source +code, runtime configuration, or user-facing operations. + +### 3. Platform-Aware Templates + +Templates, SDKs, and buildpacks should encode the contracts exposed by S1-S3 so +consumers do not need to rediscover platform assumptions. + +### 4. Clear Handoff to S5 + +CI/CD and promotion flows should produce artifacts, metadata, and evidence that +the application layer can deploy and verify without guessing. + +### 5. Fast Feedback + +Developers should learn about broken builds, missing declarations, incompatible +interfaces, and release-readiness gaps before those problems reach live +application deployments. + +### 6. Boundaries Preserve Velocity + +Enablement should make the layered architecture easier to use, not become a +shortcut for mutating infrastructure, cluster, platform, or application +responsibilities. + +--- + +## What This Is (Conceptually) + +This layer is: + +* a **developer enablement** layer +* a home for **CI/CD and GitOps workflow patterns** +* a source of **workload templates, SDKs, and buildpacks** +* a **promotion handoff** surface between source repos and S5 deployments +* a future **developer portal** and self-service entry point +* a place to codify delivery knowledge into **repeatable automation** + +--- + +## What This Is Not + +This layer is not: + +* the infrastructure substrate +* the Kubernetes runtime +* the shared platform-services layer +* the application deployment and operations layer +* the source-code home for business workloads +* a replacement for repo-owned workplans, ADRs, or implementation decisions + +It is the **delivery machinery** that helps the rest of Railiance change +safely and repeatedly. + +--- + +## Direction of Evolution + +This layer is expected to evolve toward: + +* Standard **pipeline templates** for Railiance workloads +* Reusable **build and image promotion** conventions +* GitOps workflows with clear **review and rollback** expectations +* Developer-facing **self-service templates** and portal entry points +* SDKs and examples that make platform capabilities easy to consume correctly +* Release evidence that S5 can use for **deployment readiness** + +--- + +## Guiding Question + +> **How can Railiance make the correct delivery path the easiest path, so workloads can move from source to production with speed, evidence, and clear ownership?** From b6712300c6904b6e3aff6d3f3276b912c9cc1caf Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 5 Jun 2026 15:43:13 +0200 Subject: [PATCH 02/10] Clarify enablement forge handoffs --- INTENT.md | 18 +++++++++++++++--- SCOPE.md | 49 +++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/INTENT.md b/INTENT.md index 93d1f46..7de15b0 100644 --- a/INTENT.md +++ b/INTENT.md @@ -40,7 +40,8 @@ Railiance evolve faster without dissolving its layer boundaries. To become the **canonical home for developer and delivery enablement** - CI/CD pipelines, GitOps workflows, workload templates, SDKs, buildpacks, developer portal surfaces, and promotion conventions that help source repos -move safely toward S5 application releases. +move safely toward S5 application releases while consuming forge-provided +runners, registries, and artifact evidence. This means: @@ -48,6 +49,7 @@ This means: * Build and deployment templates encode **Railiance platform expectations** * Developers get fast feedback through **standard checks and pipelines** * S5 can consume release artifacts through **clear handoff contracts** +* Forge runtime and runner substrate remain owned by **railiance-forge** * Enablement improves delivery without taking ownership of app runtime operation @@ -75,13 +77,20 @@ consumers do not need to rediscover platform assumptions. CI/CD and promotion flows should produce artifacts, metadata, and evidence that the application layer can deploy and verify without guessing. -### 5. Fast Feedback +### 5. Clear Handoff to Forge + +Reusable workflows should state the forge capabilities they require: repository +events, runner labels, package credentials, registry endpoints, and artifact +evidence. This layer defines the reusable workflow shape; `railiance-forge` +owns the runtime and credentials behind it. + +### 6. Fast Feedback Developers should learn about broken builds, missing declarations, incompatible interfaces, and release-readiness gaps before those problems reach live application deployments. -### 6. Boundaries Preserve Velocity +### 7. Boundaries Preserve Velocity Enablement should make the layered architecture easier to use, not become a shortcut for mutating infrastructure, cluster, platform, or application @@ -110,6 +119,7 @@ This layer is not: * the Kubernetes runtime * the shared platform-services layer * the application deployment and operations layer +* the source forge, package/container registry, or runner substrate layer * the source-code home for business workloads * a replacement for repo-owned workplans, ADRs, or implementation decisions @@ -125,6 +135,8 @@ This layer is expected to evolve toward: * Standard **pipeline templates** for Railiance workloads * Reusable **build and image promotion** conventions * GitOps workflows with clear **review and rollback** expectations +* Handoff contracts with `railiance-forge` for **runner labels, package + credentials, registry endpoints, and artifact evidence** * Developer-facing **self-service templates** and portal entry points * SDKs and examples that make platform capabilities easy to consume correctly * Release evidence that S5 can use for **deployment readiness** diff --git a/SCOPE.md b/SCOPE.md index 7e39267..abd6005 100644 --- a/SCOPE.md +++ b/SCOPE.md @@ -8,23 +8,31 @@ ## One-liner -S4 Developer Enablement layer of the Railiance OAS Stack — owns CI/CD pipelines, developer portal, platform templates, SDKs, and buildpacks. +S4 Developer Enablement layer of the Railiance OAS Stack — owns reusable CI/CD +templates, developer portal paths, platform templates, SDKs, and buildpacks; +uses forge capabilities without owning forge runtime or runner substrate. --- ## Core Idea -Railiance is structured as five independent repos per OAS Stack layer. This repo is S4 — the tools that allow the system to evolve. S4 depends on the platform (S3) being operational before any tooling can use platform services, and in turn S5 (applications) uses S4's CI/CD pipelines and deployment templates. +Railiance is structured as independent repos per OAS Stack layer. This repo is +S4: the reusable tools and paved paths that allow the system to evolve. S4 +depends on the platform (S3) being operational before tooling can use platform +services. S5 applications consume S4 templates and conventions, while +`railiance-forge` provides source hosting, registries, and runner substrate. --- ## In Scope -- CI/CD pipelines and automation tooling +- Reusable CI/CD workflow templates and automation patterns - Developer portal (self-service deployment interface) - Platform deployment templates for workloads - SDKs and libraries for platform consumers - Buildpacks and image builders +- Handoff contracts to `railiance-forge` for runner labels, artifact evidence, + and registry consumption --- @@ -33,7 +41,10 @@ Railiance is structured as five independent repos per OAS Stack layer. This repo - OS-level concerns → railiance-infra (S1) - Kubernetes runtime → railiance-cluster (S2) - Platform services → railiance-platform (S3) +- Source forge runtime, container/package registries, runner deployment, + runner labels, and runner credentials → railiance-forge - Application deployments → railiance-apps (S5) +- App-specific workflows, release charts, and source code → app/source repos - No re-configuration of lower layers from this repo --- @@ -42,6 +53,8 @@ Railiance is structured as five independent repos per OAS Stack layer. This repo - Setting up CI/CD for the Railiance stack - Creating or modifying developer tools and deployment templates +- Defining reusable workflow templates that run on forge-provided runners +- Defining promotion conventions and evidence formats consumed by S5 - S3 is operational and tooling layer can now be built --- @@ -50,35 +63,51 @@ Railiance is structured as five independent repos per OAS Stack layer. This repo - S3 (platform services) is not yet operational (pre-condition not met) - Infrastructure, cluster, or platform work needed (wrong layer) +- The work is Gitea/Forgejo runtime, registry endpoint, package retention, + runner deployment, or runner secret access (use `railiance-forge`) +- The work is a concrete app release or app-specific runbook (use + `railiance-apps` or the source app repo) --- ## Current State - Status: emerging (ArgoCD deployed; no S4 workplans yet) -- Implementation: ArgoCD is deployed in the `argocd` namespace on COULOMBCORE — installed as a cluster addon (managed from S2 for now); no S4-owned workplans yet +- Implementation: ArgoCD is deployed in the `argocd` namespace on COULOMBCORE + as a cluster addon managed from S2 for now; no S4-owned workplans yet - Stability: n/a for S4-owned content; ArgoCD itself is operational -- Usage: ArgoCD available for GitOps deployments; formal S4 tooling work begins after S3 baseline +- Usage: ArgoCD available for GitOps deployments; formal S4 tooling work begins + after S3 baseline and should consume runner/registry capabilities from + `railiance-forge` --- ## How It Fits - Upstream dependencies: railiance-platform (S3) must be operational -- Downstream consumers: railiance-apps (S5) uses CI/CD and templates from this layer -- Often used with: railiance-platform (S3), railiance-apps (S5) +- Adjacent forge provider: railiance-forge owns source hosting, registries, and + runner substrate used by S4 workflows +- Downstream consumers: railiance-apps (S5) uses CI/CD and templates from this + layer +- Often used with: railiance-platform (S3), railiance-forge, railiance-apps (S5) --- ## Terminology -- Preferred terms: OAS Stack Level S4, developer enablement, boundary rule +- Preferred terms: OAS Stack Level S4, developer enablement, paved path, + workflow template, promotion convention, boundary rule +- Distinguish "workflow template" from "runner substrate": templates live here; + runner deployment, labels, credentials, and health live in + `railiance-forge`. --- ## Related / Overlapping - `railiance-platform` (S3) — pre-condition; provides services that S4 tooling depends on +- `railiance-forge` — provides source forge runtime, artifact registries, and + runner substrate consumed by S4 workflows - `railiance-apps` (S5) — consumer of S4 CI/CD and templates --- @@ -89,13 +118,13 @@ Railiance is structured as five independent repos per OAS Stack layer. This repo type: infrastructure title: CI/CD pipeline automation description: Automated build, test, and deployment pipelines for Railiance workloads — planned for when railiance-platform (S3) is operational. -keywords: [ci, cd, pipeline, automation, build, deploy, gitops] +keywords: [ci, cd, pipeline, automation, template, build, deploy, gitops] ``` ```capability type: documentation title: Platform deployment templates and SDKs -description: Standardised deployment templates, Helm charts, and SDKs enabling consistent application deployments across the Railiance stack. +description: Standardised deployment templates, Helm chart patterns, SDKs, and promotion conventions enabling consistent application deployments across the Railiance stack while consuming forge-owned runners and registries. keywords: [template, sdk, helm, deployment, developer, buildpack] ``` From b34d08c358cc6e46ebbc3dc659d00a770db49350 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 5 Jun 2026 16:16:42 +0200 Subject: [PATCH 03/10] Reference forge runner contract --- INTENT.md | 2 ++ SCOPE.md | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/INTENT.md b/INTENT.md index 7de15b0..1f26605 100644 --- a/INTENT.md +++ b/INTENT.md @@ -137,6 +137,8 @@ This layer is expected to evolve toward: * GitOps workflows with clear **review and rollback** expectations * Handoff contracts with `railiance-forge` for **runner labels, package credentials, registry endpoints, and artifact evidence** +* Reusable templates that cite the forge-owned **runner/GitOps ownership + contract** before depending on privileged labels or credentials * Developer-facing **self-service templates** and portal entry points * SDKs and examples that make platform capabilities easy to consume correctly * Release evidence that S5 can use for **deployment readiness** diff --git a/SCOPE.md b/SCOPE.md index abd6005..efe7c60 100644 --- a/SCOPE.md +++ b/SCOPE.md @@ -33,6 +33,8 @@ services. S5 applications consume S4 templates and conventions, while - Buildpacks and image builders - Handoff contracts to `railiance-forge` for runner labels, artifact evidence, and registry consumption +- Template references to forge-provided runner labels and credentials documented + in `/home/worsch/railiance-forge/docs/ci-runner-actions-gitops-ownership.md` --- @@ -107,7 +109,9 @@ services. S5 applications consume S4 templates and conventions, while - `railiance-platform` (S3) — pre-condition; provides services that S4 tooling depends on - `railiance-forge` — provides source forge runtime, artifact registries, and - runner substrate consumed by S4 workflows + runner substrate consumed by S4 workflows; its runner label and GitOps + boundary contract is + `/home/worsch/railiance-forge/docs/ci-runner-actions-gitops-ownership.md` - `railiance-apps` (S5) — consumer of S4 CI/CD and templates --- From 1d944dc497959ae02dc5cad67d33cce943f4d35c Mon Sep 17 00:00:00 2001 From: tegwick Date: Tue, 16 Jun 2026 01:58:01 +0200 Subject: [PATCH 04/10] Add capability registry scaffold (REUSE-WP-0014-T07 B05) --- registry/README.md | 12 ++++++++++++ registry/capabilities/.gitkeep | 0 registry/indexes/capabilities.yaml | 4 ++++ 3 files changed, 16 insertions(+) create mode 100644 registry/README.md create mode 100644 registry/capabilities/.gitkeep create mode 100644 registry/indexes/capabilities.yaml diff --git a/registry/README.md b/registry/README.md new file mode 100644 index 0000000..569abe9 --- /dev/null +++ b/registry/README.md @@ -0,0 +1,12 @@ +# Capability Registry + +Markdown-first capability index for federation and reuse planning. + +## Authoring + +1. Copy a capability entry template (see reuse-surface `templates/capability-entry.template.md`). +2. Add the row to `indexes/capabilities.yaml`. +3. Run `reuse-surface validate` from a checkout with the CLI installed. +4. Merge to `main` and verify publish with `reuse-surface establish --publish-check`. + +Federation contract: reuse-surface `docs/RegistryFederation.md`. diff --git a/registry/capabilities/.gitkeep b/registry/capabilities/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/registry/indexes/capabilities.yaml b/registry/indexes/capabilities.yaml new file mode 100644 index 0000000..f944e47 --- /dev/null +++ b/registry/indexes/capabilities.yaml @@ -0,0 +1,4 @@ +version: 1 +updated: '2026-06-16' +domain: helix_forge +capabilities: [] From 118641586483578911a7784ee1e9949769b8e3a5 Mon Sep 17 00:00:00 2001 From: tegwick Date: Thu, 18 Jun 2026 22:48:39 +0200 Subject: [PATCH 05/10] Add credential routing instructions for all agent runtimes Propagate shared credential-routing section (Codex, Claude, Grok, llm-connect) from state-hub template via scripts/propagate_credential_routing.py. --- .claude/rules/credential-routing.md | 50 +++++++++++++++++++++++++++ AGENTS.md | 52 +++++++++++++++++++++++++++++ CLAUDE.md | 1 + 3 files changed, 103 insertions(+) create mode 100644 .claude/rules/credential-routing.md diff --git a/.claude/rules/credential-routing.md b/.claude/rules/credential-routing.md new file mode 100644 index 0000000..f951beb --- /dev/null +++ b/.claude/rules/credential-routing.md @@ -0,0 +1,50 @@ +# Credential and access routing + +**Audience:** Codex, Claude Code, Grok, and custodian agents that call **llm-connect** +for inference. Run this check **before** requesting secrets, API keys, SSH access, +login tokens, or database passwords — in any repo, not only `ops-warden`. + +ops-warden **issues SSH certificates only** (`warden sign`, `cert_command`). Every +other credential need belongs to another subsystem. **Do not** message +`ops-warden` on State Hub expecting a secret value; the reply is a pointer, not a key. + +### Lookup (do this first) + +```bash +warden route find "" --json +warden route show --json +``` + +Requires the `warden` CLI from `~/ops-warden` (`uv tool install .` or `uv run warden`). + +| Agent runtime | How to orient | +| --- | --- | +| **Codex / Grok** (shell, HTTP State Hub) | `warden route` commands above; inbox `to_agent=railiance-enablement` is for coordination, not secret vending | +| **Claude Code** (MCP when available) | `get_domain_summary("custodian")` for workstreams; **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 + +| I need… | Owner | ops-warden executes? | +| --- | --- | --- | +| SSH cert (`adm`/`agt`/`atm`) | ops-warden | **Yes** — `warden sign` | +| API key, DB password, provider token | OpenBao (`railiance-platform`) | No — route only | +| Login / OIDC / MFA | key-cape / Keycloak | No — route only | +| Authorization decision | flex-auth | No — route only | +| activity-core → issue-core emission | activity-core + issue-core | No — `warden route show activity-core-issue-sink` | +| SSH tunnel | ops-bridge (+ `cert_command` from warden) | No — route only | + +### Anti-patterns (do not do these) + +- `POST /messages/` to `ops-warden` asking for `ISSUE_CORE_API_KEY`, `OPENROUTER_API_KEY`, etc. +- Inventing `warden secret`, `warden login`, `warden bao`, `warden tunnel` — they do not exist +- Pasting secrets into Git, State Hub, workplans, logs, or chat + +### Other capabilities (reuse-surface) + +Non-credential capabilities are usually discovered through **reuse-surface** federation +(`reuse-surface` registry / `capability.*` indexes). Credential routing is inlined in +every repo's agent instructions because it is high-frequency, high-risk, and easy to +get wrong. + +**Canon:** `~/ops-warden/wiki/CredentialRouting.md` · catalog `~/ops-warden/registry/routing/catalog.yaml` \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md index 1cc9a25..54654e4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -101,6 +101,58 @@ curl -s -X PATCH "http://127.0.0.1:8000/tasks/" \ --- +## Credential and access routing + +**Audience:** Codex, Claude Code, Grok, and custodian agents that call **llm-connect** +for inference. Run this check **before** requesting secrets, API keys, SSH access, +login tokens, or database passwords — in any repo, not only `ops-warden`. + +ops-warden **issues SSH certificates only** (`warden sign`, `cert_command`). Every +other credential need belongs to another subsystem. **Do not** message +`ops-warden` on State Hub expecting a secret value; the reply is a pointer, not a key. + +### Lookup (do this first) + +```bash +warden route find "" --json +warden route show --json +``` + +Requires the `warden` CLI from `~/ops-warden` (`uv tool install .` or `uv run warden`). + +| Agent runtime | How to orient | +| --- | --- | +| **Codex / Grok** (shell, HTTP State Hub) | `warden route` commands above; inbox `to_agent=railiance-enablement` is for coordination, not secret vending | +| **Claude Code** (MCP when available) | `get_domain_summary("custodian")` for workstreams; **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 + +| I need… | Owner | ops-warden executes? | +| --- | --- | --- | +| SSH cert (`adm`/`agt`/`atm`) | ops-warden | **Yes** — `warden sign` | +| API key, DB password, provider token | OpenBao (`railiance-platform`) | No — route only | +| Login / OIDC / MFA | key-cape / Keycloak | No — route only | +| Authorization decision | flex-auth | No — route only | +| activity-core → issue-core emission | activity-core + issue-core | No — `warden route show activity-core-issue-sink` | +| SSH tunnel | ops-bridge (+ `cert_command` from warden) | No — route only | + +### Anti-patterns (do not do these) + +- `POST /messages/` to `ops-warden` asking for `ISSUE_CORE_API_KEY`, `OPENROUTER_API_KEY`, etc. +- Inventing `warden secret`, `warden login`, `warden bao`, `warden tunnel` — they do not exist +- Pasting secrets into Git, State Hub, workplans, logs, or chat + +### Other capabilities (reuse-surface) + +Non-credential capabilities are usually discovered through **reuse-surface** federation +(`reuse-surface` registry / `capability.*` indexes). Credential routing is inlined in +every repo's agent instructions because it is high-frequency, high-risk, and easy to +get wrong. + +**Canon:** `~/ops-warden/wiki/CredentialRouting.md` · catalog `~/ops-warden/registry/routing/catalog.yaml` +--- + ## Workplan Convention (ADR-001) Work items originate as files in this repo — not in the hub. The hub is a diff --git a/CLAUDE.md b/CLAUDE.md index 9d9a38f..f0d4d03 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,4 +8,5 @@ @.claude/rules/stack-and-commands.md @.claude/rules/architecture.md @.claude/rules/repo-boundary.md +@.claude/rules/credential-routing.md @.claude/rules/agents.md From 7c663d6da5346a10c85c87dbaaa7c2313e1d2e81 Mon Sep 17 00:00:00 2001 From: tegwick Date: Mon, 22 Jun 2026 17:47:41 +0200 Subject: [PATCH 06/10] Add .repo-classification.yaml (CUST-WP-0050 T11 agent first-pass) --- .repo-classification.yaml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .repo-classification.yaml diff --git a/.repo-classification.yaml b/.repo-classification.yaml new file mode 100644 index 0000000..34833e5 --- /dev/null +++ b/.repo-classification.yaml @@ -0,0 +1,17 @@ +repo_classification: + standard: Repo Classification Standard + version: '1.0' + classified_at: '2026-06-22' + classified_by: agent + category: project + domain: financials + secondary_domains: [] + capability_tags: + - platform + - operations + business_stake: + - technology + - operations + business_mechanics: + - coordination + - operation From bd2913781edb038e00ecec7cc3bea853007f288d Mon Sep 17 00:00:00 2001 From: tegwick Date: Mon, 22 Jun 2026 23:16:28 +0200 Subject: [PATCH 07/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/first-session.md | 10 +++++----- .claude/rules/repo-identity.md | 2 +- .claude/rules/session-protocol.md | 9 +++++---- .claude/rules/workplan-convention.md | 18 +++++++++++++++--- AGENTS.md | 19 ++++++++++++------- 5 files changed, 38 insertions(+), 20 deletions(-) diff --git a/.claude/rules/first-session.md b/.claude/rules/first-session.md index 5236f07..3634280 100644 --- a/.claude/rules/first-session.md +++ b/.claude/rules/first-session.md @@ -1,11 +1,11 @@ ## First Session Protocol -Triggered when `get_domain_summary("railiance")` shows **no workstreams**. +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/railiance/project_charter_v0.1.md` — purpose, scope -- `~/the-custodian/canon/projects/railiance/roadmap_v0.1.md` — planned phases +- `~/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** @@ -17,7 +17,7 @@ roadmap phase. **Wait for approval before creating.** **Step 4 — Create workplan file first, then DB record (ADR-001)** ``` -workplans/railiance-enablement-WP-NNNN-.md ← write this first +workplans/RAILIANCE-WP-NNNN-.md ← write this first ``` Then register in the hub: ``` @@ -28,7 +28,7 @@ create_task(workstream_id="", title="...", priority="high|medium|low") **Step 5 — Record the setup** ``` add_progress_event( - summary="First session: structured railiance into N workstreams, M tasks", + 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-identity.md b/.claude/rules/repo-identity.md index abad1f5..bd41c5b 100644 --- a/.claude/rules/repo-identity.md +++ b/.claude/rules/repo-identity.md @@ -1,5 +1,5 @@ **Purpose:** OAS S4 Developer Enablement — CI/CD pipelines, developer portal, platform templates -**Domain:** railiance +**Domain:** financials **Repo slug:** railiance-enablement **Topic ID:** ca369340-a64e-442e-98f1-a4fa7dc74a38 diff --git a/.claude/rules/session-protocol.md b/.claude/rules/session-protocol.md index ca2415a..64f8c4f 100644 --- a/.claude/rules/session-protocol.md +++ b/.claude/rules/session-protocol.md @@ -1,6 +1,7 @@ ## Session Protocol -State Hub: http://127.0.0.1:8000 +Dev Hub (State Hub API): http://127.0.0.1:8000 +MCP server name in `~/.claude.json`: `dev-hub` **Step 1 — Orient** @@ -10,7 +11,7 @@ cat .custodian-brief.md ``` Then call the MCP tool for richer cross-domain context when MCP tools are exposed: ``` -get_domain_summary("railiance") +get_domain_summary("financials") ``` If MCP tools are unavailable in the current agent session, use the REST API: ```bash @@ -39,11 +40,11 @@ curl -s -X PATCH "http://127.0.0.1:8000/messages//read" \ ls workplans/ ``` For each file with `status: ready`, `active`, or `blocked`, note pending -`todo`/`in_progress` tasks. +`wait`/`todo`/`progress` tasks. **Step 4 — Present brief** -1. **Active workstreams** for `railiance` — title, task counts, blocking decisions +1. **Active workstreams** for `financials` — title, task counts, blocking decisions 2. **Pending tasks** from `workplans/` + any `[repo:railiance-enablement]` hub tasks 3. **Goal guidance** — if `goal_guidance` in summary: - `needs_workplan`: surface as top action — *"Repo goal '{title}' has no workplan yet"* diff --git a/.claude/rules/workplan-convention.md b/.claude/rules/workplan-convention.md index 38dcd18..ada972b 100644 --- a/.claude/rules/workplan-convention.md +++ b/.claude/rules/workplan-convention.md @@ -1,7 +1,7 @@ ## Workplan Convention (ADR-001) -File location: `workplans/railiance-enablement-WP-NNNN-.md` -ID prefix: `RAILIANCE-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. @@ -12,7 +12,7 @@ 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-enablement-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**: @@ -25,4 +25,16 @@ Ecosystem todos from other agents arrive as `[repo:railiance-enablement]` hub ta visible at session start. Pick one up by creating the workplan file, then registering the 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: "" # 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 54654e4..5e3ac6e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,7 +4,7 @@ **Purpose:** OAS S4 Developer Enablement — CI/CD pipelines, developer portal, platform templates -**Domain:** railiance +**Domain:** financials **Repo slug:** railiance-enablement **Topic ID:** `ca369340-a64e-442e-98f1-a4fa7dc74a38` **Workplan prefix:** `RAILIANCE-WP-` @@ -63,8 +63,8 @@ Omit `workstream_id` / `task_id` when not applicable. ```bash curl -s -X PATCH "http://127.0.0.1:8000/tasks/" \ -H "Content-Type: application/json" \ - -d '{"status": "in_progress"}' -# values: todo | in_progress | done | blocked + -d '{"status": "progress"}' +# values: wait | todo | progress | done | cancel ``` ### Flag a task for human review @@ -83,7 +83,7 @@ curl -s -X PATCH "http://127.0.0.1:8000/tasks/" \ 1. `cat .custodian-brief.md` — domain goal and open workstreams (offline-safe) 2. Check inbox: `GET /messages/?to_agent=railiance-enablement&unread_only=true`; mark read 3. Scan workplans: `ls workplans/` — note `status: ready`, `active`, or `blocked` files and open tasks -4. Check blocked tasks: `GET /tasks/?needs_human=true` +4. Check human-needed tasks: `GET /tasks/?needs_human=true` **During work:** - Update task statuses in workplan files as tasks progress @@ -151,6 +151,11 @@ 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 (ADR-001) @@ -176,7 +181,7 @@ anything needing analysis, design, approval, dependencies, or multiple phases. id: RAILIANCE-WP-NNNN type: workplan title: "..." -domain: railiance +domain: financials repo: railiance-enablement status: proposed | ready | active | blocked | backlog | finished | archived owner: codex @@ -198,7 +203,7 @@ derived health labels, not frontmatter statuses. ` ` `task id: RAILIANCE-WP-NNNN-T01 -status: todo | in_progress | done | blocked +status: wait | todo | progress | done | cancel priority: high | medium | low state_hub_task_id: "" # written by fix-consistency — do not edit ` ` ` @@ -206,7 +211,7 @@ state_hub_task_id: "" # written by fix-consistency — do not edit Task description text. ``` -Status progression: `todo` → `in_progress` → `done` (or `blocked`) +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 From d0e15767f6ba203dbae4ca4031f662781d1c00ee Mon Sep 17 00:00:00 2001 From: tegwick Date: Thu, 2 Jul 2026 00:21:48 +0200 Subject: [PATCH 08/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 | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/.claude/rules/stack-and-commands.md b/.claude/rules/stack-and-commands.md index dc53ac6..ba2b566 100644 --- a/.claude/rules/stack-and-commands.md +++ b/.claude/rules/stack-and-commands.md @@ -1,19 +1,13 @@ ## Stack - -- **Language:** -- **Key deps:** +- **Language:** documentation and reusable CI/CD / platform templates (no application code yet) +- **Key deps:** none at present — S4 layer is largely unpopulated ## 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 # only target currently defined ``` + +No build, test, or deploy commands exist yet. When S4 work starts (CI/CD +templates, SDKs, buildpacks), fill this file in the same change. From 58c3c48d002091c6fd5839a9ef1fbb8518fa6eda Mon Sep 17 00:00:00 2001 From: tegwick Date: Thu, 2 Jul 2026 01:47:45 +0200 Subject: [PATCH 09/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 | 13 ++++++++---- AGENTS.md | 26 ++++++++++++++--------- 5 files changed, 61 insertions(+), 37 deletions(-) diff --git a/.claude/rules/credential-routing.md b/.claude/rules/credential-routing.md index f951beb..c6a512b 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-enablement` 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 3634280..638cbb9 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/RAILIANCE-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-enablement ``` +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 64f8c4f..4b287ce 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-enablement]` 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-enablement +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-enablement +statehub fix-consistency --repo railiance-enablement --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 ada972b..d4aa57e 100644 --- a/.claude/rules/workplan-convention.md +++ b/.claude/rules/workplan-convention.md @@ -5,7 +5,7 @@ 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 @@ -16,14 +16,15 @@ 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-enablement]` 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: @@ -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 5e3ac6e..4e2c30c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -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-enablement&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-enablement + 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-enablement` 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 dc760eb58e238af820fe56ba360f1744d0d4bc09 Mon Sep 17 00:00:00 2001 From: tegwick Date: Sat, 4 Jul 2026 12:49:06 +0200 Subject: [PATCH 10/10] Add Forgejo Actions workflow templates and repo promotion helper Canonical ci-smoke, container-build-push, and multirepo build templates for railiance01 runners. Documents adoption path for tier 1-3 repos. --- .forgejo/workflows/ci-smoke.yaml | 29 ++++++++ docs/forgejo-actions-workflow-templates.md | 66 +++++++++++++++++++ tools/promote-repo-to-forgejo.sh | 51 ++++++++++++++ workflows/ci-smoke.yaml | 29 ++++++++ workflows/container-build-push-multirepo.yaml | 61 +++++++++++++++++ workflows/container-build-push.yaml | 48 ++++++++++++++ 6 files changed, 284 insertions(+) create mode 100644 .forgejo/workflows/ci-smoke.yaml create mode 100644 docs/forgejo-actions-workflow-templates.md create mode 100755 tools/promote-repo-to-forgejo.sh create mode 100644 workflows/ci-smoke.yaml create mode 100644 workflows/container-build-push-multirepo.yaml create mode 100644 workflows/container-build-push.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 diff --git a/docs/forgejo-actions-workflow-templates.md b/docs/forgejo-actions-workflow-templates.md new file mode 100644 index 0000000..79e6795 --- /dev/null +++ b/docs/forgejo-actions-workflow-templates.md @@ -0,0 +1,66 @@ +# Forgejo Actions Workflow Templates + +Date: 2026-07-04 +Owner: `railiance-enablement` (S4) +Workplans: `RAIL-HO-WP-0005-T08`, `CUST-WP-0054-T04` + +## Purpose + +Canonical, copy-ready Forgejo Actions workflows for the railiance01 runner +substrate (`railiance01-build-01`, ADR-004). Forgejo/Gitea Actions on our +runners do **not** support `actions/checkout@v4` on the non-root host runner; +use **archive checkout** via `wget` instead. + +Templates live in `workflows/` at repo root. Consumer repos copy into +`.forgejo/workflows/` and adjust `IMAGE_NAME` / `EXTRA_REPOS` as needed. + +## Runner labels + +| Label | Use | +| --- | --- | +| `self-hosted` | Host runner routing smoke, lightweight probes | +| `ubuntu-latest` | Container-isolated smoke (label routing) | +| `container-build` | DinD image build + registry push | + +Org secrets (set on `coulomb` org): `REGISTRY_USER`, `REGISTRY_TOKEN`. + +## Templates + +| File | Tier | When to use | +| --- | ---: | --- | +| `workflows/ci-smoke.yaml` | 1 | Git+CI routing drill; infra/docs repos | +| `workflows/container-build-push.yaml` | 2 | Single-repo `Dockerfile` image publish | +| `workflows/container-build-push-multirepo.yaml` | 3 prep | Docker build with named contexts (e.g. `state-hub` + `hub-core`) | + +## Adoption + +```bash +mkdir -p .forgejo/workflows +cp /path/to/railiance-enablement/workflows/ci-smoke.yaml .forgejo/workflows/ +# For images: +cp /path/to/railiance-enablement/workflows/container-build-push.yaml .forgejo/workflows/image.yaml +# Edit IMAGE_NAME=coulomb/ +git add .forgejo/workflows && git commit -m "Add Forgejo CI from enablement templates" +git push origin main +``` + +## Proven consumers + +| Repo | Template | Evidence | +| --- | --- | --- | +| `coulomb/glas-harness` | `ci-smoke` (in-repo) | Tier 1 pilot | +| `coulomb/key-cape` | `container-build-push` (in-repo) | Tier 2 pilot | +| `coulomb/railiance-*` | `ci-smoke` | Tier 2.5 promotion (2026-07-04) | + +## Constraints + +- Do not use `actions/checkout@v4` on `self-hosted` / `container-build` runners. +- Static `docker` binary via wget; runner image is non-root and cannot `apk add`. +- Reusable `workflow_call` across repos is not relied on; copy templates instead. +- Runner substrate and labels: `railiance-forge/docs/ci-runner-actions-gitops-ownership.md`. + +## References + +- `the-custodian/docs/forgejo-repo-migration-pilot-glas-harness.md` +- `railiance-apps/docs/forgejo-on-railiance01.md` +- `docs/adr/ADR-004-forgejo-in-cluster-actions-runner.md` (in `railiance-infra`) \ No newline at end of file diff --git a/tools/promote-repo-to-forgejo.sh b/tools/promote-repo-to-forgejo.sh new file mode 100755 index 0000000..106816c --- /dev/null +++ b/tools/promote-repo-to-forgejo.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +# Promote a coulomb repo to Forgejo (tier 2.5): mirror, flip remotes, add ci-smoke. +set -euo pipefail + +REPO="${1:?usage: promote-repo-to-forgejo.sh [repo-path]}" +REPO_PATH="${2:-$HOME/${REPO}}" +ORG=coulomb +FORGEJO_API="${FORGEJO_API:-https://forgejo.coulomb.social/api/v1}" +TOKEN_FILE="${FORGEJO_TOKEN_FILE:-/tmp/forgejo-tegwick-api-token}" +TEMPLATE="${PROMOTE_CI_TEMPLATE:-$HOME/railiance-enablement/workflows/ci-smoke.yaml}" + +if [[ ! -f "${TOKEN_FILE}" ]]; then + echo "Missing API token at ${TOKEN_FILE}" >&2 + exit 1 +fi +TOKEN=$(cat "${TOKEN_FILE}") +AUTH=(-H "Authorization: token ${TOKEN}") + +code=$(curl -sS -o /dev/null -w '%{http_code}' "${AUTH[@]}" "${FORGEJO_API}/repos/${ORG}/${REPO}") +if [[ "${code}" == "404" ]]; then + echo "==> Creating ${ORG}/${REPO} on Forgejo" + curl -fsS -X POST "${FORGEJO_API}/orgs/${ORG}/repos" "${AUTH[@]}" \ + -H "Content-Type: application/json" \ + -d "{\"name\":\"${REPO}\",\"private\":false,\"auto_init\":false}" >/dev/null +elif [[ "${code}" == "200" ]]; then + echo "==> ${ORG}/${REPO} already exists on Forgejo" +else + echo "Unexpected API status ${code} for ${ORG}/${REPO}" >&2 + exit 1 +fi + +cd "${REPO_PATH}" + +mkdir -p .forgejo/workflows +if [[ ! -f .forgejo/workflows/ci-smoke.yaml ]]; then + cp "${TEMPLATE}" .forgejo/workflows/ci-smoke.yaml + git add .forgejo/workflows/ci-smoke.yaml + git commit -m "Add Forgejo CI smoke workflow (enablement template)" +fi + +if git remote get-url origin 2>/dev/null | grep -q forgejo-remote; then + echo "==> Remotes already on Forgejo" +else + git remote rename origin gitea + git remote add origin "forgejo-remote:${ORG}/${REPO}.git" + echo "==> Remotes: origin=forgejo-remote, gitea=legacy" +fi + +echo "==> Pushing ${REPO_PATH} to Forgejo" +git push -u origin main +echo "==> Promoted ${REPO}" \ No newline at end of file diff --git a/workflows/ci-smoke.yaml b/workflows/ci-smoke.yaml new file mode 100644 index 0000000..bd44c56 --- /dev/null +++ b/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 diff --git a/workflows/container-build-push-multirepo.yaml b/workflows/container-build-push-multirepo.yaml new file mode 100644 index 0000000..3fbda0b --- /dev/null +++ b/workflows/container-build-push-multirepo.yaml @@ -0,0 +1,61 @@ +# Multi-repo Docker build template for tier-3 prep (e.g. state-hub + hub-core). +# Copy to: .forgejo/workflows/image.yaml and set PRIMARY_REPO + EXTRA_REPOS. +# Uses archive checkout (no actions/checkout; non-root runner has no git). +# Dockerfile must reference named contexts, e.g.: +# COPY --from=hub_core_src pyproject.toml /tmp/hub-core/pyproject.toml +name: Build and Publish Multi-Context Image + +on: + push: + branches: + - main + paths: + - ".forgejo/workflows/image.yaml" + - "Dockerfile" + workflow_dispatch: + +env: + REGISTRY: forgejo.coulomb.social + IMAGE_NAME: coulomb/REPLACE_ME + DOCKER_HOST: tcp://127.0.0.1:2375 + # Space-separated coulomb/repo@context_name entries for extra build contexts. + # Example: "coulomb/hub-core@hub_core_src" + EXTRA_REPOS: "coulomb/hub-core@hub_core_src" + +jobs: + build-and-push: + runs-on: container-build + steps: + - name: Build and push image + env: + REGISTRY_USER: ${{ secrets.REGISTRY_USER }} + REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} + run: | + set -eu + REF="${GITHUB_SHA:-main}" + mkdir -p buildctx "${HOME}/bin" + wget -qO /tmp/primary.tar.gz \ + "https://forgejo.coulomb.social/${GITHUB_REPOSITORY}/archive/${REF}.tar.gz" + tar xzf /tmp/primary.tar.gz -C buildctx --strip-components=1 + BUILD_ARGS=() + for spec in ${EXTRA_REPOS}; do + repo="${spec%@*}" + ctx="${spec#*@}" + extra_ref="${REF}" + wget -qO "/tmp/${ctx}.tar.gz" \ + "https://forgejo.coulomb.social/${repo}/archive/${extra_ref}.tar.gz" + mkdir -p "/tmp/ctx-${ctx}" + tar xzf "/tmp/${ctx}.tar.gz" -C "/tmp/ctx-${ctx}" --strip-components=1 + BUILD_ARGS+=(--build-context "${ctx}=/tmp/ctx-${ctx}") + done + wget -qO- https://download.docker.com/linux/static/stable/x86_64/docker-27.3.1.tgz \ + | tar xz --strip-components=1 -C "${HOME}/bin" docker/docker + export PATH="${HOME}/bin:${PATH}" + echo "${REGISTRY_TOKEN}" | docker login "${REGISTRY}" -u "${REGISTRY_USER}" --password-stdin + SHORT="${REF:0:7}" + IMAGE="${REGISTRY}/${IMAGE_NAME}" + docker build "${BUILD_ARGS[@]}" \ + -t "${IMAGE}:latest" -t "${IMAGE}:main-${SHORT}" buildctx + docker push "${IMAGE}:latest" + docker push "${IMAGE}:main-${SHORT}" + echo "pushed ${IMAGE}:latest and ${IMAGE}:main-${SHORT}" \ No newline at end of file diff --git a/workflows/container-build-push.yaml b/workflows/container-build-push.yaml new file mode 100644 index 0000000..423c2b3 --- /dev/null +++ b/workflows/container-build-push.yaml @@ -0,0 +1,48 @@ +# Canonical single-repo image build template (tier 2). +# Copy to: .forgejo/workflows/image.yaml and set IMAGE_NAME. +# Requires org secrets: REGISTRY_USER, REGISTRY_TOKEN +# Runner label: container-build (DinD sidecar on railiance01-build-01) +name: Build and Publish Container Image + +on: + push: + branches: + - main + paths: + - ".forgejo/workflows/image.yaml" + - "Dockerfile" + - "src/**" + workflow_dispatch: + +env: + REGISTRY: forgejo.coulomb.social + # Set per repo, e.g. coulomb/key-cape + IMAGE_NAME: coulomb/REPLACE_ME + DOCKER_HOST: tcp://127.0.0.1:2375 + +jobs: + build-and-push: + runs-on: container-build + steps: + - name: Build and push image + env: + REGISTRY_USER: ${{ secrets.REGISTRY_USER }} + REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} + run: | + set -eu + REF="${GITHUB_SHA:-main}" + mkdir -p buildctx "${HOME}/bin" + wget -qO /tmp/repo.tar.gz \ + "https://forgejo.coulomb.social/${GITHUB_REPOSITORY}/archive/${REF}.tar.gz" + tar xzf /tmp/repo.tar.gz -C buildctx --strip-components=1 + wget -qO- https://download.docker.com/linux/static/stable/x86_64/docker-27.3.1.tgz \ + | tar xz --strip-components=1 -C "${HOME}/bin" docker/docker + export PATH="${HOME}/bin:${PATH}" + docker version + echo "${REGISTRY_TOKEN}" | docker login "${REGISTRY}" -u "${REGISTRY_USER}" --password-stdin + SHORT="${REF:0:7}" + IMAGE="${REGISTRY}/${IMAGE_NAME}" + docker build -t "${IMAGE}:latest" -t "${IMAGE}:main-${SHORT}" buildctx + docker push "${IMAGE}:latest" + docker push "${IMAGE}:main-${SHORT}" + echo "pushed ${IMAGE}:latest and ${IMAGE}:main-${SHORT}" \ No newline at end of file