fix(skills): repair audited format and resource defects

This commit is contained in:
Magnus Hedemark
2026-07-10 21:50:56 -04:00
parent 1305c770d1
commit c4cd14b5b1
21 changed files with 699 additions and 457 deletions
+3 -3
View File
@@ -99,10 +99,10 @@ Static resources: templates, images, data files, schemas.
Use **relative paths from the skill root** when referencing other files:
```markdown
See [the reference guide](references/REFERENCE.md) for details.
See [the specification](references/specification.md) for details.
Run the extraction script:
scripts/extract.py
Run a bundled script:
scripts/<script-name>
```
Keep file references one level deep from `SKILL.md`. Avoid deeply nested reference chains.
@@ -0,0 +1,23 @@
# Headscale Backup
## Why Install This Skill
Provides a repeatable backup, restore, and migration workflow for Headscale state before upgrades or recovery work.
## What You Get
| Content | Purpose |
|---|---|
| `SKILL.md` and `scripts/` | Backup, restore, and migration guidance |
## Quick Start
Read `SKILL.md` before running a backup or restore script.
## Triggers
Use before Headscale upgrades, migrations, or disaster recovery.
## Requirements
Access to the Headscale host, database, configuration, and certificates.
@@ -0,0 +1,23 @@
# Headscale Deploy
## Why Install This Skill
Helps set up and maintain a self-hosted Headscale control server.
## What You Get
| Content | Purpose |
|---|---|
| `SKILL.md` and `scripts/` | Deployment and maintenance workflow |
## Quick Start
Follow the deployment sequence in `SKILL.md` for Linux or Docker.
## Triggers
Use when deploying, configuring, or troubleshooting Headscale.
## Requirements
Linux or Docker host access and a Headscale-compatible network setup.
@@ -0,0 +1,23 @@
# Headscale DERP
## Why Install This Skill
Explains how to deploy and diagnose DERP relays when direct peer connections are unavailable.
## What You Get
| Content | Purpose |
|---|---|
| `SKILL.md` and `scripts/` | Relay deployment and latency diagnostics |
## Quick Start
Use the diagnostic guidance in `SKILL.md` before adding a custom relay.
## Triggers
Use when peers rely on DERP or direct connectivity fails.
## Requirements
Headscale administration and a reachable relay host.
@@ -0,0 +1,23 @@
# Headscale Node Lifecycle
## Why Install This Skill
Manages device registration, auth keys, tags, inventory, and decommissioning in a Headscale tailnet.
## What You Get
| Content | Purpose |
|---|---|
| `SKILL.md` and `scripts/` | Node lifecycle procedures |
## Quick Start
Follow `SKILL.md` to choose personal-node or tagged-node registration.
## Triggers
Use when adding, approving, tagging, or retiring devices.
## Requirements
Headscale administrator access.
@@ -0,0 +1,23 @@
# Headscale Routing
## Why Install This Skill
Configures subnet routers and exit nodes so a tailnet can reach LAN devices or route internet traffic.
## What You Get
| Content | Purpose |
|---|---|
| `SKILL.md` and `scripts/` | Route advertising and approval guidance |
## Quick Start
Use `SKILL.md` to advertise routes, then approve them centrally.
## Triggers
Use when adding LAN routes or an exit node.
## Requirements
Headscale administration and a gateway node with routing enabled.
@@ -0,0 +1,23 @@
# Tailnet Policy
## Why Install This Skill
Helps author and validate Headscale-compatible huJSON access policies.
## What You Get
| Content | Purpose |
|---|---|
| `SKILL.md` and `scripts/` | Policy authoring, validation, and deployment guidance |
## Quick Start
Use `SKILL.md` to validate a policy before deploying it.
## Triggers
Use when changing ACLs, grants, tags, or Tailscale SSH rules.
## Requirements
Headscale policy access and huJSON-compatible tooling.
@@ -0,0 +1,23 @@
# Tailscale Client for Headscale
## Why Install This Skill
Connects and troubleshoots official Tailscale clients against a self-hosted Headscale server.
## What You Get
| Content | Purpose |
|---|---|
| `SKILL.md` and `scripts/` | Client setup and diagnostics |
## Quick Start
Follow `SKILL.md` to connect with the appropriate `--login-server` value.
## Triggers
Use when enrolling a device or diagnosing tailnet connectivity.
## Requirements
The official Tailscale client and access to the Headscale control server.
@@ -0,0 +1,23 @@
# Bundle Builder
## Why Install This Skill
Turns a discovered workflow into a reusable skill bundle with a manifest, decision map, and phase skills.
## What You Get
| Content | Purpose |
|---|---|
| `SKILL.md` | Bundle synthesis instructions |
## Quick Start
Run workflow-architects active or passive mode, then load this step after the workflow converges.
## Triggers
Use after workflow discovery is complete and a reusable bundle is needed.
## Requirements
Hermes memory and file-writing tools.
@@ -1,86 +1,86 @@
1|---
2|name: bundle-builder
3|description: >-
4| The synthesis engine for workflow-architect. Reads accumulated workflow
5| state from memory and renders it into a valid Agent Skills bundle directory
6| with sub-skills, manifest, decision map, and optional kanban board. Loaded
7| after the interviewer or observer achieves convergence.
8|license: MIT
9|compatibility: Hermes Agent — uses write_file for bundle output, shell_quote
10|metadata:
11| tags: [workflow, generation, bundle, synthesis]
12| spec-version: "1.0"
13|---
14|
15|# Bundle Builder — Workflow Synthesis Engine
16|
17|This sub-skill is loaded after the interviewer (active mode) or observer
18|(passive mode) achieves convergence. It reads the accumulated workflow
19|state from memory and generates an output bundle directory.
20|
21|## Input
22|
23|All `workflow-architect:state:*` memory entries. Read them all at once:
24|
25|```
26|Read: workflow-architect:state:entry_points
27|Read: workflow-architect:state:phases
28|Read: workflow-architect:state:branching
29|Read: workflow-architect:state:pain_points
30|Read: workflow-architect:state:exit_criteria
31|```
32|
33|If any required fields are missing (entry_points, phases, branching, exit_criteria),
34|abort with a clear message about what's missing.
35|
36|## Output Structure
37|
38|The bundle is written to `~/.hermes/skills/<category>/<bundle-name>/` with this layout:
39|
40|```
41|<bundle-name>/
---
name: bundle-builder
description: >-
The synthesis engine for workflow-architect. Reads accumulated workflow
state from memory and renders it into a valid Agent Skills bundle directory
with sub-skills, manifest, decision map, and optional kanban board. Loaded
after the interviewer or observer achieves convergence.
license: MIT
compatibility: Hermes Agent — uses write_file for bundle output, shell_quote
metadata:
tags: [workflow, generation, bundle, synthesis]
spec-version: "1.0"
---
# Bundle Builder — Workflow Synthesis Engine
This sub-skill is loaded after the interviewer (active mode) or observer
(passive mode) achieves convergence. It reads the accumulated workflow
state from memory and generates an output bundle directory.
## Input
All `workflow-architect:state:*` memory entries. Read them all at once:
```
Read: workflow-architect:state:entry_points
Read: workflow-architect:state:phases
Read: workflow-architect:state:branching
Read: workflow-architect:state:pain_points
Read: workflow-architect:state:exit_criteria
```
If any required fields are missing (entry_points, phases, branching, exit_criteria),
abort with a clear message about what's missing.
## Output Structure
The bundle is written to `~/.hermes/skills/<category>/<bundle-name>/` with this layout:
```
<bundle-name>/
├── SKILL.md # *** UMBRELLA ENTRY POINT *** — makes the bundle
│ # loadable via skill_view() and discoverable by
│ # the agent's skill scanner on trigger keywords.
│ # CRITICAL: without this, the bundle is invisible.
50|├── README.md # Summary of this bundle
51|├── manifest.yaml # Skill-to-trigger mapping
52|├── skills/
53|│ ├── entry-skill.md # One per discovered phase
54|│ ├── phase-two.md
55|│ └── ...
56|├── decision-map.md # Mermaid flowchart
57|├── AGENTS.md # Agent loading instructions for this bundle
58|├── kanban/
59|│ └── board-definition.yaml # Only if kanban is appropriate
60|└── references/
61| └── generated-from.md # Metadata about how this bundle was created
62|```
63|
├── README.md # Summary of this bundle
├── manifest.yaml # Skill-to-trigger mapping
├── skills/
│ ├── entry-skill.md # One per discovered phase
│ ├── phase-two.md
│ └── ...
├── decision-map.md # Mermaid flowchart
├── AGENTS.md # Agent loading instructions for this bundle
├── kanban/
│ └── board-definition.yaml # Only if kanban is appropriate
└── references/
└── generated-from.md # Metadata about how this bundle was created
```
**The `SKILL.md` umbrella is not optional.** Without it, individual sub-skills
may exist on disk but the agent's skill scanner has no entry point to match
trigger keywords against. The umbrella is how the agent discovers and enters
the bundle.
74|
75|### Bundle naming
76|
77|Ask the user for a bundle name at the start of synthesis:
78|
79|```
80|"Before I generate the bundle — what should I call it?
81|Something short, lowercase with hyphens, like 'my-triage-workflow'
82|or 'dev-sprint-routine'."
83|```
84|
85|Fallback if user doesn't provide one: `my-workflow-<archetype>-<date>`.
86|
87|### Writing the files
88|
89|For each file in the output bundle, use the templates in `templates/` as
90|starting points. Render them by substituting the state values.
91|
92|**Step-by-step file creation order:**
93|
### Bundle naming
Ask the user for a bundle name at the start of synthesis:
```
"Before I generate the bundle — what should I call it?
Something short, lowercase with hyphens, like 'my-triage-workflow'
or 'dev-sprint-routine'."
```
Fallback if user doesn't provide one: `my-workflow-<archetype>-<date>`.
### Writing the files
For each file in the output bundle, use the shared templates in `../../templates/` as
starting points. Render them by substituting the state values.
**Step-by-step file creation order:**
0. **Umbrella SKILL.md****MANDATORY FIRST STEP.** This is the entry point
that makes the bundle discoverable. Write it directly to the bundle directory
as `SKILL.md`, then register it via `skill_manage(action='create')`.
@@ -124,290 +124,246 @@ the bundle.
## Pipeline Heuristics
- Can the user enter at any phase, or must they start at Phase 1?
138| - Are any phases automatic (e.g., refine always follows draft)?
139| - What's the relationship between phases (sequential, branching, optional)?
140| ```
141|
142| **Category choice:** Place the bundle in a category that matches where its
143| sub-skills live (e.g., `content` for blogging pipelines, `devops` for
144| deployment workflows). Ask the user if unsure.
145|=======
146|0. **umbrella SKILL.md** — Create the bundle's entry point. This is the
147| first file because the umbrella must be registered and discoverable
148| before any sub-skill can be loaded.
149|
150| a. Generate an umbrella SKILL.md with:
151|
152| **Frontmatter:**
153| - `name: <bundle-name>`
154| - `description:` — Craft this carefully. Include broad trigger
155| phrases that cover all phases of the workflow, so the agent can
156| auto-detect this bundle in future sessions. Pattern:
157| "Use when [trigger summary]. Covers: [phase list]."
158| - `tags: [workflow, bundle:generated, <archetype>]`
159| - `spec-version: "1.0"`
160|
161| **Body:**
162| - H1: `# <Bundle Name>` (user-friendly title)
163| - **Phase table** — Markdown table mapping each sub-skill
164| name to its trigger condition and typical entry signal.
165| Columns: | Phase | Load this skill | When |
166| - **Workflow flowchart** — Mermaid `graph LR` or `graph TD`
167| showing entry → phases (with decision diamonds for
168| branching) → exit. Entry condition links to the description.
169| - **Navigation instructions** — Explain the two-entry model:
170| (1) auto-detect via trigger conditions, (2) `skill_view(name='<bundle-name>')`
171| to inspect the pipeline. Tell the agent: identify the user's
172| current phase, load that sub-skill, follow its instructions.
173| - **Heuristics** — Phase ordering notes (sequential vs. flexible),
174| entry points (can start at any phase), transition signals.
175|
176| b. Write to `<bundle-name>/SKILL.md` via `write_file`.
177|
178| c. Register with:
179| ```
180| skill_manage(action='create', name='<bundle-name>', content='...')
181| ```
182|
183| > **Why step 0?** The umbrella SKILL.md is the agent's entry point to
184| > the entire bundle. It must exist and be registered first so that any
185| > subsequent sub-skill loading instructions reference a discoverable
186| > parent. Without it, the bundle is invisible to the agent.
187|>>>>>>> 77f9d16 (fix(bundle-builder): generate umbrella SKILL.md as discoverable entry point)
188|
189|1. **manifest.yaml** — Use `templates/manifest.yaml.tmpl`. Substitute:
190| - `{{BUNDLE_NAME}}` — the bundle name
191| - `{{PHASES}}` — each phase with its trigger keywords, entry signals,
192| typical tools, and exit signals
193| - `{{HAS_KANBAN}}` — true/false based on kanban decision
194|
195|2. **README.md** — Write from scratch (no template needed, it's prose).
196| Structure:
197|
198| ```markdown
199| # <Bundle Name>
200|
201| Generated by workflow-architect on <date>.
202|
203| This bundle covers a <archetype>-style workflow with <N> phases.
204|
205| ## Skills
206|
207| | Skill | Trigger | When it fires |
208| |-------|---------|---------------|
209| | <name> | <trigger description> | <when to load> |
210|
211| ## Loading
212|
213| Skills in this bundle are loaded automatically by trigger conditions.
214| To load a specific skill: `skill_view(name='<bundle-name>/<skill-name>')`
215|
216| ## Kanban
217|
218| (Only if kanban exists) This workflow maps to a kanban board with <N> lanes.
219| ```
220|
221|3. **Sub-skills** — For each phase in `workflow-architect:state:phases`,
222| generate a `.md` file in `skills/` using `templates/skill-skeleton.md`.
223|
224| Naming convention: `kebab-case-phase-name.md` (e.g., `morning-triage.md`).
225|
226| Each sub-skill file is a valid Agent Skills SKILL.md with:
227| - `name` matching the filename (without .md)
228| - `description` that includes trigger keywords from the phase's typical
229| openers and tools
230| - `compatibility: Compatible with any agent supporting the Agent Skills format`
231| - Body sections:
232| - **When to use** — the trigger condition in natural language
233| - **What to do** — step-by-step instructions for the agent in this phase
234| - **Transition signals** — what the user typically says or does that
235| transitions out of this phase
236| - **What to tell the user** — guidance on how the agent should communicate
237| during this phase
238|
239|4. **decision-map.md** — Use `templates/decision-map.md.tmpl`. Substitute:
240| - `{{WORKFLOW_NAME}}` — bundle name
241| - `{{PHASE_NODES}}` — phase names
242| - `{{BRANCHING}}` — decision diamonds
243| - `{{ENTRY}}` — how sessions start
244| - `{{EXITS}}` — how sessions end
245|
246|5. **AGENTS.md** — Standard agent loading instructions for this bundle.
247| Short — just says which skills exist and when to load them.
248|
249|6. **kanban/ directory** — Only if the kanban-decision-criteria.md reference
250| indicates kanban is appropriate. Generates three files:
251|
252| a) **kanban/board-setup.sh** — Use `templates/kanban-board-setup.sh.tmpl`.
253| Substitutes:
254| - `{{BOARD_SLUG}}` — bundle name (kebab-case)
255| - `{{BOARD_NAME}}` — title-case version or user-provided name
256| - `{{FIRST_PHASE_SKILL}}` — skill file for the first phase
257| - `{{FIRST_PHASE_PRIORITY}}` — priority for first-phase tasks
258| - `{{GENERATION_DATE}}` — current date
259|
260| The setup script creates the board via `hermes kanban boards create`
261| and prints instructions for adding work.
262|
263| b) **kanban/task-blueprints.yaml** — Use `templates/kanban-task-blueprints.yaml.tmpl`.
264| Substitutes:
265| - `{{BLUEPRINT_ENTRIES}}` — one blueprint entry per phase, each with:
266| - `phase:` — phase name (kebab-case)
267| - `title_template:` — e.g. "Build: {{feature}}"
268| - `skill:` — path to the sub-skill file (e.g. `my-workflow/build`)
269| - `default_priority:` — descending from first phase (highest) to last
270| - `initial_status:` — first phase = `todo`, rest = `ready`
271| - `body:` — instructions for the worker: what skill to load,
272| definition of done, and transition to next phase
273|
274| c) **kanban/README.md** — Brief usage guide explaining how to set up and
275| use the board. Structure:
276|
277| ```markdown
278| # Kanban Board: <Bundle Name>
279|
280| This workflow maps to a Hermes Kanban board with <N> phases in sequence.
281|
282| ## Setup
283|
284| Run `kanban/board-setup.sh` to create the board:
285| ```bash
286| bash kanban/board-setup.sh
287| ```
288|
289| The script creates the board and switches to it. If you prefer to set
290| it up manually:
291| ```bash
292| hermes kanban boards create <bundle-name> --name "<Bundle Name>"
293| ```
294|
295| ## Task Lifecycle
296|
297| <Phase 1> → <Phase 2> → <Phase 3>
298|
299| Each phase's task depends on the previous phase's task completing.
300| When a task is done, the next phase's task auto-promotes to "ready"
301| and the dispatcher picks it up.
302|
303| ## Adding Work
304|
305| Create a task for the first phase:
306| ```bash
307| hermes kanban create "Build: <feature description>" \\
308| --skill <bundle-name>/<phase-1-skill> \\
309| --priority 3
310| ```
311|
312| Then create subsequent-phase tasks with `--parent` pointing to the
313| first task's ID:
314| ```bash
315| hermes kanban create "Review: <feature>" \\
316| --parent <task-id> \\
317| --skill <bundle-name>/<phase-2-skill> \\
318| --priority 2
319| ```
320|
321| ## Task Blueprints
322|
323| See `kanban/task-blueprints.yaml` for template definitions of each
324| phase's task, including default priorities, skill mappings, and
325| worker instructions.
326| ```
327|
328|7. **references/generated-from.md** — Metadata about the generation process:
329|
330| ```markdown
331| # Generated From
332|
333| - **Skill:** workflow-architect
334| - **Mode:** active | passive
335| - **Date:** <date>
336| - **Archetype:** <archetype>
337| - **Convergence Score:** <score>
338| ```
339|
340|8. **Register sub-skills with Hermes skill system** — For each sub-skill `.md`
341| file written in step 3, register it so it appears in `skills_list()` and
342| can be loaded with `skill_view()`. This is the critical step that makes
343| generated skills actually usable by the agent.
344|
345| For each sub-skill file in `skills/<name>.md`:
346|
347| ```python
348| skill_manage(action='create',
349| name='<bundle-name>-<skill-name>',
350| content=read_file('<bundle-path>/skills/<name>.md')['content'],
351| category='generated')
352| ```
353|
354| This creates a proper skill directory with `SKILL.md` entry point, making
355| the sub-skill discoverable and loadable. The sub-skill's existing valid
356| Agent Skills frontmatter (name, description, license, tags) is used as-is.
357|
358| **Why separate registration is needed:** The `skill_manage()` call also
359| handles the skill directory structure (`SKILL.md` at root, not `<name>.md`
360| in a `skills/` subdirectory). Without this step, the sub-skill files exist
361| on disk but no Hermes mechanism discovers them. Only the umbrella SKILL.md
362| (registered in step 0) would be loadable.
363|
364| **Verification:** After registering all sub-skills, verify at least one:
365| ```python
366| skill_view(name='<bundle-name>-<first-phase-name>')
367| ```
368|
369| If it errors, the registration failed — check that the sub-skill file's
370| frontmatter `name` field matches and the content has valid YAML.
371|
372|## Kanban Decision
373|
374|Before generating kanban files, consult `references/kanban-decision-criteria.md`
375|to decide whether a board is appropriate. The decision depends on the phases
376|and branching structure discovered:
377|
378|- If phases form a clear linear sequence (A → B → C → D), kanban adds value
379|- If branching is emergent (session depends on context), kanban is likely inappropriate
380|- If the user mentioned waiting on others, hand-offs, or status tracking, kanban is a strong fit
381|
382|Present the decision to the user:
383|
384|```
385|"Your workflow has a [linear/emergent] structure. A kanban board [would/wouldn't]
386|add much value here because [reason]. [If yes: I'll add one to the bundle.]"
387|```
388|
389|8. **Register sub-skills** — For each generated sub-skill `.md` file in
390| `skills/`, register it so Hermes can discover it via `skill_view()` and
391| `skills_list()`:
392|
393| ```
394| For each sub-skill file `skills/<phase-name>.md`:
395| Read the file content
396| skill_manage(
397| action='create',
398| name='<bundle-name>/<phase-name>',
399| content=file_content
400| )
401| ```
402|
403| This makes each sub-skill loadable as `skill_view('<bundle-name>/<phase-name>')`.
404| The bundle name prefix prevents naming collisions with other skills.
405|
406| If `skill_manage` is not available in the agent's toolset, note this for
407| the user and suggest they run the registration manually.
408|
409|## Cleanup
410|
411|After writing all files:
412|
413|1. Verify the umbrella registered successfully:
414| ```
415| skill_view(name='<bundle-name>')
416| ```
417| If it returns `status: available`, proceed. If not found, re-run the
418| `skill_manage(action='create')` call.
419|
420|2. Remove all `workflow-architect:state:*` memory entries
421| (`memory(action='remove', target='memory', old_text='workflow-architect:state:')`)
- Are any phases automatic (e.g., refine always follows draft)?
- What's the relationship between phases (sequential, branching, optional)?
```
**Category choice:** Place the bundle in a category that matches where its
sub-skills live (e.g., `content` for blogging pipelines, `devops` for
deployment workflows). Ask the user if unsure.
1. **manifest.yaml** — Use `../../templates/manifest.yaml.tmpl`. Substitute:
- `{{BUNDLE_NAME}}` — the bundle name
- `{{PHASES}}` — each phase with its trigger keywords, entry signals,
typical tools, and exit signals
- `{{HAS_KANBAN}}` — true/false based on kanban decision
2. **README.md** — Write from scratch (no template needed, it's prose).
Structure:
```markdown
# <Bundle Name>
Generated by workflow-architect on <date>.
This bundle covers a <archetype>-style workflow with <N> phases.
## Skills
| Skill | Trigger | When it fires |
|-------|---------|---------------|
| <name> | <trigger description> | <when to load> |
## Loading
Skills in this bundle are loaded automatically by trigger conditions.
To load a specific skill: `skill_view(name='<bundle-name>/<skill-name>')`
## Kanban
(Only if kanban exists) This workflow maps to a kanban board with <N> lanes.
```
3. **Sub-skills** — For each phase in `workflow-architect:state:phases`,
generate a `.md` file in `skills/` using `../../templates/skill-skeleton.md`.
Naming convention: `kebab-case-phase-name.md` (e.g., `morning-triage.md`).
Each sub-skill file is a valid Agent Skills SKILL.md with:
- `name` matching the filename (without .md)
- `description` that includes trigger keywords from the phase's typical
openers and tools
- `compatibility: Compatible with any agent supporting the Agent Skills format`
- Body sections:
- **When to use** — the trigger condition in natural language
- **What to do** — step-by-step instructions for the agent in this phase
- **Transition signals** — what the user typically says or does that
transitions out of this phase
- **What to tell the user** — guidance on how the agent should communicate
during this phase
4. **decision-map.md** — Use `../../templates/decision-map.md.tmpl`. Substitute:
- `{{WORKFLOW_NAME}}` — bundle name
- `{{PHASE_NODES}}` — phase names
- `{{BRANCHING}}` — decision diamonds
- `{{ENTRY}}` — how sessions start
- `{{EXITS}}` — how sessions end
5. **AGENTS.md** — Standard agent loading instructions for this bundle.
Short — just says which skills exist and when to load them.
6. **kanban/ directory** — Only if the kanban-decision-criteria.md reference
indicates kanban is appropriate. Generates three files:
a) **kanban/board-setup.sh** — Use `../../templates/kanban-board-setup.sh.tmpl`.
Substitutes:
- `{{BOARD_SLUG}}` — bundle name (kebab-case)
- `{{BOARD_NAME}}` — title-case version or user-provided name
- `{{FIRST_PHASE_SKILL}}` — skill file for the first phase
- `{{FIRST_PHASE_PRIORITY}}` — priority for first-phase tasks
- `{{GENERATION_DATE}}` — current date
The setup script creates the board via `hermes kanban boards create`
and prints instructions for adding work.
b) **kanban/task-blueprints.yaml** — Use `../../templates/kanban-task-blueprints.yaml.tmpl`.
Substitutes:
- `{{BLUEPRINT_ENTRIES}}` — one blueprint entry per phase, each with:
- `phase:` — phase name (kebab-case)
- `title_template:` — e.g. "Build: {{feature}}"
- `skill:` — path to the sub-skill file (e.g. `my-workflow/build`)
- `default_priority:` — descending from first phase (highest) to last
- `initial_status:` — first phase = `todo`, rest = `ready`
- `body:` — instructions for the worker: what skill to load,
definition of done, and transition to next phase
c) **kanban/README.md** — Brief usage guide explaining how to set up and
use the board. Structure:
```markdown
# Kanban Board: <Bundle Name>
This workflow maps to a Hermes Kanban board with <N> phases in sequence.
## Setup
Run `kanban/board-setup.sh` to create the board:
```bash
bash kanban/board-setup.sh
```
The script creates the board and switches to it. If you prefer to set
it up manually:
```bash
hermes kanban boards create <bundle-name> --name "<Bundle Name>"
```
## Task Lifecycle
<Phase 1> → <Phase 2> → <Phase 3>
Each phase's task depends on the previous phase's task completing.
When a task is done, the next phase's task auto-promotes to "ready"
and the dispatcher picks it up.
## Adding Work
Create a task for the first phase:
```bash
hermes kanban create "Build: <feature description>" \\
--skill <bundle-name>/<phase-1-skill> \\
--priority 3
```
Then create subsequent-phase tasks with `--parent` pointing to the
first task's ID:
```bash
hermes kanban create "Review: <feature>" \\
--parent <task-id> \\
--skill <bundle-name>/<phase-2-skill> \\
--priority 2
```
## Task Blueprints
See `kanban/task-blueprints.yaml` for template definitions of each
phase's task, including default priorities, skill mappings, and
worker instructions.
```
7. **references/generated-from.md** — Metadata about the generation process:
```markdown
# Generated From
- **Skill:** workflow-architect
- **Mode:** active | passive
- **Date:** <date>
- **Archetype:** <archetype>
- **Convergence Score:** <score>
```
8. **Register sub-skills with Hermes skill system** — For each sub-skill `.md`
file written in step 3, register it so it appears in `skills_list()` and
can be loaded with `skill_view()`. This is the critical step that makes
generated skills actually usable by the agent.
For each sub-skill file in `skills/<name>.md`:
```python
skill_manage(action='create',
name='<bundle-name>-<skill-name>',
content=read_file('<bundle-path>/skills/<name>.md')['content'],
category='generated')
```
This creates a proper skill directory with `SKILL.md` entry point, making
the sub-skill discoverable and loadable. The sub-skill's existing valid
Agent Skills frontmatter (name, description, license, tags) is used as-is.
**Why separate registration is needed:** The `skill_manage()` call also
handles the skill directory structure (`SKILL.md` at root, not `<name>.md`
in a `skills/` subdirectory). Without this step, the sub-skill files exist
on disk but no Hermes mechanism discovers them. Only the umbrella SKILL.md
(registered in step 0) would be loadable.
**Verification:** After registering all sub-skills, verify at least one:
```python
skill_view(name='<bundle-name>-<first-phase-name>')
```
If it errors, the registration failed — check that the sub-skill file's
frontmatter `name` field matches and the content has valid YAML.
## Kanban Decision
Before generating kanban files, consult `../../references/kanban-decision-criteria.md`
to decide whether a board is appropriate. The decision depends on the phases
and branching structure discovered:
- If phases form a clear linear sequence (A → B → C → D), kanban adds value
- If branching is emergent (session depends on context), kanban is likely inappropriate
- If the user mentioned waiting on others, hand-offs, or status tracking, kanban is a strong fit
Present the decision to the user:
```
"Your workflow has a [linear/emergent] structure. A kanban board [would/wouldn't]
add much value here because [reason]. [If yes: I'll add one to the bundle.]"
```
8. **Register sub-skills** — For each generated sub-skill `.md` file in
`skills/`, register it so Hermes can discover it via `skill_view()` and
`skills_list()`:
```
For each sub-skill file `skills/<phase-name>.md`:
Read the file content
skill_manage(
action='create',
name='<bundle-name>/<phase-name>',
content=file_content
)
```
This makes each sub-skill loadable as `skill_view('<bundle-name>/<phase-name>')`.
The bundle name prefix prevents naming collisions with other skills.
If `skill_manage` is not available in the agent's toolset, note this for
the user and suggest they run the registration manually.
## Cleanup
After writing all files:
1. Verify the umbrella registered successfully:
```
skill_view(name='<bundle-name>')
```
If it returns `status: available`, proceed. If not found, re-run the
`skill_manage(action='create')` call.
2. Remove all `workflow-architect:state:*` memory entries
(`memory(action='remove', target='memory', old_text='workflow-architect:state:')`)
2. Remove all `workflow-architect:state:*` memory entries
(`memory(action='remove', target='memory', old_text='workflow-architect:state:')`)
2. Tell the user where the bundle was written and what it contains
@@ -418,4 +374,3 @@ the bundle.
`skill_view(name='<bundle-name>-<first-phase-name>')`
5. Suggest they enter the workflow via any trigger phrase covered by the
umbrella's description, or by manually loading the umbrella skill
438|
@@ -0,0 +1,23 @@
# Workflow Interviewer
## Why Install This Skill
Guides a structured conversation that turns an informal work process into clear phases and transition signals.
## What You Get
| Content | Purpose |
|---|---|
| `SKILL.md` | Adaptive workflow-discovery interview |
## Quick Start
Load it through workflow-architects active mode and answer the prompts naturally.
## Triggers
Use when someone wants to describe, map, or formalize their workflow.
## Requirements
Hermes memory tools for multi-turn state.
@@ -188,7 +188,7 @@ entries from memory and writing the output bundle files.
## Archetype Matching
After each answer, check the `references/workflow-archetypes.md` file to see
After each answer, check the shared `../../references/workflow-archetypes.md` file to see
if the user's answers match a known archetype. If they do, note it in state
and use it to seed better follow-up questions (e.g., "For a morning triage
workflow, people often have a 'stale items bucket' — do you have something
@@ -0,0 +1,23 @@
# Workflow Observer
## Why Install This Skill
Infers a workflow from a substantive session without interrupting the work with an interview.
## What You Get
| Content | Purpose |
|---|---|
| `SKILL.md` | Passive workflow-analysis instructions |
## Quick Start
Load it through workflow-architects passive mode after a session with meaningful work history.
## Triggers
Use when someone asks to infer or catalogue the process they just followed.
## Requirements
Hermes session-search and context-scanning tools.
+1 -17
View File
@@ -15,11 +15,8 @@ metadata:
- https://github.com/ComposioHQ/awesome-agent-clis
- https://ronnierocha.dev/blog/dont-build-mcps-build-cli-tools
---
# CLI Builder — Agent-Friendly Tool Design
## Overview
A CLI tool is a **contract** between your code and the agent that calls it. Every design decision is part of that contract:
| CLI Element | Contract Purpose |
@@ -491,20 +488,7 @@ See [references/skill-wrapper-example.md](references/skill-wrapper-example.md) f
## Agent-Readiness Checklist
- [ ] No interactive prompts (`read`, `select`, `dialog`)
- [ ] All inputs via flags or env vars
- [ ] `--help` on every subcommand with examples
- [ ] `--json` output is valid parseable JSON
- [ ] `--dry-run` on every destructive command
- [ ] `--force` / `--yes` to skip confirmations
- [ ] Idempotent: second call returns no-op, not error
- [ ] Consistent `resource verb` structure
- [ ] Errors go to stderr (`>&2` or `die()`)
- [ ] `--json` mode suppresses all non-JSON stdout
- [ ] Lazy auth: `--help` and `--dry-run` work without credentials
- [ ] Exit codes: 0=success, 1=usage error, 2=runtime failure
- [ ] Live-server verified for every read endpoint
- [ ] Dry-run verified for every chained-API path
Use [the agent-readiness checklist](references/agent-readiness-checklist.md) before shipping a CLI.
## References
@@ -0,0 +1,16 @@
# Agent-Readiness Checklist
- [ ] No interactive prompts (`read`, `select`, `dialog`)
- [ ] All inputs arrive through flags or environment variables
- [ ] Every subcommand has `--help` examples
- [ ] `--json` output parses as JSON
- [ ] Every destructive operation supports `--dry-run`
- [ ] `--force` or `--yes` skips confirmation
- [ ] Repeating an operation produces a no-op rather than an error
- [ ] Commands use a consistent `resource verb` structure
- [ ] Errors go to stderr
- [ ] JSON mode emits no non-JSON stdout
- [ ] `--help` and `--dry-run` work without credentials
- [ ] Exit codes distinguish success, usage errors, and runtime failures
- [ ] Each read endpoint has a live-server verification
- [ ] Each chained API path has a dry-run verification
+2 -53
View File
@@ -11,15 +11,10 @@ compatibility: Any agent supporting Agent Skills format — commands use standar
metadata:
source: https://docs.crowdsec.net
---
# CrowdSec Skill
CrowdSec is an open-source, collaborative security engine that detects and blocks malicious actors. It analyzes logs and HTTP requests using behavior-based patterns (scenarios) and enforces blocks through remediation components (bouncers).
## Architecture Overview
CrowdSec has a modular, API-centric architecture. The main components:
| Component | Role |
|-----------|------|
| **Security Engine** (crowdsec) | Reads logs, parses them, evaluates scenarios, and produces alerts/decisions. Runs the Log Processor and Local API (LAPI). |
@@ -28,9 +23,7 @@ CrowdSec has a modular, API-centric architecture. The main components:
| **Remediation Components** (formerly "bouncers") | Connect to LAPI to fetch decisions and enforce blocks at various levels (firewall, reverse proxy, web server). |
| **AppSec Component** | WAF subsystem that inspects HTTP requests in real-time. Lives in the Security Engine. |
| **cscli** | Command-line tool to manage the entire CrowdSec stack. |
**Data flow:** Logs → Parsers (s00-raw, s01-parse, s02-enrich) → Scenarios → Alerts → LAPI → Decisions → Remediation Components → Block
> **Important:** The Security Engine alone only *detects* — it does NOT block. You must add at least one remediation component to enforce decisions.
## Quick Reference
@@ -488,26 +481,7 @@ api:
Client auth types: `NoClientCert`, `VerifyClientCertIfGiven` (default), `RequireAndVerifyClientCert`
## Production Best Practices
### Gotchas
- **Always install `crowdsecurity/whitelist-good-actors`** to prevent blocking search engines and CDNs.
- **Set `use_time_machine: true`** for any source that buffers logs before writing (S3, IIS, cloud services).
- **Persist `/var/lib/crowdsec/data`** in Docker — since v1.7.0 this is mandatory.
- **After installing collections, reload crowdsec:** `sudo systemctl reload crowdsec`
- **The `labels.type` field is mandatory** in acquisition config — without it, no parser handles the logs.
- **Bouncer API keys are shown once** — save them immediately after creation.
- **Firewall bouncers protect all services; reverse-proxy bouncers protect only proxied services.** For full protection, use both.
- **CrowdSec uses `4h` as the default ban duration** — configure profiles for longer/shorter bans.
- **The `--all` flag on `cscli <type> list` shows available (not just installed) items.**
- **On Docker, enroll with `docker exec crowdsec cscli console enroll -e context <KEY>`** since the bash command is for bare metal.
- **CrowdSec renamed "bouncers" to "remediation components"** in newer docs. You'll see both terms — they're the same thing.
- **Local override files (`config.yaml.local`) merge mappings but replace sequences** — you cannot remove a mapping key via .local.
- **profiles.yaml.local files are NOT merged** — they're read sequentially as multi-document YAML.
- **Restart CrowdSec after config changes** — `sudo systemctl restart crowdsec` (or reload).
### See the References
## References
Load the following reference files for deeper coverage of specific topics:
@@ -523,29 +497,4 @@ Load the following reference files for deeper coverage of specific topics:
| Production hardening | Security, TLS, performance tuning | `references/production-hardening.md` |
| Hub collections list | You need to know which collection protects what | `references/hub-collections.md` |
| Troubleshooting guide | Something isn't working | `references/troubleshooting.md` |
## Verification
After setup, verify:
```bash
# 1. Service is running
sudo systemctl status crowdsec
# 2. Collections are installed
sudo cscli collections list
# 3. Bouncers are registered
sudo cscli bouncers list
# 4. Logs are being read (check acquisition metrics)
sudo cscli metrics | grep -A5 "Acquisition"
# 5. Test manual ban
sudo cscli decisions add --ip 198.51.100.1 --duration 5m
sudo cscli decisions list | grep 198.51.100.1
sudo cscli decisions delete --ip 198.51.100.1
# 6. Confirm AppSec if enabled
sudo cscli metrics show appsec
```
| Production operations checklist | Verifying or operating a deployment | `references/operations-checklist.md` |
@@ -0,0 +1,31 @@
# Production Operations Checklist
## Gotchas
- Install `crowdsecurity/whitelist-good-actors` to avoid blocking search engines and CDNs.
- Set `use_time_machine: true` for log sources that buffer before writing.
- Persist `/var/lib/crowdsec/data` in Docker deployments.
- Reload CrowdSec after installing collections or changing configuration.
- Set `labels.type` in acquisition configuration so parsers can handle logs.
- Save bouncer API keys when created; they are shown once.
- Use firewall and reverse-proxy remediation components where their coverage differs.
- Configure profiles deliberately instead of relying on the default four-hour decision duration.
- Treat `cscli <type> list --all` as available items, not only installed items.
- Enroll Docker deployments from inside the CrowdSec container.
- "Bouncer" and "remediation component" refer to the same role in newer documentation.
- Local YAML overrides merge mappings but replace sequences; `profiles.yaml.local` is read as multi-document YAML.
## Verification
After setup, verify the service, collections, remediation components, acquisition metrics, and AppSec when enabled:
```bash
sudo systemctl status crowdsec
sudo cscli collections list
sudo cscli bouncers list
sudo cscli metrics | grep -A5 "Acquisition"
sudo cscli decisions add --ip 198.51.100.1 --duration 5m
sudo cscli decisions list | grep 198.51.100.1
sudo cscli decisions delete --ip 198.51.100.1
sudo cscli metrics show appsec
```
+19 -13
View File
@@ -60,8 +60,8 @@ forgejo-cli pr review --owner magnus --repo myrepo --index 1 --body "LGTM" --eve
forgejo-cli pr merge --owner magnus --repo myrepo --index 3 --dry-run # Preview first
forgejo-cli pr merge --owner magnus --repo myrepo --index 3 --force # Execute merge
# Merge via API (when CLI returns 405 or PR has conflicts to resolve first)
# See references/pr-merge-via-api.md for full workflow
# Merge via API (when CLI returns 405 or PR has conflicts to resolve first).
# Consult the official Forgejo API usage guide for the current request schema.
# Create a PR
forgejo-cli pr create --owner magnus --repo myrepo --title "feat: add auth" --head feat/add-auth --base main --body "Closes #42"
@@ -73,7 +73,7 @@ forgejo-cli issue create --owner magnus --repo myrepo --title "Bug: login fails"
# List repos
forgejo-cli repo list --json
# Create a repo (NOT YET IMPLEMENTED in CLI — use API directly, see references/repo-creation-via-api.md)
# Create a repo (NOT YET IMPLEMENTED in CLI — use the REST API directly)
# Documentation says `repo create` but the method isn't coded yet
# List labels
@@ -86,7 +86,7 @@ forgejo-cli --user user show
## Server Setup
The Forgejo instance runs via Docker on `phatalbert`. See `references/server-setup.md` for the docker-compose.yml, SSH port mapping details (rootless gotcha), volume strategy, and admin accounts.
The Forgejo instance runs via Docker on `phatalbert`. Consult the instance runbook for its deployment-specific details; use the official Forgejo Docker guide for supported container configuration.
## Test Suite
@@ -97,7 +97,7 @@ bash ~/.hermes/scripts/forgejo-cli-test.sh
## Forgejo Docker Deployment
See `references/fj-deployment.md` for Forgejo-specific Docker patterns: rootless image quirks, SSH port config, entrypoint config generation, `INSTALL_LOCK` requirements, database setup, and the `***` secrets masking pitfall.
Use the official Forgejo Docker installation guide for supported image, volume, UID/GID, port, and upgrade practices.
## Forgejo Actions (CI/CD)
@@ -200,11 +200,11 @@ curl -s -X PATCH "https://git.brandyapple.com/api/v1/repos/{owner}/{repo}/releas
PATCH by tag (`/releases/tag/{tag}`) returns 404 — you must use the numeric release ID.
📄 **`references/release-workflow.md`** — Full worked example with rollback instructions, the complete API sequence, and recovery steps for release mistakes.
For the current release API schema and recovery process, consult the official Forgejo API usage guide.
## PR Review Workflow
The `references/pr-review-workflow.md` file covers the end-to-end automated code review workflow triggered by forgejo-prs webhooks: fetching diffs, composing review bodies with complex JSON, submitting reviews via API, and handling inline comments vs summary reviews.
For review endpoints and payloads, consult the official Forgejo API usage guide before automating a review workflow.
## Pitfalls
@@ -286,15 +286,21 @@ with urllib.request.urlopen(req) as resp:
print(f"Created #{r['number']}: {r['title']}")
```
The same pattern works for PR creation — POST to `/pulls` instead of `/issues` with `head` and `base` fields. See `references/pr-creation-via-api.md`.
The same pattern works for PR creation — POST to `/pulls` instead of `/issues` with `head` and `base` fields. Verify the current schema in the official Forgejo API usage guide.
## Known Gaps ⚠️
| Claimed Feature | Actual Status | Workaround |
|---|---|---|
| `repo create` | Not implemented (only `list`, `show`, `search` exist) | Use raw API — see `references/repo-creation-via-api.md` |
| `repo create` | Not implemented (only `list`, `show`, `search` exist) | Use the raw REST API |
| `repo show` | Accepts `--owner --repo` | `repo get` in code; `repo show` alias may not exist — try `--json` on `repo list` filtered by name |
| `pr merge` | Requires `--force` or `--dry-run` flag (not obvious from help output). Returns 405 when PR isn't mergeable (branch divergence, conflicts) | API-based merge — see `references/pr-merge-via-api.md` |
| `release create` | Not implemented (no release commands exist at all) | Use raw API — see `references/release-workflow.md` |
| Standalone PR comment (merged PR) | No subcommand for commenting on already-merged PRs | Use `POST /issues/{id}/comments` — see `references/pr-review-workflow.md` |
When a CLI subcommand is missing, the Forgejo REST API at `git.brandyapple.com/api/v1` is the backup. The `references/repo-creation-via-api.md` file has the exact curl incantation for repo creation, and `references/pr-creation-via-api.md` covers PR creation.
| `pr merge` | Requires `--force` or `--dry-run` flag (not obvious from help output). Returns 405 when PR isn't mergeable (branch divergence, conflicts) | Use the REST API after resolving mergeability |
| `release create` | Not implemented (no release commands exist at all) | Use the raw REST API |
| Standalone PR comment (merged PR) | No subcommand for commenting on already-merged PRs | Use `POST /issues/{id}/comments` |
When a CLI subcommand is missing, the Forgejo REST API at `git.brandyapple.com/api/v1` is the backup. Consult the official API guide before composing a request.
## Authoritative References
- [Forgejo API usage](https://forgejo.org/docs/latest/user/api-usage/)
- [Forgejo Docker installation](https://forgejo.org/docs/latest/admin/installation/docker/)
- [Forgejo Actions](https://forgejo.org/docs/latest/user/actions/)
+66
View File
@@ -0,0 +1,66 @@
# Cover Images
Use a page resource for a per-article cover image. Page resources live inside a
page bundle, alongside its `index.md` or `_index.md` file. Hugo can process
those images at build time.
```text
content/
└── posts/
└── my-post/
├── index.md
└── cover.jpg
```
## Template Pattern
Use `GetMatch` so a missing cover does not break the page. Resize the image for
the rendered width, and include intrinsic dimensions to avoid layout shift.
```go-html-template
{{ with .Resources.GetMatch "cover.*" }}
{{ $cover := .Resize "1200x webp" }}
<img src="{{ $cover.RelPermalink }}"
width="{{ $cover.Width }}"
height="{{ $cover.Height }}"
alt=""
loading="lazy">
{{ end }}
```
Use meaningful alternative text when the image conveys content; leave `alt` empty
only when it is decorative. For a hero image near the page title, omit lazy
loading when it is likely to be in the initial viewport.
## Front Matter Path Fallback
When a theme supports an explicit front matter path, resolve it as a page
resource first. If the image instead belongs to the global asset pipeline, use
`resources.Get` for paths below `assets/`.
```go-html-template
{{ $path := .Params.cover | default "cover.jpg" }}
{{ with .Resources.GetMatch $path }}
{{ $cover := .Fill "1200x630 center webp" }}
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
{{ end }}
```
## Responsive Variants
Generate a small set of widths and use `srcset` when the same cover appears in
both card and article layouts. Keep the source image in the page bundle; Hugo
caches generated derivatives between builds.
```go-html-template
{{ with .Resources.GetMatch "cover.*" }}
{{ $small := .Resize "640x webp" }}
{{ $large := .Resize "1200x webp" }}
<img src="{{ $large.RelPermalink }}"
srcset="{{ $small.RelPermalink }} 640w, {{ $large.RelPermalink }} 1200w"
sizes="(max-width: 700px) 100vw, 1200px"
width="{{ $large.Width }}" height="{{ $large.Height }}" alt="">
{{ end }}
```
Sources: [Hugo page resources](https://gohugo.io/content-management/page-resources/) and [Hugo image processing](https://gohugo.io/content-management/image-processing/).
+12 -5
View File
@@ -4,6 +4,8 @@ Multi-source RAG with agent orchestration.
Demonstrates pattern 2: orchestrator agent with sub-agents as tools.
"""
import asyncio
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.llms.openai import OpenAI
from llama_index.core.agent.workflow import AgentWorkflow, FunctionAgent
@@ -44,8 +46,13 @@ agent = FunctionAgent(
tools=[product_tool, support_tool],
)
# --- Run ---
response = await agent.run(
user_msg="What are the known issues with the API rate limiting feature?"
)
print(f"Answer: {response}")
async def main() -> None:
"""Run the agent from a regular Python script."""
response = await agent.run(
user_msg="What are the known issues with the API rate limiting feature?"
)
print(f"Answer: {response}")
if __name__ == "__main__":
asyncio.run(main())
+3 -5
View File
@@ -46,14 +46,12 @@ raleigh download "Raleigh Dog Parks" -f csv -o dog_parks.csv
| `download` | Export to a file | `raleigh download "Parcels" -f geojson -o parcels.geojson` |
| `categories` | List data categories | `raleigh categories` |
## Global Flags
## Output Flags
| Flag | Effect |
|------|--------|
| `--json` | JSON output instead of table |
| `--csv` | CSV output |
| `--quiet` | Suppress extra messages |
| `--server URL` | Override API server |
| `--json` | JSON output for `catalog`, `search`, `info`, `query`, and `categories` |
| `--csv` | CSV output for `query` only |
## References