diff --git a/.markdownlint-cli2.jsonc b/.markdownlint-cli2.jsonc new file mode 100644 index 0000000..ce9865d --- /dev/null +++ b/.markdownlint-cli2.jsonc @@ -0,0 +1,12 @@ +{ + "globs": [ + "**/*.md" + ], + "gitignore": true, + "config": { + "MD013": false, + "MD060": { + "style": "aligned" + } + } +} diff --git a/.markdownlint-cli2.mjs b/.markdownlint-cli2.mjs deleted file mode 100644 index e84bb0c..0000000 --- a/.markdownlint-cli2.mjs +++ /dev/null @@ -1,11 +0,0 @@ -export default { - globs: ['**/*.md'], - gitignore: true, - config: { - MD013: false, - MD040: true, - MD060: { - style: 'aligned', - }, - }, -}; diff --git a/.project/kanban/backlog/DEW-0028.md b/.project/kanban/backlog/DEW-0028.md index 44eed21..c91a10c 100644 --- a/.project/kanban/backlog/DEW-0028.md +++ b/.project/kanban/backlog/DEW-0028.md @@ -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 with CHANGELOG.md 1.0.0 section as body. Prerequisite: DEW-0027 (final validation) must be done first. diff --git a/.project/kanban/done/DEW-0003.md b/.project/kanban/done/DEW-0003.md index c3641ae..c009bde 100644 --- a/.project/kanban/done/DEW-0003.md +++ b/.project/kanban/done/DEW-0003.md @@ -8,4 +8,4 @@ links: type: parent_of --- -Add freeform milestone and label fields to tickets for grouping and filtering. Both are List in ticket frontmatter. +Add freeform milestone and label fields to tickets for grouping and filtering. Both are `List` in ticket frontmatter. diff --git a/.project/kanban/done/DEW-0008.md b/.project/kanban/done/DEW-0008.md index 72d66d8..7c9e8aa 100644 --- a/.project/kanban/done/DEW-0008.md +++ b/.project/kanban/done/DEW-0008.md @@ -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// (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// 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//` (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//` if present, create writes into correct column dir. diff --git a/.project/kanban/done/DEW-0011.md b/.project/kanban/done/DEW-0011.md index 4928054..6904a31 100644 --- a/.project/kanban/done/DEW-0011.md +++ b/.project/kanban/done/DEW-0011.md @@ -8,4 +8,4 @@ links: type: child_of --- -Add milestones: List and labels: List 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` and labels: `List` 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. diff --git a/.project/kanban/done/DEW-0015.md b/.project/kanban/done/DEW-0015.md index a7289f3..bbfffc0 100644 --- a/.project/kanban/done/DEW-0015.md +++ b/.project/kanban/done/DEW-0015.md @@ -8,4 +8,4 @@ links: type: child_of --- -Add `dew kanban archive --id ` that moves a ticket to .project/kanban/archive/ (and its attachments stay at attachments//). Archived tickets excluded from list/search by default; add --include-archived flag to opt in. Depends on storage refactor. +Add `dew kanban archive --id ` that moves a ticket to .project/kanban/archive/ (and its attachments stay at `attachments//`). Archived tickets excluded from list/search by default; add --include-archived flag to opt in. Depends on storage refactor. diff --git a/.project/kanban/done/DEW-0016.md b/.project/kanban/done/DEW-0016.md index 3349eb2..15e4b63 100644 --- a/.project/kanban/done/DEW-0016.md +++ b/.project/kanban/done/DEW-0016.md @@ -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 +- +- +- +- 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. diff --git a/.project/kanban/done/DEW-0017.md b/.project/kanban/done/DEW-0017.md index 5fe2bc6..7ae45ff 100644 --- a/.project/kanban/done/DEW-0017.md +++ b/.project/kanban/done/DEW-0017.md @@ -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 diff --git a/.project/kanban/done/DEW-0018.md b/.project/kanban/done/DEW-0018.md index cbf49c1..e649dd3 100644 --- a/.project/kanban/done/DEW-0018.md +++ b/.project/kanban/done/DEW-0018.md @@ -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: diff --git a/.project/kanban/done/DEW-0019.md b/.project/kanban/done/DEW-0019.md index c67fbbe..269c3d1 100644 --- a/.project/kanban/done/DEW-0019.md +++ b/.project/kanban/done/DEW-0019.md @@ -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 diff --git a/.project/kanban/done/DEW-0020.md b/.project/kanban/done/DEW-0020.md index 32bb217..288c6a9 100644 --- a/.project/kanban/done/DEW-0020.md +++ b/.project/kanban/done/DEW-0020.md @@ -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 () 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 diff --git a/.project/kanban/done/DEW-0021.md b/.project/kanban/done/DEW-0021.md index 6941849..e12c1a9 100644 --- a/.project/kanban/done/DEW-0021.md +++ b/.project/kanban/done/DEW-0021.md @@ -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` diff --git a/.project/kanban/done/DEW-0022.md b/.project/kanban/done/DEW-0022.md index 95395ae..7f95ebd 100644 --- a/.project/kanban/done/DEW-0022.md +++ b/.project/kanban/done/DEW-0022.md @@ -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): diff --git a/.project/kanban/done/DEW-0023.md b/.project/kanban/done/DEW-0023.md index 13553b5..ceb7c77 100644 --- a/.project/kanban/done/DEW-0023.md +++ b/.project/kanban/done/DEW-0023.md @@ -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) diff --git a/.project/kanban/done/DEW-0025.md b/.project/kanban/done/DEW-0025.md index d1f0ea9..ef95923 100644 --- a/.project/kanban/done/DEW-0025.md +++ b/.project/kanban/done/DEW-0025.md @@ -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 ` → .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 diff --git a/CHANGELOG.md b/CHANGELOG.md index cd52104..10763f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5ad4f7e..a555995 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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:** diff --git a/README.md b/README.md index ff60e47..9d85594 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/docs/features/kanban.md b/docs/features/kanban.md index 02d8fdb..67ee2e2 100644 --- a/docs/features/kanban.md +++ b/docs/features/kanban.md @@ -51,35 +51,35 @@ Second comment. All commands are available under `dew kanban `. -| 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 diff --git a/docs/features/mcp.md b/docs/features/mcp.md index d3841b0..2e1e114 100644 --- a/docs/features/mcp.md +++ b/docs/features/mcp.md @@ -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 | - diff --git a/docs/index.md b/docs/index.md index 99a7c39..487cd1a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -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) diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 4638fa0..c9fa684 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -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) diff --git a/packages/cli/README.md b/packages/cli/README.md index de358e8..600d666 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -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 diff --git a/packages/cli/pubspec.yaml b/packages/cli/pubspec.yaml index 32ae98e..e825305 100644 --- a/packages/cli/pubspec.yaml +++ b/packages/cli/pubspec.yaml @@ -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 diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 1be2472..e0fe8f6 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -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 diff --git a/packages/core/README.md b/packages/core/README.md index 61f7730..f3429ae 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -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. diff --git a/packages/core/pubspec.yaml b/packages/core/pubspec.yaml index 2c504f2..0fa0a55 100644 --- a/packages/core/pubspec.yaml +++ b/packages/core/pubspec.yaml @@ -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: diff --git a/packages/kanban/CHANGELOG.md b/packages/kanban/CHANGELOG.md index 2c54e16..11fda1c 100644 --- a/packages/kanban/CHANGELOG.md +++ b/packages/kanban/CHANGELOG.md @@ -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 diff --git a/packages/kanban/README.md b/packages/kanban/README.md index 65ef628..4a9d5be 100644 --- a/packages/kanban/README.md +++ b/packages/kanban/README.md @@ -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 diff --git a/packages/kanban/lib/src/ticket.dart b/packages/kanban/lib/src/ticket.dart index 7e9f59c..372ad57 100644 --- a/packages/kanban/lib/src/ticket.dart +++ b/packages/kanban/lib/src/ticket.dart @@ -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 = []; + 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; + } } diff --git a/packages/kanban/pubspec.yaml b/packages/kanban/pubspec.yaml index 9347ebe..d035b52 100644 --- a/packages/kanban/pubspec.yaml +++ b/packages/kanban/pubspec.yaml @@ -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 diff --git a/packages/kanban/test/dew_kanban_test.dart b/packages/kanban/test/dew_kanban_test.dart index d1054e8..93b5d3a 100644 --- a/packages/kanban/test/dew_kanban_test.dart +++ b/packages/kanban/test/dew_kanban_test.dart @@ -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', diff --git a/packages/mcp/CHANGELOG.md b/packages/mcp/CHANGELOG.md index 267af0e..fbbbfd5 100644 --- a/packages/mcp/CHANGELOG.md +++ b/packages/mcp/CHANGELOG.md @@ -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 diff --git a/packages/mcp/README.md b/packages/mcp/README.md index 589890c..f3425f3 100644 --- a/packages/mcp/README.md +++ b/packages/mcp/README.md @@ -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 diff --git a/packages/mcp/pubspec.yaml b/packages/mcp/pubspec.yaml index 16a3fc4..db5cc44 100644 --- a/packages/mcp/pubspec.yaml +++ b/packages/mcp/pubspec.yaml @@ -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 diff --git a/pubspec.yaml b/pubspec.yaml index fa02032..74409a0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -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: