loreli 0.0.0 → 1.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.
Files changed (88) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +670 -97
  3. package/bin/loreli.js +89 -0
  4. package/package.json +74 -14
  5. package/packages/README.md +101 -0
  6. package/packages/action/README.md +98 -0
  7. package/packages/action/src/index.js +656 -0
  8. package/packages/agent/README.md +517 -0
  9. package/packages/agent/src/backends/claude.js +287 -0
  10. package/packages/agent/src/backends/codex.js +278 -0
  11. package/packages/agent/src/backends/cursor.js +294 -0
  12. package/packages/agent/src/backends/index.js +329 -0
  13. package/packages/agent/src/base.js +138 -0
  14. package/packages/agent/src/cli.js +198 -0
  15. package/packages/agent/src/factory.js +119 -0
  16. package/packages/agent/src/index.js +12 -0
  17. package/packages/agent/src/models.js +141 -0
  18. package/packages/agent/src/output.js +62 -0
  19. package/packages/agent/src/session.js +162 -0
  20. package/packages/agent/src/trace.js +186 -0
  21. package/packages/config/README.md +833 -0
  22. package/packages/config/src/defaults.js +134 -0
  23. package/packages/config/src/index.js +192 -0
  24. package/packages/config/src/schema.js +273 -0
  25. package/packages/config/src/validate.js +160 -0
  26. package/packages/context/README.md +165 -0
  27. package/packages/context/src/index.js +198 -0
  28. package/packages/hub/README.md +338 -0
  29. package/packages/hub/src/base.js +154 -0
  30. package/packages/hub/src/github.js +1558 -0
  31. package/packages/hub/src/index.js +79 -0
  32. package/packages/hub/src/labels.js +48 -0
  33. package/packages/identity/README.md +288 -0
  34. package/packages/identity/src/index.js +620 -0
  35. package/packages/identity/src/themes/avatar.js +217 -0
  36. package/packages/identity/src/themes/digimon.js +217 -0
  37. package/packages/identity/src/themes/dragonball.js +217 -0
  38. package/packages/identity/src/themes/lotr.js +217 -0
  39. package/packages/identity/src/themes/marvel.js +217 -0
  40. package/packages/identity/src/themes/pokemon.js +217 -0
  41. package/packages/identity/src/themes/starwars.js +217 -0
  42. package/packages/identity/src/themes/transformers.js +217 -0
  43. package/packages/identity/src/themes/zelda.js +217 -0
  44. package/packages/knowledge/README.md +237 -0
  45. package/packages/knowledge/src/index.js +412 -0
  46. package/packages/log/README.md +93 -0
  47. package/packages/log/src/index.js +252 -0
  48. package/packages/marker/README.md +200 -0
  49. package/packages/marker/src/index.js +184 -0
  50. package/packages/mcp/README.md +279 -0
  51. package/packages/mcp/instructions.md +121 -0
  52. package/packages/mcp/scaffolding/.agents/skills/loreli-context/SKILL.md +89 -0
  53. package/packages/mcp/scaffolding/ISSUE_TEMPLATE/config.yml +2 -0
  54. package/packages/mcp/scaffolding/ISSUE_TEMPLATE/loreli.yml +83 -0
  55. package/packages/mcp/scaffolding/loreli.yml +453 -0
  56. package/packages/mcp/scaffolding/mcp-configs/.codex/config.toml +3 -0
  57. package/packages/mcp/scaffolding/mcp-configs/.cursor/mcp.json +11 -0
  58. package/packages/mcp/scaffolding/mcp-configs/.mcp.json +11 -0
  59. package/packages/mcp/scaffolding/pull-request.md +23 -0
  60. package/packages/mcp/src/index.js +571 -0
  61. package/packages/mcp/src/tools/agents.js +429 -0
  62. package/packages/mcp/src/tools/context.js +199 -0
  63. package/packages/mcp/src/tools/github.js +1199 -0
  64. package/packages/mcp/src/tools/hitl.js +149 -0
  65. package/packages/mcp/src/tools/index.js +17 -0
  66. package/packages/mcp/src/tools/start.js +835 -0
  67. package/packages/mcp/src/tools/status.js +146 -0
  68. package/packages/mcp/src/tools/work.js +124 -0
  69. package/packages/orchestrator/README.md +192 -0
  70. package/packages/orchestrator/src/index.js +1226 -0
  71. package/packages/planner/README.md +168 -0
  72. package/packages/planner/src/index.js +1166 -0
  73. package/packages/review/README.md +129 -0
  74. package/packages/review/src/index.js +1283 -0
  75. package/packages/risk/README.md +119 -0
  76. package/packages/risk/src/index.js +428 -0
  77. package/packages/session/README.md +165 -0
  78. package/packages/session/src/index.js +215 -0
  79. package/packages/test-utils/README.md +96 -0
  80. package/packages/test-utils/src/index.js +354 -0
  81. package/packages/tmux/README.md +261 -0
  82. package/packages/tmux/src/index.js +452 -0
  83. package/packages/workflow/README.md +313 -0
  84. package/packages/workflow/src/index.js +481 -0
  85. package/packages/workflow/src/proof-of-life.js +74 -0
  86. package/packages/workspace/README.md +143 -0
  87. package/packages/workspace/src/index.js +1076 -0
  88. package/index.js +0 -8
package/bin/loreli.js ADDED
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Loreli CLI entry point.
5
+ *
6
+ * Uses @mcp-layer/cli to expose a single custom command (`mcp`) that starts
7
+ * the MCP server. All MCP tools, prompts, and resources are automatically
8
+ * exposed as CLI commands by the framework (e.g. `loreli tools list`,
9
+ * `loreli tools start --repo owner/repo`).
10
+ */
11
+
12
+ import { execFileSync } from 'node:child_process';
13
+ import { readFileSync } from 'node:fs';
14
+ import { join, dirname } from 'node:path';
15
+ import { fileURLToPath } from 'node:url';
16
+ import { loadEnv } from 'loreli/config';
17
+ import { cli } from '@mcp-layer/cli';
18
+
19
+ /**
20
+ * Error message shown when tmux is missing from PATH.
21
+ *
22
+ * @type {string}
23
+ */
24
+ const TMUX_MISSING = [
25
+ 'tmux is required to run Loreli.',
26
+ '',
27
+ 'Install it and re-run the command:',
28
+ ' macOS (Homebrew): brew install tmux',
29
+ ' Linux (APT): sudo apt install tmux',
30
+ '',
31
+ 'If tmux is already installed, run `command -v tmux` to verify PATH.',
32
+ 'See README: https://github.com/3rd-Eden/loreli#prerequisites',
33
+ ].join('\n');
34
+
35
+ /**
36
+ * Preflight evaluation that ensures tmux is on PATH before the CLI runs.
37
+ *
38
+ * @throws {Error} When tmux is missing from PATH.
39
+ * @returns {void}
40
+ */
41
+ (function preflight() {
42
+ try {
43
+ execFileSync('which', ['tmux'], { stdio: 'ignore' });
44
+ } catch {
45
+ throw new Error(TMUX_MISSING);
46
+ }
47
+ }());
48
+
49
+ const __dirname = dirname(fileURLToPath(import.meta.url));
50
+ const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8'));
51
+
52
+ // Load .env before anything else so GITHUB_TOKEN and other vars are
53
+ // available to every subsystem. Silent no-op when no .env file exists.
54
+ loadEnv();
55
+
56
+ /**
57
+ * Build and execute the CLI.
58
+ *
59
+ * @returns {Promise<void>}
60
+ */
61
+ async function main() {
62
+ return await cli({
63
+ name: pkg.name,
64
+ version: pkg.version,
65
+ description: pkg.description,
66
+ server: 'loreli',
67
+ showServers: false
68
+ })
69
+ .command({
70
+ name: 'mcp',
71
+ description: 'Start the MCP server',
72
+ details: 'Starts the Loreli MCP server with stdio transport for client connections.',
73
+ examples: [
74
+ 'loreli mcp',
75
+ ]
76
+ }, async function start(argv, { spinner }) {
77
+ const done = spinner('Starting Loreli MCP server');
78
+ const { Loreli } = await import('loreli/mcp');
79
+ const loreli = new Loreli();
80
+ await loreli.start();
81
+ done();
82
+ })
83
+ .render();
84
+ }
85
+
86
+ main().catch(function fatal(err) {
87
+ console.error('loreli:', err.message);
88
+ process.exit(1);
89
+ });
package/package.json CHANGED
@@ -1,23 +1,83 @@
1
1
  {
2
2
  "name": "loreli",
3
- "version": "0.0.0",
4
- "description": "Loreli is an agentic system that uses the GitHub patterns we're familiar with for orchestration. Issues becomes actions for agents. Pull Requests are review tasks. Discussions are where plans are discussed and then raised as issues on approval. The system uses an antagonist style where OpenAI will always be checked by Antrophic, ensuring you get input from both models.",
5
- "keywords": [
6
- "loreli",
7
- "github",
8
- "agentic",
9
- "system",
10
- "orchestration"
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "Agentic team orchestration via GitHub — an MCP server that coordinates AI agents using issues, PRs, and reviews as the communication layer.",
6
+ "exports": {
7
+ "./tmux": "./packages/tmux/src/index.js",
8
+ "./log": "./packages/log/src/index.js",
9
+ "./hub": "./packages/hub/src/index.js",
10
+ "./identity": "./packages/identity/src/index.js",
11
+ "./agent": "./packages/agent/src/index.js",
12
+ "./config": "./packages/config/src/index.js",
13
+ "./workspace": "./packages/workspace/src/index.js",
14
+ "./workflow": "./packages/workflow/src/index.js",
15
+ "./orchestrator": "./packages/orchestrator/src/index.js",
16
+ "./planner": "./packages/planner/src/index.js",
17
+ "./action": "./packages/action/src/index.js",
18
+ "./risk": "./packages/risk/src/index.js",
19
+ "./review": "./packages/review/src/index.js",
20
+ "./session": "./packages/session/src/index.js",
21
+ "./marker": "./packages/marker/src/index.js",
22
+ "./knowledge": "./packages/knowledge/src/index.js",
23
+ "./context": "./packages/context/src/index.js",
24
+ "./test-utils": "./packages/test-utils/src/index.js",
25
+ "./mcp": "./packages/mcp/src/index.js"
26
+ },
27
+ "bin": {
28
+ "loreli": "./bin/loreli.js"
29
+ },
30
+ "scripts": {
31
+ "pretest": "node --env-file-if-exists=.env scripts/clean-test-repo.js",
32
+ "test": "node --env-file-if-exists=.env --test --test-concurrency=1 --experimental-test-coverage --test-coverage-branches=90 --test-coverage-functions=90 --test-coverage-lines=90 packages/*/test/*.test.js",
33
+ "test:ci": "LORELI_TEST_MODE=unit node --env-file-if-exists=.env --test --test-concurrency=1 packages/*/test/*.test.js",
34
+ "e2e": "node --env-file-if-exists=.env scripts/clean-test-repo.js && node --env-file-if-exists=.env --test --test-concurrency=1 e2e/single/*.test.js e2e/multi/*.test.js",
35
+ "e2e:single": "node --env-file-if-exists=.env scripts/clean-test-repo.js && node --env-file-if-exists=.env --test --test-concurrency=1 e2e/single/*.test.js",
36
+ "e2e:multi": "node --env-file-if-exists=.env scripts/clean-test-repo.js && node --env-file-if-exists=.env --test --test-concurrency=1 e2e/multi/*.test.js",
37
+ "lint:secrets": "npx secretlint \"**/*\"",
38
+ "prepublishOnly": "pnpm lint:secrets",
39
+ "prepare": "node node_modules/pre-commit/install.js && node node_modules/pre-push/install.js"
40
+ },
41
+ "pre-commit": [
42
+ "lint:secrets"
43
+ ],
44
+ "pre-push": [
45
+ "lint:secrets"
11
46
  ],
47
+ "dependencies": {
48
+ "@mcp-layer/cli": "^1.0.0",
49
+ "@modelcontextprotocol/sdk": "^1.26.0",
50
+ "@octokit/rest": "^21.1.1",
51
+ "@secretlint/secretlint-rule-preset-recommend": "^11.3.1",
52
+ "ms": "^2.1.3",
53
+ "mustache": "^4.2.0",
54
+ "secretlint": "^11.3.1",
55
+ "text-hex": "^1.0.0",
56
+ "winston": "^3.17.0",
57
+ "yaml": "^2.8.1"
58
+ },
12
59
  "repository": {
13
60
  "type": "git",
14
- "url": "github.com/3rd-Eden/loreli"
61
+ "url": "https://github.com/3rd-Eden/loreli.git"
62
+ },
63
+ "homepage": "https://www.npmjs.com/package/loreli",
64
+ "engines": {
65
+ "node": ">=24"
15
66
  },
67
+ "files": [
68
+ "bin/",
69
+ "packages/*/src/**",
70
+ "packages/*/README.md",
71
+ "packages/README.md",
72
+ "packages/*/prompts/",
73
+ "packages/mcp/scaffolding/",
74
+ "packages/mcp/instructions.md",
75
+ "LICENSE",
76
+ "README.md"
77
+ ],
16
78
  "license": "MIT",
17
- "author": "Arnout Kazemier",
18
- "type": "module",
19
- "main": "index.js",
20
- "scripts": {
21
- "test": "echo \"Error: no test specified\" && exit 1"
79
+ "devDependencies": {
80
+ "pre-commit": "^1.2.2",
81
+ "pre-push": "^0.1.4"
22
82
  }
23
83
  }
@@ -0,0 +1,101 @@
1
+ # Package Development Guide
2
+
3
+ This document is for contributors and maintainers working on Loreli internals.
4
+
5
+ For installation, setup, and operating Loreli as a consumer, use the root guide: [`README.md`](../README.md).
6
+
7
+ ## Published Package Documentation
8
+
9
+ Loreli exposes subpath imports (for example, `loreli/mcp`, `loreli/agent`, `loreli/context`) through the root package `exports` map.
10
+ Each exported subpackage has a README under `packages/<name>/README.md`, and these package READMEs are included in the published npm tarball.
11
+
12
+ ## Architecture
13
+
14
+ ```mermaid
15
+ graph TD
16
+ User["User / Parent Agent"] -->|"MCP tools"| Server["loreli/mcp"]
17
+ Server -->|"spawns via tmux"| Claude["Claude Backend"]
18
+ Server -->|"spawns via tmux"| Cursor["Cursor Backend"]
19
+ Server -->|"spawns via tmux"| Codex["Codex Backend"]
20
+ Server --> Orch["loreli/orchestrator"]
21
+ Orch --> Planner["loreli/planner"]
22
+ Orch --> Action["loreli/action"]
23
+ Orch --> Review["loreli/review"]
24
+ Planner -->|"Discussions"| GH["GitHub API"]
25
+ Action -->|"Issues + PRs"| GH
26
+ Review -->|"PR Reviews"| GH
27
+ Server -->|"reads"| Config["loreli/config"]
28
+ Config -->|"loreli.yml"| GH
29
+ Server -->|"loreli/hub"| GH
30
+ Claude -->|"interactive"| GH
31
+ Cursor -->|"interactive, multi-provider"| GH
32
+ Codex -->|"interactive"| GH
33
+ ```
34
+
35
+ ## Subpackage Index
36
+
37
+ | Import | Purpose | Documentation |
38
+ |--------|---------|---------------|
39
+ | `loreli/mcp` | MCP server with orchestration tools, workflow engine, and CLI entry | [`packages/mcp/README.md`](./mcp/README.md) |
40
+ | `loreli/orchestrator` | Agent lifecycle coordination, reactor polling, stall detection | [`packages/orchestrator/README.md`](./orchestrator/README.md) |
41
+ | `loreli/config` | Configuration loading, schema, and layered resolution | [`packages/config/README.md`](./config/README.md) |
42
+ | `loreli/hub` | Provider-agnostic git hosting abstraction for GitHub APIs | [`packages/hub/README.md`](./hub/README.md) |
43
+ | `loreli/agent` | Agent lifecycle and backend implementations | [`packages/agent/README.md`](./agent/README.md) |
44
+ | `loreli/identity` | Theme-driven agent identity generation and pairing | [`packages/identity/README.md`](./identity/README.md) |
45
+ | `loreli/tmux` | Node.js wrapper for tmux session and pane management | [`packages/tmux/README.md`](./tmux/README.md) |
46
+ | `loreli/workspace` | Worktree lifecycle, workspace scaffolding, and git operations | [`packages/workspace/README.md`](./workspace/README.md) |
47
+ | `loreli/session` | Persistent detached session storage and lifecycle | [`packages/session/README.md`](./session/README.md) |
48
+ | `loreli/log` | Structured logging with per-session and per-agent context | [`packages/log/README.md`](./log/README.md) |
49
+ | `loreli/workflow` | Base abstractions for role workflows and prompt rendering | [`packages/workflow/README.md`](./workflow/README.md) |
50
+ | `loreli/planner` | Planning workflow via GitHub Discussions | [`packages/planner/README.md`](./planner/README.md) |
51
+ | `loreli/action` | Issue claim-work PR execution workflow | [`packages/action/README.md`](./action/README.md) |
52
+ | `loreli/review` | PR review workflow, signoff, and merge gating | [`packages/review/README.md`](./review/README.md) |
53
+ | `loreli/risk` | Risk assessment workflow for pull requests | [`packages/risk/README.md`](./risk/README.md) |
54
+ | `loreli/context` | Read-path context resolution across git and GitHub artifacts | [`packages/context/README.md`](./context/README.md) |
55
+ | `loreli/knowledge` | Feedback classification and promotion workflow | [`packages/knowledge/README.md`](./knowledge/README.md) |
56
+ | `loreli/marker` | Machine-readable marker parsing and serialization | [`packages/marker/README.md`](./marker/README.md) |
57
+ | `loreli/test-utils` | Shared test helpers and integration test guards | [`packages/test-utils/README.md`](./test-utils/README.md) |
58
+
59
+ ## Development
60
+
61
+ The example below demonstrates the standard setup and test commands for developing Loreli. This matters because local development requires a working dependency install and consistent test expectations, and you should expect each command to complete without errors with tests reporting pass or skip states.
62
+
63
+ ```bash
64
+ # Setup
65
+ cp .env.example .env # then fill in GITHUB_TOKEN
66
+ pnpm install
67
+
68
+ # Run tests (includes --experimental-test-coverage)
69
+ pnpm test
70
+
71
+ # Run a specific package's tests
72
+ node --test packages/tmux/test/index.test.js
73
+
74
+ # Run end-to-end tests (requires LORELI_TEST_REPO)
75
+ pnpm e2e
76
+ ```
77
+
78
+ For CI or local unit-only runs, set `LORELI_TEST_MODE=unit` and use `pnpm test:ci`. This matters because it disables backend-dependent agentic suites, and you should expect those suites to be skipped with a clear reason.
79
+
80
+ Secret scanning runs automatically on commit, git push, and npm publish. This matters because it keeps credentials from ever reaching npm or GitHub, and the expected behavior is a failed commit/push/publish with a secretlint report if anything suspicious is detected. The example below shows the manual scan command; you should expect a clean exit on success or a secretlint report when issues are found.
81
+
82
+ ```bash
83
+ pnpm lint:secrets
84
+ ```
85
+
86
+ ## Test Utilities
87
+
88
+ Integration-test helpers live in [`packages/test-utils/README.md`](./test-utils/README.md).
89
+
90
+ Key shared values used by tests:
91
+
92
+ | Name | Source | Purpose |
93
+ |------|--------|---------|
94
+ | `TEST_REPO` | `LORELI_TEST_REPO` env var | Target GitHub repo for integration/e2e tests. |
95
+ | `TEST_SESSION` | `loreli-test-<pid>` | Per-process tmux session name used by test agents. |
96
+
97
+ Common usage pattern:
98
+
99
+ 1. Guard tests with `skipWithoutToken()` and `skipWithoutTestRepo()`.
100
+ 2. Create real clients/helpers with `createHub()` and `createConfig()`.
101
+ 3. Use `resetTestSession()`/`killTestSession()` around suites that spawn agents.
@@ -0,0 +1,98 @@
1
+ # loreli/action
2
+
3
+ Action workflow for Loreli's orchestration pipeline. Extends the `Workflow` base class to manage action agents — issue claiming, work dispatch, rework from human feedback, and the claim protocol.
4
+
5
+ ## Research Findings
6
+
7
+ No existing npm packages cover a claim-work-review cycle with cross-provider pairing. This is domain-specific to Loreli's orchestration model.
8
+
9
+ ## API Reference
10
+
11
+ ### `ActionWorkflow` (extends Workflow)
12
+
13
+ ```js
14
+ import { ActionWorkflow } from 'loreli/action';
15
+
16
+ const action = new ActionWorkflow(orchestrator, hub);
17
+ ```
18
+
19
+ #### Static Properties
20
+
21
+ | Property | Value | Description |
22
+ |----------|-------|-------------|
23
+ | `role` | `'action'` | Agent role this workflow manages |
24
+ | `template` | `prompts/action.md` | Mustache template for action prompts |
25
+
26
+ ### Methods
27
+
28
+ #### `action.work(repo)` → Promise\<Array\<{issue, agent, reviewer}\>\>
29
+
30
+ Dispatch the work cycle to action agents. Fetches unclaimed issues, assigns them round-robin to action agents, pairs each with an opposing-provider reviewer (auto-enlisting if needed), claims issues on GitHub, and renders/sends the action prompt.
31
+
32
+ ```js
33
+ const assignments = await action.work('owner/repo');
34
+ // [{ issue: 42, agent: 'optimus-0', reviewer: 'megatron-0' }]
35
+ ```
36
+
37
+ #### `action.rework(repo, pr, feedback)` → Promise\<{reworkAgent, hitlAt}\>
38
+
39
+ Handle human feedback on an HITL PR by dispatching to an existing action agent or spawning a fresh one. Renders the HITL section of the action prompt.
40
+
41
+ #### `action.claim(repo, number)` → Promise\<void\>
42
+
43
+ Post a claim comment on an issue using the hub's scoped identity.
44
+
45
+ #### `action.claimant(repo, number)` → Promise\<string|null\>
46
+
47
+ Determine who claimed an issue by parsing claim comments.
48
+
49
+ ### Reactor Handlers
50
+
51
+ The action workflow registers a `dispatch` handler that runs on every reactor tick. It checks for unclaimed `loreli`-labeled issues and dispatches available existing agents (`spawned` or `dormant`). Agent creation is handled by orchestrator scaling (`scale()`), not by `dispatch()` itself.
52
+
53
+ The reactive cycle is: spawn on demand, do work, get reaped when idle. On the next tick, if more work exists, another agent spawns.
54
+
55
+ ### Foreign Claim Gating
56
+
57
+ When `dispatch()` encounters an issue claimed by an agent not in the local orchestrator's map, it classifies the claim before acting:
58
+
59
+ | `_stale()` result | Meaning | Action |
60
+ |-------------------|---------|--------|
61
+ | `false` | Agent is local and active | Skip — already being worked |
62
+ | `true` | Agent was locally killed/shut down, or is dormant | Release claim immediately |
63
+ | `'foreign'` | Agent belongs to another orchestrator | Run proof-of-life protocol |
64
+
65
+ For foreign claims, `_checkForeignClaim()` runs the four-gate eviction protocol (see root README) before releasing. This prevents an orchestrator restart from duplicating work that another orchestrator's agents are still actively performing.
66
+
67
+ ### Circuit Breaker
68
+
69
+ The `_dispatch()` handler includes a circuit breaker to prevent infinite retry loops. After `maxClaims` (default 3) releases on a single issue, the issue is labeled `loreli:blocked` + `loreli:needs-attention` and skipped on all subsequent ticks.
70
+
71
+ The circuit breaker counts `release` markers only after the most recent **high-water mark** — either a `circuit-breaker` marker (embedded in the escalation comment) or a `restart` marker (posted by the review workflow's `_restartAction()`). This ensures:
72
+
73
+ - **System-initiated restarts** (dead action agent → `_restartAction()` posts `restart`) automatically reset the counter.
74
+ - **Human unblock** (remove `loreli:blocked` label) works correctly — the escalation comment's `circuit-breaker` marker serves as the high-water mark, so zero releases exist after it.
75
+
76
+ The escalation comment includes step-by-step guidance for humans: check closed PRs for failure patterns, review the issue description, update acceptance criteria, and remove the `loreli:blocked` label to retry.
77
+
78
+ ### Restart Marker
79
+
80
+ The `restart` marker (`<!-- loreli:restart agent="..." -->`) is recognized by `claimant()` as a claim release (same as `release`) but also resets the circuit breaker counter. It is posted by the review workflow's `_restartAction()` when a dead action agent is detected during feedback forwarding.
81
+
82
+ ## Errors
83
+
84
+ | Error | When | Resolution |
85
+ |-------|------|------------|
86
+ | `No action agents available` | work() called with no action agents and no backends discovered | Ensure at least one backend CLI is on PATH |
87
+
88
+ ## Autonomous Operation
89
+
90
+ Action agents run in headless tmux panes with no human operator. The `Workflow.render()` method automatically prepends a shared autonomous-mode preamble to every rendered prompt, instructing agents to never ask clarifying questions, skip interactive skills, and proceed with best judgment. See the `loreli/workflow` README for details on the preamble.
91
+
92
+ The orchestrator's 3-tier stall detection (`monitor()`) acts as a safety net: agents that stall despite these directives receive a nudge at 1x timeout, a warning at 2x, and are killed at 3x. See the `loreli/orchestrator` README for details.
93
+
94
+ ## Scope Boundary
95
+
96
+ **In scope**: Issue claiming, work dispatch, rework, action prompt rendering, claim protocol.
97
+
98
+ **Out of scope**: PR review (review package), planning (planner package), agent lifecycle (orchestrator).