@delorenj/pjangler 1.2.4 → 1.2.8
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/dist/index.js +797 -737
- package/dist/mcp-server.js +753 -683
- package/package.json +1 -1
- package/templates/commonproject/AGENTS.md +3 -3
- package/templates/commonproject/README.md +12 -11
- package/templates/commonproject/copier.yml +58 -10
- package/templates/commonproject/mise.toml +3 -3
- package/templates/commonproject/template/.agents/hooks/sync.py +12 -1
- package/templates/commonproject/template/.agents/local.example.json +3 -1
- package/templates/commonproject/template/.project.json.jinja +13 -6
- package/templates/commonproject/template/mise.toml.jinja +8 -4
- package/templates/hermes-agent/README.md +8 -8
- package/templates/hermes-agent/copier.yml +3 -4
- package/templates/hermes-agent/docs/architecture.md +4 -4
- package/templates/hermes-agent/docs/operations.md +2 -2
- package/templates/hermes-agent/docs/sentinel/README.md +6 -8
- package/templates/hermes-agent/docs/sentinel/architecture.md +2 -1
- package/templates/hermes-agent/docs/sentinel/development.md +13 -12
- package/templates/hermes-agent/docs/sentinel/providers.md +12 -32
- package/templates/hermes-agent/install-local.sh +6 -13
- package/templates/hermes-agent/template/.scripts/42-ticket-provider.sh +14 -37
- package/templates/hermes-agent/template/.scripts/70-systemd.sh +2 -0
- package/templates/hermes-agent/template/.scripts/lib/ticket-provider.sh +6 -2
- package/templates/hermes-agent/template/.scripts/sentinel/docs/autonomous-delegated-review.md +2 -2
- package/templates/hermes-agent/template/.scripts/sentinel/docs/continuous-ticket-orchestration.md +1 -1
- package/templates/hermes-agent/template/.scripts/sentinel.prompt.md.jinja +6 -1
- package/templates/hermes-agent/template/SOUL.md.jinja +9 -3
- package/templates/hermes-agent/template/role.yaml.jinja +3 -6
- package/templates/hermes-agent/template/.scripts/40-plane.sh +0 -51
- package/templates/hermes-agent/template/.scripts/providers/linear.sh +0 -176
package/package.json
CHANGED
|
@@ -20,7 +20,7 @@ CommonProject/
|
|
|
20
20
|
│ ├── .agentvibes/ # AgentVibes config
|
|
21
21
|
│ ├── .mise/tasks/ # File-based mise tasks
|
|
22
22
|
│ ├── .scripts/ # Post-generation utilities
|
|
23
|
-
│ │ └── setup-plane.py # Creates
|
|
23
|
+
│ │ └── setup-plane.py # Creates/links ticket provider board + ticket_provider block in .project.json
|
|
24
24
|
│ ├── AGENTS.md.jinja # Generated project's agent SSOT
|
|
25
25
|
│ ├── CLAUDE.md # Symlink → AGENTS.md
|
|
26
26
|
│ ├── GEMINI.md # Symlink → AGENTS.md
|
|
@@ -46,7 +46,7 @@ Root-level files describe the template itself. Files in `template/` are what Cop
|
|
|
46
46
|
Only two questions asked: `project_name` and `project_description`. Everything else is derived or automated:
|
|
47
47
|
- `project_slug` derived from project_name
|
|
48
48
|
- `user_name` / `user_skill_level` hardcoded for BMAD config
|
|
49
|
-
-
|
|
49
|
+
- Ticket board created or linked via post-generation task
|
|
50
50
|
- .gitignore copied from ~/.config/git/ignore
|
|
51
51
|
- git init + initial commit run automatically
|
|
52
52
|
|
|
@@ -55,7 +55,7 @@ Only two questions asked: `project_name` and `project_description`. Everything e
|
|
|
55
55
|
After rendering, Copier automatically:
|
|
56
56
|
1. Copies .gitignore from ~/.config/git/ignore
|
|
57
57
|
2. Makes scripts executable
|
|
58
|
-
3. Runs setup-plane.py (creates
|
|
58
|
+
3. Runs setup-plane.py (creates/links the ticket board, writes the ticket_provider block in .project.json)
|
|
59
59
|
4. Runs git init + git add -A + git commit
|
|
60
60
|
|
|
61
61
|
### BMAD System
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# CommonProject
|
|
2
2
|
|
|
3
|
-
Copier template for creating new 33GOD ecosystem components with BMAD methodology,
|
|
3
|
+
Copier template for creating new 33GOD ecosystem components with BMAD methodology, ticket-provider enforcement, and multi-agent development tooling.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- **Language Support**: Python, TypeScript, Rust
|
|
8
8
|
- **Event-Driven Architecture**: Optional [Bloodbank](https://github.com/delorenj/Bloodbank) integration
|
|
9
|
-
- **
|
|
10
|
-
- **Ticket Enforcement**: Git hooks enforce
|
|
9
|
+
- **Ticket Provider Integration**: `.project.json` records Plane or Trello board bindings
|
|
10
|
+
- **Ticket Enforcement**: Git hooks enforce configured ticket-provider requirements
|
|
11
11
|
- [TODO] **BMAD Integration**: Full BMAD methodology structure by auto running `npx bmad-method@latest install`
|
|
12
12
|
- [TODO] Multiple-choice selection for different workflows: BMAD, GSD, GoogleAgentSkills, None.
|
|
13
13
|
- **Containerization**: Optional Docker + Docker Compose
|
|
@@ -25,7 +25,7 @@ uv tool install copier
|
|
|
25
25
|
# Or with pip
|
|
26
26
|
pip install copier
|
|
27
27
|
|
|
28
|
-
# Set up
|
|
28
|
+
# Set up a provider key if you want automated board creation/linking
|
|
29
29
|
export PLANE_API_KEY="your-plane-api-key"
|
|
30
30
|
OR
|
|
31
31
|
[TODO] export PLANE_API_KEY=op://VaultName/Key/Field
|
|
@@ -36,14 +36,14 @@ OR
|
|
|
36
36
|
|
|
37
37
|
### Option 1: Automated Init (Recommended)
|
|
38
38
|
|
|
39
|
-
[TODO] One command handles everything:
|
|
39
|
+
[TODO] One command handles everything: ticket board creation/linking + Copier template:
|
|
40
40
|
|
|
41
41
|
> TASK - Implement the following:
|
|
42
42
|
> Currently, I have to run `copier copy --trust ~/code CommonProject .` globally, or `mise run init-project` while in the CommonProject source dir - but this is not ideal.
|
|
43
43
|
> I would rather run `commonProject .` globally.
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
|
-
# Interactive wizard - creates
|
|
46
|
+
# Interactive wizard - creates/links the configured ticket board automatically
|
|
47
47
|
mise run init-project
|
|
48
48
|
|
|
49
49
|
# Or non-interactive (uses defaults)
|
|
@@ -56,7 +56,7 @@ mise run init-project-non-interactive
|
|
|
56
56
|
The wizard will:
|
|
57
57
|
|
|
58
58
|
1. Ask for project details (name, description, type)
|
|
59
|
-
2. Create the
|
|
59
|
+
2. Create or link the configured ticket board
|
|
60
60
|
3. Run Copier with all answers pre-filled
|
|
61
61
|
4. Output next steps
|
|
62
62
|
|
|
@@ -83,9 +83,10 @@ The template asks for:
|
|
|
83
83
|
- **Project Slug**: Directory/package name (auto-generated from name)
|
|
84
84
|
- **Description**: One-sentence project description
|
|
85
85
|
|
|
86
|
-
###
|
|
86
|
+
### Ticket Provider Integration
|
|
87
87
|
|
|
88
|
-
- **
|
|
88
|
+
- **Provider**: Plane or Trello
|
|
89
|
+
- **Workspace**: Provider workspace slug when applicable (Plane default: 33god)
|
|
89
90
|
- **Project Name**
|
|
90
91
|
- **Project Identifier**: 2+ character ticket prefix (e.g., HOLO, VERN)
|
|
91
92
|
|
|
@@ -110,10 +111,10 @@ The template asks for:
|
|
|
110
111
|
git commit -m "Initial commit from template"
|
|
111
112
|
```
|
|
112
113
|
|
|
113
|
-
3. **Create
|
|
114
|
+
3. **Create or Claim Ticket**
|
|
114
115
|
|
|
115
116
|
```bash
|
|
116
|
-
# Create
|
|
117
|
+
# Create or claim a ticket in the configured provider
|
|
117
118
|
# Move to "In Progress"
|
|
118
119
|
git checkout -b <IDENTIFIER>-123-initial-setup
|
|
119
120
|
```
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
#
|
|
4
4
|
# Generic base project template. Creates a project skeleton with:
|
|
5
5
|
# - BMAD methodology (pre-initialized)
|
|
6
|
-
# -
|
|
6
|
+
# - Ticket-provider metadata (Plane or Trello)
|
|
7
7
|
# - mise environment management
|
|
8
8
|
# - CLI coder configs (Claude, Codex, Gemini, etc.)
|
|
9
9
|
|
|
@@ -30,16 +30,15 @@ project_description:
|
|
|
30
30
|
help: One-line description
|
|
31
31
|
default: ""
|
|
32
32
|
|
|
33
|
-
# Ticket board provider for this project.
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
# the
|
|
33
|
+
# Ticket board provider for this project. Plane boards can be created before
|
|
34
|
+
# Copier runs; Trello boards are linked by id/url. The board identity is
|
|
35
|
+
# persisted into .project.json so it is the single source of truth shared with
|
|
36
|
+
# the hermes-agent template's agents.
|
|
37
37
|
ticket_provider:
|
|
38
38
|
type: str
|
|
39
39
|
help: Ticket board provider this project's board lives in
|
|
40
40
|
default: plane
|
|
41
41
|
choices:
|
|
42
|
-
Linear: linear
|
|
43
42
|
Plane: plane
|
|
44
43
|
Trello: trello
|
|
45
44
|
|
|
@@ -50,8 +49,7 @@ project_slug:
|
|
|
50
49
|
default: "{{ project_name | lower | replace(' ', '-') | replace('_', '-') }}"
|
|
51
50
|
when: false
|
|
52
51
|
|
|
53
|
-
#
|
|
54
|
-
# created. Defaults keep a bare `copier copy` rendering valid (empty binding).
|
|
52
|
+
# Back-compat aliases kept for existing pjangler/CommonProject callers.
|
|
55
53
|
plane_workspace:
|
|
56
54
|
type: str
|
|
57
55
|
default: "33god"
|
|
@@ -72,6 +70,24 @@ plane_base:
|
|
|
72
70
|
default: "https://plane.delo.sh"
|
|
73
71
|
when: false
|
|
74
72
|
|
|
73
|
+
# Provider-agnostic board binding — supplied by pjangler's --data values after
|
|
74
|
+
# the board is created or linked. Defaults keep a bare `copier copy` rendering
|
|
75
|
+
# valid, and fall back to the legacy plane_* aliases above.
|
|
76
|
+
board_id:
|
|
77
|
+
type: str
|
|
78
|
+
default: "{{ plane_project_id }}"
|
|
79
|
+
when: false
|
|
80
|
+
|
|
81
|
+
board_url:
|
|
82
|
+
type: str
|
|
83
|
+
default: ""
|
|
84
|
+
when: false
|
|
85
|
+
|
|
86
|
+
ticket_workspace:
|
|
87
|
+
type: str
|
|
88
|
+
default: "{{ plane_workspace if ticket_provider == 'plane' else '' }}"
|
|
89
|
+
when: false
|
|
90
|
+
|
|
75
91
|
# Drives conditional blocks in rendered files (e.g. _.python.venv in mise.toml).
|
|
76
92
|
# Not asked interactively; init-project.sh can override via --data-file.
|
|
77
93
|
primary_language:
|
|
@@ -79,8 +95,41 @@ primary_language:
|
|
|
79
95
|
default: python
|
|
80
96
|
when: false
|
|
81
97
|
|
|
82
|
-
#
|
|
98
|
+
# Whether to scaffold the project-scoped agent-hooks + skill fan-out layer
|
|
99
|
+
# (.agents/hooks + the mise enter/leave wiring that injects into each agent CLI's
|
|
100
|
+
# per-user config). Defaults true so a bare `copier copy` still gets it. pjangler
|
|
101
|
+
# passes `--data agent_hooks_layer=false` when the machine already runs a GLOBAL
|
|
102
|
+
# agent-hooks install (~/.agents/hooks) — so a fresh project never re-injects the
|
|
103
|
+
# same hooks into shared per-user configs like ~/.codex or ~/.kimi-code.
|
|
104
|
+
agent_hooks_layer:
|
|
105
|
+
type: bool
|
|
106
|
+
default: true
|
|
107
|
+
when: false
|
|
83
108
|
|
|
109
|
+
# When agent_hooks_layer is false, omit the project-scoped hook tree + skill-link
|
|
110
|
+
# scripts entirely (the mise.toml wiring is already gated inside the template).
|
|
111
|
+
# The `.copier-noop-never-matches` sentinel keeps every pattern non-empty when the
|
|
112
|
+
# layer is enabled, which copier requires.
|
|
113
|
+
_exclude:
|
|
114
|
+
- "copier.yml"
|
|
115
|
+
- "~*"
|
|
116
|
+
- "*.py[co]"
|
|
117
|
+
- "__pycache__"
|
|
118
|
+
- ".git"
|
|
119
|
+
- ".DS_Store"
|
|
120
|
+
- ".svn"
|
|
121
|
+
- "{% if agent_hooks_layer %}.copier-noop-never-matches{% else %}.agents/hooks{% endif %}"
|
|
122
|
+
- "{% if agent_hooks_layer %}.copier-noop-never-matches{% else %}.agents/hooks/**{% endif %}"
|
|
123
|
+
- "{% if agent_hooks_layer %}.copier-noop-never-matches{% else %}.agents/local.example.json{% endif %}"
|
|
124
|
+
- "{% if agent_hooks_layer %}.copier-noop-never-matches{% else %}.mise/scripts/link-project-skills-to-clis.sh{% endif %}"
|
|
125
|
+
- "{% if agent_hooks_layer %}.copier-noop-never-matches{% else %}.mise/scripts/unlink-project-skills-from-clis.sh{% endif %}"
|
|
126
|
+
|
|
127
|
+
# --- Post-generation tasks ---
|
|
128
|
+
#
|
|
129
|
+
# NOTE: intentionally does NOT run `mise trust`. Trusting the repo fires the mise
|
|
130
|
+
# `[hooks].enter` array, which (when the agent-hooks layer is present) injects
|
|
131
|
+
# into the caller's shared per-user CLI configs. Scaffolding must never mutate
|
|
132
|
+
# global state as a side effect — the operator trusts/enters the repo themselves.
|
|
84
133
|
_tasks:
|
|
85
134
|
- "cp ~/.config/git/ignore .gitignore 2>/dev/null || echo '# Add ignores here' > .gitignore"
|
|
86
135
|
# Ensure secrets + per-dev agent-hook/skill overrides are ignored (appended after the base ignore).
|
|
@@ -89,4 +138,3 @@ _tasks:
|
|
|
89
138
|
- "ln -sf AGENTS.md GEMINI.md"
|
|
90
139
|
# Stamp the repo's absolute path into .project.json (the SOT) post-render.
|
|
91
140
|
- "python3 -c \"import json,os,pathlib; p=pathlib.Path('.project.json'); d=json.loads(p.read_text()); d['repo_path']=os.getcwd(); p.write_text(json.dumps(d,indent=2)+chr(10))\""
|
|
92
|
-
- "mise trust"
|
|
@@ -17,11 +17,11 @@ patterns = ["AGENTS.md"]
|
|
|
17
17
|
task = "link-agentfiles"
|
|
18
18
|
|
|
19
19
|
[tasks]
|
|
20
|
-
# Project initialization - creates
|
|
21
|
-
init-project = { run = ".mise/scripts/init-project.sh", description = "Initialize new 33GOD project with
|
|
20
|
+
# Project initialization - creates/links ticket board + runs Copier
|
|
21
|
+
init-project = { run = ".mise/scripts/init-project.sh", description = "Initialize new 33GOD project with ticket provider + Copier" }
|
|
22
22
|
init-project-non-interactive = { run = ".mise/scripts/init-project.sh --non-interactive", description = "Non-interactive project init" }
|
|
23
23
|
|
|
24
|
-
# Direct Plane project creation
|
|
24
|
+
# Direct Plane project creation helper
|
|
25
25
|
create-plane-project = { run = ".mise/scripts/create-plane-project.sh", description = "Create a Plane project and output ID" }
|
|
26
26
|
|
|
27
27
|
# Template testing
|
|
@@ -71,17 +71,28 @@ def load_local() -> dict:
|
|
|
71
71
|
Note: individual disabled HOOKS are enforced at RUNTIME by lib/hook-guard.sh
|
|
72
72
|
(so even Claude's committed hooks honor them); this only needs disabled
|
|
73
73
|
AGENTS, which gate install. CAF_HOOKS_SKIP_CODEX=1 is an env shortcut.
|
|
74
|
+
|
|
75
|
+
`defer_to_global` (under either `hooks` or `skills`) means "I already run
|
|
76
|
+
these hooks from a global agent system" — so the shared per-user injections
|
|
77
|
+
(codex/kimi/hermes) are suppressed and actively removed. Claude's committed
|
|
78
|
+
repo settings are harmless and left in place.
|
|
74
79
|
"""
|
|
75
80
|
disabled_agents: set[str] = set()
|
|
81
|
+
defer_to_global = False
|
|
76
82
|
p = REPO_ROOT / ".agents" / "local.json"
|
|
77
83
|
if p.exists():
|
|
78
84
|
try:
|
|
79
85
|
data = json.loads(p.read_text() or "{}")
|
|
80
|
-
|
|
86
|
+
hooks_cfg = data.get("hooks") or {}
|
|
87
|
+
skills_cfg = data.get("skills") or {}
|
|
88
|
+
disabled_agents = set(hooks_cfg.get("disabled_agents") or [])
|
|
89
|
+
defer_to_global = bool(hooks_cfg.get("defer_to_global")) or bool(skills_cfg.get("defer_to_global"))
|
|
81
90
|
except (json.JSONDecodeError, OSError) as exc:
|
|
82
91
|
warn(f"ignoring malformed .agents/local.json: {exc}")
|
|
83
92
|
if os.environ.get("CAF_HOOKS_SKIP_CODEX") == "1":
|
|
84
93
|
disabled_agents.add("codex")
|
|
94
|
+
if defer_to_global:
|
|
95
|
+
disabled_agents.update({"codex", "kimi", "hermes"})
|
|
85
96
|
return {"disabled_agents": disabled_agents}
|
|
86
97
|
|
|
87
98
|
|
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
"$disabled_help": "Hook ids from .agents/hooks/hooks.master.json: skill-check-reminder, hindsight-recall, hindsight-retain, hindsight-session-end. Listed ids are skipped at runtime across ALL agents.",
|
|
5
5
|
"disabled": [],
|
|
6
6
|
"$disabled_agents_help": "Agent keys: claude, codex, kimi, hermes. Listed agents are NOT installed (codex/kimi/hermes injections are skipped/removed). Claude's hooks are committed and can't be fully removed per-dev — disable them individually via `disabled` instead.",
|
|
7
|
-
"disabled_agents": []
|
|
7
|
+
"disabled_agents": [],
|
|
8
|
+
"$defer_to_global_help": "Set true if you already run these hooks from a GLOBAL agent system (~/.agents/hooks). When true, sync.py suppresses AND removes the shared per-user injections (codex/kimi/hermes) so a project never double-injects into ~/.codex / ~/.kimi-code; Claude's committed repo settings are left in place. Implied by skills.defer_to_global. On a machine with a global install, pjangler skips scaffolding this whole layer, so you rarely need to set this by hand.",
|
|
9
|
+
"defer_to_global": false
|
|
8
10
|
},
|
|
9
11
|
"skills": {
|
|
10
12
|
"$disabled_help": "Skill directory names under .agents/skills/. Listed skills are NOT symlinked into any agent CLI dir for you, and are pruned from your managed mirrors.",
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
{%
|
|
2
|
-
{% set
|
|
1
|
+
{% set ticket_board_id = board_id | default(plane_project_id) -%}
|
|
2
|
+
{% set ticket_board_url = board_url | default('') -%}
|
|
3
|
+
{% set workspace = ticket_workspace | default(plane_workspace if ticket_provider == 'plane' else '') -%}
|
|
4
|
+
{% if ticket_board_url -%}
|
|
5
|
+
{% set resolved_board_url = ticket_board_url -%}
|
|
6
|
+
{% elif ticket_provider == 'plane' and ticket_board_id -%}
|
|
7
|
+
{% set resolved_board_url = plane_base ~ '/' ~ workspace ~ '/projects/' ~ ticket_board_id ~ '/issues/' -%}
|
|
8
|
+
{% elif ticket_provider == 'trello' and ticket_board_id -%}
|
|
9
|
+
{% set resolved_board_url = 'https://trello.com/b/' ~ ticket_board_id -%}
|
|
3
10
|
{% else -%}
|
|
4
|
-
{% set
|
|
11
|
+
{% set resolved_board_url = '' -%}
|
|
5
12
|
{% endif -%}
|
|
6
13
|
{
|
|
7
14
|
"project_name": {{ project_name | tojson }},
|
|
@@ -10,10 +17,10 @@
|
|
|
10
17
|
"repo_path": "",
|
|
11
18
|
"ticket_provider": {
|
|
12
19
|
"type": {{ ticket_provider | tojson }},
|
|
13
|
-
"workspace": {{
|
|
20
|
+
"workspace": {{ workspace | tojson }},
|
|
14
21
|
"identifier": {{ project_identifier | tojson }},
|
|
15
|
-
"board_id": {{
|
|
16
|
-
"board_url": {{
|
|
22
|
+
"board_id": {{ ticket_board_id | tojson }},
|
|
23
|
+
"board_url": {{ resolved_board_url | tojson }}
|
|
17
24
|
},
|
|
18
25
|
"agents": {}
|
|
19
26
|
}
|
|
@@ -16,27 +16,31 @@ enter = [
|
|
|
16
16
|
"{% raw %}{{config_root}}{% endraw %}/.mise/scripts/link-agentfiles.sh",
|
|
17
17
|
"op inject -i .env.op > .env",
|
|
18
18
|
"{% raw %}{{config_root}}{% endraw %}/.mise/scripts/codegraph.sh",
|
|
19
|
+
{%- if agent_hooks_layer %}
|
|
19
20
|
"{% raw %}{{config_root}}{% endraw %}/.mise/scripts/link-project-skills-to-clis.sh",
|
|
20
21
|
"{% raw %}{{config_root}}{% endraw %}/.agents/hooks/sync.py --install --quiet",
|
|
22
|
+
{%- endif %}
|
|
21
23
|
]
|
|
24
|
+
{%- if agent_hooks_layer %}
|
|
22
25
|
leave = [
|
|
23
26
|
"{% raw %}{{config_root}}{% endraw %}/.mise/scripts/unlink-project-skills-from-clis.sh",
|
|
24
27
|
"{% raw %}{{config_root}}{% endraw %}/.agents/hooks/sync.py --uninstall --quiet",
|
|
25
28
|
]
|
|
29
|
+
{%- endif %}
|
|
26
30
|
|
|
27
31
|
[[watch_files]]
|
|
28
32
|
patterns = ["AGENTS.md"]
|
|
29
33
|
task = "link-agentfiles"
|
|
30
|
-
|
|
34
|
+
{% if agent_hooks_layer %}
|
|
31
35
|
# Re-fan-out the agent hooks whenever the single source of truth changes.
|
|
32
36
|
[[watch_files]]
|
|
33
37
|
patterns = [".agents/hooks/hooks.master.json"]
|
|
34
38
|
task = "hooks-sync"
|
|
35
|
-
|
|
39
|
+
{% endif %}
|
|
36
40
|
[tasks.link-agentfiles]
|
|
37
41
|
description = "Symlink all agent files to AGENTS.md"
|
|
38
42
|
run = "{% raw %}{{config_root}}{% endraw %}/.mise/scripts/link-agentfiles.sh"
|
|
39
|
-
|
|
43
|
+
{% if agent_hooks_layer %}
|
|
40
44
|
# --- Project-scoped agent hooks + skill fan-out (see .agents/hooks/README.md) ---
|
|
41
45
|
|
|
42
46
|
[tasks.hooks-sync]
|
|
@@ -62,7 +66,7 @@ run = "{% raw %}{{config_root}}{% endraw %}/.mise/scripts/unlink-project-skills-
|
|
|
62
66
|
[tasks.skills-relink]
|
|
63
67
|
description = "Re-fan the project skill set to all CLIs"
|
|
64
68
|
run = "{% raw %}{{config_root}}{% endraw %}/.mise/scripts/link-project-skills-to-clis.sh"
|
|
65
|
-
|
|
69
|
+
{% endif %}
|
|
66
70
|
[tasks.hindsight-setup]
|
|
67
71
|
description = "Provision this dev's shared project Hindsight key from 1Password into .env (op inject)"
|
|
68
72
|
run = "{% raw %}{{config_root}}{% endraw %}/.mise/scripts/hindsight-setup.sh"
|
|
@@ -11,7 +11,7 @@ memory/state checkpointing.
|
|
|
11
11
|
| What it scaffolds | A new top-level project | An agent role inside an existing project |
|
|
12
12
|
| Copier target | `./my-new-project/` | `./agents/hermes/<role>/` |
|
|
13
13
|
| Asks | project name + description | role + purpose + tone |
|
|
14
|
-
| Post-gen artifacts |
|
|
14
|
+
| Post-gen artifacts | Ticket board binding, bmad init, mise tasks | Ticket board binding, Telegram bot wiring, agent-hm-* runtime repo, systemd units |
|
|
15
15
|
|
|
16
16
|
CommonProject runs first to create the umbrella project. hermes-agent-template
|
|
17
17
|
runs second (for each agent role you want) to drop agents into it.
|
|
@@ -20,8 +20,8 @@ runs second (for each agent role you want) to drop agents into it.
|
|
|
20
20
|
|
|
21
21
|
The template provisions a single Hermes role per invocation. The `pm` role
|
|
22
22
|
handles project management and triage, and also runs the continuous ticket
|
|
23
|
-
sentinel out-of-band: a provider-agnostic board-reconciliation pass (
|
|
24
|
-
|
|
23
|
+
sentinel out-of-band: a provider-agnostic board-reconciliation pass (Plane or
|
|
24
|
+
Trello) with an autonomous adversarial review (act, do not wait). The
|
|
25
25
|
sentinel runs as the PM's **heartbeat** — a fused systemd timer tick that does
|
|
26
26
|
the reconciliation pass and then a gated runtime checkpoint. (There is no
|
|
27
27
|
separate `scrum-master` role; its duties folded into the PM heartbeat.)
|
|
@@ -47,7 +47,7 @@ The template will:
|
|
|
47
47
|
5. Populate it with the runtime scaffold (config.yaml, SOUL.md, memories, consumer.py)
|
|
48
48
|
6. Add it as a git submodule at `agents/hermes/pm/runtime/` (== HERMES_HOME)
|
|
49
49
|
7. Prompt for a BotFather token, store it in `runtime/.env`
|
|
50
|
-
8. Create
|
|
50
|
+
8. Create or bind the configured ticket board
|
|
51
51
|
9. Install systemd `--user` units: gateway, consumer, heartbeat timer (reconcile + checkpoint)
|
|
52
52
|
10. Append the agent to `~/.hermes/agents-registry.yaml`
|
|
53
53
|
|
|
@@ -138,14 +138,14 @@ to force re-run:
|
|
|
138
138
|
|
|
139
139
|
```bash
|
|
140
140
|
cd agents/hermes/pm
|
|
141
|
-
rm .scripts/.done-
|
|
142
|
-
|
|
141
|
+
rm .scripts/.done-42-ticket-provider
|
|
142
|
+
SKIP_SYSTEMD=1 ./.scripts/42-ticket-provider.sh
|
|
143
143
|
```
|
|
144
144
|
|
|
145
145
|
## Retiring an agent
|
|
146
146
|
|
|
147
147
|
(TODO: ship `retire.sh` in v1.1)
|
|
148
148
|
|
|
149
|
-
Manual: stop systemd units, `hermes profile delete`, archive the
|
|
150
|
-
|
|
149
|
+
Manual: stop systemd units, `hermes profile delete`, archive the ticket board
|
|
150
|
+
if the provider supports archival, `/deletebot` in BotFather, archive the
|
|
151
151
|
`agent-hm-*` runtime repo, remove the registry entry.
|
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
# 1. Renders agents/hermes/<role>/{role.yaml, SOUL.md, hermes, .scripts/}
|
|
13
13
|
# 2. Creates a per-agent runtime repo gh:delorenj/agent-hm-<repo>-<role>
|
|
14
14
|
# 3. Submodules it at agents/hermes/<role>/runtime/ (this is HERMES_HOME)
|
|
15
|
-
# 4. Creates
|
|
15
|
+
# 4. Creates or binds the configured ticket board
|
|
16
16
|
# 6. Prompts for a BotFather Telegram token, stores in runtime/.env
|
|
17
17
|
# 7. Installs a Bloodbank consumer + heartbeat timer (reconcile + checkpoint)
|
|
18
18
|
# 8. Appends to ~/.hermes/agents-registry.yaml
|
|
19
19
|
#
|
|
20
|
-
# Environment-specific defaults (Hermes binary path, runtime repo owner,
|
|
21
|
-
#
|
|
20
|
+
# Environment-specific defaults (Hermes binary path, runtime repo owner, ticket
|
|
21
|
+
# provider defaults, NATS endpoint, skills dir, …) are NOT hardcoded — they live in
|
|
22
22
|
# ~/.config/hermes-agent-template/config.toml, seeded from config.example.toml on
|
|
23
23
|
# first run. Edit that file to retarget the template for a different machine/user.
|
|
24
24
|
|
|
@@ -59,7 +59,6 @@ ticket_provider:
|
|
|
59
59
|
help: "Ticket system this agent's board lives in"
|
|
60
60
|
default: plane
|
|
61
61
|
choices:
|
|
62
|
-
"Linear": linear
|
|
63
62
|
"Plane": plane
|
|
64
63
|
"Trello": trello
|
|
65
64
|
|
|
@@ -92,11 +92,11 @@ happen to share a token, the second one's startup fails fast. The N×M cost
|
|
|
92
92
|
(N BotFather sessions per fleet) is the price we accept for zero custom
|
|
93
93
|
routing code.
|
|
94
94
|
|
|
95
|
-
## One
|
|
95
|
+
## One Ticket Board Per Repo
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
The configured ticket board is the natural unit of work isolation. The PM owns
|
|
98
|
+
one board per repo and routes worker agents through that shared source of truth,
|
|
99
|
+
so decisions, filters, and review state stay coherent.
|
|
100
100
|
|
|
101
101
|
## Bloodbank wiring
|
|
102
102
|
|
|
@@ -29,7 +29,7 @@ invocations).
|
|
|
29
29
|
| 10 hermes profile | `hermes profile create <repo>-<role> --clone --no-alias` + mirror skills/plugins/hooks from default + symlink canonical runtime skills (`delonet-conventions`, `delonet-dotenv`, `hermes-pm-template-maintenance`, `hindsight`, `subagent-driven-development`) from `/home/delorenj/.agents/skills`; PM roles also seed `VOX_URL` in profile `.env` | n/a |
|
|
30
30
|
| 20 runtime repo | Create gh:delorenj/agent-hm-<repo>-<role> (private), push scaffold from role-local `.runtime-scaffold/`, submodule-add into ./runtime/, symlink ~/.hermes/profiles/<id> → runtime; PM roles also link the Voxxy plugin and set `tts.provider: voxxy` | `SKIP_RUNTIME_REPO=1` |
|
|
31
31
|
| 30 telegram | Capture BotFather token, write to runtime/.env, enable hermes-telegram toolset | `SKIP_TELEGRAM=1` |
|
|
32
|
-
|
|
|
32
|
+
| 42 ticket provider | Create or bind the configured ticket board, patch identifier into role.yaml | `SKIP_PLANE=1` |
|
|
33
33
|
| 60 bloodbank | Install consumer (renders from scaffold w/ agent values), health-check NATS, install nats-py via uv if missing | `SKIP_BLOODBANK=1` |
|
|
34
34
|
| 70 systemd | Install user units: gateway, consumer, heartbeat timer (board-reconciliation sentinel pass + gated runtime checkpoint, one tick) | `SKIP_SYSTEMD=1` |
|
|
35
35
|
| 80 registry | Append entry to ~/.hermes/agents-registry.yaml | n/a |
|
|
@@ -187,7 +187,7 @@ systemctl --user disable --now hermes-${AGENT}-heartbeat.timer
|
|
|
187
187
|
# that's what you want!)
|
|
188
188
|
hermes profile delete ${AGENT}
|
|
189
189
|
|
|
190
|
-
# 3. Archive
|
|
190
|
+
# 3. Archive the ticket board if the provider supports archival
|
|
191
191
|
PROJECT_ID=$(python3 -c "import yaml,pathlib; print(yaml.safe_load(pathlib.Path.home().joinpath('.hermes/agents-registry.yaml').read_text())['agents']['${AGENT}']['plane']['project_id'])")
|
|
192
192
|
curl -X POST "https://plane.delo.sh/api/v1/workspaces/33god/projects/${PROJECT_ID}/archive/" \
|
|
193
193
|
-H "X-API-Key: ${PLANE_33GOD_API_KEY}"
|
|
@@ -26,7 +26,7 @@ that does the board-reconciliation pass and then a gated runtime checkpoint
|
|
|
26
26
|
`.scripts/sentinel/`.
|
|
27
27
|
|
|
28
28
|
It talks to the ticket board through a pluggable adapter, so the same engine
|
|
29
|
-
runs on
|
|
29
|
+
runs on Plane or Trello. The engine lives once in this template (the
|
|
30
30
|
single source of truth) and propagates to every deployment with
|
|
31
31
|
`copier update`.
|
|
32
32
|
|
|
@@ -37,8 +37,6 @@ The following is true as of June 1, 2026.
|
|
|
37
37
|
- The engine, the provider abstraction, and the autonomous adversarial-review
|
|
38
38
|
enforcement are built, syntax-clean, and validated offline with a mock
|
|
39
39
|
provider.
|
|
40
|
-
- The **Linear** adapter is verified live against a real board (a real
|
|
41
|
-
`DEL` team: `resolve`, `list_issues` returning 93 issues, and `get_issue`).
|
|
42
40
|
- The **Plane** adapter is verified live against a real workspace
|
|
43
41
|
(`resolve`, `list_issues`, `get_issue`, `comment`, and a
|
|
44
42
|
`transition` to `completed` on a disposable issue).
|
|
@@ -54,7 +52,7 @@ For a local, single-machine install (no GitHub runtime repo, no Telegram, no
|
|
|
54
52
|
NATS), use the one-command bootstrap. From inside the target project:
|
|
55
53
|
|
|
56
54
|
```bash
|
|
57
|
-
export PLANE_API_KEY=<key> # or
|
|
55
|
+
export PLANE_API_KEY=<key> # or TRELLO_KEY + TRELLO_TOKEN
|
|
58
56
|
curl -fsSL https://raw.githubusercontent.com/delorenj/hermes-agent-template/main/install-local.sh | sh
|
|
59
57
|
```
|
|
60
58
|
|
|
@@ -66,7 +64,7 @@ macOS). See [Development guide: local install](development.md#local-install-one-
|
|
|
66
64
|
<!-- prettier-ignore -->
|
|
67
65
|
> [!IMPORTANT]
|
|
68
66
|
> Full (non-local) provisioning is outward-facing. It can create a GitHub
|
|
69
|
-
> runtime repo, a Telegram bot, and a
|
|
67
|
+
> runtime repo, a Telegram bot, and a ticket board, and the Telegram step is
|
|
70
68
|
> interactive. Use `install-local.sh` or the `SKIP_*` flags described in
|
|
71
69
|
> [Development guide:
|
|
72
70
|
> provisioning](development.md#provisioning-the-pm-manual) for local or lean
|
|
@@ -81,7 +79,7 @@ All paths are relative to the repository root.
|
|
|
81
79
|
| `copier.yml` | Questions (`role`, `ticket_provider`) and the `_tasks` provisioning chain. |
|
|
82
80
|
| `template/role.yaml.jinja` | The rendered role manifest, including the `ticket_provider` binding and the `reconcile` knobs (`grace_hours`, `auto_review`). |
|
|
83
81
|
| `template/.scripts/lib/ticket-provider.sh` | The adapter dispatcher (`tp`). The engine's only seam to a ticket system. |
|
|
84
|
-
| `template/.scripts/providers/{
|
|
82
|
+
| `template/.scripts/providers/{plane,trello}.sh` | The provider adapters. |
|
|
85
83
|
| `template/.scripts/42-ticket-provider.sh` | Provisioning step that resolves or creates the board. |
|
|
86
84
|
| `template/.scripts/70-systemd.sh` | Provisioning step that installs the gateway, consumer, and the fused `heartbeat` timer (board-reconciliation sentinel pass + gated runtime checkpoint). |
|
|
87
85
|
| `install-local.sh` | One-command local install (no cloud, macOS + Linux). |
|
|
@@ -109,8 +107,8 @@ the agent to read at run time. Keep the two in sync when behavior changes.
|
|
|
109
107
|
|
|
110
108
|
The highest-value open work, in order:
|
|
111
109
|
|
|
112
|
-
1. Live-verify the **Trello** adapter against a real board (
|
|
113
|
-
|
|
110
|
+
1. Live-verify the **Trello** adapter against a real board (Plane is done).
|
|
111
|
+
See [Providers: verifying an
|
|
114
112
|
adapter](providers.md#verifying-an-adapter-against-a-live-board).
|
|
115
113
|
2. Confirm `install-local.sh` on a real macOS machine. The Linux path and the
|
|
116
114
|
Plane adapter are verified; the macOS `launchd` agent and `mkdir` lock get
|
|
@@ -71,7 +71,8 @@ function, `tp`, that dispatches to one provider implementation under
|
|
|
71
71
|
through the `ticket_provider` question and recorded in `role.yaml` under
|
|
72
72
|
`ticket_provider.name`.
|
|
73
73
|
|
|
74
|
-
This is what lets one engine serve
|
|
74
|
+
This is what lets one engine serve the supported ticket back ends: Plane and
|
|
75
|
+
Trello.
|
|
75
76
|
For the full contract and the per-provider details, see
|
|
76
77
|
[Providers](providers.md).
|
|
77
78
|
|
|
@@ -112,7 +112,7 @@ repository root instead of driving Copier by hand. From inside the target
|
|
|
112
112
|
project:
|
|
113
113
|
|
|
114
114
|
```bash
|
|
115
|
-
export PLANE_API_KEY=<key> # or
|
|
115
|
+
export PLANE_API_KEY=<key> # or TRELLO_KEY + TRELLO_TOKEN
|
|
116
116
|
curl -fsSL https://raw.githubusercontent.com/delorenj/hermes-agent-template/main/install-local.sh | sh
|
|
117
117
|
```
|
|
118
118
|
|
|
@@ -133,8 +133,8 @@ The script:
|
|
|
133
133
|
7. smoke-tests the board connection through the adapter.
|
|
134
134
|
|
|
135
135
|
Useful environment overrides (skip the prompts): `HAT_REPO`, `HAT_PROVIDER`,
|
|
136
|
-
`HAT_ROLES`, `HAT_PLANE_WORKSPACE`, `HAT_PLANE_PROJECT`, `
|
|
137
|
-
|
|
136
|
+
`HAT_ROLES`, `HAT_PLANE_WORKSPACE`, `HAT_PLANE_PROJECT`, `HAT_TRELLO_BOARD`,
|
|
137
|
+
and `HAT_DRY_RUN=1` to preview without changing anything.
|
|
138
138
|
|
|
139
139
|
This local path does not wire Telegram or email. Those are convenience layers in
|
|
140
140
|
the `pjangler` provisioner, not requirements for a working agent — talk to the
|
|
@@ -151,7 +151,7 @@ cd /path/to/your-project
|
|
|
151
151
|
copier copy gh:delorenj/hermes-agent-template ./agents/hermes/pm \
|
|
152
152
|
--data role=pm \
|
|
153
153
|
--data target_repo=<repo> \
|
|
154
|
-
--data ticket_provider=<
|
|
154
|
+
--data ticket_provider=<plane|trello>
|
|
155
155
|
```
|
|
156
156
|
|
|
157
157
|
The `_tasks` chain in `copier.yml` runs the numbered provisioning scripts in
|
|
@@ -162,7 +162,7 @@ order. Several of them reach outside the repository.
|
|
|
162
162
|
> Full provisioning is outward-facing and partly interactive.
|
|
163
163
|
> `20-runtime-repo.sh` creates a private GitHub repo with `gh repo create`,
|
|
164
164
|
> `30-telegram.sh` prompts for a BotFather token and blocks waiting for input,
|
|
165
|
-
> and `42-ticket-provider.sh` can create a
|
|
165
|
+
> and `42-ticket-provider.sh` can create a ticket board. Don't run full
|
|
166
166
|
> provisioning unattended.
|
|
167
167
|
|
|
168
168
|
Use the `SKIP_*` environment flags for a local or lean install. Each numbered
|
|
@@ -172,7 +172,7 @@ script checks its flag and skips cleanly.
|
|
|
172
172
|
| --- | --- |
|
|
173
173
|
| `SKIP_TELEGRAM` | The interactive BotFather token step. |
|
|
174
174
|
| `SKIP_RUNTIME_REPO` | Creating the GitHub runtime repo. |
|
|
175
|
-
| `SKIP_PLANE` | Creating
|
|
175
|
+
| `SKIP_PLANE` | Creating or linking the ticket board. |
|
|
176
176
|
| `SKIP_BLOODBANK` | Installing the BloodBank consumer. |
|
|
177
177
|
| `SKIP_SYSTEMD` | Installing `systemd` units (gateway, consumer, heartbeat timer). |
|
|
178
178
|
|
|
@@ -181,13 +181,14 @@ For example, a local install that creates no cloud resources:
|
|
|
181
181
|
```bash
|
|
182
182
|
SKIP_TELEGRAM=1 SKIP_RUNTIME_REPO=1 SKIP_PLANE=1 SKIP_BLOODBANK=1 \
|
|
183
183
|
copier copy gh:delorenj/hermes-agent-template ./agents/hermes/pm \
|
|
184
|
-
--data role=pm --data target_repo=<repo> --data ticket_provider=
|
|
184
|
+
--data role=pm --data target_repo=<repo> --data ticket_provider=trello
|
|
185
185
|
```
|
|
186
186
|
|
|
187
187
|
After provisioning, set the board binding in
|
|
188
|
-
`agents/hermes/pm/role.yaml`. For
|
|
189
|
-
|
|
190
|
-
|
|
188
|
+
`agents/hermes/pm/role.yaml`. For Trello, set `ticket_provider.board` to the
|
|
189
|
+
board id; for Plane, set `ticket_provider.workspace` and `ticket_provider.project`.
|
|
190
|
+
Make the provider key available to the heartbeat's environment: on Linux through
|
|
191
|
+
a `systemd` `EnvironmentFile` (for example
|
|
191
192
|
`~/.hermes/<agent_id>.env`); on macOS the `launchd` agent sources that same
|
|
192
193
|
per-agent env file, so write the key there.
|
|
193
194
|
|
|
@@ -256,8 +257,8 @@ These cost real debugging time. Watch for them.
|
|
|
256
257
|
|
|
257
258
|
The following work is open for the incoming agent, roughly in priority order.
|
|
258
259
|
|
|
259
|
-
1. **Live-verify the Trello adapter.**
|
|
260
|
-
(
|
|
260
|
+
1. **Live-verify the Trello adapter.** Plane is verified live
|
|
261
|
+
(including `transition` and `comment`). Trello is implemented against
|
|
261
262
|
the contract but unverified. Follow [Providers: verifying an
|
|
262
263
|
adapter](providers.md#verifying-an-adapter-against-a-live-board) with Trello
|
|
263
264
|
credentials, and fix any endpoint or field mismatches.
|