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.
Files changed (70) hide show
  1. libspec-10.2.0/PKG-INFO +186 -0
  2. libspec-10.2.0/README.md +155 -0
  3. libspec-10.2.0/libspec/__init__.py +6 -0
  4. libspec-10.2.0/libspec/agent_config.py +532 -0
  5. libspec-10.2.0/libspec/cli.py +629 -0
  6. libspec-10.2.0/libspec/colors.py +116 -0
  7. libspec-10.2.0/libspec/common.py +80 -0
  8. {libspec-1.2.0 → libspec-10.2.0}/libspec/err.py +14 -14
  9. libspec-10.2.0/libspec/lsp_client.py +193 -0
  10. libspec-10.2.0/libspec/mcp_server.py +543 -0
  11. libspec-10.2.0/libspec/pylsp_plugin.py +195 -0
  12. libspec-10.2.0/libspec/repl.py +1611 -0
  13. libspec-10.2.0/libspec/spec.py +848 -0
  14. libspec-10.2.0/libspec/spec_diff.py +280 -0
  15. libspec-10.2.0/libspec/spec_types.py +252 -0
  16. {libspec-1.2.0 → libspec-10.2.0}/libspec/specweb.py +5 -7
  17. libspec-10.2.0/libspec/store.py +20 -0
  18. libspec-10.2.0/libspec/templates/err.py +100 -0
  19. libspec-10.2.0/libspec/templates/skill.md.j2 +43 -0
  20. {libspec-1.2.0 → libspec-10.2.0}/libspec/user_story.py +3 -3
  21. libspec-10.2.0/libspec/util.py +426 -0
  22. libspec-10.2.0/libspec/watcher.py +126 -0
  23. libspec-10.2.0/libspec/workflow.py +74 -0
  24. libspec-10.2.0/libspec-scheduler/src/libspec_scheduler/__init__.py +1 -0
  25. libspec-10.2.0/libspec-scheduler/src/libspec_scheduler/mcp.py +249 -0
  26. libspec-10.2.0/libspec-scheduler/src/libspec_scheduler/scheduler.py +267 -0
  27. libspec-10.2.0/libspec-scheduler/tests/test_mcp_scheduler.py +86 -0
  28. libspec-10.2.0/libspec-scheduler/tests/test_scheduler.py +196 -0
  29. libspec-10.2.0/libspec.egg-info/PKG-INFO +186 -0
  30. libspec-10.2.0/libspec.egg-info/SOURCES.txt +52 -0
  31. {libspec-1.2.0 → libspec-10.2.0}/libspec.egg-info/entry_points.txt +3 -0
  32. libspec-10.2.0/libspec.egg-info/requires.txt +10 -0
  33. libspec-10.2.0/libspec.egg-info/top_level.txt +2 -0
  34. libspec-10.2.0/pyproject.toml +113 -0
  35. libspec-10.2.0/tests/test_agent_config.py +59 -0
  36. libspec-10.2.0/tests/test_agent_workflow.py +88 -0
  37. libspec-10.2.0/tests/test_cli.py +222 -0
  38. libspec-10.2.0/tests/test_common_types.py +87 -0
  39. libspec-10.2.0/tests/test_cwd_validation.py +73 -0
  40. {libspec-1.2.0 → libspec-10.2.0}/tests/test_idempotency.py +25 -13
  41. libspec-10.2.0/tests/test_lsp.py +66 -0
  42. libspec-10.2.0/tests/test_mcp_metadata.py +58 -0
  43. {libspec-1.2.0 → libspec-10.2.0}/tests/test_missing_requirement_variable.py +10 -4
  44. libspec-10.2.0/tests/test_mixins.py +67 -0
  45. libspec-10.2.0/tests/test_projects.py +34 -0
  46. libspec-10.2.0/tests/test_removed_cli.py +16 -0
  47. libspec-10.2.0/tests/test_repl.py +245 -0
  48. libspec-10.2.0/tests/test_spec.py +289 -0
  49. libspec-10.2.0/tests/test_spec_diff.py +157 -0
  50. libspec-10.2.0/tests/test_watcher.py +38 -0
  51. {libspec-1.2.0 → libspec-10.2.0}/tests/test_xml_render.py +118 -36
  52. libspec-1.2.0/PKG-INFO +0 -111
  53. libspec-1.2.0/README.md +0 -86
  54. libspec-1.2.0/libspec/__init__.py +0 -5
  55. libspec-1.2.0/libspec/cli.py +0 -259
  56. libspec-1.2.0/libspec/mcp_server.py +0 -82
  57. libspec-1.2.0/libspec/query_map.py +0 -19
  58. libspec-1.2.0/libspec/spec.py +0 -591
  59. libspec-1.2.0/libspec/spec_diff.py +0 -193
  60. libspec-1.2.0/libspec/util.py +0 -26
  61. libspec-1.2.0/libspec.egg-info/PKG-INFO +0 -111
  62. libspec-1.2.0/libspec.egg-info/SOURCES.txt +0 -24
  63. libspec-1.2.0/libspec.egg-info/requires.txt +0 -4
  64. libspec-1.2.0/libspec.egg-info/top_level.txt +0 -1
  65. libspec-1.2.0/pyproject.toml +0 -40
  66. libspec-1.2.0/tests/test_mixins.py +0 -49
  67. libspec-1.2.0/tests/test_spec.py +0 -109
  68. {libspec-1.2.0 → libspec-10.2.0}/LICENSE +0 -0
  69. {libspec-1.2.0 → libspec-10.2.0}/libspec.egg-info/dependency_links.txt +0 -0
  70. {libspec-1.2.0 → libspec-10.2.0}/setup.cfg +0 -0
@@ -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
+ [![CI/CD](https://github.com/drhodes/libspec/actions/workflows/ci.yml/badge.svg)](https://github.com/drhodes/libspec/actions/workflows/ci.yml)
35
+ [![Documentation](https://github.com/drhodes/libspec/actions/workflows/docs.yml/badge.svg)](https://drhodes.github.io/libspec/)
36
+ [![PyPI version](https://img.shields.io/pypi/v/libspec.svg)](https://pypi.org/project/libspec/)
37
+ [![Python versions](https://img.shields.io/pypi/pyversions/libspec.svg)](https://pypi.org/project/libspec/)
38
+ [![License](https://img.shields.io/github/license/drhodes/libspec.svg)](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
+ ![the general idea](./docs/workflow1.png)
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.
@@ -0,0 +1,155 @@
1
+ # libspec
2
+
3
+ [![CI/CD](https://github.com/drhodes/libspec/actions/workflows/ci.yml/badge.svg)](https://github.com/drhodes/libspec/actions/workflows/ci.yml)
4
+ [![Documentation](https://github.com/drhodes/libspec/actions/workflows/docs.yml/badge.svg)](https://drhodes.github.io/libspec/)
5
+ [![PyPI version](https://img.shields.io/pypi/v/libspec.svg)](https://pypi.org/project/libspec/)
6
+ [![Python versions](https://img.shields.io/pypi/pyversions/libspec.svg)](https://pypi.org/project/libspec/)
7
+ [![License](https://img.shields.io/github/license/drhodes/libspec.svg)](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
+ ![the general idea](./docs/workflow1.png)
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.
@@ -0,0 +1,6 @@
1
+ # libspec/__init__.py
2
+ from .common import * # noqa: F403, F401
3
+ from .spec import * # noqa: F403, F401
4
+ from .specweb import * # noqa: F403, F401
5
+ from .user_story import * # noqa: F403, F401
6
+ # from .spec_diff import *