loreli 0.0.0 → 2.0.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.
- package/LICENSE +1 -1
- package/README.md +710 -97
- package/bin/loreli.js +89 -0
- package/package.json +77 -14
- package/packages/README.md +101 -0
- package/packages/action/README.md +98 -0
- package/packages/action/prompts/action.md +172 -0
- package/packages/action/src/index.js +684 -0
- package/packages/agent/README.md +606 -0
- package/packages/agent/src/backends/claude.js +387 -0
- package/packages/agent/src/backends/codex.js +351 -0
- package/packages/agent/src/backends/cursor.js +371 -0
- package/packages/agent/src/backends/index.js +486 -0
- package/packages/agent/src/base.js +138 -0
- package/packages/agent/src/cli.js +275 -0
- package/packages/agent/src/discover.js +396 -0
- package/packages/agent/src/factory.js +124 -0
- package/packages/agent/src/index.js +12 -0
- package/packages/agent/src/models.js +159 -0
- package/packages/agent/src/output.js +62 -0
- package/packages/agent/src/session.js +162 -0
- package/packages/agent/src/trace.js +186 -0
- package/packages/classify/README.md +136 -0
- package/packages/classify/prompts/blocker.md +12 -0
- package/packages/classify/prompts/feedback.md +14 -0
- package/packages/classify/prompts/pane-state.md +20 -0
- package/packages/classify/src/index.js +81 -0
- package/packages/config/README.md +898 -0
- package/packages/config/src/defaults.js +145 -0
- package/packages/config/src/index.js +223 -0
- package/packages/config/src/schema.js +291 -0
- package/packages/config/src/validate.js +160 -0
- package/packages/context/README.md +165 -0
- package/packages/context/src/index.js +198 -0
- package/packages/hub/README.md +338 -0
- package/packages/hub/src/base.js +154 -0
- package/packages/hub/src/github.js +1597 -0
- package/packages/hub/src/index.js +79 -0
- package/packages/hub/src/labels.js +48 -0
- package/packages/identity/README.md +288 -0
- package/packages/identity/src/index.js +620 -0
- package/packages/identity/src/themes/avatar.js +217 -0
- package/packages/identity/src/themes/digimon.js +217 -0
- package/packages/identity/src/themes/dragonball.js +217 -0
- package/packages/identity/src/themes/lotr.js +217 -0
- package/packages/identity/src/themes/marvel.js +217 -0
- package/packages/identity/src/themes/pokemon.js +217 -0
- package/packages/identity/src/themes/starwars.js +217 -0
- package/packages/identity/src/themes/transformers.js +217 -0
- package/packages/identity/src/themes/zelda.js +217 -0
- package/packages/knowledge/README.md +217 -0
- package/packages/knowledge/src/index.js +243 -0
- package/packages/log/README.md +93 -0
- package/packages/log/src/index.js +252 -0
- package/packages/marker/README.md +200 -0
- package/packages/marker/src/index.js +184 -0
- package/packages/mcp/README.md +323 -0
- package/packages/mcp/instructions.md +126 -0
- package/packages/mcp/scaffolding/.agents/skills/loreli-context/SKILL.md +89 -0
- package/packages/mcp/scaffolding/ISSUE_TEMPLATE/config.yml +2 -0
- package/packages/mcp/scaffolding/ISSUE_TEMPLATE/loreli.yml +83 -0
- package/packages/mcp/scaffolding/loreli.yml +491 -0
- package/packages/mcp/scaffolding/mcp-configs/.codex/config.toml +4 -0
- package/packages/mcp/scaffolding/mcp-configs/.cursor/mcp.json +14 -0
- package/packages/mcp/scaffolding/mcp-configs/.mcp.json +14 -0
- package/packages/mcp/scaffolding/pull-request.md +23 -0
- package/packages/mcp/src/index.js +600 -0
- package/packages/mcp/src/tools/agent-context.js +44 -0
- package/packages/mcp/src/tools/agents.js +450 -0
- package/packages/mcp/src/tools/context.js +200 -0
- package/packages/mcp/src/tools/github.js +1163 -0
- package/packages/mcp/src/tools/hitl.js +162 -0
- package/packages/mcp/src/tools/index.js +18 -0
- package/packages/mcp/src/tools/refactor.js +227 -0
- package/packages/mcp/src/tools/repo.js +44 -0
- package/packages/mcp/src/tools/start.js +904 -0
- package/packages/mcp/src/tools/status.js +149 -0
- package/packages/mcp/src/tools/work.js +134 -0
- package/packages/orchestrator/README.md +192 -0
- package/packages/orchestrator/src/index.js +1492 -0
- package/packages/planner/README.md +251 -0
- package/packages/planner/prompts/plan-reviewer.md +109 -0
- package/packages/planner/prompts/planner.md +191 -0
- package/packages/planner/prompts/tiebreaker-reviewer.md +71 -0
- package/packages/planner/src/index.js +1381 -0
- package/packages/review/README.md +129 -0
- package/packages/review/prompts/reviewer.md +158 -0
- package/packages/review/src/index.js +1403 -0
- package/packages/risk/README.md +178 -0
- package/packages/risk/prompts/risk.md +272 -0
- package/packages/risk/src/index.js +439 -0
- package/packages/session/README.md +165 -0
- package/packages/session/src/index.js +215 -0
- package/packages/test-utils/README.md +96 -0
- package/packages/test-utils/src/index.js +354 -0
- package/packages/tmux/README.md +261 -0
- package/packages/tmux/src/index.js +501 -0
- package/packages/workflow/README.md +317 -0
- package/packages/workflow/prompts/preamble.md +14 -0
- package/packages/workflow/src/index.js +660 -0
- package/packages/workflow/src/proof-of-life.js +74 -0
- package/packages/workspace/README.md +143 -0
- package/packages/workspace/src/index.js +1127 -0
- package/index.js +0 -8
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
# loreli/workflow
|
|
2
|
+
|
|
3
|
+
Shared contract for role-specific workflow packages. Provides a `Workflow` base class that planner, action, and review packages extend to implement their orchestration logic.
|
|
4
|
+
|
|
5
|
+
## Research Findings
|
|
6
|
+
|
|
7
|
+
Evaluated Temporal, Effect, and Flowcraft as potential base frameworks. All are full-featured workflow engines with durable execution, DAG-based routing, or functional effect systems — far too heavy for our lightweight abstract base class needs. Built from scratch using Node.js built-ins.
|
|
8
|
+
|
|
9
|
+
## API Reference
|
|
10
|
+
|
|
11
|
+
### `Workflow` (abstract base class)
|
|
12
|
+
|
|
13
|
+
Subclasses define a `role` and a `template` path to their Mustache prompt file, then implement reactor handlers and event listeners.
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
import { Workflow } from 'loreli/workflow';
|
|
17
|
+
|
|
18
|
+
class Planner extends Workflow {
|
|
19
|
+
static role = 'planner';
|
|
20
|
+
static template = new URL('./prompts/planner.md', import.meta.url).pathname;
|
|
21
|
+
|
|
22
|
+
reactor() {
|
|
23
|
+
return { promote: this.promote.bind(this) };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
events() {
|
|
27
|
+
return {}; // no orchestrator events needed
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async promote(hub, repo) { /* ... */ }
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
#### Constructor
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
new Workflow(orchestrator, hub)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
| Parameter | Type | Description |
|
|
41
|
+
|-----------|------|-------------|
|
|
42
|
+
| `orchestrator` | `Orchestrator` | The orchestrator instance for agent coordination |
|
|
43
|
+
| `hub` | `BaseHub` | GitHub hub instance for API calls |
|
|
44
|
+
|
|
45
|
+
#### `static role` → string
|
|
46
|
+
|
|
47
|
+
The role name this workflow handles (`'planner'`, `'action'`, `'reviewer'`). Must be overridden by subclasses.
|
|
48
|
+
|
|
49
|
+
#### `static template` → string
|
|
50
|
+
|
|
51
|
+
Absolute path to the Mustache prompt template file for this role. Must be overridden by subclasses.
|
|
52
|
+
|
|
53
|
+
#### `workflow.reactor()` → Record\<string, Function\>
|
|
54
|
+
|
|
55
|
+
Return a map of reactor handler names to functions. The orchestrator's `tick()` calls each registered handler on every reactor cycle. Subclasses override this to register their specific handlers.
|
|
56
|
+
|
|
57
|
+
**Returns**: `object` — Map of handler name to async function.
|
|
58
|
+
|
|
59
|
+
#### `workflow.events()` → Record\<string, Function\>
|
|
60
|
+
|
|
61
|
+
Return a map of orchestrator event names to listener functions. These are auto-wired to the orchestrator's EventEmitter when the workflow is attached.
|
|
62
|
+
|
|
63
|
+
**Returns**: `object` — Map of event name (e.g. `'removed'`, `'stall'`) to handler.
|
|
64
|
+
|
|
65
|
+
#### `workflow.agents()` → Agent[]
|
|
66
|
+
|
|
67
|
+
Filter the orchestrator's agent map to only those matching this workflow's role.
|
|
68
|
+
|
|
69
|
+
**Returns**: `Agent[]` — Agents whose `role` matches `static role`.
|
|
70
|
+
|
|
71
|
+
#### `workflow.demand(repo)` → Promise\<{workload, supply, deficit}\>
|
|
72
|
+
|
|
73
|
+
Report the current demand signal for this workflow's role. Returns a structured object with three fields:
|
|
74
|
+
|
|
75
|
+
| Field | Type | Description |
|
|
76
|
+
|-------|------|-------------|
|
|
77
|
+
| `workload` | `number` | Items that need an agent (unclaimed issues, unreviewed PRs, etc.) |
|
|
78
|
+
| `supply` | `number` | Active (non-dormant) agents of this role |
|
|
79
|
+
| `deficit` | `number` | `max(0, workload - supply)` — how many agents are needed |
|
|
80
|
+
|
|
81
|
+
The base class returns `{ workload: 0, supply: 0, deficit: 0 }`. Each workflow overrides this using data from its hydrated state — no extra API calls. The orchestrator's `scale()` handler collects these signals and spawns agents proportional to deficit, respecting configurable caps and cooldowns.
|
|
82
|
+
|
|
83
|
+
The following example shows how the demand signal drives scaling decisions — `scale()` calls `demand()` on each registered workflow and spawns agents for roles with a positive deficit:
|
|
84
|
+
|
|
85
|
+
```js
|
|
86
|
+
const signal = await reviewWorkflow.demand('owner/repo');
|
|
87
|
+
// { workload: 3, supply: 1, deficit: 2 } — needs 2 more reviewers
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
#### `workflow.pair(identity, candidates)` → object | null
|
|
91
|
+
|
|
92
|
+
Find the opposing-provider agent for yin/yang review pairing. Delegates to the orchestrator's identity registry.
|
|
93
|
+
|
|
94
|
+
| Parameter | Type | Description |
|
|
95
|
+
|-----------|------|-------------|
|
|
96
|
+
| `identity` | `Identity` | The identity to find an opposite for |
|
|
97
|
+
| `candidates` | `object[]` | Candidate objects with an `identity` field |
|
|
98
|
+
|
|
99
|
+
**Returns**: The matching agent, or `null`.
|
|
100
|
+
|
|
101
|
+
#### `workflow.enlist(provider, role, opts?)` → Promise\<Agent\>
|
|
102
|
+
|
|
103
|
+
Create and spawn a new agent via the orchestrator's factory. Convenience wrapper that delegates to `orchestrator.enlist()`.
|
|
104
|
+
|
|
105
|
+
#### `workflow.custom(opts?)` → Promise\<string\>
|
|
106
|
+
|
|
107
|
+
Load the project-specific custom prompt from the `workflows.{role}.prompt` config key (e.g. `workflows.action.prompt`, `workflows.reviewer.prompt`, `workflows.planner.prompt`, `workflows.risk.prompt`). By default, resolves this workflow's `static role`; pass `opts.role` to resolve another role during cross-role rendering. Reads each role-specific file once from the target repo via the hub and caches it on the instance. Returns an empty string when:
|
|
108
|
+
|
|
109
|
+
- `workflows.{role}.prompt` is not configured for this workflow's role
|
|
110
|
+
- The hub is unavailable (e.g. unit tests)
|
|
111
|
+
- The repo is not set on the orchestrator
|
|
112
|
+
- The file cannot be read (missing or inaccessible)
|
|
113
|
+
|
|
114
|
+
Rendering never fails due to a missing custom prompt — this method degrades silently.
|
|
115
|
+
|
|
116
|
+
| Parameter | Type | Description |
|
|
117
|
+
|-----------|------|-------------|
|
|
118
|
+
| `opts.role` | `string` | Optional role override for `workflows.{role}.prompt` lookup |
|
|
119
|
+
|
|
120
|
+
**Returns**: `Promise<string>` — Custom prompt text, or empty string.
|
|
121
|
+
|
|
122
|
+
#### `workflow.render(vars)` → Promise\<string\>
|
|
123
|
+
|
|
124
|
+
Load and render this workflow's prompt template with Mustache variables. Automatically prepends the shared autonomous-mode preamble and any per-role custom prompt from `workflows.{role}.prompt` (see [Autonomous Preamble](#autonomous-preamble) and [Custom Prompt Extensions](#custom-prompt-extensions) below).
|
|
125
|
+
|
|
126
|
+
| Parameter | Type | Description |
|
|
127
|
+
|-----------|------|-------------|
|
|
128
|
+
| `vars` | `object` | Template variables (name, repo, faction, provider, model, labels) |
|
|
129
|
+
|
|
130
|
+
**Returns**: `Promise<string>` — Rendered prompt text with preamble and custom prompt prepended.
|
|
131
|
+
|
|
132
|
+
#### `workflow.renderFrom(path, vars, opts?)` → Promise\<string\>
|
|
133
|
+
|
|
134
|
+
Load and render an arbitrary Mustache template. Used for cross-role rendering (e.g. review package rendering the action prompt for `forward()`). Automatically prepends the shared autonomous-mode preamble and any per-role custom prompt.
|
|
135
|
+
|
|
136
|
+
| Parameter | Type | Description |
|
|
137
|
+
|-----------|------|-------------|
|
|
138
|
+
| `path` | `string` | Absolute path to a `.md` template file |
|
|
139
|
+
| `vars` | `object` | Template variables |
|
|
140
|
+
| `opts.role` | `string` | Optional role override for custom prompt lookup. When set, resolves `workflows.{opts.role}.prompt` instead of this workflow's `static role` |
|
|
141
|
+
|
|
142
|
+
**Returns**: `Promise<string>` — Rendered prompt text with preamble and custom prompt prepended.
|
|
143
|
+
|
|
144
|
+
#### `workflow.dispatch(agent, vars)` → Promise\<void\>
|
|
145
|
+
|
|
146
|
+
Send a rendered prompt to an agent. Renders this workflow's template and dispatches it to the agent's `send()` method.
|
|
147
|
+
|
|
148
|
+
| Parameter | Type | Description |
|
|
149
|
+
|-----------|------|-------------|
|
|
150
|
+
| `agent` | `Agent` | Target agent |
|
|
151
|
+
| `vars` | `object` | Template variables |
|
|
152
|
+
|
|
153
|
+
### Proof-of-Life Protocol
|
|
154
|
+
|
|
155
|
+
These methods implement the distributed coordination protocol for verifying agent liveness before eviction. The `check()` method is the unified gate — all eviction decisions (local and foreign) route through it as the single authority.
|
|
156
|
+
|
|
157
|
+
#### `workflow.check(repo, number, agent)` → Promise\<string\>
|
|
158
|
+
|
|
159
|
+
Unified proof-of-life gate for all eviction decisions. Posts a PoL request if none exists, checks for alive responses, and considers the response status when making the verdict.
|
|
160
|
+
|
|
161
|
+
**Status-aware**: an alive response with `status: 'unhealthy'` returns `'release'` (the agent's own orchestrator confirmed it is stalled). A `'healthy'` response returns `'active'`. This is what enables local agent eviction through PoL — when `health()` (enhanced with tmux pane detection via `refresh()`) confirms the agent is truly stalled, the PoL system correctly signals eviction.
|
|
162
|
+
|
|
163
|
+
| Parameter | Type | Description |
|
|
164
|
+
|-----------|------|-------------|
|
|
165
|
+
| `repo` | `string` | Repository in "owner/name" format |
|
|
166
|
+
| `number` | `number` | Issue or PR number |
|
|
167
|
+
| `agent` | `string` | Agent identity name to check |
|
|
168
|
+
|
|
169
|
+
**Returns**: `'active'` | `'requested'` | `'pending'` | `'release'`
|
|
170
|
+
|
|
171
|
+
| Return Value | Meaning |
|
|
172
|
+
|-------------|---------|
|
|
173
|
+
| `'active'` | Agent proved alive (healthy alive response or recent activity) |
|
|
174
|
+
| `'requested'` | PoL request posted, check again next tick |
|
|
175
|
+
| `'pending'` | PoL request exists, waiting for response |
|
|
176
|
+
| `'release'` | Agent confirmed stalled (unhealthy alive, expired request, or timeout) |
|
|
177
|
+
|
|
178
|
+
#### Low-Level Methods
|
|
179
|
+
|
|
180
|
+
These are the building blocks that `check()` composes. They can be used directly for custom liveness logic.
|
|
181
|
+
|
|
182
|
+
#### `workflow.requestProofOfLife(repo, number, agent)` → Promise\<void\>
|
|
183
|
+
|
|
184
|
+
Post a themed proof-of-life request on an issue or PR. When the orchestrator has a `clientIdentity`, the comment includes a visible council-themed message (from the identity's theme) and is posted via a scoped hub (`hub.as(identity, 'orchestrator')`), which appends the orchestrator's signature. The machine-readable marker is embedded alongside the visible text.
|
|
185
|
+
|
|
186
|
+
The marker includes the orchestrator's `sessionId` (as `orch`) when available. This enables orchestrator-scoped proof-of-life: a new orchestrator can distinguish its own requests from those left by a dead predecessor, and post a fresh request instead of blindly evicting based on an expired foreign request.
|
|
187
|
+
|
|
188
|
+
Falls back to an unscoped invisible marker when no `clientIdentity` is available.
|
|
189
|
+
|
|
190
|
+
| Parameter | Type | Description |
|
|
191
|
+
|-----------|------|-------------|
|
|
192
|
+
| `repo` | `string` | Repository in "owner/name" format |
|
|
193
|
+
| `number` | `number` | Issue or PR number |
|
|
194
|
+
| `agent` | `string` | Name of the agent being checked |
|
|
195
|
+
|
|
196
|
+
#### `workflow.respondProofOfLife(repo, number, identity, role, verdict)` → Promise\<void\>
|
|
197
|
+
|
|
198
|
+
Post a themed alive response with an embedded machine-readable marker. The response includes the agent's identity branding and the health check result.
|
|
199
|
+
|
|
200
|
+
| Parameter | Type | Description |
|
|
201
|
+
|-----------|------|-------------|
|
|
202
|
+
| `repo` | `string` | Repository in "owner/name" format |
|
|
203
|
+
| `number` | `number` | Issue or PR number |
|
|
204
|
+
| `identity` | `Identity` | Agent identity for hub scoping and branding |
|
|
205
|
+
| `role` | `string` | Agent role for hub scoping |
|
|
206
|
+
| `verdict` | `object` | Health check result: `{ alive, status, details, outputLength? }` |
|
|
207
|
+
|
|
208
|
+
#### `workflow.findProofOfLifeRequest(repo, number, agent, orch?)` → Promise\<object|null\>
|
|
209
|
+
|
|
210
|
+
Find a pending proof-of-life request for a specific agent by scanning comments for `proof-of-life` markers.
|
|
211
|
+
|
|
212
|
+
When `orch` is provided, only matches requests posted by that orchestrator session (the `orch` field in the marker must match). When omitted, matches any request for the agent — this is used by the responder, which answers regardless of who asked.
|
|
213
|
+
|
|
214
|
+
| Parameter | Type | Description |
|
|
215
|
+
|-----------|------|-------------|
|
|
216
|
+
| `repo` | `string` | Repository in "owner/name" format |
|
|
217
|
+
| `number` | `number` | Issue or PR number |
|
|
218
|
+
| `agent` | `string` | Agent name to search for |
|
|
219
|
+
| `orch` | `string?` | Orchestrator session ID filter (optional) |
|
|
220
|
+
|
|
221
|
+
**Returns**: `{ agent, ts, orch? }` or `null` if no request exists.
|
|
222
|
+
|
|
223
|
+
#### `workflow.findAliveResponse(repo, number, agent, after)` → Promise\<object|null\>
|
|
224
|
+
|
|
225
|
+
Find an alive response for a specific agent posted after a given timestamp.
|
|
226
|
+
|
|
227
|
+
| Parameter | Type | Description |
|
|
228
|
+
|-----------|------|-------------|
|
|
229
|
+
| `repo` | `string` | Repository in "owner/name" format |
|
|
230
|
+
| `number` | `number` | Issue or PR number |
|
|
231
|
+
| `agent` | `string` | Agent name to search for |
|
|
232
|
+
| `after` | `number` | Only match responses with timestamp greater than this epoch ms |
|
|
233
|
+
|
|
234
|
+
**Returns**: `{ agent, ts, status }` or `null` if no matching response exists.
|
|
235
|
+
|
|
236
|
+
#### `workflow.hasRecentActivity(repo, number, timeout)` → Promise\<boolean\>
|
|
237
|
+
|
|
238
|
+
Check whether an issue or PR has any GitHub comment within the timeout window.
|
|
239
|
+
|
|
240
|
+
| Parameter | Type | Description |
|
|
241
|
+
|-----------|------|-------------|
|
|
242
|
+
| `repo` | `string` | Repository in "owner/name" format |
|
|
243
|
+
| `number` | `number` | Issue or PR number |
|
|
244
|
+
| `timeout` | `number` | Maximum age in ms for activity to be considered recent |
|
|
245
|
+
|
|
246
|
+
**Returns**: `true` if any comment was posted within the timeout window.
|
|
247
|
+
|
|
248
|
+
### `responder(orchestrator, hub)` → Function
|
|
249
|
+
|
|
250
|
+
Factory that creates the proof-of-life reactor handler. The handler scans all open `loreli`-labeled issues and PRs for proof-of-life request markers targeting agents in the local orchestrator's agents map, runs `health()` checks, and posts themed alive responses.
|
|
251
|
+
|
|
252
|
+
Registered once during start and runs on every reactor tick. Ignores requests for agents not in the local map — only the managing orchestrator responds.
|
|
253
|
+
|
|
254
|
+
```js
|
|
255
|
+
import { responder } from 'loreli/workflow';
|
|
256
|
+
|
|
257
|
+
orchestrator.register('proof-of-life', responder(orchestrator, hub));
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
| Parameter | Type | Description |
|
|
261
|
+
|-----------|------|-------------|
|
|
262
|
+
| `orchestrator` | `Orchestrator` | Orchestrator with `agents` map and `health()` method |
|
|
263
|
+
| `hub` | `BaseHub` | GitHub hub for reading/posting comments |
|
|
264
|
+
|
|
265
|
+
**Returns**: `async function(repo)` — Reactor handler.
|
|
266
|
+
|
|
267
|
+
## Autonomous Preamble
|
|
268
|
+
|
|
269
|
+
All agent prompts run through `render()` or `renderFrom()`, which automatically prepend a shared preamble from `prompts/preamble.md`. This preamble instructs agents that they are running autonomously in a headless tmux pane and must never ask clarifying questions, invoke interactive skills, or wait for user input.
|
|
270
|
+
|
|
271
|
+
The preamble is the single source of truth for autonomous-mode directives. Role-specific templates (action, planner, reviewer) do not duplicate this text — they inherit it through the rendering pipeline. This ensures every agent prompt carries the directive without per-template maintenance.
|
|
272
|
+
|
|
273
|
+
The preamble is loaded once and cached for the lifetime of the process.
|
|
274
|
+
|
|
275
|
+
## Custom Prompt Extensions
|
|
276
|
+
|
|
277
|
+
Projects can inject per-role custom instructions into agent prompts by setting `workflows.{role}.prompt` in `loreli.yml`. Each role maps to a workflow and the value is a file path relative to the repository root.
|
|
278
|
+
|
|
279
|
+
```yaml
|
|
280
|
+
# loreli.yml
|
|
281
|
+
workflows:
|
|
282
|
+
action:
|
|
283
|
+
prompt: .loreli/action.md
|
|
284
|
+
reviewer:
|
|
285
|
+
prompt: .loreli/review.md
|
|
286
|
+
planner:
|
|
287
|
+
prompt: .loreli/planner.md
|
|
288
|
+
risk:
|
|
289
|
+
prompt: .loreli/risk.md
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
When configured, `render()` and `renderFrom()` resolve `workflows.{role}.prompt` from config, read the file from the target repo via the hub, and insert its content between the autonomous preamble and the role-specific template:
|
|
293
|
+
|
|
294
|
+
1. **Autonomous preamble** (`prompts/preamble.md`) — always present
|
|
295
|
+
2. **Custom prompt** (`workflows.{role}.prompt`) — when configured for the current role
|
|
296
|
+
3. **Role template** (action/planner/reviewer `.md` file)
|
|
297
|
+
|
|
298
|
+
Each role resolves independently — an action workflow only reads `workflows.action.prompt`, a reviewer only reads `workflows.reviewer.prompt`. Roles without a configured prompt file are unaffected.
|
|
299
|
+
|
|
300
|
+
The file is read once on the first `render()` call and cached on the `Workflow` instance for the remainder of the session. If the file is missing or unreadable, rendering continues normally — agents are never blocked by a missing custom prompt.
|
|
301
|
+
|
|
302
|
+
The custom prompt is static text (not processed through Mustache). Tailor each role's prompt to its responsibilities: coding standards for action agents, quality gates for reviewers, methodology for planners.
|
|
303
|
+
|
|
304
|
+
See the root [README](../../README.md#custom-prompt-extensions) for detailed usage examples and guidelines.
|
|
305
|
+
|
|
306
|
+
## Errors
|
|
307
|
+
|
|
308
|
+
| Error | When | Resolution |
|
|
309
|
+
|-------|------|------------|
|
|
310
|
+
| `Cannot construct Workflow directly` | Instantiating `Workflow` without subclassing | Extend the class and define `static role` and `static template` |
|
|
311
|
+
| `Template not found: {path}` | Template file missing at the specified path | Ensure the prompt `.md` file exists at the subclass's `static template` path |
|
|
312
|
+
|
|
313
|
+
## Scope Boundary
|
|
314
|
+
|
|
315
|
+
**In scope**: Role-based agent filtering, prompt template rendering, reactor/event registration contracts, demand signals for scaling, optimistic claim protocol, proof-of-life coordination protocol.
|
|
316
|
+
|
|
317
|
+
**Out of scope**: Agent lifecycle (orchestrator), GitHub API calls (hub), process management (tmux), agent spawning (handled centrally by `orchestrator.scale()`).
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<autonomous>
|
|
2
|
+
|
|
3
|
+
You are running autonomously in a headless tmux pane with no human operator. There is no user to respond to questions.
|
|
4
|
+
|
|
5
|
+
- **Never ask** clarifying questions, present multiple-choice options, or wait for user input.
|
|
6
|
+
- **Never invoke** interactive skills (brainstorming, design reviews, or anything that requires human approval gates).
|
|
7
|
+
- **Always proceed** with your best judgment. When multiple approaches exist, pick the most reasonable default and document your reasoning.
|
|
8
|
+
- If a skill or workflow would normally require user confirmation, skip it entirely and proceed directly to your task.
|
|
9
|
+
- Before planning or coding, explicitly check whether `AGENTS.md` exists at the repository root. If it exists, read it and treat it as normative repository policy for this task.
|
|
10
|
+
- `AGENTS.md` policy takes precedence over generic defaults for repository-specific behavior. Follow it without waiting for confirmation.
|
|
11
|
+
|
|
12
|
+
Violations of these rules will permanently stall your session.
|
|
13
|
+
|
|
14
|
+
</autonomous>
|