@beremaran/ralphie 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/CHANGELOG.md +832 -0
  2. package/LICENSE +21 -0
  3. package/README.md +53 -2
  4. package/dist/ralphie.js +33691 -0
  5. package/docs/README.md +71 -0
  6. package/docs/architecture.md +159 -0
  7. package/docs/cli-reference.md +126 -0
  8. package/docs/configuration.md +269 -0
  9. package/docs/development.md +248 -0
  10. package/docs/getting-started.md +134 -0
  11. package/docs/operations-and-recovery.md +328 -0
  12. package/docs/safety.md +189 -0
  13. package/docs/workflows.md +411 -0
  14. package/package.json +83 -3
  15. package/vendor/mattpocock-skills/LICENSE +21 -0
  16. package/vendor/mattpocock-skills/code-review/SKILL.md +87 -0
  17. package/vendor/mattpocock-skills/code-review/agents/openai.yaml +3 -0
  18. package/vendor/mattpocock-skills/codebase-design/DEEPENING.md +37 -0
  19. package/vendor/mattpocock-skills/codebase-design/DESIGN-IT-TWICE.md +44 -0
  20. package/vendor/mattpocock-skills/codebase-design/SKILL.md +114 -0
  21. package/vendor/mattpocock-skills/codebase-design/agents/openai.yaml +3 -0
  22. package/vendor/mattpocock-skills/diagnosing-bugs/SKILL.md +138 -0
  23. package/vendor/mattpocock-skills/diagnosing-bugs/agents/openai.yaml +3 -0
  24. package/vendor/mattpocock-skills/diagnosing-bugs/scripts/hitl-loop.template.sh +44 -0
  25. package/vendor/mattpocock-skills/implement/SKILL.md +15 -0
  26. package/vendor/mattpocock-skills/implement/agents/openai.yaml +5 -0
  27. package/vendor/mattpocock-skills/lock.json +37 -0
  28. package/vendor/mattpocock-skills/tdd/SKILL.md +38 -0
  29. package/vendor/mattpocock-skills/tdd/agents/openai.yaml +3 -0
  30. package/vendor/mattpocock-skills/tdd/mocking.md +59 -0
  31. package/vendor/mattpocock-skills/tdd/tests.md +77 -0
  32. package/vendor/mattpocock-skills/to-tickets/SKILL.md +105 -0
  33. package/vendor/mattpocock-skills/to-tickets/agents/openai.yaml +5 -0
  34. package/vendor/mattpocock-skills/triage/AGENT-BRIEF.md +207 -0
  35. package/vendor/mattpocock-skills/triage/OUT-OF-SCOPE.md +105 -0
  36. package/vendor/mattpocock-skills/triage/SKILL.md +112 -0
  37. package/vendor/mattpocock-skills/triage/agents/openai.yaml +5 -0
package/docs/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # Ralphie documentation
2
+
3
+ This directory is the detailed documentation set for Ralphie. The [root
4
+ README](../README.md) is the concise product overview and first-run guide;
5
+ these pages are the authoritative home for contracts that should not be
6
+ buried in a landing page.
7
+
8
+ ## Suggested reading paths
9
+
10
+ ### New user
11
+
12
+ 1. [Getting started](getting-started.md): prerequisites, installation,
13
+ authentication, verification, and a safe first run.
14
+ 2. [Safety](safety.md): understand what a mutation-enabled run can change.
15
+ 3. [Workflows](workflows.md): see how issues are routed and delivered.
16
+ 4. [Configuration](configuration.md): write the config file.
17
+ 5. [CLI reference](cli-reference.md): choose options and adapt the recipes.
18
+
19
+ ### Operator
20
+
21
+ 1. [Safety](safety.md): review direct-push defaults, invariants, and workspace
22
+ risks before operating on a real repository.
23
+ 2. [Configuration](configuration.md) and [CLI reference](cli-reference.md) -
24
+ settings, invocation, output, and environment variables.
25
+ 3. [Operations and recovery](operations-and-recovery.md): interpret output,
26
+ inspect artifacts, and understand what remains after interruption.
27
+ 4. [Workflows](workflows.md): understand implementation, decomposition, and
28
+ direct-push delivery.
29
+
30
+ ### Contributor
31
+
32
+ 1. [Development](development.md): local setup, checks, tests, and contribution
33
+ expectations.
34
+ 2. [Architecture](architecture.md): runtime assembly and domain boundaries.
35
+ 3. [Workflows](workflows.md): behavior and mutation boundaries to preserve.
36
+ 4. [Operations and recovery](operations-and-recovery.md): state and recovery
37
+ contracts that changes must not break.
38
+
39
+ ### Release maintainer
40
+
41
+ 1. [Getting started](getting-started.md): the installation contract
42
+ (`bunx @beremaran/ralphie`) and first run.
43
+ 2. [Development](development.md): build, package smoke, and the tag-triggered
44
+ npm publish flow.
45
+ 3. [Operations and recovery](operations-and-recovery.md): operational state and
46
+ cleanup behavior.
47
+
48
+ ## Page map
49
+
50
+ | Page | Purpose |
51
+ | --- | --- |
52
+ | [Getting started](getting-started.md) | Install Ralphie, configure credentials, verify it, and run the first run. |
53
+ | [Workflows](workflows.md) | Explain issue routing, implementation, decomposition, and direct-push delivery. |
54
+ | [Safety](safety.md) | Define deterministic Git/GitHub safety checks and destructive workspace behavior. |
55
+ | [Configuration](configuration.md) | Define the YAML config file, every key and default, repository overrides, and `--set`. |
56
+ | [CLI reference](cli-reference.md) | Record the command syntax, remaining options, environment variables, and recipes. |
57
+ | [Operations and recovery](operations-and-recovery.md) | Document progress, artifacts, state, cancellation, failure, and cleanup. |
58
+ | [Architecture](architecture.md) | Map runtime, orchestrator, domain services, and source locations. |
59
+ | [Development](development.md) | Explain local development, test commands, optional registry checks, the vendored skills sync, and contribution rules. |
60
+
61
+ ## Keeping documentation current
62
+
63
+ Keep each contract authoritative on one page. Put new settings in
64
+ [Configuration](configuration.md), new CLI options in the [CLI
65
+ reference](cli-reference.md), workflow behavior in [Workflows](workflows.md),
66
+ recovery behavior in [Operations and recovery](operations-and-recovery.md),
67
+ component changes in [Architecture](architecture.md), and release changes in
68
+ [Development](development.md)'s publishing section. Summaries elsewhere should
69
+ link here rather than copy sections that can drift. Keep safety warnings
70
+ visible before mutation-enabled commands and use relative links so pages work
71
+ on GitHub and in a checkout.
@@ -0,0 +1,159 @@
1
+ # Architecture
2
+
3
+ This page is for contributors and maintainers who need the runtime and domain
4
+ boundaries, component map, or source locations. It is the authoritative
5
+ architecture overview. Return to the [documentation index](README.md).
6
+
7
+ ## Runtime boundaries
8
+
9
+ Ralphie uses Bun's built-in argument parser and native promises. Services are
10
+ assembled as an explicit dependency object, which keeps the runtime small and
11
+ makes tests straightforward without a framework-specific execution model.
12
+
13
+ ```mermaid
14
+ flowchart LR
15
+ U[Operator] --> CLI["Inbound adapter<br/>command.ts / cli.ts / options.ts"]
16
+ CLI --> CTX["Bounded contexts<br/>agent · config · git · github · harness · issues<br/>process · progress · run · workflow · workspace"]
17
+ CTX --> PORTS["<context>/ports.ts + /domain"]
18
+ PORTS -. implemented by .-> AD["<context>/adapters/"]
19
+ AD --> GH[GitHub API]
20
+ AD --> REPO[Workspace checkout]
21
+ AD --> LLM[Harness CLIs]
22
+ AD --> DISK[State, artifacts, diagnostics]
23
+ AD --> TERM[Terminal or JSON Lines]
24
+ ```
25
+
26
+ Each bounded context owns its contract, domain model, and adapters together:
27
+ `<context>/ports.ts` (and `issues/domain/`) declares the core-owned types,
28
+ `<context>/adapters/` implements them, and application logic lives beside them
29
+ (`issues/app/`, `agent/`, `workflow/`). `src/runtime.ts` is the composition root
30
+ that binds concrete adapters into the runtime bundle.
31
+
32
+ | Context | Location | Responsibility |
33
+ | --- | --- | --- |
34
+ | `agent` | `src/agent/` | Prompts, structured-output and text-task helpers, and the role-to-session mapping (access mode, timeouts) over the harness port. Kept apart from `harness` on purpose: `agent` holds Ralphie's own prompts and role policy, while `harness` stays provider-neutral session plumbing that knows nothing about issues. |
35
+ | `config` | `src/config/` | YAML configuration: the zod schema (`settings.ts`), layering and `--set` overrides (`load.ts`, `overrides.ts`), and the file-reader port with its Bun YAML adapter. |
36
+ | `harness` | `src/harness/` | Provider-neutral harness port (session request, events, typed failures, structured results), the service that runs sessions and repairs invalid results, and one CLI adapter per harness (Claude Code, Codex, pi and OpenCode). Every workflow session runs through it, wrapped by session isolation, the read-only fingerprint guard and skill injection; `app/roles.ts` resolves the configured role assignments. The vendored skills live in `vendor/mattpocock-skills/` (see [Development](development.md#vendored-skills)). |
37
+ | `github` | `src/github/` | Issue value objects, repository slug parsing, and the Octokit/`gh` adapters. |
38
+ | `git` | `src/git/` | Checkout preparation, checkpoints, issue operations, invariants, and remote-safety adapters. |
39
+ | `issues` | `src/issues/` | Domain (`domain/`), executors and artifact/recovery logic (`app/`), filesystem adapters (`adapters/`). |
40
+ | `progress` | `src/progress/` | `ports.ts` contract plus the OpenTUI interactive adapter and the plain/JSON adapters. It renders only harness-neutral session events and imports nothing from `agent` or a harness adapter. |
41
+ | `run` | `src/run/` | Versioned run-state schemas, the state/event-log ports, and their adapters. |
42
+ | `process` | `src/process/` | Bounded command runner port (timeout, abort, stdin, streamed stdout lines), the helper, and its adapter. |
43
+ | `workspace` | `src/workspace/` | Path expansion, the workspace port, and the protected-removal adapter. |
44
+ | `workflow` | `src/workflow/` | Issue-workflow orchestration, the runtime bundle port, and exit-code policy. |
45
+ | Inbound adapter | `src/command.ts`, `src/cli.ts`, `src/options.ts` | CLI parsing, terminal detection, and the top-level error boundary. |
46
+ | Composition root | `src/runtime.ts` | Builds concrete adapters and exposes them as the workflow runtime bundle. |
47
+ | Shared kernel | `src/shared/` | Errors and terminal-control sanitization used by every context. |
48
+
49
+ Dependency direction is one-way. Contexts import each other's `ports.ts`,
50
+ domain modules and pure `app/` helpers (no I/O, no process or vendor imports),
51
+ never another context's `adapters/`; only the composition root
52
+ (`runtime.ts`, `command.ts`) instantiates adapters. Non-adapter code imports no
53
+ `node:fs`, `node:child_process`, vendor SDK, or process stream. The `issues`
54
+ context defines its file-system ports (`IssueArtifactFileSystem`,
55
+ `RecoveryFileSystem`) in `issues/app/` and its node implementations live in
56
+ `issues/adapters/`, so the atomic-write and diagnostic logic never touches
57
+ `node:fs`. Adapters receive their dependencies instead of constructing them:
58
+ the GitHub capability adapters share one adapter-owned session, git adapters
59
+ receive the command runner, and the run receives a composition-resolved
60
+ `RunLayout` plus injected `Clock` and `IdGenerator`, so no application code
61
+ reads the clock, generates ids, or composes workspace paths itself.
62
+ Cross-cutting composed services such as parent completion and issue
63
+ preparation live in `issues/app/`, and `workflow/ports.ts` exposes the
64
+ driving `IssueWorkflow` port that the CLI invokes.
65
+
66
+ The progress contract lives in `src/progress/ports.ts`; `src/progress/adapters/`
67
+ implements it and is imported only by the composition root. `src/command.ts`
68
+ owns the terminal decision and passes one shared `RunEventLog` to the
69
+ coordinator (for persistence) and the runtime (the run closes it before
70
+ removing the workspace). `tests/architecture.test.ts` enforces the adapter
71
+ import rules, the no-I/O rule for non-adapter code, the Octokit confinement
72
+ (the `github` context is the only place the SDK appears), composition-root
73
+ isolation, and process-stream ownership. `tests/contracts/` holds the shared
74
+ behavioral suites that both the in-memory fakes and the live adapters pass: the
75
+ `RunEventLog` and `IssueArtifactStore` suites, the harness adapter suite that
76
+ every `HarnessAdapter` must pass (`harness-adapter.contract.ts`), and the
77
+ harness service suite (`harness-service.contract.ts`).
78
+
79
+ ## Skill injection
80
+
81
+ For each session, skill injection copies the pinned skills into the harness's
82
+ project skills location (`SKILL_SUPPORT` in `src/harness/app/skill-injection.ts`),
83
+ shadows any same-named repository skill until the session ends, and adds the
84
+ copies to `.git/info/exclude`. The spec also allows a per-invocation skills
85
+ option where a harness has one. Of the four, only pi does (`--skill <path>`).
86
+ Claude Code's `--plugin-dir` would load the skills as a plugin and rename them
87
+ `plugin:name`, and Codex and OpenCode have no such flag. Ralphie therefore uses
88
+ the project location for every harness, so shadowing and exclusion live in one
89
+ place. A new harness adds one `SKILL_SUPPORT` entry, its location and invocation
90
+ syntax together.
91
+
92
+ ## OpenCode adapter findings
93
+
94
+ Spike against OpenCode v2.0.22 (the published docs mostly describe v1). The recorded streams live in `tests/harness/fixtures/opencode/`.
95
+
96
+ - **Invocation**: `opencode run --standalone --format json`, prompt on stdin (with no message it prints an `error` event, "You must provide a message"). `--standalone` starts a private server, so the invocation's working directory and environment apply; the background service is shared and is never used.
97
+ - **Events**: one JSON object per line: `step_start`, `text` (whole block), `tool_use` (one event with input and output once the tool finished; `state.status` is `completed` or `error`, and a tool can report failure through `metadata.metadata.error` while `completed`), `step_finish` (`tokens` and `cost` per step) and `error` (`error.type` such as `provider.no-route` or `provider.quota`). There is no terminal result event, so a run succeeded when it exited 0, printed no `error` event and produced text. An error makes the process exit 1.
98
+ - **Usage**: the adapter sums every `step_finish` into one usage event per turn. `cost` is 0 for the recorded runs, so `costUsd` is omitted then. There is no budget cap flag.
99
+ - **Sessions**: `--session <id>` resumes, or creates the session when it does not exist. Session ids look like `ses_...`.
100
+ - **Model and effort**: `--model provider/model#variant`; the variant plays the part of effort and is only applied together with a model.
101
+ - **Access**: there is no sandbox. Read-only uses `--agent plan`, which denies edit tools but still allows shell commands, so it is not a hard guarantee. `--auto` approves every permission that is not denied and is the only editing mode; `safe` is refused with an `access` failure before anything runs. Without `--auto` a headless run cannot answer approval prompts.
102
+ - **Structured output**: none native. The service falls back to the fenced JSON block protocol.
103
+ - **Skills**: a skill under `.opencode/skills/<name>/` is loaded headlessly through the `skill` tool (recorded in `skill.jsonl`). Skills hidden from the model (user-only) were not tested.
104
+ - **Not verified live**: the spike had no usable model credits, so a successful read-only `--agent plan` run, resuming with `--session`, and user-only skills headlessly are untested against the real CLI. The recorded success streams come from earlier notes; only the error streams were recorded fresh. Until that run passes, startup refuses OpenCode unless the configuration sets `harnesses.opencode.experimental: true` (`UNVERIFIED_HARNESSES` in `src/harness/ports.ts`). Run [the live smoke script](development.md#live-smoke-script) with `--harness opencode` to verify it, and drop it from that list once it passes. The smoke script opts in on its own.
105
+
106
+ ## Dependency and side-effect rules
107
+
108
+ Agents own reasoning and edits within their permitted tool boundary. They do not
109
+ own commits, pushes, issue mutations, or delivery sequencing. Deterministic
110
+ services under `src/git/adapters/` and `src/github/adapters/` perform those side
111
+ effects and verify their invariants. The explicit runtime object makes these
112
+ boundaries testable without a framework-specific execution model.
113
+
114
+ The `GitRepositoryFactsService` port in `src/git/ports.ts` reads HEAD, branch, status, recent log, and tracked files so read-only prompts, whose sessions have no shell, receive them as a `<repository-facts>` block.
115
+
116
+ Agent configuration is separate from persistent workspace state: the
117
+ `harnesses` and `roles` configuration keys choose the harness, model, and
118
+ effort per role, and each harness CLI keeps its own login and credentials.
119
+ Ralphie never stores agent configuration under the
120
+ workspace; run state and recovery artifacts belong under the workspace's
121
+ `.ralphie` directory.
122
+
123
+ For workflow behavior and the agent/deterministic boundary, see [Workflows](workflows.md)
124
+ and [Safety](safety.md). For state transitions and retained diagnostics, see
125
+ [Operations and recovery](operations-and-recovery.md).
126
+
127
+ ## Distribution boundary
128
+
129
+ Ralphie's only distribution channel is the published npm package (see
130
+ [Getting started](getting-started.md#published-package)); the former native
131
+ binary, installer, Homebrew, and container distribution machinery was removed.
132
+
133
+ The package boundary is the bundled `dist/ralphie.js` CLI reached from
134
+ `index.ts` through `src/cli.ts`, `src/command.ts`, and runtime assembly. Tests
135
+ and helper probes are verification-only consumers. In particular, a type-only
136
+ import can document or check a contract but does not make a module runtime
137
+ reachable. The deterministic source audit is described in
138
+ [Development](development.md#source-reachability-boundary) and runs as part of
139
+ the normal check gate.
140
+
141
+ ## Source map
142
+
143
+ | Concern | Primary source |
144
+ | --- | --- |
145
+ | Configuration schema, layering, and file loading | `src/config/` |
146
+ | Public trigger and flags | `index.ts`, `src/cli.ts`, `src/command.ts`, `src/options.ts` |
147
+ | Runtime dependency assembly | `src/runtime.ts` |
148
+ | Run orchestration, queue, state transitions | `src/workflow/workflow.ts`, `src/issues/domain/queue.ts` |
149
+ | Pre-flight routing | `src/issues/app/issue-routing.ts`, `src/issues/app/execution-model.ts` (outcomes and execution context), `src/issues/app/preflight.ts` |
150
+ | Hand-offs | `src/issues/domain/hand-off.ts`, `src/issues/app/hand-off.ts`, `src/github/adapters/hand-off.ts` |
151
+ | AFK triage | `src/workflow/triage-phase.ts`, `src/issues/app/triage.ts`, `src/github/adapters/triage.ts` |
152
+ | Implementation/review/delivery | `src/issues/app/implementation-executor.ts` (attempts and delivery), `src/issues/app/implementation-attempt.ts` (prompt, result, retry policy), `src/issues/app/candidate-review.ts` (candidate commits and the two-axis review gate), `src/issues/app/verification.ts`, `src/git/adapters/issue-operations.ts`, `src/git/adapters/remote-safety.ts` |
153
+ | Decomposition and GitHub mutations | `src/issues/app/decomposition-executor.ts`, `src/github/adapters/issue-mutations.ts`, `src/github/adapters/issue-relationships.ts` |
154
+ | Role assignments, session requests, and structured results | `src/harness/app/roles.ts`, `src/agent/` |
155
+ | Harness sessions, structured results, and the harness adapters | `src/harness/ports.ts`, `src/harness/app/`, `src/harness/adapters/` |
156
+ | Git checkpoints, safety, and branches | `src/git/` |
157
+ | Durable run state, artifacts, diagnostics, and event audit | `src/issues/app/artifacts.ts`, `src/issues/app/recovery.ts`, `src/run/`, `src/issues/adapters/` |
158
+ | Driving port and runtime bundle | `src/workflow/ports.ts`, `src/runtime.ts` |
159
+ | Execution contracts, presentation, and exit semantics | `src/*/ports.ts`, `src/progress/adapters/` (OpenTUI, plain, JSON), `src/workflow/exit-code.ts` |
@@ -0,0 +1,126 @@
1
+ # CLI reference
2
+
3
+ This page is for operators automating Ralphie. It is the authoritative
4
+ reference for invocation syntax, command-line options, environment variables,
5
+ and common recipes. Settings live in the [configuration file](configuration.md). Return to the
6
+ [documentation index](README.md) for suggested reading paths.
7
+
8
+ ## Invocation
9
+
10
+ ```text
11
+ bunx @beremaran/ralphie [owner/]repository [options]
12
+ ```
13
+
14
+ `[owner/]repository` is required. It accepts an `owner/name` slug, a GitHub
15
+ HTTPS/SSH clone URL, or a bare repository name whose owner comes from
16
+ `defaultOwner` or the authenticated `gh` login (see
17
+ [Configuration](configuration.md#choosing-a-repository)). Nothing is inferred
18
+ from the current directory. Extra positional arguments are rejected. When
19
+ running from a source checkout, replace the package runner with
20
+ `bun run index.ts`.
21
+
22
+ Run `bunx @beremaran/ralphie --help` for the help generated from the current
23
+ command schema.
24
+
25
+ > [!CAUTION]
26
+ > Ralphie commits and pushes directly to the selected branch. Test against a
27
+ > repository you control, and read the [safety model](safety.md) before
28
+ > running it.
29
+
30
+ ## `init`
31
+
32
+ ```text
33
+ bunx @beremaran/ralphie init [--config <path>]
34
+ ```
35
+
36
+ Detects the harnesses on PATH and writes a commented starter config at
37
+ `--config` or the default location. It never overwrites an existing file and
38
+ fails when no supported harness is found. See
39
+ [Getting started](getting-started.md#create-the-config-file).
40
+
41
+ ## Options
42
+
43
+ All behavior settings live in the [configuration file](configuration.md).
44
+ These options remain on the command line:
45
+
46
+ | Option | Default | Description |
47
+ | --- | --- | --- |
48
+ | `--config <path>` | `$XDG_CONFIG_HOME/ralphie/config.yaml`, else `~/.config/ralphie/config.yaml` | Read configuration from this file. A missing file is an error. |
49
+ | `--set <path=value>` | none | Override one configuration key for this run; repeatable. The path is dotted, a key containing a slash is double-quoted (`repos."owner/repo".branch=develop`), and the value is YAML. Applied after the file and the matching `repos` entry. |
50
+ | `--output <mode>` | `default` | Output mode: `default` renders the full-screen TUI on a terminal and plain append-only lines when piped or in CI; `json` writes JSON Lines on stdout. |
51
+
52
+ The short aliases are `-h` for `--help` and `-v` for `--version`. Former flags
53
+ fail with an error naming the configuration key that replaces them; the
54
+ mapping is in [Configuration](configuration.md#removed-flags).
55
+
56
+ Every run processes the entire matching open-issue queue, sequentially, in the
57
+ order set by `intake.sort`.
58
+
59
+ ## Environment variables
60
+
61
+ Ralphie also reads these environment variables:
62
+
63
+ | Variable | Purpose |
64
+ | --- | --- |
65
+ | `GH_TOKEN` | GitHub.com token for noninteractive `gh` authentication (preferred). |
66
+ | `GITHUB_TOKEN` | Fallback GitHub.com token alias for `gh`. |
67
+
68
+ For interactive `github.com` use, authenticate with `gh auth login` and verify
69
+ with `gh auth status`. For unattended use, provide `GH_TOKEN` (preferred) or
70
+ `GITHUB_TOKEN` as an environment input; it does not need to be printed or
71
+ exposed. A mounted GitHub CLI profile is not required when an environment token
72
+ is provided. This authentication contract covers `github.com` only. See
73
+ [Getting started](getting-started.md) for the first-run setup.
74
+
75
+ ## Common recipes
76
+
77
+ Run the issue queue with settings from the default config file:
78
+
79
+ ```bash
80
+ bunx @beremaran/ralphie owner/repository
81
+ ```
82
+
83
+ Use a different config file and a bare repository name:
84
+
85
+ ```bash
86
+ bunx @beremaran/ralphie repository --config ./ralphie.yaml
87
+ ```
88
+
89
+ Override settings for one run:
90
+
91
+ ```bash
92
+ bunx @beremaran/ralphie owner/repository \
93
+ --set 'intake.requireLabels=[bug]' \
94
+ --set 'repos."owner/repository".branch=develop'
95
+ ```
96
+
97
+ Choose a model and effort for one run with `--set` (see
98
+ [Configuration](configuration.md#harnesses-and-roles)):
99
+
100
+ ```bash
101
+ bunx @beremaran/ralphie owner/repository \
102
+ --set harnesses.claude.model=opus \
103
+ --set harnesses.claude.effort=high
104
+ ```
105
+
106
+ Write machine-readable progress to stdout:
107
+
108
+ ```bash
109
+ bunx @beremaran/ralphie owner/repository --output json > ralphie.jsonl
110
+ ```
111
+
112
+ The workflow commits and pushes directly to the selected branch. It is not a
113
+ wait-for-human-review mode: approved work is committed, the remote head is
114
+ revalidated, and the commit is pushed without force before the source issue is
115
+ closed. Read [Workflows](workflows.md) and [Safety](safety.md) before running
116
+ it; the workspace is deleted, so read [Workspace risk](safety.md#workspace-risk)
117
+ first.
118
+
119
+ ## Version and help
120
+
121
+ `ralphie --version` prints only the release version. For automation,
122
+ `ralphie --version --output json` prints a stable object containing `version`
123
+ and `commitSha`. Both forms work without a repository, GitHub credentials, or
124
+ a model provider. Release builds embed the immutable commit SHA supplied by
125
+ the build entry point; local builds use the documented `local` commit sentinel
126
+ when no release SHA is supplied.
@@ -0,0 +1,269 @@
1
+ # Configuration
2
+
3
+ Ralphie reads its settings from a YAML file instead of command-line flags. This
4
+ page is the authoritative reference for the file location, every key, its
5
+ default, and how settings are layered. Return to the
6
+ [documentation index](README.md) for reading paths, and see the
7
+ [CLI reference](cli-reference.md) for the few options that remain on the
8
+ command line.
9
+
10
+ ## File location
11
+
12
+ Ralphie loads the first of these that applies:
13
+
14
+ 1. The path given with `--config <path>`. A missing file is an error.
15
+ 2. `$XDG_CONFIG_HOME/ralphie/config.yaml`, when `XDG_CONFIG_HOME` is an
16
+ absolute path.
17
+ 3. `~/.config/ralphie/config.yaml`.
18
+
19
+ There is no built-in fallback: when no file exists, Ralphie stops at startup,
20
+ names the path it looked for, and points at `ralphie init`, which writes a
21
+ starter file. An empty file is valid and means "all
22
+ defaults".
23
+
24
+ The file is validated with a strict schema before anything else runs. Unknown
25
+ keys, wrong types, and unknown values fail with the offending path, for
26
+ example `limits.reviewRounds: Invalid input: expected number, received string`. Errors caused
27
+ by a `--set` override are marked `(from --set)`.
28
+
29
+ ## Choosing a repository
30
+
31
+ Ralphie is invoked as `ralphie [owner/]repo`. Nothing is inferred from the
32
+ current directory.
33
+
34
+ | Argument | Resolved to |
35
+ | --- | --- |
36
+ | `owner/repo` or a GitHub HTTPS/SSH clone URL | Used as given. |
37
+ | `repo` | `defaultOwner/repo`, else the login `gh` is authenticated as (`gh api user`, honoring `GH_TOKEN`/`GITHUB_TOKEN`). |
38
+
39
+ ## Layering
40
+
41
+ For the selected repository, settings are layered from lowest to highest
42
+ precedence:
43
+
44
+ 1. Built-in defaults.
45
+ 2. Top-level settings in the file.
46
+ 3. The matching `repos."owner/repo"` entry. Repository keys match
47
+ case-insensitively.
48
+ 4. `--set path=value` overrides, in command-line order.
49
+
50
+ Mappings merge key by key. Lists and scalars replace the lower layer
51
+ entirely: a `repos` entry that sets `intake.requireLabels` does not add to the
52
+ top-level list.
53
+
54
+ ### `--set path=value`
55
+
56
+ `--set` is repeatable. The path is dotted; a key containing dots or a slash
57
+ is double-quoted, and the value is read as YAML:
58
+
59
+ ```bash
60
+ ralphie acme/api \
61
+ --set limits.reviewRounds=3 \
62
+ --set 'intake.requireLabels=[bug, backend]' \
63
+ --set 'repos."acme/api".branch=develop'
64
+ ```
65
+
66
+ A `--set` path under `repos."owner/repo"` applies to that repository like
67
+ any file entry. Quote the whole argument for your shell when the value
68
+ contains spaces or brackets.
69
+
70
+ ## Keys
71
+
72
+ ```yaml
73
+ defaultOwner: acme
74
+ workspace: ~/.ralphie
75
+ approval: safe
76
+ harnesses:
77
+ claude:
78
+ model: opus
79
+ effort: high
80
+ approval: safe
81
+ roles:
82
+ default: claude
83
+ reviewer:
84
+ harness: claude
85
+ model: sonnet
86
+ intake:
87
+ requireLabels: [bug]
88
+ sort: created:asc
89
+ triage:
90
+ enabled: false
91
+ labels:
92
+ needs-triage: needs-triage
93
+ needs-info: needs-info
94
+ ready-for-agent: ready-for-agent
95
+ ready-for-human: ready-for-human
96
+ wontfix: wontfix
97
+ skills:
98
+ dir: ./my-skills
99
+ limits:
100
+ implementationAttempts: 3
101
+ reviewRounds: 5
102
+ verificationFixes: 5
103
+ maxDecompositionDepth: 3
104
+ sessionTimeoutMinutes:
105
+ edit: 60
106
+ readOnly: 15
107
+ maxBudgetUsd: 5
108
+ repos:
109
+ acme/api:
110
+ branch: develop
111
+ verify:
112
+ - bun run check
113
+ intake:
114
+ requireLabels: [bug, backend]
115
+ ```
116
+
117
+ Every key is optional. The values above are the defaults, except
118
+ `defaultOwner`, `branch`, `verify`, `skills.dir`, and `limits.maxBudgetUsd`, which have none.
119
+
120
+ ### Top level
121
+
122
+ | Key | Default | Description |
123
+ | --- | --- | --- |
124
+ | `defaultOwner` | none | Owner added to a bare `repo` argument. Top level only. |
125
+ | `approval` | `safe` | Approval mode of the editing roles (`implementer`, `fixer`): `safe` or `yolo`. Overridable per repository and per harness. See [Approval modes](safety.md#approval-modes). |
126
+ | `workspace` | `~/.ralphie` | Root directory for repository checkouts and run artifacts. Ralphie deletes this directory; use a path dedicated to Ralphie (see [Workspace risk](safety.md#workspace-risk)). Overridable per repository. |
127
+ | `repos` | none | Per-repository overrides, keyed by `owner/repo`. Top level only. |
128
+
129
+ ### `harnesses` and `roles`
130
+
131
+ Every agent session runs as a role on a harness. The harnesses are `claude`
132
+ (Claude Code), `codex`, `pi`, and `opencode`. Sessions run through the
133
+ harness's own command-line program, which brings its own login and
134
+ credentials; Ralphie stores none.
135
+
136
+ `harnesses.<name>` sets the defaults for sessions on that harness:
137
+
138
+ | Key | Default | Description |
139
+ | --- | --- | --- |
140
+ | `harnesses.<name>.model` | harness default | Model passed to the harness. |
141
+ | `harnesses.<name>.effort` | harness default | Reasoning effort passed to the harness. |
142
+ | `harnesses.<name>.approval` | top-level `approval` | Approval mode for editing roles that run on this harness. |
143
+ | `harnesses.<name>.experimental` | `false` | Opt in to a harness whose adapter has not been verified against a live model. Currently only `opencode` needs it: startup refuses any role assigned to OpenCode until `harnesses.opencode.experimental: true` is set. Other harnesses ignore it. |
144
+
145
+ `roles` assigns a harness to each role. A value is a harness name, or a
146
+ mapping `{ harness, model, effort }` whose `model` and `effort` override the
147
+ harness defaults for that role.
148
+
149
+ | Key | Default | Description |
150
+ | --- | --- | --- |
151
+ | `roles.default` | `claude` | Harness for every role without its own assignment. |
152
+ | `roles.reviewer` | `roles.default` | Assignment both `standards-reviewer` and `spec-reviewer` inherit. |
153
+ | `roles.triager`, `preflight`, `implementer`, `resolution-verifier`, `decomposer` | `roles.default` | Per-role assignment. |
154
+ | `roles.standards-reviewer`, `roles.spec-reviewer` | `roles.reviewer`, else `roles.default` | Per-role assignment. |
155
+ | `roles.fixer` | the resolved `implementer` | Per-role assignment. |
156
+
157
+ The sessions map onto the roles as follows: AFK triage is the `triager`; the
158
+ pre-flight session and hand-off confirmation are the `preflight`;
159
+ implementation is the `implementer` (it also writes the commit message);
160
+ repair sessions are the `fixer`; the review gate runs the `standards-reviewer`
161
+ and the `spec-reviewer`; issue-resolution checks are the `resolution-verifier`;
162
+ and decomposition is the `decomposer`.
163
+
164
+ Startup checks each assigned harness (the `triager` only when
165
+ `triage.enabled` is true) by running its `--version`. A harness older than the
166
+ minimum below stops the run with an error naming the harness and the version it
167
+ needs. Output that contains no readable version only produces a warning.
168
+
169
+ | Harness | Minimum version |
170
+ | --- | --- |
171
+ | Claude Code (`claude`) | 2.1.289 |
172
+ | Codex (`codex`) | 0.160.0 |
173
+ | OpenCode (`opencode`) | 2.0.22 |
174
+ | pi (`pi`) | 1.0.2 |
175
+
176
+ Only the editing roles (`implementer`, `fixer`) may edit the checkout; the
177
+ others run read-only. How the editing roles are approved is described under
178
+ [Approval modes](safety.md#approval-modes), and each session's time limit is
179
+ under `limits.sessionTimeoutMinutes`. `pi` and `opencode` editing roles need
180
+ `approval: yolo`.
181
+
182
+ ### `intake`
183
+
184
+ | Key | Default | Description |
185
+ | --- | --- | --- |
186
+ | `intake.requireLabels` | `[]` | An issue must carry every listed label to enter the queue (AND filter). Added to the mandatory `labels.ready-for-agent` label. Children created by decomposition inherit the parent's labels listed here, plus the agent-ready label (see [Decomposition](workflows.md#decomposition-workflow)). |
187
+ | `intake.sort` | `created:asc` | Queue order: `created`, `updated`, or `comments`, optionally suffixed `:asc` or `:desc`. Without a suffix the order is ascending. |
188
+
189
+ ### `triage`
190
+
191
+ | Key | Default | Description |
192
+ | --- | --- | --- |
193
+ | `triage.enabled` | `false` | Run AFK triage before the queue. See [AFK triage](workflows.md#afk-triage). |
194
+
195
+ ### `labels`
196
+
197
+ Maps Matt Pocock's five canonical triage roles to the label names used in the
198
+ tracker. Each value is a non-empty label name and defaults to the role's own
199
+ name. Two roles may not share one label (compared case-insensitively).
200
+
201
+ | Key | Default |
202
+ | --- | --- |
203
+ | `labels.needs-triage` | `needs-triage` |
204
+ | `labels.needs-info` | `needs-info` |
205
+ | `labels.ready-for-agent` | `ready-for-agent` |
206
+ | `labels.ready-for-human` | `ready-for-human` |
207
+ | `labels.wontfix` | `wontfix` |
208
+
209
+ ### `skills`
210
+
211
+ | Key | Default | Description |
212
+ | --- | --- | --- |
213
+ | `skills.dir` | the skills bundled with Ralphie | Directory whose subdirectories are skills (each holds a `SKILL.md`). Relative paths resolve against the current directory. |
214
+
215
+ Before each session Ralphie copies these skills into the harness's project
216
+ skills directory (`.claude/skills`, `.agents/skills` for Codex, `.pi/skills`,
217
+ `.opencode/skills`). A repository skill with the same name is set aside for the
218
+ session and restored afterwards, so Ralphie's copy wins while other repository
219
+ skills stay available. Everything injected is added to the checkout's
220
+ `.git/info/exclude`, and is removed again when the session ends. Sessions that
221
+ overlap in one working directory (the parallel reviewers) share one injection:
222
+ the first prepares the checkout, and the last to finish restores it. If the
223
+ repository has no `docs/agents/issue-tracker.md` or
224
+ `docs/agents/triage-labels.md`, Ralphie generates them for the session: the
225
+ label table comes from `labels`, and the tracker doc says issue content is in
226
+ the prompt and sessions must not use `gh`. Committed versions always win.
227
+
228
+ ### `limits`
229
+
230
+ All limits are positive; counts are integers.
231
+
232
+ | Key | Default | Description |
233
+ | --- | --- | --- |
234
+ | `limits.implementationAttempts` | `3` | Implementation attempts allowed when sessions leave an unresolved empty diff or an implementer session times out. After the last attempt the issue is handed off `ready-for-human`. |
235
+ | `limits.reviewRounds` | `5` | Review rounds before the issue escalates to decomposition. At most `20`. |
236
+ | `limits.verificationFixes` | `5` | Repair attempts allowed after a failing `verify` command. |
237
+ | `limits.sessionTimeoutMinutes.edit` | `60` | Wall-clock limit of one session in an editing role. Exceeding it kills the session's process group and counts as a failed attempt. |
238
+ | `limits.sessionTimeoutMinutes.readOnly` | `15` | The same limit for read-only roles. |
239
+ | `limits.maxBudgetUsd` | none | Spend cap in US dollars for each session. Only Claude Code enforces it; Codex, pi and OpenCode ignore it, and startup warns for every assigned harness that cannot. |
240
+ | `limits.maxDecompositionDepth` | `3` | Maximum generated-child lineage depth. Reaching it hands the issue off as `ready-for-human` and continues independent work. |
241
+
242
+ ### Repository entries
243
+
244
+ Each `repos."owner/repo"` entry accepts `workspace`, `approval`, `harnesses`, `roles`,
245
+ `intake`, `triage`, `labels`, `skills`, and `limits` (overriding the top level for that repository
246
+ only) plus two keys that exist only here:
247
+
248
+ | Key | Default | Description |
249
+ | --- | --- | --- |
250
+ | `branch` | `main`, otherwise `master` | Base branch that verified work is pushed to directly. |
251
+ | `verify` | `[]` | Deterministic gate commands run in order after changes are staged, each under a 30-minute deadline. When empty, the gate is skipped and review proceeds on the staged diff alone. |
252
+
253
+ ## Removed flags
254
+
255
+ Each former flag now fails with an error naming its replacement.
256
+
257
+ | Former flag | Config key |
258
+ | --- | --- |
259
+ | `-b`, `--branch` | `repos."owner/repo".branch` |
260
+ | `--verify-command` | `repos."owner/repo".verify` |
261
+ | `--issue-label` | `intake.requireLabels` |
262
+ | `--issue-sort` | `intake.sort` |
263
+ | `--implementation-attempts` | `limits.implementationAttempts` |
264
+ | `--max-decomposition-depth` | `limits.maxDecompositionDepth` |
265
+ | `--workspace` | `workspace` |
266
+ | `--model` | `harnesses.<harness>.model` or `roles.<role>.model` |
267
+ | `--thinking` | `harnesses.<harness>.effort` or `roles.<role>.effort` |
268
+ | `--notify-needs-attention` | none: hand-offs are always on |
269
+ | `--needs-attention-label` | `labels.ready-for-human` |