diff --git a/.agents/skills/ione-backlog/SKILL.md b/.agents/skills/ione-backlog/SKILL.md index 6bc2592..a55aa4b 100644 --- a/.agents/skills/ione-backlog/SKILL.md +++ b/.agents/skills/ione-backlog/SKILL.md @@ -1,10 +1,43 @@ --- name: ione-backlog -description: Implement one human-approved IONe federation or reliability issue with Postgres-backed verification and an unmerged PR. Use for the scheduled IONe backlog loop or an explicitly selected backlog-ready issue. +description: Carry one IONe issue from backlog-ready to merged — failing test, smallest safe change, verified PR, green CI, squash merge. Use for the scheduled IONe backlog loop or an explicitly selected backlog-ready issue. --- # IONe backlog -Require `backlog-ready`, non-red `main`, no open `automation-pr`, and an isolated worktree. Process one issue. TerraYield federation changes require a matching `eo_ag` issue with the same versioned interface, auth, error, and compatibility contract. +This loop merges. No human reads the diff before it lands on `main`, so the verification below is the only thing standing between a bad change and the default branch. Treat a gate you cannot run as a reason to stop, never as a reason to proceed. -Add a failing contract test, implement the smallest safe change, run focused Rust tests, then migrated Postgres-backed ignored tests serially when persistence or federation is involved. Run Playwright for static UI or browser contracts. Open a PR labeled `automation-pr` with provenance, `Closes #N`, exact verification, risks, and unrun external gates. Stop before merge or deployment. +## Pick the run's work + +Evaluate everything against remote state after `git fetch origin`. + +1. **An open `automation-pr` already exists** — that is this run's work. Do not open a second one. Drive it to green and merge it, then stop. A prior run's stalled PR blocks the queue, and unblocking it matters more than starting something new. +2. **Otherwise** — take the oldest open issue carrying `backlog-ready` and not carrying `needs-human-auth`. `backlog-ready` counts as approval whether Ryan applied it or the `auto-backlog-ready` workflow promoted it from `bug-candidate` or `research-candidate`. `needs-human-auth` is Ryan's manual hold; nothing else applies it. +3. **`main` CI is red** — fixing `main` is the run's work. Do not layer a feature on a broken base. +4. **Nothing matches** — stop and say so. A no-op run is a fine outcome. + +One issue per run. TerraYield federation changes require a matching `eo_ag` issue carrying the same versioned interface, auth, error, and compatibility contract; if it does not exist, stop and say so rather than changing one side of a wire contract alone. + +## Build it + +Write a failing contract test first, then the smallest safe change that passes it. Never edit an already-applied migration — a checksum break took down all 57 suites once, which is what issue #31 exists to prevent. + +## Verify + +Run the gates the change actually touches, and run them before the PR, not after: + +- always: `cargo fmt --all -- --check`, `cargo clippy --all-targets -- -D warnings`, `cargo test --lib --bins`, `cargo test --test phase01_chat` +- persistence or federation: `docker compose up -d postgres minio`, `cargo sqlx migrate run`, then each relevant suite as `DATABASE_URL=postgres://ione:ione@localhost:5433/ione IONE_SKIP_LIVE=1 cargo test --test -- --include-ignored --test-threads=1` +- static UI or browser contract: `npm run test:e2e` + +If the runner cannot start Postgres, MinIO, or a browser, say which gates did not run and why. CI runs the full matrix on the PR — let it be the first place they execute, and treat its verdict as binding. + +## Land it + +Open one PR labeled `automation-pr` with `Closes #N`, provenance naming the scheduled run and date, the exact commands and their output, risks, and any gate that did not run locally. + +Wait for CI. Fix what it turns red — this is your own PR. When every required check is green, `gh pr merge --squash --delete-branch`. + +Do not merge on a red or pending check, do not merge past a gate you skipped, and do not use admin override to bypass a failing check. If CI stays red after a genuine attempt to fix it, leave the PR open with a comment explaining what is wrong and stop — the next run will resume it under rule 1. + +Stop before any deployment, release, or version bump. Never write a secret value into a commit, PR body, or issue comment. diff --git a/.agents/skills/ione-scout/SKILL.md b/.agents/skills/ione-scout/SKILL.md new file mode 100644 index 0000000..42dc427 --- /dev/null +++ b/.agents/skills/ione-scout/SKILL.md @@ -0,0 +1,29 @@ +--- +name: ione-scout +description: Research IONe OLAP, OLTP, data-connection, federated-data, edge-computing, and application-support opportunities and file evidence-backed research candidates. Use for the scheduled IONe scouting loop or inbound enhancement triage. +--- + +# IONe idea scout + +Scout these six areas and nothing else: + +- **OLAP** — aggregate query paths, materialization, columnar/vector layout, pgvector index choice, chart/table aggregate endpoints, query plans that degrade with row count. +- **OLTP** — write path latency, transaction scope, lock contention, connection pooling, migration safety, RLS overhead on hot paths. +- **Data connections** — connector coverage and quality (`src/connectors/`), auth flows, retry/backoff, schema drift, ingest validation, signed webhook ingress. +- **Federated data systems** — MCP peer surface, context slices, catalog search, peer identity and credential lifecycle, conformance gaps between the kit and production semantics. +- **Edge computing** — running IONe close to the data: single-binary footprint, offline/degraded operation, sync and reconciliation after partition, resource ceilings on constrained hardware. +- **Application support** — what a downstream app (TerraYield, GroundPulse, a third party) needs from IONe as a substrate: API contracts, provisioning, error semantics, docs that match behavior. + +Ground every candidate in current primary sources plus current repo state: `md/design/`, `md/requirements/active/`, open issues, recent PRs, and the code itself. Read `CLAUDE.md` and `md/design/ione-substrate.md` first — IONe is domain-agnostic federation infrastructure, not a geospatial product, and candidates that assume otherwise are wrong. + +Verify any "already shipped" claim against the remote, never the local checkout: `git fetch origin` first, then `git merge-base --is-ancestor origin/main` or `gh pr view --json state`. A commit appearing in bare `git log` proves nothing. + +Deduplicate against every open and recently closed issue before filing. Propose the smallest testable change, not a program of work. + +Filing `research-candidate` issues is pre-authorized — file them without asking, including on scheduled runs where no human is present to answer. Ending a run with candidates described but unfiled is a failed run: the builder reads issues, not logs. Cap a scheduled run at three issues; a fourth good idea keeps until next week. + +Each issue states: dated sources, the current gap with a `file:line` citation, user or reliability value, the smallest validation experiment, blast radius, and provenance (scheduled scout run, date). + +Everything you file gets built and merged without a human reading the issue first. That is the intended design, and it makes the issue body the specification — write it so the builder cannot misread the scope. Prefer a change that ships behind a narrow contract test over one that needs judgment at implementation time. If you cannot state the acceptance criterion in a sentence, the candidate is not ready; keep researching it and file it next run. + +Never modify code, open a PR, merge, bump a version, or start a release. Never put secret values in an issue body. diff --git a/.agents/skills/ione-scout/agents/openai.yaml b/.agents/skills/ione-scout/agents/openai.yaml new file mode 100644 index 0000000..ec407a9 --- /dev/null +++ b/.agents/skills/ione-scout/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "IONe Idea Scout" + short_description: "Research IONe OLAP, OLTP, connector, federation, edge, and app-support opportunities" + default_prompt: "Use $ione-scout to research IONe improvement opportunities and file evidence-backed research-candidate issues." diff --git a/.agents/skills/ione-triage/SKILL.md b/.agents/skills/ione-triage/SKILL.md new file mode 100644 index 0000000..d1267cb --- /dev/null +++ b/.agents/skills/ione-triage/SKILL.md @@ -0,0 +1,25 @@ +--- +name: ione-triage +description: Triage inbound IONe bug reports into reproducible, scoped bug-candidate issues, or close them out. Use for the scheduled IONe triage loop or a specific inbound report. +--- + +# IONe bug triage + +Process open issues that carry `bug` and carry none of `bug-candidate`, `backlog-ready`, `automation-pr`, or `wontfix`. Oldest first. Cap a scheduled run at three issues. + +For each, do the work the reporter could not: + +1. **Reproduce.** Build a minimal case against current `main`. Use the cheap Rust path first, then migrated Postgres and the `#[ignore]`-gated suites serially when persistence or federation is involved, then Playwright for browser behavior. `docker compose up -d postgres minio`, `cargo sqlx migrate run`. +2. **Locate.** Cite the responsible code as `file:line`. A stack trace is not a location. +3. **Scope.** State the smallest change that fixes it and what it could break. + +Then take exactly one action: + +- **Reproduced** — comment with the repro command and its actual output, the `file:line` cause, the proposed fix, and a failing-test name the builder should write first. Apply `bug-candidate`. That label promotes to `backlog-ready` automatically, so do not apply `bug-candidate` to anything you did not personally reproduce. +- **Not reproducible** — comment with exactly what you ran, on what commit, and what you saw instead. Ask the reporter for the missing piece. Change no labels. +- **Already fixed** — verify against the remote (`git fetch origin`, then `git merge-base --is-ancestor origin/main` or `gh pr view --json state` reporting `MERGED`), comment with that evidence, and close. A commit in bare `git log` is not evidence. +- **Not a bug** — comment with the contract or design doc that defines the current behavior and say so. Change no labels. + +Anything you mark `bug-candidate` gets fixed and merged without a human reading it first. Your repro is the specification. That is why reproducing is not optional and why "looks wrong in the code" is never enough. + +Never guess at a repro, never mark a report reproduced on code reading alone, never modify code, never open a PR, and never put secret values, tokens, or raw credential material in a comment. Fixing is the builder's job. diff --git a/.agents/skills/ione-triage/agents/openai.yaml b/.agents/skills/ione-triage/agents/openai.yaml new file mode 100644 index 0000000..f73719b --- /dev/null +++ b/.agents/skills/ione-triage/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "IONe Bug Triage" + short_description: "Reproduce and scope inbound IONe bug reports into bug-candidate issues" + default_prompt: "Use $ione-triage to reproduce and scope open inbound IONe bug reports." diff --git a/.claude/skills/ione-backlog b/.claude/skills/ione-backlog new file mode 120000 index 0000000..60eb259 --- /dev/null +++ b/.claude/skills/ione-backlog @@ -0,0 +1 @@ +../../.agents/skills/ione-backlog \ No newline at end of file diff --git a/.claude/skills/ione-scout b/.claude/skills/ione-scout new file mode 120000 index 0000000..9bb1d2d --- /dev/null +++ b/.claude/skills/ione-scout @@ -0,0 +1 @@ +../../.agents/skills/ione-scout \ No newline at end of file diff --git a/.claude/skills/ione-triage b/.claude/skills/ione-triage new file mode 120000 index 0000000..33a71fe --- /dev/null +++ b/.claude/skills/ione-triage @@ -0,0 +1 @@ +../../.agents/skills/ione-triage \ No newline at end of file diff --git a/.github/workflows/auto-backlog-ready.yml b/.github/workflows/auto-backlog-ready.yml new file mode 100644 index 0000000..2dc3c73 --- /dev/null +++ b/.github/workflows/auto-backlog-ready.yml @@ -0,0 +1,33 @@ +name: Auto backlog-ready + +# Closes the scout/triage -> builder loop. An evidence-backed `bug-candidate` +# or `research-candidate` is promoted to `backlog-ready` (the builder's pickup +# gate) without manual approval, and the builder merges its own PR once CI is +# green — so nothing here waits on a human. `needs-human-auth` is Ryan's manual +# hold: applying it to an issue keeps that one issue out of the loop. No agent +# applies it to its own work. +on: + issues: + types: [labeled] + +permissions: + issues: write + +jobs: + promote: + if: github.event.label.name == 'bug-candidate' || github.event.label.name == 'research-candidate' + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@v7 + with: + script: | + const labels = context.payload.issue.labels.map(l => l.name); + if (labels.includes('needs-human-auth')) { core.info('held: needs-human-auth'); return; } + if (labels.includes('backlog-ready')) { core.info('already backlog-ready'); return; } + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.issue.number, + labels: ['backlog-ready'], + }); + core.info(`promoted #${context.payload.issue.number} to backlog-ready`); diff --git a/AGENTS.md b/AGENTS.md index 4774a97..a9ee839 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,4 +4,6 @@ IONe is active federated geospatial infrastructure. Read `CLAUDE.md` for current Use cheap Rust tests first. Persistence and federation claims require migrated Postgres and the ignored integration suite run serially; browser behavior requires the Playwright flow. Changes shared with TerraYield require matching issue-level interface contracts in both repositories before modifying either side. -Backlog automation accepts only Ryan-applied `backlog-ready`, skips red `main` and an existing `automation-pr`, works on one issue in an isolated worktree, opens one verified PR, and stops before merge or deployment. +Backlog automation is autonomous through merge. It accepts `backlog-ready` from Ryan or from the `auto-backlog-ready` workflow, never from an issue carrying `needs-human-auth` (Ryan's manual hold). It resumes an existing `automation-pr` before starting new work, repairs a red `main` before layering on it, takes one issue per run in an isolated worktree, opens one verified PR, drives CI green, and squash-merges. Green CI is the only merge authority: never merge on a red or pending check and never admin-override one. Stop before any deployment, release, or version bump. + +Scheduled scouting and triage are read-only on code. They file `research-candidate` and `bug-candidate` issues, which promote to `backlog-ready` automatically — so the issue body is the specification the builder ships against, and a bug is never marked a candidate without a real reproduction. No agent applies `needs-human-auth` to its own work. No agent writes a secret value into an issue, comment, commit, or PR. diff --git a/CLAUDE.md b/CLAUDE.md index 08ac437..6018d44 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -37,6 +37,27 @@ npm run test:e2e ``` Unset `IONE_SKIP_LIVE` to exercise live Ollama generator/critic/router paths. +## Automation loops +Three scheduled cloud agents, each driven by a skill in `.agents/skills/` +(symlinked into `.claude/skills/`): + +| Skill | Cadence | Writes | +|---|---|---| +| `ione-scout` | Mon, Thu | `research-candidate` issues — OLAP, OLTP, data connections, federated data, edge, app support | +| `ione-triage` | Mon, Wed, Fri | reproduces inbound `bug` reports into `bug-candidate` issues | +| `ione-backlog` | Mon, Wed, Fri | one `backlog-ready` issue → `automation-pr` → green CI → squash merge | + +The loop is autonomous end to end. `auto-backlog-ready.yml` promotes +`bug-candidate` and `research-candidate` to `backlog-ready`, and the builder +merges its own PR once CI is green. Nothing waits on a human. + +Green CI is the only merge authority — no merging on red or pending checks, no +admin override, and no deploy, release, or version bump from any loop. The +issue body is the specification, since nobody reads it before the change lands. + +Ryan steers by filing issues. `needs-human-auth` on an issue holds it out of the +loop; no agent applies that label to its own work. + ## Secrets `IONE_TOKEN_KEY` / `IONE_WEBHOOK_SECRET_KEY` live in `.env` (gitignored). Never commit `.env` or embed key values in settings/permissions entries.