@delorenj/pjangler 1.1.5 → 1.2.2
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/.mise/scripts/link-agentfiles.sh +9 -0
- package/dist/index.js +1492 -358
- package/dist/mcp-server.js +2391 -290
- package/package.json +5 -2
- package/templates/commonproject/.mise/scripts/create-plane-project.sh +26 -0
- package/templates/commonproject/copier.yml +2 -0
- package/templates/commonproject/template/.agents/hooks/README.md +151 -0
- package/templates/commonproject/template/.agents/hooks/hermes/hindsight-hook.sh +63 -0
- package/templates/commonproject/template/.agents/hooks/hindsight/hindsight-journal-write.sh +327 -0
- package/templates/commonproject/template/.agents/hooks/hindsight/hindsight-recall.sh +180 -0
- package/templates/commonproject/template/.agents/hooks/hindsight/hindsight-retain.sh +74 -0
- package/templates/commonproject/template/.agents/hooks/hindsight/hindsight-session-end.sh +57 -0
- package/templates/commonproject/template/.agents/hooks/hindsight/lib/hindsight-bank.sh +57 -0
- package/templates/commonproject/template/.agents/hooks/hindsight/lib/hindsight-journal.sh +48 -0
- package/templates/commonproject/template/.agents/hooks/hooks.master.json +97 -0
- package/templates/commonproject/template/.agents/hooks/lib/hook-guard.sh +30 -0
- package/templates/commonproject/template/.agents/hooks/lib/local-config.sh +51 -0
- package/templates/commonproject/template/.agents/hooks/reminder-for-skill-check.sh +20 -0
- package/templates/commonproject/template/.agents/hooks/sync.py +618 -0
- package/templates/commonproject/template/.agents/local.example.json +15 -0
- package/templates/commonproject/template/.mise/scripts/hindsight-setup.sh +62 -0
- package/templates/commonproject/template/.mise/scripts/link-project-skills-to-clis.sh +110 -0
- package/templates/commonproject/template/.mise/scripts/unlink-project-skills-from-clis.sh +45 -0
- package/templates/commonproject/template/mise.toml.jinja +42 -0
- package/templates/hermes-agent/.codegraph/daemon.pid +6 -0
- package/templates/hermes-agent/.omo/run-continuation/ses_0e5b28303ffeXxL53hZjKggXDW.json +10 -0
- package/templates/hermes-agent/README.md +16 -14
- package/templates/hermes-agent/copier.yml +7 -25
- package/templates/hermes-agent/docs/architecture.md +16 -18
- package/templates/hermes-agent/docs/fleet-control-plane/README.md +35 -0
- package/templates/hermes-agent/docs/fleet-control-plane/architecture.md +253 -0
- package/templates/hermes-agent/docs/fleet-control-plane/epics-and-stories.md +280 -0
- package/templates/hermes-agent/docs/fleet-control-plane/implementation-readiness-report-2026-06-27.md +118 -0
- package/templates/hermes-agent/docs/fleet-control-plane/prd.md +141 -0
- package/templates/hermes-agent/docs/operations.md +17 -19
- package/templates/hermes-agent/docs/runbooks/runtime-checkpoint-repair.md +17 -13
- package/templates/hermes-agent/docs/{scrum-master → sentinel}/README.md +47 -46
- package/templates/hermes-agent/docs/{scrum-master → sentinel}/architecture.md +39 -38
- package/templates/hermes-agent/docs/{scrum-master → sentinel}/development.md +63 -99
- package/templates/hermes-agent/docs/{scrum-master → sentinel}/providers.md +2 -2
- package/templates/hermes-agent/docs/sentinel.md +18 -0
- package/templates/hermes-agent/install-local.sh +22 -20
- package/templates/hermes-agent/runtime-scaffold/README.md +10 -9
- package/templates/hermes-agent/scripts/backfill-fleet-sot.sh +12 -21
- package/templates/hermes-agent/scripts/fleet-sync.sh +369 -0
- package/templates/hermes-agent/scripts/migrate-unify.sh +252 -0
- package/templates/hermes-agent/scripts/unify-pm.sh +148 -0
- package/templates/hermes-agent/template/.runtime-scaffold/README.md +10 -9
- package/templates/hermes-agent/template/.scripts/01-config.sh +2 -3
- package/templates/hermes-agent/template/.scripts/05-fleet-env.sh +0 -2
- package/templates/hermes-agent/template/.scripts/10-hermes-profile.sh +47 -19
- package/templates/hermes-agent/template/.scripts/20-runtime-repo.sh +71 -27
- package/templates/hermes-agent/template/.scripts/30-telegram.sh +3 -3
- package/templates/hermes-agent/template/.scripts/42-ticket-provider.sh +3 -3
- package/templates/hermes-agent/template/.scripts/70-systemd.sh +48 -43
- package/templates/hermes-agent/template/.scripts/80-registry.sh +2 -2
- package/templates/hermes-agent/template/.scripts/99-summary.sh +3 -4
- package/templates/hermes-agent/template/.scripts/_lib.sh +4 -19
- package/templates/hermes-agent/template/.scripts/checkpoint.sh +36 -0
- package/templates/hermes-agent/template/.scripts/config.example.toml +11 -5
- package/templates/hermes-agent/template/.scripts/{scrum-master/continuous-ticket-sentinel.sh → heartbeat.sh} +84 -31
- package/templates/hermes-agent/template/.scripts/lib/ticket-provider.sh +1 -1
- package/templates/hermes-agent/template/.scripts/providers/plane.sh +9 -3
- package/templates/hermes-agent/template/.scripts/{scrum-master → sentinel}/bin/emit-event.py +5 -5
- package/templates/hermes-agent/template/.scripts/{scrum-master → sentinel}/bin/issue-autonomous-review.sh +6 -6
- package/templates/hermes-agent/template/.scripts/{scrum-master → sentinel}/bin/issue-close-gate.sh +2 -2
- package/templates/hermes-agent/template/.scripts/{scrum-master → sentinel}/docs/autonomous-delegated-review.md +7 -7
- package/templates/hermes-agent/template/.scripts/{scrum-master → sentinel}/docs/bloodbank-events.md +3 -3
- package/templates/hermes-agent/template/.scripts/{scrum-master → sentinel}/docs/continuous-ticket-orchestration.md +6 -6
- package/templates/hermes-agent/template/.scripts/{scrum-master/continuous-ticket-sentinel.prompt.md.jinja → sentinel.prompt.md.jinja} +5 -4
- package/templates/hermes-agent/template/SOUL.md.jinja +3 -6
- package/templates/hermes-agent/template/hermes.jinja +6 -15
- package/templates/hermes-agent/template/role.yaml.jinja +9 -8
- package/templates/commonproject/.claude/commands/bmad/bmb/agents/agent-builder.md +0 -14
- package/templates/commonproject/.claude/commands/bmad/bmb/agents/module-builder.md +0 -14
- package/templates/commonproject/.claude/commands/bmad/bmb/agents/workflow-builder.md +0 -14
- package/templates/commonproject/.claude/commands/bmad/bmb/workflows/agent.md +0 -5
- package/templates/commonproject/.claude/commands/bmad/bmb/workflows/module.md +0 -5
- package/templates/commonproject/.claude/commands/bmad/bmb/workflows/workflow.md +0 -5
- package/templates/commonproject/.claude/commands/bmad/bmm/agents/analyst.md +0 -14
- package/templates/commonproject/.claude/commands/bmad/bmm/agents/architect.md +0 -14
- package/templates/commonproject/.claude/commands/bmad/bmm/agents/dev.md +0 -14
- package/templates/commonproject/.claude/commands/bmad/bmm/agents/pm.md +0 -14
- package/templates/commonproject/.claude/commands/bmad/bmm/agents/quick-flow-solo-dev.md +0 -14
- package/templates/commonproject/.claude/commands/bmad/bmm/agents/sm.md +0 -14
- package/templates/commonproject/.claude/commands/bmad/bmm/agents/tea.md +0 -14
- package/templates/commonproject/.claude/commands/bmad/bmm/agents/tech-writer.md +0 -14
- package/templates/commonproject/.claude/commands/bmad/bmm/agents/ux-designer.md +0 -14
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/check-implementation-readiness.md +0 -5
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/code-review.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/correct-course.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/create-architecture.md +0 -5
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/create-epics-and-stories.md +0 -5
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/create-excalidraw-dataflow.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/create-excalidraw-diagram.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/create-excalidraw-flowchart.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/create-excalidraw-wireframe.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/create-product-brief.md +0 -5
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/create-story.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/create-ux-design.md +0 -5
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/dev-story.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/document-project.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/generate-project-context.md +0 -5
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/prd.md +0 -5
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/quick-dev.md +0 -5
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/quick-spec.md +0 -5
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/research.md +0 -5
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/retrospective.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/sprint-planning.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/sprint-status.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/testarch-atdd.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/testarch-automate.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/testarch-ci.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/testarch-framework.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/testarch-nfr.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/testarch-test-design.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/testarch-test-review.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/testarch-trace.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/workflow-init.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/bmm/workflows/workflow-status.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/cis/agents/brainstorming-coach.md +0 -14
- package/templates/commonproject/.claude/commands/bmad/cis/agents/creative-problem-solver.md +0 -14
- package/templates/commonproject/.claude/commands/bmad/cis/agents/design-thinking-coach.md +0 -14
- package/templates/commonproject/.claude/commands/bmad/cis/agents/innovation-strategist.md +0 -14
- package/templates/commonproject/.claude/commands/bmad/cis/agents/presentation-master.md +0 -14
- package/templates/commonproject/.claude/commands/bmad/cis/agents/storyteller.md +0 -14
- package/templates/commonproject/.claude/commands/bmad/cis/workflows/design-thinking.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/cis/workflows/innovation-strategy.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/cis/workflows/problem-solving.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/cis/workflows/storytelling.md +0 -13
- package/templates/commonproject/.claude/commands/bmad/core/agents/bmad-master.md +0 -14
- package/templates/commonproject/.claude/commands/bmad/core/tasks/index-docs.md +0 -9
- package/templates/commonproject/.claude/commands/bmad/core/tasks/shard-doc.md +0 -9
- package/templates/commonproject/.claude/commands/bmad/core/workflows/brainstorming.md +0 -5
- package/templates/commonproject/.claude/commands/bmad/core/workflows/party-mode.md +0 -5
- package/templates/commonproject/.claude/commands/bmad/custom/workflows/ticket-lifecycle.md +0 -5
- package/templates/hermes-agent/docs/scrum-master-sentinel.md +0 -17
- package/templates/hermes-agent/template/.scripts/75-scrum-master.sh +0 -117
- package/templates/hermes-agent/template/.scripts/90-chain-scrum-master.sh +0 -45
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Heartbeat sentinel development guide
|
|
2
2
|
|
|
3
|
-
This guide covers the day-to-day work of changing the
|
|
3
|
+
This guide covers the day-to-day work of changing the heartbeat sentinel engine:
|
|
4
4
|
how to edit it, how to validate changes locally, how to provision and propagate
|
|
5
|
-
it, and what to watch out for. It closes with the
|
|
6
|
-
|
|
7
|
-
[Architecture](architecture.md) first.
|
|
5
|
+
it, and what to watch out for. It closes with the open roadmap. Read the
|
|
6
|
+
[handoff overview](README.md) and [Architecture](architecture.md) first.
|
|
8
7
|
|
|
9
8
|
## Two doc trees, kept in sync
|
|
10
9
|
|
|
11
10
|
The engine has two documentation trees, and they serve different readers. When
|
|
12
11
|
you change behavior, update both.
|
|
13
12
|
|
|
14
|
-
- `docs/
|
|
13
|
+
- `docs/sentinel/` (this directory) holds the **developer** docs for working
|
|
15
14
|
on the template.
|
|
16
|
-
- `template/.scripts/
|
|
15
|
+
- `template/.scripts/sentinel/docs/` holds the **runtime** protocol docs
|
|
17
16
|
that render into every provisioned project. The running agent reads these at
|
|
18
17
|
run time. They are `autonomous-delegated-review.md`,
|
|
19
18
|
`continuous-ticket-orchestration.md`, and `bloodbank-events.md`.
|
|
20
19
|
|
|
21
20
|
## Making a change
|
|
22
21
|
|
|
23
|
-
Most engine logic lives under `template/.scripts/
|
|
24
|
-
`template/.scripts/providers
|
|
22
|
+
Most engine logic lives under `template/.scripts/sentinel/` and
|
|
23
|
+
`template/.scripts/providers/`, and the heartbeat runner is
|
|
24
|
+
`template/.scripts/heartbeat.sh`. The flow is the same for any change.
|
|
25
25
|
|
|
26
|
-
1. Edit the engine file, the adapter, or the prompt.
|
|
26
|
+
1. Edit the runner, the engine file, the adapter, or the prompt.
|
|
27
27
|
2. Validate locally with the steps in [Validating changes
|
|
28
28
|
locally](#validating-changes-locally).
|
|
29
29
|
3. If you changed behavior, update the runtime protocol docs and these developer
|
|
@@ -32,9 +32,10 @@ Most engine logic lives under `template/.scripts/scrum-master/` and
|
|
|
32
32
|
[Propagating changes](#propagating-changes)).
|
|
33
33
|
|
|
34
34
|
The prompt is a Jinja template,
|
|
35
|
-
`template/.scripts/
|
|
36
|
-
|
|
37
|
-
`{{ ticket_provider }}`. Copier renders
|
|
35
|
+
`template/.scripts/sentinel.prompt.md.jinja` (rendered to
|
|
36
|
+
`.scripts/sentinel.prompt.md`). It uses `{{ display_name }}`,
|
|
37
|
+
`{{ target_repo }}`, `{{ role }}`, and `{{ ticket_provider }}`. Copier renders
|
|
38
|
+
it during provisioning.
|
|
38
39
|
|
|
39
40
|
## Validating changes locally
|
|
40
41
|
|
|
@@ -45,8 +46,8 @@ First, check shell syntax across the engine:
|
|
|
45
46
|
```bash
|
|
46
47
|
for f in template/.scripts/lib/ticket-provider.sh \
|
|
47
48
|
template/.scripts/providers/*.sh \
|
|
48
|
-
template/.scripts/
|
|
49
|
-
template/.scripts/
|
|
49
|
+
template/.scripts/heartbeat.sh \
|
|
50
|
+
template/.scripts/sentinel/bin/*.sh; do
|
|
50
51
|
sh -n "$f" || bash -n "$f" || echo "FAIL $f"
|
|
51
52
|
done
|
|
52
53
|
```
|
|
@@ -80,20 +81,20 @@ optional adapter-based transition without touching a real board.
|
|
|
80
81
|
<summary>Mock-provider end-to-end test</summary>
|
|
81
82
|
|
|
82
83
|
```bash
|
|
83
|
-
T=$(mktemp -d); RD="$T/agents/hermes/
|
|
84
|
-
mkdir -p "$RD/.scripts/lib" "$RD/.scripts/providers" "$RD/.scripts/
|
|
84
|
+
T=$(mktemp -d); RD="$T/agents/hermes/pm"
|
|
85
|
+
mkdir -p "$RD/.scripts/lib" "$RD/.scripts/providers" "$RD/.scripts/sentinel/bin" \
|
|
85
86
|
"$T/_bmad-output/implementation-artifacts/issue-evidence"
|
|
86
87
|
( cd "$T" && git init -q && git config user.email t@t && git config user.name t )
|
|
87
88
|
cp template/.scripts/lib/ticket-provider.sh "$RD/.scripts/lib/"
|
|
88
|
-
cp template/.scripts/
|
|
89
|
-
printf 'repo: demo\nrole:
|
|
89
|
+
cp template/.scripts/sentinel/bin/* "$RD/.scripts/sentinel/bin/"
|
|
90
|
+
printf 'repo: demo\nrole: pm\nagent_id: demo-pm\nticket_provider:\n name: fake\nreconcile:\n grace_hours: 0\n auto_review: true\n' > "$RD/role.yaml"
|
|
90
91
|
printf '#!/usr/bin/env sh\nop="$1"; shift 2>/dev/null||true\ncase "$op" in\n transition) echo "FAKE $1 -> $2" >&2; echo ok;;\n comment) echo okc;; *) echo f;; esac\n' > "$RD/.scripts/providers/fake.sh"
|
|
91
|
-
chmod +x "$RD/.scripts/providers/fake.sh" "$RD/.scripts/
|
|
92
|
+
chmod +x "$RD/.scripts/providers/fake.sh" "$RD/.scripts/sentinel/bin/"*.sh
|
|
92
93
|
EV="$T/_bmad-output/implementation-artifacts/issue-evidence"
|
|
93
94
|
printf '## Issue\n- Worker: codex\n## Acceptance Criteria\n- AC1: done\n## Repo Changes\n- x\n## Verification\n- Command: t\n- Result: pass\n## Ledger Update\n- Ledger updated: yes\n## Known Gaps\n- None\n## Close Recommendation\nClose recommendation: ready\n' > "$EV/TIC-1.md"
|
|
94
95
|
printf '## Reviewer\n- Reviewer agent: rev\n- Independent of implementer: yes\n## Locked Intent Baseline\n- Acceptance criteria source: board\n## Drift Assessment\n- Drift assessment: none\n## Adversarial Findings\n- Critical/high findings: none\n## Decision\n- Decision: accept\n' > "$EV/TIC-1.review.md"
|
|
95
96
|
export BLOODBANK_EVENTS_LOG="$T/e.jsonl"
|
|
96
|
-
bash "$RD/.scripts/
|
|
97
|
+
bash "$RD/.scripts/sentinel/bin/issue-autonomous-review.sh" TIC-1 "$EV/TIC-1.review.md" --close
|
|
97
98
|
rm -rf "$T"
|
|
98
99
|
```
|
|
99
100
|
|
|
@@ -121,12 +122,13 @@ The script:
|
|
|
121
122
|
2. writes a host-correct local `config.toml` (detects the hermes binary, leaves
|
|
122
123
|
cloud fields blank) if one doesn't exist,
|
|
123
124
|
3. lists the boards on the chosen provider and prompts for the one to manage,
|
|
124
|
-
4. provisions the `pm`
|
|
125
|
-
|
|
126
|
-
5. binds the
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
6. installs the
|
|
125
|
+
4. provisions the `pm` role through Copier with all cloud, Telegram, and the
|
|
126
|
+
gateway step skipped,
|
|
127
|
+
5. binds the PM to the existing board (it never creates one — it scrubs the
|
|
128
|
+
provider key from Copier's environment so `42-ticket-provider.sh` skips board
|
|
129
|
+
creation),
|
|
130
|
+
6. installs the PM's heartbeat timer (board-reconciliation sentinel pass + gated
|
|
131
|
+
runtime checkpoint) as a `launchd` agent on macOS or a `systemd` timer on
|
|
130
132
|
Linux,
|
|
131
133
|
7. smoke-tests the board connection through the adapter.
|
|
132
134
|
|
|
@@ -136,18 +138,18 @@ Useful environment overrides (skip the prompts): `HAT_REPO`, `HAT_PROVIDER`,
|
|
|
136
138
|
|
|
137
139
|
This local path does not wire Telegram or email. Those are convenience layers in
|
|
138
140
|
the `pjangler` provisioner, not requirements for a working agent — talk to the
|
|
139
|
-
|
|
140
|
-
timer.
|
|
141
|
+
agent with `agents/hermes/pm/hermes chat "..."` and let the sentinel run on its
|
|
142
|
+
heartbeat timer.
|
|
141
143
|
|
|
142
|
-
## Provisioning
|
|
144
|
+
## Provisioning the PM (manual)
|
|
143
145
|
|
|
144
|
-
To drive Copier directly instead of using `install-local.sh`, provision
|
|
145
|
-
|
|
146
|
+
To drive Copier directly instead of using `install-local.sh`, provision the PM
|
|
147
|
+
with:
|
|
146
148
|
|
|
147
149
|
```bash
|
|
148
150
|
cd /path/to/your-project
|
|
149
|
-
copier copy gh:delorenj/hermes-agent-template ./agents/hermes/
|
|
150
|
-
--data role=
|
|
151
|
+
copier copy gh:delorenj/hermes-agent-template ./agents/hermes/pm \
|
|
152
|
+
--data role=pm \
|
|
151
153
|
--data target_repo=<repo> \
|
|
152
154
|
--data ticket_provider=<linear|plane|trello>
|
|
153
155
|
```
|
|
@@ -172,27 +174,27 @@ script checks its flag and skips cleanly.
|
|
|
172
174
|
| `SKIP_RUNTIME_REPO` | Creating the GitHub runtime repo. |
|
|
173
175
|
| `SKIP_PLANE` | Creating a Plane project. |
|
|
174
176
|
| `SKIP_BLOODBANK` | Installing the BloodBank consumer. |
|
|
175
|
-
| `SKIP_SYSTEMD` | Installing `systemd` units. |
|
|
177
|
+
| `SKIP_SYSTEMD` | Installing `systemd` units (gateway, consumer, heartbeat timer). |
|
|
176
178
|
|
|
177
179
|
For example, a local install that creates no cloud resources:
|
|
178
180
|
|
|
179
181
|
```bash
|
|
180
182
|
SKIP_TELEGRAM=1 SKIP_RUNTIME_REPO=1 SKIP_PLANE=1 SKIP_BLOODBANK=1 \
|
|
181
|
-
copier copy gh:delorenj/hermes-agent-template ./agents/hermes/
|
|
182
|
-
--data role=
|
|
183
|
+
copier copy gh:delorenj/hermes-agent-template ./agents/hermes/pm \
|
|
184
|
+
--data role=pm --data target_repo=<repo> --data ticket_provider=linear
|
|
183
185
|
```
|
|
184
186
|
|
|
185
187
|
After provisioning, set the board binding in
|
|
186
|
-
`agents/hermes/
|
|
187
|
-
to the team key. Make the provider key available to the
|
|
188
|
+
`agents/hermes/pm/role.yaml`. For Linear, set `ticket_provider.team`
|
|
189
|
+
to the team key. Make the provider key available to the heartbeat's environment:
|
|
188
190
|
on Linux through a `systemd` `EnvironmentFile` (for example
|
|
189
191
|
`~/.hermes/<agent_id>.env`); on macOS the `launchd` agent sources that same
|
|
190
192
|
per-agent env file, so write the key there.
|
|
191
193
|
|
|
192
|
-
`SKIP_SYSTEMD` gates
|
|
193
|
-
`70-systemd.sh`. The
|
|
194
|
-
|
|
195
|
-
|
|
194
|
+
`SKIP_SYSTEMD` gates the gateway, consumer, and the fused `heartbeat` timer in
|
|
195
|
+
`70-systemd.sh`. The heartbeat timer is what drives the sentinel pass and the
|
|
196
|
+
gated checkpoint, so a local install that wants the sentinel running must leave
|
|
197
|
+
`SKIP_SYSTEMD` unset (or install the timer afterward).
|
|
196
198
|
|
|
197
199
|
## Propagating changes
|
|
198
200
|
|
|
@@ -203,7 +205,7 @@ and tokens, is preserved while the engine logic refreshes.
|
|
|
203
205
|
|
|
204
206
|
```bash
|
|
205
207
|
cd /path/to/your-project
|
|
206
|
-
copier update ./agents/hermes/
|
|
208
|
+
copier update ./agents/hermes/pm
|
|
207
209
|
```
|
|
208
210
|
|
|
209
211
|
<!-- prettier-ignore -->
|
|
@@ -211,46 +213,18 @@ copier update ./agents/hermes/scrum-master
|
|
|
211
213
|
> `copier update` re-runs the `_tasks` chain. Pass the same `SKIP_*` flags you
|
|
212
214
|
> used at provision time so the update doesn't try to recreate cloud resources.
|
|
213
215
|
|
|
214
|
-
##
|
|
215
|
-
|
|
216
|
-
Drumjangler was the prototype for this engine and the first project cut over to
|
|
217
|
-
it. The cutover used a lean, fully reversible path rather than full Copier
|
|
218
|
-
provisioning, because full provisioning would have created a GitHub repo and
|
|
219
|
-
prompted for a Telegram token.
|
|
220
|
-
|
|
221
|
-
What was done:
|
|
222
|
-
|
|
223
|
-
- The engine was deployed from the template into
|
|
224
|
-
`agents/hermes/scrum-master/`, identical to the source of truth.
|
|
225
|
-
- `role.yaml` was bound to Linear, team `DEL`. The runtime reuses the existing
|
|
226
|
-
`pm` runtime through a symlink,
|
|
227
|
-
`agents/hermes/scrum-master/runtime -> ../pm/runtime`, so the Scrum Master
|
|
228
|
-
shares the Hermes profile and the `LINEAR_API_KEY` wiring from
|
|
229
|
-
`~/.hermes/stemjangler-pm.env`.
|
|
230
|
-
- The Linear adapter was verified live against the real `DEL` board from the
|
|
231
|
-
deployed role.
|
|
232
|
-
- The `systemd` timer
|
|
233
|
-
`hermes-drumjangler-scrum-master-continuous-ticket-sentinel.timer` was
|
|
234
|
-
installed and enabled. The old
|
|
235
|
-
`hermes-stemjangler-pm-continuous-ticket-sentinel.timer` was disabled and
|
|
236
|
-
stopped.
|
|
237
|
-
- The four bespoke `pm`-role sentinel scripts were removed. They're recoverable
|
|
238
|
-
from Git history.
|
|
239
|
-
|
|
240
|
-
To roll back, restore the bespoke scripts from Git, then flip the timers:
|
|
216
|
+
## History: consolidation into the PM heartbeat
|
|
241
217
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
The full cutover record lives in the Drumjangler repo at
|
|
253
|
-
`docs/operations/scrum-master-migration.md`.
|
|
218
|
+
The sentinel began as a bespoke loop on the `pm` role, was briefly extracted into
|
|
219
|
+
a standalone `scrum-master` role with its own `continuous-ticket-sentinel` timer,
|
|
220
|
+
and has now been folded back into the unified PM. Today there is exactly one
|
|
221
|
+
role (`pm`), one engine (under `.scripts/sentinel/`), and one timer
|
|
222
|
+
(`hermes-<agent>-heartbeat.timer`) that fuses the board-reconciliation sentinel
|
|
223
|
+
pass with a gated runtime checkpoint. The old per-agent
|
|
224
|
+
`hermes-<agent>-continuous-ticket-sentinel.timer` and the separate
|
|
225
|
+
`hermes-<agent>-checkpoint.timer` are gone; both are replaced by the single
|
|
226
|
+
`heartbeat` timer. The earlier standalone-role design is recoverable from Git
|
|
227
|
+
history if you ever need to compare.
|
|
254
228
|
|
|
255
229
|
## Known gotchas
|
|
256
230
|
|
|
@@ -271,18 +245,12 @@ These cost real debugging time. Watch for them.
|
|
|
271
245
|
into a variable instead.
|
|
272
246
|
- **Quoting in `python3 -c`.** See the warning in
|
|
273
247
|
[Providers: adding a provider](providers.md#adding-a-provider).
|
|
274
|
-
- **`flock` is Linux-only.** macOS doesn't ship `flock`, so the runner
|
|
275
|
-
back to an atomic `mkdir` lock. Keep both paths working in the runner.
|
|
248
|
+
- **`flock` is Linux-only.** macOS doesn't ship `flock`, so the heartbeat runner
|
|
249
|
+
falls back to an atomic `mkdir` lock. Keep both paths working in the runner.
|
|
276
250
|
- **Plane state is a bare UUID.** The Plane v1 API returns an issue's `state` as
|
|
277
251
|
a UUID with no embedded object, so the adapter must join issues against the
|
|
278
252
|
project's states map. Descriptions are `description_html`, not
|
|
279
253
|
`description_stripped`.
|
|
280
|
-
- **Engine files render for every role.** Copier renders
|
|
281
|
-
`template/.scripts/scrum-master/` and the provider files for all roles, not
|
|
282
|
-
only `scrum-master`. They're inert for other roles because
|
|
283
|
-
`75-scrum-master.sh` self-guards on `role == scrum-master`. Restricting the
|
|
284
|
-
render to the `scrum-master` role with a conditional file path is a cosmetic
|
|
285
|
-
improvement noted in the roadmap.
|
|
286
254
|
|
|
287
255
|
## Open roadmap
|
|
288
256
|
|
|
@@ -298,14 +266,10 @@ The following work is open for the incoming agent, roughly in priority order.
|
|
|
298
266
|
`launchd` agent, the `mkdir` lock, and the assumption that the older Copier
|
|
299
267
|
steps (`10-hermes-profile.sh`, `80-registry.sh`) are Darwin-clean get their
|
|
300
268
|
first real run on a Mac.
|
|
301
|
-
3. **
|
|
302
|
-
|
|
303
|
-
`
|
|
304
|
-
|
|
305
|
-
adapter, and enforcement layers are verified, but the first live `run:full`
|
|
306
|
-
pass with the new prompt is the last thing to watch.
|
|
307
|
-
5. **Restrict engine-file rendering to the `scrum-master` role.** Use a Copier
|
|
308
|
-
conditional file path so other roles don't receive inert engine files.
|
|
269
|
+
3. **Confirm the first full Hermes reconciliation pass on a fresh PM.** The
|
|
270
|
+
heartbeat, adapter, and enforcement layers are verified, but the first live
|
|
271
|
+
`run:full` pass with the rendered prompt on a newly provisioned PM is the
|
|
272
|
+
last thing to watch.
|
|
309
273
|
|
|
310
274
|
## Read next
|
|
311
275
|
|
|
@@ -173,11 +173,11 @@ export LINEAR_API_KEY="$(grep -E '^(export )?LINEAR_API_KEY=' \
|
|
|
173
173
|
~/.hermes/<agent>.env | head -1 | sed -E 's/^(export )?LINEAR_API_KEY=//; s/^"//; s/"$//')"
|
|
174
174
|
|
|
175
175
|
# 2. Stage a role directory bound to the real board.
|
|
176
|
-
T=$(mktemp -d); RD="$T/agents/hermes/
|
|
176
|
+
T=$(mktemp -d); RD="$T/agents/hermes/pm"
|
|
177
177
|
mkdir -p "$RD/.scripts/lib" "$RD/.scripts/providers"
|
|
178
178
|
cp template/.scripts/lib/ticket-provider.sh "$RD/.scripts/lib/"
|
|
179
179
|
cp template/.scripts/providers/linear.sh "$RD/.scripts/providers/"
|
|
180
|
-
printf 'repo: demo\nrole:
|
|
180
|
+
printf 'repo: demo\nrole: pm\nticket_provider:\n name: linear\n team: DEL\n' \
|
|
181
181
|
> "$RD/role.yaml"
|
|
182
182
|
|
|
183
183
|
# 3. Run the read operations.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# The PM's heartbeat sentinel
|
|
2
|
+
|
|
3
|
+
The PM runs a provider-agnostic ticket sentinel out-of-band on its heartbeat
|
|
4
|
+
timer: a board-reconciliation pass with an autonomous adversarial review (act,
|
|
5
|
+
do not wait), fused with a gated runtime checkpoint into a single timer tick.
|
|
6
|
+
The full documentation lives in a dedicated handoff guide.
|
|
7
|
+
|
|
8
|
+
This page is kept as a stable pointer so existing links keep working.
|
|
9
|
+
|
|
10
|
+
## Where the docs live now
|
|
11
|
+
|
|
12
|
+
- [Sentinel handoff overview](sentinel/README.md): start here.
|
|
13
|
+
- [Architecture](sentinel/architecture.md): the heartbeat loop, the provider
|
|
14
|
+
abstraction, and the autonomous adversarial review.
|
|
15
|
+
- [Providers](sentinel/providers.md): the adapter contract and how to add or
|
|
16
|
+
verify a provider.
|
|
17
|
+
- [Development guide](sentinel/development.md): editing, validating,
|
|
18
|
+
provisioning, propagating, and the roadmap.
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env sh
|
|
2
|
-
# Least-friction local install of Hermes PM
|
|
2
|
+
# Least-friction local install of the Hermes PM role into a project.
|
|
3
3
|
#
|
|
4
4
|
# Local-only: no GitHub runtime repo, no Telegram, no NATS/BloodBank, no Plane
|
|
5
|
-
# project creation. It binds the
|
|
5
|
+
# project creation. It binds the PM to a ticket board you already have. The PM
|
|
6
|
+
# runs the continuous ticket sentinel out-of-band on its heartbeat timer
|
|
7
|
+
# (board-reconciliation pass + gated runtime checkpoint, one tick).
|
|
6
8
|
# Works on macOS (launchd) and Linux (systemd).
|
|
7
9
|
#
|
|
8
10
|
# One-liner (from anywhere inside the target project):
|
|
@@ -14,7 +16,7 @@
|
|
|
14
16
|
# Environment overrides (skip the prompts):
|
|
15
17
|
# HAT_REPO=<name> project/repo name (default: basename of CWD)
|
|
16
18
|
# HAT_PROVIDER=linear|plane|trello (default: plane)
|
|
17
|
-
# HAT_ROLES="pm
|
|
19
|
+
# HAT_ROLES="pm" roles to install (default: pm)
|
|
18
20
|
# HAT_DRY_RUN=1 print actions, change nothing
|
|
19
21
|
# Provider creds: LINEAR_API_KEY | PLANE_API_KEY+PLANE_BASE | TRELLO_KEY+TRELLO_TOKEN
|
|
20
22
|
set -eu
|
|
@@ -102,9 +104,9 @@ ask HAT_PROVIDER "Ticket provider (linear|plane|trello)" "plane"
|
|
|
102
104
|
PROVIDER="$HAT_PROVIDER"
|
|
103
105
|
ask HAT_REPO "Project/repo name" "$(basename "$PROJECT_DIR" | tr '[:upper:]' '[:lower:]')"
|
|
104
106
|
REPO="$HAT_REPO"
|
|
105
|
-
|
|
107
|
+
PM_ENV="$HOME/.hermes/${REPO}-pm.env"
|
|
106
108
|
|
|
107
|
-
# These get written into the
|
|
109
|
+
# These get written into the pm role.yaml binding after render.
|
|
108
110
|
# Pre-seed from optional env knobs so the install can run non-interactively.
|
|
109
111
|
TP_WORKSPACE="${HAT_PLANE_WORKSPACE:-}"; TP_PROJECT="${HAT_PLANE_PROJECT:-}"
|
|
110
112
|
TP_TEAM="${HAT_LINEAR_TEAM:-}"; TP_BOARD="${HAT_TRELLO_BOARD:-}"
|
|
@@ -151,10 +153,10 @@ TRELLO_TOKEN=$TRELLO_TOKEN"
|
|
|
151
153
|
*) die "unknown provider: $PROVIDER" ;;
|
|
152
154
|
esac
|
|
153
155
|
|
|
154
|
-
say "4. writing provider credentials to $
|
|
156
|
+
say "4. writing provider credentials to $PM_ENV"
|
|
155
157
|
if [ "${HAT_DRY_RUN:-0}" != "1" ]; then
|
|
156
158
|
mkdir -p "$HOME/.hermes"; umask 077
|
|
157
|
-
printf '%s\n' "$CRED_LINES" > "$
|
|
159
|
+
printf '%s\n' "$CRED_LINES" > "$PM_ENV"
|
|
158
160
|
fi
|
|
159
161
|
|
|
160
162
|
# --- 5. Provision each role with copier (cloud + Telegram + systemd skipped) --
|
|
@@ -162,7 +164,7 @@ fi
|
|
|
162
164
|
# we bind to the existing board below.
|
|
163
165
|
export SKIP_TELEGRAM=1 SKIP_EMAIL=1 SKIP_RUNTIME_REPO=1 SKIP_PLANE=1 \
|
|
164
166
|
SKIP_BLOODBANK=1 SKIP_SYSTEMD=1
|
|
165
|
-
ROLES="${HAT_ROLES:-pm
|
|
167
|
+
ROLES="${HAT_ROLES:-pm}"
|
|
166
168
|
for ROLE in $ROLES; do
|
|
167
169
|
say "5. provisioning role: $ROLE"
|
|
168
170
|
DEST="$PROJECT_DIR/agents/hermes/$ROLE"
|
|
@@ -174,12 +176,12 @@ for ROLE in $ROLES; do
|
|
|
174
176
|
--data target_repo='$REPO' --data role='$ROLE' --data ticket_provider='$PROVIDER'"
|
|
175
177
|
done
|
|
176
178
|
|
|
177
|
-
# --- 6. Bind the
|
|
178
|
-
|
|
179
|
-
if [ -f "$
|
|
180
|
-
say "6. binding
|
|
179
|
+
# --- 6. Bind the PM to the existing board ------------------------------------
|
|
180
|
+
PM_ROLE="$PROJECT_DIR/agents/hermes/pm/role.yaml"
|
|
181
|
+
if [ -f "$PM_ROLE" ] && [ "${HAT_DRY_RUN:-0}" != "1" ]; then
|
|
182
|
+
say "6. binding pm to your $PROVIDER board"
|
|
181
183
|
TP_WORKSPACE="$TP_WORKSPACE" TP_PROJECT="$TP_PROJECT" TP_TEAM="$TP_TEAM" \
|
|
182
|
-
TP_BOARD="$TP_BOARD" PROVIDER="$PROVIDER" python3 - "$
|
|
184
|
+
TP_BOARD="$TP_BOARD" PROVIDER="$PROVIDER" python3 - "$PM_ROLE" <<'PY'
|
|
183
185
|
import os, re, sys, pathlib
|
|
184
186
|
p = pathlib.Path(sys.argv[1]); t = p.read_text()
|
|
185
187
|
def setleaf(text, key, val):
|
|
@@ -196,19 +198,19 @@ PY
|
|
|
196
198
|
fi
|
|
197
199
|
|
|
198
200
|
# --- 7. Smoke test the board connection --------------------------------------
|
|
199
|
-
if [ "${HAT_DRY_RUN:-0}" != "1" ] && [ -f "$
|
|
201
|
+
if [ "${HAT_DRY_RUN:-0}" != "1" ] && [ -f "$PM_ROLE" ]; then
|
|
200
202
|
say "7. smoke test: reading your board through the adapter"
|
|
201
|
-
LIB="$PROJECT_DIR/agents/hermes/
|
|
202
|
-
( set -a; . "$
|
|
203
|
+
LIB="$PROJECT_DIR/agents/hermes/pm/.scripts/lib/ticket-provider.sh"
|
|
204
|
+
( set -a; . "$PM_ENV" 2>/dev/null; set +a
|
|
203
205
|
bash -c '. "$1"; tp resolve && echo " issues: $(tp list_issues | python3 -c "import sys,json;print(len(json.load(sys.stdin)))")"' _ "$LIB" ) \
|
|
204
|
-
|| warn " smoke test failed — check the binding in $
|
|
206
|
+
|| warn " smoke test failed — check the binding in $PM_ROLE and creds in $PM_ENV"
|
|
205
207
|
fi
|
|
206
208
|
|
|
207
209
|
say ""
|
|
208
210
|
say "Done. Talk to the PM: agents/hermes/pm/hermes chat \"status\""
|
|
209
211
|
if [ "$OS" = "Darwin" ]; then
|
|
210
|
-
say "Sentinel (launchd): launchctl list | grep $REPO-
|
|
212
|
+
say "Sentinel (launchd): launchctl list | grep $REPO-pm-heartbeat"
|
|
211
213
|
else
|
|
212
|
-
say "Sentinel (systemd): systemctl --user status hermes-$REPO-
|
|
214
|
+
say "Sentinel (systemd): systemctl --user status hermes-$REPO-pm-heartbeat.timer"
|
|
213
215
|
fi
|
|
214
|
-
say "Provider creds live in: $
|
|
216
|
+
say "Provider creds live in: $PM_ENV"
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
# {{agent_id}} — runtime
|
|
2
2
|
|
|
3
|
-
This is the
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
recoverable across machines.
|
|
3
|
+
This is the HERMES_HOME for the **{{display_name}}** agent. It is git-tracked
|
|
4
|
+
so memory, SOUL evolution, and conversation history are durable across machines
|
|
5
|
+
and recoverable on failure.
|
|
7
6
|
|
|
8
7
|
## What's in here
|
|
9
8
|
|
|
10
9
|
| Path | Tracked? | Purpose |
|
|
11
10
|
| --- | --- | --- |
|
|
12
|
-
| `
|
|
13
|
-
| `config.yaml` | yes | Local config overrides only; shared defaults come from the fleet default |
|
|
11
|
+
| `config.yaml` | yes | Inference + skill config (cloned from global at provision time) |
|
|
14
12
|
| `SOUL.md` | yes | The agent's personality, evolves over time |
|
|
15
13
|
| `memories/MEMORY.md` | yes | The condensed mental-model summary loaded each session |
|
|
16
14
|
| `memories/USER.md` | yes | The operator's persona (Jarad DeLorenzo, ...) |
|
|
@@ -25,11 +23,14 @@ recoverable across machines.
|
|
|
25
23
|
|
|
26
24
|
## Checkpoint cadence
|
|
27
25
|
|
|
28
|
-
-
|
|
26
|
+
- Heartbeat: systemd `--user` timer `hermes-{{agent_id}}-heartbeat.timer`. Each
|
|
27
|
+
tick reconciles the ticket board (the PM's sentinel pass) and then, gated to
|
|
28
|
+
at most once an hour, checkpoints this runtime.
|
|
29
29
|
- On session end: hermes Stop hook (TODO: hook script in `~/.hermes/hooks/`)
|
|
30
30
|
|
|
31
|
-
The
|
|
32
|
-
`git add -A`, commits only if dirty,
|
|
31
|
+
The heartbeat runner lives in the parent's `.scripts/heartbeat.sh`; it calls
|
|
32
|
+
`.scripts/checkpoint.sh` internally, which `git add -A`, commits only if dirty,
|
|
33
|
+
and pushes to `origin`.
|
|
33
34
|
|
|
34
35
|
## Restoring on a new machine
|
|
35
36
|
|
|
@@ -28,8 +28,8 @@ PYEOF
|
|
|
28
28
|
|
|
29
29
|
FLEET_ENV="${HERMES_FLEET_ENV:-$(cfg fleet.fleet_env "$HOME/.hermes/fleet.env")}"
|
|
30
30
|
REGISTRY_FILE="${HERMES_FLEET_REGISTRY_FILE:-$(cfg fleet.registry_file "$HOME/.hermes/agents-registry.yaml")}"
|
|
31
|
-
DEFAULT_BIN="${HERMES_FLEET_BIN:-$(cfg fleet.hermes_bin /
|
|
32
|
-
DEFAULT_REPO="${HERMES_FLEET_REPO:-$(cfg fleet.hermes_repo /
|
|
31
|
+
DEFAULT_BIN="${HERMES_FLEET_BIN:-$(cfg fleet.hermes_bin "$HOME/.hermes/hermes-agent/.venv/bin/hermes")}"
|
|
32
|
+
DEFAULT_REPO="${HERMES_FLEET_REPO:-$(cfg fleet.hermes_repo "$HOME/.hermes/hermes-agent")}"
|
|
33
33
|
DEFAULT_OAUTH_FILE="${HERMES_FLEET_OAUTH_FILE:-$(cfg fleet.oauth_file "$HOME/.hermes/auth.json")}"
|
|
34
34
|
DEFAULT_CODEX_HOME="${HERMES_FLEET_CODEX_HOME:-$(cfg fleet.codex_home "$HOME/.codex")}"
|
|
35
35
|
SCAFFOLD_SRC="$(cd "$(dirname "$0")/../template/.runtime-scaffold" && pwd)"
|
|
@@ -160,7 +160,6 @@ for agent_id, cfg in agents.items():
|
|
|
160
160
|
|
|
161
161
|
project_path = pathlib.Path(cfg.get("project_path") or "")
|
|
162
162
|
role_name = cfg.get("role") or "pm"
|
|
163
|
-
profile_name = cfg.get("profile_name") or agent_id
|
|
164
163
|
alt_role_path = project_path / "_agents" / "hermes" / role_name
|
|
165
164
|
if not (role_path / "hermes").exists() and (alt_role_path / "hermes").exists():
|
|
166
165
|
role_path = alt_role_path
|
|
@@ -188,14 +187,14 @@ for agent_id, cfg in agents.items():
|
|
|
188
187
|
" source \"$FLEET_ENV\"\n"
|
|
189
188
|
"fi\n\n"
|
|
190
189
|
"# Tools we expect on the host\n"
|
|
191
|
-
"HERMES_BIN=\"${HERMES_BIN:-${HERMES_FLEET_BIN
|
|
192
|
-
"HERMES_AGENT_REPO=\"${HERMES_AGENT_REPO:-${HERMES_FLEET_REPO
|
|
190
|
+
"HERMES_BIN=\"${HERMES_BIN:-${HERMES_FLEET_BIN:-$HOME/.hermes/hermes-agent/.venv/bin/hermes}}\"\n"
|
|
191
|
+
"HERMES_AGENT_REPO=\"${HERMES_AGENT_REPO:-${HERMES_FLEET_REPO:-$HOME/.hermes/hermes-agent}}\"\n"
|
|
193
192
|
"HERMES_OAUTH_FILE=\"${HERMES_OAUTH_FILE:-${HERMES_FLEET_OAUTH_FILE:-$HOME/.hermes/auth.json}}\"\n"
|
|
194
193
|
"CODEX_HOME=\"${CODEX_HOME:-${HERMES_FLEET_CODEX_HOME:-$HOME/.codex}}\"\n"
|
|
195
194
|
"# Prefer a scaffold vendored into this agent directory; fall back to legacy template path.\n"
|
|
196
195
|
"RUNTIME_SCAFFOLD_DIR=\"${RUNTIME_SCAFFOLD_DIR:-$ROLE_DIR/.runtime-scaffold}\"\n"
|
|
197
196
|
"if [[ ! -d \"$RUNTIME_SCAFFOLD_DIR\" ]]; then\n"
|
|
198
|
-
" RUNTIME_SCAFFOLD_DIR=\"${HERMES_TEMPLATE_RUNTIME_SCAFFOLD
|
|
197
|
+
" RUNTIME_SCAFFOLD_DIR=\"${HERMES_TEMPLATE_RUNTIME_SCAFFOLD:-$HOME/code/hermes-agent-template/runtime-scaffold}\"\n"
|
|
199
198
|
"fi\n"
|
|
200
199
|
"REGISTRY_FILE=\"${REGISTRY_FILE:-${HERMES_FLEET_REGISTRY_FILE:-$HOME/.hermes/agents-registry.yaml}}\"\n"
|
|
201
200
|
)
|
|
@@ -203,8 +202,8 @@ for agent_id, cfg in agents.items():
|
|
|
203
202
|
lib_text = lib_text.replace(old_block, new_block)
|
|
204
203
|
if "HERMES_OAUTH_FILE=" not in lib_text:
|
|
205
204
|
lib_text = lib_text.replace(
|
|
206
|
-
"HERMES_AGENT_REPO=\"${HERMES_AGENT_REPO:-${HERMES_FLEET_REPO
|
|
207
|
-
"HERMES_AGENT_REPO=\"${HERMES_AGENT_REPO:-${HERMES_FLEET_REPO
|
|
205
|
+
"HERMES_AGENT_REPO=\"${HERMES_AGENT_REPO:-${HERMES_FLEET_REPO:-$HOME/.hermes/hermes-agent}}\"\n",
|
|
206
|
+
"HERMES_AGENT_REPO=\"${HERMES_AGENT_REPO:-${HERMES_FLEET_REPO:-$HOME/.hermes/hermes-agent}}\"\n"
|
|
208
207
|
"HERMES_OAUTH_FILE=\"${HERMES_OAUTH_FILE:-${HERMES_FLEET_OAUTH_FILE:-$HOME/.hermes/auth.json}}\"\n"
|
|
209
208
|
"CODEX_HOME=\"${CODEX_HOME:-${HERMES_FLEET_CODEX_HOME:-$HOME/.codex}}\"\n",
|
|
210
209
|
)
|
|
@@ -226,28 +225,20 @@ for agent_id, cfg in agents.items():
|
|
|
226
225
|
|
|
227
226
|
wrapper.write_text(
|
|
228
227
|
"#!/usr/bin/env bash\n"
|
|
229
|
-
f"# Launcher for {agent_id}. Resolves HERMES_HOME
|
|
228
|
+
f"# Launcher for {agent_id}. Resolves HERMES_HOME to runtime and execs shared fleet Hermes.\n"
|
|
230
229
|
"set -euo pipefail\n\n"
|
|
231
230
|
"ROLE_DIR=\"$(cd \"$(dirname \"$0\")\" && pwd)\"\n"
|
|
232
|
-
"
|
|
231
|
+
"HERMES_HOME=\"$ROLE_DIR/runtime\"\n\n"
|
|
233
232
|
"FLEET_ENV=\"${HERMES_FLEET_ENV:-$HOME/.hermes/fleet.env}\"\n"
|
|
234
233
|
"if [[ -f \"$FLEET_ENV\" ]]; then\n"
|
|
235
234
|
" # shellcheck disable=SC1090\n"
|
|
236
235
|
" source \"$FLEET_ENV\"\n"
|
|
237
236
|
"fi\n\n"
|
|
238
|
-
"HERMES_BIN=\"${HERMES_BIN:-${HERMES_FLEET_BIN
|
|
237
|
+
"HERMES_BIN=\"${HERMES_BIN:-${HERMES_FLEET_BIN:-$HOME/.hermes/hermes-agent/.venv/bin/hermes}}\"\n\n"
|
|
239
238
|
"HERMES_OAUTH_FILE=\"${HERMES_OAUTH_FILE:-${HERMES_FLEET_OAUTH_FILE:-$HOME/.hermes/auth.json}}\"\n"
|
|
240
239
|
"CODEX_HOME=\"${CODEX_HOME:-${HERMES_FLEET_CODEX_HOME:-$HOME/.codex}}\"\n\n"
|
|
241
|
-
"
|
|
242
|
-
|
|
243
|
-
"PROFILE_HOME=\"$FLEET_HOME/profiles/$PROFILE_NAME\"\n"
|
|
244
|
-
"if [[ -d \"$PROFILE_HOME\" ]]; then\n"
|
|
245
|
-
" HERMES_HOME=\"$PROFILE_HOME\"\n"
|
|
246
|
-
"else\n"
|
|
247
|
-
" HERMES_HOME=\"$RUNTIME_HOME\"\n"
|
|
248
|
-
"fi\n\n"
|
|
249
|
-
"if [[ ! -d \"$RUNTIME_HOME\" ]]; then\n"
|
|
250
|
-
" echo \"hermes: runtime submodule not initialized at $RUNTIME_HOME\" >&2\n"
|
|
240
|
+
"if [[ ! -d \"$HERMES_HOME\" ]]; then\n"
|
|
241
|
+
" echo \"hermes: runtime submodule not initialized at $HERMES_HOME\" >&2\n"
|
|
251
242
|
" echo \" fix: git submodule update --init --recursive\" >&2\n"
|
|
252
243
|
" exit 1\n"
|
|
253
244
|
"fi\n\n"
|