uncoded 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. uncoded-0.5.0/.agents/skills/coherence-review/SKILL.md +359 -0
  2. uncoded-0.5.0/.claude/settings.json +18 -0
  3. uncoded-0.5.0/.claude/skills/coherence-review/SKILL.md +359 -0
  4. uncoded-0.5.0/.github/workflows/ci.yml +33 -0
  5. uncoded-0.5.0/.github/workflows/publish.yml +42 -0
  6. uncoded-0.5.0/.gitignore +212 -0
  7. uncoded-0.5.0/.mcp.json +20 -0
  8. uncoded-0.5.0/.pre-commit-config.yaml +34 -0
  9. uncoded-0.5.0/.serena/project.yml +165 -0
  10. uncoded-0.5.0/.uncoded/namespace.yaml +325 -0
  11. uncoded-0.5.0/.uncoded/reviews/2026-04-25-001215.md +150 -0
  12. uncoded-0.5.0/.uncoded/stubs/src/uncoded/__init__.pyi +5 -0
  13. uncoded-0.5.0/.uncoded/stubs/src/uncoded/cli.pyi +23 -0
  14. uncoded-0.5.0/.uncoded/stubs/src/uncoded/config.pyi +17 -0
  15. uncoded-0.5.0/.uncoded/stubs/src/uncoded/extract.pyi +41 -0
  16. uncoded-0.5.0/.uncoded/stubs/src/uncoded/instruction_files.pyi +22 -0
  17. uncoded-0.5.0/.uncoded/stubs/src/uncoded/namespace_map.pyi +22 -0
  18. uncoded-0.5.0/.uncoded/stubs/src/uncoded/serena_setup.pyi +32 -0
  19. uncoded-0.5.0/.uncoded/stubs/src/uncoded/skill.pyi +12 -0
  20. uncoded-0.5.0/.uncoded/stubs/src/uncoded/stubs.pyi +112 -0
  21. uncoded-0.5.0/.uncoded/stubs/src/uncoded/sync.pyi +11 -0
  22. uncoded-0.5.0/.uncoded/stubs/tests/test_cli.pyi +66 -0
  23. uncoded-0.5.0/.uncoded/stubs/tests/test_config.pyi +43 -0
  24. uncoded-0.5.0/.uncoded/stubs/tests/test_extract.pyi +62 -0
  25. uncoded-0.5.0/.uncoded/stubs/tests/test_instruction_files.pyi +48 -0
  26. uncoded-0.5.0/.uncoded/stubs/tests/test_namespace_map.pyi +54 -0
  27. uncoded-0.5.0/.uncoded/stubs/tests/test_serena_setup.pyi +74 -0
  28. uncoded-0.5.0/.uncoded/stubs/tests/test_skill.pyi +40 -0
  29. uncoded-0.5.0/.uncoded/stubs/tests/test_stubs.pyi +187 -0
  30. uncoded-0.5.0/.uncoded/stubs/tests/test_sync.pyi +43 -0
  31. uncoded-0.5.0/.uncoded/stubs/tests/test_uncoded.pyi +9 -0
  32. uncoded-0.5.0/AGENTS.md +124 -0
  33. uncoded-0.5.0/CLAUDE.md +124 -0
  34. uncoded-0.5.0/LICENSE +21 -0
  35. uncoded-0.5.0/MAINTENANCE.md +26 -0
  36. uncoded-0.5.0/PKG-INFO +226 -0
  37. uncoded-0.5.0/README.md +207 -0
  38. uncoded-0.5.0/SYSTEM.md +53 -0
  39. uncoded-0.5.0/pyproject.toml +59 -0
  40. uncoded-0.5.0/resources/lsp-research.md +45 -0
  41. uncoded-0.5.0/src/uncoded/__init__.py +5 -0
  42. uncoded-0.5.0/src/uncoded/cli.py +103 -0
  43. uncoded-0.5.0/src/uncoded/config.py +62 -0
  44. uncoded-0.5.0/src/uncoded/extract.py +137 -0
  45. uncoded-0.5.0/src/uncoded/instruction_files.py +133 -0
  46. uncoded-0.5.0/src/uncoded/namespace_map.py +84 -0
  47. uncoded-0.5.0/src/uncoded/serena_setup.py +203 -0
  48. uncoded-0.5.0/src/uncoded/skill.py +388 -0
  49. uncoded-0.5.0/src/uncoded/stubs.py +389 -0
  50. uncoded-0.5.0/src/uncoded/sync.py +50 -0
  51. uncoded-0.5.0/tests/__init__.py +0 -0
  52. uncoded-0.5.0/tests/test_cli.py +199 -0
  53. uncoded-0.5.0/tests/test_config.py +83 -0
  54. uncoded-0.5.0/tests/test_extract.py +287 -0
  55. uncoded-0.5.0/tests/test_instruction_files.py +92 -0
  56. uncoded-0.5.0/tests/test_namespace_map.py +213 -0
  57. uncoded-0.5.0/tests/test_serena_setup.py +199 -0
  58. uncoded-0.5.0/tests/test_skill.py +90 -0
  59. uncoded-0.5.0/tests/test_stubs.py +633 -0
  60. uncoded-0.5.0/tests/test_sync.py +82 -0
  61. uncoded-0.5.0/tests/test_uncoded.py +10 -0
  62. uncoded-0.5.0/uv.lock +229 -0
@@ -0,0 +1,359 @@
1
+ ---
2
+ name: coherence-review
3
+ description: "Perform a coherence review of a Python codebase: a diagnostic sweep for semantic drift, naming inconsistency, promissory mismatch, and structural incoherence. Produces a Markdown report of findings with verbatim evidence and confidence levels, for human investigation. Assumes uncoded is installed (.uncoded/namespace.yaml and .uncoded/stubs/ present)."
4
+ ---
5
+
6
+ # Coherence Review
7
+
8
+ A diagnostic sweep of a Python codebase for specific, observable symptoms of
9
+ semantic drift and incoherence. Output is a structured Markdown report of
10
+ candidate regions, each with verbatim evidence and a confidence level, for a
11
+ human to investigate. Not a bug hunt, not a lint pass, not a refactor.
12
+
13
+ ## Why coherence, and what you are looking for
14
+
15
+ A codebase accumulates corruption differently from how it accumulates bugs. Bugs
16
+ announce themselves — tests fail, users complain, exceptions raise. Corruption
17
+ passes every integrity check. It is the slow divergence between what the code
18
+ claims to mean and what it actually does, between how one part of the codebase
19
+ names a concept and how another names the same concept, between an architecture
20
+ as declared and an architecture as practised. Each local decision that
21
+ contributed to it was reasonable. The accumulation is not.
22
+
23
+ Corruption's one observable signature is **internal inconsistency**. Not
24
+ absolute wrongness — that requires a reference outside the code, which is not
25
+ available here. Just pairwise disagreement between things that ought to agree:
26
+ a name and its behaviour, two names for the same concept, a docstring and the
27
+ signature it sits on, a declared architecture and the actual import graph. Every
28
+ symptom in the sweeps below is a form of inconsistency. The review's job is to
29
+ find these disagreements — not to diagnose root cause and not to fix them.
30
+
31
+ ## What this skill is not
32
+
33
+ - **Not a bug-finder.** Bugs are the job of testing and code review. A coherence
34
+ review can run on code that passes every test and still find plenty.
35
+ - **Not a style pass.** Tabs versus spaces, docstring format, import ordering —
36
+ irrelevant. Linters exist.
37
+ - **Not a refactor.** No proposing fixes, no suggesting renames, no rewriting
38
+ code. The output is findings. The human decides what to do with them.
39
+ - **Not a general code review.** Performance, security, correctness — out of
40
+ scope unless they happen to manifest as a coherence symptom.
41
+
42
+ ## Prerequisites
43
+
44
+ Verify by reading `.uncoded/namespace.yaml` — if it exists and is non-empty,
45
+ proceed. If not, stop and tell the user to run `uncoded sync` first; the review
46
+ depends on the index.
47
+
48
+ If Serena MCP tools are available (`mcp__serena__*`), the structural sweep has
49
+ more leverage. The review still works without Serena but will be weaker on
50
+ cross-file reference checks.
51
+
52
+ ## Workflow
53
+
54
+ The review proceeds in four sweeps, each building on the previous:
55
+
56
+ 1. **Orient** — load the navigation index and form a mental map.
57
+ 2. **Lexical sweep** — read the namespace, look for naming-level inconsistency.
58
+ 3. **Promissory sweep** — read stubs, check each symbol's name / signature /
59
+ docstring for internal disagreement.
60
+ 4. **Structural sweep** — combine namespace and imports to find boundary and
61
+ shape symptoms.
62
+
63
+ Do the sweeps in order. Write findings as you go — do not hold them in memory
64
+ until the end.
65
+
66
+ ## Step 1: Orient
67
+
68
+ Read `.uncoded/namespace.yaml` in full. This is the map — directories, files,
69
+ classes, methods, functions — in source order. Do not skim. Every public symbol
70
+ in the codebase is listed here, and the shape of the namespace itself is
71
+ evidence.
72
+
73
+ While reading, note:
74
+
75
+ - The vocabulary the codebase uses for its core concepts
76
+ - The organisational logic (domain-driven? layered? feature-based? ad hoc?)
77
+ - Anything that surprises you — odd names, asymmetric organisation, suspicious
78
+ clusters
79
+
80
+ Also read `CLAUDE.md` if present, and follow any repo-specific navigation
81
+ protocol throughout the review.
82
+
83
+ Before starting the sweeps, tell the user how many public symbols were indexed.
84
+ Then proceed without asking for further confirmation.
85
+
86
+ ## Step 2: Lexical sweep
87
+
88
+ Working from the namespace alone, look for four categories of naming-level
89
+ symptom.
90
+
91
+ **Concept duplication under different names.** The same concept referred to by
92
+ different names in different parts of the codebase. Examples: `fetch_user`,
93
+ `get_user`, `load_user`, `retrieve_user` all appearing as separate functions
94
+ doing substantively the same thing. `compute_*`, `calculate_*`, `derive_*` used
95
+ interchangeably. Two classes called `UserRecord` and `AccountProfile` that
96
+ model the same entity.
97
+
98
+ Detection: scan the namespace for symbol clusters with verb or noun overlap.
99
+ Where suspicion arises, spot-check the relevant stubs to confirm they overlap
100
+ in meaning.
101
+
102
+ **Qualifier accretion.** Names carrying modifiers that are fossils of
103
+ iteration: `_new`, `_v2`, `_updated`, `_legacy`, `_real`, `_proper`, `_final`,
104
+ `_fixed`. Also prefix forms: `new_`, `old_`, `real_`. These are almost always
105
+ worth flagging — someone needed to distinguish a new thing from an old thing
106
+ and the distinction was never resolved.
107
+
108
+ Detection: scan the namespace for these qualifier patterns.
109
+
110
+ **Vocabulary islands.** A subregion of the codebase (a directory, a module
111
+ cluster) using a distinct vocabulary that doesn't overlap with the rest. Often
112
+ the result of an unintegrated contribution, or a session that added a feature
113
+ without looking outward.
114
+
115
+ Detection: look for directories whose namespace entries share few word-roots
116
+ with the rest of the codebase.
117
+
118
+ **Collision with drift.** The same name appearing in multiple places with
119
+ subtly different meanings — visible as different signatures, different docstring
120
+ content, or different domain associations.
121
+
122
+ Detection: identify name collisions in the namespace, then examine the stubs to
123
+ see whether the uses agree.
124
+
125
+ ## Step 3: Promissory sweep
126
+
127
+ Working from stubs, examine each public symbol's name / signature / docstring
128
+ triple for internal disagreement.
129
+
130
+ For each non-trivial public symbol (skip trivial one-liners and `__init__` with
131
+ no meaningful body):
132
+
133
+ **Name–signature mismatch.** Does the name's verb fit the signature's return? A
134
+ function called `validate_*` that returns the validated object rather than
135
+ raising or returning bool. A `get_*` that mutates. A noun-named thing that is a
136
+ verb's worth of work. A boolean-returning function whose name doesn't start with
137
+ `is_`, `has_`, `can_`, or similar.
138
+
139
+ **Docstring–signature mismatch.** Does the docstring refer to parameters not in
140
+ the signature, or fail to mention parameters that are? Does the docstring
141
+ describe return behaviour that contradicts the type annotation?
142
+
143
+ **Docstring–name mismatch.** Does the docstring describe an operation noticeably
144
+ more specific, more general, or simply different from what the name advertises?
145
+ "Normalises and validates the record" on a function called `check_record`.
146
+
147
+ **Defensive docstrings.** Docstrings that warn about the function rather than
148
+ describe it. "Note: this does not actually X despite the name." "Do not use
149
+ this for Y; use Z instead." These are confessions — someone noticed drift and
150
+ documented it rather than fixing it.
151
+
152
+ The stub itself is the evidence. Quote the stub excerpt (name, signature,
153
+ first-line docstring) verbatim in the finding.
154
+
155
+ **When to read source.** The stub is usually sufficient for discovery — the
156
+ inconsistency IS the mismatch between name, signature, and docstring, all of
157
+ which the stub provides. Read the symbol body when a finding is already
158
+ identified but confidence is genuinely uncertain: an undocumented parameter
159
+ where significance depends on what it controls; a name–behaviour mismatch where
160
+ the stub alone doesn't confirm it; a defensive docstring you want to verify is
161
+ accurate. Use Serena's `find_symbol` with `include_body=True` — targeted to the
162
+ symbol, no offset arithmetic, no risk of over-reading. Never read a whole source
163
+ file during this sweep.
164
+
165
+ ## Step 4: Structural sweep
166
+
167
+ Combine the namespace with the import graph and, if available, Serena's
168
+ reference resolution.
169
+
170
+ **Overgrown public surfaces / god modules.** A module or class whose public
171
+ namespace is much larger than its siblings, or spans obviously different
172
+ concerns. Look for outlier symbol counts: a file with forty public symbols where
173
+ its neighbours have five; a class with thirty methods covering multiple domains.
174
+
175
+ **Boundary violations.** One module importing private symbols (leading
176
+ underscore) from another. Scan `from module import _thing` patterns across
177
+ stubs' import sections. Each instance is a finding.
178
+
179
+ **Cross-vocabulary imports.** Imports that cross domain boundaries in suspicious
180
+ directions — a `core/` or `utils/` module importing from a specific business
181
+ domain; a module in domain A importing from domain B when those domains appear
182
+ meant to be independent. Flag candidates and note the direction; let the human
183
+ decide.
184
+
185
+ **Zero-caller public symbols.** A public symbol (no leading underscore) with no
186
+ references anywhere in the codebase. Either dead code or an unused API surface.
187
+
188
+ Check systematically, not by spot-check:
189
+
190
+ 1. From the namespace map, list all public symbols in each source module.
191
+ 2. Cross-reference with stub import sections — any symbol imported by another
192
+ source module is live; remove it from the candidate list. This culls the
193
+ obvious cases cheaply.
194
+ 3. For remaining candidates, use Serena's `find_referencing_symbols` to verify.
195
+ If Serena is unavailable, note findings as lower confidence.
196
+ 4. Distinguish two sub-cases when reporting:
197
+ - *No callers anywhere* — dead code; highest priority.
198
+ - *Callers only in tests* — the symbol is tested but not used in source;
199
+ may be an exposed internal that should be private.
200
+
201
+ **Redundant public surface.** A public constant and a public parameterless
202
+ function in the same module where the function's sole body is `return
203
+ <constant>`. Both symbols being public exposes an implementation detail
204
+ unnecessarily — only one needs to be public. Detection: use the stubs to find
205
+ public parameterless functions near public constants, then verify each
206
+ candidate body with Serena's `find_symbol` with `include_body=True` before
207
+ reporting.
208
+
209
+ ## Report format
210
+
211
+ Save the report as `.uncoded/reviews/YYYY-MM-DD-HHMMSS.md`, using today's date
212
+ and current time (timestamped to preserve multiple runs on the same day).
213
+ Create the directory if it does not exist.
214
+
215
+ Use this structure:
216
+
217
+ ```markdown
218
+ # Coherence Review — <repo name>
219
+
220
+ **Date:** YYYY-MM-DD
221
+ **Symbols indexed:** N
222
+ **Sweeps run:** lexical, promissory, structural
223
+ **Findings:** N total (N lexical · N promissory · N structural)
224
+
225
+ ## Priority regions
226
+
227
+ Regions with two or more findings — examine these first:
228
+
229
+ - `path/to/file.py` — N findings
230
+ - ...
231
+
232
+ *(Omit this section if no region has more than one finding.)*
233
+
234
+ ## Findings
235
+
236
+ ### 1 · <symptom summary>
237
+
238
+ **Category:** lexical | promissory | structural
239
+ **Symptom:** concept-duplication | qualifier-accretion | vocabulary-island |
240
+ collision-with-drift | name-signature-mismatch | docstring-signature-mismatch |
241
+ docstring-name-mismatch | defensive-docstring | god-module |
242
+ boundary-violation | cross-vocabulary-import | zero-caller
243
+ **Location:** `path/to/file.py` · `ClassName/method_name`
244
+ **Confidence:** high | medium | low
245
+
246
+ **Evidence:**
247
+ > Verbatim quote from namespace.yaml, stub, or import statement.
248
+
249
+ One or two sentences describing the inconsistency. Not a diagnosis. Not a fix.
250
+
251
+ ---
252
+
253
+ ### 2 · ...
254
+ ```
255
+
256
+ ## Principles
257
+
258
+ **Coverage, not filtering.** Report every finding at its confidence level. Do
259
+ not silently drop findings judged low-severity. A low-confidence finding with
260
+ clear evidence is useful — the human can filter. A dropped finding is not.
261
+
262
+ **Confidence is part of the finding, not a gate.**
263
+
264
+ - `high` — the inconsistency is explicit; evidence is directly in the stub or
265
+ namespace
266
+ - `medium` — strongly implied but depends on judgement about intent
267
+ - `low` — pattern-based suspicion that needs human interpretation
268
+
269
+ **Evidence must be verbatim.** Quote the relevant namespace line, stub excerpt,
270
+ or import statement exactly. A finding the human cannot quickly verify is worse
271
+ than no finding.
272
+
273
+ **One finding per inconsistency.** If a single symbol has a name–signature
274
+ mismatch and a docstring–name mismatch, that is two findings on the same
275
+ symbol, not one combined finding. Let the report show the density.
276
+
277
+ **Do not propose fixes.** No renaming suggestions, no refactoring proposals, no
278
+ "this should be moved to". The finding describes what is inconsistent. The
279
+ human owns remediation.
280
+
281
+ **Do not flag style.** Docstring format, type annotation style, import ordering,
282
+ naming conventions — out of scope. Coherence is about semantic consistency, not
283
+ surface consistency.
284
+
285
+ **Do not fabricate.** Every finding must be anchored to code you actually
286
+ examined. If a sweep suggests a pattern but you cannot find concrete instances,
287
+ do not include it.
288
+
289
+ ## Scope control
290
+
291
+ If the codebase has more than ~1000 public symbols:
292
+
293
+ 1. Complete the lexical sweep in full (the namespace is compact enough).
294
+ 2. For the promissory sweep, prioritise: core domain modules (identified from
295
+ the namespace structure), any module that appeared in a lexical finding, and
296
+ a representative sample of the rest (~30% of remaining stubs).
297
+ 3. For the structural sweep, focus on the module and package level first,
298
+ descending to individual symbols only where the higher-level scan raised
299
+ flags.
300
+
301
+ Note the scope chosen in the report summary so the human knows what was and was
302
+ not examined.
303
+
304
+ ## Examples
305
+
306
+ <example>
307
+ <scenario>Three public functions: `fetch_user(id)`, `get_user_by_id(id)`,
308
+ `load_user(user_id)`, in three different files, all returning a User and all
309
+ doing substantively the same lookup.</scenario>
310
+ <flag>Yes. Concept duplication, high confidence. Evidence: three stub excerpts
311
+ quoted verbatim.</flag>
312
+ </example>
313
+
314
+ <example>
315
+ <scenario>A function `validate_user(user)` whose signature returns `User` rather
316
+ than `bool` or `None`, and whose docstring says "Validates and returns the user
317
+ if valid, raising UserValidationError otherwise."</scenario>
318
+ <flag>Yes. Name–signature mismatch, medium confidence. The name reads as a
319
+ predicate but the behaviour is a validator-filter. Stub quoted as
320
+ evidence.</flag>
321
+ </example>
322
+
323
+ <example>
324
+ <scenario>Two modules, `storage/cache.py` and `runtime/memoize.py`, both
325
+ defining functions that wrap callables with LRU caching, with slightly different
326
+ cache-size defaults.</scenario>
327
+ <flag>Yes. Concept duplication, medium confidence. Both stubs quoted. Note the
328
+ difference — the human may determine it is intentional.</flag>
329
+ </example>
330
+
331
+ <example>
332
+ <scenario>A class `OrderProcessor` with 34 methods spanning order creation,
333
+ validation, payment capture, fulfilment dispatch, refund handling, and
334
+ reporting.</scenario>
335
+ <flag>Yes. God module, high confidence. Method list quoted from
336
+ namespace.</flag>
337
+ </example>
338
+
339
+ <example>
340
+ <scenario>A function uses `x` as a parameter name in a mathematical formula
341
+ module.</scenario>
342
+ <flag>No. Short variable names in mathematical contexts are conventional and do
343
+ not indicate drift.</flag>
344
+ </example>
345
+
346
+ <example>
347
+ <scenario>A function is 80 lines of non-trivial logic.</scenario>
348
+ <flag>No, not by itself. Complexity is not incoherence. Flag only if the
349
+ complexity manifests as inconsistency — e.g. the function's behaviour has
350
+ drifted from what its name or docstring promise.</flag>
351
+ </example>
352
+
353
+ <example>
354
+ <scenario>The codebase uses both `Optional[X]` and `X | None` in different
355
+ files.</scenario>
356
+ <flag>No. Both are valid Python and mean the same thing. Flag only if the
357
+ semantics of absence differ — e.g. some functions return None on failure while
358
+ others raise, for the same kind of operation.</flag>
359
+ </example>
@@ -0,0 +1,18 @@
1
+ {
2
+ "enabledMcpjsonServers": [
3
+ "serena"
4
+ ],
5
+ "permissions": {
6
+ "allow": [
7
+ "mcp__serena__initial_instructions",
8
+ "mcp__serena__find_symbol",
9
+ "mcp__serena__find_referencing_symbols",
10
+ "mcp__serena__get_symbols_overview",
11
+ "mcp__serena__rename_symbol",
12
+ "mcp__serena__safe_delete_symbol",
13
+ "mcp__serena__insert_before_symbol",
14
+ "mcp__serena__insert_after_symbol",
15
+ "mcp__serena__replace_symbol_body"
16
+ ]
17
+ }
18
+ }