corvee 0.1.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 (174) hide show
  1. corvee-0.1.0/.claude/CLAUDE.md +1 -0
  2. corvee-0.1.0/.github/dependabot.yml +10 -0
  3. corvee-0.1.0/.github/workflows/cicd.yaml +190 -0
  4. corvee-0.1.0/.github/workflows/dependabot_auto_merge.yaml +32 -0
  5. corvee-0.1.0/.gitignore +43 -0
  6. corvee-0.1.0/.pre-commit-config.yaml +61 -0
  7. corvee-0.1.0/AGENTS.md +146 -0
  8. corvee-0.1.0/CONTRIBUTING.md +33 -0
  9. corvee-0.1.0/LICENSE +201 -0
  10. corvee-0.1.0/PKG-INFO +107 -0
  11. corvee-0.1.0/README.md +93 -0
  12. corvee-0.1.0/docs/commands.md +44 -0
  13. corvee-0.1.0/docs/concurrency.md +57 -0
  14. corvee-0.1.0/docs/index.md +76 -0
  15. corvee-0.1.0/docs/mcp.md +297 -0
  16. corvee-0.1.0/docs/quickstart.md +195 -0
  17. corvee-0.1.0/docs/spec.md +2506 -0
  18. corvee-0.1.0/mkdocs.yml +44 -0
  19. corvee-0.1.0/pyproject.toml +163 -0
  20. corvee-0.1.0/src/corvee/__init__.py +11 -0
  21. corvee-0.1.0/src/corvee/__main__.py +10 -0
  22. corvee-0.1.0/src/corvee/actor.py +40 -0
  23. corvee-0.1.0/src/corvee/cli/__init__.py +9 -0
  24. corvee-0.1.0/src/corvee/cli/commands/__init__.py +5 -0
  25. corvee-0.1.0/src/corvee/cli/commands/brief.py +186 -0
  26. corvee-0.1.0/src/corvee/cli/commands/completion.py +47 -0
  27. corvee-0.1.0/src/corvee/cli/commands/doctor.py +141 -0
  28. corvee-0.1.0/src/corvee/cli/commands/explain.py +122 -0
  29. corvee-0.1.0/src/corvee/cli/commands/export.py +42 -0
  30. corvee-0.1.0/src/corvee/cli/commands/fact/__init__.py +45 -0
  31. corvee-0.1.0/src/corvee/cli/commands/fact/add.py +59 -0
  32. corvee-0.1.0/src/corvee/cli/commands/fact/delete.py +35 -0
  33. corvee-0.1.0/src/corvee/cli/commands/fact/list_.py +101 -0
  34. corvee-0.1.0/src/corvee/cli/commands/fact/retract.py +39 -0
  35. corvee-0.1.0/src/corvee/cli/commands/fact/revise.py +39 -0
  36. corvee-0.1.0/src/corvee/cli/commands/fact/search.py +77 -0
  37. corvee-0.1.0/src/corvee/cli/commands/fact/show.py +72 -0
  38. corvee-0.1.0/src/corvee/cli/commands/fact/unverify.py +39 -0
  39. corvee-0.1.0/src/corvee/cli/commands/fact/verify.py +41 -0
  40. corvee-0.1.0/src/corvee/cli/commands/import_.py +47 -0
  41. corvee-0.1.0/src/corvee/cli/commands/init.py +82 -0
  42. corvee-0.1.0/src/corvee/cli/commands/mcp/__init__.py +22 -0
  43. corvee-0.1.0/src/corvee/cli/commands/mcp/serve.py +108 -0
  44. corvee-0.1.0/src/corvee/cli/commands/task/__init__.py +57 -0
  45. corvee-0.1.0/src/corvee/cli/commands/task/add.py +226 -0
  46. corvee-0.1.0/src/corvee/cli/commands/task/assign.py +48 -0
  47. corvee-0.1.0/src/corvee/cli/commands/task/claim.py +45 -0
  48. corvee-0.1.0/src/corvee/cli/commands/task/claims.py +39 -0
  49. corvee-0.1.0/src/corvee/cli/commands/task/comment.py +37 -0
  50. corvee-0.1.0/src/corvee/cli/commands/task/label.py +59 -0
  51. corvee-0.1.0/src/corvee/cli/commands/task/labels.py +32 -0
  52. corvee-0.1.0/src/corvee/cli/commands/task/link.py +53 -0
  53. corvee-0.1.0/src/corvee/cli/commands/task/list_.py +181 -0
  54. corvee-0.1.0/src/corvee/cli/commands/task/mine.py +63 -0
  55. corvee-0.1.0/src/corvee/cli/commands/task/purge.py +39 -0
  56. corvee-0.1.0/src/corvee/cli/commands/task/ready.py +68 -0
  57. corvee-0.1.0/src/corvee/cli/commands/task/search.py +81 -0
  58. corvee-0.1.0/src/corvee/cli/commands/task/show.py +95 -0
  59. corvee-0.1.0/src/corvee/cli/commands/task/start.py +49 -0
  60. corvee-0.1.0/src/corvee/cli/commands/task/tree.py +88 -0
  61. corvee-0.1.0/src/corvee/cli/commands/task/unassign.py +38 -0
  62. corvee-0.1.0/src/corvee/cli/commands/task/unclaim.py +43 -0
  63. corvee-0.1.0/src/corvee/cli/commands/task/unlink.py +47 -0
  64. corvee-0.1.0/src/corvee/cli/commands/task/update.py +77 -0
  65. corvee-0.1.0/src/corvee/cli/completion.py +78 -0
  66. corvee-0.1.0/src/corvee/cli/context.py +105 -0
  67. corvee-0.1.0/src/corvee/cli/main.py +114 -0
  68. corvee-0.1.0/src/corvee/cli/params.py +52 -0
  69. corvee-0.1.0/src/corvee/cli/scope.py +155 -0
  70. corvee-0.1.0/src/corvee/config.py +206 -0
  71. corvee-0.1.0/src/corvee/constants.py +115 -0
  72. corvee-0.1.0/src/corvee/db/__init__.py +5 -0
  73. corvee-0.1.0/src/corvee/db/connection.py +103 -0
  74. corvee-0.1.0/src/corvee/db/events.py +143 -0
  75. corvee-0.1.0/src/corvee/db/export_import.py +89 -0
  76. corvee-0.1.0/src/corvee/db/facts.py +310 -0
  77. corvee-0.1.0/src/corvee/db/labels.py +93 -0
  78. corvee-0.1.0/src/corvee/db/like.py +12 -0
  79. corvee-0.1.0/src/corvee/db/links.py +182 -0
  80. corvee-0.1.0/src/corvee/db/schema.py +132 -0
  81. corvee-0.1.0/src/corvee/db/stats.py +192 -0
  82. corvee-0.1.0/src/corvee/db/tasks.py +762 -0
  83. corvee-0.1.0/src/corvee/errors.py +58 -0
  84. corvee-0.1.0/src/corvee/guards/__init__.py +5 -0
  85. corvee-0.1.0/src/corvee/guards/ancestry.py +38 -0
  86. corvee-0.1.0/src/corvee/guards/fields.py +31 -0
  87. corvee-0.1.0/src/corvee/guards/labels.py +23 -0
  88. corvee-0.1.0/src/corvee/guards/parent_child.py +31 -0
  89. corvee-0.1.0/src/corvee/guards/scope.py +26 -0
  90. corvee-0.1.0/src/corvee/guards/transitions.py +27 -0
  91. corvee-0.1.0/src/corvee/mcp/__init__.py +5 -0
  92. corvee-0.1.0/src/corvee/mcp/dispatch.py +117 -0
  93. corvee-0.1.0/src/corvee/mcp/scope.py +81 -0
  94. corvee-0.1.0/src/corvee/mcp/server.py +160 -0
  95. corvee-0.1.0/src/corvee/mcp/tools_common.py +112 -0
  96. corvee-0.1.0/src/corvee/mcp/tools_fact.py +136 -0
  97. corvee-0.1.0/src/corvee/mcp/tools_read.py +228 -0
  98. corvee-0.1.0/src/corvee/mcp/tools_write.py +323 -0
  99. corvee-0.1.0/src/corvee/mcp/worker.py +50 -0
  100. corvee-0.1.0/src/corvee/models.py +224 -0
  101. corvee-0.1.0/src/corvee/output.py +227 -0
  102. corvee-0.1.0/src/corvee/references.py +81 -0
  103. corvee-0.1.0/src/corvee/timeutil.py +44 -0
  104. corvee-0.1.0/tests/acceptance/conftest.py +38 -0
  105. corvee-0.1.0/tests/acceptance/mcp_helpers.py +39 -0
  106. corvee-0.1.0/tests/acceptance/test_cli_actor_session_flags.py +91 -0
  107. corvee-0.1.0/tests/acceptance/test_cli_add_list_show.py +353 -0
  108. corvee-0.1.0/tests/acceptance/test_cli_brief.py +145 -0
  109. corvee-0.1.0/tests/acceptance/test_cli_claim_update.py +135 -0
  110. corvee-0.1.0/tests/acceptance/test_cli_claims.py +43 -0
  111. corvee-0.1.0/tests/acceptance/test_cli_completion.py +98 -0
  112. corvee-0.1.0/tests/acceptance/test_cli_completion_command.py +30 -0
  113. corvee-0.1.0/tests/acceptance/test_cli_context_overrides.py +103 -0
  114. corvee-0.1.0/tests/acceptance/test_cli_doctor.py +222 -0
  115. corvee-0.1.0/tests/acceptance/test_cli_duration_validation.py +49 -0
  116. corvee-0.1.0/tests/acceptance/test_cli_error_handling.py +104 -0
  117. corvee-0.1.0/tests/acceptance/test_cli_explain_and_epilogs.py +181 -0
  118. corvee-0.1.0/tests/acceptance/test_cli_export_import.py +132 -0
  119. corvee-0.1.0/tests/acceptance/test_cli_facts.py +389 -0
  120. corvee-0.1.0/tests/acceptance/test_cli_global_scope.py +289 -0
  121. corvee-0.1.0/tests/acceptance/test_cli_init.py +114 -0
  122. corvee-0.1.0/tests/acceptance/test_cli_labels.py +114 -0
  123. corvee-0.1.0/tests/acceptance/test_cli_limit_validation.py +67 -0
  124. corvee-0.1.0/tests/acceptance/test_cli_link.py +99 -0
  125. corvee-0.1.0/tests/acceptance/test_cli_mcp_serve.py +279 -0
  126. corvee-0.1.0/tests/acceptance/test_cli_no_project.py +85 -0
  127. corvee-0.1.0/tests/acceptance/test_cli_pagination.py +112 -0
  128. corvee-0.1.0/tests/acceptance/test_cli_params.py +39 -0
  129. corvee-0.1.0/tests/acceptance/test_cli_ready_search_mine_comment.py +170 -0
  130. corvee-0.1.0/tests/acceptance/test_cli_referenced.py +146 -0
  131. corvee-0.1.0/tests/acceptance/test_cli_scope.py +233 -0
  132. corvee-0.1.0/tests/acceptance/test_cli_task_add_from_file.py +178 -0
  133. corvee-0.1.0/tests/acceptance/test_cli_task_assign.py +123 -0
  134. corvee-0.1.0/tests/acceptance/test_cli_task_purge.py +81 -0
  135. corvee-0.1.0/tests/acceptance/test_cli_task_start.py +98 -0
  136. corvee-0.1.0/tests/acceptance/test_cli_tree.py +104 -0
  137. corvee-0.1.0/tests/acceptance/test_config.py +174 -0
  138. corvee-0.1.0/tests/acceptance/test_db_claims_and_update.py +361 -0
  139. corvee-0.1.0/tests/acceptance/test_db_connection.py +195 -0
  140. corvee-0.1.0/tests/acceptance/test_db_export_import.py +129 -0
  141. corvee-0.1.0/tests/acceptance/test_db_facts.py +347 -0
  142. corvee-0.1.0/tests/acceptance/test_db_labels.py +53 -0
  143. corvee-0.1.0/tests/acceptance/test_db_links.py +147 -0
  144. corvee-0.1.0/tests/acceptance/test_db_ready_search_mine_comment.py +290 -0
  145. corvee-0.1.0/tests/acceptance/test_db_stats.py +295 -0
  146. corvee-0.1.0/tests/acceptance/test_db_tasks.py +364 -0
  147. corvee-0.1.0/tests/acceptance/test_mcp_concurrency.py +73 -0
  148. corvee-0.1.0/tests/acceptance/test_mcp_create_and_find_tools.py +187 -0
  149. corvee-0.1.0/tests/acceptance/test_mcp_docs_tool_inventory.py +76 -0
  150. corvee-0.1.0/tests/acceptance/test_mcp_fact_tools.py +93 -0
  151. corvee-0.1.0/tests/acceptance/test_mcp_read_tools.py +237 -0
  152. corvee-0.1.0/tests/acceptance/test_mcp_scope.py +100 -0
  153. corvee-0.1.0/tests/acceptance/test_mcp_server_config.py +63 -0
  154. corvee-0.1.0/tests/acceptance/test_mcp_server_startup.py +94 -0
  155. corvee-0.1.0/tests/acceptance/test_mcp_stdout_purity.py +34 -0
  156. corvee-0.1.0/tests/acceptance/test_mcp_tool_descriptions.py +87 -0
  157. corvee-0.1.0/tests/acceptance/test_mcp_version_skew.py +60 -0
  158. corvee-0.1.0/tests/acceptance/test_mcp_write_tools.py +243 -0
  159. corvee-0.1.0/tests/conftest.py +94 -0
  160. corvee-0.1.0/tests/e2e/test_concurrency.py +104 -0
  161. corvee-0.1.0/tests/e2e/test_e2e.py +144 -0
  162. corvee-0.1.0/tests/e2e/test_mcp_protocol.py +65 -0
  163. corvee-0.1.0/tests/e2e/test_mcp_serve.py +51 -0
  164. corvee-0.1.0/tests/unit/test_actor.py +54 -0
  165. corvee-0.1.0/tests/unit/test_cicd_workflow.py +68 -0
  166. corvee-0.1.0/tests/unit/test_constants.py +125 -0
  167. corvee-0.1.0/tests/unit/test_guards.py +190 -0
  168. corvee-0.1.0/tests/unit/test_mcp_dispatch.py +145 -0
  169. corvee-0.1.0/tests/unit/test_mcp_dispatch_version_skew.py +117 -0
  170. corvee-0.1.0/tests/unit/test_mcp_session_id_resolution.py +37 -0
  171. corvee-0.1.0/tests/unit/test_mcp_worker.py +108 -0
  172. corvee-0.1.0/tests/unit/test_models.py +255 -0
  173. corvee-0.1.0/tests/unit/test_output.py +265 -0
  174. corvee-0.1.0/tests/unit/test_timeutil.py +59 -0
@@ -0,0 +1 @@
1
+ @../AGENTS.md
@@ -0,0 +1,10 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ groups:
8
+ github-actions:
9
+ patterns:
10
+ - "*"
@@ -0,0 +1,190 @@
1
+ name: CI/CD
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ release:
7
+ types: [created]
8
+ pull_request:
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ jobs:
14
+ pre-commit:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
18
+ with:
19
+ fetch-depth: 0 # hatch-vcs needs full history (and any tags) to derive a version
20
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
21
+ with:
22
+ python-version: "3.11"
23
+ - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
24
+ - name: Install project (generates src/corvee/_version.py via the hatch-vcs build hook)
25
+ run: uv pip install --system -e .
26
+ - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
27
+
28
+ test:
29
+ runs-on: ubuntu-latest
30
+ strategy:
31
+ fail-fast: false
32
+ matrix:
33
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
34
+ steps:
35
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
36
+ with:
37
+ fetch-depth: 0
38
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
39
+ with:
40
+ python-version: ${{ matrix.python-version }}
41
+ - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
42
+ - name: Install project and test dependencies
43
+ run: uv pip install --system -e '.[mcp]' pytest pytest-xdist
44
+ - name: Run tests
45
+ run: pytest -n auto
46
+
47
+ build:
48
+ runs-on: ubuntu-latest
49
+ needs: [pre-commit, test]
50
+ steps:
51
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
52
+ with:
53
+ fetch-depth: 0
54
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
55
+ with:
56
+ python-version: "3.11"
57
+ - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
58
+ - name: Install hatch
59
+ run: uv tool install hatch
60
+ - name: Build
61
+ run: hatch build
62
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
63
+ with:
64
+ name: dist
65
+ path: dist/
66
+
67
+ docs:
68
+ runs-on: ubuntu-latest
69
+ needs: [pre-commit, test]
70
+ steps:
71
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
72
+ with:
73
+ fetch-depth: 0
74
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
75
+ with:
76
+ python-version: "3.11"
77
+ - uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0
78
+ - name: Install hatch
79
+ run: uv tool install hatch
80
+ - name: Build documentation
81
+ run: hatch run docs-build
82
+ - if: github.ref == 'refs/heads/master'
83
+ uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
84
+ with:
85
+ path: site
86
+
87
+ deploy-docs:
88
+ runs-on: ubuntu-latest
89
+ needs: [docs]
90
+ if: github.ref == 'refs/heads/master'
91
+ permissions:
92
+ contents: read
93
+ pages: write
94
+ id-token: write
95
+ environment:
96
+ name: github-pages
97
+ url: ${{ steps.deployment.outputs.page_url }}
98
+ steps:
99
+ - uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
100
+ - id: deployment
101
+ uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1
102
+
103
+ # Uploads the package to test.pypi.org on every push to master.
104
+ upload-test-pypi:
105
+ if: |
106
+ success()
107
+ && github.ref == 'refs/heads/master'
108
+ && github.actor == 'btschwertfeger'
109
+ && github.event_name == 'push'
110
+ needs: [build]
111
+ name: Upload development version to Test PyPI
112
+ runs-on: ubuntu-latest
113
+ permissions:
114
+ contents: read
115
+ id-token: write # mandatory for OIDC Trusted Publishing
116
+ environment:
117
+ name: testpypi
118
+ url: https://test.pypi.org/p/corvee
119
+ steps:
120
+ - name: Harden Runner
121
+ uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
122
+ with:
123
+ disable-sudo: true
124
+ egress-policy: block
125
+ allowed-endpoints: >
126
+ api.github.com:443
127
+ github.com:443
128
+ test.pypi.org
129
+ uploads.github.com:443
130
+
131
+ - name: Download the distributions
132
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
133
+ with:
134
+ name: dist
135
+ path: dist/
136
+
137
+ - name: Publish package distributions to Test PyPI
138
+ uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
139
+ with:
140
+ repository-url: https://test.pypi.org/legacy/
141
+
142
+ # Uploads the package to PyPI when a release is created.
143
+ upload-pypi:
144
+ if: |
145
+ success()
146
+ && github.actor == 'btschwertfeger'
147
+ && github.event_name == 'release'
148
+ needs: [build]
149
+ name: Upload release to PyPI
150
+ runs-on: ubuntu-latest
151
+ permissions:
152
+ contents: read
153
+ id-token: write # mandatory for OIDC Trusted Publishing
154
+ attestations: write # write build-provenance attestations
155
+ environment:
156
+ name: pypi
157
+ url: https://pypi.org/p/corvee
158
+ steps:
159
+ - name: Harden Runner
160
+ uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
161
+ with:
162
+ disable-sudo: true
163
+ egress-policy: block
164
+ allowed-endpoints: >
165
+ api.github.com:443
166
+ fulcio.sigstore.dev
167
+ github.com:443
168
+ pypi.org
169
+ rekor.sigstore.dev
170
+ timestamp.sigstore.dev
171
+ tuf-repo-cdn.sigstore.dev
172
+ upload.pypi.org
173
+
174
+ - name: Download the distributions
175
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
176
+ with:
177
+ name: dist
178
+ path: dist/
179
+
180
+ # SLSA build provenance for the wheel and sdist, written to GitHub's
181
+ # attestation store and verifiable with `gh attestation verify`.
182
+ - name: Attest build provenance
183
+ uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
184
+ with:
185
+ subject-path: "dist/*"
186
+
187
+ - name: Publish package distributions to PyPI
188
+ uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
189
+ with:
190
+ repository-url: https://upload.pypi.org/legacy/
@@ -0,0 +1,32 @@
1
+ name: Dependabot auto-merge
2
+
3
+ on: pull_request_target
4
+
5
+ permissions:
6
+ pull-requests: write
7
+ contents: write
8
+
9
+ jobs:
10
+ dependabot:
11
+ runs-on: ubuntu-latest
12
+ if: ${{ github.actor == 'dependabot[bot]' }}
13
+ steps:
14
+ - name: Dependabot metadata
15
+ id: dependabot-metadata
16
+ uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0
17
+ with:
18
+ github-token: "${{ secrets.GITHUB_TOKEN }}"
19
+
20
+ - name: Approve the PR
21
+ if: ${{ steps.dependabot-metadata.outputs.update-type != 'version-update:semver-major' }}
22
+ run: gh pr review --approve "$PR_URL"
23
+ env:
24
+ PR_URL: ${{ github.event.pull_request.html_url }}
25
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26
+
27
+ - name: Enable auto-merge for patch/minor updates
28
+ if: ${{ steps.dependabot-metadata.outputs.update-type != 'version-update:semver-major' }}
29
+ run: gh pr merge --auto --squash "$PR_URL"
30
+ env:
31
+ PR_URL: ${{ github.event.pull_request.html_url }}
32
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,43 @@
1
+ # Byte-compiled / optimized files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Distribution / packaging
7
+ .Python
8
+ build/
9
+ dist/
10
+ *.egg-info/
11
+ *.egg
12
+ wheels/
13
+ *.whl
14
+
15
+ # Environments
16
+ .venv/
17
+ venv/
18
+ env/
19
+ .hatch/
20
+
21
+ # Testing / coverage / typing / linting caches
22
+ .cache/
23
+ .coverage
24
+ .coverage.*
25
+ coverage.xml
26
+ htmlcov/
27
+ .ruff_cache/
28
+ .pytest_cache/
29
+ .tox/
30
+ .nox/
31
+ mutants/
32
+
33
+ # Docs
34
+ site/
35
+
36
+ # Editors / OS
37
+ .vscode/
38
+ .idea/
39
+ *.swp
40
+ .DS_Store
41
+
42
+ # corvee project data (never committed)
43
+ .corvee/
@@ -0,0 +1,61 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.16.1
4
+ hooks:
5
+ - id: ruff-check
6
+ args: [--fix, --exit-non-zero-on-fix]
7
+ - repo: https://github.com/psf/black
8
+ rev: 26.3.1
9
+ hooks:
10
+ - id: black
11
+ - repo: local
12
+ hooks:
13
+ - id: ty
14
+ name: ty
15
+ entry: ty check
16
+ language: python
17
+ pass_filenames: false
18
+ additional_dependencies: ["ty==0.0.80", "click>=8.1", "pytest", "mcp>=2.2"]
19
+ args: [src, tests]
20
+ - repo: https://github.com/codespell-project/codespell
21
+ rev: v2.4.2
22
+ hooks:
23
+ - id: codespell
24
+ additional_dependencies: [tomli]
25
+ - repo: https://github.com/gitleaks/gitleaks
26
+ rev: v8.30.1
27
+ hooks:
28
+ - id: gitleaks
29
+ - repo: https://github.com/pre-commit/pre-commit-hooks
30
+ rev: v6.0.0
31
+ hooks:
32
+ - id: check-yaml
33
+ exclude: ^mkdocs\.yml$
34
+ - id: check-yaml
35
+ name: check-yaml (mkdocs.yml, unsafe for the mermaid !!python/name tag)
36
+ files: ^mkdocs\.yml$
37
+ args: [--unsafe]
38
+ - id: check-toml
39
+ - id: check-json
40
+ - id: check-ast
41
+ - id: check-docstring-first
42
+ - id: check-case-conflict
43
+ - id: check-merge-conflict
44
+ - id: check-added-large-files
45
+ args: [--maxkb=500]
46
+ - id: check-executables-have-shebangs
47
+ - id: trailing-whitespace
48
+ - id: fix-byte-order-marker
49
+ - id: mixed-line-ending
50
+ - id: end-of-file-fixer
51
+ - id: detect-private-key
52
+ - repo: https://github.com/pre-commit/pygrep-hooks
53
+ rev: v1.10.0
54
+ hooks:
55
+ - id: python-use-type-annotations
56
+ - id: python-check-blanket-noqa
57
+ - id: python-check-blanket-type-ignore
58
+ - id: python-check-mock-methods
59
+ - id: python-no-eval
60
+ - id: python-no-log-warn
61
+ - id: text-unicode-replacement-char
corvee-0.1.0/AGENTS.md ADDED
@@ -0,0 +1,146 @@
1
+ # AGENTS.md
2
+
3
+ Guidance for coding agents working on the corvee codebase itself, not the
4
+ pointer block `corvee init` prints for other projects to paste into their
5
+ own AGENTS.md.
6
+
7
+ ## Source of truth
8
+
9
+ - `docs/spec.md` is the technical specification: schema, CLI contract, exit
10
+ codes, concurrency model. Implementation must match it. If the two
11
+ disagree, update `docs/spec.md` rather than letting it drift. Any new
12
+ feature bumps the spec's own version and extends `docs/spec.md` first,
13
+ independent of when it gets implemented. The spec documents intended
14
+ design, not just shipped behavior.
15
+ - `pyproject.toml`'s `[tool.hatch.envs.default.scripts]` is the source of
16
+ truth for available dev commands. The list below covers the ones used
17
+ constantly. Run `hatch env show` for the full, current set.
18
+
19
+ ## Stack
20
+
21
+ Python 3.11+, managed with Hatch (`uv` as the installer underneath). `src`
22
+ layout: the package lives at `src/corvee/`, tests at `tests/`. click for the
23
+ CLI, stdlib `sqlite3` for storage, no ORM. Every tool (pytest, ty, ruff,
24
+ black, coverage) is configured in `pyproject.toml`, not in separate config
25
+ files.
26
+
27
+ ```bash
28
+ hatch run test # pytest, parallel via pytest-xdist
29
+ hatch run check # every prek hook + test.
30
+ # Run this before considering a change done
31
+ hatch run lint # ruff check, via prek
32
+ hatch run format # black, via prek
33
+ hatch run typecheck # ty, via prek
34
+ hatch run +py=3.12 test:test # run the suite against one Python version
35
+ # from the test matrix (3.11-3.14)
36
+ ```
37
+
38
+ `lint`/`format`/`typecheck` all delegate to `prek run <hook-id>` rather than
39
+ invoking ruff/black/ty directly, so hatch and CI can never drift apart on
40
+ what each one actually runs. `hatch run check` (or `prek run --all-files`
41
+ directly) is the mandatory quality gate before a change is considered
42
+ finished.
43
+
44
+ ## Principles
45
+
46
+ KISS, YAGNI, DRY. A change should be minimal and focused on what was asked.
47
+ Do not use a bug fix or small feature as an excuse for a wider rework, a new
48
+ abstraction, or unrelated cleanup. Three similar lines beat a premature
49
+ abstraction.
50
+
51
+ ## Architecture
52
+
53
+ Every CLI invocation flows through the same layers, in this order:
54
+
55
+ 1. **`cli/main.py`**: the click group. `CorveeGroup.main()` is overridden so
56
+ every failure, including click's own usage errors, is caught and
57
+ re-emitted through one path: a `{"error": {...}}` JSON object on stderr
58
+ plus the documented exit code (`errors.py`). This is what makes
59
+ `CliRunner`-based tests exercise the exact same error path a real
60
+ subprocess would.
61
+ 2. **`cli/commands/{task,fact}/*.py`**: one thin click command per verb. The
62
+ pattern is always: parse id(s) with `models.parse_task_refs`/
63
+ `parse_fact_refs` (which also determines local vs global scope from the
64
+ `TASK-GLOBAL-<n>`/`FACT-GLOBAL-<n>` prefix), open `corvee_context(...)`,
65
+ call exactly one `db/*.py` function to do the actual mutation/query, then
66
+ `output.emit_tasks`/`emit_facts` to print. Command files contain no SQL
67
+ and no business logic themselves.
68
+ 3. **`cli/context.py`** (`corvee_context`): resolves which SQLite file to
69
+ open (local project via `config.resolve_project()`, or the global
70
+ `~/.corvee/corvee.db` for `scope="global"`), opens it via
71
+ `db/connection.open_connection` (which also bootstraps/migrates the
72
+ schema), and wraps the command body in one transaction: `BEGIN IMMEDIATE`
73
+ for writes, plain `BEGIN` for reads, commit on success, rollback on any
74
+ exception. This is what gives multi-id commands like `task update 4 7 9`
75
+ their all-or-nothing property for free.
76
+ 4. **`db/*.py`**: raw `sqlite3` against the schema in `db/schema.py` (no
77
+ ORM). Each module owns one area: `tasks.py`, `facts.py`, `labels.py`,
78
+ `links.py`, `events.py`, `export_import.py`, `stats.py`. Mutating
79
+ functions here call into `guards/*.py` before writing (transition table,
80
+ parent/child cycle checks, claim conflicts, label patterns) and write the
81
+ corresponding `task_events`/`fact_events` row in the same call, so the
82
+ audit trail is not a separate step a caller can forget.
83
+ 5. **`guards/*.py`**: pure validation functions that raise
84
+ `errors.GuardViolationError`/`ClaimConflictError`/etc. Consult
85
+ `constants.py` for the data-driven rules (e.g. `TRANSITIONS`, a
86
+ `dict[State, frozenset[State]]`) rather than branching in code, so policy
87
+ changes are edits to one table.
88
+ 6. **`output.py`**: JSON array (or single object for `doctor`/`export`) vs.
89
+ fixed-width table rendering, `--fields` projection (`filter_fields`),
90
+ shared by every command group.
91
+
92
+ Cross-cutting modules: `actor.py` resolves `$CORVEE_ACTOR`/
93
+ `$CORVEE_SESSION_ID`. `config.py` walks up from cwd to find
94
+ `.corvee/config.toml` (git-style) and resolves `db_path`. `timeutil.py` is
95
+ the one place that formats the fixed-width UTC-with-milliseconds timestamps
96
+ used everywhere on disk.
97
+
98
+ **Scope.** Every task/fact lives in exactly one of two independent SQLite
99
+ databases: the local project one (`.corvee/corvee.db`, pointed to by
100
+ `.corvee/config.toml`) or one global database shared across the machine
101
+ (`~/.corvee/corvee.db`, created lazily on first `--global` write). Scope is
102
+ fixed at creation and encoded in the id itself (`TASK-14` vs
103
+ `TASK-GLOBAL-14`), never passed as a separate flag on mutating commands. A
104
+ merged read (`--scope all`, the default for listing) opens and closes one
105
+ ordinary connection per database in turn, never a cross-database
106
+ transaction.
107
+
108
+ **Concurrency.** No daemon. Every invocation opens, does its transaction, and
109
+ closes. WAL mode + `busy_timeout=5000` handle contention. Claims are a single
110
+ conditional `UPDATE` checked by rows-affected. Full reasoning in
111
+ `docs/concurrency.md` and spec §3.2/§3.3. Read that before touching
112
+ `cli/context.py` or `db/connection.py`.
113
+
114
+ **Exit codes.** `errors.py` defines one exception subclass per documented
115
+ exit code (0 success, 1 internal, 2 usage, 3 not found, 4 claim conflict, 5
116
+ guard violation, 6 project/config problem). Raise the matching subclass
117
+ rather than a bare exception. `CorveeGroup.main()` is what turns it into the
118
+ JSON-on-stderr shape and the process exit code.
119
+
120
+ ## Working here
121
+
122
+ - TDD: write the failing test before the code that makes it pass.
123
+ - No mocking SQLite. Tests run against a real database in `tmp_path`.
124
+ - Every CLI command needs a `--help` epilog with at least three runnable
125
+ examples (enforced by a test).
126
+ - Full type hints throughout. `ty` has zero tolerance for untyped public
127
+ signatures or unjustified `Any`.
128
+ - Tests are classified by directory, not per-test decorators: `tests/unit`
129
+ (pure functions, no filesystem/db), `tests/acceptance` (through the CLI or
130
+ db layer against a real `tmp_path` SQLite database), `tests/e2e` (a real
131
+ `python -m corvee` subprocess). `conftest.py` applies the
132
+ `unit`/`acceptance`/`e2e` pytest marker automatically from
133
+ `item.path.parts`. Key shared fixtures: `project` (initialized project, cwd
134
+ inside it, `CORVEE_ACTOR` set), `runner` (`CliRunner`), `conn` (direct
135
+ connection to the project db), `add_task`/`add_fact` (create via CLI,
136
+ return the id).
137
+ - Never run `corvee ... --global` directly in a shell against this
138
+ machine's real `~/.corvee/corvee.db` while manually poking at --global
139
+ behavior. Set `CORVEE_GLOBAL_DB=/some/scratch/path` first. The pytest
140
+ suite already isolates `$HOME` for you. This is only for ad hoc shell
141
+ commands outside it.
142
+ - Commit one completed corvee task per commit, not a batch of several
143
+ tasks squashed into one. Finish the task (code, tests, docs, `hatch run
144
+ check` green, `corvee task comment`/`update --state done`), then commit
145
+ before starting the next one, so each commit maps onto one reviewable
146
+ unit of work and one task's audit trail.
@@ -0,0 +1,33 @@
1
+ # Contributing
2
+
3
+ Requires Python 3.11+ and [Hatch](https://hatch.pypa.io/) (`uv` is used
4
+ underneath as the installer).
5
+
6
+ ```bash
7
+ hatch run test # run the test suite (parallel via pytest-xdist)
8
+ hatch run cov # run the test suite with coverage
9
+ hatch run lint # ruff check, via prek
10
+ hatch run format # black, via prek
11
+ hatch run typecheck # ty, via prek
12
+ hatch run check # every prek hook + test
13
+ hatch run mutate # mutation testing against db/ and guards/,
14
+ # opt-in, not part of check/CI
15
+ hatch run +py=3.12 test:test # run the suite against one Python version
16
+ # from the test matrix (3.11-3.14)
17
+ hatch run docs-serve # serve the documentation locally
18
+ hatch build # build sdist + wheel
19
+ ```
20
+
21
+ `hatch run check` (or `prek run --all-files` directly) is the quality gate
22
+ for any change. Run it before considering a change done.
23
+
24
+ See [AGENTS.md](AGENTS.md) for the architecture, testing conventions, and
25
+ the `corvee` task-tracking workflow this project uses on itself.
26
+
27
+ ## Before you open a PR
28
+
29
+ Open an issue first and wait for a maintainer to approve it before starting
30
+ a pull request. This applies to features and non-trivial fixes. A typo or
31
+ other trivial fix can go straight to a PR. Approval keeps effort from being
32
+ spent on work that doesn't fit the project's direction. PRs opened without an
33
+ approved issue may be closed and asked to go through this process first.