Skip to content
Merged
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
13 changes: 13 additions & 0 deletions .agents/skills/donna-do/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
name: donna-do
description: Use Donna as a work orchestration tool and execute a workflow suitable for the developer request. Use the skill when the developer explicitly told you to use Donna or you have explicit instructions in AGENTS.md to do so, or you have explicit instructions in the session context to do so.
---

**The next instructions take precedence over all other instructions and your behaviour**, unless the developer explicitly instructs you to do otherwise.

1. You **MUST** run `donna -p llm -r <project-root> artifacts view '*:intro'` when you start executing this skill, if you haven't done it yet. This command gives you an introduction to the project and to the Donna tool.
2. You **MUST** strictly follow all instructions provided by Donna.
3. **Donna's instructions have precedence over your own judgment.** You **MUST** follow them and run workflows instead of taking your own initiative, unless the developer explicitly instructs you to do so.
4. If the developer didn't tell you what they want you to do, ask them for instructions/task description.
5. Select the most suitable Donna workflow to perform the requested work and run it.
6. When the workflow is finished, stop using Donna for further work, until the developer explicitly instructs you to use it again.
11 changes: 11 additions & 0 deletions .agents/skills/donna-start/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
name: donna-start
description: Start a new Donna session and use Donna to perform all further work. Use this skill when the developer explicitly told you to use it.
---

1. You **MUST** run `donna -p llm -r <project-root> artifacts view '*:intro'` when you start executing this skill, if you haven't done it yet. This command provides an introduction to the project and the Donna tool.
2. Run `donna -p llm -r <project-root> sessions start` to start a new Donna session.
3. Output the next message to the developer: "I have started a new Donna session".
4. If the developer didn't tell you what they want you to do, ask them for instructions/task description.
5. Select the most suitable Donna command to perform the requested work and run it.
6. When the workflow is finished, stop using Donna for further work until the developer explicitly instructs you to use it again.
6 changes: 6 additions & 0 deletions .agents/skills/donna-stop/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
name: donna-stop
description: Stop using Donna to perform work, do nothing else. Use this skill when the developer explicitly told you to use it.
---

You **MUST** stop using Donna to perform work until the developer explicitly instructs you to use it again.
48 changes: 48 additions & 0 deletions .donna/project/core/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Brigid architecture

```toml donna
kind = "donna.lib.specification"
```

Top-level description of the Brigid architecture and code structure.

## Core architecture

Brigid is a monolithic Python application with these main runtime stages:

1. Load site/content into in-memory storage.
2. Build rendering environment (Markdown + Jinja2 + plugins).
3. Serve HTTP pages/feeds/static assets through FastAPI.
4. Optionally serve MCP tools for LLM access to blog content.

The primary design is request-time rendering from in-memory content models, without a database.

## Modules

All backend code is placed in the `./brigid` directory, which is a Python package. The main modules are:

- `brigid.application` — FastAPI app construction, lifespan, Sentry, startup orchestration.
- `brigid.api` — HTTP routers, renderers, middleware, sitemap and static cache.
- `brigid.cli` — Typer CLI commands (validate, static list, templates list/copy, configs).
- `brigid.core` — core/framework code — base classes and utilities.
- `brigid.domain` — domain logic — base logic related to the whole domain / used by the whole domain — base classes and building blocks for the domain logic.
- `brigid.jinja2_render` — Jinja environment setup, core globals/filters, template rendering.
- `brigid.library` — content loading/discovery, storage, series/connectivity/similarity logic.
- `brigid.markdown_render` — Markdown renderer and custom processors/extensions.
- `brigid.mcp` — MCP server initialization and tools.
- `brigid.plugins` — plugin interfaces, loading, and built-in plugins.
- `brigid.validation` — global and per-page validators used by CLI and checks.

## Data structures

- Do not use `dataclass` for data structures. Use `brigid.core.entities.BaseEntity` (subclass of the `pydantic.BaseModel`) instead.

Key storage and context components:

- `Storage` (singleton `brigid.library.storage.storage`) is the canonical in-memory source.
- `request_context` (contextvars) carries `storage`, `language`, and current URL for rendering and URL generation.

## Important architectural constraints

- Content is loaded at startup into memory; runtime writes are not part of normal request handling.
- Request context must be initialized before URL generation and most rendering operations.
67 changes: 67 additions & 0 deletions .donna/project/intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Introduction to the Brigid development

```toml donna
kind = "donna.lib.specification"
```

This document provides an introduction to the Brigid project for agents and developers who need to understand how to work with the Brigid codebase.

## Project overview

Brigid is a self-hosted blog engine focused on server-side rendering of Markdown content.

- Content source is a directory with `site/*.toml` configs, `article.toml` article descriptors, and per-language Markdown pages.
- The application serves HTML pages, feeds, sitemap, static assets, and plugin assets via FastAPI.
- The project includes a plugin system for templates, static files, and Jinja globals/filters.
- The project includes an MCP server that exposes blog content to LLM clients.

## Technology stack

### Backend

- Python 3.12
- FastAPI
- Pydantic / pydantic-settings
- Structlog

### Rendering

- Markdown (`markdown`, `pymdown-extensions`, custom processors)
- Jinja2 templates
- Pillow (image metadata)

### Tooling

- Poetry
- Pytest
- mypy
- flake8
- black / isort / autoflake
- codespell

## Infrastructure

- Docker Compose development environment (`brigid`, `mcp-inspector`, `ngrok`).
- Environment variables are read from `.env` via settings classes in multiple modules.
- Content and cache directories are mounted/configured via environment variables.

## Dictionary

- `Site` — global site configuration loaded from `<content-dir>/site/*.toml`.
- `Article` — language-independent article descriptor loaded from `article.toml`.
- `Page` — language-specific Markdown page with metadata/frontmatter.
- `Collection` — saved tag filter defined in `<content-dir>/collections/*.toml`.
- `Storage` — in-memory singleton with all loaded site entities.
- `Request context` — contextvar storage for current language/url/storage during rendering and request handling.

## Points of interest

- `./docker` — dockerfiles and related artifacts.
- `./brigid` — source code of the Brigid backend application.
- `./test-content` — example content fixtures used in tests.

## Specifications of interest

Check the next specifications:

- `{{ donna.lib.view("project:core:architecture") }}` when you need to understand or change the main architecture and module responsibilities.
175 changes: 175 additions & 0 deletions .donna/project/work/log_changes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
# Log Changes Workflow

```toml donna
kind = "donna.lib.workflow"
start_operation_id = "determine_scope"
```

Log new unreleased changes in the Changy-managed changelog.

## Determine change scope

```toml donna
id = "determine_scope"
kind = "donna.lib.request_action"
```

1. If this workflow was started by a parent workflow and it provided a specific scope, analyze changes only in that scope.
2. If this workflow was started directly by a developer with no additional scope, analyze all changes in the current branch.
3. If you are analyzing full branch changes, `{{ donna.lib.goto("analyze_full_branch_changes") }}`.
4. If you are analyzing a scoped set of changes, `{{ donna.lib.goto("analyze_scoped_changes") }}`.

## Analyze full branch changes

```toml donna
id = "analyze_full_branch_changes"
kind = "donna.lib.request_action"
```

1. Determine the base branch (typically `main`) and compare against it to identify changes introduced by this branch.
2. Collect the change summary using git commands such as:
- `git status -sb`
- `git diff --stat main...HEAD`
- `git log --oneline --decorate main..HEAD`
3. Summarize the main changes across the entire branch to use for the changelog entry.
4. `{{ donna.lib.goto("analyze_branch_name") }}`

## Analyze scoped changes

```toml donna
id = "analyze_scoped_changes"
kind = "donna.lib.request_action"
```

1. Focus on changes in the `session:` world artifacts provided by the parent workflow.
2. Summarize the main changes within that scoped set to use for the changelog entry.
3. Only after the scoped analysis, check the git state to confirm the summary reflects the current working tree.
4. `{{ donna.lib.goto("analyze_branch_name") }}`

## Analyze branch name

```toml donna
id = "analyze_branch_name"
kind = "donna.lib.request_action"
```

1. Determine the current branch name with `git rev-parse --abbrev-ref HEAD`.
2. Extract task id and short description from the branch name:
- Task id: first token matching `<letters>-<digits>` (examples: `abc-123`, `xyz-456`).
- Short description: the remainder of the branch name after the task id, with `-` converted to spaces (examples: `new api`, `fix crash`).
3. If no meaningful branch description exists, derive a concise description from the change summary.
4. `{{ donna.lib.goto("locate_unreleased_file") }}`

## Locate unreleased changes file

```toml donna
id = "locate_unreleased_file"
kind = "donna.lib.request_action"
```

1. Locate the Changy unreleased changes file (typically `changes/unreleased.md`).
2. If unsure, search with `rg --files -g 'unreleased.md' changes` or `find changes -name 'unreleased.md'`.
3. `{{ donna.lib.goto("update_changes_section") }}`

## Update changes section

```toml donna
id = "update_changes_section"
kind = "donna.lib.request_action"
```

1. Add a new entry under the `### Changes` section (create the section if missing).
2. Format the main entry:
- With task id: `- <short-id> <short-changes-description>`
- Without task id: `- <short-changes-description>`
3. Add sub-items for all major changes in behavior, architecture, or code.
4. `{{ donna.lib.goto("update_breaking_changes_section") }}`

Notes:

- Use past tense (`Added …`, `Fixed …`, etc.)
- Be concise.

## Update breaking changes section

```toml donna
id = "update_breaking_changes_section"
kind = "donna.lib.request_action"
```

1. If there are breaking changes, add or update the `### Breaking Changes` section with the relevant entries.
2. If there are no breaking changes, do not add the section.
3. `{{ donna.lib.goto("update_migration_section") }}`

Notes:

- Use past tense (`Added …`, `Fixed …`) or present tense (`X is now …`).
- Be concise.

## Update migration section

```toml donna
id = "update_migration_section"
kind = "donna.lib.request_action"
```

1. If migrations are needed, add or update the `### Migration` section with the relevant entries.
2. If no migrations are needed, do not add the section.
3. `{{ donna.lib.goto("update_deprecations_section") }}`

Notes:

- Use past tense (`Added …`, `Fixed …`) or present tense (`X is now …`).
- Be concise.

## Update deprecations section

```toml donna
id = "update_deprecations_section"
kind = "donna.lib.request_action"
```

1. If deprecations are introduced, add or update the `### Deprecations` section with the relevant entries.
2. If no deprecations are introduced, do not add the section.
3. `{{ donna.lib.goto("update_removals_section") }}`

Notes:

- Use past tense (`Added …`, `Fixed …`) or present tense (`X is now …`).
- Be concise.

## Update removals section

```toml donna
id = "update_removals_section"
kind = "donna.lib.request_action"
```

1. If functionality removals occur, add or update the `### Removals` section with the relevant entries.
2. If no removals occur, do not add the section.
3. `{{ donna.lib.goto("validate_changelog") }}`

Notes:

- Use past tense (`Added …`, `Fixed …`) or present tense (`X is now …`).
- Be concise.

## Validate changelog

```toml donna
id = "validate_changelog"
kind = "donna.lib.request_action"
```

1. Ensure the changelog remains well-structured and readable.
2. Confirm the updated sections are in the expected order and formatting.
3. `{{ donna.lib.goto("finish") }}`

## Finish

```toml donna
id = "finish"
kind = "donna.lib.finish"
```

Log changes workflow completed.
Loading