Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .agents/skills/align/ADR-FORMAT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# ADR format

ADRs record _that_ a decision was made and _why_. They live in `docs/adr/`, numbered `0001-slug.md`, `0002-slug.md`, … Create the directory only when the first ADR is due.

## Template

```md
# {Decision in a short title}

{1–3 sentences: the situation, what we chose, and why.}
```

A single paragraph is enough. The worth is in the record, not in filling sections.

## Optional sections

Add only when they earn their place — most ADRs need none:

- **Status** (`proposed | accepted | deprecated | superseded by ADR-NNNN`) — when decisions get revisited.
- **Options considered** — when the rejected paths are worth remembering.
- **Consequences** — when downstream effects aren't obvious.

## Numbering

Take the highest number in `docs/adr/` and add one.

## When to write one

All three must hold:

1. **Costly to undo** — reversing later hurts.
2. **Non-obvious** — a future reader will ask "why this way?"
3. **A real trade-off** — there were live alternatives and you chose one deliberately.

Easy to reverse? Skip it. Obvious? Nobody will wonder. No alternative? Nothing to record.
36 changes: 36 additions & 0 deletions .agents/skills/align/CONTEXT-FORMAT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# CONTEXT.md format

A `CONTEXT.md` is a glossary for one domain — nothing else. It fixes the words the team uses so code, docs, and conversation stay aligned.

## Shape

```md
# {Context name}

{One or two sentences: what this context covers and why it exists.}

## Language

**Room**:
A Matrix room: a set of members sharing one event timeline.
_Avoid_: channel, chat, group

**Practitioner**:
A healthcare professional who acts in the system on behalf of an organization.
_Avoid_: doctor, user, staff

**Patient**:
The natural person a health record belongs to, distinct from the user operating the system.
_Avoid_: user, account, client
```

## Rules

- **Pick one word per concept.** List the rejected synonyms under `_Avoid_`.
- **One or two sentences.** Say what the term _is_, not what it does.
- **Context-specific only.** Skip general engineering terms (timeouts, error enums, `famedly-rust-utils` helpers). Ask: is this concept unique to this domain? If not, leave it out.
- **Cluster under subheadings** when groups emerge; a flat list is fine for one tight area.

## Where it lives

One `CONTEXT.md` at the repo root, created the first time a term is pinned down. If a repo ever grows several distinct domains, drop a `CONTEXT.md` into each subtree and use the one nearest the code in play — no central index needed for now.
90 changes: 90 additions & 0 deletions .agents/skills/align/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
name: align
description: Pressure-test a plan or design with the engineer until it is fully aligned, walking every branch of the decision tree and checking it against Famedly's documented language (CONTEXT.md) and decisions (ADRs), updating those docs as agreement lands. Decisions are raised as multiple-choice prompts through the agent's question tool; when aligned, optionally captures the result as a PRD (Notion, Jira, or repo). Use when the user wants to create a plan, yet also invoke this skill proactively before starting any non-trivial change: one carrying genuine design choices or ambiguity, or spanning multiple files, unfamiliar code, or real research. Skip trivial, well-specified edits (a rename, a one-liner, a typo).
---

<job>

Drive the plan to alignment. Take the decision tree branch by branch, settle dependencies before the choices that rest on them, and put a recommended answer on every decision.

Answer your own questions from the code first — search the repo, read the relevant crate/module — and only bring me what truly needs my intent or domain knowledge.

</job>

<when-to-engage>

Engage proactively, before starting the work — not only on an explicit "align" invocation. A change is worth aligning on when it carries genuine design choices or ambiguity, or when it spans multiple files, unfamiliar code, or real research. A trivial, well-specified edit — a rename, a one-liner, a typo fix — needs none of this; just do it.

Right-size the effort to the task. Scale the number of rounds and the depth of grilling to the ambiguity and blast radius: a medium, mostly-clear change may need a single round on the one real decision, while a large or open-ended one earns the full tree. If exploring the code shows the task is actually trivial or already unambiguous, say so and drop straight into the work rather than manufacturing questions.

</when-to-engage>

<how-to-ask>

Raise decisions through whatever structured question tool the agent runtime exposes:

- **Cursor** → `AskQuestion` or similar,
- **Claude Code / Claude CLI** → `AskUserQuestion` or similar,
- **none tool available** → ask questions in chat one by one.

For each question:

1. Group related but independent decisions together (1–5 per round). Resolve upstream choices first; only ask dependent follow-ups once their parent is settled.
2. Lead with your recommended option, tag it `Recommended:`, and justify it in one line.
3. Give at least two real options plus a way for user to specify their own answer. Allow multi-select when several answers can hold at once.
4. Keep rounds going until the tree is exhausted, then restate the settled decisions back to me.

</how-to-ask>

<capture-the-outcome>

Once the tree is settled, summarize the agreed decisions. Then ask me — via the same question tool — how to capture them:

- **Keep in chat only** — the alignment lives in this conversation; write nothing.
- **Write a PRD** — produce the structured doc below. Then ask _where_: a Notion page, a Jira ticket, or a markdown file in the repo. Default to whatever I've used for this work already.

Synthesize the PRD from what we settled — do not re-interview me. Use `CONTEXT.md` vocabulary throughout; keep file paths and code snippets out (they rot), except a short snippet that pins a precise decision (a type, schema, or state machine).

```md
# {Title}

## Problem

{The problem, from the user's view.}

## Solution

{The chosen approach, from the user's view.}

## User stories

1. As a {actor}, I want {capability}, so that {benefit}.
{Cover every facet we aligned on.}

## Decisions

{Modules touched, interfaces, schema/API contracts, trade-offs settled, the test seams (prefer existing, highest possible).}

## Out of scope

{What we deliberately excluded.}
```

</capture-the-outcome>

<check-against-the-docs>

While exploring, pull in the project's domain docs and verify the plan against them.

**Locate them:** expect a `CONTEXT.md` plus `docs/adr/` at the repo root (or the nearest one to the code in play). Write these files only once you have something concrete to record and I've confirmed docs should be created.

During the alignment:

- **Term clashes** — when I use a word against its `CONTEXT.md` meaning, stop me: "Glossary says 'room' is X; you mean Y — which holds?"
- **Vague words** — offer a precise canonical term ("'user' — the account, the Matrix user, or the patient?").
- **Edge scenarios** — invent concrete cases (federation, multi-tenant, gematik/ePA flows, GDPR deletion) to force sharp boundaries.
- **Code reality** — when a claim conflicts with the code, name the contradiction.
- **Record terms live** in `CONTEXT.md` as they settle — never batch. It stays a pure glossary: no implementation, specs, or notes. See [CONTEXT-FORMAT.md](./CONTEXT-FORMAT.md).
- **Suggest an ADR only** when the call is costly to undo, non-obvious to a later reader, and a genuine trade-off. Otherwise skip. See [ADR-FORMAT.md](./ADR-FORMAT.md).

</check-against-the-docs>
33 changes: 33 additions & 0 deletions .config/filegen-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"clobber-by-default": null,
"files": [
{
"clobber": true,
"deactivate": null,
"ignore-modification": null,
"permissions": "600",
"source": "/nix/store/is33zqwvd62zv52jjjk2xqf34p2n5hpz-ADR-FORMAT.md",
"target": "./.agents/skills/align/ADR-FORMAT.md",
"type": "copy"
},
{
"clobber": true,
"deactivate": null,
"ignore-modification": null,
"permissions": "600",
"source": "/nix/store/1rd8h8d3nniwnzm8lvq999l439v3vppl-CONTEXT-FORMAT.md",
"target": "./.agents/skills/align/CONTEXT-FORMAT.md",
"type": "copy"
},
{
"clobber": true,
"deactivate": null,
"ignore-modification": null,
"permissions": "600",
"source": "/nix/store/2wq7jci81iq1976yaghqais7cbd38j4p-SKILL.md",
"target": "./.agents/skills/align/SKILL.md",
"type": "copy"
}
],
"version": 3
}
35 changes: 35 additions & 0 deletions llm/skills/align/ADR-FORMAT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# ADR format

ADRs record _that_ a decision was made and _why_. They live in `docs/adr/`, numbered `0001-slug.md`, `0002-slug.md`, … Create the directory only when the first ADR is due.

## Template

```md
# {Decision in a short title}

{1–3 sentences: the situation, what we chose, and why.}
```

A single paragraph is enough. The worth is in the record, not in filling sections.

## Optional sections

Add only when they earn their place — most ADRs need none:

- **Status** (`proposed | accepted | deprecated | superseded by ADR-NNNN`) — when decisions get revisited.
- **Options considered** — when the rejected paths are worth remembering.
- **Consequences** — when downstream effects aren't obvious.

## Numbering

Take the highest number in `docs/adr/` and add one.

## When to write one

All three must hold:

1. **Costly to undo** — reversing later hurts.
2. **Non-obvious** — a future reader will ask "why this way?"
3. **A real trade-off** — there were live alternatives and you chose one deliberately.

Easy to reverse? Skip it. Obvious? Nobody will wonder. No alternative? Nothing to record.
36 changes: 36 additions & 0 deletions llm/skills/align/CONTEXT-FORMAT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# CONTEXT.md format

A `CONTEXT.md` is a glossary for one domain — nothing else. It fixes the words the team uses so code, docs, and conversation stay aligned.

## Shape

```md
# {Context name}

{One or two sentences: what this context covers and why it exists.}

## Language

**Room**:
A Matrix room: a set of members sharing one event timeline.
_Avoid_: channel, chat, group

**Practitioner**:
A healthcare professional who acts in the system on behalf of an organization.
_Avoid_: doctor, user, staff

**Patient**:
The natural person a health record belongs to, distinct from the user operating the system.
_Avoid_: user, account, client
```

## Rules

- **Pick one word per concept.** List the rejected synonyms under `_Avoid_`.
- **One or two sentences.** Say what the term _is_, not what it does.
- **Context-specific only.** Skip general engineering terms (timeouts, error enums, `famedly-rust-utils` helpers). Ask: is this concept unique to this domain? If not, leave it out.
- **Cluster under subheadings** when groups emerge; a flat list is fine for one tight area.

## Where it lives

One `CONTEXT.md` at the repo root, created the first time a term is pinned down. If a repo ever grows several distinct domains, drop a `CONTEXT.md` into each subtree and use the one nearest the code in play — no central index needed for now.
90 changes: 90 additions & 0 deletions llm/skills/align/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
name: align
description: Pressure-test a plan or design with the engineer until it is fully aligned, walking every branch of the decision tree and checking it against Famedly's documented language (CONTEXT.md) and decisions (ADRs), updating those docs as agreement lands. Decisions are raised as multiple-choice prompts through the agent's question tool; when aligned, optionally captures the result as a PRD (Notion, Jira, or repo). Use when the user wants to create a plan, yet also invoke this skill proactively before starting any non-trivial change: one carrying genuine design choices or ambiguity, or spanning multiple files, unfamiliar code, or real research. Skip trivial, well-specified edits (a rename, a one-liner, a typo).
---

<job>

Drive the plan to alignment. Take the decision tree branch by branch, settle dependencies before the choices that rest on them, and put a recommended answer on every decision.

Answer your own questions from the code first — search the repo, read the relevant crate/module — and only bring me what truly needs my intent or domain knowledge.

</job>

<when-to-engage>

Engage proactively, before starting the work — not only on an explicit "align" invocation. A change is worth aligning on when it carries genuine design choices or ambiguity, or when it spans multiple files, unfamiliar code, or real research. A trivial, well-specified edit — a rename, a one-liner, a typo fix — needs none of this; just do it.

Right-size the effort to the task. Scale the number of rounds and the depth of grilling to the ambiguity and blast radius: a medium, mostly-clear change may need a single round on the one real decision, while a large or open-ended one earns the full tree. If exploring the code shows the task is actually trivial or already unambiguous, say so and drop straight into the work rather than manufacturing questions.

</when-to-engage>

<how-to-ask>

Raise decisions through whatever structured question tool the agent runtime exposes:

- **Cursor** → `AskQuestion` or similar,
- **Claude Code / Claude CLI** → `AskUserQuestion` or similar,
- **none tool available** → ask questions in chat one by one.

For each question:

1. Group related but independent decisions together (1–5 per round). Resolve upstream choices first; only ask dependent follow-ups once their parent is settled.
2. Lead with your recommended option, tag it `Recommended:`, and justify it in one line.
3. Give at least two real options plus a way for user to specify their own answer. Allow multi-select when several answers can hold at once.
4. Keep rounds going until the tree is exhausted, then restate the settled decisions back to me.

</how-to-ask>

<capture-the-outcome>

Once the tree is settled, summarize the agreed decisions. Then ask me — via the same question tool — how to capture them:

- **Keep in chat only** — the alignment lives in this conversation; write nothing.
- **Write a PRD** — produce the structured doc below. Then ask _where_: a Notion page, a Jira ticket, or a markdown file in the repo. Default to whatever I've used for this work already.

Synthesize the PRD from what we settled — do not re-interview me. Use `CONTEXT.md` vocabulary throughout; keep file paths and code snippets out (they rot), except a short snippet that pins a precise decision (a type, schema, or state machine).

```md
# {Title}

## Problem

{The problem, from the user's view.}

## Solution

{The chosen approach, from the user's view.}

## User stories

1. As a {actor}, I want {capability}, so that {benefit}.
{Cover every facet we aligned on.}

## Decisions

{Modules touched, interfaces, schema/API contracts, trade-offs settled, the test seams (prefer existing, highest possible).}

## Out of scope

{What we deliberately excluded.}
```

</capture-the-outcome>

<check-against-the-docs>

While exploring, pull in the project's domain docs and verify the plan against them.

**Locate them:** expect a `CONTEXT.md` plus `docs/adr/` at the repo root (or the nearest one to the code in play). Write these files only once you have something concrete to record and I've confirmed docs should be created.

During the alignment:

- **Term clashes** — when I use a word against its `CONTEXT.md` meaning, stop me: "Glossary says 'room' is X; you mean Y — which holds?"
- **Vague words** — offer a precise canonical term ("'user' — the account, the Matrix user, or the patient?").
- **Edge scenarios** — invent concrete cases (federation, multi-tenant, gematik/ePA flows, GDPR deletion) to force sharp boundaries.
- **Code reality** — when a claim conflicts with the code, name the contradiction.
- **Record terms live** in `CONTEXT.md` as they settle — never batch. It stays a pure glossary: no implementation, specs, or notes. See [CONTEXT-FORMAT.md](./CONTEXT-FORMAT.md).
- **Suggest an ADR only** when the call is costly to undo, non-obvious to a later reader, and a genuine trade-off. Otherwise skip. See [ADR-FORMAT.md](./ADR-FORMAT.md).

</check-against-the-docs>
5 changes: 4 additions & 1 deletion nix/general/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
...
}:
importingFlake: {
imports = [ ./action-versions.nix ];
imports = [
./action-versions.nix
./skills.nix
];

config.perSystem =
{ config, ... }:
Expand Down
20 changes: 20 additions & 0 deletions nix/general/skills.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
_: {
perSystem =
{ lib, ... }:
let
skillsSrc = ../../llm/skills;
prefix = "${toString skillsSrc}/";
in
{
# Distribute the vendored agent skills into every environment under the
# cross-client `.agents/skills/` directory. smfh's `copy` only accepts
# file sources, so we emit one entry per file; parent directories are
# created automatically during activation.
filegen.settings.files = map (file: {
type = "copy";
target = "./.agents/skills/${lib.removePrefix prefix (toString file)}";
source = file;
clobber = true;
}) (lib.filesystem.listFilesRecursive skillsSrc);
};
}