housestyle 0.1.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.
@@ -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 [yyyy] [name of copyright owner]
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,14 @@
1
+ housestyle
2
+ Copyright 2026 Jonas Kieselbach
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
@@ -0,0 +1,324 @@
1
+ Metadata-Version: 2.4
2
+ Name: housestyle
3
+ Version: 0.1.0
4
+ Summary: Learn your own writing voice from your own texts, measured locally - raw text never leaves the machine.
5
+ Author: Jonas Kieselbach
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/TheKieselbach/housestyle
8
+ Project-URL: Source, https://github.com/TheKieselbach/housestyle
9
+ Project-URL: Documentation, https://github.com/TheKieselbach/housestyle/blob/main/INSTALL.md
10
+ Project-URL: Changelog, https://github.com/TheKieselbach/housestyle/blob/main/CHANGELOG.md
11
+ Project-URL: Issues, https://github.com/TheKieselbach/housestyle/issues
12
+ Keywords: writing,style,voice,privacy,local,corpus,llm
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: End Users/Desktop
16
+ Classifier: Natural Language :: English
17
+ Classifier: Natural Language :: German
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Topic :: Utilities
26
+ Classifier: Topic :: Text Processing :: Linguistic
27
+ Requires-Python: >=3.9
28
+ Description-Content-Type: text/markdown
29
+ License-File: LICENSE
30
+ License-File: NOTICE
31
+ Dynamic: license-file
32
+
33
+ # housestyle
34
+
35
+ [![tests](https://github.com/TheKieselbach/housestyle/actions/workflows/ci.yml/badge.svg)](https://github.com/TheKieselbach/housestyle/actions/workflows/ci.yml)
36
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue)](https://www.python.org/downloads/)
37
+ [![License: Apache 2.0](https://img.shields.io/badge/license-Apache--2.0-green)](LICENSE)
38
+ [![dependencies: none](https://img.shields.io/badge/dependencies-none-brightgreen)](INSTALL.md)
39
+
40
+ **Learn your own writing voice from your own texts — without sending those
41
+ texts to a model.**
42
+
43
+ A language model can imitate your style if you show it enough of your
44
+ writing. The usual way to do that is to paste your writing into the context.
45
+ For a private person that is a nuisance. For a business it is a decision
46
+ nobody made deliberately: every mail you ever sent, in someone else's
47
+ infrastructure, because a draft needed to sound right.
48
+
49
+ housestyle takes the other route. It measures your writing **locally** and
50
+ produces numbers. Only the numbers, plus a handful of short redacted
51
+ passages, go into building the profile. The corpus stays on your machine.
52
+
53
+ **Who this is for:** anyone whose writing carries their own name — consultants,
54
+ founders, freelancers, people who send a lot of mail that has to sound like
55
+ them. Also anyone under a duty of confidentiality who would rather not paste
56
+ their sent folder into a chat window.
57
+
58
+ **Who it is not for:** teams looking for a shared house tone. That is a
59
+ different problem — this measures one person, and mixing several writers
60
+ produces an average nobody actually writes like.
61
+
62
+ ---
63
+
64
+ ## What you actually get
65
+
66
+ Ask any model to decline a proposal, and you get this:
67
+
68
+ > Dear Mr Fisher,
69
+ >
70
+ > Thank you for your message and for the detailed proposal. Having carefully
71
+ > reviewed the approach you outlined, I would like to share some thoughts.
72
+ > While I appreciate the thinking behind it, I am concerned that the
73
+ > associated costs may be considerable. I would therefore suggest that we
74
+ > explore alternative avenues together. Please do not hesitate to reach out
75
+ > should you have any questions.
76
+
77
+ Competent. Polite. Not you. Give the same model your profile, and it writes
78
+ to the measurements instead:
79
+
80
+ > Hi Tom,
81
+ >
82
+ > too expensive. We tried it twice, it didn't work.
83
+ > I'll look at it tomorrow and come back to you.
84
+ >
85
+ > Cheers
86
+
87
+ Every difference traces to a number, not to taste:
88
+
89
+ | Measurement | What it changed |
90
+ |---|---|
91
+ | Sentence median **7 words**, 48 % under six | The long, hedged sentences collapse |
92
+ | Intensifiers and hedges at **0 per 1000 words** | "carefully", "considerable", "I would like to" go |
93
+ | Greeting measured as **"Hi"**, sign-off as **"Cheers"** | No "Dear …", no "Please do not hesitate" |
94
+ | Exclamation marks **0.0 per sentence** | None appear |
95
+ | Informal address throughout | No formal register |
96
+
97
+ That is the point of measuring rather than asking a model to guess: **you can
98
+ see why a sentence changed.**
99
+
100
+ ## What the measurement looks like
101
+
102
+ Real output from `measure.py`, abridged:
103
+
104
+ ```json
105
+ {
106
+ "volume": { "texts": 180, "sentences": 633, "words": 3917 },
107
+ "sentence_length_words": {
108
+ "median": 7, "mean": 6.3, "p10": 2.0, "p90": 9.0,
109
+ "short_under_6": 48, "long_over_25": 0 },
110
+ "punctuation_per_sentence": {
111
+ "comma": 0.39, "dash": 0.07, "colon": 0.15, "exclamation_mark": 0.0 },
112
+ "markers_per_1000_words": {
113
+ "hedges": 0.0, "intensifiers": 0.0, "questions": 12.3 },
114
+ "particles": [ ["also", 48, 12.25], ["gern", 40, 10.21], ["ja", 31, 7.91] ]
115
+ }
116
+ ```
117
+
118
+ From that plus a few short redacted passages you write `style-profile.md` —
119
+ roughly one page. **That page is what you paste into your AI tool.**
120
+
121
+ Writing it is the one step a model does for you. With the Claude Code plugin
122
+ the `profile` skill does it. Without it, paste the metrics file into whatever
123
+ model you use and ask:
124
+
125
+ > Here are measurements of my writing, taken from my own texts, plus a few
126
+ > short sample passages. Write a one-page style profile I can give to a model
127
+ > so it writes like me. Every statement must trace back to one of these
128
+ > numbers — no "clear and concise", but "median 7 words, 48 percent of
129
+ > sentences under six". End with a short checklist for reviewing a draft.
130
+
131
+ Note what does **not** happen here: your corpus is not in that prompt. Only
132
+ counts, medians and a handful of redacted lines. It says
133
+ things like *"median 7 words; 48 percent of sentences under six; opens with
134
+ Hi, closes with Cheers; intensifiers essentially absent — emphasis comes from
135
+ negation, not from adverbs."*
136
+
137
+ Every line of it is a claim you can check against a number. That is the
138
+ difference from "write in a casual tone": a model can follow it, and you can
139
+ tell when it did not.
140
+
141
+ ## How you use it day to day
142
+
143
+ 1. **Once a quarter** — refresh the corpus and remeasure. Ten minutes.
144
+ 2. **Once, then rarely** — paste `style-profile.md` into your tool's
145
+ instructions: ChatGPT custom instructions, a Claude Project, a Gem, your
146
+ `.cursorrules`. It stays there.
147
+ 3. **Per draft** — check it against your own vocabulary:
148
+ ```bash
149
+ housestyle outliers draft.txt
150
+ ```
151
+ It lists words whose stem you almost never use. In the reference corpus
152
+ one flagged word appeared **once** in 50,000 of the author's own words.
153
+ Not every hit is wrong — technical terms land there too. It is a list to
154
+ look at, not a list to delete.
155
+ 4. **When you rewrite a draft** — put the rewritten version back into the
156
+ corpus. Texts you approved are the best material there is, because they
157
+ are certainly in your voice.
158
+
159
+ With the Claude Code plugin, steps 2 to 4 happen on their own.
160
+
161
+ ---
162
+
163
+ ## Start with what you already have
164
+
165
+ If you use Claude Code, your corpus already exists. Your own messages in the
166
+ transcripts are typed and dictated prose, and nobody has to export anything.
167
+
168
+ ```bash
169
+ python3 scripts/setup.py # four questions, shows what it will create
170
+ python3 scripts/collect_transcripts.py
171
+ python3 scripts/measure.py "$ROOT/corpus/transcripts.jsonl" --tag transcripts
172
+ ```
173
+
174
+ That is the whole first run. You now have a file of numbers describing how you
175
+ write, and no text has left the machine.
176
+
177
+ Add registers as you go — sent mail (mbox or Microsoft Graph), published
178
+ articles. Registers are kept apart on purpose: most people write very
179
+ differently in mail than in public. Getting your texts out of Gmail, Microsoft
180
+ 365, Apple Mail or any IMAP provider is covered in
181
+ [`docs/getting-your-texts.md`](docs/getting-your-texts.md).
182
+
183
+ **Requirements: Python 3.9 and nothing else.** No packages, no account, no
184
+ network. See [`INSTALL.md`](INSTALL.md) — including exactly what gets created
185
+ and how to remove it.
186
+
187
+ ## Works with whatever you already use
188
+
189
+ The measurement is plain Python and produces a Markdown profile. Paste it into
190
+ ChatGPT's custom instructions, a Claude Project or Style, a Gem, your
191
+ `.cursorrules`, or a local model's system prompt. Or read it yourself — it is
192
+ an honest description of how you write.
193
+
194
+ The `skills/` directory adds a [Claude Code](https://claude.com/claude-code)
195
+ plugin on top, which loads the profile automatically and checks drafts against
196
+ it. **That layer is optional** and deleting it changes nothing else.
197
+
198
+ ## What it measures
199
+
200
+ | | |
201
+ |---|---|
202
+ | Sentence length | median, mean, p10/p90, share under 6 and over 25 words |
203
+ | Punctuation | commas, dashes, colons, brackets, question and exclamation marks per sentence |
204
+ | Markers | hedges, intensifiers, connectives, contrast, subjunctive, modals, nominal style, passive, person, forms of address |
205
+ | Closed word classes | particles, degree words, evaluative words — the actual style signal |
206
+ | Openings and closings | how you start sentences, how you greet, how you sign off |
207
+ | Topic vocabulary | reported separately and labelled **not style** |
208
+
209
+ ## Three things that cost a full run each
210
+
211
+ These are in the code as comments too. They are the reason this repository
212
+ exists rather than a description of one.
213
+
214
+ **1 · Mail clients emit `\r\n`.** Every `$` anchor in a line-based regular
215
+ expression fails on the leftover `\r`, silently. Normalise before anything
216
+ else.
217
+
218
+ **2 · The signature was 43 percent of the mail corpus.** An automatic
219
+ signature block — address, service list, marketing line, booking link — hangs
220
+ on every mail and dwarfs the actual message. Worse, its canned sign-off looks
221
+ exactly like a typed one, so the profile concluded a farewell formula the
222
+ author never types. Signature anchors are configuration in this project, and
223
+ `collect_mail.py` warns when you leave them empty.
224
+
225
+ **3 · Word frequency over open word classes measures your topic, not your
226
+ style.** An early run produced a profile whose most characteristic words were
227
+ "client", "backup" and "folder". True, and useless. What someone writes
228
+ *about* changes with the project. Which particles they reach for does not.
229
+ Closed classes — particles, degree words, evaluative words — are the signal;
230
+ open classes are reported separately and clearly labelled.
231
+
232
+ ## Languages
233
+
234
+ The method is language-independent. The word lists are not, so they live in
235
+ `lang/<code>.json` rather than in the code.
236
+
237
+ Shipped: **German** (`de`, the reference language — built and validated
238
+ against a real 54,000-word corpus) and **English** (`en`). Adding a language
239
+ means writing one JSON file; see `docs/adding-a-language.md`.
240
+
241
+ ## What this does not do
242
+
243
+ - It does not write for you. It produces a profile; a model writes with it.
244
+ - It does not verify authorship or detect AI text.
245
+ - It will not make a model sound like you from a small corpus. Below roughly
246
+ 10,000 of your own words the numbers are noise.
247
+ - It is not a privacy guarantee for whatever you do next. It keeps *this*
248
+ step local. What you paste elsewhere is still your call.
249
+
250
+ ## Privacy
251
+
252
+ The corpus contains the full text of things you wrote. It lives under the
253
+ path you set in `housestyle.conf`, deliberately outside this repository, and
254
+ `.gitignore` is a second net in case something is ever written here by
255
+ mistake. Sample passages — the one place actual text is meant to be shown to
256
+ a model — are redacted first: configured names, mail addresses, links, phone
257
+ numbers and amounts.
258
+
259
+ **Secrets are redacted when the corpus is written.** People type API keys and
260
+ passwords into chat windows, and transcripts keep them. Keys, tokens, private
261
+ key blocks and credentials in URLs are replaced with placeholders before
262
+ anything is stored — and again before any sample is shown to a model.
263
+
264
+ Nothing in this project sends anything anywhere. There is no telemetry, no
265
+ network call except the one in `collect_web.py`, which fetches URLs you pass
266
+ it yourself — and only over http and https, never `file://`.
267
+
268
+ What was checked before release, and what it found, is in
269
+ [`SECURITY.md`](SECURITY.md).
270
+
271
+ ## Why it was built this way
272
+
273
+ The long version is in [`docs/why-measure-locally.md`](docs/why-measure-locally.md).
274
+ The short version: a guardrail that only exists in a policy document is not a
275
+ guardrail. This one is in the file layout — the corpus cannot reach a model
276
+ by accident, because the thing that reaches the model is a JSON file full of
277
+ numbers.
278
+
279
+ ## Tests
280
+
281
+ ```bash
282
+ python3 -W error::ResourceWarning -m unittest discover tests -v
283
+ ```
284
+
285
+ 52 tests, no corpus and no setup needed. They are not coverage theatre — each
286
+ one records a specific way an earlier version was wrong, or a security
287
+ constraint that must keep holding.
288
+
289
+ ## Did it work for you?
290
+
291
+ The tool has been built and measured on one machine, against one corpus, in
292
+ two languages. That is not enough to know whether it works.
293
+
294
+ If you set it up, a short note in
295
+ [Discussions](../../discussions) helps more than a star — and four things
296
+ would help most:
297
+
298
+ 1. **Which language, which corpus?** Transcripts, mail, published texts — and
299
+ roughly how many words before the numbers stopped looking like noise.
300
+ 2. **How did you get your texts out?** The export routes in
301
+ [`docs/getting-your-texts.md`](docs/getting-your-texts.md) are documented
302
+ from testing, not from using every provider. If yours was different, that
303
+ is worth a paragraph.
304
+ 3. **Which tool did you paste the profile into**, and did it follow it?
305
+ 4. **The one that matters: did a draft actually come out different?** Not
306
+ "did it feel better" — what changed, and does it trace to a number? That
307
+ is the question this project stands or falls on, and it is the one nobody
308
+ else asks.
309
+
310
+ Reports that say it did **not** work are more useful than reports that say it
311
+ did. A profile that reads well and changes nothing is the failure mode worth
312
+ knowing about.
313
+
314
+ Findings from those reports go into a field-reports section here, with
315
+ attribution, once there are any.
316
+
317
+ ## Contributing
318
+
319
+ The most useful contribution is **a language pack** — one JSON file, no code,
320
+ and it needs a native speaker. See [`CONTRIBUTING.md`](CONTRIBUTING.md).
321
+
322
+ ## License
323
+
324
+ Apache-2.0. See `LICENSE` and `NOTICE`.