-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpyproject.toml
More file actions
169 lines (154 loc) · 6.25 KB
/
Copy pathpyproject.toml
File metadata and controls
169 lines (154 loc) · 6.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
[project]
name = "kstrl"
version = "0.2.0"
description = "A software factory for AI coding agents: measures what the agent built with checks it did not write, feeds the gap back, and stops only when independent checks agree."
readme = "README.md"
requires-python = ">=3.11"
license = "MIT"
keywords = [
"ai-agents",
"coding-agent",
"claude-code",
"codex",
"autonomous-agents",
"llm",
"code-review",
"software-factory",
"devsecops",
]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: POSIX",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Environment :: Console",
"Topic :: Software Development :: Quality Assurance",
"Topic :: Software Development :: Code Generators",
"Topic :: Software Development :: Testing",
]
dependencies = [
"rich>=15.0.0",
"click>=8.4.2",
# TUI rewrite PR D: the dashboard engine. Pinned <9; 8.2.8 verified
# against locked rich 15.x during the Textual 8 migration (the 6.0.0
# Static.renderable -> content rename and 6-8 render changes were
# absorbed there). Bumped from the earlier <6 pin.
"textual>=8.2.8,<9",
]
# R7.6: the claude-sdk agent adapter is opt-in because the SDK carries a
# heavy transitive set (anyio, mcp, starlette, uvicorn, ...) while the
# core harness runs on rich+click. agent_type = "claude-sdk" without the
# extra fails loudly with the install hint.
[project.optional-dependencies]
sdk = [
"claude-agent-sdk>=0.2.128,<0.3",
]
[project.urls]
Homepage = "https://github.com/0xfauzi/kstrl"
Repository = "https://github.com/0xfauzi/kstrl"
Documentation = "https://github.com/0xfauzi/kstrl/wiki"
Architecture = "https://github.com/0xfauzi/kstrl/blob/main/ARCHITECTURE.md"
Changelog = "https://github.com/0xfauzi/kstrl/blob/main/CHANGELOG.md"
Issues = "https://github.com/0xfauzi/kstrl/issues"
[project.scripts]
ks = "kstrl.cli:main"
kstrl = "kstrl.cli:main"
[dependency-groups]
dev = [
"pytest>=9.1.1",
"pytest-asyncio>=1.4.0",
"pytest-cov>=6.0.0",
"ruff>=0.16.1",
"mypy>=2.3.0",
# The sdk extra is part of the dev set so the R7.6 unit tests and
# mypy always exercise the adapter+runner.
"claude-agent-sdk>=0.2.128,<0.3",
"pytest-textual-snapshot>=1.0.0",
]
[build-system]
requires = ["hatchling>=1.31.0"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["kstrl"]
[tool.pytest.ini_options]
testpaths = ["tests"]
asyncio_mode = "auto"
markers = [
"spine: real-git spine tier (R4.2) - unmocked worktree/PR/lock paths; deselect with -m 'not spine' to keep the fast tier fast",
]
# R4.4 coverage measurement. relative_files lets CI combine data files
# recorded in different checkouts (fast tier + spine tier jobs) and lets
# the report resolve paths from the repo root. The ratchet baseline CI
# enforces lives in .github/coverage-baseline.txt - a MEASURED number,
# updated only upward (or deliberately, with justification in the PR).
[tool.coverage.run]
source = ["kstrl"]
relative_files = true
[tool.coverage.report]
precision = 2
[tool.ruff]
line-length = 100
target-version = "py311"
[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B"]
ignore = []
[tool.ruff.lint.per-file-ignores]
# Long lines in these files live inside triple-quoted LLM prompt
# bodies. Reformatting them changes the prompt SHA-256 (H3 protects
# against silent prompt drift) and would force a version bump for
# what is purely cosmetic. The prompt IS the artifact -- keep its
# bytes stable.
"kstrl/decompose.py" = ["E501"]
"kstrl/review.py" = ["E501"]
"kstrl/security.py" = ["E501"]
"kstrl/knowledge.py" = ["E501"]
# init_cmd.py is full of triple-quoted CLAUDE.md / prompt template
# strings used to scaffold user projects. Reflowing markdown inside
# those strings changes the output users see; keep bytes stable.
"kstrl/init_cmd.py" = ["E501"]
# Test files contain long literal expected strings (verification
# output, JSON payloads). Reflowing would obscure the test intent.
"tests/test_verify.py" = ["E501"]
"tests/test_evolution.py" = ["E501"]
"tests/test_harness_integration.py" = ["E501"]
"tests/test_parsers.py" = ["E501"]
[tool.mypy]
python_version = "3.11"
strict = true
# `files` is consulted by `uv run mypy` (no args) and by the kstrl
# factory's new smart-default typecheck command (verify._default_typecheck_command).
# Listing kstrl here keeps CLAUDE.md's stated typecheck contract
# (`uv run mypy kstrl/ --strict`) and `uv run mypy` invoked from the
# factory's verify phase in lockstep -- no command-line override needed.
# kstrl is the only Python package.
files = ["kstrl"]
[tool.vulture]
# vulture exits 2 with no paths, which reads as a broken hook rather than a
# finding, so this section is what makes the pre-commit hook usable at all.
# min_confidence 80 keeps it to findings worth reading; a reviewed whitelist.py
# goes in paths once one exists.
min_confidence = 80
paths = ['kstrl']
# cancel_futures is a false positive, not dead code. _InlineExecutor.shutdown
# duck-types concurrent.futures.Executor.shutdown, whose signature is
# (wait=True, *, cancel_futures=False). factory.py calls
# executor.shutdown(wait=False, cancel_futures=True) on the abort path and on
# the scheduler-backstop path, and both can hold an _InlineExecutor. The body
# has nothing to shut down, so the name is never read - measured: deleting the
# parameter turns those two calls into
# "TypeError: shutdown() got an unexpected keyword argument 'cancel_futures'".
ignore_names = ["cancel_futures"]
[tool.codespell]
# All verified false positives, not typos. critcial is a deliberately invalid
# env value in a test asserting ValueError. Excetra is a project name.
# unparseable and pre-empt are accepted spellings codespell dislikes.
ignore-words-list = "crasher,critcial,excetra,missable,nd,pre-empt,unparseable"
# tests/tool_output/ is captured tool output kept as evidence (#258).
# pytest truncates its short-summary lines to the terminal width, which
# cuts the exception name off mid-word - the very behaviour those
# fixtures exist to pin. Spell-correcting a capture would falsify it.
skip = "uv.lock,*/package-lock.json,.git,tests/tool_output/*"