diff --git a/.github/workflows/doctor-loop.yml b/.github/workflows/doctor-loop.yml new file mode 100644 index 00000000..e50365f0 --- /dev/null +++ b/.github/workflows/doctor-loop.yml @@ -0,0 +1,40 @@ +name: doctor-loop + +# Layer-2 autonomous Railway fleet doctor for trios-trainer-igla. +# Bypass-discipline: lives in its own workflow + crate, does NOT modify +# gardener-loop.yml (v2.9 / PR #149 territory). Skill: docker-railway-doctor v1.2. +# Anchor: phi^2 + phi^-2 = 3 · TRINITY · NEVER STOP · DOI 10.5281/zenodo.19227877 + +on: + schedule: + - cron: '*/5 * * * *' # every 5 minutes (cron-tier monitor runs hourly) + workflow_dispatch: + inputs: + action: + description: 'doctor action: diagnose | cure | cure-all' + required: false + default: 'diagnose' + +concurrency: + group: doctor-loop + cancel-in-progress: false + +permissions: + contents: read + actions: write + issues: write + +jobs: + doctor: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Skeleton — Layer-2 doctor stub (PR #155, feat/doctor-v1.0) + run: | + echo "DOCTOR Layer-2 skeleton — not yet wired." + echo "Anchor: phi^2 + phi^-2 = 3" + echo "Action: ${{ inputs.action || 'diagnose' }}" + echo "Pending merge of crates/tri-doctor (PR #155)." + # TODO: invoke `cargo run -p tri-doctor -- $ACTION` once the crate lands. + # TODO: append row to public.gardener_runs with action='doctor_cure'. + # TODO: emit Railway serviceInstanceDeployV2 force-redeploys on AMBER. diff --git a/crates/tri-doctor/Cargo.toml b/crates/tri-doctor/Cargo.toml new file mode 100644 index 00000000..c3de14b2 --- /dev/null +++ b/crates/tri-doctor/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "tri-doctor" +version = "0.1.0" +edition = "2021" +license = "Apache-2.0" +description = "Layer-1 autonomous Railway fleet doctor for trios-trainer-igla. Skill: docker-railway-doctor v1.2." + +[[bin]] +name = "tri-doctor" +path = "src/main.rs" + +[dependencies] +anyhow = "1" +clap = { version = "4", features = ["derive"] } +serde = { version = "1", features = ["derive"] } +serde_json = "1" +sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "postgres", "chrono"] } +tokio = { version = "1", features = ["full"] } +reqwest = { version = "0.12", features = ["json", "rustls-tls"], default-features = false } +chrono = { version = "0.4", features = ["serde"] } diff --git a/crates/tri-doctor/src/main.rs b/crates/tri-doctor/src/main.rs new file mode 100644 index 00000000..649adaab --- /dev/null +++ b/crates/tri-doctor/src/main.rs @@ -0,0 +1,42 @@ +// tri-doctor — Layer-1 autonomous Railway fleet doctor. +// Anchor: phi^2 + phi^-2 = 3 · TRINITY · NEVER STOP · DOI 10.5281/zenodo.19227877 +// +// Skill: docker-railway-doctor v1.2 (Perplexity Computer user-scope). +// This is a skeleton stub — actual cure logic lands in a follow-up PR. + +use anyhow::Result; +use clap::{Parser, Subcommand}; + +#[derive(Parser, Debug)] +#[command(name = "tri-doctor", version, about = "Autonomous Railway fleet doctor")] +struct Cli { + #[command(subcommand)] + command: Cmd, +} + +#[derive(Subcommand, Debug)] +enum Cmd { + /// Run R5-honest probes (writer pulse, bit-id, seq-burn, matrix champ) and emit JSON verdict. + Diagnose, + /// Apply a single cure-action: force-redeploy + variable upsert + GARDENER_LIVE flap. + Cure, + /// Apply all cure-actions in sequence (max 40 per Railway GraphQL quota). + CureAll, +} + +#[tokio::main] +async fn main() -> Result<()> { + let cli = Cli::parse(); + match cli.command { + Cmd::Diagnose => { + println!("{{\"verdict\":\"AMBER\",\"reason\":\"skeleton-stub\",\"anchor\":\"phi^2+phi^-2=3\"}}"); + } + Cmd::Cure => { + anyhow::bail!("cure not yet implemented — pending Layer-1 wiring"); + } + Cmd::CureAll => { + anyhow::bail!("cure-all not yet implemented — pending Layer-1 wiring"); + } + } + Ok(()) +}