From cce6f2505393aabf1d8221b0c9a00d682d829ebd Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 5 Apr 2026 09:50:32 +0000 Subject: [PATCH] feat: add ralphloops staging directory for ralphloops.io and ralphloops/ralphloops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a self-contained ralphloops/ directory with two subfolders: - website/ — static site for ralphloops.io (minimal, technical, inspired by agentskills.io) - repo/ — contents of the future ralphloops/ralphloops GitHub repo: spec, creator docs, implementor docs, six reference example loops, JSON Schema, conformance fixtures, RFCs, and governance Ralph Loops is positioned as an open proposed format for portable Ralph-style agent loops, inspired by Geoffrey Huntley's Ralph loop methodology, with Ralphify as one reference runtime — not a standard and not a Ralphify feature. This directory will be moved out into its own org and repo once they exist. --- ralphloops/README.md | 72 +++++ .../bug-in-fixture-or-example.md | 23 ++ .../.github/ISSUE_TEMPLATE/rfc-proposal.md | 39 +++ .../ISSUE_TEMPLATE/spec-clarification.md | 22 ++ ralphloops/repo/CODE_OF_CONDUCT.md | 32 ++ ralphloops/repo/CONTRIBUTING.md | 69 +++++ ralphloops/repo/GOVERNANCE.md | 64 ++++ ralphloops/repo/LICENSE | 21 ++ ralphloops/repo/README.md | 131 ++++++++ ralphloops/repo/VERSIONING.md | 57 ++++ ralphloops/repo/examples/bug-hunter/RALPH.md | 65 ++++ ralphloops/repo/examples/bug-hunter/README.md | 16 + .../examples/bug-hunter/prompts/edge-cases.md | 48 +++ .../repo/examples/dependency-updater/RALPH.md | 56 ++++ .../examples/dependency-updater/README.md | 17 + .../repo/examples/fix-failing-tests/RALPH.md | 69 +++++ .../repo/examples/fix-failing-tests/README.md | 33 ++ .../docs/repo-conventions.md | 25 ++ .../fix-failing-tests/scripts/run-tests.sh | 15 + .../fix-failing-tests/scripts/validate.sh | 21 ++ .../repo/examples/raise-coverage/RALPH.md | 64 ++++ .../repo/examples/raise-coverage/README.md | 20 ++ .../repo/examples/refactor-module/RALPH.md | 64 ++++ .../repo/examples/refactor-module/README.md | 7 + .../templates/pr-description.md | 23 ++ ralphloops/repo/examples/write-docs/RALPH.md | 55 ++++ ralphloops/repo/examples/write-docs/README.md | 7 + ralphloops/repo/implementors/discovery.md | 87 ++++++ .../repo/implementors/execution-model.md | 94 ++++++ ralphloops/repo/implementors/overview.md | 81 +++++ ralphloops/repo/implementors/parsing.md | 101 ++++++ ralphloops/repo/implementors/test-cases.md | 76 +++++ .../repo/loop-creation/best-practices.md | 98 ++++++ ralphloops/repo/loop-creation/quickstart.md | 100 ++++++ .../loop-creation/templates/RALPH.md.template | 56 ++++ .../repo/rfcs/0001-format-principles.md | 82 +++++ ralphloops/repo/rfcs/README.md | 46 +++ ralphloops/repo/schemas/metadata.schema.json | 73 +++++ ralphloops/repo/specification/changelog.md | 25 ++ .../repo/specification/compatibility.md | 88 ++++++ .../repo/specification/directory-layout.md | 83 +++++ ralphloops/repo/specification/format.md | 169 ++++++++++ ralphloops/repo/specification/metadata.md | 107 +++++++ ralphloops/repo/specification/overview.md | 77 +++++ .../repo/specification/runtime-contract.md | 95 ++++++ ralphloops/repo/tests/README.md | 28 ++ .../tests/invalid/bad-frontmatter/RALPH.md | 11 + .../tests/invalid/bad-frontmatter/REASON.md | 10 + .../tests/invalid/missing-ralph-md/REASON.md | 9 + ralphloops/repo/tests/valid/full/RALPH.md | 32 ++ .../repo/tests/valid/full/docs/notes.md | 4 + .../repo/tests/valid/full/scripts/validate.sh | 4 + ralphloops/repo/tests/valid/minimal/RALPH.md | 9 + ralphloops/website/examples/index.html | 77 +++++ ralphloops/website/governance/index.html | 88 ++++++ .../website/implementors/overview/index.html | 94 ++++++ .../website/implementors/reference/index.html | 84 +++++ ralphloops/website/index.html | 291 ++++++++++++++++++ .../loop-creation/best-practices/index.html | 64 ++++ .../loop-creation/quickstart/index.html | 88 ++++++ ralphloops/website/specification/index.html | 224 ++++++++++++++ ralphloops/website/styles.css | 269 ++++++++++++++++ 62 files changed, 4059 insertions(+) create mode 100644 ralphloops/README.md create mode 100644 ralphloops/repo/.github/ISSUE_TEMPLATE/bug-in-fixture-or-example.md create mode 100644 ralphloops/repo/.github/ISSUE_TEMPLATE/rfc-proposal.md create mode 100644 ralphloops/repo/.github/ISSUE_TEMPLATE/spec-clarification.md create mode 100644 ralphloops/repo/CODE_OF_CONDUCT.md create mode 100644 ralphloops/repo/CONTRIBUTING.md create mode 100644 ralphloops/repo/GOVERNANCE.md create mode 100644 ralphloops/repo/LICENSE create mode 100644 ralphloops/repo/README.md create mode 100644 ralphloops/repo/VERSIONING.md create mode 100644 ralphloops/repo/examples/bug-hunter/RALPH.md create mode 100644 ralphloops/repo/examples/bug-hunter/README.md create mode 100644 ralphloops/repo/examples/bug-hunter/prompts/edge-cases.md create mode 100644 ralphloops/repo/examples/dependency-updater/RALPH.md create mode 100644 ralphloops/repo/examples/dependency-updater/README.md create mode 100644 ralphloops/repo/examples/fix-failing-tests/RALPH.md create mode 100644 ralphloops/repo/examples/fix-failing-tests/README.md create mode 100644 ralphloops/repo/examples/fix-failing-tests/docs/repo-conventions.md create mode 100755 ralphloops/repo/examples/fix-failing-tests/scripts/run-tests.sh create mode 100755 ralphloops/repo/examples/fix-failing-tests/scripts/validate.sh create mode 100644 ralphloops/repo/examples/raise-coverage/RALPH.md create mode 100644 ralphloops/repo/examples/raise-coverage/README.md create mode 100644 ralphloops/repo/examples/refactor-module/RALPH.md create mode 100644 ralphloops/repo/examples/refactor-module/README.md create mode 100644 ralphloops/repo/examples/refactor-module/templates/pr-description.md create mode 100644 ralphloops/repo/examples/write-docs/RALPH.md create mode 100644 ralphloops/repo/examples/write-docs/README.md create mode 100644 ralphloops/repo/implementors/discovery.md create mode 100644 ralphloops/repo/implementors/execution-model.md create mode 100644 ralphloops/repo/implementors/overview.md create mode 100644 ralphloops/repo/implementors/parsing.md create mode 100644 ralphloops/repo/implementors/test-cases.md create mode 100644 ralphloops/repo/loop-creation/best-practices.md create mode 100644 ralphloops/repo/loop-creation/quickstart.md create mode 100644 ralphloops/repo/loop-creation/templates/RALPH.md.template create mode 100644 ralphloops/repo/rfcs/0001-format-principles.md create mode 100644 ralphloops/repo/rfcs/README.md create mode 100644 ralphloops/repo/schemas/metadata.schema.json create mode 100644 ralphloops/repo/specification/changelog.md create mode 100644 ralphloops/repo/specification/compatibility.md create mode 100644 ralphloops/repo/specification/directory-layout.md create mode 100644 ralphloops/repo/specification/format.md create mode 100644 ralphloops/repo/specification/metadata.md create mode 100644 ralphloops/repo/specification/overview.md create mode 100644 ralphloops/repo/specification/runtime-contract.md create mode 100644 ralphloops/repo/tests/README.md create mode 100644 ralphloops/repo/tests/invalid/bad-frontmatter/RALPH.md create mode 100644 ralphloops/repo/tests/invalid/bad-frontmatter/REASON.md create mode 100644 ralphloops/repo/tests/invalid/missing-ralph-md/REASON.md create mode 100644 ralphloops/repo/tests/valid/full/RALPH.md create mode 100644 ralphloops/repo/tests/valid/full/docs/notes.md create mode 100755 ralphloops/repo/tests/valid/full/scripts/validate.sh create mode 100644 ralphloops/repo/tests/valid/minimal/RALPH.md create mode 100644 ralphloops/website/examples/index.html create mode 100644 ralphloops/website/governance/index.html create mode 100644 ralphloops/website/implementors/overview/index.html create mode 100644 ralphloops/website/implementors/reference/index.html create mode 100644 ralphloops/website/index.html create mode 100644 ralphloops/website/loop-creation/best-practices/index.html create mode 100644 ralphloops/website/loop-creation/quickstart/index.html create mode 100644 ralphloops/website/specification/index.html create mode 100644 ralphloops/website/styles.css diff --git a/ralphloops/README.md b/ralphloops/README.md new file mode 100644 index 0000000..4ad455a --- /dev/null +++ b/ralphloops/README.md @@ -0,0 +1,72 @@ +# `ralphloops/` — staging area for ralphloops.io and ralphloops/ralphloops + +This directory is a **staging area** for the Ralph Loops project. It +contains two things that will eventually move to their own homes: + +- **[`website/`](website/)** — the static site for + [ralphloops.io](https://ralphloops.io/). Minimal, technical, + inspired by [agentskills.io](https://agentskills.io/). +- **[`repo/`](repo/)** — the contents of the future + `ralphloops/ralphloops` GitHub repository: specification, creator + docs, implementor docs, example loop packages, JSON Schema, + conformance fixtures, RFCs, and governance. + +## Why it lives here for now + +The `ralphloops` GitHub organization and repo do not exist yet. This +subdirectory lets us develop the format, the spec, and the site +alongside Ralphify (one reference implementation) until we're ready +to move it out. + +When the `ralphloops` org is created: + +1. Copy `ralphloops/repo/` into the new `ralphloops/ralphloops` repo. +2. Deploy `ralphloops/website/` to the ralphloops.io domain. +3. Remove this staging directory from the Ralphify repo. + +## Positioning + +Ralph Loops is positioned everywhere as: + +> **An open proposed format for portable Ralph-style agent loops.** + +- It is **not** a standard. +- It is **not** a Ralphify feature. +- It is **inspired by** Geoffrey Huntley's Ralph loop methodology and + does not claim ownership of that methodology. +- Ralphify is **one reference runtime** for the format, not the + format itself. + +## Layout + +``` +ralphloops/ +├── README.md # this file +├── website/ # ralphloops.io static site +│ ├── index.html +│ ├── styles.css +│ ├── specification/ +│ ├── loop-creation/ +│ │ ├── quickstart/ +│ │ └── best-practices/ +│ ├── implementors/ +│ │ ├── overview/ +│ │ └── reference/ +│ ├── examples/ +│ └── governance/ +└── repo/ # ralphloops/ralphloops repo contents + ├── README.md + ├── LICENSE + ├── CONTRIBUTING.md + ├── CODE_OF_CONDUCT.md + ├── GOVERNANCE.md + ├── VERSIONING.md + ├── specification/ + ├── loop-creation/ + ├── implementors/ + ├── examples/ # six reference loop packages + ├── schemas/ + ├── tests/ # conformance corpus + ├── rfcs/ + └── .github/ +``` diff --git a/ralphloops/repo/.github/ISSUE_TEMPLATE/bug-in-fixture-or-example.md b/ralphloops/repo/.github/ISSUE_TEMPLATE/bug-in-fixture-or-example.md new file mode 100644 index 0000000..fca4f9d --- /dev/null +++ b/ralphloops/repo/.github/ISSUE_TEMPLATE/bug-in-fixture-or-example.md @@ -0,0 +1,23 @@ +--- +name: Bug in a fixture or example +about: Report a problem with a conformance fixture or example loop +title: "[bug] " +labels: ["bug", "examples"] +--- + +## Where + + + +## What's wrong + + + +## How to reproduce + + + +## Suggested fix + + diff --git a/ralphloops/repo/.github/ISSUE_TEMPLATE/rfc-proposal.md b/ralphloops/repo/.github/ISSUE_TEMPLATE/rfc-proposal.md new file mode 100644 index 0000000..07658d7 --- /dev/null +++ b/ralphloops/repo/.github/ISSUE_TEMPLATE/rfc-proposal.md @@ -0,0 +1,39 @@ +--- +name: RFC proposal +about: Propose a non-trivial change to the Ralph Loops format +title: "[rfc] " +labels: ["rfc"] +--- + +## Summary + + + +## Motivation + + + +## Proposal + + + +## Impact + +- **Breaking?** +- **Target version:** +- **Affected documents:** + +## Alternatives considered + + + +## Unresolved questions + + + +--- + +If this is accepted for further discussion, a maintainer will ask you +to write it up as a file under `rfcs/` using the template at +`rfcs/0001-format-principles.md`. diff --git a/ralphloops/repo/.github/ISSUE_TEMPLATE/spec-clarification.md b/ralphloops/repo/.github/ISSUE_TEMPLATE/spec-clarification.md new file mode 100644 index 0000000..6c1bd09 --- /dev/null +++ b/ralphloops/repo/.github/ISSUE_TEMPLATE/spec-clarification.md @@ -0,0 +1,22 @@ +--- +name: Spec clarification +about: The specification is ambiguous or unclear +title: "[clarify] " +labels: ["spec", "clarification"] +--- + +## Which part of the spec? + + + +## What is ambiguous? + + + +## What interpretations are possible? + + + +## Why it matters + + diff --git a/ralphloops/repo/CODE_OF_CONDUCT.md b/ralphloops/repo/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..03bb36f --- /dev/null +++ b/ralphloops/repo/CODE_OF_CONDUCT.md @@ -0,0 +1,32 @@ +# Code of Conduct + +Ralph Loops follows the +[Contributor Covenant v2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct/). + +## Our pledge + +We as members, contributors, and maintainers pledge to make participation in +our community a harassment-free experience for everyone, regardless of age, +body size, visible or invisible disability, ethnicity, sex characteristics, +gender identity and expression, level of experience, education, socio-economic +status, nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies +when an individual is officially representing the community in public spaces. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the maintainers listed in [`GOVERNANCE.md`](GOVERNANCE.md). All +complaints will be reviewed and investigated promptly and fairly. + +## Attribution + +This Code of Conduct is adapted from the +[Contributor Covenant](https://www.contributor-covenant.org), version 2.1. diff --git a/ralphloops/repo/CONTRIBUTING.md b/ralphloops/repo/CONTRIBUTING.md new file mode 100644 index 0000000..fccdef4 --- /dev/null +++ b/ralphloops/repo/CONTRIBUTING.md @@ -0,0 +1,69 @@ +# Contributing to Ralph Loops + +Thanks for helping shape Ralph Loops. This repository is the canonical source +for the Ralph Loops format: its specification, examples, conformance tests, +and governance. + +## What lives here + +- **`specification/`** — the normative format spec +- **`loop-creation/`** — creator-facing docs +- **`implementors/`** — runtime-author docs +- **`examples/`** — reference loop packages +- **`schemas/`** — JSON Schema for frontmatter metadata +- **`tests/`** — valid/invalid conformance fixtures +- **`rfcs/`** — RFCs for non-trivial changes + +Code for specific runtimes (e.g. Ralphify) does **not** live here. + +## Kinds of contributions we welcome + +- Typo, clarity, and wording fixes in the spec and docs +- New conformance fixtures under `tests/valid/` and `tests/invalid/` +- New example loops under `examples/` +- RFCs proposing additions or changes to the format +- Translations and accessibility improvements to docs + +## Discussion first, PR second + +For anything beyond a typo or a small clarification, please open an issue or +a discussion first. This is especially true for spec changes. We prefer +small, well-scoped PRs over large, speculative ones. + +## Spec changes require an RFC + +Any change that affects what a Ralph Loop *is* — required fields, path +resolution rules, compatibility classes, runtime contract, etc. — must go +through the RFC process under `rfcs/`. Use `rfcs/0001-format-principles.md` +as a template. + +Additive, backwards-compatible clarifications to existing fields may be +landed directly as a PR against `specification/`. + +## Adding an example loop + +Each example under `examples/` must include: + +1. A `RALPH.md` with complete, valid frontmatter +2. A short `README.md` explaining what the loop is for +3. At least one bundled supporting file (script, doc, template, or fixture) +4. Realistic exit conditions and validation steps + +Prefer outcome-oriented names (`fix-failing-tests`, not `my-loop-1`). + +## Adding conformance fixtures + +- Valid fixtures go under `tests/valid//`. +- Invalid fixtures go under `tests/invalid//` with a short + `REASON.md` file explaining why the fixture is invalid. + +## Style + +- Prose: plain English, short sentences, no hype language. +- Normative keywords (MUST, SHOULD, MAY) follow RFC 2119 semantics. +- Code fences should declare a language where applicable. + +## Code of conduct + +Participation in this project is governed by our +[Code of Conduct](CODE_OF_CONDUCT.md). diff --git a/ralphloops/repo/GOVERNANCE.md b/ralphloops/repo/GOVERNANCE.md new file mode 100644 index 0000000..c71ace9 --- /dev/null +++ b/ralphloops/repo/GOVERNANCE.md @@ -0,0 +1,64 @@ +# Governance + +Ralph Loops is an **open proposed format** for portable Ralph-style agent +loops. This document describes how the format is stewarded and evolved. + +## Status + +The current format version is `0.1`. All `0.x` versions are draft and +subject to change. A stable `1.x` line will be cut once the format has +proven itself across multiple runtimes and loop packages in the wild. + +## Non-ownership of Ralph methodology + +Ralph Loops is a community-oriented format proposal **inspired by** +[Geoffrey Huntley's Ralph loop methodology](https://ghuntley.com/ralph/). +This repository defines the package format. It does **not** define, own, +or gate the broader Ralph methodology itself. + +## Maintainers + +The format is maintained by a small group of stewards who land PRs, review +RFCs, and cut spec releases. Current maintainers are listed in the +repository `MAINTAINERS` file. Additional maintainers are added by +consensus of existing maintainers based on sustained, thoughtful +contribution. + +## Decision making + +- **Typos, clarifications, small doc fixes.** Any maintainer may merge + after a brief review. +- **Additive, backwards-compatible spec changes.** Require review from at + least one other maintainer and an open discussion thread. +- **Breaking changes.** Require an accepted RFC under `rfcs/` and + consensus among active maintainers. + +We prefer rough consensus over formal voting. If consensus cannot be +reached, the maintainers may choose to defer the decision rather than +force it through. + +## RFC process + +1. Open a discussion or issue describing the problem and the proposed change. +2. If the change is non-trivial, draft an RFC under `rfcs/` using the + template in `rfcs/0001-format-principles.md`. +3. Maintainers and community members review and comment. +4. The RFC author revises in response to feedback. +5. A maintainer either accepts, rejects, or defers the RFC. +6. Accepted RFCs ship in a future `ralphloops_version` release, referenced + from `specification/changelog.md`. + +## Stewardship principles + +- Keep the format small. +- Prefer portability over runtime-specific convenience. +- Prefer human-readability over machine-centric schemas. +- Do not claim ownership of the broader Ralph methodology. +- Do not favor any single runtime in normative text. +- Ship breaking changes through RFCs, not surprises. + +## Relationship to runtimes + +Runtimes like [Ralphify](https://ralphify.co/) are welcome to ship features +that go beyond the format, but the format itself stays neutral. Runtime- +specific behavior belongs in runtime documentation, not in the spec. diff --git a/ralphloops/repo/LICENSE b/ralphloops/repo/LICENSE new file mode 100644 index 0000000..47c788e --- /dev/null +++ b/ralphloops/repo/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Ralph Loops contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/ralphloops/repo/README.md b/ralphloops/repo/README.md new file mode 100644 index 0000000..918a271 --- /dev/null +++ b/ralphloops/repo/README.md @@ -0,0 +1,131 @@ +# Ralph Loops + +> Specification and documentation for **Ralph Loops**, an open proposed format +> for portable Ralph-style agent loops. + +Ralph Loops is an open proposed format for portable Ralph-style agent loops. +A Ralph Loop is a directory containing a required `RALPH.md` file plus any +supporting scripts, prompts, plans, templates, examples, or other resources +needed to run the loop. The format is designed to make loops easier to share, +version, inspect, and run across compatible tools. + +> **Status.** Ralph Loops is an *open proposed format*, not a standard. The +> current format version is `0.1` and all `0.x` versions are draft. + +## What a Ralph Loop looks like + +``` +fix-failing-tests/ +├── RALPH.md +├── scripts/ +│ ├── run-tests.sh +│ └── validate.sh +└── docs/ + └── repo-conventions.md +``` + +Every Ralph Loop is a directory. The only required file is `RALPH.md` — the +canonical entrypoint. Everything else is optional bundled context: scripts, +templates, fixtures, reference docs, or any other files the loop needs. + +Minimal `RALPH.md`: + +```markdown +--- +name: fix-failing-tests +description: Fix failing tests one failure at a time. +ralphloops_version: 0.1 +entry: + validate: scripts/validate.sh + test: scripts/run-tests.sh +--- + +# Goal +Fix failing tests one failure at a time. + +# Loop +1. Run the validation commands. +2. Identify the highest-signal failure. +3. Make the smallest useful change. +4. Re-run validation. +5. Commit only if checks pass. +``` + +## Why this format exists + +Autonomous agent loops are powerful, but most of them live as one-off prompts +pasted into chat windows or hard-coded into a single tool. Ralph Loops +proposes a small, portable package format so that loops can be: + +- **portable** across tools and runtimes +- **shareable** as reusable packages +- **versionable** in git +- **inspectable** by humans +- **bundled** with the scripts, prompts, and reference files they need + +The design intentionally follows the successful pattern used by +[Agent Skills](https://agentskills.io): a simple directory-based format with a +canonical entrypoint file and room for bundled resources. + +## For creators + +- [Quickstart](loop-creation/quickstart.md) — author your first loop +- [Best practices](loop-creation/best-practices.md) — authoring guidelines +- [Templates](loop-creation/templates/) — starter packages + +## For implementors + +- [Overview](implementors/overview.md) — how runtimes should load loops +- [Discovery](implementors/discovery.md) +- [Parsing](implementors/parsing.md) +- [Execution model](implementors/execution-model.md) +- [Test cases](implementors/test-cases.md) — conformance corpus + +## Specification + +The canonical specification lives under [`specification/`](specification/): + +- [Overview](specification/overview.md) +- [Format](specification/format.md) +- [Metadata](specification/metadata.md) +- [Directory layout](specification/directory-layout.md) +- [Runtime contract](specification/runtime-contract.md) +- [Compatibility](specification/compatibility.md) +- [Changelog](specification/changelog.md) + +A JSON Schema for frontmatter metadata is available in +[`schemas/metadata.schema.json`](schemas/metadata.schema.json). + +## Examples + +Six complete example packages live under [`examples/`](examples/): + +- [`fix-failing-tests/`](examples/fix-failing-tests/) +- [`bug-hunter/`](examples/bug-hunter/) +- [`raise-coverage/`](examples/raise-coverage/) +- [`refactor-module/`](examples/refactor-module/) +- [`write-docs/`](examples/write-docs/) +- [`dependency-updater/`](examples/dependency-updater/) + +## Governance + +Ralph Loops is maintained through this public repository. Breaking changes go +through a lightweight RFC process under [`rfcs/`](rfcs/). See +[`GOVERNANCE.md`](GOVERNANCE.md) and [`VERSIONING.md`](VERSIONING.md). + +## Relationship to Ralphify and other runtimes + +[Ralphify](https://ralphify.co/) is one reference implementation and runtime +for Ralph Loops. Any other tool is welcome to implement the format — it is +intentionally runtime-agnostic. Runtimes declare which +[compatibility class](specification/compatibility.md) they support. + +## Attribution + +Ralph Loops is a community-oriented format proposal **inspired by** +[Geoffrey Huntley's Ralph loop methodology](https://ghuntley.com/ralph/). This +repository defines the package format, **not** the Ralph methodology itself. + +## License + +[MIT](LICENSE). diff --git a/ralphloops/repo/VERSIONING.md b/ralphloops/repo/VERSIONING.md new file mode 100644 index 0000000..379b409 --- /dev/null +++ b/ralphloops/repo/VERSIONING.md @@ -0,0 +1,57 @@ +# Versioning + +Ralph Loops uses a single version number, `ralphloops_version`, declared +per package in `RALPH.md` frontmatter. + +## Version lines + +- **`0.x` — draft / experimental.** Breaking changes may land in any + `0.x` release. Runtimes and authors should track releases closely. +- **`1.x` — stable compatibility line.** Once cut, breaking changes + require a new major version and an RFC. Additive changes ship as minor + versions. + +The current release is **`0.1`**. + +## What counts as breaking + +A change is breaking if, after it lands, a package that was valid under +the previous version is no longer valid, or behaves materially differently +under a conforming runtime. + +Examples: + +- Removing or renaming a required field +- Tightening validation rules so that previously valid packages fail +- Changing path resolution semantics +- Changing the meaning of an existing field + +Not breaking: + +- Adding a new optional field +- Clarifying prose without changing behavior +- Adding new conformance fixtures that match existing rules +- Adding recommended (not required) metadata + +## Runtime behavior across versions + +Runtimes MUST refuse to execute packages whose `ralphloops_version` is +strictly greater than the runtime's supported version. Runtimes SHOULD +emit warnings, not errors, when they encounter unknown optional fields +or recommended fields they do not use. + +## Release process + +1. Land all accepted RFCs for the release against `main`. +2. Update `specification/changelog.md` with a release entry. +3. Tag the release as `v` (e.g. `v0.1`). +4. Announce in GitHub Discussions. + +## Compatibility guidance + +Authors should declare `ralphloops_version` honestly. When in doubt, set +it to the version you actually tested against. + +Runtimes should declare which versions they support in their own +documentation, and should publish a conformance report against the +fixtures in `tests/`. diff --git a/ralphloops/repo/examples/bug-hunter/RALPH.md b/ralphloops/repo/examples/bug-hunter/RALPH.md new file mode 100644 index 0000000..b77f50f --- /dev/null +++ b/ralphloops/repo/examples/bug-hunter/RALPH.md @@ -0,0 +1,65 @@ +--- +name: bug-hunter +description: Reproduce, localize, and patch a reported bug. +ralphloops_version: 0.1 +version: 0.1.0 +license: MIT +tags: + - bugs + - debugging +compatible_runtimes: + - ralphify >=0.3.0 +triggers: + - reported bug + - reproduction needed + - regression +entry: + validate: scripts/validate.sh + test: scripts/run-tests.sh +resources: + - prompts/edge-cases.md +--- + +# Goal + +Given a bug report, reproduce the bug, localize it to a single +function or module, write a regression test that fails because of it, +and then patch the code so the test passes. + +# Context + +Read `prompts/edge-cases.md` — it lists common categories of bugs +(off-by-one, null handling, timezone handling, concurrency) that are +worth ruling in or out during triage. + +# Loop + +1. Read the bug report supplied to the runtime. +2. Attempt a minimal reproduction. Prefer a failing unit test. +3. If a reproduction exists, commit the new failing test as + `test: add regression for `. +4. Localize the bug by reading the code exercised by the failing test. +5. Make the smallest useful fix. +6. Run the full test suite. If anything new fails, back out and try + another fix. +7. When the regression test passes and nothing else breaks, commit the + fix as `fix: `. + +# Constraints + +- Do not close bugs without a regression test. +- Do not introduce new public APIs to fix a bug. +- Stay inside the module where the bug was localized, unless the bug + clearly crosses a module boundary. + +# Validation + +- `scripts/run-tests.sh` passes. +- A new regression test exists that fails without the fix and passes + with it. + +# Exit conditions + +- The regression test is committed. +- The fix is committed. +- The full test suite passes. diff --git a/ralphloops/repo/examples/bug-hunter/README.md b/ralphloops/repo/examples/bug-hunter/README.md new file mode 100644 index 0000000..5661f47 --- /dev/null +++ b/ralphloops/repo/examples/bug-hunter/README.md @@ -0,0 +1,16 @@ +# bug-hunter + +A Ralph Loop for turning a bug report into a reproduction, a +regression test, and a fix. + +## How to use it + +Run this loop with a bug report attached to the runtime's input. The +runtime decides how the report is passed in (CLI flag, file, issue +link, etc.) — the loop itself only cares that "the bug report" is +available somewhere in the agent's working context. + +## What it bundles + +- `prompts/edge-cases.md` — a checklist of common bug categories that + helps the agent triage the report. diff --git a/ralphloops/repo/examples/bug-hunter/prompts/edge-cases.md b/ralphloops/repo/examples/bug-hunter/prompts/edge-cases.md new file mode 100644 index 0000000..4a2f3b3 --- /dev/null +++ b/ralphloops/repo/examples/bug-hunter/prompts/edge-cases.md @@ -0,0 +1,48 @@ +# Common bug categories to rule in or out during triage + +When a bug is reported, walk through this checklist before diving into +a specific fix: + +## Input handling +- Empty input +- Single-element input +- Very large input +- Unicode / non-ASCII input +- Input with leading/trailing whitespace +- Duplicate keys or elements + +## Null and absence +- `None` / `null` / `nil` where a value is expected +- Missing optional fields +- Uninitialized variables + +## Numbers +- Off-by-one at loop boundaries +- Integer overflow +- Floating-point equality +- Division by zero + +## Time and dates +- Timezone handling +- Daylight saving time transitions +- Leap years and leap seconds +- Unix epoch boundaries + +## Concurrency +- Race conditions on shared state +- Deadlocks +- Iteration over a mutating collection + +## I/O +- File not found +- Permission denied +- Partial reads/writes +- Encoding mismatches + +## State and identity +- Equality vs identity +- Mutable default arguments +- Stale caches + +Use this list as a triage checklist — don't chase every category, but +rule out the obvious ones before committing to a hypothesis. diff --git a/ralphloops/repo/examples/dependency-updater/RALPH.md b/ralphloops/repo/examples/dependency-updater/RALPH.md new file mode 100644 index 0000000..1b9855c --- /dev/null +++ b/ralphloops/repo/examples/dependency-updater/RALPH.md @@ -0,0 +1,56 @@ +--- +name: dependency-updater +description: Upgrade dependencies one at a time with tests green. +ralphloops_version: 0.1 +version: 0.1.0 +license: MIT +tags: + - dependencies + - maintenance +compatible_runtimes: + - ralphify >=0.3.0 +triggers: + - outdated dependencies + - dependabot +entry: + validate: scripts/validate.sh + test: scripts/run-tests.sh + outdated: scripts/list-outdated.sh +--- + +# Goal + +Upgrade the project's dependencies one at a time, keeping tests green +at every step. Never upgrade multiple dependencies in a single commit. + +# Loop + +1. Run `scripts/list-outdated.sh`. Read the list. +2. Pick **one** dependency to upgrade. Prefer: + - security updates first + - patch-level updates next + - minor updates after that + - major updates last (and only when explicitly allowed) +3. Upgrade just that dependency in the project's manifest file. +4. Run `scripts/run-tests.sh`. +5. If tests pass, commit as `chore: bump to `. +6. If tests fail, revert the upgrade and move on to the next + dependency. +7. Repeat until no updates remain, or until a configured maximum + number of upgrades has been applied this iteration. + +# Constraints + +- One dependency per commit. +- Never bypass lockfile updates. +- Never upgrade major versions unless explicitly allowed. +- Never delete tests to make an upgrade pass. + +# Validation + +- `scripts/run-tests.sh` exits 0 after every commit. + +# Exit conditions + +- No outdated dependencies remain within the allowed tiers. +- OR: the configured upgrade budget is exhausted. diff --git a/ralphloops/repo/examples/dependency-updater/README.md b/ralphloops/repo/examples/dependency-updater/README.md new file mode 100644 index 0000000..c3a11c0 --- /dev/null +++ b/ralphloops/repo/examples/dependency-updater/README.md @@ -0,0 +1,17 @@ +# dependency-updater + +A Ralph Loop for upgrading dependencies one at a time with tests green +at every step. + +## Why one-at-a-time + +Batched dependency upgrades are painful to diagnose when something +breaks. This loop deliberately commits each upgrade separately so the +test suite tells you exactly which change caused any regression. + +## Wiring + +- `scripts/list-outdated.sh` — emits the list of outdated dependencies + in whatever form your package manager supports. +- `scripts/run-tests.sh` — runs the full test suite. +- `scripts/validate.sh` — optional preflight checks. diff --git a/ralphloops/repo/examples/fix-failing-tests/RALPH.md b/ralphloops/repo/examples/fix-failing-tests/RALPH.md new file mode 100644 index 0000000..153f2f3 --- /dev/null +++ b/ralphloops/repo/examples/fix-failing-tests/RALPH.md @@ -0,0 +1,69 @@ +--- +name: fix-failing-tests +description: Find and fix failing tests one failure at a time. +ralphloops_version: 0.1 +version: 0.1.0 +license: MIT +tags: + - tests + - bugs +compatible_runtimes: + - ralphify >=0.3.0 +triggers: + - failing tests + - test suite is red + - CI is broken +entry: + validate: scripts/validate.sh + test: scripts/run-tests.sh +resources: + - docs/repo-conventions.md +--- + +# Goal + +Fix failing tests in this repository one failure at a time, until the +entire test suite is green. + +# Context + +Read `docs/repo-conventions.md` before making changes. It describes +the repo's conventions for test naming, fixtures, and commit messages. + +# Loop + +1. Run `scripts/validate.sh` to confirm the workspace is clean and the + tools are available. +2. Run `scripts/run-tests.sh` to collect the current set of failures. +3. Pick the **highest-signal** failing test — prefer tests whose + failure message clearly points at one function or module. +4. Read the failing test and the code it exercises. +5. Make the **smallest useful change** that fixes just that failure. +6. Re-run `scripts/run-tests.sh`. +7. If the chosen test now passes and no new failures appeared, commit + with a message of the form `fix: `. +8. Repeat from step 2 until no failures remain. + +# Constraints + +- Do not disable, skip, or delete failing tests to make them pass. +- Do not modify test files unless the test itself is clearly wrong. +- Do not refactor code beyond what the fix requires. +- Do not touch files outside the repository root. + +# Validation + +- `scripts/validate.sh` exits with status 0. +- `scripts/run-tests.sh` exits with status 0. + +# Exit conditions + +- All tests pass in a clean run. +- OR: no progress has been made for three consecutive iterations. + +# Recovery / Failure handling + +- If a change makes new tests fail, revert the change and try a + different approach. +- If a failure resists two attempts, leave it and move to the next + failing test. diff --git a/ralphloops/repo/examples/fix-failing-tests/README.md b/ralphloops/repo/examples/fix-failing-tests/README.md new file mode 100644 index 0000000..479f00f --- /dev/null +++ b/ralphloops/repo/examples/fix-failing-tests/README.md @@ -0,0 +1,33 @@ +# fix-failing-tests + +A Ralph Loop that drives an autonomous agent to fix failing tests one +at a time until the suite is green. + +## What it assumes + +- A runnable test command (wired through `scripts/run-tests.sh`). +- A clean working tree (checked by `scripts/validate.sh`). +- A git repository — the loop commits after each successful fix. + +## How to use it + +Point a compatible runtime at this directory: + +``` +ralph run examples/fix-failing-tests/ +``` + +Edit `scripts/run-tests.sh` to match your project's test runner before +running the loop. The script is the seam between the loop and the +project. + +## Why this loop is safe by construction + +The loop is constrained to: + +- never disable or delete failing tests +- never refactor beyond the fix +- stop if it makes no progress for three iterations + +Those constraints live in `RALPH.md` so any compatible runtime picks +them up. diff --git a/ralphloops/repo/examples/fix-failing-tests/docs/repo-conventions.md b/ralphloops/repo/examples/fix-failing-tests/docs/repo-conventions.md new file mode 100644 index 0000000..2ebf6e5 --- /dev/null +++ b/ralphloops/repo/examples/fix-failing-tests/docs/repo-conventions.md @@ -0,0 +1,25 @@ +# Repository Conventions (sample) + +This is a placeholder document that the `fix-failing-tests` loop +references from its `resources` list. Replace the contents with your +project's actual conventions when you adapt this loop. + +## Test layout + +- Tests live under `tests/`, mirroring the package structure. +- Each test file is named `test_.py` (or equivalent for your + language). +- Fixtures live in `tests/fixtures/`. + +## Commit message style + +- Use conventional commit prefixes: `fix:`, `feat:`, `refactor:`, + `docs:`, `test:`. +- Keep the subject under 72 characters. +- Explain *why* in the body, not just *what*. + +## What the agent should not touch + +- `CHANGELOG.md` +- `LICENSE` +- Anything under `third_party/` diff --git a/ralphloops/repo/examples/fix-failing-tests/scripts/run-tests.sh b/ralphloops/repo/examples/fix-failing-tests/scripts/run-tests.sh new file mode 100755 index 0000000..1889330 --- /dev/null +++ b/ralphloops/repo/examples/fix-failing-tests/scripts/run-tests.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# Run the project's test suite and print the results. +# Edit this script to match your project's test runner. +set -euo pipefail + +# Example: a Python project using pytest. +# exec uv run pytest + +# Example: a Node project. +# exec npm test + +# Default: refuse to run until the user has configured a test command. +echo "fix-failing-tests: scripts/run-tests.sh has not been configured." >&2 +echo "Edit this file to run your project's test suite." >&2 +exit 2 diff --git a/ralphloops/repo/examples/fix-failing-tests/scripts/validate.sh b/ralphloops/repo/examples/fix-failing-tests/scripts/validate.sh new file mode 100755 index 0000000..78b7146 --- /dev/null +++ b/ralphloops/repo/examples/fix-failing-tests/scripts/validate.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# Confirm the workspace is in a sane state before the loop touches it. +set -euo pipefail + +if ! command -v git >/dev/null 2>&1; then + echo "validate: git is not installed" >&2 + exit 1 +fi + +if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then + echo "validate: not inside a git repository" >&2 + exit 1 +fi + +# Warn (don't fail) if the working tree is dirty. The loop decides +# whether to continue. +if ! git diff --quiet || ! git diff --cached --quiet; then + echo "validate: working tree has uncommitted changes" >&2 +fi + +echo "validate: ok" diff --git a/ralphloops/repo/examples/raise-coverage/RALPH.md b/ralphloops/repo/examples/raise-coverage/RALPH.md new file mode 100644 index 0000000..15d1019 --- /dev/null +++ b/ralphloops/repo/examples/raise-coverage/RALPH.md @@ -0,0 +1,64 @@ +--- +name: raise-coverage +description: Add focused tests to lift coverage on under-tested modules. +ralphloops_version: 0.1 +version: 0.1.0 +license: MIT +tags: + - tests + - coverage +compatible_runtimes: + - ralphify >=0.3.0 +triggers: + - low coverage + - under-tested module +entry: + validate: scripts/validate.sh + test: scripts/run-tests.sh + coverage: scripts/report-coverage.sh +resources: + - docs/coverage-targets.md +--- + +# Goal + +Raise test coverage on under-tested modules by adding **focused** +tests, not by chasing a coverage percentage. + +# Context + +Read `docs/coverage-targets.md` — it lists which modules are in scope +and which are deliberately excluded. + +# Loop + +1. Run `scripts/report-coverage.sh` to produce a coverage report. +2. Pick the module with the **lowest covered-lines / total-lines** + ratio that is in scope. +3. Read the module and identify one behavior that is currently + untested. +4. Write a single focused test for that behavior. Prefer tests that + assert *behavior*, not *implementation details*. +5. Run `scripts/run-tests.sh`. The new test must pass. +6. Commit as `test: cover .`. +7. Repeat until every in-scope module meets its minimum coverage + target. + +# Constraints + +- Do not add tests that only exercise getters, setters, or pass-through + code. +- Do not modify production code except to expose things that are + obviously missing (e.g., a needed type export). +- Do not chase 100% coverage. Stop at the declared target. + +# Validation + +- `scripts/run-tests.sh` passes. +- `scripts/report-coverage.sh` shows progress over the previous + iteration. + +# Exit conditions + +- All in-scope modules meet their coverage target. +- OR: three consecutive iterations make no coverage progress. diff --git a/ralphloops/repo/examples/raise-coverage/README.md b/ralphloops/repo/examples/raise-coverage/README.md new file mode 100644 index 0000000..63f0663 --- /dev/null +++ b/ralphloops/repo/examples/raise-coverage/README.md @@ -0,0 +1,20 @@ +# raise-coverage + +A Ralph Loop for adding focused tests to under-tested modules without +chasing a coverage percentage. + +The loop deliberately caps itself at a declared target and refuses to +write tests for trivial pass-through code. That keeps the resulting +test suite useful instead of noisy. + +## What you need to wire up + +- `scripts/run-tests.sh` — runs the existing test suite +- `scripts/report-coverage.sh` — emits a coverage report the agent can read +- `scripts/validate.sh` — optional preflight checks + +## What you should edit + +Update `docs/coverage-targets.md` (create it when you adapt the loop) +to declare which modules are in scope and what the target percentage +is for each. diff --git a/ralphloops/repo/examples/refactor-module/RALPH.md b/ralphloops/repo/examples/refactor-module/RALPH.md new file mode 100644 index 0000000..714733e --- /dev/null +++ b/ralphloops/repo/examples/refactor-module/RALPH.md @@ -0,0 +1,64 @@ +--- +name: refactor-module +description: Refactor a single module against a set of invariants. +ralphloops_version: 0.1 +version: 0.1.0 +license: MIT +tags: + - refactor +compatible_runtimes: + - ralphify >=0.3.0 +triggers: + - refactor needed + - module is messy +entry: + validate: scripts/validate.sh + test: scripts/run-tests.sh + lint: scripts/lint.sh +resources: + - templates/pr-description.md +--- + +# Goal + +Refactor a single named module so that its public behavior is +unchanged but its internals are clearer. The module to refactor is +passed in via the runtime. + +# Context + +Refactoring is behavior-preserving by definition. Before making any +change, list the module's public surface and the tests that exercise +it. Those tests are your safety net — they must stay green at every +step. + +# Loop + +1. Run `scripts/validate.sh` and `scripts/run-tests.sh`. Both must + pass before any refactor begins. +2. Identify one **small** refactoring opportunity: a rename, an + extracted function, a removed duplication, a clarified condition. +3. Apply exactly that change. +4. Run `scripts/run-tests.sh`. If anything breaks, revert the change. +5. Run `scripts/lint.sh`. Fix any issues introduced by the change. +6. Commit as `refactor: `. +7. Repeat until the declared invariants are satisfied or the module + feels finished. + +# Invariants + +- The module's public API is unchanged. +- All tests that existed at the start still exist and still pass. +- No new dependencies are added. +- Line count does not grow by more than 10%. + +# Exit conditions + +- The loop has made at least one commit AND feels the module is + clearer than it started. +- OR: three consecutive iterations produce no committable change. + +# Notes for the agent + +Small, reviewable refactors beat large, clever ones. When in doubt, +do less. diff --git a/ralphloops/repo/examples/refactor-module/README.md b/ralphloops/repo/examples/refactor-module/README.md new file mode 100644 index 0000000..14489f7 --- /dev/null +++ b/ralphloops/repo/examples/refactor-module/README.md @@ -0,0 +1,7 @@ +# refactor-module + +A Ralph Loop for behavior-preserving refactors of a single named module. + +The loop is deliberately conservative: small commits, full tests +between every change, a hard cap on line-count growth. The goal is +*clearer internals*, not cleverness. diff --git a/ralphloops/repo/examples/refactor-module/templates/pr-description.md b/ralphloops/repo/examples/refactor-module/templates/pr-description.md new file mode 100644 index 0000000..ca84471 --- /dev/null +++ b/ralphloops/repo/examples/refactor-module/templates/pr-description.md @@ -0,0 +1,23 @@ +# Refactor: + +## What changed + +- + +## Why + +<1-2 sentences explaining the motivation — usually readability, +duplication removal, or clarity.> + +## Invariants preserved + +- [ ] Public API unchanged +- [ ] All pre-existing tests still pass +- [ ] No new dependencies +- [ ] Line count within +10% of the starting module + +## How to review + +Read the commits in order. Each commit is a small, self-contained +refactor step. If any commit is unclear, it can be reverted +independently. diff --git a/ralphloops/repo/examples/write-docs/RALPH.md b/ralphloops/repo/examples/write-docs/RALPH.md new file mode 100644 index 0000000..eba3149 --- /dev/null +++ b/ralphloops/repo/examples/write-docs/RALPH.md @@ -0,0 +1,55 @@ +--- +name: write-docs +description: Generate and revise documentation for existing code. +ralphloops_version: 0.1 +version: 0.1.0 +license: MIT +tags: + - docs +compatible_runtimes: + - ralphify >=0.3.0 +triggers: + - docs out of date + - missing documentation +entry: + validate: scripts/validate.sh + build: scripts/build-docs.sh +--- + +# Goal + +Bring project documentation back in line with the code: document +undocumented public symbols, update stale examples, and fix broken +links. Do not invent behavior — every claim in the docs must be +grounded in the code as it exists today. + +# Loop + +1. Run `scripts/build-docs.sh`. Note any warnings or broken links. +2. Pick **one** of: + - an undocumented public symbol + - a stale example that no longer runs + - a broken internal link + - a page that references a file that no longer exists +3. Fix exactly that one thing. Read the relevant code before writing + anything. +4. Rebuild the docs. The warning you fixed must be gone and no new + warnings introduced. +5. Commit as `docs: `. +6. Repeat until the docs build cleanly. + +# Constraints + +- Never invent behavior. If you can't find it in the code, don't + write it in the docs. +- Never delete a doc page to make a warning go away. +- Keep prose short and direct. + +# Validation + +- `scripts/build-docs.sh` exits 0 with zero warnings. + +# Exit conditions + +- The docs build cleanly. +- OR: three consecutive iterations produce no committable change. diff --git a/ralphloops/repo/examples/write-docs/README.md b/ralphloops/repo/examples/write-docs/README.md new file mode 100644 index 0000000..29889ec --- /dev/null +++ b/ralphloops/repo/examples/write-docs/README.md @@ -0,0 +1,7 @@ +# write-docs + +A Ralph Loop for bringing project documentation back in line with the +code. Focused on small, grounded fixes — never invented behavior. + +Wire `scripts/build-docs.sh` to your docs builder (MkDocs, Sphinx, +Docusaurus, etc.) before running the loop. diff --git a/ralphloops/repo/implementors/discovery.md b/ralphloops/repo/implementors/discovery.md new file mode 100644 index 0000000..a1721de --- /dev/null +++ b/ralphloops/repo/implementors/discovery.md @@ -0,0 +1,87 @@ +# Discovery + +Discovery is the process of locating Ralph Loop packages so they can be +loaded and executed. The format does not mandate a single discovery +mechanism — runtimes are free to combine whichever sources make sense +for their environment. + +## Discovery sources + +A runtime SHOULD support discovering packages from several sources: + +### 1. Explicit paths + +The simplest case: the user points the runtime at a directory. + +``` +ralph run path/to/fix-failing-tests/ +``` + +The runtime looks for `RALPH.md` at that path. + +### 2. Project-local loops + +Many projects will want to check in their loops alongside source code. +Runtimes SHOULD allow a configurable project-local directory, for +example `./loops/` or `./.ralphloops/`, containing one package per +subdirectory: + +``` +my-project/ +├── src/ +└── loops/ + ├── fix-failing-tests/ + │ └── RALPH.md + └── raise-coverage/ + └── RALPH.md +``` + +### 3. User-installed loops + +Runtimes MAY maintain a user-level directory of installed shared loops, +analogous to `~/.local/share/ralphloops/` or similar. + +### 4. Registry-downloaded loops + +When registries exist, a runtime MAY resolve a package name to a +download URL, fetch the package, unpack it into a local cache, and +then load it like any other directory package. The format itself is +agnostic to registry protocols. + +## Recursive discovery + +When scanning a directory tree for loops, a runtime: + +- MUST treat each `RALPH.md` file as the root of its own package. +- MUST NOT descend into a subdirectory of a package looking for a + nested package (a package owns its own directory tree). +- SHOULD skip hidden directories (`.git`, `.cache`, etc.) and common + build outputs (`node_modules`, `target`, `dist`). + +## Name resolution + +When the user asks for a loop by name (not path), the runtime SHOULD +resolve it by: + +1. Checking explicit paths passed on the command line. +2. Checking the project-local directory. +3. Checking the user-installed directory. +4. Optionally fetching from a registry. + +If multiple sources contain a package with the same name, earlier +sources take precedence. The runtime SHOULD warn the user about the +shadowing. + +## Listing and search + +Readers (Level 1) may present lists of loops to users. Useful sort and +filter dimensions: + +- `name` +- `description` +- `tags` +- `triggers` +- `compatible_runtimes` + +These are all optional metadata fields. Not every package will have +them, and discovery UIs should degrade gracefully. diff --git a/ralphloops/repo/implementors/execution-model.md b/ralphloops/repo/implementors/execution-model.md new file mode 100644 index 0000000..3cc3be0 --- /dev/null +++ b/ralphloops/repo/implementors/execution-model.md @@ -0,0 +1,94 @@ +# Execution Model + +The Ralph Loops format deliberately does not mandate a single execution +engine. Different runtimes have different strengths, and forcing them +into one execution model would make the format less portable, not more. + +This document describes what the format *does* require, and lists the +decisions runtimes are free to make. + +## What the format requires + +A Level 2 (Executor) runtime MUST: + +1. Load `RALPH.md` per the parsing rules. +2. Make the markdown body available to the agent as instructions. +3. Resolve bundled resources relative to the package root. +4. Refuse any path that escapes the package root. +5. Refuse packages whose `ralphloops_version` exceeds the runtime's + supported version. +6. Honor declared `entry` commands when the runtime's execution model + invokes them. + +## What the format does NOT specify + +Runtimes choose their own answers to the following questions: + +- **Iteration.** Does the runtime run the loop once, N times, or until + a condition is met? Is context reset between iterations or carried + forward? +- **Context construction.** Is the entire body passed to the agent on + every turn? Is it trimmed? Is it combined with additional runtime- + injected context? +- **Resource exposure.** Are bundled files mounted into the agent's + working directory? Embedded into the prompt? Exposed via a retrieval + tool? +- **Command execution.** How are `entry` commands run — directly on the + host, in a sandbox, via a container, as a subprocess? +- **Timeouts.** Per-command and per-iteration timeouts are a runtime + concern. +- **Logging and observability.** Runtimes are free to log however they + like. +- **Sandboxing and permissions.** The format does not attempt to solve + sandboxing universally. +- **Model selection.** Runtimes pick their own models, providers, and + sampling parameters. + +## Recommended practices + +Runtimes SHOULD: + +- Expose a stable working directory that corresponds to the package + root during execution. +- Surface declared `entry` commands to the agent as named, invokable + commands. +- Treat bundled scripts as untrusted by default, requiring opt-in + before running them on the host. +- Provide clear, reproducible logs of which iteration ran, what it + saw, and what it produced. + +## Runtime-specific templating + +A runtime MAY implement template expansion in the body. For example, +Ralphify expands `{{ commands. }}` to the output of a declared +command and `{{ args. }}` to named CLI arguments. The format +itself does not require or forbid templating; runtimes that implement +it MUST document their templating syntax and limitations in their own +docs. + +Loops that rely on runtime-specific templating SHOULD declare that +dependency via `compatible_runtimes`. + +## Error semantics + +When execution fails, the runtime SHOULD: + +- Report which package, which file, and which step failed. +- Distinguish fatal errors (cannot continue) from warnings (should + continue). +- Not leave the host in a half-executed state (e.g., partial + filesystem writes with no record). + +## Documentation expectation + +An Executor runtime is expected to publish its execution model in its +own documentation. Loop authors need to know: + +- how iteration works +- how context is constructed +- how resources are exposed +- how commands are executed +- how the loop terminates + +Without that documentation, authors cannot write portable loops for +your runtime. diff --git a/ralphloops/repo/implementors/overview.md b/ralphloops/repo/implementors/overview.md new file mode 100644 index 0000000..895036a --- /dev/null +++ b/ralphloops/repo/implementors/overview.md @@ -0,0 +1,81 @@ +# Implementor Overview + +This document is a narrative overview for people building runtimes, +editors, registries, or analysis tools that understand Ralph Loops. For +normative rules, read the [specification](../specification/format.md). + +## What a runtime has to do + +At a minimum, a compatible runtime: + +1. **Discovers** packages by locating `RALPH.md` files. +2. **Parses** optional YAML frontmatter and the markdown body. +3. **Resolves** bundled resources relative to the package root. +4. **Exposes** loop instructions to an agent or downstream tool. + +A runtime does not need to implement all of these in one tool. Many +useful tools only implement Level 1 (Reader) or Level 2 (Executor); see +[`compatibility.md`](../specification/compatibility.md). + +## Recommended reading order + +1. [`overview.md`](overview.md) — this file +2. [`discovery.md`](discovery.md) — how to find packages +3. [`parsing.md`](parsing.md) — how to read `RALPH.md` +4. [`execution-model.md`](execution-model.md) — how to run loops +5. [`test-cases.md`](test-cases.md) — conformance fixtures + +## Principles for implementors + +### Be permissive about what you accept + +Unknown keys in frontmatter should be preserved and surfaced as warnings, +not fatal errors. Recommended fields are recommended, not required. + +### Be strict about safety + +Path traversal, symlink escape, and absolute paths outside the package +root are always fatal. A runtime that loads a malicious package should +not compromise the host. + +### Don't reinvent execution semantics + +The format intentionally leaves runtime behavior open. Build whatever +execution model fits your tool — iteration, reset, context accumulation, +retrieval — but document it so loop authors can rely on consistent +behavior. + +### Prefer readable errors + +Loop authors are humans. When validation fails, say exactly which file, +which field, and why. + +### Round-trip unknown metadata + +If you rewrite `RALPH.md` for any reason (packaging, signing, caching), +preserve unknown frontmatter keys. The format evolves; don't drop fields +you don't recognize. + +## Minimal parser pseudocode + +```python +def load_ralph_loop(package_root: Path) -> Loop: + entry = package_root / "RALPH.md" + if not entry.exists(): + raise FatalError("missing RALPH.md") + + text = entry.read_text(encoding="utf-8") # fatal if not UTF-8 + frontmatter, body = split_frontmatter(text) + + metadata = {} + if frontmatter is not None: + metadata = yaml_safe_load(frontmatter) + require(metadata, ["name", "description", "ralphloops_version"]) + reject_path_traversal(metadata) + reject_unsupported_version(metadata["ralphloops_version"]) + + return Loop(root=package_root, metadata=metadata, body=body) +``` + +This is pseudocode, not normative. The normative rules live in the +[specification](../specification/format.md). diff --git a/ralphloops/repo/implementors/parsing.md b/ralphloops/repo/implementors/parsing.md new file mode 100644 index 0000000..772f7ad --- /dev/null +++ b/ralphloops/repo/implementors/parsing.md @@ -0,0 +1,101 @@ +# Parsing + +This document describes how to parse a Ralph Loop `RALPH.md` file. It +is a companion to the normative rules in +[`specification/format.md`](../specification/format.md) and +[`specification/metadata.md`](../specification/metadata.md). + +## File encoding + +`RALPH.md` MUST be valid UTF-8. Implementations: + +- MUST reject files that are not valid UTF-8 as fatal. +- SHOULD handle and strip a UTF-8 BOM if present. +- SHOULD normalize line endings to `\n` internally. + +## Frontmatter detection + +Frontmatter is a YAML block at the very top of the file, delimited by +`---` lines. Detection rules: + +- If the first line is exactly `---`, frontmatter begins on the next + line. +- Frontmatter ends at the next line that is exactly `---`. +- If no closing `---` is found, the file is invalid: treat as a fatal + parse error. +- If the first line is not `---`, the file has no frontmatter and the + entire file is the body. + +## YAML parsing + +- Use a **safe** YAML loader. Do not allow arbitrary object + instantiation. +- YAML 1.2 semantics are recommended. +- The top-level frontmatter document MUST be a mapping. Lists or + scalars at the top level are a fatal error. + +## Required fields + +If frontmatter is present, these fields are required: + +- `name` (string) +- `description` (string) +- `ralphloops_version` (string) + +Missing any of these is a fatal error. + +## Path fields + +Path-valued fields include everything under `entry` and everything in +`resources`. For each path: + +- Normalize it against the package root. +- Reject paths containing `..` that escape the package root. +- Reject absolute paths on POSIX (`/...`) and Windows (`C:\...`, + `\\?\...`). +- Treat forward slashes as path separators, regardless of host OS. + +Missing files referenced from `entry` are fatal. Missing files +referenced from `resources` are warnings. + +## Unknown fields + +- Unknown top-level frontmatter keys MUST be preserved. +- Unknown keys MAY produce warnings. +- Unknown keys MUST NOT cause a fatal parse error. + +## Version gating + +If `ralphloops_version` is strictly greater than the version the +runtime supports, the runtime MUST refuse to load the package and +SHOULD emit a clear error explaining the mismatch. + +## Body handling + +Everything after the closing frontmatter `---` is the markdown body. +The body: + +- Is agent-facing instructions. +- MUST NOT be interpreted as a strict schema. +- MAY use any markdown features (headings, lists, fenced code blocks, + tables, inline HTML). +- SHOULD be passed to the agent as text, unmodified, except for + possible template expansion performed by the runtime (a runtime- + specific feature). + +## Template expansion + +The format itself does not define template expansion in the body. +Runtimes MAY implement template expansion (e.g. Ralphify's +`{{ commands.name }}` and `{{ args.name }}`), but they MUST document +their templating syntax in their own docs and MUST degrade gracefully +when a loop doesn't use templating. + +## Error reporting + +When reporting errors, implementations SHOULD include: + +- the package root path +- the field or line number where the error occurred +- a short explanation of the rule that was violated +- a link to the relevant spec section when possible diff --git a/ralphloops/repo/implementors/test-cases.md b/ralphloops/repo/implementors/test-cases.md new file mode 100644 index 0000000..3c0a695 --- /dev/null +++ b/ralphloops/repo/implementors/test-cases.md @@ -0,0 +1,76 @@ +# Test Cases + +The [`tests/`](../tests/) directory in this repository contains a +conformance corpus of valid and invalid Ralph Loop packages. Runtimes +are encouraged to run against it and publish a conformance report. + +## Layout + +``` +tests/ +├── valid/ +│ ├── minimal/ +│ └── full/ +└── invalid/ + ├── missing-ralph-md/ + └── bad-frontmatter/ +``` + +Each valid fixture is a complete, loadable package. Each invalid +fixture is a package that MUST be rejected, with a short `REASON.md` +file explaining why. + +## How to use the corpus + +### Readers (Level 1) + +For each valid fixture, a Reader SHOULD: + +- Successfully locate `RALPH.md`. +- Successfully parse the frontmatter (if present). +- Return the declared metadata without loss. + +For each invalid fixture, a Reader SHOULD: + +- Reject the package with a clear error. +- Not crash. +- Not silently accept invalid input. + +### Executors (Level 2) + +Everything a Reader does, plus: + +- Successfully resolve every file referenced from `entry` and + `resources` in valid fixtures. +- Reject any valid fixture whose `entry` commands cannot be resolved + safely. +- Reject any invalid fixture that requests path traversal. + +### Publishers (Level 3) + +Everything an Executor does, plus: + +- Produce a deterministic validation report for every fixture. +- Refuse to publish any invalid fixture. + +## Conformance report format + +A conformance report is a plain-text or JSON document listing, for +each fixture, whether the implementation accepted or rejected it, and +whether that matched the expected outcome. Example: + +``` +tests/valid/minimal accepted PASS +tests/valid/full accepted PASS +tests/invalid/missing-ralph-md rejected PASS +tests/invalid/bad-frontmatter rejected PASS +``` + +## Adding fixtures + +See [`CONTRIBUTING.md`](../CONTRIBUTING.md) for rules on adding new +fixtures. In short: + +- Valid fixtures go under `tests/valid//`. +- Invalid fixtures go under `tests/invalid//` with a `REASON.md`. +- Keep fixtures minimal — each should demonstrate one rule. diff --git a/ralphloops/repo/loop-creation/best-practices.md b/ralphloops/repo/loop-creation/best-practices.md new file mode 100644 index 0000000..e7aeab7 --- /dev/null +++ b/ralphloops/repo/loop-creation/best-practices.md @@ -0,0 +1,98 @@ +# Best Practices + +Guidelines for writing portable, reusable Ralph Loops. + +## One job per loop + +Each package should describe a single outcome. Small loops are easier +to reuse, review, and debug than large monolithic ones. If a loop feels +like it's doing two things, split it. + +Good names: `fix-failing-tests`, `raise-coverage`, `refactor-module`, +`write-docs`, `dependency-updater`, `bug-hunter`. + +Bad names: `do-stuff`, `main-loop`, `my-ralphify-loop-v2`. + +## Keep RALPH.md operational + +The body is agent-facing instructions, not marketing copy. Write: + +- concrete steps +- explicit validation commands +- clear exit conditions +- short, direct sentences + +Move large background material into bundled files under `docs/` and +reference them. + +## Bundle reusable scripts + +If the loop needs to run tests, lint, or validate something, put the +commands in a script under `scripts/` and reference it from the +`entry` map. This makes the loop portable across projects that wire +their commands differently. + +## Prefer relative paths + +All paths in metadata resolve relative to the package root. Avoid +absolute paths. Never reference files outside the loop directory. + +## Include validation and exit conditions + +An autonomous loop must know when to stop. Always include: + +- a `validate` or `test` entry that can verify progress +- explicit exit conditions in the body + +Without these, the runtime cannot decide when the loop is done and may +loop indefinitely. + +## Name packages by outcome + +Outcome-oriented names (`fix-failing-tests`) travel across projects +better than tool-oriented names (`my-ralphify-loop`). Assume someone +will find your loop in a list and need to understand what it does in +under three seconds. + +## Declare runtime compatibility + +Use `compatible_runtimes` to declare which runtimes and versions you +have tested the loop against: + +```yaml +compatible_runtimes: + - ralphify >=0.3.0 +``` + +This is a hint, not a hard constraint. Be honest about what you've +actually tested. + +## Ship a realistic example + +Include a small fixture or sample input under `examples/` so users +and runtimes can smoke-test the loop without a real project attached. + +## Keep frontmatter small + +The frontmatter is intentionally minimal. Resist the urge to encode +every behavior as metadata. If something belongs in code or prose, put +it in a script or a markdown file. + +## Write for an agent that forgets + +Assume the agent has no memory between iterations. Every loop +iteration must be able to re-read `RALPH.md` and know exactly what to +do next. Avoid instructions that depend on remembering a previous +turn. + +## Don't require a specific model + +The format is runtime-agnostic and model-agnostic. Don't hardcode +model names, provider-specific features, or token budgets into your +loop body unless the loop genuinely cannot work without them. + +## Test your loop before publishing + +Run the loop against a realistic project before sharing it. Loops that +look clean in the abstract often fall apart the first time they hit +real code. Fix the loop, then publish. diff --git a/ralphloops/repo/loop-creation/quickstart.md b/ralphloops/repo/loop-creation/quickstart.md new file mode 100644 index 0000000..0c7435f --- /dev/null +++ b/ralphloops/repo/loop-creation/quickstart.md @@ -0,0 +1,100 @@ +# Quickstart + +This guide walks you through authoring your first Ralph Loop package. +You will end up with a directory that any compatible runtime can +discover and execute. + +## 1. Create a loop directory + +```bash +mkdir fix-failing-tests +cd fix-failing-tests +``` + +The directory name is the loop's package name. Choose an outcome- +oriented name like `fix-failing-tests` or `raise-coverage`. + +## 2. Add a RALPH.md file + +Create `RALPH.md` with frontmatter and a loop body: + +```markdown +--- +name: fix-failing-tests +description: Find and fix failing tests one failure at a time. +ralphloops_version: 0.1 +version: 0.1.0 +license: MIT +entry: + validate: scripts/validate.sh + test: scripts/run-tests.sh +--- + +# Goal + +Fix failing tests one failure at a time. + +# Loop + +1. Run the validation commands. +2. Identify the highest-signal failure. +3. Make the smallest useful change. +4. Re-run validation. +5. Commit only if checks pass. + +# Exit conditions + +- All tests pass. +- No remaining failures reported by `scripts/run-tests.sh`. +``` + +## 3. Add supporting files + +Bundle the scripts, docs, and fixtures the loop needs alongside +`RALPH.md`: + +``` +fix-failing-tests/ +├── RALPH.md +├── scripts/ +│ ├── run-tests.sh +│ └── validate.sh +└── docs/ + └── repo-conventions.md +``` + +Scripts referenced from `entry` must exist, or the package fails +validation. + +## 4. Validate the package + +Any Level 1 (Reader) runtime can validate your package. For example, +with a conforming CLI: + +```bash +ralphloops validate fix-failing-tests/ +``` + +## 5. Run it with a compatible runtime + +Use any runtime that supports Ralph Loops at Level 2 (Executor) or +higher. For example, with [Ralphify](https://ralphify.co/): + +```bash +ralph run fix-failing-tests/ +``` + +## 6. Share it + +Because a Ralph Loop is just a directory, you can share it by: + +- committing it to a git repository as a subdirectory +- publishing it as its own repository +- zipping it up and sending it +- publishing it to a registry (when one exists) + +## Next steps + +- Read the [best practices guide](best-practices.md) +- Browse the [example packages](../examples/) +- Read the full [specification](../specification/format.md) diff --git a/ralphloops/repo/loop-creation/templates/RALPH.md.template b/ralphloops/repo/loop-creation/templates/RALPH.md.template new file mode 100644 index 0000000..0e74138 --- /dev/null +++ b/ralphloops/repo/loop-creation/templates/RALPH.md.template @@ -0,0 +1,56 @@ +--- +name: +description: +ralphloops_version: 0.1 +version: 0.1.0 +license: MIT +author: +tags: + - +compatible_runtimes: + - ralphify >=0.3.0 +triggers: + - +entry: + validate: scripts/validate.sh + test: scripts/run-tests.sh +resources: + - docs/context.md +--- + +# Goal + + + +# Context + + + +# Loop + +1. +2. +3. +4. +5. + +# Constraints + +- +- + +# Validation + +- Run `scripts/validate.sh`. +- Run `scripts/run-tests.sh`. + +# Exit conditions + +- +- + +# Recovery / Failure handling + +- +- diff --git a/ralphloops/repo/rfcs/0001-format-principles.md b/ralphloops/repo/rfcs/0001-format-principles.md new file mode 100644 index 0000000..88975da --- /dev/null +++ b/ralphloops/repo/rfcs/0001-format-principles.md @@ -0,0 +1,82 @@ +# RFC 0001 — Format Principles + +- **Status:** Accepted +- **Target version:** 0.1 +- **Author:** Ralph Loops contributors + +## Summary + +This RFC records the design principles that Ralph Loops v0.1 is built +on, and which future RFCs should be judged against. + +## Motivation + +Without written principles, small decisions accrete into a format +that contradicts itself. This RFC fixes the principles so that future +changes have something to argue with. + +## Principles + +### 1. The unit of portability is a directory + +A Ralph Loop is a folder with a required entrypoint file, not a +single file and not a ZIP archive. Folders are git-friendly, +human-inspectable, and trivially bundleable. + +### 2. Frontmatter is small + +The required metadata is kept as small as possible. Recommended +metadata is long-tailed and optional. Runtimes preserve unknown keys. + +### 3. The body is prose, not an AST + +The markdown body of `RALPH.md` is agent-facing instructions, not a +strict schema. Runtimes MUST NOT enforce a fixed section layout. + +### 4. Paths resolve against the package root + +Every relative path in metadata resolves relative to the package +root. Traversal outside the root is always a fatal error. + +### 5. One runtime is not special + +The format is runtime-agnostic. No runtime's convention becomes +normative in the spec. Runtime-specific behavior belongs in runtime +docs. + +### 6. Conformance is tiered + +Runtimes self-declare as Reader, Executor, or Publisher. Not every +tool has to implement everything. + +### 7. The format is a proposal, not a standard + +Ralph Loops is explicitly a proposed format. It earns adoption +through usefulness, not authority. Status language in every artifact +reflects this. + +### 8. Ralph methodology is not owned + +Ralph Loops is inspired by Geoffrey Huntley's Ralph loop methodology. +The format does not claim ownership of the methodology. Naming and +attribution across the project reflect this explicitly. + +## Drawbacks + +Fixing principles makes some future changes harder. That is the +point. + +## Alternatives considered + +- **Single-file format.** Rejected: would prevent bundling scripts + and supporting docs, which is one of the format's primary reasons + to exist. +- **Mandatory section schema in the body.** Rejected: would make the + format brittle and hostile to authors. +- **Runtime-prescriptive spec.** Rejected: would entrench one + implementation at the expense of portability. + +## Unresolved questions + +None for v0.1. Later RFCs may revisit specific fields, the +compatibility model, or registry semantics. diff --git a/ralphloops/repo/rfcs/README.md b/ralphloops/repo/rfcs/README.md new file mode 100644 index 0000000..5d11d75 --- /dev/null +++ b/ralphloops/repo/rfcs/README.md @@ -0,0 +1,46 @@ +# RFCs + +Ralph Loops uses a lightweight RFC process for non-trivial changes to +the format. + +## When to write an RFC + +Write an RFC when your change: + +- adds, removes, or renames a metadata field +- tightens or loosens a validation rule +- changes path resolution semantics +- changes the runtime contract +- introduces a new compatibility class +- defines registry or distribution semantics + +You do **not** need an RFC for typo fixes, clarifications, new +fixtures, or new examples. Open a normal PR for those. + +## Process + +1. Open a discussion or issue describing the problem. +2. Copy `0001-format-principles.md` as a template under a new number. +3. Fill in Summary, Motivation, Proposal, Drawbacks, Alternatives, + and Unresolved Questions. +4. Open a PR. Maintainers and the community review. +5. Revise in response to feedback. +6. A maintainer accepts, rejects, or defers the RFC. +7. Accepted RFCs ship in a future `ralphloops_version` release and + are referenced from `specification/changelog.md`. + +## Numbering + +RFCs are numbered sequentially starting at `0001`. Numbers are +assigned when an RFC PR is opened, not when it is accepted. + +## Initial RFCs + +- [`0001-format-principles.md`](0001-format-principles.md) — the + design principles Ralph Loops v0.1 is built on. + +Planned future RFCs: + +- `0002` — Metadata shape (revisiting recommended fields) +- `0003` — Compatibility declaration model +- `0004` — Registry / distribution model diff --git a/ralphloops/repo/schemas/metadata.schema.json b/ralphloops/repo/schemas/metadata.schema.json new file mode 100644 index 0000000..d27caf0 --- /dev/null +++ b/ralphloops/repo/schemas/metadata.schema.json @@ -0,0 +1,73 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://ralphloops.io/schemas/metadata.schema.json", + "title": "Ralph Loops frontmatter metadata", + "description": "JSON Schema for the YAML frontmatter block of a RALPH.md file (ralphloops_version 0.1).", + "type": "object", + "required": ["name", "description", "ralphloops_version"], + "additionalProperties": true, + "properties": { + "name": { + "type": "string", + "minLength": 1, + "description": "Short stable package name." + }, + "description": { + "type": "string", + "minLength": 1, + "description": "One-sentence summary for discovery." + }, + "ralphloops_version": { + "type": "string", + "pattern": "^[0-9]+\\.[0-9]+(\\.[0-9]+)?$", + "description": "Format version used by the package." + }, + "version": { + "type": "string", + "description": "Package version (semver recommended)." + }, + "license": { + "type": "string", + "description": "SPDX license identifier." + }, + "author": { + "oneOf": [ + {"type": "string"}, + { + "type": "object", + "properties": { + "name": {"type": "string"}, + "email": {"type": "string", "format": "email"}, + "url": {"type": "string", "format": "uri"} + }, + "additionalProperties": true + } + ] + }, + "homepage": {"type": "string", "format": "uri"}, + "repository": {"type": "string"}, + "tags": { + "type": "array", + "items": {"type": "string"} + }, + "compatible_runtimes": { + "type": "array", + "items": {"type": "string"}, + "description": "Runtimes or version ranges known to support this package." + }, + "triggers": { + "type": "array", + "items": {"type": "string"} + }, + "entry": { + "type": "object", + "description": "Map of named entrypoints (relative paths to files inside the package).", + "additionalProperties": {"type": "string"} + }, + "resources": { + "type": "array", + "items": {"type": "string"}, + "description": "Supporting files that are particularly important for this loop." + } + } +} diff --git a/ralphloops/repo/specification/changelog.md b/ralphloops/repo/specification/changelog.md new file mode 100644 index 0000000..7a9d05f --- /dev/null +++ b/ralphloops/repo/specification/changelog.md @@ -0,0 +1,25 @@ +# Specification Changelog + +All notable changes to the Ralph Loops specification are documented here. +The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) +loosely. + +## 0.1 — initial draft + +Initial public draft of the Ralph Loops format. + +- Defined the package as a directory containing a required `RALPH.md`. +- Defined optional YAML frontmatter with required fields `name`, + `description`, and `ralphloops_version`. +- Defined recommended fields: `version`, `license`, `author`, + `homepage`, `repository`, `tags`, `compatible_runtimes`, `triggers`, + `entry`, `resources`. +- Defined path resolution rules (relative to package root, no + traversal). +- Defined compatibility classes: Reader, Executor, Publisher. +- Defined validation rules and the minimum runtime contract. +- Shipped six reference example packages. +- Shipped a draft JSON Schema for frontmatter metadata. +- Established the RFC process under `rfcs/`. + +This is a draft release. Breaking changes may land in any `0.x` version. diff --git a/ralphloops/repo/specification/compatibility.md b/ralphloops/repo/specification/compatibility.md new file mode 100644 index 0000000..3af394c --- /dev/null +++ b/ralphloops/repo/specification/compatibility.md @@ -0,0 +1,88 @@ +# Compatibility Classes + +Runtimes declare their support level for Ralph Loops using one of three +compatibility classes. This lets users and loop authors set accurate +expectations without forcing every tool to implement the whole format. + +## Level 1 — Reader + +A **Reader** can discover and parse Ralph Loop packages. + +A Reader MUST: + +- Locate `RALPH.md` files in a given directory. +- Parse optional YAML frontmatter using a safe YAML loader. +- Load the markdown body as text. +- Validate required metadata if frontmatter is present. +- Reject path traversal in metadata. + +A Reader is NOT required to execute loops. + +Example use cases: + +- Registries and galleries +- IDE extensions that preview loops +- Static analyzers and linters + +## Level 2 — Executor + +An **Executor** is everything a Reader is, plus it can execute loop +instructions and load bundled files. + +An Executor MUST: + +- Implement every Reader requirement. +- Make the markdown body available as instructions to an agent. +- Resolve bundled files relative to the package root. +- Refuse to execute packages that escape the package root. +- Refuse to execute packages whose `ralphloops_version` exceeds what + the Executor supports. + +An Executor SHOULD: + +- Document its execution model publicly. +- Support declared `entry` commands. +- Provide clear error messages for validation failures. + +Example use cases: + +- Runtime harnesses like [Ralphify](https://ralphify.co/) +- CI integrations that run loops as part of automation + +## Level 3 — Publisher + +A **Publisher** is everything an Executor is, plus it can package and +publish Ralph Loops for reuse. + +A Publisher MUST: + +- Implement every Executor requirement. +- Validate a package against the format before publishing. +- Refuse to publish packages with path traversal, missing required + fields, or unparseable frontmatter. + +A Publisher SHOULD: + +- Sign or attest to published packages. +- Provide a way to resolve a published package back to a directory + locally. + +Example use cases: + +- Registries that host shared loop packages +- CLI tools for packaging and distributing loops + +## Declaring compatibility + +Runtimes SHOULD state their compatibility class and the +`ralphloops_version` range they support in their own documentation. For +example: + +> *FooRuntime implements Ralph Loops at Level 2 (Executor) and supports +> `ralphloops_version` 0.1.* + +## Conformance + +The [`tests/`](../tests/) directory in this repository contains valid +and invalid fixtures. Implementations are encouraged to run against +them and publish a conformance report. diff --git a/ralphloops/repo/specification/directory-layout.md b/ralphloops/repo/specification/directory-layout.md new file mode 100644 index 0000000..22feb78 --- /dev/null +++ b/ralphloops/repo/specification/directory-layout.md @@ -0,0 +1,83 @@ +# Directory Layout + +A Ralph Loop package is a directory. This document describes the +conventions and constraints for that directory's layout. + +## Minimum + +The minimum valid package is a directory containing a single `RALPH.md` +file: + +``` +minimal-loop/ +└── RALPH.md +``` + +## Typical layout + +Most real packages bundle supporting resources. A typical package might +look like: + +``` +fix-failing-tests/ +├── RALPH.md +├── README.md +├── scripts/ +│ ├── run-tests.sh +│ └── validate.sh +├── prompts/ +│ └── edge-cases.md +├── templates/ +│ └── issue-comment.md +├── docs/ +│ └── repo-conventions.md +└── examples/ + └── sample-failure.txt +``` + +There are no required subdirectories beyond `RALPH.md`. + +## Conventional subdirectories + +These names are not required, but are recommended for clarity: + +| Directory | Convention | +|--------------|---------------------------------------------------| +| `scripts/` | Executable helpers invoked by the loop. | +| `prompts/` | Prompt snippets and supplementary instructions. | +| `templates/` | Reusable text/code templates. | +| `docs/` | Reference documentation for the agent. | +| `examples/` | Sample inputs or fixtures. | +| `fixtures/` | Test data. | +| `plans/` | Plan documents for multi-step loops. | + +## Required entrypoint + +- `RALPH.md` MUST exist at the package root. +- The filename is case-sensitive: `RALPH.md`, not `ralph.md` or + `Ralph.md`. + +## Package root + +The package root is the directory containing `RALPH.md`. All relative +paths in metadata resolve against this directory. + +## What does NOT belong in a package + +- Absolute paths to resources outside the package root +- Symlinks whose targets lie outside the package root +- Files referenced via `..` traversal in metadata +- Runtime-specific lock files or caches (these belong to the runtime, + not the package) + +## Nested packages + +A directory MAY contain multiple Ralph Loop packages as subdirectories, +each with its own `RALPH.md`. Runtimes performing recursive discovery +MUST treat each `RALPH.md` as the root of its own package. + +## README files + +A package MAY include a `README.md` alongside `RALPH.md`. The README is +for humans browsing the repository; `RALPH.md` is for the runtime and +the agent. They serve different audiences. diff --git a/ralphloops/repo/specification/format.md b/ralphloops/repo/specification/format.md new file mode 100644 index 0000000..eda385a --- /dev/null +++ b/ralphloops/repo/specification/format.md @@ -0,0 +1,169 @@ +# Ralph Loop Format (v0.1 draft) + +This document defines the Ralph Loop package format, version `0.1`. + +## 1. Definition + +A **Ralph Loop** is a directory-based package with: + +- one required file: `RALPH.md` +- zero or more optional bundled files and subdirectories + +A loop package MAY contain scripts, templates, fixtures, reference +materials, sample inputs, plans, checklists, or any other files that help +a compatible runtime execute the loop. + +## 2. Required entrypoint + +Each Ralph Loop package MUST contain a file named: + +``` +RALPH.md +``` + +This file is the canonical entrypoint for the package. + +## 3. Package root + +The package root is the directory containing `RALPH.md`. All relative +paths in the format are resolved relative to the package root unless +otherwise specified. + +## 4. Allowed structure + +There are no required subdirectories beyond `RALPH.md`. A typical +package might look like: + +``` +fix-failing-tests/ +├── RALPH.md +├── scripts/ +│ ├── run-tests.sh +│ └── validate.sh +├── prompts/ +│ └── edge-cases.md +├── templates/ +│ └── issue-comment.md +└── docs/ + └── repo-conventions.md +``` + +## 5. `RALPH.md` file structure + +`RALPH.md` consists of: + +1. optional YAML frontmatter +2. markdown body content + +Example: + +```markdown +--- +name: fix-failing-tests +description: Find and fix failing tests one failure at a time. +version: 0.1 +ralphloops_version: 0.1 +license: MIT +compatible_runtimes: + - ralphify >=0.3.0 +triggers: + - failing tests + - test suite is red +entry: + validate: scripts/validate.sh + test: scripts/run-tests.sh +resources: + - docs/repo-conventions.md +--- + +# Goal + +Fix failing tests one failure at a time. + +# Loop + +1. Run the validation commands. +2. Identify the next highest-signal failure. +3. Make the smallest useful change. +4. Re-run validation. +5. Commit only if checks pass. +``` + +## 6. Markdown body semantics + +The RALPH.md body contains the human-readable loop definition. + +The format deliberately avoids over-structuring the markdown body. +Compatible runtimes MUST treat the body as agent-facing instructions, +not as a strict AST. There is no enforced section schema. + +Recommended sections (non-normative): + +- `Goal` +- `Context` +- `Loop` +- `Constraints` +- `Validation` +- `Exit Conditions` +- `Recovery / Failure Handling` +- `Notes for the Agent` + +## 7. Optional bundled files + +A package MAY include any supporting files, including: + +- scripts +- prompts +- templates +- examples +- fixtures +- plans +- checklists +- JSON/YAML config +- reference docs +- generated examples + +Compatible runtimes MUST allow the agent to reference these files +relative to the loop package root. + +## 8. Path resolution rules + +All paths in metadata are relative to the package root unless they are +absolute URIs. + +Runtimes MUST: + +- normalize relative paths safely +- reject path traversal that escapes the package root +- treat missing referenced files as package errors or warnings (see + [`runtime-contract.md`](runtime-contract.md)) + +## 9. Validation rules + +A valid v0.1 package MUST: + +- contain `RALPH.md` +- use valid UTF-8 text for `RALPH.md` +- contain parseable YAML if frontmatter is present +- not reference missing required entry files if declared in metadata +- not contain path traversal references in metadata + +## 10. Packaging and distribution + +A Ralph Loop package MAY be distributed as: + +- a git repository subdirectory +- a standalone repository +- a tarball or zip archive +- a registry package (when registries exist) + +The directory itself is the unit of portability. + +## 11. Versioning + +`ralphloops_version` controls spec compatibility. + +- `0.x` — draft / experimental +- `1.x` — stable compatibility line + +See [`VERSIONING.md`](../VERSIONING.md) for the full policy. diff --git a/ralphloops/repo/specification/metadata.md b/ralphloops/repo/specification/metadata.md new file mode 100644 index 0000000..d8d7d4d --- /dev/null +++ b/ralphloops/repo/specification/metadata.md @@ -0,0 +1,107 @@ +# Metadata + +`RALPH.md` frontmatter is optional YAML delimited by `---` lines at the +top of the file. Frontmatter is strongly recommended for ecosystem +compatibility but is not strictly required. + +## Required fields (if frontmatter is present) + +| Field | Type | Meaning | +|----------------------|--------|----------------------------------------------| +| `name` | string | Short stable package name. | +| `description` | string | One-sentence summary for discovery. | +| `ralphloops_version` | string | Format version used by the package. | + +If frontmatter is omitted entirely, a runtime MAY still load the loop, +but the package is considered minimally described. + +## Recommended fields + +| Field | Type | Meaning | +|-----------------------|-------------------------|---------------------------------------------------------------| +| `version` | string | Package version (semver recommended). | +| `license` | string | SPDX license identifier. | +| `author` | string or object | Author name or structured author info. | +| `homepage` | string (URL) | Project homepage. | +| `repository` | string (URL) | Source repository URL. | +| `tags` | list of strings | Free-form tags for discovery. | +| `compatible_runtimes` | list of strings | Runtimes/version ranges known to support the package. | +| `triggers` | list of strings | Human-readable phrases describing when to select this loop. | +| `entry` | map of string → path | Named executable or reference entrypoints. | +| `resources` | list of paths | Supporting files that are particularly important. | + +## Field semantics + +### `name` + +A short, stable identifier for the package. Typically matches the +directory name. Outcome-oriented names are preferred +(`fix-failing-tests`, not `my-loop-1`). + +### `description` + +A one-sentence summary suitable for listings, registries, and runtime +discovery UIs. + +### `ralphloops_version` + +The format version the package targets, e.g. `0.1`. Runtimes MUST refuse +to execute packages whose `ralphloops_version` is strictly greater than +the version they support. + +### `version` + +The package's own version. Semver is recommended. Separate from +`ralphloops_version`. + +### `compatible_runtimes` + +A list of strings of the form ` `, e.g.: + +```yaml +compatible_runtimes: + - ralphify >=0.3.0 +``` + +Runtimes SHOULD evaluate these strings and warn on mismatch. +This is a hint, not a hard constraint. + +### `triggers` + +Human-readable phrases that describe the conditions under which a +runtime or a user might select this loop. These are for discovery UIs, +not for execution logic. + +### `entry` + +A map of named entrypoints. Values are paths relative to the package +root. Suggested keys: + +- `validate` — a command that verifies the loop's preconditions or + results +- `test` — a command that runs the project's tests +- `lint` — a command that lints the project +- `plan` — a file or script that produces a plan document +- `bootstrap` — a script that prepares the environment + +Additional keys are allowed and will be preserved. + +### `resources` + +A list of relative paths to supporting files that are particularly +important for the loop. Runtimes MAY use this list to decide which +files to surface to the agent first. + +## Path rules + +- Paths MUST be relative to the package root unless they are absolute + URIs. +- Paths MUST NOT use `..` to escape the package root. +- Forward slashes MUST be used as path separators in metadata, even on + platforms that use a different native separator. + +## Unknown fields + +Unknown top-level frontmatter keys MUST be preserved by implementations +and MAY be surfaced as warnings during validation. They MUST NOT cause a +fatal parse error. diff --git a/ralphloops/repo/specification/overview.md b/ralphloops/repo/specification/overview.md new file mode 100644 index 0000000..f54b34c --- /dev/null +++ b/ralphloops/repo/specification/overview.md @@ -0,0 +1,77 @@ +# Specification Overview + +**Ralph Loops** is an open proposed format for portable Ralph-style agent +loops. A Ralph Loop is a directory-based package centered on a required +`RALPH.md` file. + +This overview introduces the format in narrative form. The normative rules +live in the other documents in this directory: + +- [`format.md`](format.md) — the package format itself +- [`metadata.md`](metadata.md) — frontmatter fields and their semantics +- [`directory-layout.md`](directory-layout.md) — directory structure rules +- [`runtime-contract.md`](runtime-contract.md) — what runtimes must do +- [`compatibility.md`](compatibility.md) — compatibility classes +- [`changelog.md`](changelog.md) — spec version history + +## Goals + +Ralph Loops is designed to make Ralph-style loops: + +- **portable** across tools and runtimes +- **shareable** as reusable packages +- **versionable** in git +- **inspectable** by humans +- **tool-agnostic** where possible +- **easy to author** without complex schemas +- **easy to bundle** with supporting files + +### Secondary goals + +- provide a base for registries and galleries +- support future compatibility across multiple loop runners +- enable community-authored reusable loop packages + +### Non-goals for v1 + +- defining one mandatory runtime engine +- defining network protocol behavior +- defining model-specific execution semantics +- solving sandboxing, security, or permissions universally +- forcing a single metadata schema beyond a small required core + +## Core concept + +A **Ralph Loop** is a directory containing: + +- one required file: `RALPH.md` +- zero or more optional bundled files and subdirectories + +The reusable unit is the **folder**, not a single file. A loop may bundle +scripts, templates, fixtures, reference materials, sample inputs, plans, +checklists, or any other files that help a compatible runtime execute it. + +## Status language + +Ralph Loops is described everywhere as: + +> **An open proposed format for portable Ralph-style agent loops.** + +It is not a standard. It is not presented as official or canonical for all +Ralph methodology. It is a portable package format proposal inspired by +Geoffrey Huntley's Ralph loop methodology. + +## Terminology + +- **Package** — a Ralph Loop directory containing `RALPH.md`. +- **Package root** — the directory containing `RALPH.md`. +- **Entrypoint** — the `RALPH.md` file itself. +- **Bundled resource** — any other file inside the package root. +- **Runtime** — a tool that discovers, parses, and/or executes packages. +- **Compatibility class** — the level of support a runtime declares (see + [`compatibility.md`](compatibility.md)). + +## Normative keywords + +The words MUST, SHOULD, and MAY in the specification documents follow +[RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) semantics. diff --git a/ralphloops/repo/specification/runtime-contract.md b/ralphloops/repo/specification/runtime-contract.md new file mode 100644 index 0000000..eed3990 --- /dev/null +++ b/ralphloops/repo/specification/runtime-contract.md @@ -0,0 +1,95 @@ +# Runtime Contract + +This document describes what a compatible runtime MUST and SHOULD do +when loading and executing Ralph Loops. The format does not mandate a +single universal execution engine; runtimes are free to differ in how +they iterate, reset context, or wire tools. But certain behaviors are +required for a runtime to be considered compatible. + +## Loading a package + +A runtime MUST: + +1. Locate `RALPH.md` within the candidate directory. +2. Read the file as UTF-8. +3. If the file starts with a `---` line, parse the YAML frontmatter + block using a safe YAML loader. +4. Treat everything after the closing `---` as the markdown body. +5. Validate required metadata (`name`, `description`, + `ralphloops_version`) if frontmatter is present. +6. Refuse to load the package if the declared `ralphloops_version` is + strictly greater than the version the runtime supports. + +A runtime SHOULD: + +- Emit warnings (not errors) for unknown metadata keys. +- Emit warnings for missing recommended metadata. +- Preserve unknown metadata so it can be round-tripped. + +## Resolving bundled resources + +A runtime MUST: + +- Resolve all relative paths against the package root. +- Reject any path that escapes the package root via `..`, symlinks, or + any other mechanism. +- Treat missing files referenced from `entry` as fatal errors. +- Treat missing files referenced from `resources` as warnings. + +A runtime SHOULD: + +- Normalize path separators to the host OS when invoking files. +- Make resources available to the agent via whatever context mechanism + the runtime uses (files, tools, embedded strings, etc.). + +## Executing the loop + +A runtime MUST: + +- Make the `RALPH.md` body available to the agent as instructions. +- Make bundled resources reachable from inside the agent's working + context. +- Execute declared `entry` commands via its own command execution + mechanism when asked. + +A runtime SHOULD document, in its own docs: + +- How iteration is performed (reset per loop, accumulate, etc.). +- How context is constructed from the package root and resources. +- How commands declared under `entry` are surfaced to the agent. +- How the runtime decides when the loop terminates. + +## Security and safety + +A runtime MUST: + +- Refuse to execute packages whose metadata contains path traversal. +- Refuse to load resources outside the package root. + +A runtime SHOULD: + +- Treat bundled scripts as untrusted by default and require explicit + user opt-in before executing them on the host system. +- Surface clearly what the loop is about to do before running it. + +## Error reporting + +A runtime SHOULD distinguish: + +- **Fatal errors** — the package cannot be loaded or executed. +- **Warnings** — the package loads but something is suspicious. +- **Informational notes** — recommended but non-required metadata is + absent. + +## What runtimes are free to do + +The format intentionally leaves room for runtime-specific behavior, +including but not limited to: + +- How the agent is iterated or reset between turns +- How bundled resources are surfaced (filesystem, embedded, retrieval) +- How commands are scheduled, timed out, or sandboxed +- How the agent is invoked under the hood +- How logs, traces, and metrics are produced + +These concerns belong in runtime documentation, not in the format. diff --git a/ralphloops/repo/tests/README.md b/ralphloops/repo/tests/README.md new file mode 100644 index 0000000..452894b --- /dev/null +++ b/ralphloops/repo/tests/README.md @@ -0,0 +1,28 @@ +# Conformance Corpus + +This directory holds fixtures that runtimes can use to check their +conformance with the Ralph Loops format. + +``` +tests/ +├── valid/ +│ ├── minimal/ # RALPH.md with no frontmatter +│ └── full/ # RALPH.md with every recommended field +└── invalid/ + ├── missing-ralph-md/ # directory with no RALPH.md + └── bad-frontmatter/ # unparseable YAML frontmatter +``` + +## Valid fixtures + +Every directory under `valid/` is a complete, loadable Ralph Loop +package. A conforming implementation MUST accept it. + +## Invalid fixtures + +Every directory under `invalid/` contains a `REASON.md` explaining why +the fixture is invalid. A conforming implementation MUST reject it and +SHOULD produce an error message that corresponds to the stated reason. + +See [`implementors/test-cases.md`](../implementors/test-cases.md) for +how to use this corpus in a conformance suite. diff --git a/ralphloops/repo/tests/invalid/bad-frontmatter/RALPH.md b/ralphloops/repo/tests/invalid/bad-frontmatter/RALPH.md new file mode 100644 index 0000000..202bce1 --- /dev/null +++ b/ralphloops/repo/tests/invalid/bad-frontmatter/RALPH.md @@ -0,0 +1,11 @@ +--- +name: bad-frontmatter +description: "unterminated string +ralphloops_version: 0.1 +--- + +# Goal + +This fixture has unparseable YAML frontmatter (an unterminated quoted +string on the `description` line). A conforming implementation MUST +reject it. diff --git a/ralphloops/repo/tests/invalid/bad-frontmatter/REASON.md b/ralphloops/repo/tests/invalid/bad-frontmatter/REASON.md new file mode 100644 index 0000000..2eff505 --- /dev/null +++ b/ralphloops/repo/tests/invalid/bad-frontmatter/REASON.md @@ -0,0 +1,10 @@ +# Why this fixture is invalid + +The YAML frontmatter in `RALPH.md` is unparseable: the `description` +field opens a quoted string that is never closed. A conforming +implementation MUST treat this as a fatal parse error. + +Per `specification/format.md` §9 and `implementors/parsing.md`: + +> A valid v0.1 package must contain parseable YAML if frontmatter is +> present. diff --git a/ralphloops/repo/tests/invalid/missing-ralph-md/REASON.md b/ralphloops/repo/tests/invalid/missing-ralph-md/REASON.md new file mode 100644 index 0000000..6ca5423 --- /dev/null +++ b/ralphloops/repo/tests/invalid/missing-ralph-md/REASON.md @@ -0,0 +1,9 @@ +# Why this fixture is invalid + +This directory does **not** contain a `RALPH.md` file at its root. A +conforming implementation MUST reject it as fatal with an error +indicating that `RALPH.md` is missing. + +Per `specification/format.md` §2: + +> Each Ralph Loop package MUST contain a file named `RALPH.md`. diff --git a/ralphloops/repo/tests/valid/full/RALPH.md b/ralphloops/repo/tests/valid/full/RALPH.md new file mode 100644 index 0000000..69e6db5 --- /dev/null +++ b/ralphloops/repo/tests/valid/full/RALPH.md @@ -0,0 +1,32 @@ +--- +name: full-fixture +description: A fixture exercising every recommended frontmatter field. +ralphloops_version: 0.1 +version: 1.2.3 +license: MIT +author: Ralph Loops contributors +homepage: https://ralphloops.io/ +repository: https://github.com/ralphloops/ralphloops +tags: + - fixture + - conformance +compatible_runtimes: + - ralphify >=0.3.0 +triggers: + - conformance test +entry: + validate: scripts/validate.sh +resources: + - docs/notes.md +--- + +# Goal + +Exercise every recommended frontmatter field in a single valid +package. + +# Loop + +1. The runtime parses this file. +2. The runtime validates the metadata. +3. The runtime reports success. diff --git a/ralphloops/repo/tests/valid/full/docs/notes.md b/ralphloops/repo/tests/valid/full/docs/notes.md new file mode 100644 index 0000000..a764dc0 --- /dev/null +++ b/ralphloops/repo/tests/valid/full/docs/notes.md @@ -0,0 +1,4 @@ +# Notes + +Referenced from the `resources` list to verify that resource paths +resolve correctly inside the package root. diff --git a/ralphloops/repo/tests/valid/full/scripts/validate.sh b/ralphloops/repo/tests/valid/full/scripts/validate.sh new file mode 100755 index 0000000..4c9142c --- /dev/null +++ b/ralphloops/repo/tests/valid/full/scripts/validate.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# Conformance fixture: a trivial validate script referenced from entry. +set -euo pipefail +echo "validate: ok" diff --git a/ralphloops/repo/tests/valid/minimal/RALPH.md b/ralphloops/repo/tests/valid/minimal/RALPH.md new file mode 100644 index 0000000..941bdc7 --- /dev/null +++ b/ralphloops/repo/tests/valid/minimal/RALPH.md @@ -0,0 +1,9 @@ +# Goal + +This is the minimum viable Ralph Loop: a directory with a single +`RALPH.md` file and no frontmatter. + +# Loop + +1. Do one useful thing. +2. Stop. diff --git a/ralphloops/website/examples/index.html b/ralphloops/website/examples/index.html new file mode 100644 index 0000000..697de4a --- /dev/null +++ b/ralphloops/website/examples/index.html @@ -0,0 +1,77 @@ + + + + + + Examples — Ralph Loops + + + + + + + + +
+

Gallery

+

Examples

+

+ Six reference Ralph Loops, each shipped as a complete directory package in + the canonical repository. + Clone the repo to inspect the full source of every loop. +

+ +
+
+

fix-failing-tests

+

Find and fix failing tests one failure at a time. Ships with scripts/run-tests.sh, scripts/validate.sh, and repo conventions docs.

+
+
+

bug-hunter

+

Reproduce, localize, and patch reported bugs. Bundles an edge-cases prompt file.

+
+
+

raise-coverage

+

Add focused tests to lift coverage on under-tested modules.

+
+
+

refactor-module

+

Refactor a single module against a set of invariants. Bundles a PR description template.

+
+
+

write-docs

+

Generate and revise documentation for existing code.

+
+
+

dependency-updater

+

Upgrade dependencies one at a time with tests green.

+
+
+ +

Anatomy of an example

+
fix-failing-tests/
+├── RALPH.md             # required entrypoint
+├── README.md            # what this loop is for
+├── scripts/
+│   ├── run-tests.sh
+│   └── validate.sh
+└── docs/
+    └── repo-conventions.md
+ +

Contribute your own by opening a PR against ralphloops/ralphloops.

+
+ + + diff --git a/ralphloops/website/governance/index.html b/ralphloops/website/governance/index.html new file mode 100644 index 0000000..9660d70 --- /dev/null +++ b/ralphloops/website/governance/index.html @@ -0,0 +1,88 @@ + + + + + + Governance — Ralph Loops + + + + + + + + +
+

Governance

+

+ Ralph Loops is an open proposed format. This page + describes how the format is maintained and evolved. +

+ +

Status

+

+ Ralph Loops is currently a draft. The current format version is + 0.1. All 0.x versions are draft and may change. + A stable 1.x line will be cut once the format is proven in + the wild. +

+ +

Stewardship

+

+ The format is stewarded through the public + ralphloops/ralphloops + repository. Day-to-day maintenance is performed by a small group of + named maintainers listed in GOVERNANCE.md. Decisions about + breaking changes are made via a lightweight RFC process in the + rfcs/ directory. +

+ +

Non-ownership of Ralph methodology

+

+ Ralph Loops is a community-oriented format proposal + inspired by + Geoffrey Huntley’s Ralph loop methodology. + This project defines a portable package format for sharing and running + Ralph-style loops across tools. It does not define, own, or gate the + broader Ralph methodology itself. +

+ +

Relationship to Ralphify and other runtimes

+

+ Ralphify is one reference runtime for + Ralph Loops. Any other tool is welcome to implement the format — the + specification is intentionally runtime-agnostic. Runtimes declare the + compatibility class they support (Reader, Executor, or Publisher). +

+ +

Proposal process

+
    +
  1. Open a discussion or issue describing the problem and the proposed change.
  2. +
  3. If the change is non-trivial, write an RFC under rfcs/ using the template.
  4. +
  5. The maintainers comment, request revisions, and eventually accept or reject the RFC.
  6. +
  7. Accepted RFCs ship in a future ralphloops_version release.
  8. +
+ +

Versioning policy

+
    +
  • ralphloops_version is declared per package.
  • +
  • Breaking changes require an RFC and a bump of the format version.
  • +
  • Additive changes (new optional fields) may land in minor versions.
  • +
  • Runtimes MUST refuse to execute packages whose ralphloops_version is strictly newer than the runtime supports.
  • +
+
+ + + diff --git a/ralphloops/website/implementors/overview/index.html b/ralphloops/website/implementors/overview/index.html new file mode 100644 index 0000000..a337827 --- /dev/null +++ b/ralphloops/website/implementors/overview/index.html @@ -0,0 +1,94 @@ + + + + + + Implementor Overview — Ralph Loops + + + + + + + + +
+

For implementors

+

Implementor Overview

+

+ How a compatible runtime discovers, parses, and executes Ralph Loops. + This page is a narrative overview — the normative rules live in the + specification and the + implementor reference. +

+ +

Discovery

+

A runtime SHOULD look for RALPH.md files in:

+
    +
  • directories passed directly on the command line
  • +
  • a configurable local loops directory
  • +
  • project-local loop packages checked into git
  • +
  • installed shared loop packages (global)
  • +
  • registry-downloaded packages, when a registry exists
  • +
+ +

Parsing

+
    +
  1. Read RALPH.md as UTF-8.
  2. +
  3. If the file starts with a --- line, parse the YAML frontmatter block.
  4. +
  5. Treat the remainder as the agent-facing markdown body.
  6. +
  7. Validate required metadata (name, description, ralphloops_version) if frontmatter is present.
  8. +
+ +

Resource resolution

+

All relative paths resolve against the package root (the directory containing RALPH.md). Runtimes MUST reject any path that escapes the package root — this includes .. traversal and symlink escape.

+ +

Execution

+

The format does not mandate a specific execution engine. A runtime is responsible for:

+
    +
  • making the loop body and bundled resources available to the agent
  • +
  • wiring declared entry commands to the runtime’s command execution mechanism
  • +
  • deciding how iteration, context reset, and validation are performed
  • +
+

A runtime SHOULD document its execution contract so loop authors can rely on consistent behavior.

+ +

Compatibility classes

+

Runtimes self-declare their compatibility level:

+
    +
  • Reader — can discover and parse loop packages
  • +
  • Executor — can execute loop instructions and load bundled files
  • +
  • Publisher — can validate and publish loops for reuse
  • +
+ +

Errors vs warnings

+ + + + + + + + + + + +
ConditionSeverity
Missing RALPH.mdFatal
Invalid UTF-8 in RALPH.mdFatal
Unparseable YAML frontmatterFatal
Missing declared entry fileFatal
Path traversal outside package rootFatal
Missing recommended metadataWarning
Unknown metadata fieldsWarning
+ +
+

Next: implementor reference.

+
+ + + diff --git a/ralphloops/website/implementors/reference/index.html b/ralphloops/website/implementors/reference/index.html new file mode 100644 index 0000000..9a2ebf6 --- /dev/null +++ b/ralphloops/website/implementors/reference/index.html @@ -0,0 +1,84 @@ + + + + + + Implementor Reference — Ralph Loops + + + + + + + + +
+

For implementors

+

Implementor Reference

+

Normative rules. If the specification and this page disagree, the specification wins.

+ +

Metadata parsing

+
    +
  • Frontmatter is a YAML 1.2 document delimited by --- lines.
  • +
  • Parsers MUST use safe YAML loading. They MUST NOT instantiate arbitrary Python/Ruby/JavaScript objects.
  • +
  • Unknown keys are preserved and emitted as warnings, not errors.
  • +
  • String fields are treated as UTF-8 text.
  • +
+ +

Path handling

+
    +
  • Normalize each path with the host platform’s canonicalization.
  • +
  • Reject paths containing .. that escape the package root.
  • +
  • Reject symlinks whose targets lie outside the package root.
  • +
  • Treat forward slashes as path separators in metadata, regardless of host OS.
  • +
+ +

Compatibility declaration

+

+ The compatible_runtimes field is a list of strings of the form + <runtime-name> <version-range>, for example: +

+
compatible_runtimes:
+  - ralphify >=0.3.0
+  - some-other-runtime ~=1.2
+

Runtimes SHOULD evaluate these strings and warn when a loop declares support for a different runtime or an incompatible version range. This is a hint, not a hard enforcement rule.

+ +

Entry map

+

The entry map contains named references to files inside the package. Suggested keys include validate, test, lint, plan, and bootstrap. Keys outside this list are allowed. Values are relative paths.

+ +

Validation behavior

+

Implementations providing a validate command SHOULD report:

+
    +
  • missing RALPH.md — fatal
  • +
  • unparseable frontmatter — fatal
  • +
  • missing required metadata — fatal
  • +
  • missing declared entry files — fatal
  • +
  • path traversal — fatal
  • +
  • missing recommended metadata — warning
  • +
  • unknown keys — warning
  • +
+ +

Versioning

+

The spec version declared by a package is its ralphloops_version. Runtimes MUST refuse to execute packages whose ralphloops_version is strictly greater than the runtime’s supported version.

+ +

Test cases

+

The canonical repository ships a conformance corpus under tests/valid/ and tests/invalid/. Implementations are encouraged to run against it.

+ +
+

Canonical source: ralphloops/ralphloops/implementors.

+
+ + + diff --git a/ralphloops/website/index.html b/ralphloops/website/index.html new file mode 100644 index 0000000..2782984 --- /dev/null +++ b/ralphloops/website/index.html @@ -0,0 +1,291 @@ + + + + + + Ralph Loops — An open proposed format for portable Ralph-style agent loops + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+

An open proposed format

+

Ralph Loops

+

+ An open proposed format for portable Ralph-style agent loops. +

+

+ Package an autonomous loop as a directory with RALPH.md + and any supporting files. Write once, version it in git, and run it + across compatible tools. +

+ + +
my-loop/
+├── RALPH.md
+├── scripts/
+│   └── validate.sh
+└── context/
+    └── coding-guidelines.md
+
+
+ +
+
+

What is a Ralph Loop?

+
+
+

+ A Ralph Loop is a self-contained directory package + that describes an autonomous agent loop. Every package has one + required entrypoint file — RALPH.md — and may bundle + any supporting scripts, prompts, templates, fixtures, or reference + docs beside it. +

+

+ Compatible runtimes discover RALPH.md, parse its + metadata, read its instructions, and make the bundled resources + available to the agent as it loops. +

+

+ The format is deliberately small. It does not mandate a runtime, + an execution engine, or a single metadata schema beyond a tiny + required core. +

+
+
+
---
+name: fix-failing-tests
+description: Fix failing tests one failure at a time.
+ralphloops_version: 0.1
+entry:
+  validate: scripts/validate.sh
+  test: scripts/run-tests.sh
+---
+
+# Goal
+Fix failing tests one failure at a time.
+
+# Loop
+1. Run the validation commands.
+2. Identify the highest-signal failure.
+3. Make the smallest useful change.
+4. Re-run validation.
+5. Commit only if checks pass.
+
+
+
+
+ +
+
+

Why Ralph Loops?

+
+

Portable across tools

A directory plus one file. Any compatible runtime can load it.

+

Bundled context

Scripts, prompts, fixtures, and reference docs travel with the loop.

+

Git-native

Version, diff, and review loops like any other code artifact.

+

Reusable

Share loops across projects, teams, and tools without rewriting them.

+

Inspectable

Plain markdown and plain files. Humans can read every byte.

+

Better than chat

Stop pasting giant prompts into chat windows that forget them.

+
+
+
+ +
+
+

How it works

+
    +
  1. + 1 +
    +

    Author a loop directory

    +

    Create a folder with a RALPH.md file and any supporting scripts or docs the loop needs.

    +
    +
  2. +
  3. + 2 +
    +

    Runtime discovers RALPH.md

    +

    A compatible runtime locates the package, parses its metadata, and reads the loop instructions.

    +
    +
  4. +
  5. + 3 +
    +

    Runtime executes the loop

    +

    The agent loops over the instructions with bundled resources resolved relative to the package root.

    +
    +
  6. +
+
+
+ +
+
+
+
+

For creators

+

Authoring a Ralph Loop means deciding what the agent should do, then packaging everything it needs beside the instructions.

+
    +
  • Instructions in RALPH.md
  • +
  • Validation and test commands
  • +
  • Templates and checklists
  • +
  • Reference docs and examples
  • +
  • Scripts the agent can invoke
  • +
  • Fixtures and sample inputs
  • +
+

Quickstart →

+
+
+

For implementors

+

A compatible runtime loads a Ralph Loop and makes it executable by an agent.

+
    +
  • Locate RALPH.md
  • +
  • Parse optional YAML frontmatter
  • +
  • Read the markdown body as instructions
  • +
  • Resolve bundled files relative to the package root
  • +
  • Reject path traversal outside the root
  • +
  • Expose an execution contract to the agent
  • +
+

Implementor guide →

+
+
+
+
+ +
+
+

Examples

+

Six reference loop packages shipped with the specification repo.

+
+

fix-failing-tests

Find and fix failing tests one failure at a time.

+

bug-hunter

Reproduce, localize, and patch reported bugs.

+

raise-coverage

Add focused tests to lift coverage on under-tested modules.

+

refactor-module

Refactor a single module against a set of invariants.

+

write-docs

Generate and revise documentation for existing code.

+

dependency-updater

Upgrade dependencies one at a time with tests green.

+
+

All examples →

+
+
+ +
+
+

Governance

+

+ Ralph Loops is an open proposed format. It evolves + through public discussion in the + ralphloops/ralphloops + repository, with versioned specifications and a lightweight RFC + process for breaking changes. +

+

+ Ralph Loops is inspired by + Geoffrey Huntley’s Ralph loop methodology. + This project proposes a portable package format for sharing and + running Ralph-style loops across tools — it does not claim ownership + of the broader Ralph methodology itself. +

+

+ Read the governance model → +

+
+
+ +
+ + + + + diff --git a/ralphloops/website/loop-creation/best-practices/index.html b/ralphloops/website/loop-creation/best-practices/index.html new file mode 100644 index 0000000..1c6b179 --- /dev/null +++ b/ralphloops/website/loop-creation/best-practices/index.html @@ -0,0 +1,64 @@ + + + + + + Best Practices — Ralph Loops + + + + + + + + +
+

For creators

+

Best Practices

+

Guidelines for writing clear, portable, reusable Ralph Loops.

+ +

One job per loop

+

Each package should describe a single outcome. Small loops are easier to reuse, review, and debug than large monolithic ones. If a loop feels like it is doing two things, split it.

+ +

Keep RALPH.md operational

+

The body is agent-facing instructions. Write concrete steps, validation commands, and exit conditions — not background essays. Move large references into bundled files and link to them.

+ +

Bundle reusable scripts

+

If the loop needs to run tests, lint, or validate something, put the commands in a script under scripts/ and reference it from the entry map. This makes the loop portable across projects that wire their commands slightly differently.

+ +

Prefer relative paths

+

All paths in metadata resolve relative to the package root. Avoid absolute paths, and never reference paths outside the loop directory.

+ +

Include validation and exit conditions

+

An autonomous loop needs to know when to stop. Explicit exit conditions and validation commands prevent runaway loops and make behavior reproducible.

+ +

Name packages by outcome

+

Use names like fix-failing-tests, raise-coverage, or refactor-module. Avoid tool-specific names like my-ralphify-loop.

+ +

Declare runtime compatibility

+

Use compatible_runtimes to tell users which runtimes and versions you have tested the loop against. This is a hint, not a hard constraint.

+ +

Ship a realistic example

+

Include a small fixture or sample input under examples/ inside the package so users (and runtimes) can smoke-test the loop without a real project.

+ +

Avoid giant monolithic manifests

+

The frontmatter is intentionally small. Resist the urge to encode every behavior as metadata. If something belongs in code or prose, put it in a script or a markdown file.

+ +
+

See also: specification, examples.

+
+ + + diff --git a/ralphloops/website/loop-creation/quickstart/index.html b/ralphloops/website/loop-creation/quickstart/index.html new file mode 100644 index 0000000..7e2a2fb --- /dev/null +++ b/ralphloops/website/loop-creation/quickstart/index.html @@ -0,0 +1,88 @@ + + + + + + Quickstart — Ralph Loops + + + + + + + + +
+

For creators

+

Quickstart

+

+ Create your first Ralph Loop package in a few minutes. You will end up + with a directory that any compatible runtime can discover and execute. +

+ +

1. Create a loop directory

+
mkdir fix-failing-tests
+cd fix-failing-tests
+

The directory name is the loop’s package name. Choose an outcome-oriented name.

+ +

2. Add a RALPH.md file

+

Create RALPH.md with frontmatter and a loop body:

+
---
+name: fix-failing-tests
+description: Find and fix failing tests one failure at a time.
+ralphloops_version: 0.1
+version: 0.1.0
+entry:
+  validate: scripts/validate.sh
+  test: scripts/run-tests.sh
+---
+
+# Goal
+Fix failing tests one failure at a time.
+
+# Loop
+1. Run the validation commands.
+2. Identify the highest-signal failure.
+3. Make the smallest useful change.
+4. Re-run validation.
+5. Commit only if checks pass.
+
+# Exit conditions
+- All tests pass.
+- No remaining failures reported by `scripts/run-tests.sh`.
+ +

3. Add supporting files

+

Bundle any scripts, docs, or fixtures the loop needs beside RALPH.md:

+
fix-failing-tests/
+├── RALPH.md
+├── scripts/
+│   ├── run-tests.sh
+│   └── validate.sh
+└── docs/
+    └── repo-conventions.md
+ +

4. Run it with a compatible runtime

+

Any runtime that supports the Ralph Loops format can discover and execute the package. For example, with Ralphify:

+
ralph run fix-failing-tests/
+ +

5. Share it

+

Because a Ralph Loop is just a directory, you can share it by committing it to a git repository, zipping it up, or publishing it to a registry when one exists.

+ +
+

Next: read the best practices guide or browse example loops.

+
+ + + diff --git a/ralphloops/website/specification/index.html b/ralphloops/website/specification/index.html new file mode 100644 index 0000000..44fd139 --- /dev/null +++ b/ralphloops/website/specification/index.html @@ -0,0 +1,224 @@ + + + + + + Specification — Ralph Loops + + + + + + + + +
+

v0.1 draft

+

Ralph Loops Specification

+ +

+ This document defines the Ralph Loops format: a directory-based, portable + package format for Ralph-style autonomous agent loops. It is an + open proposed format, not a standard. Breaking changes go + through an RFC process in the + canonical repository. +

+ +

1. Definition

+

A Ralph Loop is a directory-based package with:

+
    +
  • one required file: RALPH.md
  • +
  • zero or more optional bundled files and subdirectories
  • +
+

+ A loop package may contain scripts, templates, fixtures, reference + materials, sample inputs, plans, checklists, or any other files that help + a compatible runtime execute the loop. +

+ +

2. Required entrypoint

+

Each Ralph Loop package MUST contain a file named:

+
RALPH.md
+

This file is the canonical entrypoint for the package.

+ +

3. Package root

+

+ The package root is the directory containing RALPH.md. All + relative paths in the format are resolved relative to the package root + unless otherwise specified. +

+ +

4. Allowed structure

+

There are no required subdirectories beyond RALPH.md. Example:

+
fix-failing-tests/
+├── RALPH.md
+├── scripts/
+│   ├── run-tests.sh
+│   └── validate.sh
+├── prompts/
+│   └── edge-cases.md
+├── templates/
+│   └── issue-comment.md
+└── docs/
+    └── repo-conventions.md
+ +

5. RALPH.md file structure

+

RALPH.md consists of:

+
    +
  1. optional YAML frontmatter
  2. +
  3. markdown body content
  4. +
+
---
+name: fix-failing-tests
+description: Find and fix failing tests one failure at a time.
+version: 0.1
+ralphloops_version: 0.1
+license: MIT
+compatible_runtimes:
+  - ralphify >=0.3.0
+triggers:
+  - failing tests
+  - test suite is red
+entry:
+  validate: scripts/validate.sh
+  test: scripts/run-tests.sh
+resources:
+  - docs/repo-conventions.md
+---
+
+# Goal
+Fix failing tests one failure at a time.
+
+# Loop
+1. Run the validation commands.
+2. Identify the next highest-signal failure.
+3. Make the smallest useful change.
+4. Re-run validation.
+5. Commit only if checks pass.
+ +

6. Metadata fields

+ +

Required (if frontmatter is present)

+
    +
  • name
  • +
  • description
  • +
  • ralphloops_version
  • +
+

+ If frontmatter is omitted entirely, runtimes MAY still load the loop, + but the package is considered minimally described. Frontmatter is + strongly recommended for ecosystem compatibility. +

+ +

Recommended

+ + + + + + + + + + + + + + +
FieldMeaning
versionPackage version.
licenseSPDX license identifier.
authorAuthor name or handle.
homepageProject homepage URL.
repositorySource repository URL.
tagsFree-form tags for discovery.
compatible_runtimesRuntimes/version ranges known to support the package.
triggersHuman-readable phrases describing when to select this loop.
entryMap of named entrypoints (typically relative paths). Suggested keys: validate, test, lint, plan, bootstrap.
resourcesList of supporting files that are particularly important for the loop.
+ +

7. Markdown body semantics

+

+ The format deliberately avoids over-structuring the markdown body. + Compatible runtimes MUST treat the body as agent-facing instructions, + not as a strict AST. +

+

Recommended sections: Goal, Context, Loop, Constraints, Validation, Exit Conditions, Recovery / Failure Handling, Notes for the Agent.

+ +

8. Optional bundled files

+

+ A package may include scripts, prompts, templates, examples, fixtures, + plans, checklists, JSON/YAML config, reference docs, or generated + examples. Compatible runtimes MUST allow the agent to reference these + files relative to the loop package root. +

+ +

9. Path resolution rules

+

All paths in metadata are relative to the package root unless they are absolute URIs. Runtimes MUST:

+
    +
  • normalize relative paths safely
  • +
  • reject path traversal that escapes the package root
  • +
  • treat missing referenced files as package errors or warnings
  • +
+ +

10. Discovery model

+

A compatible runtime SHOULD be able to discover Ralph Loops by scanning directories for RALPH.md. Discovery options may include local loop directories, project-local loop packages, installed shared loop packages, and registry-downloaded packages.

+ +

11. Execution contract

+

The format does not mandate one universal runtime execution engine. However, a compatible runtime SHOULD, at minimum:

+
    +
  1. locate RALPH.md
  2. +
  3. parse metadata if present
  4. +
  5. load the markdown body
  6. +
  7. make bundled resources available
  8. +
  9. resolve referenced relative files safely
  10. +
  11. expose runtime-specific execution behavior consistently
  12. +
+ +

12. Compatibility classes

+ + + + + + + +
LevelNameCapability
1ReaderCan discover and parse a Ralph Loop package.
2ExecutorCan execute loop instructions and load bundled files.
3PublisherCan package, validate, and publish Ralph Loops for reuse.
+ +

13. Validation rules

+

A valid v0.1 package MUST:

+
    +
  • contain RALPH.md
  • +
  • use valid UTF-8 text for RALPH.md
  • +
  • contain parseable YAML if frontmatter is present
  • +
  • not reference missing required entry files if declared in metadata
  • +
  • not contain path traversal references in metadata
  • +
+ +

14. Packaging and distribution

+

+ A Ralph Loop package may be distributed as a git repository subdirectory, + a standalone repository, a tarball or zip archive, or a registry package. + The directory itself is the unit of portability. +

+ +

15. Versioning

+

ralphloops_version controls spec compatibility.

+
    +
  • 0.x — draft / experimental
  • +
  • 1.x — stable compatibility line
  • +
+

Breaking changes require an RFC and explicit compatibility notes.

+ +
+

+ The canonical specification lives in + ralphloops/ralphloops/specification. + This page tracks the current published draft. +

+
+ + + diff --git a/ralphloops/website/styles.css b/ralphloops/website/styles.css new file mode 100644 index 0000000..e2adc45 --- /dev/null +++ b/ralphloops/website/styles.css @@ -0,0 +1,269 @@ +/* Ralph Loops — minimal technical site */ + +:root { + --bg: #0b1020; + --bg-alt: #0f172a; + --surface: #111a33; + --border: #1f2a48; + --text: #e6ecff; + --muted: #9aa7c7; + --accent: #7c9cff; + --accent-2: #5eead4; + --code-bg: #0a1128; + --max: 1080px; +} + +* { box-sizing: border-box; } + +html, body { + margin: 0; + padding: 0; + background: var(--bg); + color: var(--text); + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, Helvetica, Arial, sans-serif; + font-size: 16px; + line-height: 1.6; + -webkit-font-smoothing: antialiased; +} + +a { color: var(--accent); text-decoration: none; } +a:hover { text-decoration: underline; } + +.container { max-width: var(--max); margin: 0 auto; padding: 0 24px; } + +code, pre { + font-family: "JetBrains Mono", "SF Mono", Menlo, Consolas, monospace; + font-size: 14px; +} + +code { + background: var(--code-bg); + padding: 2px 6px; + border-radius: 4px; + color: #c7d2ff; +} + +pre { + background: var(--code-bg); + border: 1px solid var(--border); + border-radius: 8px; + padding: 16px 20px; + overflow-x: auto; + color: #dbe4ff; +} + +pre code { background: none; padding: 0; color: inherit; } + +h1, h2, h3, h4 { line-height: 1.25; font-weight: 650; } +h1 { font-size: 44px; margin: 0 0 16px; letter-spacing: -0.02em; } +h2 { font-size: 28px; margin: 0 0 24px; letter-spacing: -0.01em; } +h3 { font-size: 18px; margin: 0 0 8px; } +h4 { font-size: 14px; margin: 0 0 12px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); } + +p { margin: 0 0 16px; } +.muted { color: var(--muted); } +.small { font-size: 13px; } + +/* Header */ +.site-header { + position: sticky; + top: 0; + background: rgba(11, 16, 32, 0.88); + backdrop-filter: blur(10px); + border-bottom: 1px solid var(--border); + z-index: 50; +} + +.nav { + display: flex; + align-items: center; + justify-content: space-between; + padding: 14px 24px; +} + +.brand { + display: inline-flex; + align-items: center; + gap: 8px; + color: var(--text); + font-weight: 700; +} +.brand:hover { text-decoration: none; } +.brand-mark { font-size: 20px; } +.brand-name { font-size: 16px; } +.brand-tag { + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--muted); + border: 1px solid var(--border); + padding: 2px 6px; + border-radius: 999px; + margin-left: 4px; +} + +.nav-links { + display: flex; + align-items: center; + gap: 22px; +} +.nav-links a { + color: var(--muted); + font-size: 14px; +} +.nav-links a:hover { color: var(--text); text-decoration: none; } +.nav-github { + border: 1px solid var(--border); + padding: 6px 12px; + border-radius: 6px; + color: var(--text) !important; +} + +/* Hero */ +.hero { padding: 96px 0 64px; } +.eyebrow { + text-transform: uppercase; + font-size: 12px; + letter-spacing: 0.12em; + color: var(--accent-2); + margin: 0 0 12px; +} +.lede { + font-size: 22px; + color: var(--text); + margin: 0 0 8px; + max-width: 720px; +} +.sub { + font-size: 17px; + color: var(--muted); + max-width: 720px; + margin: 0 0 28px; +} + +.cta-row { + display: flex; + flex-wrap: wrap; + gap: 10px; + margin-bottom: 40px; +} + +.btn { + display: inline-block; + padding: 10px 16px; + border-radius: 8px; + border: 1px solid var(--border); + background: var(--surface); + color: var(--text); + font-size: 14px; + font-weight: 500; +} +.btn:hover { text-decoration: none; border-color: var(--accent); } +.btn-primary { + background: var(--accent); + border-color: var(--accent); + color: #0b1020; + font-weight: 600; +} +.btn-primary:hover { background: #94b0ff; border-color: #94b0ff; } +.btn-ghost { background: transparent; } + +.hero-code { + max-width: 520px; + margin: 0; +} + +/* Sections */ +.section { padding: 72px 0; } +.section-alt { background: var(--bg-alt); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); } + +.grid-2 { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 40px; + align-items: start; +} +@media (max-width: 760px) { + .grid-2 { grid-template-columns: 1fr; gap: 24px; } + h1 { font-size: 34px; } + .hero { padding: 64px 0 40px; } + .section { padding: 48px 0; } + .nav-links { gap: 14px; } + .nav-links a { font-size: 13px; } +} + +.cards { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); + gap: 16px; + margin: 24px 0; +} +.card { + background: var(--surface); + border: 1px solid var(--border); + border-radius: 10px; + padding: 20px; +} +.card h3 { margin-bottom: 6px; color: var(--text); } +.card p { margin: 0; color: var(--muted); font-size: 14px; } + +.steps { + list-style: none; + margin: 0; + padding: 0; + display: grid; + gap: 20px; + max-width: 760px; +} +.steps li { + display: flex; + gap: 18px; + align-items: flex-start; +} +.step-num { + flex: 0 0 36px; + height: 36px; + border-radius: 50%; + background: var(--accent); + color: #0b1020; + font-weight: 700; + display: grid; + place-items: center; +} + +ul { padding-left: 20px; } +li { margin-bottom: 6px; } + +/* Footer */ +.site-footer { + border-top: 1px solid var(--border); + padding: 48px 0 24px; + background: var(--bg-alt); +} +.footer-grid { + display: grid; + grid-template-columns: 1.4fr repeat(4, 1fr); + gap: 32px; +} +@media (max-width: 760px) { + .footer-grid { grid-template-columns: 1fr 1fr; } +} +.footer-grid ul { list-style: none; padding: 0; margin: 0; } +.footer-grid li { margin-bottom: 6px; } +.footer-grid a { color: var(--muted); font-size: 14px; } +.footer-grid a:hover { color: var(--text); } +.footer-bottom { margin-top: 32px; padding-top: 16px; border-top: 1px solid var(--border); } + +/* Doc subpages */ +.doc { + max-width: 760px; + margin: 0 auto; + padding: 80px 24px 120px; +} +.doc h1 { font-size: 36px; margin-bottom: 24px; } +.doc h2 { font-size: 24px; margin-top: 48px; } +.doc h3 { font-size: 18px; margin-top: 32px; } +.doc hr { border: 0; border-top: 1px solid var(--border); margin: 32px 0; } +.doc table { width: 100%; border-collapse: collapse; margin: 16px 0; } +.doc th, .doc td { text-align: left; padding: 8px 12px; border-bottom: 1px solid var(--border); font-size: 14px; } +.doc th { color: var(--muted); font-weight: 600; }