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.
Order:
1. `cd packages/core && dart pub publish`
2. `cd packages/kanban && 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).
After all four are published:
1. `git checkout main`
2. `git merge develop`
3. `git tag v1.0.0`
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.

View file

@ -8,4 +8,4 @@ links:
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
---
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
---
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
---
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:
- https://pub.dev/packages/dew
- https://pub.dev/packages/dew_core
- https://pub.dev/packages/dew_kanban
- https://pub.dev/packages/dew_mcp
- <https://pub.dev/packages/dew>
- <https://pub.dev/packages/dew_core>
- <https://pub.dev/packages/dew_kanban>
- <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.

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`
Files to edit:
- packages/cli/pubspec.yaml
- packages/core/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.
Changes needed:
- `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/mcp/pubspec.yaml`: change dew_core from `path: ../core` to `^1.0.0`
Add to root `pubspec.yaml`:
```yaml
dependency_overrides:
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.
Files:
- packages/cli/pubspec.yaml
- packages/core/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.
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:
- dew init command
- 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

View file

@ -13,6 +13,7 @@ labels:
Overhaul /README.md for a compelling 1.0 release page.
Must include:
- Elevator pitch (1-2 sentences: what dew is, who it's for)
- Feature highlights with brief descriptions (Kanban CLI, TUI, MCP server)
- 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.
The section should include:
- What the TUI is and how to launch it (`dew kanban tui`)
- Overview of the three modes: Board, Detail, Editor
- Full keybinding reference table (mirrors the F1 help overlay):

View file

@ -13,28 +13,37 @@ labels:
Create /CONTRIBUTING.md at the repo root.
Should cover:
- Prerequisites: Dart SDK ^3.11.4
- Clone & setup:
```bash
git clone https://github.com/artificery-dev/dew.git
cd dew
dart pub get
```
- Running the CLI locally:
```bash
dart run packages/cli/bin/dew.dart kanban list
```
- Running tests:
```bash
dart test packages/core/test/
dart test packages/kanban/test/
dart test packages/mcp/test/
```
- Linting and formatting:
```bash
dart analyze
dart format .
```
- Branch strategy: feature branches off `develop`, PRs into `develop`, releases merge to `main`
- 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)

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).
Test flows:
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
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]
## [1.0.0] - 2026-04-25
## [0.1.0] - 2026-04-25
### 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:
| Subcommand | Description |
| ------------ | ------------------------------------------------------------------------ |
| `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 |
| `get` | Fetch a single ticket by ID |
| `update` | Update any field on a ticket (title, type, column, body, labels, milestones) |
| `delete` | Permanently delete a ticket |
| `move` | Move a ticket to a different column (validates column transition rules) |
| `search` | Full-text search across ticket titles, bodies, and comments |
| `comment` | Append a comment to a ticket |
| `archive` | Soft-delete a ticket by moving it to the archive column |
| `unarchive` | Restore an archived ticket to a column |
| `link` | Create a typed bidirectional link between two tickets |
| `unlink` | Remove a link between two tickets |
| `stats` | Display ticket counts grouped by column and type |
| `board` | Print an ASCII representation of the board |
| `config` | Print the current kanban configuration |
| `tui` | Launch the interactive terminal UI |
| Subcommand | Description |
| ----------- | ---------------------------------------------------------------------------- |
| `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 |
| `get` | Fetch a single ticket by ID |
| `update` | Update any field on a ticket (title, type, column, body, labels, milestones) |
| `delete` | Permanently delete a ticket |
| `move` | Move a ticket to a different column (validates column transition rules) |
| `search` | Full-text search across ticket titles, bodies, and comments |
| `comment` | Append a comment to a ticket |
| `archive` | Soft-delete a ticket by moving it to the archive column |
| `unarchive` | Restore an archived ticket to a column |
| `link` | Create a typed bidirectional link between two tickets |
| `unlink` | Remove a link between two tickets |
| `stats` | Display ticket counts grouped by column and type |
| `board` | Print an ASCII representation of the board |
| `config` | Print the current kanban configuration |
| `tui` | Launch the interactive terminal UI |
- File-based storage: each ticket is a Markdown file with YAML frontmatter for
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
testable path resolution.
[Unreleased]: https://github.com/artificery-dev/dew/compare/v1.0.0...HEAD
[1.0.0]: https://github.com/artificery-dev/dew/releases/tag/v1.0.0
[Unreleased]: https://github.com/artificerchris/dew/compare/v0.1.0...HEAD
[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 | Purpose |
| --------- | ---------------------------------------------------------- |
| `main` | Stable, released code. Only merged into from `develop`. |
| `develop` | Integration branch. All PRs target this branch. |
| `feat/*` | Feature branches cut from `develop`. |
| `fix/*` | Bug-fix branches cut from `develop`. |
| Branch | Purpose |
| --------- | ------------------------------------------------------- |
| `main` | Stable, released code. Only merged into from `develop`. |
| `develop` | Integration branch. All PRs target this branch. |
| `feat/*` | Feature branches cut from `develop`. |
| `fix/*` | Bug-fix branches cut from `develop`. |
**Workflow:**

View file

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

View file

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

View file

@ -87,4 +87,3 @@ The following tools are registered by the `kanban` package:
| `is_duplicated_by`| `duplicates` | No |
| `parent_of` | `child_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:
| Package | Description |
| ----------------- | ----------------------------------------------------------------------------------------------- |
| `packages/cli` | The `dew` command-line tool. Wires all packages together at startup. |
| `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/mcp` | The MCP server. Collects tools from `CommandRegistry` and serves them over stdio. |
| Package | Description |
| ----------------- | -------------------------------------------------------------------------------------------- |
| `packages/cli` | The `dew` command-line tool. Wires all packages together at startup. |
| `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/mcp` | The MCP server. Collects tools from `CommandRegistry` and serves them over stdio. |
### 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.
```
```text
ArgParser definition
├─► dew kanban create (human CLI)

View file

@ -1,8 +1,8 @@
# 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 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.
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

View file

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

View file

@ -1,8 +1,8 @@
# 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
- `DewToolCommand` mixin for commands that expose an MCP tool

View file

@ -1,6 +1,6 @@
# 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.

View file

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

View file

@ -1,8 +1,8 @@
# 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`
- Interactive TUI with board view, ticket detail, inline editor, and help overlay

View file

@ -1,12 +1,12 @@
# 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.
## 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

View file

@ -121,15 +121,17 @@ class Ticket {
}
}
buf.writeln('---');
if (body.isNotEmpty) {
final normalizedBody = _normalizeMarkdownSection(body);
if (normalizedBody.isNotEmpty) {
buf.writeln();
buf.writeln(body);
buf.writeln(normalizedBody);
}
for (final comment in comments) {
final normalizedComment = _normalizeMarkdownSection(comment);
buf.writeln();
buf.writeln('---');
buf.writeln();
buf.writeln(comment);
buf.writeln(normalizedComment);
}
return buf.toString();
}
@ -200,4 +202,119 @@ class Ticket {
if (!needsQuoting) return value;
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
description: Kanban board feature for the Dew project management tool. Implements McpToolProvider to expose board tools to the MCP server.
version: 1.0.0
repository: https://github.com/artificery-dev/dew
issue_tracker: https://github.com/artificery-dev/dew/issues
version: 0.1.0
repository: https://github.com/artificerchris/dew
issue_tracker: https://github.com/artificerchris/dew/issues
resolution: workspace
environment:
@ -10,7 +10,7 @@ environment:
# Add regular dependencies here.
dependencies:
dew_core: ^1.0.0
dew_core: ^0.1.0
dart_console: ^4.1.2
file: ^7.0.1
path: ^1.9.0

View file

@ -276,9 +276,89 @@ dew:
expect(parsed.comments, isEmpty);
});
test('links roundtrip serialisation', () {
test('serializes markdown lists with surrounding blank lines', () {
final t = Ticket(
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',
type: 'task',
column: 'todo',
@ -300,7 +380,7 @@ dew:
test('no links field when links is empty', () {
final t = Ticket(
id: 'TEST-0004',
id: 'TEST-0007',
title: 'No links',
type: 'task',
column: 'todo',
@ -313,7 +393,7 @@ dew:
test('milestones and labels roundtrip serialisation', () {
final t = Ticket(
id: 'TEST-0005',
id: 'TEST-0008',
title: 'Tagged',
type: 'task',
column: 'todo',
@ -330,7 +410,7 @@ dew:
test('no milestones/labels fields when empty', () {
final t = Ticket(
id: 'TEST-0006',
id: 'TEST-0009',
title: 'Plain',
type: 'task',
column: 'todo',

View file

@ -1,8 +1,8 @@
# 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
- 15 MCP tools covering the full kanban lifecycle

View file

@ -1,6 +1,6 @@
# 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.
@ -10,7 +10,7 @@ Exposes all Dew kanban operations as MCP tools so AI assistants (GitHub Copilot,
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

View file

@ -1,8 +1,8 @@
name: dew_mcp
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
repository: https://github.com/artificery-dev/dew
issue_tracker: https://github.com/artificery-dev/dew/issues
version: 0.1.0
repository: https://github.com/artificerchris/dew
issue_tracker: https://github.com/artificerchris/dew/issues
resolution: workspace
environment:
@ -10,11 +10,11 @@ environment:
# Add regular dependencies here.
dependencies:
dew_core: ^1.0.0
dew_core: ^0.1.0
dart_mcp: ^0.5.0
yaml: ^3.1.0
dev_dependencies:
lints: ^6.0.0
test: ^1.25.6
dew_kanban: ^1.0.0
dew_kanban: ^0.1.0

View file

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