taskill 0.1.1__tar.gz → 0.1.2__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 (74) hide show
  1. taskill-0.1.2/CHANGELOG.md +124 -0
  2. {taskill-0.1.1 → taskill-0.1.2}/PKG-INFO +4 -6
  3. {taskill-0.1.1 → taskill-0.1.2}/README.md +3 -5
  4. taskill-0.1.2/SUMD.md +489 -0
  5. taskill-0.1.2/SUMR.md +532 -0
  6. taskill-0.1.2/TODO.md +78 -0
  7. taskill-0.1.2/VERSION +1 -0
  8. taskill-0.1.2/app.doql.less +28 -0
  9. {taskill-0.1.1 → taskill-0.1.2}/goal.yaml +3 -2
  10. taskill-0.1.2/planfile.yaml +552 -0
  11. taskill-0.1.2/prefact.yaml +91 -0
  12. taskill-0.1.2/project/README.md +339 -0
  13. taskill-0.1.2/project/analysis.toon.yaml +60 -0
  14. taskill-0.1.2/project/calls.mmd +65 -0
  15. taskill-0.1.2/project/calls.png +0 -0
  16. taskill-0.1.2/project/calls.toon.yaml +123 -0
  17. taskill-0.1.2/project/calls.yaml +415 -0
  18. taskill-0.1.2/project/compact_flow.mmd +2 -0
  19. taskill-0.1.2/project/compact_flow.png +0 -0
  20. taskill-0.1.2/project/context.md +471 -0
  21. taskill-0.1.2/project/duplication.toon.yaml +34 -0
  22. taskill-0.1.2/project/evolution.toon.yaml +47 -0
  23. taskill-0.1.2/project/flow.mmd +25 -0
  24. taskill-0.1.2/project/flow.png +0 -0
  25. taskill-0.1.2/project/index.html +623 -0
  26. taskill-0.1.2/project/map.toon.yaml +175 -0
  27. taskill-0.1.2/project/mermaid.export +98 -0
  28. taskill-0.1.2/project/project.toon.yaml +53 -0
  29. taskill-0.1.2/project/prompt.txt +49 -0
  30. {taskill-0.1.1 → taskill-0.1.2}/pyproject.toml +11 -1
  31. {taskill-0.1.1 → taskill-0.1.2}/src/taskill/__init__.py +1 -1
  32. taskill-0.1.2/src/taskill/providers/__init__.py +75 -0
  33. taskill-0.1.2/src/taskill/updaters/__init__.py +59 -0
  34. taskill-0.1.2/src/taskill/updaters/base.py +44 -0
  35. taskill-0.1.2/src/taskill/updaters/changelog.py +119 -0
  36. taskill-0.1.2/src/taskill/updaters/readme.py +99 -0
  37. taskill-0.1.2/src/taskill/updaters/todo.py +113 -0
  38. taskill-0.1.2/testql-scenarios/generated-cli-tests.testql.toon.yaml +12 -0
  39. taskill-0.1.2/tests/test_providers.py +76 -0
  40. taskill-0.1.1/CHANGELOG.md +0 -51
  41. taskill-0.1.1/SUMD.md +0 -79
  42. taskill-0.1.1/TODO.md +0 -3
  43. taskill-0.1.1/VERSION +0 -1
  44. taskill-0.1.1/src/taskill/providers/__init__.py +0 -37
  45. taskill-0.1.1/src/taskill/updaters/__init__.py +0 -6
  46. taskill-0.1.1/src/taskill/updaters/changelog.py +0 -92
  47. taskill-0.1.1/src/taskill/updaters/readme.py +0 -74
  48. taskill-0.1.1/src/taskill/updaters/todo.py +0 -77
  49. {taskill-0.1.1 → taskill-0.1.2}/.gitignore +0 -0
  50. {taskill-0.1.1 → taskill-0.1.2}/LICENSE +0 -0
  51. {taskill-0.1.1 → taskill-0.1.2}/ROADMAP.md +0 -0
  52. {taskill-0.1.1 → taskill-0.1.2}/examples/ansible-playbook.yml +0 -0
  53. {taskill-0.1.1 → taskill-0.1.2}/examples/github-action.yml +0 -0
  54. {taskill-0.1.1 → taskill-0.1.2}/examples/gitlab-ci.yml +0 -0
  55. {taskill-0.1.1 → taskill-0.1.2}/examples/systemd-timer/taskill.service +0 -0
  56. {taskill-0.1.1 → taskill-0.1.2}/examples/systemd-timer/taskill.timer +0 -0
  57. {taskill-0.1.1 → taskill-0.1.2}/project.sh +0 -0
  58. {taskill-0.1.1 → taskill-0.1.2}/src/taskill/cli.py +0 -0
  59. {taskill-0.1.1 → taskill-0.1.2}/src/taskill/config.py +0 -0
  60. {taskill-0.1.1 → taskill-0.1.2}/src/taskill/core.py +0 -0
  61. {taskill-0.1.1 → taskill-0.1.2}/src/taskill/git_state.py +0 -0
  62. {taskill-0.1.1 → taskill-0.1.2}/src/taskill/providers/algorithmic.py +0 -0
  63. {taskill-0.1.1 → taskill-0.1.2}/src/taskill/providers/base.py +0 -0
  64. {taskill-0.1.1 → taskill-0.1.2}/src/taskill/providers/openrouter.py +0 -0
  65. {taskill-0.1.1 → taskill-0.1.2}/src/taskill/providers/windsurf_mcp.py +0 -0
  66. {taskill-0.1.1 → taskill-0.1.2}/src/taskill/state.py +0 -0
  67. {taskill-0.1.1 → taskill-0.1.2}/src/taskill/triggers.py +0 -0
  68. {taskill-0.1.1 → taskill-0.1.2}/taskill.yaml +0 -0
  69. {taskill-0.1.1 → taskill-0.1.2}/tests/__init__.py +0 -0
  70. {taskill-0.1.1 → taskill-0.1.2}/tests/test_algorithmic.py +0 -0
  71. {taskill-0.1.1 → taskill-0.1.2}/tests/test_config.py +0 -0
  72. {taskill-0.1.1 → taskill-0.1.2}/tests/test_triggers.py +0 -0
  73. {taskill-0.1.1 → taskill-0.1.2}/tests/test_updaters.py +0 -0
  74. {taskill-0.1.1 → taskill-0.1.2}/tree.sh +0 -0
@@ -0,0 +1,124 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.10] - 2026-04-25
9
+
10
+ ### Fixed
11
+ - Fix unused-imports issues (ticket-db5e9dd3)
12
+ - Fix magic-numbers issues (ticket-dba8c3c5)
13
+ - Fix unused-imports issues (ticket-af09dd4b)
14
+ - Fix magic-numbers issues (ticket-ea7332e2)
15
+ - Fix unused-imports issues (ticket-9c26f888)
16
+ - Fix magic-numbers issues (ticket-f494aa3e)
17
+ - Fix ai-boilerplate issues (ticket-3bd97300)
18
+ - Fix string-concat issues (ticket-b6a4b573)
19
+ - Fix unused-imports issues (ticket-5432ca41)
20
+ - Fix magic-numbers issues (ticket-bd9bfba5)
21
+ - Fix unused-imports issues (ticket-d5ad71d9)
22
+ - Fix magic-numbers issues (ticket-fe3ac057)
23
+ - Fix unused-imports issues (ticket-4d94a8de)
24
+ - Fix magic-numbers issues (ticket-8d730c8d)
25
+ - Fix unused-imports issues (ticket-7a0100b5)
26
+ - Fix magic-numbers issues (ticket-bbec1630)
27
+ - Fix unused-imports issues (ticket-8a420046)
28
+ - Fix unused-imports issues (ticket-1e4e88a3)
29
+ - Fix unused-imports issues (ticket-e510c6ac)
30
+ - Fix string-concat issues (ticket-827efc22)
31
+ - Fix unused-imports issues (ticket-d605ceff)
32
+ - Fix unused-imports issues (ticket-36ce53f0)
33
+ - Fix string-concat issues (ticket-2afcff30)
34
+ - Fix unused-imports issues (ticket-3865ee88)
35
+ - Fix unused-imports issues (ticket-f2dc4a4e)
36
+ - Fix llm-generated-code issues (ticket-190195e3)
37
+ - Fix string-concat issues (ticket-b05e6370)
38
+ - Fix unused-imports issues (ticket-fdbb78c9)
39
+ - Fix string-concat issues (ticket-605e46fa)
40
+ - Fix unused-imports issues (ticket-8062d9b4)
41
+ - Fix smart-return-type issues (ticket-c98c14b7)
42
+ - Fix unused-imports issues (ticket-14a6db68)
43
+ - Fix smart-return-type issues (ticket-af05b203)
44
+ - Fix unused-imports issues (ticket-885edd98)
45
+ - Fix duplicate-imports issues (ticket-f77051af)
46
+ - Fix smart-return-type issues (ticket-1f6a0131)
47
+ - Fix unused-imports issues (ticket-1ced127f)
48
+ - Fix smart-return-type issues (ticket-22f03c7b)
49
+ - Fix unused-imports issues (ticket-11ba31e7)
50
+ - Fix smart-return-type issues (ticket-098fd02a)
51
+ - Fix unused-imports issues (ticket-3ec5ceaf)
52
+
53
+ ## [Unreleased]
54
+
55
+ ## [0.1.2] - 2026-04-25
56
+
57
+ ### Docs
58
+ - Update CHANGELOG.md
59
+ - Update README.md
60
+ - Update SUMD.md
61
+ - Update SUMR.md
62
+ - Update TODO.md
63
+ - Update project/README.md
64
+ - Update project/context.md
65
+
66
+ ### Test
67
+ - Update testql-scenarios/generated-cli-tests.testql.toon.yaml
68
+ - Update tests/test_providers.py
69
+
70
+ ### Other
71
+ - Update app.doql.less
72
+ - Update planfile.yaml
73
+ - Update prefact.yaml
74
+ - Update project/analysis.toon.yaml
75
+ - Update project/calls.mmd
76
+ - Update project/calls.png
77
+ - Update project/calls.toon.yaml
78
+ - Update project/calls.yaml
79
+ - Update project/compact_flow.mmd
80
+ - Update project/compact_flow.png
81
+ - ... and 9 more files
82
+
83
+ ## [0.1.1] - 2026-04-25
84
+
85
+ ### Docs
86
+ - Update CHANGELOG.md
87
+ - Update README.md
88
+ - Update ROADMAP.md
89
+ - Update SUMD.md
90
+ - Update TODO.md
91
+
92
+ ### Test
93
+ - Update tests/__init__.py
94
+ - Update tests/test_algorithmic.py
95
+ - Update tests/test_config.py
96
+ - Update tests/test_triggers.py
97
+ - Update tests/test_updaters.py
98
+
99
+ ### Other
100
+ - Update .env.example
101
+ - Update .gitignore
102
+ - Update PKG-INFO
103
+ - Update examples/ansible-playbook.yml
104
+ - Update examples/github-action.yml
105
+ - Update examples/gitlab-ci.yml
106
+ - Update examples/systemd-timer/taskill.service
107
+ - Update examples/systemd-timer/taskill.timer
108
+ - Update project.sh
109
+ - Update taskill.yaml
110
+ - ... and 1 more files
111
+
112
+ ## [0.1.0] - 2026-04-25
113
+
114
+ ### Added
115
+
116
+ - Initial working version
117
+ - Provider chain: Windsurf MCP → OpenRouter → algorithmic fallback
118
+ - Trigger system with state persistence in `.taskill/state.json`
119
+ - CHANGELOG / TODO / README updaters (idempotent, marker-bounded)
120
+ - CLI: `taskill init / status / run / release / clean-todo`
121
+ - `.env` loading via `python-dotenv`; auto-strips `openrouter/` prefix from `LLM_MODEL`
122
+ - Conventional Commits parser for the algorithmic provider
123
+ - Loose-coupling integration with `pyqual` (subprocess + JSON report)
124
+ - Example configs for GitHub Actions, GitLab CI, Ansible
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: taskill
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: Daily project hygiene: keep README / CHANGELOG / TODO in sync with reality. LLM-first, algorithmic fallback.
5
5
  Project-URL: Homepage, https://github.com/oqlos/taskill
6
6
  Project-URL: Issues, https://github.com/oqlos/taskill/issues
@@ -37,18 +37,16 @@ Description-Content-Type: text/markdown
37
37
 
38
38
  ## AI Cost Tracking
39
39
 
40
- ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.1.1-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
41
- ![AI Cost](https://img.shields.io/badge/AI%20Cost-$0.15-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-1.0h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
40
+ ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.1.2-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
41
+ ![AI Cost](https://img.shields.io/badge/AI%20Cost-$0.15-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-2.0h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
42
42
 
43
43
  - 🤖 **LLM usage:** $0.1500 (1 commits)
44
- - 👤 **Human dev:** ~$100 (1.0h @ $100/h, 30min dedup)
44
+ - 👤 **Human dev:** ~$200 (2.0h @ $100/h, 30min dedup)
45
45
 
46
46
  Generated on 2026-04-25 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
47
47
 
48
48
  ---
49
49
 
50
-
51
-
52
50
  > Daily project hygiene: keep `README.md` / `CHANGELOG.md` / `TODO.md` in sync with reality.
53
51
  > LLM-first, algorithmic fallback. Works standalone, in CI, or via Ansible.
54
52
 
@@ -3,18 +3,16 @@
3
3
 
4
4
  ## AI Cost Tracking
5
5
 
6
- ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.1.1-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
7
- ![AI Cost](https://img.shields.io/badge/AI%20Cost-$0.15-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-1.0h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
6
+ ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.1.2-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
7
+ ![AI Cost](https://img.shields.io/badge/AI%20Cost-$0.15-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-2.0h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
8
8
 
9
9
  - 🤖 **LLM usage:** $0.1500 (1 commits)
10
- - 👤 **Human dev:** ~$100 (1.0h @ $100/h, 30min dedup)
10
+ - 👤 **Human dev:** ~$200 (2.0h @ $100/h, 30min dedup)
11
11
 
12
12
  Generated on 2026-04-25 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
13
13
 
14
14
  ---
15
15
 
16
-
17
-
18
16
  > Daily project hygiene: keep `README.md` / `CHANGELOG.md` / `TODO.md` in sync with reality.
19
17
  > LLM-first, algorithmic fallback. Works standalone, in CI, or via Ansible.
20
18
 
taskill-0.1.2/SUMD.md ADDED
@@ -0,0 +1,489 @@
1
+ # taskill
2
+
3
+ Daily project hygiene: keep README / CHANGELOG / TODO in sync with reality. LLM-first, algorithmic fallback.
4
+
5
+ ## Contents
6
+
7
+ - [Metadata](#metadata)
8
+ - [Architecture](#architecture)
9
+ - [Interfaces](#interfaces)
10
+ - [Configuration](#configuration)
11
+ - [Dependencies](#dependencies)
12
+ - [Deployment](#deployment)
13
+ - [Environment Variables (`.env.example`)](#environment-variables-envexample)
14
+ - [Release Management (`goal.yaml`)](#release-management-goalyaml)
15
+ - [Code Analysis](#code-analysis)
16
+ - [Call Graph](#call-graph)
17
+ - [Test Contracts](#test-contracts)
18
+ - [Intent](#intent)
19
+
20
+ ## Metadata
21
+
22
+ - **name**: `taskill`
23
+ - **version**: `0.1.1`
24
+ - **python_requires**: `>=3.10`
25
+ - **license**: Apache-2.0
26
+ - **ai_model**: `openrouter/qwen/qwen3-coder-next`
27
+ - **ecosystem**: SUMD + DOQL + testql + taskfile
28
+ - **generated_from**: pyproject.toml, testql(1), app.doql.less, goal.yaml, .env.example, project/(2 analysis files)
29
+
30
+ ## Architecture
31
+
32
+ ```
33
+ SUMD (description) → DOQL/source (code) → taskfile (automation) → testql (verification)
34
+ ```
35
+
36
+ ### DOQL Application Declaration (`app.doql.less`)
37
+
38
+ ```less markpact:doql path=app.doql.less
39
+ // LESS format — define @variables here as needed
40
+
41
+ app {
42
+ name: taskill;
43
+ version: 0.1.1;
44
+ }
45
+
46
+ dependencies {
47
+ runtime: "pyyaml>=6.0, python-dotenv>=1.0, httpx>=0.27, click>=8.1, rich>=13.7, goal>=2.1.0, costs>=0.1.20, pfix>=0.1.60";
48
+ dev: "pytest>=7.0, pytest-asyncio>=0.21, ruff>=0.1, mypy>=1.5, goal>=2.1.0, costs>=0.1.20, pfix>=0.1.60";
49
+ }
50
+
51
+ interface[type="cli"] {
52
+ framework: click;
53
+ }
54
+ interface[type="cli"] page[name="taskill"] {
55
+
56
+ }
57
+
58
+ deploy {
59
+ target: pip;
60
+ }
61
+
62
+ environment[name="local"] {
63
+ runtime: python;
64
+ env_file: .env;
65
+ python_version: >=3.10;
66
+ }
67
+ ```
68
+
69
+ ## Interfaces
70
+
71
+ ### CLI Entry Points
72
+
73
+ - `taskill`
74
+
75
+ ### testql Scenarios
76
+
77
+ #### `testql-scenarios/generated-cli-tests.testql.toon.yaml`
78
+
79
+ ```toon markpact:testql path=testql-scenarios/generated-cli-tests.testql.toon.yaml
80
+ # SCENARIO: CLI Command Tests
81
+ # TYPE: cli
82
+ # GENERATED: true
83
+
84
+ CONFIG[2]{key, value}:
85
+ cli_command, python -mtaskill
86
+ timeout_ms, 10000
87
+
88
+ LOG[3]{message}:
89
+ "Test CLI help command"
90
+ "Test CLI version command"
91
+ "Test CLI main workflow"
92
+ ```
93
+
94
+ ## Configuration
95
+
96
+ ```yaml
97
+ project:
98
+ name: taskill
99
+ version: 0.1.1
100
+ env: local
101
+ ```
102
+
103
+ ## Dependencies
104
+
105
+ ### Runtime
106
+
107
+ ```text markpact:deps python
108
+ pyyaml>=6.0
109
+ python-dotenv>=1.0
110
+ httpx>=0.27
111
+ click>=8.1
112
+ rich>=13.7
113
+ goal>=2.1.0
114
+ costs>=0.1.20
115
+ pfix>=0.1.60
116
+ ```
117
+
118
+ ### Development
119
+
120
+ ```text markpact:deps python scope=dev
121
+ pytest>=7.0
122
+ pytest-asyncio>=0.21
123
+ ruff>=0.1
124
+ mypy>=1.5
125
+ goal>=2.1.0
126
+ costs>=0.1.20
127
+ pfix>=0.1.60
128
+ ```
129
+
130
+ ## Deployment
131
+
132
+ ```bash markpact:run
133
+ pip install taskill
134
+
135
+ # development install
136
+ pip install -e .[dev]
137
+ ```
138
+
139
+ ## Environment Variables (`.env.example`)
140
+
141
+ | Variable | Default | Description |
142
+ |----------|---------|-------------|
143
+ | `OPENROUTER_API_KEY` | `*(not set)*` | |
144
+ | `LLM_MODEL` | `openrouter/qwen/qwen3-coder-next` | (taskill auto-strips the openrouter/ prefix for the OpenRouter REST API) |
145
+
146
+ ## Release Management (`goal.yaml`)
147
+
148
+ - **versioning**: `semver`
149
+ - **commits**: `conventional` scope=`taskill`
150
+ - **changelog**: `keep-a-changelog`
151
+ - **build strategies**: `python`, `nodejs`, `rust`
152
+ - **version files**: `pyproject.toml:version`, `src/taskill/__init__.py:__version__`
153
+
154
+ ## Code Analysis
155
+
156
+ ### `project/map.toon.yaml`
157
+
158
+ ```toon markpact:analysis path=project/map.toon.yaml
159
+ # taskill | 26f 2554L | python:23,shell:2,less:1 | 2026-04-25
160
+ # stats: 76 func | 21 cls | 26 mod | CC̄=3.7 | critical:3 | cycles:0
161
+ # alerts[5]: CC evaluate=21; CC run=16; CC status=11; CC build_user_prompt=9; CC load_config=8
162
+ # hotspots[5]: run fan=16; status fan=12; load_config fan=12; collect_snapshot fan=10; evaluate fan=10
163
+ # evolution: baseline
164
+ # Keys: M=modules, D=details, i=imports, e=exports, c=classes, f=functions, m=methods
165
+ M[26]:
166
+ app.doql.less,29
167
+ project.sh,47
168
+ src/taskill/__init__.py,21
169
+ src/taskill/cli.py,254
170
+ src/taskill/config.py,171
171
+ src/taskill/core.py,212
172
+ src/taskill/git_state.py,148
173
+ src/taskill/providers/__init__.py,76
174
+ src/taskill/providers/algorithmic.py,156
175
+ src/taskill/providers/base.py,106
176
+ src/taskill/providers/openrouter.py,115
177
+ src/taskill/providers/windsurf_mcp.py,136
178
+ src/taskill/state.py,43
179
+ src/taskill/triggers.py,95
180
+ src/taskill/updaters/__init__.py,60
181
+ src/taskill/updaters/base.py,45
182
+ src/taskill/updaters/changelog.py,120
183
+ src/taskill/updaters/readme.py,100
184
+ src/taskill/updaters/todo.py,114
185
+ tests/__init__.py,1
186
+ tests/test_algorithmic.py,94
187
+ tests/test_config.py,61
188
+ tests/test_providers.py,77
189
+ tests/test_triggers.py,119
190
+ tests/test_updaters.py,152
191
+ tree.sh,2
192
+ D:
193
+ src/taskill/__init__.py:
194
+ src/taskill/cli.py:
195
+ e: _setup_logging,main,run,status,init,release,clean_todo
196
+ _setup_logging(verbose)
197
+ main(ctx;verbose;config)
198
+ run(ctx;force;dry_run;as_json)
199
+ status(ctx;as_json)
200
+ init(force)
201
+ release(version;changelog)
202
+ clean_todo(todo)
203
+ src/taskill/config.py:
204
+ e: load_config,Triggers,ProviderConfig,IntegrationConfig,TaskillConfig
205
+ Triggers: # Conditions that must be met to run an update.
206
+ ProviderConfig: # Single provider configuration.
207
+ IntegrationConfig: # Optional CI / VCS / orchestrator integration.
208
+ TaskillConfig: env_model(0),env_api_key(0)
209
+ load_config(path;project_root)
210
+ src/taskill/core.py:
211
+ e: TaskillResult,Taskill
212
+ TaskillResult: as_dict(0)
213
+ Taskill: __init__(2),run(1),status(0),_snapshot(0),_build_context(1),_maybe_pyqual_report(0),_apply(2),_update_state(1)
214
+ src/taskill/git_state.py:
215
+ e: _run,head_sha,commits_since,changed_files_since,read_coverage,read_failed_tests,file_hash,collect_snapshot,Commit,ProjectSnapshot
216
+ Commit: conventional_type(0),is_breaking(0)
217
+ ProjectSnapshot:
218
+ _run(cmd;cwd)
219
+ head_sha(project_root)
220
+ commits_since(project_root;since_sha)
221
+ changed_files_since(project_root;since_sha)
222
+ read_coverage(project_root)
223
+ read_failed_tests(project_root)
224
+ file_hash(path)
225
+ collect_snapshot(project_root;files;last_commit_sha)
226
+ src/taskill/providers/__init__.py:
227
+ e: discover_providers,build_chain
228
+ discover_providers()
229
+ build_chain(provider_configs)
230
+ src/taskill/providers/algorithmic.py:
231
+ e: AlgorithmicProvider
232
+ AlgorithmicProvider: is_available(0),generate(1),_format_commit(1),_find_completed_todos(2),_extract_new_todos(1)
233
+ src/taskill/providers/base.py:
234
+ e: build_user_prompt,ProviderError,GeneratedDocs,Provider
235
+ ProviderError: # Provider failed — chain falls through to next provider.
236
+ GeneratedDocs: __post_init__(0) # What every provider returns.
237
+ Provider: __init__(1),is_available(0),generate(1) # Abstract provider — produces docs from a project snapshot.
238
+ build_user_prompt(context)
239
+ src/taskill/providers/openrouter.py:
240
+ e: _normalize_model,OpenRouterProvider
241
+ OpenRouterProvider: is_available(0),generate(1),_parse_json_loosely(1)
242
+ _normalize_model(model)
243
+ src/taskill/providers/windsurf_mcp.py:
244
+ e: _mcp_lib_present,_candidate_endpoints,WindsurfMcpProvider
245
+ WindsurfMcpProvider: is_available(0),generate(1)
246
+ _mcp_lib_present()
247
+ _candidate_endpoints(options)
248
+ src/taskill/state.py:
249
+ e: load_state,save_state,TaskillState
250
+ TaskillState: last_run_dt(0),stamp(0)
251
+ load_state(path)
252
+ save_state(path;state)
253
+ src/taskill/triggers.py:
254
+ e: evaluate,TriggerEvaluation
255
+ TriggerEvaluation: summary(0)
256
+ evaluate(triggers;state;snapshot;project_root)
257
+ src/taskill/updaters/__init__.py:
258
+ e: discover_updaters
259
+ discover_updaters()
260
+ src/taskill/updaters/base.py:
261
+ e: UpdateResult,DocumentUpdater
262
+ UpdateResult: # What every updater returns.
263
+ DocumentUpdater: __init__(1),apply(3) # Abstract updater — applies changes to a document file.
264
+ src/taskill/updaters/changelog.py:
265
+ e: update_changelog,release_unreleased,ChangelogUpdater
266
+ ChangelogUpdater: apply(3),_update_changelog(2) # Updater for CHANGELOG.md files.
267
+ update_changelog(path;entries)
268
+ release_unreleased(path;version;today)
269
+ src/taskill/updaters/readme.py:
270
+ e: render_status_block,update_readme,ReadmeUpdater
271
+ ReadmeUpdater: apply(3),_update_readme(3) # Updater for README.md files.
272
+ render_status_block(snapshot;summary)
273
+ update_readme(path;snapshot;summary)
274
+ src/taskill/updaters/todo.py:
275
+ e: update_todo,empty_todo,TodoUpdater
276
+ TodoUpdater: apply(3),_update_todo(3) # Updater for TODO.md files.
277
+ update_todo(path;completed_lines;new_items)
278
+ empty_todo(path;header)
279
+ tests/__init__.py:
280
+ tests/test_algorithmic.py:
281
+ e: _commit,_snap,test_groups_commits_by_conventional_type,test_breaking_change_surfaces_first,test_detects_explicit_checkbox_completion,test_detects_completion_via_token_overlap,test_extracts_new_todos_from_commit_bodies,test_empty_input_is_safe,test_always_available
282
+ _commit(subject;body)
283
+ _snap(commits)
284
+ test_groups_commits_by_conventional_type()
285
+ test_breaking_change_surfaces_first()
286
+ test_detects_explicit_checkbox_completion()
287
+ test_detects_completion_via_token_overlap()
288
+ test_extracts_new_todos_from_commit_bodies()
289
+ test_empty_input_is_safe()
290
+ test_always_available()
291
+ tests/test_config.py:
292
+ e: test_missing_yaml_returns_defaults,test_yaml_overrides_defaults,test_dotenv_loaded_from_project_root,test_process_env_overrides_dotenv,test_files_config_merges_with_defaults
293
+ test_missing_yaml_returns_defaults(tmp_path)
294
+ test_yaml_overrides_defaults(tmp_path)
295
+ test_dotenv_loaded_from_project_root(tmp_path;monkeypatch)
296
+ test_process_env_overrides_dotenv(tmp_path;monkeypatch)
297
+ test_files_config_merges_with_defaults(tmp_path)
298
+ tests/test_providers.py:
299
+ e: test_discover_providers_returns_builtins,test_build_chain_with_enabled_providers,test_build_chain_with_unknown_provider,test_build_chain_preserves_order,test_build_chain_empty_config,test_build_chain_all_disabled
300
+ test_discover_providers_returns_builtins()
301
+ test_build_chain_with_enabled_providers()
302
+ test_build_chain_with_unknown_provider()
303
+ test_build_chain_preserves_order()
304
+ test_build_chain_empty_config()
305
+ test_build_chain_all_disabled()
306
+ tests/test_triggers.py:
307
+ e: _snap,_commit,test_first_run_always_triggers,test_recent_run_skips_when_no_commits,test_commits_above_threshold_triggers,test_coverage_delta_triggers,test_coverage_within_threshold_does_not_trigger,test_sumd_change_triggers,test_require_all_with_partial_match_does_not_trigger,test_watched_file_mtime_triggers
308
+ _snap()
309
+ _commit(subject)
310
+ test_first_run_always_triggers(tmp_path)
311
+ test_recent_run_skips_when_no_commits(tmp_path)
312
+ test_commits_above_threshold_triggers(tmp_path)
313
+ test_coverage_delta_triggers(tmp_path)
314
+ test_coverage_within_threshold_does_not_trigger(tmp_path)
315
+ test_sumd_change_triggers(tmp_path)
316
+ test_require_all_with_partial_match_does_not_trigger(tmp_path)
317
+ test_watched_file_mtime_triggers(tmp_path)
318
+ tests/test_updaters.py:
319
+ e: test_changelog_creates_file_with_entries,test_changelog_appends_to_unreleased,test_changelog_dedupes_existing_entries,test_changelog_empty_entries_no_op,test_release_promotes_unreleased,test_todo_archives_completed,test_todo_appends_new_under_discovered,test_todo_dedupes_new_items,test_todo_no_change_no_write,test_empty_todo_resets,_snap,test_readme_inserts_status_when_no_markers,test_readme_replaces_only_marker_block,test_readme_creates_file_when_missing
320
+ test_changelog_creates_file_with_entries(tmp_path)
321
+ test_changelog_appends_to_unreleased(tmp_path)
322
+ test_changelog_dedupes_existing_entries(tmp_path)
323
+ test_changelog_empty_entries_no_op(tmp_path)
324
+ test_release_promotes_unreleased(tmp_path)
325
+ test_todo_archives_completed(tmp_path)
326
+ test_todo_appends_new_under_discovered(tmp_path)
327
+ test_todo_dedupes_new_items(tmp_path)
328
+ test_todo_no_change_no_write(tmp_path)
329
+ test_empty_todo_resets(tmp_path)
330
+ _snap()
331
+ test_readme_inserts_status_when_no_markers(tmp_path)
332
+ test_readme_replaces_only_marker_block(tmp_path)
333
+ test_readme_creates_file_when_missing(tmp_path)
334
+ ```
335
+
336
+ ## Call Graph
337
+
338
+ *34 nodes · 28 edges · 12 modules · CC̄=4.3*
339
+
340
+ ### Hubs (by degree)
341
+
342
+ | Function | CC | in | out | total |
343
+ |----------|----|----|-----|-------|
344
+ | `load_config` *(in src.taskill.config)* | 8 | 3 | 35 | **38** |
345
+ | `run` *(in src.taskill.cli)* | 16 ⚠ | 0 | 32 | **32** |
346
+ | `generate` *(in src.taskill.providers.windsurf_mcp.WindsurfMcpProvider)* | 7 | 0 | 32 | **32** |
347
+ | `generate` *(in src.taskill.providers.openrouter.OpenRouterProvider)* | 6 | 0 | 27 | **27** |
348
+ | `evaluate` *(in src.taskill.triggers)* | 21 ⚠ | 2 | 23 | **25** |
349
+ | `status` *(in src.taskill.cli)* | 11 ⚠ | 0 | 25 | **25** |
350
+ | `run` *(in src.taskill.core.Taskill)* | 11 ⚠ | 0 | 20 | **20** |
351
+ | `collect_snapshot` *(in src.taskill.git_state)* | 3 | 1 | 13 | **14** |
352
+
353
+ ```toon markpact:analysis path=project/calls.toon.yaml
354
+ # code2llm call graph | /home/tom/github/semcod/taskill
355
+ # nodes: 34 | edges: 28 | modules: 12
356
+ # CC̄=4.3
357
+
358
+ HUBS[20]:
359
+ src.taskill.config.load_config
360
+ CC=8 in:3 out:35 total:38
361
+ src.taskill.cli.run
362
+ CC=16 in:0 out:32 total:32
363
+ src.taskill.providers.windsurf_mcp.WindsurfMcpProvider.generate
364
+ CC=7 in:0 out:32 total:32
365
+ src.taskill.providers.openrouter.OpenRouterProvider.generate
366
+ CC=6 in:0 out:27 total:27
367
+ src.taskill.triggers.evaluate
368
+ CC=21 in:2 out:23 total:25
369
+ src.taskill.cli.status
370
+ CC=11 in:0 out:25 total:25
371
+ src.taskill.core.Taskill.run
372
+ CC=11 in:0 out:20 total:20
373
+ src.taskill.git_state.collect_snapshot
374
+ CC=3 in:1 out:13 total:14
375
+ src.taskill.updaters.readme.update_readme
376
+ CC=6 in:1 out:11 total:12
377
+ src.taskill.git_state.read_coverage
378
+ CC=7 in:1 out:11 total:12
379
+ src.taskill.core.Taskill._apply
380
+ CC=4 in:0 out:12 total:12
381
+ src.taskill.git_state.read_failed_tests
382
+ CC=5 in:1 out:8 total:9
383
+ src.taskill.providers.windsurf_mcp._candidate_endpoints
384
+ CC=5 in:2 out:7 total:9
385
+ src.taskill.git_state.commits_since
386
+ CC=7 in:1 out:8 total:9
387
+ src.taskill.providers.discover_providers
388
+ CC=6 in:1 out:7 total:8
389
+ src.taskill.cli.release
390
+ CC=2 in:0 out:8 total:8
391
+ src.taskill.state.load_state
392
+ CC=3 in:1 out:6 total:7
393
+ src.taskill.updaters.changelog.release_unreleased
394
+ CC=4 in:1 out:6 total:7
395
+ src.taskill.updaters.readme.render_status_block
396
+ CC=6 in:1 out:5 total:6
397
+ src.taskill.git_state._run
398
+ CC=2 in:4 out:2 total:6
399
+
400
+ MODULES:
401
+ src.taskill.cli [6 funcs]
402
+ _setup_logging CC=2 out:1
403
+ clean_todo CC=1 out:6
404
+ main CC=1 out:6
405
+ release CC=2 out:8
406
+ run CC=16 out:32
407
+ status CC=11 out:25
408
+ src.taskill.config [1 funcs]
409
+ load_config CC=8 out:35
410
+ src.taskill.core [5 funcs]
411
+ __init__ CC=2 out:2
412
+ _apply CC=4 out:12
413
+ _snapshot CC=1 out:1
414
+ run CC=11 out:20
415
+ status CC=1 out:3
416
+ src.taskill.git_state [8 funcs]
417
+ _run CC=2 out:2
418
+ changed_files_since CC=4 out:2
419
+ collect_snapshot CC=3 out:13
420
+ commits_since CC=7 out:8
421
+ file_hash CC=2 out:4
422
+ head_sha CC=2 out:1
423
+ read_coverage CC=7 out:11
424
+ read_failed_tests CC=5 out:8
425
+ src.taskill.providers [2 funcs]
426
+ build_chain CC=4 out:4
427
+ discover_providers CC=6 out:7
428
+ src.taskill.providers.openrouter [2 funcs]
429
+ generate CC=6 out:27
430
+ _normalize_model CC=2 out:2
431
+ src.taskill.providers.windsurf_mcp [4 funcs]
432
+ generate CC=7 out:32
433
+ is_available CC=2 out:3
434
+ _candidate_endpoints CC=5 out:7
435
+ _mcp_lib_present CC=2 out:0
436
+ src.taskill.state [1 funcs]
437
+ load_state CC=3 out:6
438
+ src.taskill.triggers [1 funcs]
439
+ evaluate CC=21 out:23
440
+ src.taskill.updaters.changelog [1 funcs]
441
+ release_unreleased CC=4 out:6
442
+ src.taskill.updaters.readme [2 funcs]
443
+ render_status_block CC=6 out:5
444
+ update_readme CC=6 out:11
445
+ src.taskill.updaters.todo [1 funcs]
446
+ empty_todo CC=1 out:1
447
+
448
+ EDGES:
449
+ src.taskill.providers.build_chain → src.taskill.providers.discover_providers
450
+ src.taskill.providers.windsurf_mcp.WindsurfMcpProvider.is_available → src.taskill.providers.windsurf_mcp._mcp_lib_present
451
+ src.taskill.providers.windsurf_mcp.WindsurfMcpProvider.is_available → src.taskill.providers.windsurf_mcp._candidate_endpoints
452
+ src.taskill.providers.windsurf_mcp.WindsurfMcpProvider.generate → src.taskill.providers.windsurf_mcp._candidate_endpoints
453
+ src.taskill.providers.windsurf_mcp.WindsurfMcpProvider.generate → src.taskill.providers.windsurf_mcp._mcp_lib_present
454
+ src.taskill.providers.openrouter.OpenRouterProvider.generate → src.taskill.providers.openrouter._normalize_model
455
+ src.taskill.git_state.head_sha → src.taskill.git_state._run
456
+ src.taskill.git_state.commits_since → src.taskill.git_state._run
457
+ src.taskill.git_state.changed_files_since → src.taskill.git_state._run
458
+ src.taskill.git_state.collect_snapshot → src.taskill.git_state.head_sha
459
+ src.taskill.git_state.collect_snapshot → src.taskill.git_state.commits_since
460
+ src.taskill.git_state.collect_snapshot → src.taskill.git_state.changed_files_since
461
+ src.taskill.git_state.collect_snapshot → src.taskill.git_state.read_coverage
462
+ src.taskill.git_state.collect_snapshot → src.taskill.git_state.read_failed_tests
463
+ src.taskill.git_state.collect_snapshot → src.taskill.git_state.file_hash
464
+ src.taskill.updaters.readme.update_readme → src.taskill.updaters.readme.render_status_block
465
+ src.taskill.core.Taskill.__init__ → src.taskill.state.load_state
466
+ src.taskill.core.Taskill.__init__ → src.taskill.config.load_config
467
+ src.taskill.core.Taskill.run → src.taskill.triggers.evaluate
468
+ src.taskill.core.Taskill.run → src.taskill.providers.build_chain
469
+ src.taskill.core.Taskill.status → src.taskill.triggers.evaluate
470
+ src.taskill.core.Taskill._snapshot → src.taskill.git_state.collect_snapshot
471
+ src.taskill.core.Taskill._apply → src.taskill.updaters.readme.update_readme
472
+ src.taskill.cli.main → src.taskill.cli._setup_logging
473
+ src.taskill.cli.run → src.taskill.config.load_config
474
+ src.taskill.cli.status → src.taskill.config.load_config
475
+ src.taskill.cli.release → src.taskill.updaters.changelog.release_unreleased
476
+ src.taskill.cli.clean_todo → src.taskill.updaters.todo.empty_todo
477
+ ```
478
+
479
+ ## Test Contracts
480
+
481
+ *Scenarios as contract signatures — what the system guarantees.*
482
+
483
+ ### Cli (1)
484
+
485
+ **`CLI Command Tests`**
486
+
487
+ ## Intent
488
+
489
+ Daily project hygiene: keep README / CHANGELOG / TODO in sync with reality. LLM-first, algorithmic fallback.