You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/changelog.md
+6-2Lines changed: 6 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -24,14 +24,18 @@ Renamed "prompt" to "ralph" everywhere, simplified the CLI, and added a spinner
24
24
25
25
- Agent result message is now displayed in CLI output after each iteration.
26
26
- Raw Claude Code `stream-json` output no longer leaks to the terminal during iterations.
27
-
-Web dashboard page now clearly marked as "Coming Soon" to prevent users from trying non-existent commands.
27
+
-Removed placeholder dashboard page so all docs describe real, shipping features.
28
28
29
29
### Improved
30
30
31
+
- Introduced `Primitive` protocol in `_discovery.py` so all four primitive types (`Check`, `Context`, `Instruction`, `Ralph`) share a typed interface for discovery, filtering, merging, and display.
32
+
- Added generic `_discover_and_filter_enabled()` in the engine, replacing per-type boilerplate with a single code path bounded by the `Primitive` protocol.
33
+
- Moved check result serialization into `CheckResult.to_event_data()` so event data formatting has a single source of truth.
34
+
- Added missing event data fields (`result_text`, `detail`, `duration_formatted`) to API docs so library users see what the engine actually emits.
31
35
- Extracted shared scanning logic in `_discovery.py` to reduce duplication across primitive types.
32
36
- Added `PrimitiveEntry` type annotations for better code clarity.
33
37
- Moved `merge_by_name` to `_discovery.py` and deduplicated checks discovery logic.
34
-
- Updated codebase map and contributing docs to match the renamed source structure.
38
+
- Updated codebase map and contributing docs to match the current architecture.
### The four primitives and the `Primitive` protocol
75
75
76
-
All four follow the same pattern: a directory under `.ralphify/` with a marker markdown file containing YAML frontmatter.
76
+
All four primitive types follow the same pattern: a directory under `.ralphify/` with a marker markdown file containing YAML frontmatter. Each type's dataclass (`Check`, `Context`, `Instruction`, `Ralph`) satisfies the `Primitive` protocol defined in `_discovery.py`, which requires `name` and `enabled` properties. This enables type-safe generic functions for discovery, filtering, merging, and display — the engine's `_discover_and_filter_enabled()` helper uses the protocol to handle all four types through a single code path.
| Ralph |`RALPH.md`| At run start | Replaces root RALPH.md when selected by name |
84
84
85
-
Discovery is handled by `_discovery.py:discover_primitives()` which scans `.ralphify/{kind}/*/` for marker files.
85
+
Discovery is handled by `_discovery.py:discover_primitives()` which scans `.ralphify/{kind}/*/` for marker files. The engine groups enabled primitives into an `EnabledPrimitives` NamedTuple for clean parameter passing.
86
86
87
87
### Placeholder resolution
88
88
@@ -98,7 +98,7 @@ The run loop communicates via structured events (`_events.py`). Each event has a
98
98
99
99
-**`EventEmitter`** — protocol that any listener implements (just an `emit(event)` method)
100
100
-**`NullEmitter`** — discards events (used in tests)
101
-
-**`QueueEmitter`** — pushes events into a `queue.Queue` for async consumption (used by the UI)
101
+
-**`QueueEmitter`** — pushes events into a `queue.Queue` for async consumption (used by external orchestration layers)
102
102
-**`FanoutEmitter`** — broadcasts events to multiple emitters (used by the manager for fan-out to queue + persistence)
103
103
104
104
The CLI uses a `ConsoleEmitter` (defined in `_console_emitter.py`) that renders events to the terminal with Rich formatting.
@@ -117,7 +117,7 @@ The CLI uses a `ConsoleEmitter` (defined in `_console_emitter.py`) that renders
117
117
1.**`engine.py`** — The core run loop. Uses `RunConfig` and `RunState` (from `_run_types.py`) and `EventEmitter`. This is where iteration logic lives.
118
118
2.**`_run_types.py`** — `RunConfig`, `RunState`, and `RunStatus`. These are the shared data types used by the engine, CLI, and manager. Separated so modules that only need the types don't pull in execution logic.
119
119
3.**`cli.py`** — All CLI commands. Delegates to `engine.run_loop()` for the actual loop. Prompt source resolution (name vs. file path vs. inline) lives in `ralphs.py:resolve_ralph_source()`. Scaffold templates live in `_templates.py`. Terminal event rendering lives in `_console_emitter.py`.
120
-
4.**`_frontmatter.py`** + **`_discovery.py`** — Frontmatter parsing and primitive discovery. `_frontmatter.py` handles YAML parsing and defines marker constants. `_discovery.py` scans `.ralphify/` directories and uses `parse_frontmatter()`to yield `PrimitiveEntry` results. Understanding both is essential for working on checks/contexts/instructions/ralphs.
120
+
4.**`_frontmatter.py`** + **`_discovery.py`** — Frontmatter parsing and primitive discovery. `_frontmatter.py` handles YAML parsing and defines marker constants. `_discovery.py`defines the `Primitive` protocol, scans `.ralphify/` directories, and provides `merge_by_name()`for overlaying ralph-scoped primitives on globals. Understanding both is essential for working on checks/contexts/instructions/ralphs.
121
121
5.**`resolver.py`** — Template placeholder logic shared by contexts and instructions. Small file but critical — changes here affect both.
122
122
123
123
## Traps and gotchas
@@ -138,9 +138,9 @@ Add it in `cli.py`. The CLI uses Typer. The `new` subcommand group uses `app.add
138
138
139
139
You need to:
140
140
141
-
1. Create a new module (like `ralphs.py`) with dataclass, discover, and resolve functions
141
+
1. Create a new module (like `ralphs.py`) with a dataclass that satisfies the `Primitive` protocol (`name` and `enabled` properties), plus discover and resolve functions
142
142
2. Add a scaffold template in `_templates.py` and a `new` subcommand in `cli.py`
143
-
3. Wire it into `engine.py:run_loop()`if it affects the iteration cycle
143
+
3. Wire it into `engine.py:run_loop()`— add it to `EnabledPrimitives` and use `_discover_and_filter_enabled()`
0 commit comments