commitship-cli 0.1.0__py3-none-any.whl
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.
- commitship_cli-0.1.0.dist-info/METADATA +394 -0
- commitship_cli-0.1.0.dist-info/RECORD +18 -0
- commitship_cli-0.1.0.dist-info/WHEEL +5 -0
- commitship_cli-0.1.0.dist-info/entry_points.txt +2 -0
- commitship_cli-0.1.0.dist-info/licenses/COMMERCIAL.md +28 -0
- commitship_cli-0.1.0.dist-info/licenses/LICENSE +662 -0
- commitship_cli-0.1.0.dist-info/top_level.txt +1 -0
- ship/__init__.py +13 -0
- ship/__main__.py +3 -0
- ship/cli.py +143 -0
- ship/eyes.py +95 -0
- ship/law.py +175 -0
- ship/measure.py +432 -0
- ship/mechanical.py +386 -0
- ship/pipeline.py +384 -0
- ship/say.c +115 -0
- ship/say.py +134 -0
- ship/ship.c +122 -0
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: commitship-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: One word, one safely pushed commit. Two machine-authored branchless kernels decide how far a change may travel and what its subject may claim: zero tokens, no API key, nothing leaves your machine but the push.
|
|
5
|
+
Author-email: Devieswar Kancheti <devkancheti4@gmail.com>
|
|
6
|
+
Maintainer-email: Devieswar Kancheti <devkancheti4@gmail.com>
|
|
7
|
+
License-Expression: AGPL-3.0-or-later
|
|
8
|
+
Project-URL: Homepage, https://github.com/devkancheti4-design/ship
|
|
9
|
+
Project-URL: Repository, https://github.com/devkancheti4-design/ship
|
|
10
|
+
Project-URL: Issues, https://github.com/devkancheti4-design/ship/issues
|
|
11
|
+
Keywords: git,commit,commit-message,conventional-commits,cli,branchless,local-first,zero-token,offline,ollama
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Natural Language :: English
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
23
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
24
|
+
Classifier: Topic :: Utilities
|
|
25
|
+
Requires-Python: >=3.10
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
License-File: COMMERCIAL.md
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
31
|
+
Requires-Dist: build; extra == "dev"
|
|
32
|
+
Requires-Dist: twine; extra == "dev"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# ship
|
|
36
|
+
|
|
37
|
+
<p align="center">
|
|
38
|
+
<img src="https://raw.githubusercontent.com/devkancheti4-design/ship/main/docs/media/old-vs-new.gif" width="960" alt="The same folder pushed twice, for real: first with five git commands and a commit message typed by hand, then with the single line ship ../new.git, which measures, summarises, commits and pushes it.">
|
|
39
|
+
</p>
|
|
40
|
+
|
|
41
|
+
**One word, one safely pushed commit.** Type `ship` and your change is
|
|
42
|
+
staged, summarised, committed and pushed, or refused with the reason. No
|
|
43
|
+
config, no model, no API key, nothing leaves your machine but the push. Two
|
|
44
|
+
machine-authored, exhaustively proved kernels decide how far the change may
|
|
45
|
+
travel and what its subject line may claim.
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install commitship-cli
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The package on PyPI is `commitship-cli`; the command it installs is `ship`. If that command
|
|
52
|
+
is then "not recognized" (Windows, when pip's `Scripts` folder is not on
|
|
53
|
+
PATH), run it as `python -m ship` instead of `ship` — every command below
|
|
54
|
+
works both ways. Git must be installed too, since everything ship does is
|
|
55
|
+
git. To install the latest `main` rather than a release:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
python -m pip install https://github.com/devkancheti4-design/ship/archive/refs/heads/main.zip
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
ship # stage, summarise, commit, push, as far as the law allows
|
|
63
|
+
ship "why I did this" # your words become the subject's phrase, verbatim
|
|
64
|
+
ship -i # show the ruling, then ask y/N before anything is written
|
|
65
|
+
ship -n # dry run: measure and rule, write nothing
|
|
66
|
+
ship https://github.com/you/repo.git # a plain folder: create the repo, set origin, ship it
|
|
67
|
+
ship --eyes ollama # let a local model write the prose instead
|
|
68
|
+
ship selfcheck # re-derive both laws over all 256 inputs, in Python and in C
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
<p align="center">
|
|
72
|
+
<img src="https://raw.githubusercontent.com/devkancheti4-design/ship/main/docs/media/one-word.gif" width="960" alt="A plain terminal: two files are typed in, the word ship is typed, and the change is measured, summarised, committed and pushed to GitHub as feat(billing): add price_after_discount.">
|
|
73
|
+
</p>
|
|
74
|
+
|
|
75
|
+
To have the bare word `ship` on PATH on Windows, either install with
|
|
76
|
+
`pipx install https://github.com/devkancheti4-design/ship/archive/refs/heads/main.zip`
|
|
77
|
+
or add the folder that `python -m pip show -f commitship-cli` lists for `ship.exe` to PATH.
|
|
78
|
+
|
|
79
|
+
## Why this exists
|
|
80
|
+
|
|
81
|
+
Every AI commit tool I looked at does three things I do not want done to my
|
|
82
|
+
history. It sends the diff to someone else's API, so it needs a key, costs
|
|
83
|
+
tokens, and the diff leaves the machine. It writes a fluent message that
|
|
84
|
+
nobody can audit, so the same diff gets a different message on a different
|
|
85
|
+
day and the message can claim a fix the diff does not contain. And it never
|
|
86
|
+
refuses: it will stage a leaked key, write it a nice subject, and push.
|
|
87
|
+
|
|
88
|
+
`ship` is built the other way round. Nothing is inferred by anything that
|
|
89
|
+
cannot be audited: eight yes/no measurements become a byte, a 20-instruction
|
|
90
|
+
branchless kernel turns the byte into how far the change may go, and a
|
|
91
|
+
second byte through an 8-instruction kernel decides what the subject may
|
|
92
|
+
claim, with the nouns copied from the diff. Refusal is a first-class outcome,
|
|
93
|
+
not an error. And the two kernels come with exhaustive self-checks over all
|
|
94
|
+
256 inputs that you run yourself, offline, in under a second.
|
|
95
|
+
|
|
96
|
+
## Safety first
|
|
97
|
+
|
|
98
|
+
The report prints the ruling **before** the first git write, so you see what
|
|
99
|
+
is about to happen, and `ship -i` stops there and asks:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
ship byte 0x81 DIRTY FORWARD act PUSH
|
|
103
|
+
DIRTY 1 2 paths differ from HEAD
|
|
104
|
+
SECRET 0 no credential shape in added lines or staged paths
|
|
105
|
+
...
|
|
106
|
+
FORWARD 1 origin/feature is an ancestor of HEAD: fast-forward
|
|
107
|
+
-> will stage, commit and push. Continue? [y/N]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Without `-i`, `ship` acts on the ruling at once. Either way these hold:
|
|
111
|
+
|
|
112
|
+
- **A leaked secret, a conflict marker, or a bulk change writes nothing.**
|
|
113
|
+
Not the index, not history, not the remote. The tree is byte-identical
|
|
114
|
+
afterwards and the report names the file and the shape, never the secret.
|
|
115
|
+
- **`main` is never pushed.** Neither is a red test suite, a diverged
|
|
116
|
+
branch, or a detached HEAD. The commit is made as a local checkpoint and
|
|
117
|
+
the push is left to you. `ship` never runs `--force`, never rebases, never
|
|
118
|
+
merges.
|
|
119
|
+
- **No commit under a message the eyes did not write.** If the summary
|
|
120
|
+
cannot be produced, the change is staged and `.git/SHIP_MSG` explains.
|
|
121
|
+
- **Exactly the measured change is staged.** Files that appear during the
|
|
122
|
+
test run are not part of the change that was ruled on.
|
|
123
|
+
|
|
124
|
+
<p align="center">
|
|
125
|
+
<img src="https://raw.githubusercontent.com/devkancheti4-design/ship/main/docs/media/refused.gif" width="960" alt="An AWS key is written into .env; ship refuses with act NONE, reports SECRET at .env line 1, and git status shows the tree untouched.">
|
|
126
|
+
</p>
|
|
127
|
+
|
|
128
|
+
## Zero tokens, zero keys, 100% private
|
|
129
|
+
|
|
130
|
+
By default there is no model at all. The summary is written by measurement:
|
|
131
|
+
the SAY law names the kind (`feat`, `fix`, `test`, `docs`, `build`, `style`,
|
|
132
|
+
`revert`, or plain), and the definition names, paths and scope come straight
|
|
133
|
+
from the diff. Zero tokens, the same message for the same change every time,
|
|
134
|
+
0 to 85 ms. If you want fluent prose instead, `--eyes ollama` asks whatever
|
|
135
|
+
Ollama is already running on your machine, still with nothing leaving it.
|
|
136
|
+
The only network `ship` ever touches is your own remote: one `fetch` to
|
|
137
|
+
measure whether the push would fast-forward, and the push itself.
|
|
138
|
+
|
|
139
|
+
## Ultra-lightweight
|
|
140
|
+
|
|
141
|
+
| | |
|
|
142
|
+
|---|---|
|
|
143
|
+
| wheel | 54 kB |
|
|
144
|
+
| runtime dependencies | 0 (git and the Python standard library) |
|
|
145
|
+
| source | 1,994 lines including both kernels and their C self-checks |
|
|
146
|
+
| the two kernels | 20 and 8 machine instructions, no branches |
|
|
147
|
+
| a full run | 0.1 to 0.8 s wall on a small repo, test suite included |
|
|
148
|
+
|
|
149
|
+
## How it works
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
working tree ──► measure 8 bits ──► ship(byte) → act ◄ SHIP law: how far may it travel 20 instructions, 0 branches
|
|
153
|
+
──► measure 8 bits ──► say(byte) → kind ◄ SAY law: what may the subject claim 8 instructions, 0 branches
|
|
154
|
+
──► render <kind>(<scope>): <nouns> ◄ the eyes: measurement, 0 tokens
|
|
155
|
+
──► run git exactly as far as the act says, then stop and say why
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The act is a ladder, and the change climbs it only as far as the SHIP law rules:
|
|
159
|
+
|
|
160
|
+
| act | what happens | who can undo it |
|
|
161
|
+
|---|---|---|
|
|
162
|
+
| **3 PUSH** | stage, commit, push | nobody: it is on the remote |
|
|
163
|
+
| **2 COMMIT** | stage, commit; stop before the network | `git reset --soft HEAD~1` |
|
|
164
|
+
| **1 STAGE** | stage, write `.git/SHIP_MSG`; stop before history | `git reset` |
|
|
165
|
+
| **0 NONE** | write nothing, not even the index | nothing to undo |
|
|
166
|
+
|
|
167
|
+
### The SHIP byte: how far
|
|
168
|
+
|
|
169
|
+
Every bit is measured, none is an opinion, and all are measured before the
|
|
170
|
+
first git write. What counts as a secret shape, a protected branch or a bulk
|
|
171
|
+
change lives in the measurement ([measure.py](https://github.com/devkancheti4-design/ship/blob/main/src/ship/measure.py)), never in
|
|
172
|
+
the law.
|
|
173
|
+
|
|
174
|
+
| bit | name | tier | set when |
|
|
175
|
+
|---|---|---|---|
|
|
176
|
+
| 0 | DIRTY | gate | the working tree differs from HEAD (modified, deleted, or untracked non-ignored files) |
|
|
177
|
+
| 1 | SECRET | veto | an added line matches a credential shape (private-key header, AWS/GitHub/Slack/Google/`sk-` keys, bearer tokens, `PASSWORD = "…"`), or a staged path matches `.env*`, `*.pem`, `id_rsa*`, `*.key`, `*.p12`, `*.pfx` (`.example`/`.sample`/`.template` exempt) |
|
|
178
|
+
| 2 | CONFLICT | veto | `<<<<<<<`/`>>>>>>>` markers in a changed file, unmerged paths, or MERGE_HEAD / REBASE_HEAD / CHERRY_PICK_HEAD present |
|
|
179
|
+
| 3 | BULK | veto | more than 50 paths, any file over 5 MB, or an untracked binary |
|
|
180
|
+
| 4 | BLIND | eyes | no usable summary: empty, subject over 72 characters, diff syntax in the text, or the eyes did not answer |
|
|
181
|
+
| 5 | RED | net | the repository's own check exists and exited non-zero (pytest, `npm test`, `cargo test`, `go test`, `make test`; auto-detected) |
|
|
182
|
+
| 6 | PROTECTED | net | branch is `main`, `master`, `release/*`, or HEAD is detached |
|
|
183
|
+
| 7 | FORWARD | gate | a remote exists and, after `git fetch`, the upstream is an ancestor of HEAD or does not exist yet |
|
|
184
|
+
|
|
185
|
+
**Fail closed.** Gates (DIRTY, FORWARD) are set only by a measurement that
|
|
186
|
+
succeeded. Hazards are set by a positive finding *and* by any measurement
|
|
187
|
+
that could not complete. The law never receives "unknown".
|
|
188
|
+
|
|
189
|
+
### The SAY byte: what the subject may claim
|
|
190
|
+
|
|
191
|
+
The eyes are measurement too ([mechanical.py](https://github.com/devkancheti4-design/ship/blob/main/src/ship/mechanical.py)).
|
|
192
|
+
Eight facts about the change become a byte; the SAY law turns the byte into
|
|
193
|
+
the KIND of claim the subject line may make; the body supplies the nouns.
|
|
194
|
+
|
|
195
|
+
| bit | name | tier | set when |
|
|
196
|
+
|---|---|---|---|
|
|
197
|
+
| 0 | INVERSE | shape | the change's patch, reversed, is byte-identical to one of the last 20 commits |
|
|
198
|
+
| 1 | BLANK | shape | the diff has hunks, none survive `-w --ignore-blank-lines`, no untracked file has content |
|
|
199
|
+
| 2 | TESTSONLY | shape | every changed path is a test (by directory or name) |
|
|
200
|
+
| 3 | DOCSONLY | shape | every changed path is documentation |
|
|
201
|
+
| 4 | DEPSONLY | shape | every changed path is a manifest, lockfile, build or CI file |
|
|
202
|
+
| 5 | NEWDEF | content | a code path gained a definition whose name no removed definition had |
|
|
203
|
+
| 6 | GUARD | content | a code path gained a guard (raise, throw, assert, null check, `return err`) inside a definition that existed before; moved or reindented lines do not count |
|
|
204
|
+
| 7 | FOCUSED | gate | the code paths number 1 to 3 and share one top-level directory |
|
|
205
|
+
|
|
206
|
+
| kind | subject | when |
|
|
207
|
+
|---|---|---|
|
|
208
|
+
| 0 revert | `revert: <that commit's subject>` + `This reverts commit <sha>.` | INVERSE |
|
|
209
|
+
| 1 style | `style: reformat <paths>` | BLANK |
|
|
210
|
+
| 2 test | `test: add <test names>` | TESTSONLY |
|
|
211
|
+
| 3 docs | `docs: <verb> <paths>` | DOCSONLY |
|
|
212
|
+
| 4 build | `build: <verb> <files>` | DEPSONLY |
|
|
213
|
+
| 5 feat | `feat(<scope>): add <new definitions>` | NEWDEF and FOCUSED |
|
|
214
|
+
| 6 fix | `fix(<scope>): guard <definitions>` | GUARD and FOCUSED |
|
|
215
|
+
| 7 plain | `<verb> <paths>` or `<n> files across <m> directories` | nothing above: describe, never diagnose |
|
|
216
|
+
|
|
217
|
+
The verb follows its object: `add` only when every named path is a new
|
|
218
|
+
file, `remove` only when every one is deleted, `update` otherwise. A hint
|
|
219
|
+
on the command line replaces the phrase, never the type:
|
|
220
|
+
`ship "validate the discount rate"` on that same change gives
|
|
221
|
+
`feat(billing): validate the discount rate`. The hint is never an input to
|
|
222
|
+
the law: the author's words are opinion, and the law reads only
|
|
223
|
+
measurements. The subject is clipped to 72 characters at a word boundary,
|
|
224
|
+
so the SHIP law's BLIND can only fire when git itself fails.
|
|
225
|
+
|
|
226
|
+
### The laws
|
|
227
|
+
|
|
228
|
+
[`ship.c`](https://github.com/devkancheti4-design/ship/blob/main/src/ship/ship.c) and [`say.c`](https://github.com/devkancheti4-design/ship/blob/main/src/ship/say.c) were authored by
|
|
229
|
+
search and are vendored verbatim; [`law.py`](https://github.com/devkancheti4-design/ship/blob/main/src/ship/law.py) and
|
|
230
|
+
[`say.py`](https://github.com/devkancheti4-design/ship/blob/main/src/ship/say.py) carry the same lane expressions character for
|
|
231
|
+
character, and a test fails if they drift. Both are ladders: tiers nest, so
|
|
232
|
+
they are bits of one mask in tier order, and `ctz` returns the answer with
|
|
233
|
+
no encoding step.
|
|
234
|
+
|
|
235
|
+
```
|
|
236
|
+
SHIP R1 a veto is absolute SECRET | CONFLICT | BULK → NONE, whatever else is set
|
|
237
|
+
R2 DIRTY gates everything clean tree → NONE; never an empty commit
|
|
238
|
+
R3 no history without eyes BLIND → STAGE at most
|
|
239
|
+
R4 no network without ff/green RED | PROTECTED | ¬FORWARD → COMMIT at most
|
|
240
|
+
R5 monotone a hazard never moves a change further; a gate never moves it back
|
|
241
|
+
|
|
242
|
+
SAY R1 shape outranks content an undo, a reformat, tests, docs, deps: described as that
|
|
243
|
+
R2 no diagnosis without focus feat and fix need FOCUSED; a diffuse change is plain
|
|
244
|
+
R3 feat outranks fix a new definition with a guard inside is a feature
|
|
245
|
+
R4 silence is the floor no evidence → plain; the law never invents a claim
|
|
246
|
+
R5 monotone more evidence never yields a vaguer message
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Both partitions were derived in closed form before synthesis and are
|
|
250
|
+
matched exactly: SHIP pushes on **1 input of 256** (0x81), commits on 7,
|
|
251
|
+
stages on 8, refuses on 240; SAY splits **128/64/32/16/8/2/1/5**. A kernel
|
|
252
|
+
that always refuses, or always says plain, passes every R and is rejected
|
|
253
|
+
by the counts. Run the proofs yourself, offline, in under a second:
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
ship selfcheck
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
```
|
|
260
|
+
SHIP law (how far the change travels), pure-Python reference over all 256 inputs:
|
|
261
|
+
travelled further than allowed 0
|
|
262
|
+
refused when it must not 0
|
|
263
|
+
R1 veto absolute 0
|
|
264
|
+
R2 DIRTY gates everything 0
|
|
265
|
+
R3 no history without eyes 0
|
|
266
|
+
R4 no network without ff/green 0
|
|
267
|
+
R5 monotone 0
|
|
268
|
+
partition PUSH 1 COMMIT 7 STAGE 8 NONE 240
|
|
269
|
+
counts 1/7/8/240 exact
|
|
270
|
+
the eight situations 0 violations
|
|
271
|
+
|
|
272
|
+
TOTAL 256 inputs 0 violations
|
|
273
|
+
|
|
274
|
+
SAY law (what the subject may claim), pure-Python reference over all 256 inputs:
|
|
275
|
+
said something vaguer than allowed 0
|
|
276
|
+
claimed more than the evidence 0
|
|
277
|
+
R1 shape outranks content 0
|
|
278
|
+
R2 no diagnosis without focus 0
|
|
279
|
+
R3 feat outranks fix 0
|
|
280
|
+
R4 silence is the floor 0
|
|
281
|
+
R5 monotone 0
|
|
282
|
+
partition 128/64/32/16/8/2/1/5
|
|
283
|
+
counts 128/64/32/16/8/2/1/5 exact
|
|
284
|
+
the nine situations 0 violations
|
|
285
|
+
|
|
286
|
+
TOTAL 256 inputs 0 violations
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Each check runs twice: the pure-Python reference, and the vendored C
|
|
290
|
+
compiled with your `cc`, each against a branchy oracle that shares no
|
|
291
|
+
expression with the kernel. Emitted for arm64 by clang `-O2`: **ship() is
|
|
292
|
+
20 instructions including `ret`, say() is 8; 0 branches, 0 compares, 0
|
|
293
|
+
selects, 0 loads** in either. The authoring prompts are
|
|
294
|
+
[SHIP_LAW_PROMPT.md](https://github.com/devkancheti4-design/ship/blob/main/SHIP_LAW_PROMPT.md) and [SAY_LAW_PROMPT.md](https://github.com/devkancheti4-design/ship/blob/main/SAY_LAW_PROMPT.md).
|
|
295
|
+
|
|
296
|
+
### Measure only what the ruling depends on
|
|
297
|
+
|
|
298
|
+
SHIP bits are measured in cost order, and a bit is measured only while the
|
|
299
|
+
law's ruling still depends on it. That follows from R5: with the unmeasured
|
|
300
|
+
hazards assumed set and the unmeasured gates clear, the law gives a floor;
|
|
301
|
+
with the reverse, a ceiling; when they meet, nothing left to measure can
|
|
302
|
+
change the act. So a leaked key never wakes the eyes, a protected branch
|
|
303
|
+
never runs your test suite, and only the happy byte pays for everything.
|
|
304
|
+
The report names what was skipped:
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
unmeasured BLIND RED PROTECTED FORWARD (the ruling did not depend on them)
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
No if-statement in the body decides where the change goes, or what it is
|
|
311
|
+
called. The acts do.
|
|
312
|
+
|
|
313
|
+
## Measured, not promised
|
|
314
|
+
|
|
315
|
+
All runs 2026-09-08 in scratch repositories with a bare local remote (fetch
|
|
316
|
+
and push are real git, not the public network), Apple Silicon Mac.
|
|
317
|
+
Wall-clock times are the whole `ship` invocation.
|
|
318
|
+
|
|
319
|
+
**The SAY law as eyes** (the default), one change after another on one branch:
|
|
320
|
+
|
|
321
|
+
| change | SAY byte | subject written | eyes | wall |
|
|
322
|
+
|---|---|---|---|---|
|
|
323
|
+
| guard in an existing function, new `total`, two tests | `0xE0` | `feat(billing): add total` | 48 ms | 0.68 s |
|
|
324
|
+
| one new test function | `0x04` | `test: add test_zero_rate` | 59 ms | 0.69 s |
|
|
325
|
+
| reindent only | `0x82` | `style: reformat billing.py` | 121 ms | 0.75 s |
|
|
326
|
+
| that reindent undone by hand | `0x83` | `revert: style: reformat billing.py` | 35 ms | 0.67 s |
|
|
327
|
+
| `package-lock.json` alone | `0x10` | `build: add package-lock.json` | 0 ms | 0.65 s |
|
|
328
|
+
| a comment, with the hint "note the module purpose" | `0x80` | `note the module purpose` | 111 ms | 0.75 s |
|
|
329
|
+
|
|
330
|
+
Every subject matches the REQUIRED line for its situation in the SAY
|
|
331
|
+
prompt, and every message passed the SHIP law's BLIND check. The same
|
|
332
|
+
first change, with `--eyes ollama` and qwen2.5-coder:7b, took 7.9 s cold
|
|
333
|
+
and wrote "Validate discount rate and add total helper": longer, and not
|
|
334
|
+
wrong, but nothing in it is auditable.
|
|
335
|
+
|
|
336
|
+
**The SHIP law's situations**, run with the model as eyes earlier the same day:
|
|
337
|
+
|
|
338
|
+
| situation | SHIP byte | act | wall | what happened |
|
|
339
|
+
|---|---|---|---|---|
|
|
340
|
+
| the happy path (cold model) | `0x81` | PUSH | 7.9 s | staged 2, committed, pushed |
|
|
341
|
+
| the leaked key (`.env` with an AWS key) | `0x03` | NONE | 0.2 s | refused; eyes, check, fetch never run; tree byte-identical; exit 2 |
|
|
342
|
+
| straight to `main` | `0x41` | COMMIT | 0.6 s | committed locally; check and fetch never run; not pushed |
|
|
343
|
+
| the silent model | `0x91` | STAGE | 0.3 s | index holds the change, `.git/SHIP_MSG` explains; no commit |
|
|
344
|
+
| the diverged branch (remote 1 ahead) | `0x01` | COMMIT | 2.0 s | committed locally; never rebased, merged or forced |
|
|
345
|
+
|
|
346
|
+
The test suite (228 tests, hermetic git, a test double for the eyes)
|
|
347
|
+
builds every one of these in a real repository and checks the tree, the
|
|
348
|
+
index, the history, the remote and the message afterwards, plus: a hook
|
|
349
|
+
that rejects the commit is reported (exit 3), not hidden; a file the check
|
|
350
|
+
creates after measurement is never staged; a dry run writes nothing; eyes
|
|
351
|
+
that raise are BLIND, not a crash; the same change gets the same message.
|
|
352
|
+
|
|
353
|
+
```bash
|
|
354
|
+
.venv/bin/python -m pytest -q
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## Configuration (all optional)
|
|
358
|
+
|
|
359
|
+
| variable | default | meaning |
|
|
360
|
+
|---|---|---|
|
|
361
|
+
| `SHIP_EYES` | `law` | `law`: the SAY law and measurement, 0 tokens. `ollama`: a local model writes the prose |
|
|
362
|
+
| `OLLAMA_HOST` | `http://localhost:11434` | where the model lives, when asked for |
|
|
363
|
+
| `SHIP_MODEL` | first model Ollama lists | which model, when asked for |
|
|
364
|
+
| `SHIP_CONFIRM` | unset | `1`: always ask y/N before the first git write, as `-i` does |
|
|
365
|
+
| `SHIP_CHECK` | auto-detected | the check command; `none` disables |
|
|
366
|
+
| `SHIP_CHECK_TIMEOUT` | 600 | seconds before a check is RED for not answering |
|
|
367
|
+
| `SHIP_FETCH_TIMEOUT` | 60 | seconds before a fetch clears FORWARD |
|
|
368
|
+
|
|
369
|
+
Exit codes: `0` ran as far as ruled (including "nothing to record"), `2`
|
|
370
|
+
refused by a veto, `3` git itself failed at commit or push (a hook, an
|
|
371
|
+
identity, a rejected push: the report shows git's last line), `1` not a
|
|
372
|
+
repository.
|
|
373
|
+
|
|
374
|
+
## What ship does not decide
|
|
375
|
+
|
|
376
|
+
- **Which files.** The change is the whole working-tree delta or nothing.
|
|
377
|
+
Selecting a safe subset would be a deciding if-statement in the body.
|
|
378
|
+
- **The why.** A mechanical message describes what changed and never
|
|
379
|
+
explains motive. Your words on the command line are the phrase,
|
|
380
|
+
verbatim. Your `pre-commit` hooks still run inside `git commit`, and
|
|
381
|
+
their verdict is reported, not overridden.
|
|
382
|
+
- **Recovery.** On a diverged branch `ship` stops; fetching, rebasing and
|
|
383
|
+
forcing are yours. On a red check `ship` stops; repairing the tree is
|
|
384
|
+
another law's job.
|
|
385
|
+
|
|
386
|
+
## Status
|
|
387
|
+
|
|
388
|
+
Alpha. On PyPI as `commitship-cli`, source at
|
|
389
|
+
https://github.com/devkancheti4-design/ship. Python 3.10+ and any git from
|
|
390
|
+
the last several years (the test suite wants 2.28+ for `init -b`). No model,
|
|
391
|
+
no server, no account, no key. Ollama is used only if you ask for it.
|
|
392
|
+
|
|
393
|
+
Licensed AGPL-3.0-or-later, with a commercial option: see
|
|
394
|
+
[COMMERCIAL.md](https://github.com/devkancheti4-design/ship/blob/main/COMMERCIAL.md).
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
commitship_cli-0.1.0.dist-info/licenses/COMMERCIAL.md,sha256=m3m2yibBYj_SXm7WGmx9ZYf1NrofPhvDS_i8GY4pGkE,1316
|
|
2
|
+
commitship_cli-0.1.0.dist-info/licenses/LICENSE,sha256=jVa0BUaKrRH4erV2P5AeJ24I2WRv9chIGxditreJ6e0,34524
|
|
3
|
+
ship/__init__.py,sha256=m-ANkGn5XWUBX5xENGErJnOJ5D6MxdZsrLuLQohD6UM,631
|
|
4
|
+
ship/__main__.py,sha256=k1ocEWawweo1qCJWNFAAvyxz3tcY13dzvCenHszij30,48
|
|
5
|
+
ship/cli.py,sha256=hbIxfsNGFOz4-yEsMyLIbBU1QTemSzc8Wlo2t0px4eA,6803
|
|
6
|
+
ship/eyes.py,sha256=IZWD7uI1XVWS4Zv0NX43Bih561revE3GvelubLJbDNI,3284
|
|
7
|
+
ship/law.py,sha256=2XkxPRjymcui6Z8iy1MW5q-CIl5Fx0AmGT80WwJYPTU,6465
|
|
8
|
+
ship/measure.py,sha256=RB2HXvzwBNQHhRnhkCjnl-kr9UYssSsqGtZDtEOgw-w,18401
|
|
9
|
+
ship/mechanical.py,sha256=qs8UBixJaTrc4n9u4b88OIKhtD3U_0Uz4nTJPN2G0T4,16153
|
|
10
|
+
ship/pipeline.py,sha256=EU3aAMRNgsp2uGXnI83twA7dSYVoUR4rEgc1WXRb-jM,16376
|
|
11
|
+
ship/say.c,sha256=dzz1VCyTIU4c6a0R405Rt1lnMKigpLIYMiJrB6wGWUk,5398
|
|
12
|
+
ship/say.py,sha256=673w8RYW99MRQ-LZ-NgSvIXV52KcHehwn7TFbtAtznk,4789
|
|
13
|
+
ship/ship.c,sha256=HKp8-f9vNNDUVBHQb73z0svtAYbXxoFD3MjPvSdBso8,5489
|
|
14
|
+
commitship_cli-0.1.0.dist-info/METADATA,sha256=IGYqX7zekHyc73d-hFuwLcpXAofMCLs7-LgDH1R4zWA,21325
|
|
15
|
+
commitship_cli-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
16
|
+
commitship_cli-0.1.0.dist-info/entry_points.txt,sha256=9SMjUQox8wuL2LXXt3ycGXagc6o6HKYi9fUs-tsTTkI,39
|
|
17
|
+
commitship_cli-0.1.0.dist-info/top_level.txt,sha256=eD2OKJlHWtqWvgOmP4YojnVy5R80if7UolJgVEBieXM,5
|
|
18
|
+
commitship_cli-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Commercial licensing
|
|
2
|
+
|
|
3
|
+
ship is dual-licensed.
|
|
4
|
+
|
|
5
|
+
**Open source.** Under AGPL-3.0-or-later you may use, modify, and
|
|
6
|
+
redistribute ship freely — including commercially — provided you comply with
|
|
7
|
+
the AGPL, including section 13: if you run a modified version as a network
|
|
8
|
+
service, you must offer the complete corresponding source to that service's
|
|
9
|
+
users.
|
|
10
|
+
|
|
11
|
+
**Commercial.** If the AGPL does not suit your use — embedding ship in a
|
|
12
|
+
proprietary product, shipping it inside a closed developer tool or CI
|
|
13
|
+
service, or any deployment where the source-offer obligation is unacceptable
|
|
14
|
+
— a commercial license removes those obligations.
|
|
15
|
+
|
|
16
|
+
Contact: devkancheti4@gmail.com with:
|
|
17
|
+
|
|
18
|
+
1. how ship will be deployed (developer workstations, CI, a hosted service),
|
|
19
|
+
2. approximate scale (developers or repositories),
|
|
20
|
+
3. whether you need policy changes to the measurements — the secret shapes,
|
|
21
|
+
the protected-branch list, the bulk limits — compiled for your
|
|
22
|
+
organisation. The two laws are fixed and proved; what counts as a secret
|
|
23
|
+
or a protected branch lives in the measurement, and that is where
|
|
24
|
+
per-organisation policy belongs.
|
|
25
|
+
|
|
26
|
+
The copyright holder for ship and its two machine-authored kernels
|
|
27
|
+
(`ship.c`, `say.c`) is devkancheti4-design; dual licensing is offered by the
|
|
28
|
+
copyright holder, which the AGPL fully permits.
|