libspec 1.2.0__tar.gz → 10.2.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.
- libspec-10.2.0/PKG-INFO +186 -0
- libspec-10.2.0/README.md +155 -0
- libspec-10.2.0/libspec/__init__.py +6 -0
- libspec-10.2.0/libspec/agent_config.py +532 -0
- libspec-10.2.0/libspec/cli.py +629 -0
- libspec-10.2.0/libspec/colors.py +116 -0
- libspec-10.2.0/libspec/common.py +80 -0
- {libspec-1.2.0 → libspec-10.2.0}/libspec/err.py +14 -14
- libspec-10.2.0/libspec/lsp_client.py +193 -0
- libspec-10.2.0/libspec/mcp_server.py +543 -0
- libspec-10.2.0/libspec/pylsp_plugin.py +195 -0
- libspec-10.2.0/libspec/repl.py +1611 -0
- libspec-10.2.0/libspec/spec.py +848 -0
- libspec-10.2.0/libspec/spec_diff.py +280 -0
- libspec-10.2.0/libspec/spec_types.py +252 -0
- {libspec-1.2.0 → libspec-10.2.0}/libspec/specweb.py +5 -7
- libspec-10.2.0/libspec/store.py +20 -0
- libspec-10.2.0/libspec/templates/err.py +100 -0
- libspec-10.2.0/libspec/templates/skill.md.j2 +43 -0
- {libspec-1.2.0 → libspec-10.2.0}/libspec/user_story.py +3 -3
- libspec-10.2.0/libspec/util.py +426 -0
- libspec-10.2.0/libspec/watcher.py +126 -0
- libspec-10.2.0/libspec/workflow.py +74 -0
- libspec-10.2.0/libspec-scheduler/src/libspec_scheduler/__init__.py +1 -0
- libspec-10.2.0/libspec-scheduler/src/libspec_scheduler/mcp.py +249 -0
- libspec-10.2.0/libspec-scheduler/src/libspec_scheduler/scheduler.py +267 -0
- libspec-10.2.0/libspec-scheduler/tests/test_mcp_scheduler.py +86 -0
- libspec-10.2.0/libspec-scheduler/tests/test_scheduler.py +196 -0
- libspec-10.2.0/libspec.egg-info/PKG-INFO +186 -0
- libspec-10.2.0/libspec.egg-info/SOURCES.txt +52 -0
- {libspec-1.2.0 → libspec-10.2.0}/libspec.egg-info/entry_points.txt +3 -0
- libspec-10.2.0/libspec.egg-info/requires.txt +10 -0
- libspec-10.2.0/libspec.egg-info/top_level.txt +2 -0
- libspec-10.2.0/pyproject.toml +113 -0
- libspec-10.2.0/tests/test_agent_config.py +59 -0
- libspec-10.2.0/tests/test_agent_workflow.py +88 -0
- libspec-10.2.0/tests/test_cli.py +222 -0
- libspec-10.2.0/tests/test_common_types.py +87 -0
- libspec-10.2.0/tests/test_cwd_validation.py +73 -0
- {libspec-1.2.0 → libspec-10.2.0}/tests/test_idempotency.py +25 -13
- libspec-10.2.0/tests/test_lsp.py +66 -0
- libspec-10.2.0/tests/test_mcp_metadata.py +58 -0
- {libspec-1.2.0 → libspec-10.2.0}/tests/test_missing_requirement_variable.py +10 -4
- libspec-10.2.0/tests/test_mixins.py +67 -0
- libspec-10.2.0/tests/test_projects.py +34 -0
- libspec-10.2.0/tests/test_removed_cli.py +16 -0
- libspec-10.2.0/tests/test_repl.py +245 -0
- libspec-10.2.0/tests/test_spec.py +289 -0
- libspec-10.2.0/tests/test_spec_diff.py +157 -0
- libspec-10.2.0/tests/test_watcher.py +38 -0
- {libspec-1.2.0 → libspec-10.2.0}/tests/test_xml_render.py +118 -36
- libspec-1.2.0/PKG-INFO +0 -111
- libspec-1.2.0/README.md +0 -86
- libspec-1.2.0/libspec/__init__.py +0 -5
- libspec-1.2.0/libspec/cli.py +0 -259
- libspec-1.2.0/libspec/mcp_server.py +0 -82
- libspec-1.2.0/libspec/query_map.py +0 -19
- libspec-1.2.0/libspec/spec.py +0 -591
- libspec-1.2.0/libspec/spec_diff.py +0 -193
- libspec-1.2.0/libspec/util.py +0 -26
- libspec-1.2.0/libspec.egg-info/PKG-INFO +0 -111
- libspec-1.2.0/libspec.egg-info/SOURCES.txt +0 -24
- libspec-1.2.0/libspec.egg-info/requires.txt +0 -4
- libspec-1.2.0/libspec.egg-info/top_level.txt +0 -1
- libspec-1.2.0/pyproject.toml +0 -40
- libspec-1.2.0/tests/test_mixins.py +0 -49
- libspec-1.2.0/tests/test_spec.py +0 -109
- {libspec-1.2.0 → libspec-10.2.0}/LICENSE +0 -0
- {libspec-1.2.0 → libspec-10.2.0}/libspec.egg-info/dependency_links.txt +0 -0
- {libspec-1.2.0 → libspec-10.2.0}/setup.cfg +0 -0
libspec-10.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: libspec
|
|
3
|
+
Version: 10.2.0
|
|
4
|
+
Summary: Spec-driven development library for LLM-assisted coding
|
|
5
|
+
Author-email: "Derek A. Rhodes" <physci@gmail.com>
|
|
6
|
+
License-Expression: GPL-3.0-or-later
|
|
7
|
+
Project-URL: Homepage, https://github.com/drhodes/libspec
|
|
8
|
+
Project-URL: Repository, https://github.com/drhodes/libspec
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/drhodes/libspec/issues
|
|
10
|
+
Keywords: specification,llm,codegen,spec-driven,development
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Requires-Python: >=3.12
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: click>=8.1.8
|
|
21
|
+
Requires-Dist: jinja2>=3.1.6
|
|
22
|
+
Requires-Dist: mcp>=1.27.0
|
|
23
|
+
Requires-Dist: python-lsp-server>=1.12.2
|
|
24
|
+
Requires-Dist: toml>=0.10.2
|
|
25
|
+
Requires-Dist: skillkit>=0.4.0
|
|
26
|
+
Requires-Dist: prompt-toolkit>=3.0.52
|
|
27
|
+
Requires-Dist: colored>=2.3.2
|
|
28
|
+
Requires-Dist: aiofiles>=25.1.0
|
|
29
|
+
Requires-Dist: pyyaml>=6.0.2
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# libspec
|
|
33
|
+
|
|
34
|
+
[](https://github.com/drhodes/libspec/actions/workflows/ci.yml)
|
|
35
|
+
[](https://drhodes.github.io/libspec/)
|
|
36
|
+
[](https://pypi.org/project/libspec/)
|
|
37
|
+
[](https://pypi.org/project/libspec/)
|
|
38
|
+
[](https://github.com/drhodes/libspec/blob/main/LICENSE)
|
|
39
|
+
|
|
40
|
+
> **an ounce of spec is worth a pound of tokens**
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
`libspec` is a **Specification Management System** in Python. Similar in spirit
|
|
44
|
+
to object-relation mapping (ORM), libspec uses an Object Specification Mapping
|
|
45
|
+
to compile logical requirements into structured database snapshots. Instead of
|
|
46
|
+
generating SQL, it tracks how requirements evolve over time.
|
|
47
|
+
|
|
48
|
+
By diff'ing snapshots and using a Model Context Protocol (MCP) server, it
|
|
49
|
+
provides a centralized context layer for local coding agents to trace specs directly
|
|
50
|
+
to generated code. The developer workflow is incremental and exploratory, less like
|
|
51
|
+
gambling and more like delegating.
|
|
52
|
+
|
|
53
|
+

|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
### Example Spec
|
|
57
|
+
|
|
58
|
+
Here is the specification `spec/err.py` used to establish fundamental code quality, error handling, and robustness constraints across the entire project via multiple inheritance:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from libspec import Ctx, Feature, Requirement
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# The Err docstrings are compiled into specification snapshots and
|
|
65
|
+
# injected as prompt context for LLM code generation.
|
|
66
|
+
class Err(Ctx):
|
|
67
|
+
"""
|
|
68
|
+
It is important that error handling be done excellently.
|
|
69
|
+
|
|
70
|
+
If a function can fail, then it needs to do so in the most elegant way
|
|
71
|
+
possible. Error reporting, handling, exceptions and all aspects of failure
|
|
72
|
+
must be taken to extreme. It should be possible to understand the program
|
|
73
|
+
by reading the error messages.
|
|
74
|
+
|
|
75
|
+
When an error occurs there should be a story about the failure at each step
|
|
76
|
+
of the way. What went wrong and why.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class BoilerPlate(Ctx):
|
|
81
|
+
"""
|
|
82
|
+
If you can see a way to reduce boiler plate, then do it.
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class FunctionLines(Ctx):
|
|
87
|
+
"""
|
|
88
|
+
Try to keep functions under 20 lines.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class Indentation(Ctx):
|
|
93
|
+
"""
|
|
94
|
+
Try to keep indentation under 4 levels.
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class PreCondition(Ctx):
|
|
99
|
+
"""
|
|
100
|
+
Functions should validate preconditions at their entry point.
|
|
101
|
+
|
|
102
|
+
Instead of using `assert` statements (which can be disabled globally),
|
|
103
|
+
raise explicit, descriptive exceptions (e.g., ValueError, TypeError, or
|
|
104
|
+
custom domain exceptions) to robustly reject malformed input.
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class GlobalMutableState(Ctx):
|
|
109
|
+
"""
|
|
110
|
+
Broadly you should avoid global mutable state.
|
|
111
|
+
"""
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class PostCondition(Ctx):
|
|
115
|
+
"""
|
|
116
|
+
Before a function returns, it should verify postconditions to ensure
|
|
117
|
+
invariant properties hold true.
|
|
118
|
+
|
|
119
|
+
Raise explicit, descriptive exceptions (such as RuntimeError or domain
|
|
120
|
+
exceptions) rather than using `assert` statements to handle post-execution
|
|
121
|
+
verification failures.
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
# Composite specification aggregating precondition, postcondition, and global state avoidance guidelines.
|
|
126
|
+
class DefensiveProgramming(PreCondition, PostCondition, GlobalMutableState):
|
|
127
|
+
pass
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class Refactor(BoilerPlate, FunctionLines, Indentation):
|
|
131
|
+
"""
|
|
132
|
+
Always keep an eye out for ways to generalize a function if it's utility
|
|
133
|
+
might be helpful to other functions.
|
|
134
|
+
|
|
135
|
+
Classes should be implemented in their own files with filename being the
|
|
136
|
+
classname with correct naming convention
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class Robustness(DefensiveProgramming):
|
|
141
|
+
"""
|
|
142
|
+
Always prioritize library-provided constructors for complex objects. Ensure
|
|
143
|
+
all components are fully initialized before calling any state- mutating
|
|
144
|
+
methods. Assume private internal state is uninitialized until the official
|
|
145
|
+
constructor has returned. When extending library components, prioritize
|
|
146
|
+
composition (pointers) over embedding by value to avoid risky state-copying
|
|
147
|
+
bugs.
|
|
148
|
+
|
|
149
|
+
Use dependency injection for system level objects for composability and to
|
|
150
|
+
make testing easier.
|
|
151
|
+
"""
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
# Use multiple inheritance to endow Feature and Requirement specs with
|
|
155
|
+
# disciplined error handling guidance from above.
|
|
156
|
+
class Feat(Err, Refactor, Robustness, Feature):
|
|
157
|
+
pass
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class Req(Err, Refactor, Robustness, Requirement):
|
|
161
|
+
pass
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
# The Object Model
|
|
165
|
+
|
|
166
|
+
Each class declares a specification fragment that is optionally a
|
|
167
|
+
Jinja2 template string. More about that later...
|
|
168
|
+
|
|
169
|
+
## Inheritance
|
|
170
|
+
|
|
171
|
+
Inheritance means "does this and more." The inherited superclass
|
|
172
|
+
docstrings are normative, but the compiled XML preserves them as
|
|
173
|
+
`<inherits><ref>...</ref></inherits>` references instead of prepending
|
|
174
|
+
their prose into the child docstring. Renderers such as `libspec diff`
|
|
175
|
+
can expand those refs when a review needs the inherited context.
|
|
176
|
+
|
|
177
|
+
## Mixins
|
|
178
|
+
|
|
179
|
+
Mixins help get around the diamond problem. (TODO: write more about this)
|
|
180
|
+
|
|
181
|
+
## Versioning
|
|
182
|
+
|
|
183
|
+
Note that the versioning of `libspec` is still being hammered
|
|
184
|
+
out. Currently, the version of `libspec` appears in the generated XML
|
|
185
|
+
(`libspec-version` field). But, how diffs will be performed on
|
|
186
|
+
different versions is unexplored.
|
libspec-10.2.0/README.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# libspec
|
|
2
|
+
|
|
3
|
+
[](https://github.com/drhodes/libspec/actions/workflows/ci.yml)
|
|
4
|
+
[](https://drhodes.github.io/libspec/)
|
|
5
|
+
[](https://pypi.org/project/libspec/)
|
|
6
|
+
[](https://pypi.org/project/libspec/)
|
|
7
|
+
[](https://github.com/drhodes/libspec/blob/main/LICENSE)
|
|
8
|
+
|
|
9
|
+
> **an ounce of spec is worth a pound of tokens**
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
`libspec` is a **Specification Management System** in Python. Similar in spirit
|
|
13
|
+
to object-relation mapping (ORM), libspec uses an Object Specification Mapping
|
|
14
|
+
to compile logical requirements into structured database snapshots. Instead of
|
|
15
|
+
generating SQL, it tracks how requirements evolve over time.
|
|
16
|
+
|
|
17
|
+
By diff'ing snapshots and using a Model Context Protocol (MCP) server, it
|
|
18
|
+
provides a centralized context layer for local coding agents to trace specs directly
|
|
19
|
+
to generated code. The developer workflow is incremental and exploratory, less like
|
|
20
|
+
gambling and more like delegating.
|
|
21
|
+
|
|
22
|
+

|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Example Spec
|
|
26
|
+
|
|
27
|
+
Here is the specification `spec/err.py` used to establish fundamental code quality, error handling, and robustness constraints across the entire project via multiple inheritance:
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
from libspec import Ctx, Feature, Requirement
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# The Err docstrings are compiled into specification snapshots and
|
|
34
|
+
# injected as prompt context for LLM code generation.
|
|
35
|
+
class Err(Ctx):
|
|
36
|
+
"""
|
|
37
|
+
It is important that error handling be done excellently.
|
|
38
|
+
|
|
39
|
+
If a function can fail, then it needs to do so in the most elegant way
|
|
40
|
+
possible. Error reporting, handling, exceptions and all aspects of failure
|
|
41
|
+
must be taken to extreme. It should be possible to understand the program
|
|
42
|
+
by reading the error messages.
|
|
43
|
+
|
|
44
|
+
When an error occurs there should be a story about the failure at each step
|
|
45
|
+
of the way. What went wrong and why.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class BoilerPlate(Ctx):
|
|
50
|
+
"""
|
|
51
|
+
If you can see a way to reduce boiler plate, then do it.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class FunctionLines(Ctx):
|
|
56
|
+
"""
|
|
57
|
+
Try to keep functions under 20 lines.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class Indentation(Ctx):
|
|
62
|
+
"""
|
|
63
|
+
Try to keep indentation under 4 levels.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class PreCondition(Ctx):
|
|
68
|
+
"""
|
|
69
|
+
Functions should validate preconditions at their entry point.
|
|
70
|
+
|
|
71
|
+
Instead of using `assert` statements (which can be disabled globally),
|
|
72
|
+
raise explicit, descriptive exceptions (e.g., ValueError, TypeError, or
|
|
73
|
+
custom domain exceptions) to robustly reject malformed input.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class GlobalMutableState(Ctx):
|
|
78
|
+
"""
|
|
79
|
+
Broadly you should avoid global mutable state.
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class PostCondition(Ctx):
|
|
84
|
+
"""
|
|
85
|
+
Before a function returns, it should verify postconditions to ensure
|
|
86
|
+
invariant properties hold true.
|
|
87
|
+
|
|
88
|
+
Raise explicit, descriptive exceptions (such as RuntimeError or domain
|
|
89
|
+
exceptions) rather than using `assert` statements to handle post-execution
|
|
90
|
+
verification failures.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
# Composite specification aggregating precondition, postcondition, and global state avoidance guidelines.
|
|
95
|
+
class DefensiveProgramming(PreCondition, PostCondition, GlobalMutableState):
|
|
96
|
+
pass
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class Refactor(BoilerPlate, FunctionLines, Indentation):
|
|
100
|
+
"""
|
|
101
|
+
Always keep an eye out for ways to generalize a function if it's utility
|
|
102
|
+
might be helpful to other functions.
|
|
103
|
+
|
|
104
|
+
Classes should be implemented in their own files with filename being the
|
|
105
|
+
classname with correct naming convention
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class Robustness(DefensiveProgramming):
|
|
110
|
+
"""
|
|
111
|
+
Always prioritize library-provided constructors for complex objects. Ensure
|
|
112
|
+
all components are fully initialized before calling any state- mutating
|
|
113
|
+
methods. Assume private internal state is uninitialized until the official
|
|
114
|
+
constructor has returned. When extending library components, prioritize
|
|
115
|
+
composition (pointers) over embedding by value to avoid risky state-copying
|
|
116
|
+
bugs.
|
|
117
|
+
|
|
118
|
+
Use dependency injection for system level objects for composability and to
|
|
119
|
+
make testing easier.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# Use multiple inheritance to endow Feature and Requirement specs with
|
|
124
|
+
# disciplined error handling guidance from above.
|
|
125
|
+
class Feat(Err, Refactor, Robustness, Feature):
|
|
126
|
+
pass
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class Req(Err, Refactor, Robustness, Requirement):
|
|
130
|
+
pass
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
# The Object Model
|
|
134
|
+
|
|
135
|
+
Each class declares a specification fragment that is optionally a
|
|
136
|
+
Jinja2 template string. More about that later...
|
|
137
|
+
|
|
138
|
+
## Inheritance
|
|
139
|
+
|
|
140
|
+
Inheritance means "does this and more." The inherited superclass
|
|
141
|
+
docstrings are normative, but the compiled XML preserves them as
|
|
142
|
+
`<inherits><ref>...</ref></inherits>` references instead of prepending
|
|
143
|
+
their prose into the child docstring. Renderers such as `libspec diff`
|
|
144
|
+
can expand those refs when a review needs the inherited context.
|
|
145
|
+
|
|
146
|
+
## Mixins
|
|
147
|
+
|
|
148
|
+
Mixins help get around the diamond problem. (TODO: write more about this)
|
|
149
|
+
|
|
150
|
+
## Versioning
|
|
151
|
+
|
|
152
|
+
Note that the versioning of `libspec` is still being hammered
|
|
153
|
+
out. Currently, the version of `libspec` appears in the generated XML
|
|
154
|
+
(`libspec-version` field). But, how diffs will be performed on
|
|
155
|
+
different versions is unexplored.
|