@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.
Files changed (139) hide show
  1. package/.mise/scripts/link-agentfiles.sh +9 -0
  2. package/dist/index.js +1492 -358
  3. package/dist/mcp-server.js +2391 -290
  4. package/package.json +5 -2
  5. package/templates/commonproject/.mise/scripts/create-plane-project.sh +26 -0
  6. package/templates/commonproject/copier.yml +2 -0
  7. package/templates/commonproject/template/.agents/hooks/README.md +151 -0
  8. package/templates/commonproject/template/.agents/hooks/hermes/hindsight-hook.sh +63 -0
  9. package/templates/commonproject/template/.agents/hooks/hindsight/hindsight-journal-write.sh +327 -0
  10. package/templates/commonproject/template/.agents/hooks/hindsight/hindsight-recall.sh +180 -0
  11. package/templates/commonproject/template/.agents/hooks/hindsight/hindsight-retain.sh +74 -0
  12. package/templates/commonproject/template/.agents/hooks/hindsight/hindsight-session-end.sh +57 -0
  13. package/templates/commonproject/template/.agents/hooks/hindsight/lib/hindsight-bank.sh +57 -0
  14. package/templates/commonproject/template/.agents/hooks/hindsight/lib/hindsight-journal.sh +48 -0
  15. package/templates/commonproject/template/.agents/hooks/hooks.master.json +97 -0
  16. package/templates/commonproject/template/.agents/hooks/lib/hook-guard.sh +30 -0
  17. package/templates/commonproject/template/.agents/hooks/lib/local-config.sh +51 -0
  18. package/templates/commonproject/template/.agents/hooks/reminder-for-skill-check.sh +20 -0
  19. package/templates/commonproject/template/.agents/hooks/sync.py +618 -0
  20. package/templates/commonproject/template/.agents/local.example.json +15 -0
  21. package/templates/commonproject/template/.mise/scripts/hindsight-setup.sh +62 -0
  22. package/templates/commonproject/template/.mise/scripts/link-project-skills-to-clis.sh +110 -0
  23. package/templates/commonproject/template/.mise/scripts/unlink-project-skills-from-clis.sh +45 -0
  24. package/templates/commonproject/template/mise.toml.jinja +42 -0
  25. package/templates/hermes-agent/.codegraph/daemon.pid +6 -0
  26. package/templates/hermes-agent/.omo/run-continuation/ses_0e5b28303ffeXxL53hZjKggXDW.json +10 -0
  27. package/templates/hermes-agent/README.md +16 -14
  28. package/templates/hermes-agent/copier.yml +7 -25
  29. package/templates/hermes-agent/docs/architecture.md +16 -18
  30. package/templates/hermes-agent/docs/fleet-control-plane/README.md +35 -0
  31. package/templates/hermes-agent/docs/fleet-control-plane/architecture.md +253 -0
  32. package/templates/hermes-agent/docs/fleet-control-plane/epics-and-stories.md +280 -0
  33. package/templates/hermes-agent/docs/fleet-control-plane/implementation-readiness-report-2026-06-27.md +118 -0
  34. package/templates/hermes-agent/docs/fleet-control-plane/prd.md +141 -0
  35. package/templates/hermes-agent/docs/operations.md +17 -19
  36. package/templates/hermes-agent/docs/runbooks/runtime-checkpoint-repair.md +17 -13
  37. package/templates/hermes-agent/docs/{scrum-master → sentinel}/README.md +47 -46
  38. package/templates/hermes-agent/docs/{scrum-master → sentinel}/architecture.md +39 -38
  39. package/templates/hermes-agent/docs/{scrum-master → sentinel}/development.md +63 -99
  40. package/templates/hermes-agent/docs/{scrum-master → sentinel}/providers.md +2 -2
  41. package/templates/hermes-agent/docs/sentinel.md +18 -0
  42. package/templates/hermes-agent/install-local.sh +22 -20
  43. package/templates/hermes-agent/runtime-scaffold/README.md +10 -9
  44. package/templates/hermes-agent/scripts/backfill-fleet-sot.sh +12 -21
  45. package/templates/hermes-agent/scripts/fleet-sync.sh +369 -0
  46. package/templates/hermes-agent/scripts/migrate-unify.sh +252 -0
  47. package/templates/hermes-agent/scripts/unify-pm.sh +148 -0
  48. package/templates/hermes-agent/template/.runtime-scaffold/README.md +10 -9
  49. package/templates/hermes-agent/template/.scripts/01-config.sh +2 -3
  50. package/templates/hermes-agent/template/.scripts/05-fleet-env.sh +0 -2
  51. package/templates/hermes-agent/template/.scripts/10-hermes-profile.sh +47 -19
  52. package/templates/hermes-agent/template/.scripts/20-runtime-repo.sh +71 -27
  53. package/templates/hermes-agent/template/.scripts/30-telegram.sh +3 -3
  54. package/templates/hermes-agent/template/.scripts/42-ticket-provider.sh +3 -3
  55. package/templates/hermes-agent/template/.scripts/70-systemd.sh +48 -43
  56. package/templates/hermes-agent/template/.scripts/80-registry.sh +2 -2
  57. package/templates/hermes-agent/template/.scripts/99-summary.sh +3 -4
  58. package/templates/hermes-agent/template/.scripts/_lib.sh +4 -19
  59. package/templates/hermes-agent/template/.scripts/checkpoint.sh +36 -0
  60. package/templates/hermes-agent/template/.scripts/config.example.toml +11 -5
  61. package/templates/hermes-agent/template/.scripts/{scrum-master/continuous-ticket-sentinel.sh → heartbeat.sh} +84 -31
  62. package/templates/hermes-agent/template/.scripts/lib/ticket-provider.sh +1 -1
  63. package/templates/hermes-agent/template/.scripts/providers/plane.sh +9 -3
  64. package/templates/hermes-agent/template/.scripts/{scrum-master → sentinel}/bin/emit-event.py +5 -5
  65. package/templates/hermes-agent/template/.scripts/{scrum-master → sentinel}/bin/issue-autonomous-review.sh +6 -6
  66. package/templates/hermes-agent/template/.scripts/{scrum-master → sentinel}/bin/issue-close-gate.sh +2 -2
  67. package/templates/hermes-agent/template/.scripts/{scrum-master → sentinel}/docs/autonomous-delegated-review.md +7 -7
  68. package/templates/hermes-agent/template/.scripts/{scrum-master → sentinel}/docs/bloodbank-events.md +3 -3
  69. package/templates/hermes-agent/template/.scripts/{scrum-master → sentinel}/docs/continuous-ticket-orchestration.md +6 -6
  70. package/templates/hermes-agent/template/.scripts/{scrum-master/continuous-ticket-sentinel.prompt.md.jinja → sentinel.prompt.md.jinja} +5 -4
  71. package/templates/hermes-agent/template/SOUL.md.jinja +3 -6
  72. package/templates/hermes-agent/template/hermes.jinja +6 -15
  73. package/templates/hermes-agent/template/role.yaml.jinja +9 -8
  74. package/templates/commonproject/.claude/commands/bmad/bmb/agents/agent-builder.md +0 -14
  75. package/templates/commonproject/.claude/commands/bmad/bmb/agents/module-builder.md +0 -14
  76. package/templates/commonproject/.claude/commands/bmad/bmb/agents/workflow-builder.md +0 -14
  77. package/templates/commonproject/.claude/commands/bmad/bmb/workflows/agent.md +0 -5
  78. package/templates/commonproject/.claude/commands/bmad/bmb/workflows/module.md +0 -5
  79. package/templates/commonproject/.claude/commands/bmad/bmb/workflows/workflow.md +0 -5
  80. package/templates/commonproject/.claude/commands/bmad/bmm/agents/analyst.md +0 -14
  81. package/templates/commonproject/.claude/commands/bmad/bmm/agents/architect.md +0 -14
  82. package/templates/commonproject/.claude/commands/bmad/bmm/agents/dev.md +0 -14
  83. package/templates/commonproject/.claude/commands/bmad/bmm/agents/pm.md +0 -14
  84. package/templates/commonproject/.claude/commands/bmad/bmm/agents/quick-flow-solo-dev.md +0 -14
  85. package/templates/commonproject/.claude/commands/bmad/bmm/agents/sm.md +0 -14
  86. package/templates/commonproject/.claude/commands/bmad/bmm/agents/tea.md +0 -14
  87. package/templates/commonproject/.claude/commands/bmad/bmm/agents/tech-writer.md +0 -14
  88. package/templates/commonproject/.claude/commands/bmad/bmm/agents/ux-designer.md +0 -14
  89. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/check-implementation-readiness.md +0 -5
  90. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/code-review.md +0 -13
  91. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/correct-course.md +0 -13
  92. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/create-architecture.md +0 -5
  93. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/create-epics-and-stories.md +0 -5
  94. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/create-excalidraw-dataflow.md +0 -13
  95. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/create-excalidraw-diagram.md +0 -13
  96. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/create-excalidraw-flowchart.md +0 -13
  97. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/create-excalidraw-wireframe.md +0 -13
  98. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/create-product-brief.md +0 -5
  99. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/create-story.md +0 -13
  100. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/create-ux-design.md +0 -5
  101. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/dev-story.md +0 -13
  102. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/document-project.md +0 -13
  103. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/generate-project-context.md +0 -5
  104. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/prd.md +0 -5
  105. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/quick-dev.md +0 -5
  106. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/quick-spec.md +0 -5
  107. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/research.md +0 -5
  108. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/retrospective.md +0 -13
  109. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/sprint-planning.md +0 -13
  110. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/sprint-status.md +0 -13
  111. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/testarch-atdd.md +0 -13
  112. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/testarch-automate.md +0 -13
  113. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/testarch-ci.md +0 -13
  114. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/testarch-framework.md +0 -13
  115. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/testarch-nfr.md +0 -13
  116. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/testarch-test-design.md +0 -13
  117. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/testarch-test-review.md +0 -13
  118. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/testarch-trace.md +0 -13
  119. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/workflow-init.md +0 -13
  120. package/templates/commonproject/.claude/commands/bmad/bmm/workflows/workflow-status.md +0 -13
  121. package/templates/commonproject/.claude/commands/bmad/cis/agents/brainstorming-coach.md +0 -14
  122. package/templates/commonproject/.claude/commands/bmad/cis/agents/creative-problem-solver.md +0 -14
  123. package/templates/commonproject/.claude/commands/bmad/cis/agents/design-thinking-coach.md +0 -14
  124. package/templates/commonproject/.claude/commands/bmad/cis/agents/innovation-strategist.md +0 -14
  125. package/templates/commonproject/.claude/commands/bmad/cis/agents/presentation-master.md +0 -14
  126. package/templates/commonproject/.claude/commands/bmad/cis/agents/storyteller.md +0 -14
  127. package/templates/commonproject/.claude/commands/bmad/cis/workflows/design-thinking.md +0 -13
  128. package/templates/commonproject/.claude/commands/bmad/cis/workflows/innovation-strategy.md +0 -13
  129. package/templates/commonproject/.claude/commands/bmad/cis/workflows/problem-solving.md +0 -13
  130. package/templates/commonproject/.claude/commands/bmad/cis/workflows/storytelling.md +0 -13
  131. package/templates/commonproject/.claude/commands/bmad/core/agents/bmad-master.md +0 -14
  132. package/templates/commonproject/.claude/commands/bmad/core/tasks/index-docs.md +0 -9
  133. package/templates/commonproject/.claude/commands/bmad/core/tasks/shard-doc.md +0 -9
  134. package/templates/commonproject/.claude/commands/bmad/core/workflows/brainstorming.md +0 -5
  135. package/templates/commonproject/.claude/commands/bmad/core/workflows/party-mode.md +0 -5
  136. package/templates/commonproject/.claude/commands/bmad/custom/workflows/ticket-lifecycle.md +0 -5
  137. package/templates/hermes-agent/docs/scrum-master-sentinel.md +0 -17
  138. package/templates/hermes-agent/template/.scripts/75-scrum-master.sh +0 -117
  139. package/templates/hermes-agent/template/.scripts/90-chain-scrum-master.sh +0 -45
@@ -1,29 +1,29 @@
1
- # Scrum Master development guide
1
+ # Heartbeat sentinel development guide
2
2
 
3
- This guide covers the day-to-day work of changing the Scrum Master engine:
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 record of the Drumjangler
6
- cutover and the open roadmap. Read the [handoff overview](README.md) and
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/scrum-master/` (this directory) holds the **developer** docs for working
13
+ - `docs/sentinel/` (this directory) holds the **developer** docs for working
15
14
  on the template.
16
- - `template/.scripts/scrum-master/docs/` holds the **runtime** protocol docs
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/scrum-master/` and
24
- `template/.scripts/providers/`. The flow is the same for any change.
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/scrum-master/continuous-ticket-sentinel.prompt.md.jinja`. It
36
- uses `{{ display_name }}`, `{{ target_repo }}`, `{{ role }}`, and
37
- `{{ ticket_provider }}`. Copier renders it during provisioning.
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/scrum-master/continuous-ticket-sentinel.sh \
49
- template/.scripts/scrum-master/bin/*.sh; do
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/scrum-master"
84
- mkdir -p "$RD/.scripts/lib" "$RD/.scripts/providers" "$RD/.scripts/scrum-master/bin" \
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/scrum-master/bin/* "$RD/.scripts/scrum-master/bin/"
89
- printf 'repo: demo\nrole: scrum-master\nagent_id: demo-sm\nticket_provider:\n name: fake\nscrum_master:\n grace_hours: 0\n auto_review: true\n' > "$RD/role.yaml"
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/scrum-master/bin/"*.sh
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/scrum-master/bin/issue-autonomous-review.sh" TIC-1 "$EV/TIC-1.review.md" --close
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` and `scrum-master` roles through Copier with all cloud,
125
- Telegram, and `systemd`/gateway steps skipped,
126
- 5. binds the Scrum Master to the existing board (it never creates one — it
127
- scrubs the provider key from Copier's environment so `42-ticket-provider.sh`
128
- skips board creation),
129
- 6. installs the sentinel as a `launchd` agent on macOS or a `systemd` timer on
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
- agents with `agents/hermes/pm/hermes chat "..."` and let the sentinel run on its
140
- timer.
141
+ agent with `agents/hermes/pm/hermes chat "..."` and let the sentinel run on its
142
+ heartbeat timer.
141
143
 
142
- ## Provisioning a Scrum Master (manual)
144
+ ## Provisioning the PM (manual)
143
145
 
144
- To drive Copier directly instead of using `install-local.sh`, provision a
145
- standalone Scrum Master with:
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/scrum-master \
150
- --data role=scrum-master \
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/scrum-master \
182
- --data role=scrum-master --data target_repo=<repo> --data ticket_provider=linear
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/scrum-master/role.yaml`. For Linear, set `ticket_provider.team`
187
- to the team key. Make the provider key available to the sentinel's environment:
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 only the gateway, consumer, and checkpoint units in
193
- `70-systemd.sh`. The sentinel scheduler itself is installed by
194
- `75-scrum-master.sh`, which picks `launchd` on macOS and `systemd` on Linux
195
- regardless of that flag.
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/scrum-master
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
- ## The Drumjangler cutover
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
- ```bash
243
- git checkout <previous-commit> -- \
244
- agents/hermes/pm/.scripts/continuous-ticket-sentinel.sh \
245
- agents/hermes/pm/.scripts/75-continuous-ticket-sentinel.sh \
246
- agents/hermes/pm/.scripts/run-adversarial-review.sh \
247
- agents/hermes/pm/continuous-ticket-sentinel.prompt.md
248
- systemctl --user enable --now hermes-stemjangler-pm-continuous-ticket-sentinel.timer
249
- systemctl --user disable --now hermes-drumjangler-scrum-master-continuous-ticket-sentinel.timer
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 falls
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. **Give the Drumjangler Scrum Master its own runtime repo.** It currently
302
- reuses the `pm` runtime through a symlink. Re-provision with
303
- `SKIP_TELEGRAM=1` and a dedicated runtime repo, then replace the symlink.
304
- 4. **Confirm the first full Hermes pass after a cutover.** Heartbeat,
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/scrum-master"
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: scrum-master\nticket_provider:\n name: linear\n team: DEL\n' \
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 + Scrum Master roles into a project.
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 Scrum Master to a ticket board you already have.
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 scrum-master" roles to install (default: both)
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
- SM_ENV="$HOME/.hermes/${REPO}-scrum-master.env"
107
+ PM_ENV="$HOME/.hermes/${REPO}-pm.env"
106
108
 
107
- # These get written into the scrum-master role.yaml binding after render.
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 $SM_ENV"
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" > "$SM_ENV"
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 scrum-master}"
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 Scrum Master to the existing board --------------------------
178
- SM_ROLE="$PROJECT_DIR/agents/hermes/scrum-master/role.yaml"
179
- if [ -f "$SM_ROLE" ] && [ "${HAT_DRY_RUN:-0}" != "1" ]; then
180
- say "6. binding scrum-master to your $PROVIDER board"
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 - "$SM_ROLE" <<'PY'
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 "$SM_ROLE" ]; then
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/scrum-master/.scripts/lib/ticket-provider.sh"
202
- ( set -a; . "$SM_ENV" 2>/dev/null; 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 $SM_ROLE and creds in $SM_ENV"
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-scrum-master"
212
+ say "Sentinel (launchd): launchctl list | grep $REPO-pm-heartbeat"
211
213
  else
212
- say "Sentinel (systemd): systemctl --user status hermes-$REPO-scrum-master-continuous-ticket-sentinel.timer"
214
+ say "Sentinel (systemd): systemctl --user status hermes-$REPO-pm-heartbeat.timer"
213
215
  fi
214
- say "Provider creds live in: $SM_ENV"
216
+ say "Provider creds live in: $PM_ENV"
@@ -1,16 +1,14 @@
1
1
  # {{agent_id}} — runtime
2
2
 
3
- This is the durable runtime for the **{{display_name}}** agent. The named
4
- Hermes profile `{{profile_name}}` points here from `~/.hermes/profiles/{{profile_name}}`,
5
- so Hermes sees an ordinary profile while this repo stays git-tracked and
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
- | `profile.yaml` | yes | Opts this profile into inheriting config from default |
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
- - Hourly: systemd `--user` timer `hermes-{{agent_id}}-checkpoint.timer`
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 checkpoint script lives in the parent's `.scripts/checkpoint.sh`. It
32
- `git add -A`, commits only if dirty, and pushes to `origin`.
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 /home/delorenj/code/hermes-agent/.venv/bin/hermes)}"
32
- DEFAULT_REPO="${HERMES_FLEET_REPO:-$(cfg fleet.hermes_repo /home/delorenj/code/hermes-agent)}"
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:-/home/delorenj/code/hermes-agent/.venv/bin/hermes}}\"\n"
192
- "HERMES_AGENT_REPO=\"${HERMES_AGENT_REPO:-${HERMES_FLEET_REPO:-/home/delorenj/code/hermes-agent}}\"\n"
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:-/home/delorenj/code/hermes-agent-template/runtime-scaffold}\"\n"
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:-/home/delorenj/code/hermes-agent}}\"\n",
207
- "HERMES_AGENT_REPO=\"${HERMES_AGENT_REPO:-${HERMES_FLEET_REPO:-/home/delorenj/code/hermes-agent}}\"\n"
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 through the fleet profile when available.\n"
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
- "RUNTIME_HOME=\"$ROLE_DIR/runtime\"\n\n"
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:-/home/delorenj/code/hermes-agent/.venv/bin/hermes}}\"\n\n"
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
- "FLEET_HOME=\"${HERMES_FLEET_HOME:-$HOME/.hermes}\"\n"
242
- f"PROFILE_NAME=\"${{HERMES_PROFILE_NAME:-{profile_name}}}\"\n"
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"