@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.
Files changed (30) hide show
  1. package/dist/index.js +797 -737
  2. package/dist/mcp-server.js +753 -683
  3. package/package.json +1 -1
  4. package/templates/commonproject/AGENTS.md +3 -3
  5. package/templates/commonproject/README.md +12 -11
  6. package/templates/commonproject/copier.yml +58 -10
  7. package/templates/commonproject/mise.toml +3 -3
  8. package/templates/commonproject/template/.agents/hooks/sync.py +12 -1
  9. package/templates/commonproject/template/.agents/local.example.json +3 -1
  10. package/templates/commonproject/template/.project.json.jinja +13 -6
  11. package/templates/commonproject/template/mise.toml.jinja +8 -4
  12. package/templates/hermes-agent/README.md +8 -8
  13. package/templates/hermes-agent/copier.yml +3 -4
  14. package/templates/hermes-agent/docs/architecture.md +4 -4
  15. package/templates/hermes-agent/docs/operations.md +2 -2
  16. package/templates/hermes-agent/docs/sentinel/README.md +6 -8
  17. package/templates/hermes-agent/docs/sentinel/architecture.md +2 -1
  18. package/templates/hermes-agent/docs/sentinel/development.md +13 -12
  19. package/templates/hermes-agent/docs/sentinel/providers.md +12 -32
  20. package/templates/hermes-agent/install-local.sh +6 -13
  21. package/templates/hermes-agent/template/.scripts/42-ticket-provider.sh +14 -37
  22. package/templates/hermes-agent/template/.scripts/70-systemd.sh +2 -0
  23. package/templates/hermes-agent/template/.scripts/lib/ticket-provider.sh +6 -2
  24. package/templates/hermes-agent/template/.scripts/sentinel/docs/autonomous-delegated-review.md +2 -2
  25. package/templates/hermes-agent/template/.scripts/sentinel/docs/continuous-ticket-orchestration.md +1 -1
  26. package/templates/hermes-agent/template/.scripts/sentinel.prompt.md.jinja +6 -1
  27. package/templates/hermes-agent/template/SOUL.md.jinja +9 -3
  28. package/templates/hermes-agent/template/role.yaml.jinja +3 -6
  29. package/templates/hermes-agent/template/.scripts/40-plane.sh +0 -51
  30. package/templates/hermes-agent/template/.scripts/providers/linear.sh +0 -176
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@delorenj/pjangler",
3
- "version": "1.2.4",
3
+ "version": "1.2.8",
4
4
  "description": "Project subsystem bootstrapper CLI",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -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 Plane project + ticket_provider block in .project.json
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
- - Plane project created via API in post-generation task
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 Plane project, writes the ticket_provider block in .project.json)
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, Plane ticket enforcement, and multi-agent development tooling.
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
- - **Plane Integration**: `.project.json` for ticket management and project config
10
- - **Ticket Enforcement**: Git hooks enforce Plane ticket requirements
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 Plane API key (for automated project creation)
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: Plane project creation + Copier template:
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 Plane project automatically
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 Plane project automatically
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
- ### Plane Integration
86
+ ### Ticket Provider Integration
87
87
 
88
- - **Workspace**: Plane workspace slug (default: 33god)
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 Plane Ticket**
114
+ 3. **Create or Claim Ticket**
114
115
 
115
116
  ```bash
116
- # Create ticket in Plane (or it was already created for you!)
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
- # - Plane project (auto-created in 33god workspace)
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. The board itself is created by
34
- # init-project.sh (create-plane-project.sh) BEFORE copier runs; its identity is
35
- # threaded back in via plane_* below and persisted into .project.json so it is
36
- # the single source of truth shared with the hermes-agent template's agents.
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
- # Board binding supplied by init-project.sh's --data-file after the board is
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
- # --- Post-generation tasks ---
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 Plane project + runs Copier
21
- init-project = { run = ".mise/scripts/init-project.sh", description = "Initialize new 33GOD project with Plane + Copier" }
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
- disabled_agents = set((data.get("hooks") or {}).get("disabled_agents") or [])
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
- {% if ticket_provider == 'plane' and plane_project_id -%}
2
- {% set board_url = plane_base ~ '/' ~ plane_workspace ~ '/projects/' ~ plane_project_id ~ '/issues/' -%}
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 board_url = '' -%}
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": {{ plane_workspace | tojson }},
20
+ "workspace": {{ workspace | tojson }},
14
21
  "identifier": {{ project_identifier | tojson }},
15
- "board_id": {{ plane_project_id | tojson }},
16
- "board_url": {{ board_url | tojson }}
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 | Plane project, bmad init, mise tasks | Plane project, Telegram bot wiring, agent-hm-* runtime repo, systemd units |
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 (Linear,
24
- Plane, or Trello) with an autonomous adversarial review (act, do not wait). The
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 a Plane project in your configured workspace
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-40-plane
142
- SKIP_TELEGRAM=1 SKIP_SYSTEMD=1 ./.scripts/40-plane.sh
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 Plane
150
- project, `/deletebot` in BotFather, archive the
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 a Plane project in 33god workspace
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, Plane
21
- # workspace/URL, NATS endpoint, skills dir, …) are NOT hardcoded — they live in
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 Plane project per agent
95
+ ## One Ticket Board Per Repo
96
96
 
97
- A Plane "project" is the natural unit of work isolation. Mixing agents into a
98
- shared project would conflate decisions and break filters. 1:1 also makes
99
- archive-on-retire clean.
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
- | 40 plane | Create Plane project in 33god workspace (1:1 with agent), patch identifier into role.yaml | `SKIP_PLANE=1` |
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 Plane project (Plane UI or API)
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 Linear, Plane, or Trello. The engine lives once in this template (the
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 LINEAR_API_KEY / TRELLO_KEY + TRELLO_TOKEN
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 Plane project, and the Telegram step is
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/{linear,plane,trello}.sh` | The provider adapters. |
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 (Linear and Plane are
113
- done). See [Providers: verifying an
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 three back ends: Trello, Plane, and Linear.
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 LINEAR_API_KEY / TRELLO_KEY + TRELLO_TOKEN
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`, `HAT_LINEAR_TEAM`,
137
- `HAT_TRELLO_BOARD`, and `HAT_DRY_RUN=1` to preview without changing anything.
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=<linear|plane|trello>
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 Plane project. Don't run full
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 a Plane project. |
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=linear
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 Linear, set `ticket_provider.team`
189
- to the team key. Make the provider key available to the heartbeat's environment:
190
- on Linux through a `systemd` `EnvironmentFile` (for example
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.** Linear and Plane are verified live
260
- (Plane includes `transition` and `comment`). Trello is implemented against
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.