tasktree-manager 2.8.0__tar.gz → 2.9.0__tar.gz

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 (62) hide show
  1. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/CHANGELOG.md +14 -0
  2. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/PKG-INFO +1 -1
  3. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/docs/configuration.md +55 -9
  4. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/docs/user-guide.md +5 -0
  5. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/pyproject.toml +1 -1
  6. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tasktree_manager/_version.py +2 -2
  7. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tasktree_manager/app.py +312 -247
  8. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tasktree_manager/services/claude_hooks.py +42 -3
  9. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tasktree_manager/services/config.py +12 -1
  10. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tasktree_manager/services/task_manager.py +134 -82
  11. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tasktree_manager/widgets/create_modal.py +27 -25
  12. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tasktree_manager/widgets/task_list.py +7 -2
  13. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tasktree_manager/widgets/worktree_list.py +6 -2
  14. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tests/test_claude_hooks.py +67 -0
  15. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tests/test_task_manager.py +150 -20
  16. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/SKILL.md +0 -0
  17. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/assets/README.md +0 -0
  18. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/assets/dashboard_app.py +0 -0
  19. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/assets/data_viewer.py +0 -0
  20. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/assets/todo_app.py +0 -0
  21. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/assets/worker_demo.py +0 -0
  22. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/references/layouts.md +0 -0
  23. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/references/official-guides-index.md +0 -0
  24. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/references/styling.md +0 -0
  25. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/.claude/skills/textual-tui/references/widgets.md +0 -0
  26. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/.github/templates/CHANGELOG.md.j2 +0 -0
  27. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/.github/workflows/ci.yml +0 -0
  28. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/.github/workflows/release.yml +0 -0
  29. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/.gitignore +0 -0
  30. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/CONTRIBUTING.md +0 -0
  31. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/LICENSE +0 -0
  32. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/OPENSPEC.md +0 -0
  33. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/README.md +0 -0
  34. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/ROADMAP.md +0 -0
  35. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/docs/claude-code-integration-spec.md +0 -0
  36. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/docs/installation.md +0 -0
  37. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/docs/troubleshooting.md +0 -0
  38. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/mise.toml +0 -0
  39. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/scripts/bump_version.py +0 -0
  40. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tasktree_manager/__init__.py +0 -0
  41. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tasktree_manager/commands.py +0 -0
  42. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tasktree_manager/services/__init__.py +0 -0
  43. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tasktree_manager/services/git_ops.py +0 -0
  44. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tasktree_manager/services/models.py +0 -0
  45. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tasktree_manager/themes.py +0 -0
  46. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tasktree_manager/widgets/__init__.py +0 -0
  47. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tasktree_manager/widgets/app_header.py +0 -0
  48. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tasktree_manager/widgets/messages_panel.py +0 -0
  49. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tasktree_manager/widgets/setup_modal.py +0 -0
  50. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tasktree_manager/widgets/status_panel.py +0 -0
  51. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tests/__init__.py +0 -0
  52. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tests/conftest.py +0 -0
  53. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tests/test_app.py +0 -0
  54. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tests/test_commands.py +0 -0
  55. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tests/test_config.py +0 -0
  56. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tests/test_git_ops.py +0 -0
  57. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tests/test_integration_git.py +0 -0
  58. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tests/test_memory.py +0 -0
  59. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tests/test_messages_panel.py +0 -0
  60. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tests/test_modals.py +0 -0
  61. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tests/test_setup_modal.py +0 -0
  62. {tasktree_manager-2.8.0 → tasktree_manager-2.9.0}/tests/test_status_panel.py +0 -0
@@ -15,6 +15,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
15
15
  - Git hooks support
16
16
  - Custom task metadata
17
17
 
18
+ ## [2.9.0] - 2026-07-14
19
+
20
+ ### Added
21
+ - **app**: Move blocking git work off the UI thread
22
+
23
+ ### Changed
24
+ - Format worktree settings call with ruff
25
+ - **app**: Extract Claude session preparation helper
26
+
27
+ ### Fixed
28
+ - Address review findings in async refresh and hook merging
29
+ - Harden task/branch validation, hook merging, markup rendering
30
+
31
+
18
32
  ## [2.8.0] - 2026-07-14
19
33
 
20
34
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tasktree-manager
3
- Version: 2.8.0
3
+ Version: 2.9.0
4
4
  Summary: TUI application for managing worktree-based tasks
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.10
@@ -222,7 +222,7 @@ cycle_theme = "t" # Cycle through the design-system themes
222
222
  # Symlinks
223
223
  # ============================================================================
224
224
  # When creating worktrees, gitignored files are symlinked from the source repo.
225
- # Blocklist specifies patterns to exclude (e.g., cache files).
225
+ # Blocklist specifies patterns to exclude (e.g., cache files, key material).
226
226
  [symlinks]
227
227
  blocklist = [
228
228
  "*.pyc",
@@ -233,6 +233,9 @@ blocklist = [
233
233
  ".ruff_cache",
234
234
  ".coverage",
235
235
  "*.log",
236
+ "*.pem",
237
+ "*.key",
238
+ "id_rsa",
236
239
  ]
237
240
  ```
238
241
 
@@ -388,7 +391,9 @@ When creating worktrees, tasktree-manager automatically symlinks gitignored file
388
391
 
389
392
  ### Default Blocklist
390
393
 
391
- By default, these patterns are excluded from symlinking:
394
+ By default, these patterns are excluded from symlinking. Caches and build
395
+ artifacts are excluded as noise; key material (`*.pem`, `*.key`, SSH keys)
396
+ is excluded so private keys never spread beyond the main checkout:
392
397
 
393
398
  ```toml
394
399
  [symlinks]
@@ -409,14 +414,28 @@ blocklist = [
409
414
  ".nox",
410
415
  "*.so",
411
416
  "*.dylib",
417
+ "*.pem",
418
+ "*.key",
419
+ "*.p12",
420
+ "*.pfx",
421
+ "*.keystore",
422
+ "id_rsa",
423
+ "id_ecdsa",
424
+ "id_ed25519",
412
425
  ]
413
426
  ```
414
427
 
415
428
  ### How It Works
416
429
 
417
- 1. When a worktree is created, tasktree-manager reads the source repo's `.gitignore`
418
- 2. For each gitignored file pattern, it finds matching files
419
- 3. Files matching the blocklist are skipped
430
+ 1. When a worktree is created, tasktree-manager asks git for the repo's
431
+ ignored files (`git ls-files --others --ignored --exclude-standard`), so
432
+ full gitignore semantics apply: nested `.gitignore` files work, and a
433
+ root pattern like `*.log` matches in subdirectories
434
+ 2. Wholly-ignored directories (e.g. `node_modules/`) are skipped entirely —
435
+ their contents are never walked or symlinked
436
+ 3. Files matching the blocklist (by filename or repo-relative path, so
437
+ patterns like `secrets/*` work) and anything under `.git/` or `.claude/`
438
+ are skipped
420
439
  4. Remaining files are symlinked to the worktree
421
440
 
422
441
  ### Customizing the Blocklist
@@ -437,7 +456,9 @@ blocklist = [
437
456
  ]
438
457
  ```
439
458
 
440
- **Add to default blocklist (must include all patterns):**
459
+ **Add to default blocklist (must include ALL default patterns — an explicit
460
+ blocklist replaces the defaults entirely, including the key-material
461
+ protection):**
441
462
  ```toml
442
463
  [symlinks]
443
464
  blocklist = [
@@ -445,22 +466,47 @@ blocklist = [
445
466
  "*.pyc",
446
467
  "*.pyo",
447
468
  "__pycache__",
469
+ ".pytest_cache",
470
+ ".mypy_cache",
471
+ ".ruff_cache",
448
472
  ".coverage",
449
473
  "*.log",
474
+ "*.egg-info",
475
+ ".eggs",
476
+ "dist",
477
+ "build",
478
+ ".tox",
479
+ ".nox",
480
+ "*.so",
481
+ "*.dylib",
482
+ "*.pem",
483
+ "*.key",
484
+ "*.p12",
485
+ "*.pfx",
486
+ "*.keystore",
487
+ "id_rsa",
488
+ "id_ecdsa",
489
+ "id_ed25519",
450
490
  # Your additions
451
491
  "*.tmp",
452
492
  ".DS_Store",
453
493
  ]
454
494
  ```
455
495
 
496
+ > **Upgrading note:** if your existing `config.toml` already contains a
497
+ > `blocklist`, it keeps overriding the defaults — the key-material patterns
498
+ > added in newer versions do NOT apply until you add them (or delete the
499
+ > `blocklist` line to inherit the defaults).
500
+
456
501
  ### Common Use Cases
457
502
 
458
- **Symlink environment files, block caches:**
503
+ **Symlink environment files, block caches and keys:**
459
504
  ```toml
460
505
  [symlinks]
461
- blocklist = ["*.pyc", "__pycache__", ".coverage", "*.log"]
506
+ blocklist = ["*.pyc", "__pycache__", ".coverage", "*.log", "*.pem", "*.key", "id_rsa"]
462
507
  ```
463
- This allows `.env`, `.mise.toml` to be symlinked while blocking cache files.
508
+ This allows `.env`, `.mise.toml` to be symlinked while blocking cache files
509
+ and private keys.
464
510
 
465
511
  **Block everything (disable symlinks):**
466
512
  ```toml
@@ -309,6 +309,11 @@ what is displayed. Press `?` for the full reference at any time.
309
309
  5. Select repos with `Space` (can select multiple)
310
310
  6. Tab to "Create" button, press `Enter`
311
311
 
312
+ Task names may contain letters, numbers, `.`, `_`, `/` and `-`. Because the
313
+ name becomes a directory under your tasks dir (and a git branch), names with
314
+ `.`/`..` path segments, empty segments, or a leading `-` are rejected; base
315
+ branch names must not start with `-` either.
316
+
312
317
  **Clone task workflow:**
313
318
  Useful when you're spinning up several similar tasks that share the same set of repos.
314
319
 
@@ -70,7 +70,7 @@ version-file = "tasktree_manager/_version.py"
70
70
  # Semantic Release Configuration
71
71
  [tool.semantic_release]
72
72
  version_toml = ["pyproject.toml:tool.semantic_release.version"]
73
- version = "2.8.0"
73
+ version = "2.9.0"
74
74
  tag_format = "v{version}"
75
75
  branch = "main"
76
76
  commit_message = "chore(release): {version} [skip ci]"
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '2.8.0'
22
- __version_tuple__ = version_tuple = (2, 8, 0)
21
+ __version__ = version = '2.9.0'
22
+ __version_tuple__ = version_tuple = (2, 9, 0)
23
23
 
24
24
  __commit_id__ = commit_id = None