Metadata-Version: 2.4
Name: stapel-tasks
Version: 0.4.0
Summary: Generic tasks and kanban boards for the Stapel framework
Author: Stapel
License: MIT
Project-URL: Homepage, https://stapel.dev
Project-URL: Repository, https://github.com/usestapel/stapel-tasks
Project-URL: Documentation, https://github.com/usestapel/stapel-tasks/blob/main/MODULE.md
Project-URL: Changelog, https://github.com/usestapel/stapel-tasks/blob/main/CHANGELOG.md
Project-URL: Issues, https://github.com/usestapel/stapel-tasks/issues
Keywords: django,stapel,tasks,kanban,boards,workflow
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: Django
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: stapel-core<1.0,>=0.27.0
Requires-Dist: djangorestframework>=3.14
Requires-Dist: drf-spectacular>=0.27
Provides-Extra: attributes
Requires-Dist: stapel-attributes<0.5,>=0.4; extra == "attributes"
Provides-Extra: all
Requires-Dist: stapel-attributes<0.5,>=0.4; extra == "all"
Dynamic: license-file

<!-- Generated by stapel-readme from docs/readme.md + docs/*.json. Do not edit this file; edit docs/readme.md and re-run `make readme`. -->

# stapel-tasks

[![CI](https://img.shields.io/github/actions/workflow/status/usestapel/stapel-tasks/ci.yml?branch=main&logo=github&label=CI)](https://github.com/usestapel/stapel-tasks/actions/workflows/ci.yml?query=branch%3Amain)
[![coverage](https://img.shields.io/codecov/c/github/usestapel/stapel-tasks?branch=main&logo=codecov&label=coverage)](https://app.codecov.io/gh/usestapel/stapel-tasks)
[![pypi](https://img.shields.io/pypi/v/stapel-tasks?logo=pypi&logoColor=white&label=pypi)](https://pypi.org/project/stapel-tasks/)
[![downloads](https://static.pepy.tech/badge/stapel-tasks/month)](https://pepy.tech/project/stapel-tasks)
[![python](https://img.shields.io/pypi/pyversions/stapel-tasks?logo=python&logoColor=white)](https://pypi.org/project/stapel-tasks/)
[![license](https://img.shields.io/github/license/usestapel/stapel-tasks)](https://github.com/usestapel/stapel-tasks/blob/main/LICENSE)
[![llms.txt](https://img.shields.io/badge/llms.txt-blue)](https://github.com/usestapel/stapel-tasks/blob/main/docs/llms.txt)

> Generic tasks and kanban boards: Board/Column/Task/ChecklistItem/TaskComment, a REST surface, a full outbox event surface, and custom fields via stapel-attributes. Usable standalone (a team runs a board by hand) or as the substrate an external orchestrator projects onto through opaque origin_* handles, a MOVE_POLICY authorization seam, and comm Functions (tasks.get/list_board/create/move/comment).

Part of the [Stapel framework](https://github.com/usestapel) — composable Django apps that deploy as a monolith or as microservices without changing module code.

## Install

```bash
pip install stapel-tasks
```

## At a glance

| Fact | Value |
|---|---|
| Version | `0.4.0` |
| Python | `>=3.11` (3.11, 3.12, 3.13, 3.14) |
| Django | `djangorestframework>=3.14` |
| HTTP operations | 22 |
| Config axes | 3 |
| Usage surface | 28 |
| Extension points | 5 |
| Error codes | 57 |
| Documented flows | 3 |
| Fleet dependencies | [`stapel-attributes`](https://github.com/usestapel/stapel-attributes) (optional) · [`stapel-core`](https://github.com/usestapel/stapel-core) |

## Documentation

[OpenAPI](https://github.com/usestapel/stapel-tasks/blob/main/docs/schema.json) · [capabilities.json](https://github.com/usestapel/stapel-tasks/blob/main/docs/capabilities.json) · [llms.txt (for agents)](https://github.com/usestapel/stapel-tasks/blob/main/docs/llms.txt)

## What this is

A **generic task domain** — Board / Column / Task / ChecklistItem /
TaskComment, a REST surface, a full outbox event surface, and custom fields
via stapel-attributes. It is useful to any project by itself (a team runs a
board by hand), and it is the substrate an orchestrator *projects* onto: an
external state machine drives cards through opaque `origin_*` handles and the
`MOVE_POLICY` seam — the module knows nothing about the machine.

## Quick start

```bash
pip install stapel-tasks              # core
pip install "stapel-tasks[attributes]"  # + typed custom-field validation
```

```python
INSTALLED_APPS = [
    # ...
    "stapel_tasks",
]

# urls.py
path("tasks/", include("stapel_tasks.urls"))
```

> **Requires** a stapel-core whose background `taskstore` app uses the label
> `stapel_taskstore` — this module owns the Django label `stapel_tasks`. See
> [MODULE.md](https://github.com/usestapel/stapel-tasks/blob/main/MODULE.md).

## Concepts

- **Board** — an ordered set of columns and the cards on them. Owns the
  custom-field *schema* (`feature_defs`) and optional workflow `settings`.
- **Column** — a status. Its `key` is the card's status; its `category`
  (`backlog/active/review/waiting/done`) is the fixed machine semantic.
- **Task (card)** — status = its column; order within the column is a
  fractional `position` (drag-and-drop moves write one row). Custom-field
  values live in `features`; a projecting system writes `origin_meta`.
- **Move** — drag-and-drop is a `move` validated by `MOVE_POLICY`:
  `allow` / `deny(reason_key)` / `defer` (the managed-card path).

Two reads of the same cards, deliberately: `GET boards/{id}/tasks` is a keyset
**feed** (`-created_at`), `GET boards/{id}/cards` is the **board shape** —
columns in order, cards grouped by column key and sorted by `position`. A
kanban view wants the second. `GET boards/presets` serves the vocabularies a
board-creation form needs (presets, categories, checklist states, priority
scale) instead of making the client hard-code them.

```python
from stapel_tasks import services

board = services.create_board(name="Team", preset="simple")
card = services.create_task(board=board, title="Ship it")
services.move_task(card, to_column=board.columns.get(key="done"))  # emits task.completed
```

## comm surface

| Kind | Name | Purpose |
|---|---|---|
| Emit | `task.created` / `task.updated` / `task.moved` / `task.assigned` / `task.completed` / `task.comment_added` / `task.checklist_item_changed` / `task.archived` | Card lifecycle facts (via the outbox) |
| Consume | `user.deleted` | GDPR anonymization |
| Function | `tasks.get` / `tasks.list_board` / `tasks.create` / `tasks.move` / `tasks.comment` | Machine interface / MCP-tool candidates |

## Settings (`STAPEL_TASKS`)

| Key | Default | What it customizes |
|---|---|---|
| `SCOPE_PROVIDER` | single global scope, allow-all | Tenancy resolution/filtering + permissions |
| `MOVE_POLICY` | allow any move (honours `transitions`) | Drag-and-drop authorization |
| `BOARD_PRESETS` | `{}` (merged over built-in `simple`) | Board-shape presets |
| `STORE_UNKNOWN_FEATURES` | `True` | Keep raw custom fields when attributes is absent |
| `DEFAULT_PAGE_SIZE` | `100` | Card-list page size |
| `BOARD_CARDS_MAX` | `2000` | Cap on the whole-board read (`truncated` beyond it) |
| `PRIORITY_SCALE` | low/normal/high/urgent | Priority steps served to clients |

See [MODULE.md](https://github.com/usestapel/stapel-tasks/blob/main/MODULE.md) for the full seam map (providers, registries, serializer
seams, comm tables, anti-patterns, override-vs-upstream).

## License

MIT — see [LICENSE](https://github.com/usestapel/stapel-tasks/blob/main/LICENSE).

---

<sub>This page is assembled by `stapel-readme` from `docs/readme.md` plus the contract artifacts in `docs/`. Edit the prose in `docs/readme.md`; the badges, facts and links above and below it are generated — do not hand-edit `README.md`.</sub>
