dctracker 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. dct/__init__.py +6 -0
  2. dct/cli.py +1659 -0
  3. dct/config.py +150 -0
  4. dct/core/__init__.py +0 -0
  5. dct/core/analytics.py +382 -0
  6. dct/core/changelog.py +112 -0
  7. dct/core/checkpoints.py +205 -0
  8. dct/core/decisions.py +238 -0
  9. dct/core/engine.py +32 -0
  10. dct/core/handoff.py +151 -0
  11. dct/core/ids.py +25 -0
  12. dct/core/items.py +382 -0
  13. dct/core/plans/__init__.py +6 -0
  14. dct/core/plans/classify.py +94 -0
  15. dct/core/plans/crud.py +680 -0
  16. dct/core/plans/ingest.py +408 -0
  17. dct/core/plans/parser.py +312 -0
  18. dct/core/projects.py +298 -0
  19. dct/core/sprint.py +315 -0
  20. dct/core/sprints.py +601 -0
  21. dct/core/version.py +116 -0
  22. dct/db.py +558 -0
  23. dct/export.py +107 -0
  24. dct/hooks/check-changelog-on-stop.sh +49 -0
  25. dct/hooks/check-changelog.sh +143 -0
  26. dct/hooks/dct-plan-autoscan.sh +54 -0
  27. dct/hooks/dct-task-mirror.sh +62 -0
  28. dct/server.py +1812 -0
  29. dct/setup.py +258 -0
  30. dct/skills/clog/SKILL.md +73 -0
  31. dct/skills/commit/SKILL.md +153 -0
  32. dct/skills/dct-import/SKILL.md +329 -0
  33. dct/skills/dct-init/SKILL.md +289 -0
  34. dct/skills/handoff/SKILL.md +136 -0
  35. dct/skills/pickup/SKILL.md +115 -0
  36. dct/skills/plan-resolve-uncertain/SKILL.md +82 -0
  37. dct/skills/plan-status/SKILL.md +79 -0
  38. dct/skills/release/SKILL.md +281 -0
  39. dct/skills/track/SKILL.md +121 -0
  40. dct/skills/track-list/SKILL.md +134 -0
  41. dct/skills/track-resolve/SKILL.md +53 -0
  42. dct/skills/track-update/SKILL.md +109 -0
  43. dct/web/__init__.py +1 -0
  44. dct/web/app.py +83 -0
  45. dct/web/blueprints/__init__.py +5 -0
  46. dct/web/blueprints/analytics.py +34 -0
  47. dct/web/blueprints/changelog.py +40 -0
  48. dct/web/blueprints/decisions.py +23 -0
  49. dct/web/blueprints/events.py +69 -0
  50. dct/web/blueprints/handoffs.py +26 -0
  51. dct/web/blueprints/home.py +15 -0
  52. dct/web/blueprints/items.py +128 -0
  53. dct/web/blueprints/plans.py +53 -0
  54. dct/web/blueprints/projects.py +23 -0
  55. dct/web/blueprints/sprints.py +71 -0
  56. dct/web/changes.py +77 -0
  57. dct/web/serializers.py +109 -0
  58. dct/web/static/app.css +609 -0
  59. dct/web/static/app.js +62 -0
  60. dct/web/static/vendor/SOURCES.txt +10 -0
  61. dct/web/static/vendor/htmx.min.js +1 -0
  62. dct/web/static/vendor/uPlot.iife.min.js +2 -0
  63. dct/web/static/vendor/uPlot.min.css +1 -0
  64. dct/web/templates/analytics.html +63 -0
  65. dct/web/templates/base.html +106 -0
  66. dct/web/templates/changelog/list.html +23 -0
  67. dct/web/templates/decisions/list.html +22 -0
  68. dct/web/templates/handoffs/list.html +45 -0
  69. dct/web/templates/home.html +20 -0
  70. dct/web/templates/item_detail.html +91 -0
  71. dct/web/templates/items_list.html +44 -0
  72. dct/web/templates/partials/_bars.html +15 -0
  73. dct/web/templates/partials/_checkpoint_steps.html +22 -0
  74. dct/web/templates/partials/_items_table.html +23 -0
  75. dct/web/templates/partials/_plan_section.html +24 -0
  76. dct/web/templates/partials/_project_card.html +24 -0
  77. dct/web/templates/plans/detail.html +16 -0
  78. dct/web/templates/plans/list.html +15 -0
  79. dct/web/templates/project_home.html +51 -0
  80. dct/web/templates/sprints/detail.html +37 -0
  81. dct/web/templates/sprints/list.html +35 -0
  82. dctracker-1.0.0.dist-info/METADATA +357 -0
  83. dctracker-1.0.0.dist-info/RECORD +87 -0
  84. dctracker-1.0.0.dist-info/WHEEL +5 -0
  85. dctracker-1.0.0.dist-info/entry_points.txt +2 -0
  86. dctracker-1.0.0.dist-info/licenses/LICENSE +21 -0
  87. dctracker-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,281 @@
1
+ ---
2
+ name: release
3
+ description: |
4
+ Bump project version and release changelog entries.
5
+ Use when: "release", "/release", "bump version", "nowa wersja",
6
+ "release X.Y", "wypuść wersję", "zamknij wersję".
7
+ ---
8
+
9
+ # /release — Version Bump & Changelog Release
10
+
11
+ Zero-argument workflow. Auto-detects project from CWD.
12
+
13
+ ## Workflow
14
+
15
+ ### Step 0: Ensure a clean working tree (auto-commit WIP first)
16
+
17
+ Run `git status --porcelain` in the project root.
18
+
19
+ **Clean (empty output)** → continue to Step 1.
20
+
21
+ **Dirty** → do NOT stop. The release commit (Step 7) must still contain ONLY the
22
+ changelog file + version-synced files, so auto-commit the working changes as
23
+ their OWN separate commit first, then continue. This preserves the reason the
24
+ gate existed — a clean release commit is a clean revert target — while removing
25
+ the manual interruption. The WIP simply lands in its own commit *below* the
26
+ release commit.
27
+
28
+ > Why a separate commit, not mixed in: mixing WIP code with a version bump
29
+ > pollutes `git log` and makes rollback risky. Committing the WIP first keeps the
30
+ > release commit changelog-only with zero friction.
31
+
32
+ Auto-commit procedure (same safety rules as `/commit` — never lose history,
33
+ never leak secrets):
34
+
35
+ 1. **Only genuinely-unsafe state stops the flow.** If a merge / rebase /
36
+ cherry-pick is in progress (`.git/MERGE_HEAD`, `.git/rebase-merge/`,
37
+ `.git/CHERRY_PICK_HEAD`), STOP and report — an auto-commit mid-operation is
38
+ unsafe. This is the ONLY hard stop in Step 0.
39
+ 2. **Stage explicitly — never `git add -A` / `git add .`.** Stage tracked
40
+ modifications and safe untracked files by path. EXCLUDE secrets and junk:
41
+ anything matching `.env*`, `*.pem`, `*.key`, `id_rsa*`, `*.p12`,
42
+ credential/token files, or large binaries. If such a file is dirty/untracked,
43
+ leave it unstaged and note it in the Step 9 report — do not commit it, do not
44
+ stop. Split into multiple logical commits when the changes cleanly separate by
45
+ file/concern (mirrors `/commit`); one commit is fine when they don't.
46
+ 3. **Message** — follow the `/commit` conventions: conventional-commit subject
47
+ `<type>(<scope>): <description> (v<current_version>)` derived from the staged
48
+ diff, with the `Co-Authored-By` trailer. If the changes span too many concerns
49
+ to summarize, use `chore: commit work in progress before release
50
+ (v<current_version>)`.
51
+ 4. **Commit.** If the pre-commit hook rejects, fix the underlying issue, re-stage,
52
+ and make a NEW commit (never `--amend`, never `--no-verify`).
53
+ 5. Re-run `git status --porcelain`; it MUST now be empty (modulo any
54
+ intentionally-skipped secret/junk files from step 2). Then continue to Step 1.
55
+
56
+ ### Step 1: Gather state
57
+ Call `mcp__dct__list_projects()` and match CWD to a registered project.
58
+ Call `mcp__dct__count_unreleased_changelog(project)`.
59
+ Call `mcp__dct__list_changelog(project, unreleased_only=true)`.
60
+
61
+ Present the state:
62
+ ```
63
+ Project: myproj (My Project)
64
+ Current version: 1.0
65
+ Unreleased entries: 5
66
+
67
+ [added] New Python parser support
68
+ [added] Incremental indexing
69
+ [fixed] Parser crash on empty files
70
+ [fixed] Memory leak in watcher
71
+ [changed] Refactored graph schema
72
+ ```
73
+
74
+ If there are no unreleased entries, inform the user and stop.
75
+
76
+ ### Step 2: Offer changelog review before bumping
77
+
78
+ After showing the unreleased entries in Step 1, ask via `AskUserQuestion`:
79
+ - question: "Ready to release, or review entries first?"
80
+ - options:
81
+ - `"Go ahead — entries look correct"` → proceed to Step 2b
82
+ - `"Amend one entry"` → free-text `AskUserQuestion` asking which (id) and the new text, call `mcp__dct__add_changelog` for the replacement and mark the old one via `/clog` amend flow; then re-show the list
83
+ - `"Drop one entry"` → free-text `AskUserQuestion` for id, soft-delete via direct DB update (or flag for post-release removal); re-show the list
84
+ - `"Cancel release"` → stop
85
+
86
+ This is the pre-stamp safety net — once Step 4 stamps, reverting requires
87
+ manual SQL. Offering an explicit review step prevents regret.
88
+
89
+ ### Step 2b: Ask bump type
90
+
91
+ The bump type MUST be chosen through `AskUserQuestion` — do NOT substitute a
92
+ plain-text prompt, and do NOT infer it from the user's earlier words, even if
93
+ they seem decided. The bump is effectively irreversible once Step 4 stamps
94
+ (reverting needs manual SQL), so the structured options must show the semver
95
+ implication AND the concrete resulting version number before committing to it.
96
+ This overrides any general "a plain-text answer is fine" preference.
97
+
98
+ Compute the concrete next version from `current_version` (vX.Y.Z) for each label:
99
+ - question: `"What type of release? (current: v<current_version>)"`
100
+ - options:
101
+ - `"patch — v<X.Y.(Z+1)> (bug fixes only)"`
102
+ - `"minor — v<X.(Y+1).0> (new features, backward compatible)"`
103
+ - `"major — v<(X+1).0.0> (breaking changes)"`
104
+ - `"explicit version — I'll type one"` → follow-up free-text AskUserQuestion
105
+
106
+ ### Step 3: Confirm
107
+ ```
108
+ Release myproj 1.1?
109
+ 5 changelog entries will be stamped
110
+ Version: 1.0 → 1.1
111
+ ```
112
+ Wait for confirmation.
113
+
114
+ ### Step 4: Stamp version in DB
115
+
116
+ Call `mcp__dct__release_changelog(project, version=<version>)`. This:
117
+ - Updates all unreleased changelog entries with the new `version`.
118
+ - Updates the project's `current_version` field.
119
+ - After this call, `count_unreleased_changelog(project)` will return 0.
120
+
121
+ ### Step 5: Append the new version's section to the changelog file
122
+
123
+ The changelog file (`F`, resolved below) is an **append-only archive**. /release ADDS the just-released
124
+ version's section to the top of the existing file — it does NOT regenerate the
125
+ whole file from the DB.
126
+
127
+ > **Why append, not regenerate:** a full `export_changelog`
128
+ > renders the file from DB rows only. For a project that adopted dct mid-life,
129
+ > the DB holds only post-adoption versions, so overwriting `changelog.md`
130
+ > silently DROPS every pre-adoption section (one such project lost 18 versions
131
+ > / ~536 lines this way). An operation that only ever inserts cannot lose history.
132
+
133
+ Let `V` = the version just stamped in Step 4 and `F` = the project's changelog
134
+ file. **Resolve `F` via the project's `changelog_path`, do NOT hardcode
135
+ `changelog.md`:** `F = {project.path}/{changelog_path}`, where `changelog_path`
136
+ comes from the Step 1 `list_projects` result (default `changelog.md` when the
137
+ field is absent — e.g. a not-yet-restarted MCP server). A project that keeps its
138
+ changelog in a subdirectory (e.g. a monorepo with `packages/core/changelog.md`) is then
139
+ handled transparently. Authoritative cross-check, always live:
140
+ `dct project changelog-path <slug>` prints the resolved absolute path on its
141
+ `→` line.
142
+
143
+ **Case A — F does not exist (bootstrap / from-scratch project):**
144
+ Call `mcp__dct__export_changelog(project, include_unreleased=false)` and write
145
+ the full result to F. For a from-scratch project the full render equals the
146
+ incremental one, so this is safe. Then continue to Step 6.
147
+
148
+ **Case B — F already exists (the normal path):**
149
+
150
+ 1. Render ONLY the new section:
151
+ `section = mcp__dct__export_changelog(project, version=V)`.
152
+ - If `isinstance(section, dict)` → it is an error: do NOT touch F, report it,
153
+ stop (the DB was already stamped in Step 4, so either fix the export error
154
+ and re-run Step 5, or manually revert the stamped entries).
155
+ - If `section == ""` → V has no entries (unexpected after Step 4): STOP and
156
+ report rather than writing an empty section.
157
+ 2. Read F. Count its existing version-section markers — **lines that start with** `## [` (`grep -c '^## \['`) — call it `N`. Anchor to line start; an entry body may contain `## [` mid-text and MUST NOT be counted.
158
+ 3. **Idempotency guard:** if a **line starting with** `## [V]` already appears in F (anchored — `grep -q '^## \[V\]'`), the section is
159
+ already archived (e.g. a re-run after a partial release). Do NOT write —
160
+ report "changelog.md already contains [V]" and continue to Step 6.
161
+ 4. Insert `section` directly **below the `# Changelog` header** (keep exactly
162
+ one blank line after the header) so it becomes the TOP version section.
163
+ Every existing section MUST stay byte-for-byte unchanged below it.
164
+ - Preferred mechanism: an Edit whose `old_string` is the current top
165
+ `## [...] - ...` line and whose `new_string` is `section` + that same line
166
+ (i.e. prepend the new section in front of the previous top version).
167
+ - If F has only the `# Changelog` header and no version sections yet,
168
+ append `section` after the header instead.
169
+ 5. **Safety check (mandatory):** re-read F and re-count **lines starting with** `## [` (`grep -c '^## \['`). The new
170
+ count MUST be exactly `N + 1` — one section added, zero lost. If it is not,
171
+ STOP, restore F to its pre-write contents, and report. NEVER commit a
172
+ changelog that lost history.
173
+
174
+ The DB stays the source of truth for the NEXT release's unreleased entries;
175
+ the FILE is the source of truth for shipped history.
176
+
177
+ ### Step 6: Sync version-bearing files
178
+
179
+ If `{project.path}/scripts/dct-version-sync.sh` exists, run it:
180
+ ```bash
181
+ bash scripts/dct-version-sync.sh <version>
182
+ ```
183
+
184
+ The sync script is **project-specific** — each project uncomments the
185
+ relevant block in the template. Canonical patterns by project kind:
186
+
187
+ | Project kind | Files to bump | sed/jq snippet |
188
+ |---|---|---|
189
+ | Python package | `pyproject.toml` `[project].version` | `sed -i '' "s/^version = \".*\"/version = \"$VERSION\"/" pyproject.toml` |
190
+ | Python package (fallback) | `<pkg>/__init__.py` `__version__` | `sed -i '' "s/__version__ = \".*\"/__version__ = \"$VERSION\"/" dct/__init__.py` |
191
+ | Rust | `Cargo.toml` `[package].version` | `sed -i '' "s/^version = \".*\"/version = \"$VERSION\"/" Cargo.toml` |
192
+ | Node (npm/yarn) | `package.json` `.version` | `jq --arg v "$VERSION" '.version = $v' package.json > tmp && mv tmp package.json` |
193
+ | Tauri | `src-tauri/tauri.conf.json` `.version` | `jq --arg v "$VERSION" '.version = $v' src-tauri/tauri.conf.json > tmp && mv tmp src-tauri/tauri.conf.json` |
194
+ | Claude Code plugin | `plugin.json` `.version` | `jq --arg v "$VERSION" '.version = $v' plugin.json > tmp && mv tmp plugin.json` |
195
+ | Swift (Info.plist) | `CFBundleShortVersionString` | `/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $VERSION" Info.plist` |
196
+
197
+ For **monorepos** with independently-versioned sub-packages, wrap each
198
+ block in `if has_changes "<path>"; then ... fi` so only sub-packages that
199
+ actually changed get bumped. `has_changes` is provided by the template.
200
+
201
+ For **dct itself** (Python package, single-version), the sync script is
202
+ uncommented to always bump `pyproject.toml` + `dct/__init__.py` fallback.
203
+
204
+ If the sync script doesn't exist, skip this step — DB is the source of
205
+ truth. Inform the user so they can add one if they have build files that
206
+ need sync.
207
+
208
+ ### Step 7: Commit the release
209
+
210
+ Stage ONLY the artifacts touched by Steps 5 and 6:
211
+ - `changelog.md`
212
+ - Any files modified by `scripts/dct-version-sync.sh` (check `git status --porcelain` after Step 6)
213
+
214
+ Then commit with the **literal** release message format:
215
+ ```bash
216
+ git commit -m "release: v<version>"
217
+ ```
218
+
219
+ No type, no scope, no version suffix — just `release: v1.1`. The dct global hook
220
+ recognizes this prefix and bypasses the changelog-presence check (which would otherwise
221
+ fail because all entries were just stamped).
222
+
223
+ ### Step 8: Tag the release (mandatory)
224
+
225
+ Tag HEAD with the `v<version>` prefix:
226
+ ```bash
227
+ git tag v<version>
228
+ ```
229
+
230
+ Rationale: the tag is the canonical marker of "this commit = this release"
231
+ for git log, GitHub, and future `git describe` output. Conventional `v`
232
+ prefix matches npm, PyPI, Cargo, and GitHub release UI expectations.
233
+
234
+ **Do NOT `git push --tags`** automatically — pushing to remote is a
235
+ separate, user-confirmed action. Inform the user the tag is local; if
236
+ they want it on the remote, they run `git push origin v<version>` or
237
+ `git push --tags` themselves.
238
+
239
+ If a tag `v<version>` already exists (rare — usually indicates a failed
240
+ earlier release), ask the user via `AskUserQuestion`:
241
+ - "Tag v<version> exists. Move it to the new commit, or fail?"
242
+ - `"Move tag to new HEAD (--force)"`
243
+ - `"Leave tag alone, don't tag this commit"`
244
+ - `"Abort — the existing tag is correct, something is wrong with this release"`
245
+
246
+ ### Step 9: Report
247
+ ```
248
+ ✓ myproj released as 1.1
249
+ 5 entries stamped
250
+ changelog.md: [1.1] section prepended (older history preserved)
251
+ Version-synced files: pyproject.toml, myproj/__init__.py
252
+ Commit: release: v1.1 (abc1234)
253
+ Tag: v1.1 (local only — run `git push origin v1.1` to push)
254
+ ```
255
+
256
+ ## Rules
257
+ - NEVER release without user confirmation.
258
+ - NEVER skip the bump type question, and NEVER substitute a plain-text prompt
259
+ for it — the bump type MUST be an AskUserQuestion (Step 2b). The pre-stamp
260
+ structured choice is the last reversible point.
261
+ - If `current_version` is not set, ask for explicit version instead of bump type.
262
+ - `changelog.md` is an **append-only archive**: /release only PREPENDS the new
263
+ version's section (Step 5 Case B), it does NOT regenerate the whole file.
264
+ Full-DB export is bootstrap-only (Case A, when no file exists yet). Rationale:
265
+ regenerating from the DB drops pre-adoption history.
266
+ - Editing an already-released entry in the DB will NOT re-render the file —
267
+ shipped history lives in `changelog.md`; correct it there directly.
268
+ - The release commit's `changelog.md` diff MUST be purely additive (one new
269
+ `## [vX]` section on top). If `git diff` shows deletions of older sections,
270
+ the append-only flow failed — STOP and investigate before committing.
271
+ - Release commit message MUST be exactly `release: vX.Y.Z` (no scope, no description).
272
+ The hook's release bypass depends on this prefix.
273
+ - The release commit contains ONLY changelog.md + version-synced files — no app
274
+ code. Step 0 guarantees this by auto-committing any WIP as a SEPARATE commit
275
+ first, so the release commit stays a clean revert target.
276
+ - Tag is **mandatory** — every release commit gets a `v<version>` tag (Step 8).
277
+ A release without a tag is not a release — it's a commit that happens to bump
278
+ `pyproject.toml`. Tags are the git-native marker for `git describe`,
279
+ `git log --decorate`, GitHub's release UI, and `pip install <pkg>==<version>`.
280
+ - Pushing the tag to remote is NOT automatic — inform the user the tag is local
281
+ and suggest `git push origin v<version>` (or `git push --tags`) as a separate step.
@@ -0,0 +1,121 @@
1
+ ---
2
+ name: track
3
+ description: |
4
+ Create a tracked item (issue, todo, feature, idea, improvement) in dct.
5
+ Use when: "track", "add issue", "add todo", "dodaj issue", "zanotuj",
6
+ "śledź", "track this", "new issue", "nowy issue", "zgłoś",
7
+ "dodaj jako problem", "problem", "bug", "błąd", "crash", "nie działa",
8
+ "dodaj feature", "ficzer", "dodaj ficzer", "dodaj todo",
9
+ "pomysł", "idea", "a może", "rozważ",
10
+ "poprawa", "ulepszenie", "poprawmy", "refactor", "cleanup".
11
+ ---
12
+
13
+ # /track — Create Tracked Item
14
+
15
+ ## Type triggers — natural language → item_type
16
+
17
+ Map the phrase the user actually used to the closest type. Do NOT ask
18
+ about type unless the phrase is genuinely ambiguous. When in doubt, prefer
19
+ `todo` (the most neutral bucket).
20
+
21
+ | User says (EN / PL) | item_type | When to pick |
22
+ |---|---|---|
23
+ | "problem", "bug", "issue", "crash", "broken", "error", "doesn't work", "regression" / "problem", "błąd", "bug", "crash", "nie działa", "popsute", "zepsute" | **issue** | Observable defect in existing code/system. Reproducible wrong behavior. |
24
+ | "todo", "task", "action item", "need to", "must do" / "todo", "zadanie", "zrobić", "do zrobienia", "trzeba" | **todo** | Concrete work that's neither a bug nor a new user-visible capability. Generic "stuff to do". |
25
+ | "feature", "add X", "new capability", "let's build", "we should have" / "feature", "ficzer", "funkcja", "dodajmy", "zbudujmy", "nowa funkcja" | **feature** | New user-visible capability that doesn't exist yet. |
26
+ | "idea", "maybe", "what if", "consider", "brainstorm", "explore" / "pomysł", "idea", "a może", "rozważ", "zastanów się", "pomyślmy" | **idea** | Exploratory — not yet decided to build. May become a feature later. |
27
+ | "improvement", "refactor", "polish", "cleanup", "tidy up", "make X nicer" / "ulepszenie", "poprawa", "poprawmy", "polerka", "cleanup", "refactor", "uporządkuj" | **improvement** | Existing thing works but could be better (refactor, UX polish, perf, docs). |
28
+
29
+ ### Examples
30
+
31
+ | Phrase | item_type | Why |
32
+ |---|---|---|
33
+ | "dodaj jako problem że parser się wywala na pustych plikach" | issue | "problem" + observable broken behavior |
34
+ | "dodaj ficzer, chcę zrobić dark mode" | feature | "ficzer" + new capability |
35
+ | "a może pomyślmy nad wtyczkami?" | idea | "a może" + exploratory |
36
+ | "trzeba uporządkować ten moduł parsera" | improvement | "uporządkować" + existing code |
37
+ | "dodaj todo — wysłać PR do review" | todo | explicit "todo", generic task |
38
+
39
+ ## Workflow
40
+
41
+ ### Step 1: Infer type, then gather rest
42
+
43
+ From the conversation context, determine:
44
+
45
+ - **project**: Detect from CWD using `mcp__dct__list_projects()` (longest path prefix), or ask if ambiguous
46
+ - **item_type**: Infer from the user's phrasing per the table above
47
+ - **title**: Concise summary (max ~80 chars)
48
+ - **priority**: P1 (blocks work / data loss / security), P2 (important — default), P3 (backlog), future (post-v1)
49
+ - **description**: Details, context, steps to reproduce (for issues) — prose, not checkbox lists
50
+ - **component**: Module or subsystem (optional)
51
+ - **source_file**: Relative path where the item lives (optional)
52
+ - **source_lines**: Line range, e.g. "42-58" (optional)
53
+ - **tags**: Comma-separated labels (optional)
54
+
55
+ ### Step 2: Confirm with user
56
+
57
+ Present the proposed item (short form — no wall of JSON):
58
+
59
+ ```
60
+ Track this?
61
+ Type: issue
62
+ Priority: P1
63
+ Title: Parser crashes on empty files
64
+ File: cmd/parse.go:42-58
65
+ Tags: parser, crash
66
+ ```
67
+
68
+ Wait for confirmation or corrections. If user said "just add it" or similar,
69
+ skip confirmation.
70
+
71
+ ### Step 3: Create
72
+
73
+ Call `mcp__dct__create_item(project, item_type, title, ...)` with all fields.
74
+ **REMEMBER the returned `id`** — needed for any follow-up (add_checkpoint,
75
+ update_item, resolve_item).
76
+
77
+ ### Step 4: Sketch checkpoints (feature / improvement only)
78
+
79
+ If `item_type` ∈ {feature, improvement}, IMMEDIATELY after create_item,
80
+ call `add_checkpoint` 3-7 times to break the work into concrete steps.
81
+ Do this BEFORE starting any code. Remember each checkpoint id.
82
+
83
+ Skip for `issue`, `todo`, `idea` unless the user explicitly asks for a
84
+ checkpoint breakdown.
85
+
86
+ ### Step 5: Report
87
+
88
+ ```
89
+ ✓ #42 issue/P1 — Parser crashes on empty files
90
+ ```
91
+
92
+ For feature/improvement with checkpoints:
93
+ ```
94
+ ✓ #43 feature/P2 — Dark mode
95
+ Checkpoints: 5 (ready to track)
96
+ ```
97
+
98
+ ## Priority mapping
99
+
100
+ P2 is the fallback ONLY when the user gives no priority cue. Read their
101
+ language first — urgency words trump the default.
102
+
103
+ | User phrasing | priority |
104
+ |---|---|
105
+ | "blocker", "blokuje", "data loss", "security", "critical", "pilne", "urgent", "krytyczne", "ważne" | **P1** |
106
+ | No urgency cue, neutral report | P2 (default) |
107
+ | "kiedyś", "backlog", "eventually", "nice to have", "low prio", "niski priorytet" | **P3** |
108
+ | "post-v1", "long-term", "someday", "może w przyszłości", "future" | **future** |
109
+
110
+ Never silently default to P2 when the user said "ważne" or "pilne" — that
111
+ would bury a P1 in the backlog.
112
+
113
+ ## Rules
114
+
115
+ - **Never ask about type** if the phrase maps cleanly per the table. Claude's
116
+ job is to read the language, not interrogate the user.
117
+ - **Never silently create** — always show the draft and wait for confirmation
118
+ (exception: user explicitly waived with "just add it", "szybko", "don't ask").
119
+ - **REMEMBER the returned id** — it's the handle for every future operation.
120
+ - **Checkpoints are mandatory for feature/improvement** — the visible
121
+ plan is the contract. No "I'll add them later" — add before coding.
@@ -0,0 +1,134 @@
1
+ ---
2
+ name: track-list
3
+ description: |
4
+ List and search tracked items across projects. Supports priority grouping,
5
+ file hotspots, and cross-project aggregation.
6
+ Use when: "list issues", "show todos", "what's open", "pokaż issues",
7
+ "co mamy", "backlog", "track-list", "all items", "open issues".
8
+ ---
9
+
10
+ # /track-list — List Tracked Items
11
+
12
+ Default: open items in the current project (auto-detected from CWD), grouped
13
+ by priority (P1 → P2 → P3 → future), compact `{cols, rows}` format. Resolved
14
+ items are hidden unless explicitly requested.
15
+
16
+ ## Routing — direct vs subagent
17
+
18
+ Pick based on cost, not habit. Main context is precious.
19
+
20
+ **Run directly (main context)** when:
21
+ - Single project, ≤50 open items expected
22
+ - Single #ID lookup (`/track-list #42` → `mcp__dct__get_item(42)`)
23
+ - Simple filter (priority / type / component / in_sprint)
24
+
25
+ **Delegate to subagent** (`Agent` tool with `subagent_type=Explore` or `general-purpose`) when:
26
+ - **Cross-project aggregation** (no `project` filter, >1 registered project with >20 items each)
27
+ - **Hotspot detection** (needs to group by `source_file` across items — Python-side work, not SQL)
28
+ - **Cross-source matching** (e.g. "which items share a changelog entry? which are in the sprint AND have stale checkpoints?")
29
+ - Expected output >200 rows
30
+ - Long free-text search across large description bodies
31
+
32
+ Subagent returns a concise summary. You relay that summary, not the raw rows — keeps your context lean.
33
+
34
+ ## Workflow
35
+
36
+ ### Step 1: Parse user intent
37
+
38
+ Extract from the request:
39
+ - **project**: explicit slug, `--all`/"all"/"cross-project" → empty (cross-project), otherwise auto-detect from CWD via `mcp__dct__list_projects` longest-prefix match
40
+ - **status**: default `"open"`. Accepts `"in_progress"`, `"resolved"`, `"wont_fix"`, or `""` for all. Convenience aliases: `--all-statuses`, `--include-resolved`
41
+ - **item_type**: `issue`/`todo`/`feature`/`idea`/`improvement`, or empty
42
+ - **priority**: `P1`/`P2`/`P3`/`future`, or empty
43
+ - **component**: match exact component name
44
+ - **in_current_sprint**: `"true"` (only sprint), `"false"` (exclude sprint), or empty
45
+ - **search**: free-text, searched in `title` + `description`
46
+ - **limit**: default 50
47
+
48
+ ID normalization (from `#42`, `42`, `ITEM-42`, `item-42`, `ITEM_42`, `item_42`, `0042` → `42`): regex `^(#|ITEM-|item-|ITEM_|item_)?0*(\d+)$` — case-insensitive prefix strip, leading-zero strip, cast int. Uniform with /track-update and /track-resolve. If a single ID is given, skip listing and go to `mcp__dct__get_item(id)`.
49
+
50
+ ### Step 2: Query
51
+
52
+ Call `mcp__dct__list_items(project, status, item_type, priority, component, in_current_sprint, search, limit, format="structured")`.
53
+
54
+ Response shape:
55
+ ```
56
+ {"cols": ["id","item_type","priority","status","in_current_sprint","cp","component","tags","created_at","title","description"],
57
+ "rows": [[22,"improvement","P2","open",false,[0,0],"server",["mcp"],"2026-04-17","Optimize...","..."]]}
58
+ ```
59
+
60
+ ### Step 3: Present — priority grouping
61
+
62
+ Group rows by priority (P1 → P2 → P3 → future). Within each group sort by `cp` progress descending (most-done first), then by `created_at` ascending (oldest first).
63
+
64
+ Render as markdown:
65
+
66
+ ```
67
+ ## P1 — blocking (2)
68
+ | # | Type | Sprint | cp | Component | Title |
69
+ |-----|-------|--------|-------|-----------|-------------------------------|
70
+ | 42 | issue | ● | 2/3 | parser | Crash on empty files |
71
+ | 88 | todo | | 0/0 | auth | Rotate session tokens |
72
+
73
+ ## P2 — important (11)
74
+ ...
75
+
76
+ ## P3 — backlog (4)
77
+ ...
78
+ ```
79
+
80
+ Use `●` for `in_current_sprint=true`, blank for false. Use `cp` as `done/total` string (e.g. `2/5`) from the raw `[2,5]` array.
81
+
82
+ ### Step 4: Hotspots (only if explicitly asked OR >1 hotspot auto-detected)
83
+
84
+ A **hotspot** is a file/component with ≥2 open items. Run Python-side aggregation on the rows (no extra DB call).
85
+
86
+ Trigger automatically when rows.length ≥ 20 AND at least one file has ≥2 items. The thresholds are empirical — below 20 items a hotspot section is noise (few rows, hotspots self-evident); above 20, the extra section reveals structural debt clusters. Otherwise show only on request (`/track-list --hotspots`).
87
+
88
+ ```
89
+ ## Hotspots (top 3 files by open-item count)
90
+ | Path | Open | P1 | Titles |
91
+ |--------------------------|------|----|-------------------------------------|
92
+ | dct/server.py | 4 | 0 | #22, #6, #14, #20 |
93
+ | dct/skills/track-list/SKILL.md | 3 | 0 | #6, #14, #19 |
94
+ | dct/core/items.py | 2 | 0 | #4, #23 (resolved) |
95
+ ```
96
+
97
+ If no source_file on items, skip this section.
98
+
99
+ ### Step 5: Cross-project summary (only when no project filter)
100
+
101
+ When `project` is empty (cross-project mode), prepend a summary line:
102
+
103
+ ```
104
+ Cross-project: 37 open items in 4 projects (dct: 13, proj-a: 87, proj-b: 63, proj-c: 35)
105
+ ```
106
+
107
+ Then show **top 3 priorities cross-project**, skipping detailed rows (delegate full listings to subagent if user asks).
108
+
109
+ ### Step 6: Final summary line
110
+
111
+ Always end with a count:
112
+ ```
113
+ Showing 13 open items in dct. Use /track-list --include-resolved to show closed.
114
+ ```
115
+
116
+ ## Shortcuts
117
+
118
+ - `/track-list` — open items in current project
119
+ - `/track-list #42` — direct `get_item(42)` (skips list)
120
+ - `/track-list proj-a` — items in project `proj-a`
121
+ - `/track-list --all` — cross-project (delegate to subagent if >100 expected)
122
+ - `/track-list P1` — P1-only filter
123
+ - `/track-list parser` — search "parser" in title/description
124
+ - `/track-list --sprint` — only `in_current_sprint=true`
125
+ - `/track-list --hotspots` — force hotspot section
126
+ - `/track-list --include-resolved` — include resolved + wont_fix
127
+
128
+ ## Rules
129
+
130
+ - **Always parse with ID normalization regex**. Do not reject `#42` because of the hash sign.
131
+ - **Default hides resolved** — do not surprise the user with closed items unless they ask.
132
+ - **Prefer subagent for cross-project** when ≥2 projects have ≥20 open items each. Tell the user: "Cross-project aggregation — delegating to subagent".
133
+ - **`cp` column is authoritative** — do not re-query per-item to compute progress (N+1).
134
+ - **Don't show `description` in the table** (it's in cols but too long for a grid row). Keep it available for follow-up `get_item` calls. Render only `title` in the grid.
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: track-resolve
3
+ description: |
4
+ Resolve or close a tracked item in dct.
5
+ Use when: "resolve issue", "close item", "mark as done", "zamknij issue",
6
+ "track-resolve", "wont fix", "done with #42".
7
+ ---
8
+
9
+ # /track-resolve — Resolve/Close Item
10
+
11
+ ## Workflow
12
+
13
+ ### Step 1: Identify item(s)
14
+
15
+ **ID normalization** — accept all of these forms:
16
+ - `#42`, `42`, `ITEM-42`, `item-42`, `0042`
17
+
18
+ Parse by: strip leading `#`, strip `ITEM-` / `item-` prefix (case-insensitive), strip leading zeros, cast to integer.
19
+ Regex: `^(#|ITEM-|item-|ITEM_|item_)?0*(\d+)$` — capture group 2 is the numeric id.
20
+
21
+ **Batch resolution** — user may pass multiple IDs separated by whitespace or commas:
22
+ ```
23
+ /track-resolve #42 #45 #51 ← three items in one call
24
+ /track-resolve 42, 45, 51 ← comma form
25
+ /track-resolve ITEM-42 #45 ← mixed forms
26
+ ```
27
+ Split input on whitespace and commas, normalize each id, then call `resolve_item` once per id.
28
+
29
+ Call `mcp__dct__get_item(item_id)` for each id to fetch current state.
30
+
31
+ ### Step 2: Determine resolution
32
+ - **resolved**: Fixed, implemented, completed
33
+ - **wont_fix**: Intentionally not addressing
34
+
35
+ Build resolution note from context:
36
+ - If a commit was just made: "Fixed in commit {hash}"
37
+ - If decision: "Decision: {reason}"
38
+ - Ask user if context is insufficient
39
+
40
+ ### Step 3: Confirm
41
+ ```
42
+ Resolve #42 — Parser crashes on empty files?
43
+ Status: open → resolved
44
+ Resolution: Fixed in commit abc1234
45
+ ```
46
+
47
+ ### Step 4: Execute
48
+ Call `mcp__dct__resolve_item(item_id, status, resolution)`.
49
+
50
+ ### Step 5: Report
51
+ ```
52
+ ✓ #42 → resolved
53
+ ```