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,329 @@
1
+ ---
2
+ name: dct-import
3
+ description: |
4
+ Import existing tracking data from markdown files into dct. Handles checkbox
5
+ TODOs, narrative sprints, custom issue formats (ORCH-N / BUG-N with field
6
+ blocks), plan-as-parent documents (1k+ line planning docs), Keep-a-Changelog
7
+ with or without [Unreleased], and conventional-commit style entries.
8
+ Use when: "dct-import", "importuj", "zaimportuj todos", "migruj dane",
9
+ "import tracking data", "import from markdown", "migrate to dct", "zmigruj",
10
+ "przenieś", "załaduj istniejące todo", "convert roadmap to dct",
11
+ "parse sprint doc", "import issue file".
12
+ ---
13
+
14
+ # /dct-import — Import Existing Tracking Data
15
+
16
+ ## Two import paths (v0.2.0)
17
+
18
+ Markdown files fall into three buckets; each uses a different tool:
19
+
20
+ | Bucket | Files | Tool |
21
+ | ------------ | ----------------------------------------------------------- | ---------------------------------------- |
22
+ | **Plan-like**| plans, specs, ADRs, roadmaps, retros, backlogs | `mcp__dct__ingest_plan_file` (v0.2 pipeline) |
23
+ | **Issue-like**| ORCH-N / BUG-N custom-field files, TODOS with inline status | v0.1 items + checkpoints (see Pattern Catalog below) |
24
+ | **Changelog**| CHANGELOG.md, changelog.md, changelog_unreleased.md | `mcp__dct__add_changelog` |
25
+
26
+ The v0.2 pipeline handles ULID injection, `[x]` historical state, and
27
+ optional LLM classification of uncertain sections in one call — you don't
28
+ re-implement Pattern Catalog logic for plan-like files.
29
+
30
+ ## Key principle
31
+
32
+ Claude proposes, user decides via `AskUserQuestion`. Never auto-create
33
+ without confirmation. Ambiguous entries are flagged and asked one-by-one.
34
+
35
+ ## Workflow
36
+
37
+ ### Step 1: Detect candidate files
38
+
39
+ Scan project root (and common subdirs) for typical tracking files. Apply
40
+ the stale-file skip list FIRST (see below) — do not even offer skipped
41
+ paths to the user.
42
+
43
+ Typical patterns (file name heuristic):
44
+ - **Plan-like** (→ `ingest_plan_file`):
45
+ - `docs/plans/*.md`, `docs/specs/*.md`, `docs/adr/*.md`, `docs/retros/*.md`
46
+ - `ROADMAP.md`, `TODOS.md`, `FUTURE.md`, `BACKLOG.md`
47
+ - `SPRINT*.md`, `PLAN*.md`
48
+ - **Issue-like** (→ v0.1 items path):
49
+ - `ISSUES.md`, `BUGS.md`, `*issues*.md`, `*orchestrator*.md`
50
+ - **Changelog** (→ `add_changelog`):
51
+ - `CHANGELOG.md`, `changelog.md`, `changelog_unreleased.md`
52
+
53
+ ### Step 2: Classify each file by format
54
+
55
+ For each candidate, read the first ~60 lines and classify by content.
56
+ The Pattern Catalog below lists 10 known formats. A file may match multiple
57
+ (e.g. a plan with embedded checkboxes) — pick the dominant one, flag as
58
+ composite in Step 4.
59
+
60
+ ### Step 3: Parse per-format
61
+
62
+ Apply the mapping rules from the Pattern Catalog. Build a draft table of
63
+ proposed imports BEFORE any DB write.
64
+
65
+ ### Step 4: Present review — AskUserQuestion pipeline
66
+
67
+ First `AskUserQuestion`:
68
+ - question: "Found N files. Which to import?"
69
+ - options: one per file formatted `TODOS.md (304 lines) — checkbox TODOs`,
70
+ plus `"All detected files"`, `"Pick subset (I'll list)"`, `"Cancel"`.
71
+ - On subset: follow-up multi-select AskUserQuestion.
72
+
73
+ For each selected file, show the proposed table then `AskUserQuestion`:
74
+ - question: "Proceed with <file>? (N entries, M ambiguous)"
75
+ - options:
76
+ - `"Import all as shown"`
77
+ - `"Resolve ambiguities one-by-one"` — one AskUserQuestion per flagged row
78
+ - `"Edit first"` — free-text AskUserQuestion, parse corrections, re-show
79
+ - `"Skip this file"`
80
+ - `"Cancel import"`
81
+
82
+ ### Step 5: Execute
83
+
84
+ **For plan-like files** (v0.2 pipeline):
85
+ - Call `mcp__dct__ingest_plan_file(file_path, project, auto_resolve_uncertain=true)`.
86
+ - The tool handles ULID injection, DB upsert, first-import `[x]` historical
87
+ state, and optional LLM classification in one call.
88
+ - This DOES modify the MD file by injecting `<!-- dct:plan/section/cp:<ULID> -->`
89
+ HTML comments — this is intentional; the anchors are the stable cross-cut
90
+ between file and DB. Original text / ordering / code blocks are preserved.
91
+
92
+ For each confirmed issue-like or changelog entry (legacy v0.1 path):
93
+ 1. Items: `mcp__dct__create_item(...)` — **REMEMBER the returned `id`** per entry.
94
+ 2. Parent + sub-tasks: after creating the parent item, loop
95
+ `mcp__dct__add_checkpoint(parent_id, text)` for each sub-task —
96
+ remember each checkpoint id. Mark already-done sub-tasks via
97
+ `complete_checkpoint(cp_id)` in a second pass.
98
+ 3. Changelog entries: `mcp__dct__add_changelog(...)`.
99
+ 4. Provenance: `mcp__dct__add_note(item_id, f"Imported from {filename} on {date}")`
100
+ for every item. This feeds the post-migration audit trail.
101
+ 5. For issue-like / changelog: NEVER modify or delete the source markdown file.
102
+
103
+ ### Step 6: Report
104
+
105
+ Per-file summary: counts by type / priority / done-vs-open. End with
106
+ "X items, Y checkpoints, Z changelog entries imported from N files".
107
+
108
+ ---
109
+
110
+ ## Pattern Catalog
111
+
112
+ ### Format A — TODOS.md (checkbox flat list)
113
+
114
+ ```markdown
115
+ ## P1 — Blockers
116
+ - [ ] Fix parser crash on empty files
117
+ - [x] Rotate session tokens ← already done
118
+
119
+ ## P2 — Important
120
+ - [ ] Add progress bar
121
+ ```
122
+
123
+ Mapping:
124
+ - Section heading `## P1 — ...` → `priority="P1"` for items in that section
125
+ - `- [ ]` / `- [x]` → `status="open"` / `status="resolved"`
126
+ - `✅` or bare `**DONE**` or `STATUS: DONE` at entry end → equivalent to `[x]`
127
+ - Line after dash → `title` (strip bold markers, emoji, leading/trailing whitespace)
128
+ - `item_type` defaults to `todo` unless entry text matches type triggers
129
+ ("bug", "crash", "error" → issue; "add X" → feature; etc.)
130
+
131
+ ### Format B — Narrative sprint / ROADMAP
132
+
133
+ ```markdown
134
+ ## Sprint 3 — January push
135
+
136
+ Goal: ship the parser rewrite, close the 4 blocker bugs, validate perf.
137
+
138
+ - Parser rewrite from scratch (new AST, incremental indexing)
139
+ - Memory leak fix in watcher — blocking prod since Jan 4
140
+ - Cross-platform CI matrix
141
+ - Performance baseline vs v0.17
142
+ ```
143
+
144
+ Mapping (**plan-as-parent** strategy):
145
+ - Each `## Sprint N — <title>` or `## Sprint 0.5 — <title>` → ONE parent item:
146
+ `item_type="feature"`, `title="Sprint N — <title>"`, description includes the Goal line
147
+ - Each bullet under the sprint → `add_checkpoint(parent_id, bullet_text)`
148
+ - Completed sprint (all bullets done, or marked "Done"/"✅ Shipped"):
149
+ resolve parent + complete all checkpoints
150
+ - Recognize multilingual section markers: `## Sprint`, `## Iteration`,
151
+ `## Faza`, `## Etap`
152
+
153
+ ### Format C — Custom issue format (ORCH-N, BUG-N)
154
+
155
+ ```markdown
156
+ ## ORCH-3 — Scheduler race on concurrent writes
157
+
158
+ **Where**: cmd/scheduler/dispatch.go:142
159
+ **Problem**: Two workers claim the same job when heartbeat skipped.
160
+ **Fix**: Add advisory lock around SELECT FOR UPDATE SKIP LOCKED.
161
+ **Severity**: P1
162
+ **Status**: open
163
+ ```
164
+
165
+ Mapping:
166
+ - Heading → `title` (strip the ID prefix or capture it as tag)
167
+ - `**Where**:` → `source_file` (+ `source_lines` if line range present)
168
+ - `**Problem**:` + `**Fix**:` → merged into `description`
169
+ - `**Severity**:` → `priority` (P1/P2/P3)
170
+ - `**Status**:` → `status` (map "open"/"in progress"/"done"/"resolved")
171
+ - `item_type="issue"` (that's what this format represents)
172
+ - Prefix like `ORCH-3` → `tags=["orch"]` (derive bucket tag from prefix)
173
+
174
+ ### Format D — Plan-as-parent (1.5k+ line planning doc)
175
+
176
+ Large planning documents (1.5k-2k+ lines) SHOULD NOT be flattened into
177
+ hundreds of items. Instead:
178
+
179
+ 1. File → ONE parent item: `item_type="feature"`, title from file H1,
180
+ description = first prose section + link to file path.
181
+ 2. Each `##` section → `add_checkpoint(parent_id, section_title)`.
182
+ 3. Each checkbox WITHIN those sections → one more `add_checkpoint` (nested
183
+ via sort_order grouping, e.g. section 1 gets sort 10-19, section 2 gets 20-29).
184
+ 4. If file has >7 `##` sections, ask user via `AskUserQuestion` whether
185
+ they prefer "one parent per section" (multiple items) instead.
186
+
187
+ ### Format E — Keep-a-Changelog with [Unreleased]
188
+
189
+ Standard format:
190
+ ```markdown
191
+ ## [Unreleased]
192
+ ### Added
193
+ - New Python parser support
194
+
195
+ ### Fixed
196
+ - Memory leak in watcher
197
+ ```
198
+
199
+ Mapping:
200
+ - `### Added/Changed/Fixed/Removed` → `category` directly
201
+ - Bullet → `entry`
202
+ - Only import `[Unreleased]` section by default (past versions already released)
203
+
204
+ ### Format F — Keep-a-Changelog WITHOUT [Unreleased]
205
+
206
+ Some projects collapse everything into versioned sections and have no
207
+ `[Unreleased]`. Ask user via `AskUserQuestion`:
208
+ - question: "No [Unreleased] section found. Import all versions or skip?"
209
+ - options:
210
+ - `"Import latest version only (treat as unreleased)"`
211
+ - `"Import all versions, stamped with their versions"` — uses
212
+ `mcp__dct__add_changelog` then `release_changelog(version=X)` per version
213
+ - `"Skip changelog import"`
214
+
215
+ ### Format G — Empty subsections
216
+
217
+ ```markdown
218
+ ## [Unreleased]
219
+ ### Added
220
+
221
+ ### Fixed
222
+ - Actually something here
223
+ ```
224
+
225
+ Skip empty subsections gracefully — do not create placeholder items. If
226
+ ALL subsections under [Unreleased] are empty, treat the file as "no
227
+ unreleased content" and move on.
228
+
229
+ ### Format H — FUTURE.md / IDEAS.md (prose or loose bullets)
230
+
231
+ ```markdown
232
+ ## Maybe someday
233
+
234
+ Would be cool to support Ruby parsers. The challenge is...
235
+
236
+ Another idea: plugin system for custom languages.
237
+ ```
238
+
239
+ Mapping:
240
+ - Each H2/bullet → `item_type="idea"`, `priority="future"`
241
+ - Description = the prose underneath (first 500 chars)
242
+
243
+ ### Format I — Conventional-commit style entries
244
+
245
+ ```markdown
246
+ - feat(parser): add Python support
247
+ - fix(watcher): memory leak on large trees
248
+ - refactor(graph): extract schema builder
249
+ ```
250
+
251
+ Mapping (useful when importing from git log turned into markdown):
252
+ - Prefix `feat:` / `feat(scope):` → `category="added"`, `component=<scope>`
253
+ - `fix:` → `category="fixed"`
254
+ - `refactor:` / `chore:` / `perf:` / `style:` → `category="changed"`
255
+ - `revert:` / `remove:` → `category="removed"`
256
+ - Text after `:` → `entry`
257
+
258
+ ### Format J — No-changelog graceful case
259
+
260
+ If the project has NO changelog file, do NOT error. Report: `"No changelog
261
+ file found — skipping changelog import"` and continue with items only.
262
+
263
+ ---
264
+
265
+ ## Stale-file skip list
266
+
267
+ Skip these paths during Step 1 detection — do NOT offer them to the user.
268
+ Common sources of already-migrated / archival / generated content:
269
+
270
+ - `.cursor/plans/`, `.cursor/chats/` — Cursor working files
271
+ - `worktrees/`, `.git/worktrees/` — git worktree dirs
272
+ - `old_modules*`, `old-*`, `*-archive`, `archive/` — manual archives
273
+ - `node_modules/`, `target/`, `dist/`, `build/` — build outputs
274
+ - `.venv/`, `venv/`, `__pycache__/` — Python virtualenvs
275
+ - `.claude/`, `.gstack/` — plugin internals
276
+ - Any file matching `*.bak`, `*.old`, `*~`
277
+
278
+ User can override ("include archive/old-bugs.md anyway") via explicit path
279
+ in their /dct-import invocation.
280
+
281
+ ---
282
+
283
+ ## Edge case handling
284
+
285
+ ### Bilingual / mixed-language titles
286
+
287
+ Polish, English, mixed — preserve as-is. Do not translate, do not strip
288
+ language markers. Example: `"Parser crashes / Parser się wywala"` stays
289
+ as the title unchanged.
290
+
291
+ ### Composite files (plan + checkboxes + narrative)
292
+
293
+ When a file clearly mixes formats, pick the dominant one and note the
294
+ mixed nature in the user's review table ("composite: plan-as-parent with
295
+ embedded checkboxes"). Usually "plan-as-parent" wins for 500+ line docs.
296
+
297
+ ### Done-status recognition
298
+
299
+ A sub-task is DONE when ANY of these hold:
300
+ - `[x]` or `[X]` prefix
301
+ - `✅` marker anywhere in the line
302
+ - Literal `**DONE**`, `STATUS: DONE`, `[DONE]`, `(done)`, `— done`
303
+ - Line struck through with `~~text~~`
304
+
305
+ ### No sprint / no plan / no checkboxes
306
+
307
+ If the file is pure prose without structure, offer to import as a single
308
+ `item_type="idea"` with the file content as description (truncated to
309
+ ~1000 chars with link to full file path).
310
+
311
+ ---
312
+
313
+ ## Rules
314
+
315
+ - **Every user decision is AskUserQuestion** — no plain-text prompts.
316
+ - **Plan-like files → `ingest_plan_file`** — v0.2 pipeline owns ULID injection
317
+ and first-import state semantics. Do not re-implement these inline.
318
+ - **Issue-like / changelog files → v0.1 items / changelog path** — unchanged,
319
+ uses Pattern Catalog below.
320
+ - **Plan-like ingest DOES modify source files** — it injects HTML-comment
321
+ ULID anchors. Users should know this (show diff option if they're unsure).
322
+ Other formats: NEVER modify source files.
323
+ - **Provenance notes are mandatory for v0.1 items** — every legacy-path
324
+ item gets `add_note("Imported from <file> on <date>")`. Plan-like entries
325
+ have `plans.source_file` + `plans.imported_at` which serve the same role.
326
+ - **Respect stale-file skip list** — do not even offer those to the user.
327
+ - **One file, one format** — pick dominant; note composites for the user.
328
+ - **Changelog missing is OK** — skip gracefully, never error out.
329
+ - **Ambiguities are NEVER silent** — always flag and ask.
@@ -0,0 +1,289 @@
1
+ ---
2
+ name: dct-init
3
+ description: |
4
+ Initialize dct for the current project — dual-mode: runs global bootstrap if
5
+ missing, then registers the current directory as a dct project. Interactive
6
+ via AskUserQuestion for path / slug / name / version (with smart defaults from
7
+ detect_version). Also offers to inject `mcp__dct__*` into the Claude Code
8
+ permissions allowlist so daily MCP calls stop prompting.
9
+ Use when: "dct-init", "/dct-init", "zainicjalizuj dct", "setup dct here",
10
+ "add this project to dct", "register this project", "dodaj projekt do dct",
11
+ "skonfiguruj dct", "dct setup", "initialize dct", "bootstrap dct".
12
+ ---
13
+
14
+ # /dct-init — bootstrap or register
15
+
16
+ One entry point for dct setup. Replaces the split mental model of
17
+ `dct init` (global, once) + `dct project add` (per-project, manual).
18
+
19
+ ## Workflow
20
+
21
+ ### Step 1: Probe global bootstrap state
22
+
23
+ Check three things in parallel:
24
+
25
+ 1. MCP registration: read `~/.claude.json`; does `mcpServers.dct` exist?
26
+ 2. Skills: does `~/.claude/skills/track` exist (as symlink or dir)?
27
+ 3. Hooks: does `~/.claude/hooks/dct-check-changelog.sh` exist?
28
+
29
+ Derive `bootstrap_complete` = all three present.
30
+
31
+ If NOT complete:
32
+ AskUserQuestion:
33
+ question: "Global dct bootstrap is incomplete. Run `dct init` now?"
34
+ header: "Bootstrap"
35
+ options:
36
+ - "Yes — run bootstrap (recommended)"
37
+ - "Abort — I'll fix it manually"
38
+ On "yes": Bash `dct init`, capture output, show summary. Re-probe after.
39
+ On "abort": print instructions and exit.
40
+
41
+ If complete: skip to Step 2.
42
+
43
+ ### Step 2: Probe + offer MCP allowlist injection
44
+
45
+ Read `~/.claude/settings.json`. Check if `permissions.allow` contains
46
+ any entry matching `mcp__dct__*` (wildcard) or any individual
47
+ `mcp__dct__<tool>` entry.
48
+
49
+ If none present:
50
+ AskUserQuestion:
51
+ question: "dct MCP tools aren't on the Claude Code allow list — every call prompts. Add them?"
52
+ header: "Allowlist"
53
+ options:
54
+ - "Yes — global ~/.claude/settings.json (recommended)"
55
+ - "Yes — project-scope .claude/settings.local.json"
56
+ - "No — skip, I'll prompt-approve each time"
57
+
58
+ On "global": edit `~/.claude/settings.json`, append
59
+ `"mcp__dct__*"` to `permissions.allow` (preserve order; dedupe).
60
+ On "project": edit `.claude/settings.local.json` in the CWD
61
+ (create file if missing) with the same entry.
62
+ On "no": continue.
63
+
64
+ If already present: note "✓ allowlist already has dct entries" and continue.
65
+
66
+ ### Step 2.5: Probe project-local CC artefacts for conflicts
67
+
68
+ Scan CWD for project-local CC artefacts that could conflict with or shadow
69
+ the global dct install. Read-only until Step 2.5b.
70
+
71
+ Check in parallel:
72
+
73
+ | Location | What to look for | Conflict when… |
74
+ |---|---|---|
75
+ | `./.claude/skills/<name>/SKILL.md` | names matching dct's skill list (track, track-list, clog, commit, release, dct-import, dct-init, handoff, pickup) | local skill **shadows** global — typically unintentional |
76
+ | `./.claude/hooks/*changelog*.sh` | project-local changelog hooks | duplicates global dct hook behavior |
77
+ | `./.claude/settings.json` `hooks` section | wires to local hooks | runs in addition to global ones |
78
+ | `./CLAUDE.md` / `./.claude/CLAUDE.md` | mentions of other trackers ("linear", "jira", "TODOS.md", "ISSUES.md") | project has an existing tracker — `/dct-import` may help migrate |
79
+
80
+ If zero conflicts: report "✓ No CC artefact conflicts with global dct" and continue.
81
+
82
+ For each conflict, ask via `AskUserQuestion`:
83
+
84
+ question: f"Conflict: {<describe>} (found at {<path>})"
85
+ header: "Conflict"
86
+ options:
87
+ - "Keep local, use it (ignore global)" — CC precedence already favors local, no action
88
+ - "Remove local (backup to <path>.bak) and use global dct" — rename file, keep backup
89
+ - "Integrate — wire local into dct workflow" — for hooks: add `exec <global-hook>` at end of local script; for CLAUDE.md: add a "[uses dct]" note and suggest /dct-import
90
+ - "Skip — decide later" — leave the conflict, proceed to Step 3
91
+
92
+ Each decision is recorded; at the end of Step 2.5, print a short summary:
93
+ "✓ Handled N conflicts: <list>" or "✓ No conflicts" if clean.
94
+
95
+ ### Step 2.6: Probe version-sync script integration
96
+
97
+ dct's `/release` Step 6 runs `./scripts/dct-version-sync.sh <version>` if
98
+ present. We want every registered project to have a version-sync script so
99
+ `/release` can bump project files automatically.
100
+
101
+ Probe in order (first-match wins for the existence check):
102
+
103
+ 1. `./scripts/dct-version-sync.sh` — if line 1 begins with `# dct-version-sync template v`, report "✓ version-sync already integrated" and continue. Otherwise treat as existing-but-unmarked → ask user whether to add sentinel.
104
+ 2. `./scripts/*version*.sh` or `./scripts/*bump*.sh` or `./scripts/release.sh` — existing non-dct bump script.
105
+ 3. `./Makefile` or `./justfile` or `./Taskfile.yml` with a `version:` / `bump:` / `release:` target.
106
+ 4. None of the above — greenfield, no script.
107
+
108
+ Based on probe result, use `AskUserQuestion`:
109
+
110
+ **Case 1 — existing dct template (sentinel present)**: skip, already good.
111
+
112
+ **Case 2 — existing non-dct script**:
113
+ question: f"Found existing {script_path}. Integrate with dct?"
114
+ header: "Version sync"
115
+ options:
116
+ - "Wrap — generate scripts/dct-version-sync.sh that delegates to <script> $1 (recommended)"
117
+ - "Replace — overwrite with dct template (backup original to .bak)"
118
+ - "Keep standalone — /release will skip Step 6; user runs script manually"
119
+ - "Skip for now"
120
+
121
+ On "wrap": write minimal shim:
122
+ ```bash
123
+ #!/usr/bin/env bash
124
+ # dct-version-sync template v1 (wraps <original-script>)
125
+ set -euo pipefail
126
+ exec "$(dirname "$0")/<original-script-name>" "$@"
127
+ ```
128
+
129
+ On "replace": copy dct's `scripts/dct-version-sync.sh` template, uncomment
130
+ the block matching detected project kind (result of `detect_version` in
131
+ Step 4d: VERSION / pyproject.toml / package.json / Cargo.toml / tauri.conf.json).
132
+
133
+ **Case 3 — Makefile/justfile/Taskfile target**:
134
+ question: f"Found {tool} target {target_name}. Integrate with dct?"
135
+ header: "Version sync"
136
+ options:
137
+ - "Wrap — generate scripts/dct-version-sync.sh that calls `{tool} {target} $1` (recommended)"
138
+ - "Skip — /release will skip Step 6; user runs {tool} {target} manually"
139
+
140
+ **Case 4 — no script detected**:
141
+ question: "No version-sync script found. Generate template?"
142
+ header: "Version sync"
143
+ options:
144
+ - f"Generate scripts/dct-version-sync.sh with {detected_kind} block uncommented (recommended)"
145
+ - "Generate all blocks commented (pick manually later)"
146
+ - "Skip"
147
+
148
+ All generated scripts include the sentinel `# dct-version-sync template v1`
149
+ as line 1 (after shebang) so future `/dct-init` runs short-circuit via
150
+ Case 1 and do not regenerate.
151
+
152
+ ### Step 3: Probe current project registration
153
+
154
+ Call `mcp__dct__list_projects`. Let `cwd = os.getcwd()`.
155
+
156
+ Match: for each project row, check if `cwd == row.path` or
157
+ `cwd.startswith(row.path + "/")`. Longest-prefix wins (use
158
+ `get_project_by_path` semantics).
159
+
160
+ If matched:
161
+ Print "✓ Already registered as `<slug>` — current_version=<v>, path=<path>".
162
+ Offer via AskUserQuestion:
163
+ question: "Project is already registered. What now?"
164
+ header: "Registered"
165
+ options:
166
+ - "Nothing — just confirm status"
167
+ - "Update version — call `dct project set-version`"
168
+ - "Show current items — /track-list"
169
+ Run matching action. Exit.
170
+
171
+ If no match: continue to Step 4.
172
+
173
+ ### Step 4: Collect registration inputs
174
+
175
+ Derive defaults first (pure functions, no side effects):
176
+ - `default_path` = CWD
177
+ - `default_slug` = `basename(CWD)`, lowercased, non-alnum → `-`
178
+ - `default_name` = title-case of `default_slug` (split on `-`/`_`, capitalize)
179
+ - `(detected_version, source_file)` = `dct.core.version.detect_version(default_path)`
180
+
181
+ Ask sequentially (four AskUserQuestions bundled in one tool call when possible):
182
+
183
+ a) Path confirmation:
184
+ question: "Register dct project at this path?"
185
+ header: "Path"
186
+ options:
187
+ - f"Yes — {default_path} (recommended)"
188
+ - "Different path — I'll type it"
189
+
190
+ b) Slug:
191
+ question: "Project slug (short id used in CLI, URLs, queries)?"
192
+ header: "Slug"
193
+ options:
194
+ - f"{default_slug} (recommended)"
195
+ - "Other — type custom"
196
+
197
+ c) Name:
198
+ question: "Human-readable display name?"
199
+ header: "Name"
200
+ options:
201
+ - f"{default_name} (recommended)"
202
+ - "Other — type custom"
203
+
204
+ d) Version:
205
+ If `detected_version` is not None:
206
+ question: f"Starting version? (detected: {detected_version} from {source_file})"
207
+ header: "Version"
208
+ options:
209
+ - f"{detected_version} (detected, recommended)"
210
+ - "Type custom"
211
+ - "Leave NULL (set later via `dct project set-version`)"
212
+ Else:
213
+ question: "Starting version? (none detected)"
214
+ header: "Version"
215
+ options:
216
+ - "0.1.0 (alpha — recommended)"
217
+ - "0.0.1 (pre-alpha)"
218
+ - "1.0.0 (stable)"
219
+ - "Type custom"
220
+
221
+ For any "Other — type custom" / "Type custom", use the answer's free-text value.
222
+
223
+ ### Step 5: Execute registration
224
+
225
+ Build command:
226
+ ```
227
+ dct project add <slug> <path> --name "<name>" [--version <vX.Y.Z>]
228
+ ```
229
+
230
+ Skip `--version` when user picked "Leave NULL".
231
+
232
+ Run via Bash. Verify with `mcp__dct__list_projects` — the new slug must appear.
233
+
234
+ ### Step 6: Final report
235
+
236
+ ```
237
+ ✓ Bootstrap: mcpServers.dct OK, N skills installed, M hooks installed
238
+ ✓ Allowlist: "mcp__dct__*" in ~/.claude/settings.json
239
+ ✓ Project: <slug> registered at <path>, version <v>
240
+ ```
241
+
242
+ ### Step 7: Propose a concrete next action
243
+
244
+ Registration alone does nothing visible — the project's DB row is empty.
245
+ Offer the natural follow-up via `AskUserQuestion`:
246
+
247
+ question: "Project is registered. What next?"
248
+ header: "Next step"
249
+ options:
250
+ - "Import existing MD tracking — run /dct-import now"
251
+ → delegate to the `/dct-import` skill (pass the freshly-registered
252
+ slug implicitly via CWD auto-detect — the skill takes over from
253
+ there with its own AskUserQuestion flow for file selection).
254
+ - "Create first item manually — run /track"
255
+ → delegate to the `/track` skill.
256
+ - "Exit — I'll come back later"
257
+ → print a one-liner hint listing both commands and stop.
258
+
259
+ **Why this matters**: without the follow-up prompt, users correctly
260
+ register their project and then bounce off a blank slate — the DB has a
261
+ projects row but nothing else, so `/pickup` returns empty, `/track-list`
262
+ returns empty, and it looks like dct "doesn't do anything". For projects
263
+ with pre-existing MD tracking (ROADMAP, TODOS, sprint docs, changelog),
264
+ `/dct-import` is almost always the right next move and should be
265
+ offered proactively, not discovered by hunting.
266
+
267
+ **Probe before offering**: if the project path contains plausible
268
+ tracking files (any of `ROADMAP.md`, `TODOS.md`, `BACKLOG.md`,
269
+ `SPRINT*.md`, `PLAN*.md`, `CHANGELOG.md`, `changelog.md`,
270
+ `docs/plans/*.md`, `docs/specs/*.md`), make the `/dct-import` option the
271
+ **recommended** choice. If none exist, demote it — the recommended
272
+ default becomes `/track` for a greenfield project.
273
+
274
+ ## Rules
275
+
276
+ - **Every decision is AskUserQuestion.** Never plain Y/N via read.
277
+ - **Idempotent probes first.** Safe to re-run at any time — re-running
278
+ with everything in place reports ✓ for each check and exits.
279
+ - **Smart defaults, no free-text when avoidable.** The "Other — type
280
+ custom" escape hatch covers unusual cases but default path is one click.
281
+ - **Single source of truth for bootstrap.** Skill calls `dct init`
282
+ under the hood; never re-implements MCP/skill/hook installation.
283
+ - **Single source of truth for registration.** Skill calls
284
+ `dct project add`; never writes the DB directly.
285
+ - **Preserve existing allowlist order.** Append, don't sort; dedupe
286
+ before write.
287
+ - **No overwrite without confirmation.** If `mcpServers.dct` already
288
+ exists with different config, surface the conflict via AskUserQuestion
289
+ before touching it.