chore: prepare v0.1.0 release

This commit is contained in:
Chris Hendrickson 2026-04-28 15:22:41 -04:00
parent 7e1e7d0502
commit 07e8c98c7c
37 changed files with 363 additions and 147 deletions

12
.markdownlint-cli2.jsonc Normal file
View file

@ -0,0 +1,12 @@
{
"globs": [
"**/*.md"
],
"gitignore": true,
"config": {
"MD013": false,
"MD060": {
"style": "aligned"
}
}
}

View file

@ -1,11 +0,0 @@
export default {
globs: ['**/*.md'],
gitignore: true,
config: {
MD013: false,
MD040: true,
MD060: {
style: 'aligned',
},
},
};

View file

@ -12,6 +12,7 @@ labels:
Publish all four packages to pub.dev in dependency order, then tag the release. Publish all four packages to pub.dev in dependency order, then tag the release.
Order: Order:
1. `cd packages/core && dart pub publish` 1. `cd packages/core && dart pub publish`
2. `cd packages/kanban && dart pub publish` 2. `cd packages/kanban && dart pub publish`
3. `cd packages/mcp && dart pub publish` 3. `cd packages/mcp && dart pub publish`
@ -20,10 +21,11 @@ Order:
Wait for each to appear on pub.dev before publishing the next (pub.dev propagation can take a few minutes). Wait for each to appear on pub.dev before publishing the next (pub.dev propagation can take a few minutes).
After all four are published: After all four are published:
1. `git checkout main` 1. `git checkout main`
2. `git merge develop` 2. `git merge develop`
3. `git tag v1.0.0` 3. `git tag v1.0.0`
4. `git push origin main --tags` 4. `git push origin main --tags`
5. Create GitHub release at https://github.com/artificery-dev/dew/releases with CHANGELOG.md 1.0.0 section as body. 5. Create GitHub release at <https://github.com/artificery-dev/dew/releases> with CHANGELOG.md 1.0.0 section as body.
Prerequisite: DEW-0027 (final validation) must be done first. Prerequisite: DEW-0027 (final validation) must be done first.

View file

@ -8,4 +8,4 @@ links:
type: parent_of type: parent_of
--- ---
Add freeform milestone and label fields to tickets for grouping and filtering. Both are List<String> in ticket frontmatter. Add freeform milestone and label fields to tickets for grouping and filtering. Both are `List<String>` in ticket frontmatter.

View file

@ -8,4 +8,4 @@ links:
type: child_of type: child_of
--- ---
Move ticket .md files from flat .project/kanban/ into column subdirectories (.project/kanban/todo/DEW-0001.md). Attachments live at .project/kanban/attachments/<ticket-id>/ (stable path, unaffected by moves). TicketStore changes: _filePath needs column, findById searches all column dirs, move physically moves the .md file, delete removes .md + attachments/<id>/ if present, create writes into correct column dir. Move ticket .md files from flat .project/kanban/ into column subdirectories (.project/kanban/todo/DEW-0001.md). Attachments live at `.project/kanban/attachments/<ticket-id>/` (stable path, unaffected by moves). TicketStore changes: _filePath needs column, findById searches all column dirs, move physically moves the .md file, delete removes .md + `attachments/<id>/` if present, create writes into correct column dir.

View file

@ -8,4 +8,4 @@ links:
type: child_of type: child_of
--- ---
Add milestones: List<String> and labels: List<String> to the Ticket model and YAML frontmatter. Support --milestone and --label flags on create/update. Add --label and --milestone filter flags to list and search commands. Depends on storage refactor. Add milestones: `List<String>` and labels: `List<String>` to the Ticket model and YAML frontmatter. Support --milestone and --label flags on create/update. Add --label and --milestone filter flags to list and search commands. Depends on storage refactor.

View file

@ -8,4 +8,4 @@ links:
type: child_of type: child_of
--- ---
Add `dew kanban archive --id <id>` that moves a ticket to .project/kanban/archive/ (and its attachments stay at attachments/<id>/). Archived tickets excluded from list/search by default; add --include-archived flag to opt in. Depends on storage refactor. Add `dew kanban archive --id <id>` that moves a ticket to .project/kanban/archive/ (and its attachments stay at `attachments/<id>/`). Archived tickets excluded from list/search by default; add --include-archived flag to opt in. Depends on storage refactor.

View file

@ -12,9 +12,9 @@ labels:
Check that all four package names are available on pub.dev before we invest in publishing prep: Check that all four package names are available on pub.dev before we invest in publishing prep:
- https://pub.dev/packages/dew - <https://pub.dev/packages/dew>
- https://pub.dev/packages/dew_core - <https://pub.dev/packages/dew_core>
- https://pub.dev/packages/dew_kanban - <https://pub.dev/packages/dew_kanban>
- https://pub.dev/packages/dew_mcp - <https://pub.dev/packages/dew_mcp>
If any name is taken, we need to decide on alternatives (e.g. `dew_cli`, `dew_board`, etc.) and update package names + imports throughout the codebase. If any name is taken, we need to decide on alternatives (e.g. `dew_cli`, `dew_board`, etc.) and update package names + imports throughout the codebase.

View file

@ -17,6 +17,7 @@ Update all pubspec.yaml files for the 1.0 release:
- All four packages: add `issue_tracker: https://github.com/artificery-dev/dew/issues` - All four packages: add `issue_tracker: https://github.com/artificery-dev/dew/issues`
Files to edit: Files to edit:
- packages/cli/pubspec.yaml - packages/cli/pubspec.yaml
- packages/core/pubspec.yaml - packages/core/pubspec.yaml
- packages/kanban/pubspec.yaml - packages/kanban/pubspec.yaml

View file

@ -13,11 +13,13 @@ labels:
pub.dev rejects path dependencies. Switch all inter-package deps to versioned, and use dependency_overrides in the workspace root for local development. pub.dev rejects path dependencies. Switch all inter-package deps to versioned, and use dependency_overrides in the workspace root for local development.
Changes needed: Changes needed:
- `packages/cli/pubspec.yaml`: change dew_core, dew_kanban, dew_mcp from `path: ../x` to `^1.0.0` - `packages/cli/pubspec.yaml`: change dew_core, dew_kanban, dew_mcp from `path: ../x` to `^1.0.0`
- `packages/kanban/pubspec.yaml`: change dew_core from `path: ../core` to `^1.0.0` - `packages/kanban/pubspec.yaml`: change dew_core from `path: ../core` to `^1.0.0`
- `packages/mcp/pubspec.yaml`: change dew_core from `path: ../core` to `^1.0.0` - `packages/mcp/pubspec.yaml`: change dew_core from `path: ../core` to `^1.0.0`
Add to root `pubspec.yaml`: Add to root `pubspec.yaml`:
```yaml ```yaml
dependency_overrides: dependency_overrides:
dew_core: dew_core:

View file

@ -13,6 +13,7 @@ labels:
Remove `publish_to: none` from all four package pubspec.yaml files so they can be published to pub.dev. Remove `publish_to: none` from all four package pubspec.yaml files so they can be published to pub.dev.
Files: Files:
- packages/cli/pubspec.yaml - packages/cli/pubspec.yaml
- packages/core/pubspec.yaml - packages/core/pubspec.yaml
- packages/kanban/pubspec.yaml - packages/kanban/pubspec.yaml

View file

@ -12,9 +12,10 @@ labels:
Write /CHANGELOG.md at the repo root covering the full 0.x → 1.0.0 history. Write /CHANGELOG.md at the repo root covering the full 0.x → 1.0.0 history.
Format: Keep a Changelog (https://keepachangelog.com/en/1.0.0/) Format: Keep a Changelog (<https://keepachangelog.com/en/1.0.0/>)
The 1.0.0 section should cover all major features shipped: The 1.0.0 section should cover all major features shipped:
- dew init command - dew init command
- Kanban CLI: create, list, get, update, delete, move, search, comment, archive, unarchive, link, unlink, stats, config - Kanban CLI: create, list, get, update, delete, move, search, comment, archive, unarchive, link, unlink, stats, config
- Kanban TUI: interactive board, column nav, ticket detail, editor modal, search/filter, delete, link, type picker, help overlay, auto-refresh, SIGWINCH resize - Kanban TUI: interactive board, column nav, ticket detail, editor modal, search/filter, delete, link, type picker, help overlay, auto-refresh, SIGWINCH resize

View file

@ -13,6 +13,7 @@ labels:
Overhaul /README.md for a compelling 1.0 release page. Overhaul /README.md for a compelling 1.0 release page.
Must include: Must include:
- Elevator pitch (1-2 sentences: what dew is, who it's for) - Elevator pitch (1-2 sentences: what dew is, who it's for)
- Feature highlights with brief descriptions (Kanban CLI, TUI, MCP server) - Feature highlights with brief descriptions (Kanban CLI, TUI, MCP server)
- Installation: `dart pub global activate dew` - Installation: `dart pub global activate dew`

View file

@ -13,6 +13,7 @@ labels:
docs/features/kanban.md currently has zero coverage of `dew kanban tui`. Add a full TUI section. docs/features/kanban.md currently has zero coverage of `dew kanban tui`. Add a full TUI section.
The section should include: The section should include:
- What the TUI is and how to launch it (`dew kanban tui`) - What the TUI is and how to launch it (`dew kanban tui`)
- Overview of the three modes: Board, Detail, Editor - Overview of the three modes: Board, Detail, Editor
- Full keybinding reference table (mirrors the F1 help overlay): - Full keybinding reference table (mirrors the F1 help overlay):

View file

@ -13,28 +13,37 @@ labels:
Create /CONTRIBUTING.md at the repo root. Create /CONTRIBUTING.md at the repo root.
Should cover: Should cover:
- Prerequisites: Dart SDK ^3.11.4 - Prerequisites: Dart SDK ^3.11.4
- Clone & setup: - Clone & setup:
```bash ```bash
git clone https://github.com/artificery-dev/dew.git git clone https://github.com/artificery-dev/dew.git
cd dew cd dew
dart pub get dart pub get
``` ```
- Running the CLI locally: - Running the CLI locally:
```bash ```bash
dart run packages/cli/bin/dew.dart kanban list dart run packages/cli/bin/dew.dart kanban list
``` ```
- Running tests: - Running tests:
```bash ```bash
dart test packages/core/test/ dart test packages/core/test/
dart test packages/kanban/test/ dart test packages/kanban/test/
dart test packages/mcp/test/ dart test packages/mcp/test/
``` ```
- Linting and formatting: - Linting and formatting:
```bash ```bash
dart analyze dart analyze
dart format . dart format .
``` ```
- Branch strategy: feature branches off `develop`, PRs into `develop`, releases merge to `main` - Branch strategy: feature branches off `develop`, PRs into `develop`, releases merge to `main`
- Commit message conventions (reference existing commit style in git log) - Commit message conventions (reference existing commit style in git log)
- How to add a new kanban command (implement DewToolCommand, register in dew_kanban_base.dart) - How to add a new kanban command (implement DewToolCommand, register in dew_kanban_base.dart)

View file

@ -15,6 +15,7 @@ Add end-to-end integration tests that exercise the full CLI against real temp di
Create packages/cli/test/integration_test.dart (or packages/kanban/test/integration_test.dart). Create packages/cli/test/integration_test.dart (or packages/kanban/test/integration_test.dart).
Test flows: Test flows:
1. `dew init <tmpdir>` → .project/dew.yaml and .project/kanban/ are created 1. `dew init <tmpdir>` → .project/dew.yaml and .project/kanban/ are created
2. `dew kanban create --title "Test" --type task` → ticket file appears in backlog 2. `dew kanban create --title "Test" --type task` → ticket file appears in backlog
3. `dew kanban list` → returns the created ticket 3. `dew kanban list` → returns the created ticket

View file

@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
## [1.0.0] - 2026-04-25 ## [0.1.0] - 2026-04-25
### Added ### Added
@ -20,24 +20,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
Full set of kanban subcommands, each also registered as an MCP tool automatically: Full set of kanban subcommands, each also registered as an MCP tool automatically:
| Subcommand | Description | | Subcommand | Description |
| ------------ | ------------------------------------------------------------------------ | | ----------- | ---------------------------------------------------------------------------- |
| `create` | Create a new ticket with title, type, column, body, labels, and milestones | | `create` | Create a new ticket with title, type, column, body, labels, and milestones |
| `list` | List tickets filtered by column, type, label, milestone, or archived state | | `list` | List tickets filtered by column, type, label, milestone, or archived state |
| `get` | Fetch a single ticket by ID | | `get` | Fetch a single ticket by ID |
| `update` | Update any field on a ticket (title, type, column, body, labels, milestones) | | `update` | Update any field on a ticket (title, type, column, body, labels, milestones) |
| `delete` | Permanently delete a ticket | | `delete` | Permanently delete a ticket |
| `move` | Move a ticket to a different column (validates column transition rules) | | `move` | Move a ticket to a different column (validates column transition rules) |
| `search` | Full-text search across ticket titles, bodies, and comments | | `search` | Full-text search across ticket titles, bodies, and comments |
| `comment` | Append a comment to a ticket | | `comment` | Append a comment to a ticket |
| `archive` | Soft-delete a ticket by moving it to the archive column | | `archive` | Soft-delete a ticket by moving it to the archive column |
| `unarchive` | Restore an archived ticket to a column | | `unarchive` | Restore an archived ticket to a column |
| `link` | Create a typed bidirectional link between two tickets | | `link` | Create a typed bidirectional link between two tickets |
| `unlink` | Remove a link between two tickets | | `unlink` | Remove a link between two tickets |
| `stats` | Display ticket counts grouped by column and type | | `stats` | Display ticket counts grouped by column and type |
| `board` | Print an ASCII representation of the board | | `board` | Print an ASCII representation of the board |
| `config` | Print the current kanban configuration | | `config` | Print the current kanban configuration |
| `tui` | Launch the interactive terminal UI | | `tui` | Launch the interactive terminal UI |
- File-based storage: each ticket is a Markdown file with YAML frontmatter for - File-based storage: each ticket is a Markdown file with YAML frontmatter for
metadata and inline `---` separators for comments. Column is derived from the metadata and inline `---` separators for comments. Column is derived from the
@ -86,5 +86,5 @@ Full set of kanban subcommands, each also registered as an MCP tool automaticall
- `ProjectDirs` with injectable filesystem abstraction (`package:file`) for - `ProjectDirs` with injectable filesystem abstraction (`package:file`) for
testable path resolution. testable path resolution.
[Unreleased]: https://github.com/artificery-dev/dew/compare/v1.0.0...HEAD [Unreleased]: https://github.com/artificerchris/dew/compare/v0.1.0...HEAD
[1.0.0]: https://github.com/artificery-dev/dew/releases/tag/v1.0.0 [0.1.0]: https://github.com/artificerchris/dew/releases/tag/v0.1.0

View file

@ -40,12 +40,12 @@ Fix any analysis warnings before opening a PR. The project uses the rules define
## Branch strategy ## Branch strategy
| Branch | Purpose | | Branch | Purpose |
| --------- | ---------------------------------------------------------- | | --------- | ------------------------------------------------------- |
| `main` | Stable, released code. Only merged into from `develop`. | | `main` | Stable, released code. Only merged into from `develop`. |
| `develop` | Integration branch. All PRs target this branch. | | `develop` | Integration branch. All PRs target this branch. |
| `feat/*` | Feature branches cut from `develop`. | | `feat/*` | Feature branches cut from `develop`. |
| `fix/*` | Bug-fix branches cut from `develop`. | | `fix/*` | Bug-fix branches cut from `develop`. |
**Workflow:** **Workflow:**

View file

@ -10,7 +10,7 @@
16 subcommands cover the full lifecycle of a ticket: 16 subcommands cover the full lifecycle of a ticket:
``` ```text
create list get update delete move create list get update delete move
search comment archive unarchive link unlink search comment archive unarchive link unlink
stats board config tui stats board config tui

View file

@ -51,35 +51,35 @@ Second comment.
All commands are available under `dew kanban <subcommand>`. All commands are available under `dew kanban <subcommand>`.
| Subcommand | Description | | Subcommand | Description |
| ------------- | ------------------------------------------------------------------------------ | | ----------- | ----------------------------------------------------------------------------------- |
| `create` | Create a new ticket (`--title`, `--type`, `--column`, `--body`) | | `create` | Create a new ticket (`--title`, `--type`, `--column`, `--body`) |
| `list` | List tickets (`--column`, `--type`, `--label`, `--milestone`, `--include-archived`) | | `list` | List tickets (`--column`, `--type`, `--label`, `--milestone`, `--include-archived`) |
| `get` | Get a ticket by ID (`--id`) | | `get` | Get a ticket by ID (`--id`) |
| `update` | Update fields on a ticket (`--id`, `--title`, `--type`, `--column`, `--body`) | | `update` | Update fields on a ticket (`--id`, `--title`, `--type`, `--column`, `--body`) |
| `delete` | Delete a ticket permanently (`--id`) | | `delete` | Delete a ticket permanently (`--id`) |
| `move` | Move a ticket to a different column (`--id`, `--column`) | | `move` | Move a ticket to a different column (`--id`, `--column`) |
| `search` | Full-text search across all ticket content (`--query`, `--include-archived`) | | `search` | Full-text search across all ticket content (`--query`, `--include-archived`) |
| `comment` | Append a comment to a ticket (`--id`, `--comment`) | | `comment` | Append a comment to a ticket (`--id`, `--comment`) |
| `archive` | Soft-delete a ticket by moving it to the archive column (`--id`) | | `archive` | Soft-delete a ticket by moving it to the archive column (`--id`) |
| `unarchive` | Restore an archived ticket to a column (`--id`, `--column`) | | `unarchive` | Restore an archived ticket to a column (`--id`, `--column`) |
| `link` | Link two tickets with a typed relationship (`--id`, `--target`, `--type`) | | `link` | Link two tickets with a typed relationship (`--id`, `--target`, `--type`) |
| `unlink` | Remove a link between two tickets (`--id`, `--target`) | | `unlink` | Remove a link between two tickets (`--id`, `--target`) |
| `stats` | Show ticket counts by column and type | | `stats` | Show ticket counts by column and type |
| `board` | Print an ASCII representation of the board | | `board` | Print an ASCII representation of the board |
| `config` | Print the current kanban configuration | | `config` | Print the current kanban configuration |
| `tui` | Launch the interactive terminal UI | | `tui` | Launch the interactive terminal UI |
## Ticket links ## Ticket links
Links are typed and bidirectional — writing one side automatically writes the inverse on the target. Links are typed and bidirectional — writing one side automatically writes the inverse on the target.
| Type | Inverse | Use case | | Type | Inverse | Use case |
| ----------------- | ------------------ | --------------------------------- | | ------------ | ------------------ | -------------------------------- |
| `blocks` | `is_blocked_by` | Dependency between tickets | | `blocks` | `is_blocked_by` | Dependency between tickets |
| `relates_to` | `relates_to` | General relationship (symmetric) | | `relates_to` | `relates_to` | General relationship (symmetric) |
| `duplicates` | `is_duplicated_by` | Duplicate ticket tracking | | `duplicates` | `is_duplicated_by` | Duplicate ticket tracking |
| `parent_of` | `child_of` | Epic → story → task hierarchy | | `parent_of` | `child_of` | Epic → story → task hierarchy |
## Configuration ## Configuration
@ -120,41 +120,41 @@ The TUI has three modes. Press **F1** in any mode for a context-sensitive help o
### Modes ### Modes
| Mode | How to enter | How to leave | | Mode | How to enter | How to leave |
| ---------- | ----------------------------------- | ------------------ | | ---------- | ---------------------------------- | ------------------------ |
| **Board** | Default on launch | `q` to quit | | **Board** | Default on launch | `q` to quit |
| **Detail** | Press `Enter` on a ticket in Board | `b` or `Esc` | | **Detail** | Press `Enter` on a ticket in Board | `b` or `Esc` |
| **Editor** | Press `e` in Board or Detail mode | `s` save / `Esc` discard | | **Editor** | Press `e` in Board or Detail mode | `s` save / `Esc` discard |
### Keybinding reference ### Keybinding reference
#### Board mode #### Board mode
| Key | Action | | Key | Action |
| --------- | ----------------------------------------------- | | --------- | ------------------------------------------------------ |
| `↑` / `↓` | Navigate tickets within the current column | | `↑` / `↓` | Navigate tickets within the current column |
| `←` / `→` | Switch to the previous / next column | | `←` / `→` | Switch to the previous / next column |
| `<` / `>` | Move the selected ticket to the previous / next column | | `<` / `>` | Move the selected ticket to the previous / next column |
| `Enter` | Open Detail view for the selected ticket | | `Enter` | Open Detail view for the selected ticket |
| `n` | Create a new ticket (opens Editor) | | `n` | Create a new ticket (opens Editor) |
| `e` | Edit the selected ticket (opens Editor) | | `e` | Edit the selected ticket (opens Editor) |
| `a` | Archive the selected ticket | | `a` | Archive the selected ticket |
| `D` | Delete the selected ticket (with confirmation) | | `D` | Delete the selected ticket (with confirmation) |
| `c` | Append a comment to the selected ticket | | `c` | Append a comment to the selected ticket |
| `L` | Link the selected ticket to another ticket | | `L` | Link the selected ticket to another ticket |
| `?` | Open the live filter / search overlay | | `?` | Open the live filter / search overlay |
| `F1` | Toggle the help overlay | | `F1` | Toggle the help overlay |
| `q` | Quit | | `q` | Quit |
#### Detail mode #### Detail mode
| Key | Action | | Key | Action |
| --------- | ----------------------------- | | ----------- | ------------------------------ |
| `↑` / `↓` | Scroll the ticket content | | `↑` / `↓` | Scroll the ticket content |
| `e` | Edit the ticket (opens Editor) | | `e` | Edit the ticket (opens Editor) |
| `b` / `Esc` | Return to Board mode | | `b` / `Esc` | Return to Board mode |
| `F1` | Toggle the help overlay | | `F1` | Toggle the help overlay |
| `q` | Quit | | `q` | Quit |
#### Editor mode #### Editor mode

View file

@ -87,4 +87,3 @@ The following tools are registered by the `kanban` package:
| `is_duplicated_by`| `duplicates` | No | | `is_duplicated_by`| `duplicates` | No |
| `parent_of` | `child_of` | No | | `parent_of` | `child_of` | No |
| `child_of` | `parent_of` | No | | `child_of` | `parent_of` | No |

View file

@ -15,18 +15,18 @@ Welcome to the documentation for the Dew project management tool!
Dew is structured as a Dart workspace with the following packages: Dew is structured as a Dart workspace with the following packages:
| Package | Description | | Package | Description |
| ----------------- | ----------------------------------------------------------------------------------------------- | | ----------------- | -------------------------------------------------------------------------------------------- |
| `packages/cli` | The `dew` command-line tool. Wires all packages together at startup. | | `packages/cli` | The `dew` command-line tool. Wires all packages together at startup. |
| `packages/core` | Shared foundation: `DewCommand`, `DewToolCommand` mixin, `CommandRegistry`, and `DewConfig`. | | `packages/core` | Shared foundation: `DewCommand`, `DewToolCommand` mixin, `CommandRegistry`, and `DewConfig`. |
| `packages/kanban` | Kanban board logic. Each command automatically registers itself as an MCP tool. | | `packages/kanban` | Kanban board logic. Each command automatically registers itself as an MCP tool. |
| `packages/mcp` | The MCP server. Collects tools from `CommandRegistry` and serves them over stdio. | | `packages/mcp` | The MCP server. Collects tools from `CommandRegistry` and serves them over stdio. |
### How commands become MCP tools ### How commands become MCP tools
Every CLI command that mixes in `DewToolCommand` is automatically registered as an MCP tool — no separate registration needed. The mixin derives the JSON Schema for the tool's input from the command's own `ArgParser`, so argument definitions are written exactly once. Every CLI command that mixes in `DewToolCommand` is automatically registered as an MCP tool — no separate registration needed. The mixin derives the JSON Schema for the tool's input from the command's own `ArgParser`, so argument definitions are written exactly once.
``` ```text
ArgParser definition ArgParser definition
├─► dew kanban create (human CLI) ├─► dew kanban create (human CLI)

View file

@ -1,8 +1,8 @@
# Changelog # Changelog
## 1.0.0 — 2026-04-25 ## 0.1.0 — 2026-04-25
Initial stable release. Initial release.
- `dew init` — initialise a Dew project - `dew init` — initialise a Dew project
- `dew kanban` — full kanban board management (16 subcommands + TUI) - `dew kanban` — full kanban board management (16 subcommands + TUI)

View file

@ -2,7 +2,7 @@
A git-native, file-based project management CLI with a kanban board and MCP server. A git-native, file-based project management CLI with a kanban board and MCP server.
See the [full documentation](https://github.com/artificery-dev/dew#readme) for installation, quick-start, and all available commands. See the [full documentation](https://github.com/artificerchris/dew#readme) for installation, quick-start, and all available commands.
## Installation ## Installation

View file

@ -1,8 +1,8 @@
name: dew name: dew
description: Command-line interface for the Dew project management tool. description: Command-line interface for the Dew project management tool.
version: 1.0.0 version: 0.1.0
repository: https://github.com/artificery-dev/dew repository: https://github.com/artificerchris/dew
issue_tracker: https://github.com/artificery-dev/dew/issues issue_tracker: https://github.com/artificerchris/dew/issues
resolution: workspace resolution: workspace
environment: environment:
@ -10,9 +10,9 @@ environment:
dependencies: dependencies:
args: ^2.7.0 args: ^2.7.0
dew_core: ^1.0.0 dew_core: ^0.1.0
dew_kanban: ^1.0.0 dew_kanban: ^0.1.0
dew_mcp: ^1.0.0 dew_mcp: ^0.1.0
dev_dependencies: dev_dependencies:
lints: ^6.0.0 lints: ^6.0.0

View file

@ -1,8 +1,8 @@
# Changelog # Changelog
## 1.0.0 — 2026-04-25 ## 0.1.0 — 2026-04-25
Initial stable release. Initial release.
- `DewCommand` base class with arg-parser-driven CLI and MCP tool dual-mode - `DewCommand` base class with arg-parser-driven CLI and MCP tool dual-mode
- `DewToolCommand` mixin for commands that expose an MCP tool - `DewToolCommand` mixin for commands that expose an MCP tool

View file

@ -1,6 +1,6 @@
# dew_core # dew_core
Core abstractions for the [Dew](https://github.com/artificery-dev/dew) project management tool. Core abstractions for the [Dew](https://github.com/artificerchris/dew) project management tool.
Provides `DewCommand`, `DewToolCommand`, `CommandRegistry`, and `ProjectContext` — the building blocks used by every Dew feature package. Provides `DewCommand`, `DewToolCommand`, `CommandRegistry`, and `ProjectContext` — the building blocks used by every Dew feature package.

View file

@ -1,8 +1,8 @@
name: dew_core name: dew_core
description: Core shared types, interfaces, and configuration for the Dew project management tool. description: Core shared types, interfaces, and configuration for the Dew project management tool.
version: 1.0.0 version: 0.1.0
repository: https://github.com/artificery-dev/dew repository: https://github.com/artificerchris/dew
issue_tracker: https://github.com/artificery-dev/dew/issues issue_tracker: https://github.com/artificerchris/dew/issues
resolution: workspace resolution: workspace
environment: environment:

View file

@ -1,8 +1,8 @@
# Changelog # Changelog
## 1.0.0 — 2026-04-25 ## 0.1.0 — 2026-04-25
Initial stable release. Initial release.
- 16 kanban CLI subcommands: `create`, `list`, `move`, `get`, `update`, `delete`, `archive`, `unarchive`, `link`, `unlink`, `comment`, `search`, `board`, `stats`, `config`, `tui` - 16 kanban CLI subcommands: `create`, `list`, `move`, `get`, `update`, `delete`, `archive`, `unarchive`, `link`, `unlink`, `comment`, `search`, `board`, `stats`, `config`, `tui`
- Interactive TUI with board view, ticket detail, inline editor, and help overlay - Interactive TUI with board view, ticket detail, inline editor, and help overlay

View file

@ -1,12 +1,12 @@
# dew_kanban # dew_kanban
Kanban board feature package for the [Dew](https://github.com/artificery-dev/dew) project management tool. Kanban board feature package for the [Dew](https://github.com/artificerchris/dew) project management tool.
Provides all kanban CLI commands (`create`, `list`, `move`, `get`, `update`, `delete`, `archive`, `unarchive`, `link`, `unlink`, `comment`, `search`, `board`, `stats`, `config`, `tui`) plus the interactive terminal UI and MCP tool definitions. Provides all kanban CLI commands (`create`, `list`, `move`, `get`, `update`, `delete`, `archive`, `unarchive`, `link`, `unlink`, `comment`, `search`, `board`, `stats`, `config`, `tui`) plus the interactive terminal UI and MCP tool definitions.
## Usage ## Usage
This package is consumed by the `dew` CLI and `dew_mcp` packages. See the [main README](https://github.com/artificery-dev/dew#readme) for full documentation. This package is consumed by the `dew` CLI and `dew_mcp` packages. See the [main README](https://github.com/artificerchris/dew#readme) for full documentation.
## License ## License

View file

@ -121,15 +121,17 @@ class Ticket {
} }
} }
buf.writeln('---'); buf.writeln('---');
if (body.isNotEmpty) { final normalizedBody = _normalizeMarkdownSection(body);
if (normalizedBody.isNotEmpty) {
buf.writeln(); buf.writeln();
buf.writeln(body); buf.writeln(normalizedBody);
} }
for (final comment in comments) { for (final comment in comments) {
final normalizedComment = _normalizeMarkdownSection(comment);
buf.writeln(); buf.writeln();
buf.writeln('---'); buf.writeln('---');
buf.writeln(); buf.writeln();
buf.writeln(comment); buf.writeln(normalizedComment);
} }
return buf.toString(); return buf.toString();
} }
@ -200,4 +202,119 @@ class Ticket {
if (!needsQuoting) return value; if (!needsQuoting) return value;
return '"${value.replaceAll('\\', '\\\\').replaceAll('"', '\\"')}"'; return '"${value.replaceAll('\\', '\\\\').replaceAll('"', '\\"')}"';
} }
static String _normalizeMarkdownSection(String value) {
final normalizedNewlines = value
.replaceAll('\r\n', '\n')
.replaceAll('\r', '\n')
.trimRight();
if (normalizedNewlines.isEmpty) return '';
final lines = normalizedNewlines.split('\n');
final out = <String>[];
var inFence = false;
var inListBlock = false;
var justClosedFence = false;
for (final line in lines) {
final wasInFence = inFence;
final isBlank = line.trim().isEmpty;
final isFenceBoundary = _isMarkdownFenceBoundary(line);
final isOpeningFence = isFenceBoundary && !wasInFence;
final isClosingFence = isFenceBoundary && wasInFence;
final isListItem = !wasInFence && _isMarkdownListItem(line);
final isListContinuation =
!wasInFence &&
inListBlock &&
!isBlank &&
_isMarkdownListContinuation(line);
if (isBlank && !wasInFence && out.isNotEmpty && out.last.trim().isEmpty) {
justClosedFence = false;
inListBlock = false;
continue;
}
if (justClosedFence && !isBlank && out.last.trim().isNotEmpty) {
out.add('');
}
justClosedFence = false;
if (isOpeningFence && out.isNotEmpty && out.last.trim().isNotEmpty) {
out.add('');
} else if (!isOpeningFence &&
isListItem &&
!inListBlock &&
out.isNotEmpty &&
out.last.trim().isNotEmpty) {
out.add('');
} else if (inListBlock &&
!isBlank &&
!isListItem &&
!isListContinuation &&
out.isNotEmpty &&
out.last.trim().isNotEmpty) {
out.add('');
}
out.add(isOpeningFence ? _fenceLineWithDefaultLanguage(line) : line);
if (isFenceBoundary) {
inFence = !inFence;
}
if (isClosingFence) {
inListBlock = false;
justClosedFence = true;
continue;
}
if (wasInFence || isOpeningFence) {
inListBlock = false;
continue;
}
if (isBlank) {
inListBlock = false;
} else if (isListItem || isListContinuation) {
inListBlock = true;
} else {
inListBlock = false;
}
}
return out.join('\n').trimRight();
}
static bool _isMarkdownListItem(String line) =>
RegExp(r'^( {0,3})(?:[-+*]|\d+[.)])\s+').hasMatch(line);
static bool _isMarkdownListContinuation(String line) =>
line.startsWith(' ') || line.startsWith('\t');
static String _fenceLineWithDefaultLanguage(String line) {
final marker = _markdownFenceMarker(line);
if (marker == null) return line;
final trimmed = line.trimLeft();
final info = trimmed.substring(marker.length).trim();
if (info.isNotEmpty) return line;
final indent = line.substring(0, line.length - trimmed.length);
return '$indent${marker}text';
}
static bool _isMarkdownFenceBoundary(String line) =>
_markdownFenceMarker(line) != null;
static String? _markdownFenceMarker(String line) {
final trimmed = line.trimLeft();
if (trimmed.startsWith('```')) {
return RegExp(r'^`{3,}').stringMatch(trimmed);
}
if (trimmed.startsWith('~~~')) {
return RegExp(r'^~{3,}').stringMatch(trimmed);
}
return null;
}
} }

View file

@ -1,8 +1,8 @@
name: dew_kanban name: dew_kanban
description: Kanban board feature for the Dew project management tool. Implements McpToolProvider to expose board tools to the MCP server. description: Kanban board feature for the Dew project management tool. Implements McpToolProvider to expose board tools to the MCP server.
version: 1.0.0 version: 0.1.0
repository: https://github.com/artificery-dev/dew repository: https://github.com/artificerchris/dew
issue_tracker: https://github.com/artificery-dev/dew/issues issue_tracker: https://github.com/artificerchris/dew/issues
resolution: workspace resolution: workspace
environment: environment:
@ -10,7 +10,7 @@ environment:
# Add regular dependencies here. # Add regular dependencies here.
dependencies: dependencies:
dew_core: ^1.0.0 dew_core: ^0.1.0
dart_console: ^4.1.2 dart_console: ^4.1.2
file: ^7.0.1 file: ^7.0.1
path: ^1.9.0 path: ^1.9.0

View file

@ -276,9 +276,89 @@ dew:
expect(parsed.comments, isEmpty); expect(parsed.comments, isEmpty);
}); });
test('links roundtrip serialisation', () { test('serializes markdown lists with surrounding blank lines', () {
final t = Ticket( final t = Ticket(
id: 'TEST-0003', id: 'TEST-0003',
title: 'List spacing',
type: 'task',
column: 'todo',
created: DateTime.utc(2026, 1, 3),
body: '''
Scope:
- First item
- Second item
Outcome:
1. Done
2. Verified
''',
comments: const [
'''
Notes:
- Comment item
Next paragraph.
''',
],
);
final content = t.toFileContent();
expect(
content,
contains('Scope:\n\n- First item\n- Second item\n\nOutcome:'),
);
expect(content, contains('Outcome:\n\n1. Done\n2. Verified'));
expect(content, contains('Notes:\n\n- Comment item\n\nNext paragraph.'));
});
test('does not alter list-like lines inside fenced code blocks', () {
final t = Ticket(
id: 'TEST-0004',
title: 'Fence spacing',
type: 'task',
column: 'todo',
created: DateTime.utc(2026, 1, 4),
body: '''
Example:
```text
- keep this adjacent
next line
```
Then:
- Real item
''',
comments: const [],
);
final content = t.toFileContent();
expect(content, contains('Example:\n\n```text'));
expect(
content,
contains('```text\n- keep this adjacent\nnext line\n```\n\nThen:'),
);
expect(content, contains('Then:\n\n- Real item'));
});
test('adds a default language to unlabeled fenced code blocks', () {
final t = Ticket(
id: 'TEST-0005',
title: 'Fence language',
type: 'task',
column: 'todo',
created: DateTime.utc(2026, 1, 5),
body: '''
Example:
```
plain output
```
''',
comments: const [],
);
expect(t.toFileContent(), contains('Example:\n\n```text\nplain output'));
});
test('links roundtrip serialisation', () {
final t = Ticket(
id: 'TEST-0006',
title: 'Linked', title: 'Linked',
type: 'task', type: 'task',
column: 'todo', column: 'todo',
@ -300,7 +380,7 @@ dew:
test('no links field when links is empty', () { test('no links field when links is empty', () {
final t = Ticket( final t = Ticket(
id: 'TEST-0004', id: 'TEST-0007',
title: 'No links', title: 'No links',
type: 'task', type: 'task',
column: 'todo', column: 'todo',
@ -313,7 +393,7 @@ dew:
test('milestones and labels roundtrip serialisation', () { test('milestones and labels roundtrip serialisation', () {
final t = Ticket( final t = Ticket(
id: 'TEST-0005', id: 'TEST-0008',
title: 'Tagged', title: 'Tagged',
type: 'task', type: 'task',
column: 'todo', column: 'todo',
@ -330,7 +410,7 @@ dew:
test('no milestones/labels fields when empty', () { test('no milestones/labels fields when empty', () {
final t = Ticket( final t = Ticket(
id: 'TEST-0006', id: 'TEST-0009',
title: 'Plain', title: 'Plain',
type: 'task', type: 'task',
column: 'todo', column: 'todo',

View file

@ -1,8 +1,8 @@
# Changelog # Changelog
## 1.0.0 — 2026-04-25 ## 0.1.0 — 2026-04-25
Initial stable release. Initial release.
- `DewMcpServer` stdio MCP server exposing all kanban tools - `DewMcpServer` stdio MCP server exposing all kanban tools
- 15 MCP tools covering the full kanban lifecycle - 15 MCP tools covering the full kanban lifecycle

View file

@ -1,6 +1,6 @@
# dew_mcp # dew_mcp
MCP (Model Context Protocol) server package for the [Dew](https://github.com/artificery-dev/dew) project management tool. MCP (Model Context Protocol) server package for the [Dew](https://github.com/artificerchris/dew) project management tool.
Exposes all Dew kanban operations as MCP tools so AI assistants (GitHub Copilot, Claude, etc.) can manage your kanban board directly. Exposes all Dew kanban operations as MCP tools so AI assistants (GitHub Copilot, Claude, etc.) can manage your kanban board directly.
@ -10,7 +10,7 @@ Exposes all Dew kanban operations as MCP tools so AI assistants (GitHub Copilot,
dew mcp serve dew mcp serve
``` ```
Connect your MCP client to the process via stdio. See the [main README](https://github.com/artificery-dev/dew#readme) for full setup instructions. Connect your MCP client to the process via stdio. See the [main README](https://github.com/artificerchris/dew#readme) for full setup instructions.
## License ## License

View file

@ -1,8 +1,8 @@
name: dew_mcp name: dew_mcp
description: MCP server for the Dew project management tool. Collects and serves tools registered by feature packages via the McpToolProvider interface. description: MCP server for the Dew project management tool. Collects and serves tools registered by feature packages via the McpToolProvider interface.
version: 1.0.0 version: 0.1.0
repository: https://github.com/artificery-dev/dew repository: https://github.com/artificerchris/dew
issue_tracker: https://github.com/artificery-dev/dew/issues issue_tracker: https://github.com/artificerchris/dew/issues
resolution: workspace resolution: workspace
environment: environment:
@ -10,11 +10,11 @@ environment:
# Add regular dependencies here. # Add regular dependencies here.
dependencies: dependencies:
dew_core: ^1.0.0 dew_core: ^0.1.0
dart_mcp: ^0.5.0 dart_mcp: ^0.5.0
yaml: ^3.1.0 yaml: ^3.1.0
dev_dependencies: dev_dependencies:
lints: ^6.0.0 lints: ^6.0.0
test: ^1.25.6 test: ^1.25.6
dew_kanban: ^1.0.0 dew_kanban: ^0.1.0

View file

@ -1,7 +1,7 @@
name: dew_workspace name: dew_workspace
description: A Dart workspace for the dew project management tool. description: A Dart workspace for the dew project management tool.
version: 0.1.0 version: 0.1.0
# repository: https://github.com/my_org/my_repo repository: https://github.com/artificerchris/dew
publish_to: none publish_to: none
environment: environment: