squalor-slicer 1.0.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.
- squalor_slicer-1.0.0/LICENSE +202 -0
- squalor_slicer-1.0.0/PKG-INFO +457 -0
- squalor_slicer-1.0.0/README.md +435 -0
- squalor_slicer-1.0.0/pyproject.toml +40 -0
- squalor_slicer-1.0.0/setup.cfg +4 -0
- squalor_slicer-1.0.0/src/slicer/__init__.py +10 -0
- squalor_slicer-1.0.0/src/slicer/__main__.py +8 -0
- squalor_slicer-1.0.0/src/slicer/ai.py +134 -0
- squalor_slicer-1.0.0/src/slicer/check.py +57 -0
- squalor_slicer-1.0.0/src/slicer/cli.py +1957 -0
- squalor_slicer-1.0.0/src/slicer/config.py +287 -0
- squalor_slicer-1.0.0/src/slicer/errors.py +89 -0
- squalor_slicer-1.0.0/src/slicer/graph.py +178 -0
- squalor_slicer-1.0.0/src/slicer/ids.py +110 -0
- squalor_slicer-1.0.0/src/slicer/jsonio.py +80 -0
- squalor_slicer-1.0.0/src/slicer/legacy.py +292 -0
- squalor_slicer-1.0.0/src/slicer/migrator.py +386 -0
- squalor_slicer-1.0.0/src/slicer/model.py +491 -0
- squalor_slicer-1.0.0/src/slicer/ops.py +1192 -0
- squalor_slicer-1.0.0/src/slicer/outline.py +235 -0
- squalor_slicer-1.0.0/src/slicer/prose.py +88 -0
- squalor_slicer-1.0.0/src/slicer/py.typed +0 -0
- squalor_slicer-1.0.0/src/slicer/render.py +452 -0
- squalor_slicer-1.0.0/src/slicer/store.py +389 -0
- squalor_slicer-1.0.0/src/slicer/sync.py +118 -0
- squalor_slicer-1.0.0/src/slicer/templates/roadmap.md +13 -0
- squalor_slicer-1.0.0/src/slicer/templates/row.md +1 -0
- squalor_slicer-1.0.0/src/slicer/templates/slice.md +5 -0
- squalor_slicer-1.0.0/src/slicer/templates.py +21 -0
- squalor_slicer-1.0.0/src/slicer/tui.py +1069 -0
- squalor_slicer-1.0.0/src/slicer/tui_style.py +133 -0
- squalor_slicer-1.0.0/src/slicer/tui_wizard.py +247 -0
- squalor_slicer-1.0.0/src/slicer/vcs.py +267 -0
- squalor_slicer-1.0.0/src/slicer/verify.py +185 -0
- squalor_slicer-1.0.0/src/squalor_slicer.egg-info/PKG-INFO +457 -0
- squalor_slicer-1.0.0/src/squalor_slicer.egg-info/SOURCES.txt +90 -0
- squalor_slicer-1.0.0/src/squalor_slicer.egg-info/dependency_links.txt +1 -0
- squalor_slicer-1.0.0/src/squalor_slicer.egg-info/entry_points.txt +2 -0
- squalor_slicer-1.0.0/src/squalor_slicer.egg-info/top_level.txt +1 -0
- squalor_slicer-1.0.0/tests/test_add_options.py +110 -0
- squalor_slicer-1.0.0/tests/test_ai.py +240 -0
- squalor_slicer-1.0.0/tests/test_atomic.py +99 -0
- squalor_slicer-1.0.0/tests/test_batch.py +135 -0
- squalor_slicer-1.0.0/tests/test_boundary.py +149 -0
- squalor_slicer-1.0.0/tests/test_claim.py +147 -0
- squalor_slicer-1.0.0/tests/test_cli.py +1186 -0
- squalor_slicer-1.0.0/tests/test_code_location.py +72 -0
- squalor_slicer-1.0.0/tests/test_config.py +140 -0
- squalor_slicer-1.0.0/tests/test_corruption.py +143 -0
- squalor_slicer-1.0.0/tests/test_depends_validation.py +120 -0
- squalor_slicer-1.0.0/tests/test_deps.py +61 -0
- squalor_slicer-1.0.0/tests/test_docs_coverage.py +57 -0
- squalor_slicer-1.0.0/tests/test_edit.py +193 -0
- squalor_slicer-1.0.0/tests/test_effort.py +197 -0
- squalor_slicer-1.0.0/tests/test_errors.py +325 -0
- squalor_slicer-1.0.0/tests/test_find.py +112 -0
- squalor_slicer-1.0.0/tests/test_goals.py +55 -0
- squalor_slicer-1.0.0/tests/test_handoff.py +200 -0
- squalor_slicer-1.0.0/tests/test_ids.py +343 -0
- squalor_slicer-1.0.0/tests/test_import.py +413 -0
- squalor_slicer-1.0.0/tests/test_isolation.py +84 -0
- squalor_slicer-1.0.0/tests/test_lean.py +150 -0
- squalor_slicer-1.0.0/tests/test_legacy_index.py +48 -0
- squalor_slicer-1.0.0/tests/test_legacy_slice.py +86 -0
- squalor_slicer-1.0.0/tests/test_merge.py +379 -0
- squalor_slicer-1.0.0/tests/test_migrate.py +437 -0
- squalor_slicer-1.0.0/tests/test_next.py +136 -0
- squalor_slicer-1.0.0/tests/test_next_offset.py +92 -0
- squalor_slicer-1.0.0/tests/test_note.py +84 -0
- squalor_slicer-1.0.0/tests/test_ops.py +739 -0
- squalor_slicer-1.0.0/tests/test_outline.py +129 -0
- squalor_slicer-1.0.0/tests/test_packaging.py +55 -0
- squalor_slicer-1.0.0/tests/test_park.py +129 -0
- squalor_slicer-1.0.0/tests/test_parser_cache.py +49 -0
- squalor_slicer-1.0.0/tests/test_prose.py +276 -0
- squalor_slicer-1.0.0/tests/test_ready.py +315 -0
- squalor_slicer-1.0.0/tests/test_remove.py +319 -0
- squalor_slicer-1.0.0/tests/test_render.py +170 -0
- squalor_slicer-1.0.0/tests/test_schema.py +165 -0
- squalor_slicer-1.0.0/tests/test_scoring.py +215 -0
- squalor_slicer-1.0.0/tests/test_sort.py +50 -0
- squalor_slicer-1.0.0/tests/test_start.py +290 -0
- squalor_slicer-1.0.0/tests/test_status.py +65 -0
- squalor_slicer-1.0.0/tests/test_status_keys.py +61 -0
- squalor_slicer-1.0.0/tests/test_store.py +69 -0
- squalor_slicer-1.0.0/tests/test_sync.py +112 -0
- squalor_slicer-1.0.0/tests/test_tables.py +209 -0
- squalor_slicer-1.0.0/tests/test_tui.py +656 -0
- squalor_slicer-1.0.0/tests/test_tui_style.py +274 -0
- squalor_slicer-1.0.0/tests/test_tui_wizard.py +395 -0
- squalor_slicer-1.0.0/tests/test_unscored_hint.py +76 -0
- squalor_slicer-1.0.0/tests/test_worktree_claims.py +207 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright 2026 Squalor LLC
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: squalor-slicer
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Roadmap and slice manager for the review -> slice -> implement loop
|
|
5
|
+
Author: Squalor LLC
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/squalor-xyz/slicer
|
|
8
|
+
Project-URL: Source, https://github.com/squalor-xyz/slicer
|
|
9
|
+
Project-URL: Issues, https://github.com/squalor-xyz/slicer/issues
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Requires-Python: >=3.11
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
|
|
23
|
+
# slicer
|
|
24
|
+
|
|
25
|
+
Roadmap and slice management for the review → slice → implement → done loop.
|
|
26
|
+
|
|
27
|
+
slicer is AI-friendly: a coding agent can review a project, turn accepted findings into
|
|
28
|
+
an importable roadmap, and work through bounded slices using commands with JSON output.
|
|
29
|
+
For a new project, start with goals and acceptance criteria instead of review findings.
|
|
30
|
+
The AI supplies the review and planning; slicer stores, validates, prioritizes, and
|
|
31
|
+
renders the work. It runs locally without an AI service or API key.
|
|
32
|
+
|
|
33
|
+
Run `slicer ai instructions` for a concise agent quick start, or add `--json` for
|
|
34
|
+
machine-readable output. It works before initialization and reads no project state.
|
|
35
|
+
|
|
36
|
+
Start with the [worked workflows](docs/getting-started.md#worked-workflows), use the
|
|
37
|
+
[agent prompts](docs/agents.md#reusable-prompts), or follow the
|
|
38
|
+
[contributor workflow](AGENTS.md#working-on-the-roadmap) to work on slicer itself.
|
|
39
|
+
See the [changelog](CHANGELOG.md) for notable changes by release.
|
|
40
|
+
|
|
41
|
+
State is **JSON**. The markdown under `.slicer/render/` is generated output — readable,
|
|
42
|
+
committed, and never parsed back. Edit through the commands or the TUI, not by hand.
|
|
43
|
+
|
|
44
|
+
Stdlib Python 3.11+, no dependencies.
|
|
45
|
+
|
|
46
|
+
## Install
|
|
47
|
+
|
|
48
|
+
Python 3.11+, no dependencies. Install it to use slicer; clone it to change slicer.
|
|
49
|
+
|
|
50
|
+
### Install it (no clone)
|
|
51
|
+
|
|
52
|
+
Into its own virtual environment from PyPI. The distribution is `squalor-slicer`
|
|
53
|
+
because the `slicer` name on PyPI is taken; the command it installs is still `slicer`.
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
python3 -m venv ~/.slicer-venv
|
|
57
|
+
~/.slicer-venv/bin/pip install squalor-slicer
|
|
58
|
+
ln -s ~/.slicer-venv/bin/slicer ~/.local/bin/slicer # or anywhere on your PATH
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`slicer --help` confirms it. Update with
|
|
62
|
+
`~/.slicer-venv/bin/pip install -U squalor-slicer`; uninstall by
|
|
63
|
+
deleting the venv and the symlink.
|
|
64
|
+
|
|
65
|
+
If you prefer a single command, `pip install --user squalor-slicer` also works, with two
|
|
66
|
+
caveats: on macOS Homebrew and recent Debian/Ubuntu/Fedora the system Python is
|
|
67
|
+
"externally managed" (PEP 668) and rejects it — use the venv above instead — and the user
|
|
68
|
+
scripts directory must be on your `PATH` (`~/.local/bin` on Linux,
|
|
69
|
+
`~/Library/Python/3.11/bin` on macOS). Uninstall with `pip uninstall squalor-slicer`. If
|
|
70
|
+
you already use [pipx](https://pipx.pypa.io) or [uv](https://docs.astral.sh/uv/),
|
|
71
|
+
`pipx install squalor-slicer` or `uv tool install squalor-slicer` install it isolated and
|
|
72
|
+
on your `PATH` in one step.
|
|
73
|
+
|
|
74
|
+
To try unreleased main instead of the latest release, replace the package name with
|
|
75
|
+
`git+https://github.com/squalor-xyz/slicer`.
|
|
76
|
+
|
|
77
|
+
### Develop on it (clone + editable)
|
|
78
|
+
|
|
79
|
+
To hack on slicer itself, use an editable install so the command tracks your checkout:
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
git clone git@github.com:squalor-xyz/slicer.git
|
|
83
|
+
cd slicer
|
|
84
|
+
python3 -m venv .venv
|
|
85
|
+
.venv/bin/pip install -e .
|
|
86
|
+
ln -s "$PWD/.venv/bin/slicer" ~/.local/bin/slicer # or anywhere on your PATH
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The install is editable, so `slicer` follows the checkout. `slicer --help` confirms it.
|
|
90
|
+
|
|
91
|
+
## Use it on a project
|
|
92
|
+
|
|
93
|
+
```sh
|
|
94
|
+
cd any-repo
|
|
95
|
+
slicer init # creates .slicer/
|
|
96
|
+
slicer add "Parse the config file" --size M --tree core
|
|
97
|
+
slicer promote S01 # give it a slice file from the template
|
|
98
|
+
slicer edit S01 --section Why --text "Load settings before starting the app"
|
|
99
|
+
slicer render # regenerate .slicer/render/
|
|
100
|
+
slicer check # the gate: exit 1 if anything drifted
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`add` appends a roadmap row; `promote` gives it a slice file.
|
|
104
|
+
|
|
105
|
+
Got a whole roadmap to load? Write it as a markdown outline and import it in one go:
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
slicer import --skeleton > roadmap.md # a template, built from your config
|
|
109
|
+
slicer import roadmap.md --dry-run # validate; writes nothing
|
|
110
|
+
slicer import roadmap.md # apply
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Each `##` heading is an item, optional `key: value` lines carry its size, tree and
|
|
114
|
+
dependencies, and `###` sections become the slice itself — so one file can produce a
|
|
115
|
+
fully written roadmap. It is a one-way ramp: the file is yours to delete afterwards.
|
|
116
|
+
|
|
117
|
+
Already running this workflow by hand in markdown? `slicer migrate --from docs/slices`
|
|
118
|
+
converts an existing tree that is **already in slicer's legacy format**. It refuses to
|
|
119
|
+
write anything unless every file round-trips byte for byte, so a document slicer cannot
|
|
120
|
+
reproduce is never half-migrated.
|
|
121
|
+
|
|
122
|
+
**→ [docs/getting-started.md](docs/getting-started.md)** walks through all of this with
|
|
123
|
+
real output. [docs/import.md](docs/import.md) is the outline format;
|
|
124
|
+
[docs/agents.md](docs/agents.md) is how to drive slicer from an AI agent;
|
|
125
|
+
[docs/migrate-format.md](docs/migrate-format.md) is the legacy grammar; and
|
|
126
|
+
[docs/configuration.md](docs/configuration.md) is every config key.
|
|
127
|
+
|
|
128
|
+
## Commands
|
|
129
|
+
|
|
130
|
+
| | |
|
|
131
|
+
|---|---|
|
|
132
|
+
| `ai instructions` | agent quick start, available without a project; supports `--json` |
|
|
133
|
+
| `ai skill` | the same loop and exit rules as a `SKILL.md` for Claude Code, Codex, and Grok |
|
|
134
|
+
| `init [--force]` | create `.slicer/` with config and templates; `--force` rewrites an existing config and templates only |
|
|
135
|
+
| `setup-git` | print the two `git config` lines that enable the `slicer-generated` render merge driver in this clone (`slicer setup-git \| sh` applies them); needs no project |
|
|
136
|
+
| `import FILE [--dry-run] [--force]` | bulk-load a roadmap from a markdown outline |
|
|
137
|
+
| `import --skeleton` | print an outline template built from your config |
|
|
138
|
+
| `migrate --from DIR [--dry-run] [--force]` | convert an existing legacy markdown tree; `--force` replaces an existing roadmap |
|
|
139
|
+
| `add TITLE [--id/--size/--tree/--findings/--status/--pass/--importance/--urgency/--effort/--depends-on/--short-title]` | append a roadmap item (no slice file yet); repeat `--depends-on ID` for multiple dependencies. `--effort` is 1–3 and optional; an open item left at importance 2, urgency 2 and no effort gets a stderr hint |
|
|
140
|
+
| `promote ID [--file/--stdin] [--boundary TEXT] [--force]` | give an item a slice file; a one-item outline fills its sections in one call. `--force` overwrites an existing slice |
|
|
141
|
+
| `move ID --before/--after/--to` | reorder the queue; position is the manual priority, and breaks score ties |
|
|
142
|
+
| `sort [--by score\|effort] [--render]` | reorder the whole queue in one step. `score` (default) persists `list --sort score`. `effort` persists `list --sort effort`: lightest estimate first, unset last |
|
|
143
|
+
| `next [-n N] [--start] [--show\|--ready [--section NAME ...]]` | one eligible item at offset N (default 0), with its effective score and status; `--start` marks it started. `--show` adds the full item and its slice. `--ready` returns item identity, the slice, and blocked ids. Repeat `--section` with `--ready` to return the scope boundary and those sections only. An item started or claimed in a sibling Git worktree is skipped and reported (`in_work_elsewhere`), unless this checkout has it too |
|
|
144
|
+
| `next-id` | the id the next `add` or `import` would take, without allocating it |
|
|
145
|
+
| `list [--all] [--status/--tree/--pass/--flag] [--sort score\|effort]` | the queue in `next`'s order: unblocked started, then unblocked open, then the other visible rows, each by effective score. The text table has a CLAIM column: the local owner, `*` for locally in-progress with no claim, `wt:NAME` for work in a sibling worktree, or `-`. `wt:NAME+N` means N more worktrees. `--json` includes `claim` (`{"owner", "at"}` or null) and `in_work_elsewhere` (an array of `{worktree, owner}`). Done and retired items are omitted unless `--all` is set or `--status` names them. Repeat `--flag` to keep an item that has any of those flags. Flags are free-form labels set with `set --flag`. `--sort score` is a flat score sort. `--sort effort` orders estimates 1–3 and puts unset items last, without writing state |
|
|
146
|
+
| `find PATTERN [--in FIELDS]` | search items by text (id, title, findings and slice bodies by default); shows the matched field and a snippet |
|
|
147
|
+
| `deps [ID] [--format mermaid]` | dependencies: unblocked open items, or one item's waits-on/blocked-by/dependents; `--format mermaid` renders the graph |
|
|
148
|
+
| `show ID [--section NAME ...] [--context]` | print one slice or selected sections; `--context` adds title, dependencies, and scope boundary |
|
|
149
|
+
| `set ID [ID ...] --title/--short-title/--size/--tree/--findings/--status/--pass/--depends-on/--flag/--no-flags/--group/--importance/--urgency/--effort/--no-effort` | change fields. `--no-effort` clears an estimate. `add` and `set` refuse an unknown, self, retired, or cycle-closing `--depends-on` and write nothing |
|
|
150
|
+
| `edit ID (--section NAME / --boundary) [--text/--file/--stdin]` | edit a section or scope boundary; sections also accept `--append` |
|
|
151
|
+
| `note ID [--text/--file/--stdin] [--render]` | append a dated note to any item — no slice needed (shows in `show`/`render`, unlike `done --note`) |
|
|
152
|
+
| `prose list / show REF / edit REF` | read and edit the roadmap's own prose |
|
|
153
|
+
| `prose add-pass KEY / drop-pass KEY` | open or close a pass group |
|
|
154
|
+
| `goals` | print the project's goals and non-goals together; supports `--json` |
|
|
155
|
+
| `start ID [ID ...] [--note TEXT]` | mark an item in progress and claim it (owner and time). The owner is `claim_owner` in config, otherwise the git user name, otherwise the worktree name. A second start does not refresh the claim |
|
|
156
|
+
| `release ID [ID ...]` | clear a claim without changing status. An item that was in progress stays in progress and lists as `*` |
|
|
157
|
+
| `handoff ID [ID ...] [--note TEXT]` | hand a started slice to review: status becomes `review_status` and the claim is cleared. `next` skips review items and dependents stay blocked until `done`; a reviewer finds them with `list --status review` and claims one with `start` |
|
|
158
|
+
| `done ID [ID ...]` / `park ID [ID ...]` / `unpark ID [ID ...]` `[--note TEXT]` | change status; `--note` records a one-line *history* entry (for a durable note on the item, use `slicer note`); `done` moves the file with `git mv` and clears a claim |
|
|
159
|
+
| `remove ID --reason "…"` | retire an obsolete item; the id stays claimed |
|
|
160
|
+
| `remove ID --purge` | delete outright, for something that never should have existed |
|
|
161
|
+
| `remove ID --purge/--reason --dry-run` | preview the removal and its fallout (dependents, id fate); write nothing |
|
|
162
|
+
| `remove ID ... --force` | retire or purge despite dependents, or a done item |
|
|
163
|
+
| `render` | regenerate `.slicer/render/` (ROADMAP.md, a browser-viewable ROADMAP.html, and one file per slice) |
|
|
164
|
+
| `sync [--check]` | rewrite derived lines in other documents |
|
|
165
|
+
| `verify` | check the index for consistency, and against `git log` (unless `git_check` is off) |
|
|
166
|
+
| `check [--diff]` | the CI gate: render staleness, sync drift, integrity |
|
|
167
|
+
| `stats` / `log [--limit N] [--item ID] [--action A]` | counts + completion % and per-tree progress; history, newest first (`--limit` defaults to 20; `--item`/`--action` scope it; `set` records old→new values) |
|
|
168
|
+
| `status` | the front door: next item, progress census, and blockers in one view (`--json`) |
|
|
169
|
+
| `tui` / `ui` | browse, read, reorder and edit interactively (two names for the same command) |
|
|
170
|
+
|
|
171
|
+
The sibling worktree signal comes from local `git worktree list` and each checkout's
|
|
172
|
+
`.slicer/index.json`. It sees worktrees on this machine only, not work on another machine.
|
|
173
|
+
|
|
174
|
+
`slicer next -n 1` returns the item after the current next item. Offsets are
|
|
175
|
+
nonnegative integers: `-n 0` is the same as `next`. Eligible started items come
|
|
176
|
+
before eligible open items; each group uses descending effective priority with
|
|
177
|
+
roadmap order breaking ties. Skipping an item does not complete it or unblock its
|
|
178
|
+
dependents. The command returns one item, including rows without slice files;
|
|
179
|
+
an exhausted offset exits 2 (JSON returns `item: null` and blocked details).
|
|
180
|
+
The text form of `slicer list` labels its columns: number, id, status, size,
|
|
181
|
+
effort, score, quadrant, and title. An unset effort appears as `-`. When the
|
|
182
|
+
default status filter hides done or retired items, a final line counts the
|
|
183
|
+
matching hidden rows and points to `--all`. `--all` and `--status` suppress that
|
|
184
|
+
notice; `--json` remains an array of the visible item records.
|
|
185
|
+
`slicer next --ready` is a bounded pickup of that same item: `id`, `title`,
|
|
186
|
+
`status`, `depends_on`, `effective_score`, `path`, the slice when the item has
|
|
187
|
+
one, and every blocked id. The agent loop uses
|
|
188
|
+
`slicer next --ready --section "Implement" --section "Check" --json --lean`.
|
|
189
|
+
The headings are examples; pass the section names the project configures.
|
|
190
|
+
Repeat `--section NAME` with `--ready` to keep the
|
|
191
|
+
scope boundary and those section bodies; omit it and the slice stays complete.
|
|
192
|
+
`--section` without `--ready` is a usage error. A row with no slice still says
|
|
193
|
+
to run `promote`. An empty queue uses the same exit 2 result as `next`.
|
|
194
|
+
Pass either `--ready` or `--show`. The text form of `--ready` stays the
|
|
195
|
+
identity, the boundary, and the section headings.
|
|
196
|
+
|
|
197
|
+
In the TUI, the queue opens in the same ranked order as `slicer list`: eligible
|
|
198
|
+
started items, then eligible open items, then the other visible rows, each by
|
|
199
|
+
effective score, with parked items last. Done and retired stay hidden until
|
|
200
|
+
you clear the filter or ask for them. `o` sorts that view by ranked order, ID, title, status, size,
|
|
201
|
+
importance, urgency, effective score, or effort, ascending or descending. The
|
|
202
|
+
choice lasts for the session and does not rewrite the stored queue. `J`, `K`,
|
|
203
|
+
`T`, and `M` still move items in stored order, and only when no filter or
|
|
204
|
+
search is active. `tab` moves between the queue and the detail pane, `e` opens `$EDITOR` on
|
|
205
|
+
whatever is selected there — an item field (size, trees, findings, depends, importance,
|
|
206
|
+
urgency), a slice section, its scope boundary, a note (edit it, or empty to remove; the
|
|
207
|
+
`+ add a note` line adds one), or a prose block — `s` starts the selected item and `a` adds a
|
|
208
|
+
new one. Press `w` for the guided roadmap wizard; an empty roadmap offers it once
|
|
209
|
+
when the TUI starts.
|
|
210
|
+
|
|
211
|
+
The wizard collects an optional roadmap heading and each item's title, size, trees,
|
|
212
|
+
findings, importance, urgency, group, and dependencies (comma-separated exact titles,
|
|
213
|
+
including later draft items). Enter advances and Shift-Tab goes back. Each configured
|
|
214
|
+
section offers `e` to open `$EDITOR`, or Enter to leave its body as it is. Every item
|
|
215
|
+
gets a slice, even when its section bodies are empty.
|
|
216
|
+
|
|
217
|
+
After adding items, review the answers with Up/Down and Enter to revisit a field or
|
|
218
|
+
section, add another item, or select **Save roadmap**. Esc asks before discarding draft
|
|
219
|
+
answers. Nothing is saved until the final save; validation errors keep the draft for
|
|
220
|
+
correction. A supplied heading is prepended to existing roadmap preamble prose; a blank
|
|
221
|
+
heading leaves it unchanged. Saving generates the normal roadmap output without a
|
|
222
|
+
separate outline file. The project must already be initialized with `slicer init`.
|
|
223
|
+
|
|
224
|
+
The main TUI screen keeps common shortcuts visible below the status and feedback
|
|
225
|
+
lines: pane switching, editing, adding, starting/completing items, search, filters,
|
|
226
|
+
show all, jump, movement, help, and quit. Hints use one row when they fit or two at
|
|
227
|
+
80 columns, and stay visible after actions. These are fixed defaults; `?` opens
|
|
228
|
+
the complete shortcut list. Prompts and overlays show their own instructions.
|
|
229
|
+
|
|
230
|
+
The TUI initially hides the project's configured done status. View controls:
|
|
231
|
+
|
|
232
|
+
| Key | Action |
|
|
233
|
+
|---|---|
|
|
234
|
+
| `/` | Search IDs, full titles, and short titles as you type; Enter accepts, Esc cancels |
|
|
235
|
+
| `f` | Filter by status, tree, pass, importance, and urgency |
|
|
236
|
+
| `c` | Clear search and all filters, including the default hide-done filter |
|
|
237
|
+
| `g` | Jump to an ID; hidden targets are revealed by clearing search and filters |
|
|
238
|
+
| `J` / `K` | Reorder the selected item down / up |
|
|
239
|
+
| `T` | Move the selected item to the top |
|
|
240
|
+
| `M` | Move the selected item to a numbered position |
|
|
241
|
+
| `?` | Open help; arrows or `j/k` scroll, `?` or Esc closes |
|
|
242
|
+
|
|
243
|
+
In the filter panel, arrows or `j/k` navigate, Space toggles choices, Enter applies,
|
|
244
|
+
and Esc cancels. Each group offers Any; tree and pass also offer `(none)`. Multiple
|
|
245
|
+
choices within a group match any selected value; different groups must all match.
|
|
246
|
+
Importance and urgency use the item's assigned values (1–3), not inherited priority.
|
|
247
|
+
Search is case-insensitive literal text and combines with the filters.
|
|
248
|
+
|
|
249
|
+
The status line shows matching/total item counts and active restrictions. Roadmap
|
|
250
|
+
prose stays accessible below the items and is excluded from those counts. Filters
|
|
251
|
+
last only for this session. `J/K` reorder down/up, `T` moves to the top and `M` moves to
|
|
252
|
+
a numbered position; reordering requires clearing all restrictions with `c`. Filtering
|
|
253
|
+
itself preserves queue order.
|
|
254
|
+
|
|
255
|
+
Queue and Details headings mark the focused pane with `>`. Focused selections use
|
|
256
|
+
reverse/bold; inactive selections retain a marker and bold text. Queue rows show
|
|
257
|
+
`P:22`-style base priority scores (importance × 10 + urgency); an axis of 3 emphasizes
|
|
258
|
+
the score without reordering items. The detail pane retains the score and quadrant.
|
|
259
|
+
|
|
260
|
+
When supported, cyan marks headings/started work, green marks done/success, yellow
|
|
261
|
+
marks parked/blocked work and high priority, and red marks errors. Labels and `!`
|
|
262
|
+
blocked markers remain visible without color. Feedback uses `OK:`, `Error:`, and
|
|
263
|
+
`Info:` prefixes; unchanged actions and cancellations are informational. Set
|
|
264
|
+
`NO_COLOR=1` for monochrome; unsupported terminals also fall back automatically.
|
|
265
|
+
Below 80 columns or 10 rows, the TUI shows a resize prompt and preserves the session.
|
|
266
|
+
|
|
267
|
+
Every command except the interactive `tui`/`ui` takes `--json`, including the failures — an agent calls `slicer next
|
|
268
|
+
--json` rather than parsing markdown, and reads `{"error": {"code": ...}}` rather than
|
|
269
|
+
prose. Exit codes: `0` fine, `1` drift or a failed check, `2` usage, validation, or nothing to do, `3` internal or state (`corrupt`, `locked`, `io`, `config`, `schema_too_new`).
|
|
270
|
+
See [docs/agents.md](docs/agents.md).
|
|
271
|
+
|
|
272
|
+
Every command that changes state — `add`, `set`, `start`, `done`, `move`, `sort`, `promote`,
|
|
273
|
+
`edit`, `note`, `remove`, `park`, `unpark`, `import`, `migrate`, and the `prose` edits — takes `--render`
|
|
274
|
+
to regenerate `.slicer/render/` in the same step, so a mutation and its render are one
|
|
275
|
+
command. By default the change is saved first and rendered after; add `--strict` to require
|
|
276
|
+
the render to succeed first, so a change that cannot be rendered is rolled back rather than
|
|
277
|
+
landed (this is how `done --render` already behaves). The agent loop passes
|
|
278
|
+
`--render --strict` on `start` and on slice edits. `done` stays `--render`.
|
|
279
|
+
|
|
280
|
+
Items carry an Eisenhower-style priority: an `--importance` and an `--urgency` (each 1–3),
|
|
281
|
+
combined into a score (importance leads). A blocker of a critical item inherits its
|
|
282
|
+
priority, so `slicer next` and `slicer list --sort score` surface the blockers of
|
|
283
|
+
important work first, while the stored queue order stays whatever `move` set.
|
|
284
|
+
|
|
285
|
+
**slicer never commits, pushes or tags.** `git` access is allowlisted to
|
|
286
|
+
`rev-parse`, `status`, `log`, `mv`, `ls-files`, and the read-only queries
|
|
287
|
+
`worktree list --porcelain`, `branch --all`, and `config --get user.name`. `start` uses
|
|
288
|
+
the branch and worktree queries to warn when another checkout already refers to the slice;
|
|
289
|
+
the exit code does not change, and
|
|
290
|
+
`next` stays silent. Writing subcommands cannot be reached from the code at all.
|
|
291
|
+
|
|
292
|
+
### Batch changes
|
|
293
|
+
|
|
294
|
+
`done`, `start`, `release`, `park`, `unpark`, and `set` accept multiple IDs.
|
|
295
|
+
For example, `slicer set S01 S02 --urgency 3 --render` applies the same fields to
|
|
296
|
+
both items. Use `slicer done -` to read whitespace-separated IDs from stdin.
|
|
297
|
+
See [batch changes](docs/getting-started.md#batch-changes) for validation and output rules.
|
|
298
|
+
|
|
299
|
+
## What lives in `.slicer/`
|
|
300
|
+
|
|
301
|
+
```
|
|
302
|
+
config.json paths, statuses, fields, templates, sync targets
|
|
303
|
+
index.json the ordered queue plus roadmap prose (preamble, goals, non-goals, epilogue)
|
|
304
|
+
slices/<ID>.json one open slice: title, lead, sections (ordered list)
|
|
305
|
+
slices/done/<ID>.json finished slices
|
|
306
|
+
slices/retired/<ID>.json obsolete slices, with the reason on the item
|
|
307
|
+
templates/*.md render templates, yours to edit
|
|
308
|
+
render/ GENERATED - ROADMAP.md, ROADMAP.html (browser-viewable), and one file per slice
|
|
309
|
+
log.jsonl append-only history of status changes
|
|
310
|
+
.gitattributes union-merges log.jsonl, and keeps generated render/ on merge (see below)
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Sections are an ordered **list**, not a map: real slices carry headings no schema names,
|
|
314
|
+
sometimes more than once, and their order is part of the document.
|
|
315
|
+
|
|
316
|
+
Landing work on parallel branches touches these files: `log.jsonl` is append-only and
|
|
317
|
+
union-merges automatically (via the generated `.gitattributes`), so both sides' entries
|
|
318
|
+
survive without a conflict. `index.json` is the source of truth — a genuine overlap there is
|
|
319
|
+
yours to resolve. Anything under `render/` is a projection of `index.json`, so after resolving
|
|
320
|
+
a merge just re-run `slicer render` (and `slicer check` will flag it if you forget) rather than
|
|
321
|
+
merging the generated markdown by hand.
|
|
322
|
+
|
|
323
|
+
The `.gitattributes` also points `render/` at a `slicer-generated` merge driver that keeps the
|
|
324
|
+
current branch's copy instead of writing conflict markers — but a driver name only resolves
|
|
325
|
+
once the clone defines it. Run `slicer setup-git` to print the two lines (or `slicer setup-git
|
|
326
|
+
| sh` to apply them), once per clone — slicer's git allowlist cannot run `git config` for you:
|
|
327
|
+
|
|
328
|
+
```sh
|
|
329
|
+
git config merge.slicer-generated.name "keep the current branch's generated files"
|
|
330
|
+
git config merge.slicer-generated.driver true
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
Either way, re-run `slicer render` after resolving `index.json` so the kept files match it.
|
|
334
|
+
|
|
335
|
+
The scope boundary is a separate field on each slice. It renders after metadata and
|
|
336
|
+
before sections, so section edits cannot remove it. Use `slicer edit ID --boundary`
|
|
337
|
+
with `--text`, `--file`, `--stdin`, or the editor to change the full paragraph. Empty
|
|
338
|
+
text clears it. `promote --boundary TEXT` overrides the source/default boundary.
|
|
339
|
+
|
|
340
|
+
## Removing an item
|
|
341
|
+
|
|
342
|
+
Removal is two different acts, so `remove` has two modes.
|
|
343
|
+
|
|
344
|
+
`remove ID --reason "superseded by S30"` **retires** it: the status becomes `retired`, the
|
|
345
|
+
slice moves to `.slicer/slices/retired/`, and the row keeps rendering with the reason
|
|
346
|
+
beside it. The id stays claimed. This is for something that existed and was cited — a
|
|
347
|
+
commit or a review that names it must still resolve to something that explains itself.
|
|
348
|
+
|
|
349
|
+
`remove ID --purge` **deletes** it: the item and its slice file go. This is for a mistyped
|
|
350
|
+
`add`. The id comes back only when it was the most recently allocated *and* no commit
|
|
351
|
+
subject mentions it — that is undoing an allocation, not reusing an identifier. Any
|
|
352
|
+
earlier id stays burned, and the output says which happened and why.
|
|
353
|
+
|
|
354
|
+
Both refuse when another item depends on it, or when it is `done`; `--force` overrides and
|
|
355
|
+
names the rule it overrode. After a forced purge, `slicer check` reports the dangling
|
|
356
|
+
dependency it left behind. Add `--dry-run` to either mode to preview the outcome first — the
|
|
357
|
+
dependents that would dangle and whether a purge would free or burn the id — without writing;
|
|
358
|
+
it turns that surprise into a decision.
|
|
359
|
+
|
|
360
|
+
Retiring needs a status to move into. A tracking directory created before `remove` existed
|
|
361
|
+
gains a `retired` status automatically on load — only that one key, so a project that
|
|
362
|
+
dropped some other status does not get it back.
|
|
363
|
+
|
|
364
|
+
## Roadmap prose
|
|
365
|
+
|
|
366
|
+
A roadmap carries text that belongs to no slice: an opening note, a heading and prose
|
|
367
|
+
around each pass group, and a closing section. `slicer prose` addresses those blocks:
|
|
368
|
+
|
|
369
|
+
```
|
|
370
|
+
preamble the opening note
|
|
371
|
+
goals project goals (see below)
|
|
372
|
+
non_goals project non-goals (see below)
|
|
373
|
+
pass.<key>.heading the group's markdown heading
|
|
374
|
+
pass.<key>.intro prose above the group's table
|
|
375
|
+
pass.<key>.outro prose below it
|
|
376
|
+
epilogue the closing section
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
`slicer prose list` names every block in the order it renders. Both `edit` and `prose edit`
|
|
380
|
+
take exactly one of `--text`, `--file`, or `--stdin`, or open `$EDITOR` when none is
|
|
381
|
+
supplied. In replacement mode, `--text` preserves the argument exactly, including
|
|
382
|
+
newlines, and `--text ""` clears the body. Section editing also accepts `--append` with an
|
|
383
|
+
explicit source: it joins old and new text with one blank line, removing boundary
|
|
384
|
+
newline characters. Empty appended content leaves the body unchanged.
|
|
385
|
+
For example, `slicer prose edit preamble --text "Current priorities"` replaces the preamble.
|
|
386
|
+
A pass group is opened with `prose add-pass 6 --heading
|
|
387
|
+
"# ..."` and closed with `drop-pass`, which refuses while any item is still filed under
|
|
388
|
+
it. Items are filed with `slicer add --pass 6` or moved with `slicer set <id> --pass 6`.
|
|
389
|
+
|
|
390
|
+
A declared pass renders even with no items yet, so a group can be opened before its first
|
|
391
|
+
slice exists.
|
|
392
|
+
|
|
393
|
+
## Goals and non-goals
|
|
394
|
+
|
|
395
|
+
The backlog says what is queued; **goals and non-goals** say what the project is *for*, so
|
|
396
|
+
humans and AI agents can judge what belongs on the backlog at all. They are two roadmap
|
|
397
|
+
prose blocks (`goals`, `non_goals`), edited like any other prose and rendered near the top
|
|
398
|
+
of `ROADMAP.md`:
|
|
399
|
+
|
|
400
|
+
```
|
|
401
|
+
slicer goals print both, or slicer goals --json for agents
|
|
402
|
+
slicer prose edit goals record or revise them (--text/--file/--stdin/$EDITOR)
|
|
403
|
+
slicer prose edit non_goals
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
`slicer check` keeps the rendered copy current. Set direction with the owner — do not
|
|
407
|
+
infer it from the backlog.
|
|
408
|
+
|
|
409
|
+
slicer's own goals and non-goals: run `slicer goals`, or read them at the top of
|
|
410
|
+
[the roadmap](.slicer/render/ROADMAP.md). In short, slicer is a small, dependency-light,
|
|
411
|
+
file-based store for a project's roadmap, goals, and issues — canonical JSON that humans
|
|
412
|
+
and AI agents plan from, projected deterministically to markdown — and is *not* a
|
|
413
|
+
real-time, multi-user collaboration tool (coordination happens through git).
|
|
414
|
+
|
|
415
|
+
## Configuration
|
|
416
|
+
|
|
417
|
+
Everything project-specific is in `.slicer/config.json` — status vocabulary and how each
|
|
418
|
+
one renders, the section list `promote` seeds, the scope-boundary marker, which flags
|
|
419
|
+
exclude an item from derived pointers, and the `sync` targets. Nothing is compiled into
|
|
420
|
+
the tool, so slicer works on a repo with no review protocol at all.
|
|
421
|
+
|
|
422
|
+
Every key, its default, and which ones are unsafe to change once items exist:
|
|
423
|
+
[docs/configuration.md](docs/configuration.md). Two to know up front — `id.prefix` and
|
|
424
|
+
`id.width` can change before the first item exists. After allocation the index owns the
|
|
425
|
+
scheme; changing the config does not renumber items, and a mismatch fails `check`.
|
|
426
|
+
|
|
427
|
+
## Tests
|
|
428
|
+
|
|
429
|
+
```sh
|
|
430
|
+
python3 -m unittest discover -s tests -t tests
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
No install step and no dependencies — the suite puts `src/` on `sys.path` itself.
|
|
434
|
+
|
|
435
|
+
`tests/fixtures/legacy/` is a synthetic 14-slice tree for a project that does not
|
|
436
|
+
exist. It is shaped to exercise the awkward parts of the legacy format — a middot
|
|
437
|
+
inside a findings value, singular and plural tree keys, a collective trees cell,
|
|
438
|
+
headings no schema names, prose between the tables — and the suite proves every file
|
|
439
|
+
round-trips through the parser byte for byte.
|
|
440
|
+
|
|
441
|
+
Set `SLICER_LEGACY_TREE=/path/to/docs/slices` to additionally prove the migrator
|
|
442
|
+
against a live markdown tree of your own. That test is skipped when the variable is
|
|
443
|
+
unset, and it is the only way to exercise the migrator against real, messily
|
|
444
|
+
hand-written markdown — worth running before changing `legacy.py` or `migrator.py`.
|
|
445
|
+
|
|
446
|
+
## Status
|
|
447
|
+
|
|
448
|
+
slicer manages its own roadmap: `.slicer/` in this repository is a worked
|
|
449
|
+
example you can read, and `.slicer/render/ROADMAP.md` is what it renders to. Run
|
|
450
|
+
`slicer --version` for the installed version, and see the [changelog](CHANGELOG.md).
|
|
451
|
+
|
|
452
|
+
[docs/getting-started.md](docs/getting-started.md) is the walkthrough, and
|
|
453
|
+
[docs/agents.md](docs/agents.md) covers driving slicer from an agent.
|
|
454
|
+
[ARCHITECTURE.md](ARCHITECTURE.md) explains the layering and the invariants.
|
|
455
|
+
[AGENTS.md](AGENTS.md) has the commands and the house style.
|
|
456
|
+
|
|
457
|
+
Apache-2.0. Stdlib Python, no dependencies, and none planned.
|