uncoded 2.1.1__tar.gz → 3.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.
Files changed (90) hide show
  1. {uncoded-2.1.1/.claude → uncoded-3.0.0/.agents}/skills/uncoded-code-navigation/SKILL.md +25 -18
  2. uncoded-3.0.0/.agents/skills/uncoded-consistency-review/SKILL.md +145 -0
  3. uncoded-3.0.0/.agents/skills/uncoded-doc-navigation/SKILL.md +29 -0
  4. uncoded-2.1.1/src/uncoded/code_navigation.md → uncoded-3.0.0/.claude/skills/uncoded-code-navigation/SKILL.md +31 -17
  5. uncoded-3.0.0/.claude/skills/uncoded-consistency-review/SKILL.md +145 -0
  6. uncoded-3.0.0/.claude/skills/uncoded-doc-navigation/SKILL.md +29 -0
  7. {uncoded-2.1.1 → uncoded-3.0.0}/.pre-commit-config.yaml +6 -0
  8. {uncoded-2.1.1 → uncoded-3.0.0}/AGENTS.md +23 -17
  9. {uncoded-2.1.1 → uncoded-3.0.0}/PKG-INFO +61 -61
  10. {uncoded-2.1.1 → uncoded-3.0.0}/README.md +58 -59
  11. uncoded-3.0.0/dreamcatcher.toml +25 -0
  12. {uncoded-2.1.1 → uncoded-3.0.0}/pyproject.toml +5 -1
  13. {uncoded-2.1.1 → uncoded-3.0.0}/src/uncoded/cli.py +13 -6
  14. uncoded-2.1.1/.agents/skills/uncoded-code-navigation/SKILL.md → uncoded-3.0.0/src/uncoded/code_navigation.md +24 -24
  15. {uncoded-2.1.1 → uncoded-3.0.0}/src/uncoded/config.py +43 -36
  16. uncoded-3.0.0/src/uncoded/consistency_review.md +138 -0
  17. uncoded-3.0.0/src/uncoded/doc_navigation.md +22 -0
  18. {uncoded-2.1.1 → uncoded-3.0.0}/src/uncoded/refs.py +5 -5
  19. {uncoded-2.1.1 → uncoded-3.0.0}/src/uncoded/resolver.py +43 -26
  20. {uncoded-2.1.1 → uncoded-3.0.0}/src/uncoded/skill.py +68 -43
  21. {uncoded-2.1.1 → uncoded-3.0.0}/src/uncoded/stubs.py +32 -21
  22. {uncoded-2.1.1 → uncoded-3.0.0}/src/uncoded/sync.py +3 -4
  23. {uncoded-2.1.1 → uncoded-3.0.0}/tests/test_body.py +20 -13
  24. {uncoded-2.1.1 → uncoded-3.0.0}/tests/test_cli.py +60 -25
  25. {uncoded-2.1.1 → uncoded-3.0.0}/tests/test_refs.py +9 -9
  26. {uncoded-2.1.1 → uncoded-3.0.0}/tests/test_skill.py +62 -63
  27. {uncoded-2.1.1 → uncoded-3.0.0}/uv.lock +174 -0
  28. uncoded-2.1.1/.agents/skills/uncoded-coherence-review/SKILL.md +0 -371
  29. uncoded-2.1.1/.agents/skills/uncoded-doc-navigation/SKILL.md +0 -24
  30. uncoded-2.1.1/.claude/skills/uncoded-coherence-review/SKILL.md +0 -371
  31. uncoded-2.1.1/.claude/skills/uncoded-doc-navigation/SKILL.md +0 -24
  32. uncoded-2.1.1/.uncoded/docs.yaml +0 -36
  33. uncoded-2.1.1/.uncoded/namespace.yaml +0 -594
  34. uncoded-2.1.1/.uncoded/stubs/src/uncoded/__init__.pyi +0 -6
  35. uncoded-2.1.1/.uncoded/stubs/src/uncoded/ast_helpers.pyi +0 -10
  36. uncoded-2.1.1/.uncoded/stubs/src/uncoded/body.pyi +0 -13
  37. uncoded-2.1.1/.uncoded/stubs/src/uncoded/cli.pyi +0 -41
  38. uncoded-2.1.1/.uncoded/stubs/src/uncoded/config.pyi +0 -26
  39. uncoded-2.1.1/.uncoded/stubs/src/uncoded/docs_map.pyi +0 -31
  40. uncoded-2.1.1/.uncoded/stubs/src/uncoded/extract.pyi +0 -33
  41. uncoded-2.1.1/.uncoded/stubs/src/uncoded/markers.pyi +0 -4
  42. uncoded-2.1.1/.uncoded/stubs/src/uncoded/namespace_map.pyi +0 -15
  43. uncoded-2.1.1/.uncoded/stubs/src/uncoded/read_helpers.pyi +0 -15
  44. uncoded-2.1.1/.uncoded/stubs/src/uncoded/refs.pyi +0 -56
  45. uncoded-2.1.1/.uncoded/stubs/src/uncoded/resolver.pyi +0 -36
  46. uncoded-2.1.1/.uncoded/stubs/src/uncoded/skill.pyi +0 -32
  47. uncoded-2.1.1/.uncoded/stubs/src/uncoded/stubs.pyi +0 -101
  48. uncoded-2.1.1/.uncoded/stubs/src/uncoded/sync.pyi +0 -10
  49. uncoded-2.1.1/.uncoded/stubs/src/uncoded/yaml_tree.pyi +0 -11
  50. uncoded-2.1.1/.uncoded/stubs/tests/test_body.pyi +0 -149
  51. uncoded-2.1.1/.uncoded/stubs/tests/test_cli.pyi +0 -215
  52. uncoded-2.1.1/.uncoded/stubs/tests/test_config.pyi +0 -62
  53. uncoded-2.1.1/.uncoded/stubs/tests/test_docs_map.pyi +0 -154
  54. uncoded-2.1.1/.uncoded/stubs/tests/test_encoding_gate.pyi +0 -8
  55. uncoded-2.1.1/.uncoded/stubs/tests/test_extract.pyi +0 -86
  56. uncoded-2.1.1/.uncoded/stubs/tests/test_markers.pyi +0 -21
  57. uncoded-2.1.1/.uncoded/stubs/tests/test_namespace_map.pyi +0 -47
  58. uncoded-2.1.1/.uncoded/stubs/tests/test_refs.pyi +0 -89
  59. uncoded-2.1.1/.uncoded/stubs/tests/test_skill.pyi +0 -100
  60. uncoded-2.1.1/.uncoded/stubs/tests/test_stubs.pyi +0 -237
  61. uncoded-2.1.1/.uncoded/stubs/tests/test_sync.pyi +0 -54
  62. uncoded-2.1.1/.uncoded/stubs/tests/test_uncoded.pyi +0 -10
  63. uncoded-2.1.1/src/uncoded/coherence_review.md +0 -364
  64. uncoded-2.1.1/src/uncoded/doc_navigation.md +0 -17
  65. {uncoded-2.1.1 → uncoded-3.0.0}/.github/workflows/ci.yml +0 -0
  66. {uncoded-2.1.1 → uncoded-3.0.0}/.github/workflows/publish.yml +0 -0
  67. {uncoded-2.1.1 → uncoded-3.0.0}/.gitignore +0 -0
  68. {uncoded-2.1.1 → uncoded-3.0.0}/.markdownlint-cli2.yaml +0 -0
  69. {uncoded-2.1.1 → uncoded-3.0.0}/.prettierrc +0 -0
  70. {uncoded-2.1.1 → uncoded-3.0.0}/CLAUDE.md +0 -0
  71. {uncoded-2.1.1 → uncoded-3.0.0}/LICENSE +0 -0
  72. {uncoded-2.1.1 → uncoded-3.0.0}/src/uncoded/__init__.py +0 -0
  73. {uncoded-2.1.1 → uncoded-3.0.0}/src/uncoded/ast_helpers.py +0 -0
  74. {uncoded-2.1.1 → uncoded-3.0.0}/src/uncoded/body.py +0 -0
  75. {uncoded-2.1.1 → uncoded-3.0.0}/src/uncoded/docs_map.py +0 -0
  76. {uncoded-2.1.1 → uncoded-3.0.0}/src/uncoded/extract.py +0 -0
  77. {uncoded-2.1.1 → uncoded-3.0.0}/src/uncoded/markers.py +0 -0
  78. {uncoded-2.1.1 → uncoded-3.0.0}/src/uncoded/namespace_map.py +0 -0
  79. {uncoded-2.1.1 → uncoded-3.0.0}/src/uncoded/read_helpers.py +0 -0
  80. {uncoded-2.1.1 → uncoded-3.0.0}/src/uncoded/yaml_tree.py +0 -0
  81. {uncoded-2.1.1 → uncoded-3.0.0}/tests/__init__.py +0 -0
  82. {uncoded-2.1.1 → uncoded-3.0.0}/tests/test_config.py +0 -0
  83. {uncoded-2.1.1 → uncoded-3.0.0}/tests/test_docs_map.py +0 -0
  84. {uncoded-2.1.1 → uncoded-3.0.0}/tests/test_encoding_gate.py +0 -0
  85. {uncoded-2.1.1 → uncoded-3.0.0}/tests/test_extract.py +0 -0
  86. {uncoded-2.1.1 → uncoded-3.0.0}/tests/test_markers.py +0 -0
  87. {uncoded-2.1.1 → uncoded-3.0.0}/tests/test_namespace_map.py +0 -0
  88. {uncoded-2.1.1 → uncoded-3.0.0}/tests/test_stubs.py +0 -0
  89. {uncoded-2.1.1 → uncoded-3.0.0}/tests/test_sync.py +0 -0
  90. {uncoded-2.1.1 → uncoded-3.0.0}/tests/test_uncoded.py +0 -0
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: uncoded-code-navigation
3
- description: Use before searching, reading, or editing Python source in a codebase indexed by uncoded. This covers locating a symbol, reading a definition, or checking references before you refactor, rename, or delete.
3
+ description: Load once per session, before the first search, read, or edit of Python source in a codebase indexed by uncoded. Covers locating a symbol, reading a definition, or checking references before you refactor, rename, or delete.
4
4
  ---
5
5
 
6
6
  <!-- Generated by uncoded — do not edit; regeneration overwrites. -->
@@ -17,23 +17,25 @@ for reading a symbol's body and `uncoded refs` for finding references.
17
17
  symbols are classes, functions, methods, attributes, and module-level constants.
18
18
  If it's a pattern, regex, or free-text phrase, use grep.**
19
19
 
20
- This applies to every tool call where you find code, not just the first in the
21
- session. The pretrained reflex for "find X" is grep, and that reflex is wrong
22
- here. Reaching for `grep -rn 'def parse_config'` to read a function's body is a
23
- case for `uncoded body`. Reaching for `grep -rn 'validate_input'` to check
24
- callers before a refactor is a case for `uncoded refs`. Reaching for `grep` then
25
- `Edit` to delete dead code is a case for `uncoded refs` to confirm the code is
26
- dead, then `Edit`. The grep version of any of these is noisier and less
27
- reliable. Grep matches comments, strings, and unrelated attributes. Grep misses
28
- re-exports, so caller and delete checks come back incomplete. Grep forces offset
29
- arithmetic to slice a body. The indexed tools don't.
20
+ This dispatch rule applies to every tool call where you find code, not just the
21
+ first in the session. The pretrained reflex for "find X" is grep, and that
22
+ reflex is wrong here. Reaching for `grep -rn 'def parse_config'` to read a
23
+ function's body is a case for `uncoded body`. Reaching for
24
+ `grep -rn 'validate_input'` to check callers before a refactor is a case for
25
+ `uncoded refs`. Reaching for `grep` then `Edit` to delete dead code is a case
26
+ for `uncoded refs` to confirm the code is dead, then `Edit`. The grep version of
27
+ any of these is noisier and less reliable. Grep matches comments, strings, and
28
+ unrelated attributes. Grep misses re-exports, so caller and delete checks come
29
+ back incomplete. Grep forces offset arithmetic to slice a body. The indexed
30
+ tools don't.
30
31
 
31
32
  ## How to execute the rule
32
33
 
33
- The index has two parts (a namespace map and per-file stubs) and three steps
34
- (orient, understand, act).
34
+ The index has two parts: a namespace map and per-file stubs. Follow this
35
+ sequence.
35
36
 
36
- **Step 1: Orient. Read the namespace map first.** Before answering the user,
37
+ **Step 1: Orient. Read the namespace map first.** If the map is missing, run the
38
+ repository's configured `uncoded sync` command. Then, before answering the user,
37
39
  before any other tool call:
38
40
 
39
41
  ```text
@@ -74,10 +76,11 @@ for a method and `function_name` for a top-level function. Per task:
74
76
 
75
77
  - **Find every reference to a symbol.**
76
78
  `uvx uncoded refs <name_path> --in <relative_path>`. Prints one reference per
77
- line as `file:line:col`, sorted. Grep on the name misses re-exports and adds
78
- false positives from comments, strings, and attribute lookups on other types.
79
- If the next move depends on the answer being complete, grep cannot give you
80
- that.
79
+ line as `<path>:<line>:<col>`, sorted by path, then line, then column. Each
80
+ path is relative to the current working directory when possible and otherwise
81
+ absolute. Grep on the name misses re-exports and adds false positives from
82
+ comments, strings, and attribute lookups on other types. If the next move
83
+ depends on the answer being complete, grep cannot give you that.
81
84
 
82
85
  - **Edit a symbol.** `uvx uncoded body <name_path> --in <relative_path>` gives
83
86
  the exact `old_string`; then `Edit` to apply the change.
@@ -88,6 +91,10 @@ for a method and `function_name` for a top-level function. Per task:
88
91
  - **Safely delete.** `uvx uncoded refs <name_path> --in <relative_path>` must
89
92
  return empty; then `Edit` to remove.
90
93
 
94
+ **Step 4: Refresh.** After every modification to indexed Python source, run the
95
+ repository's configured `uncoded sync` command before the next code-navigation
96
+ operation. The modification can change the namespace map and stubs.
97
+
91
98
  ## Where Read, Edit, and grep are still the right tools
92
99
 
93
100
  The rule is about source navigation by symbol name. Outside that, Read, Edit,
@@ -0,0 +1,145 @@
1
+ ---
2
+ name: uncoded-consistency-review
3
+ description: Review a Python codebase for semantic and naming consistency. It reports only concrete disagreements between two claims about the same concept, with verbatim evidence for each claim. It assumes uncoded is installed (.uncoded/namespace.yaml and .uncoded/stubs/ present).
4
+ ---
5
+
6
+ <!-- Generated by uncoded — do not edit; regeneration overwrites. -->
7
+
8
+ # Semantic Consistency Review
9
+
10
+ Review a Python codebase for concrete disagreements in its vocabulary and symbol
11
+ contracts. A finding must identify two claims about the same concept that ought
12
+ to agree, but do not.
13
+
14
+ ## Guardrails
15
+
16
+ Admit a finding only when the codebase supports both claims, their observable
17
+ difference, and the reason that they should agree. Quote both claims verbatim.
18
+ Omit a candidate when either claim or the reason for comparing them is
19
+ unsupported.
20
+
21
+ Review semantic and naming consistency, not formatting or style consistency. Do
22
+ not report general bugs, complexity, performance, security, or design
23
+ preferences unless they appear as a disagreement between two supported claims.
24
+ Do not report overgrown public surfaces, private imports, cross-domain imports,
25
+ zero-reference symbols, or redundant public surfaces merely because they exist.
26
+
27
+ ## Prerequisites
28
+
29
+ Run the repository's configured `uncoded sync` command. Read the repository's
30
+ agent instructions and follow its navigation rules.
31
+
32
+ ## Orientation
33
+
34
+ Read `.uncoded/namespace.yaml` in full. Use its package structure and symbol
35
+ names to map the codebase's main concepts and vocabulary.
36
+
37
+ ## Vocabulary sweep
38
+
39
+ Use the namespace and stubs to find candidates, then confirm semantic overlap
40
+ from signatures, docstrings, or bodies. Look for:
41
+
42
+ - **Competing terms:** different names for substantively the same concept.
43
+ - **Conflicting use:** the same term used incompatibly within a shared context.
44
+ - **Stale qualifiers:** names such as `legacy`, `v2`, or `final` whose
45
+ distinction conflicts with another symbol or a symbol's docstring.
46
+
47
+ Similar spelling, low vocabulary overlap, or the presence of a qualifier is not
48
+ evidence on its own. A finding needs two concrete claims that establish the
49
+ shared concept and the disagreement.
50
+
51
+ ## Symbol-contract sweep
52
+
53
+ Compare a symbol's name, signature, docstring, and, when needed, behaviour.
54
+ Findings may cover:
55
+
56
+ - name-signature disagreement
57
+ - name-docstring disagreement
58
+ - docstring-signature disagreement
59
+ - name-behaviour disagreement
60
+
61
+ Read each relevant source file's stub for names and signatures. Run the
62
+ repository's configured `uncoded body` command only when a docstring or
63
+ implementation is needed to confirm a candidate. Do not retrieve every symbol
64
+ body.
65
+
66
+ ## Report
67
+
68
+ Return the report directly as the final turn output.
69
+
70
+ Use this structure:
71
+
72
+ ```markdown
73
+ ## Semantic Consistency Review
74
+
75
+ ### Scope
76
+
77
+ <What was reviewed and intentionally omitted.>
78
+
79
+ ### Summary
80
+
81
+ <Two or three sentences that summarise the supported findings.>
82
+
83
+ ### Vocabulary findings
84
+
85
+ #### 1. <Summary>
86
+
87
+ **Claim A** — `<path>` · `<symbol>` · name | signature | docstring | body
88
+
89
+ > Verbatim evidence
90
+
91
+ **Claim B** — `<path>` · `<symbol>` · name | signature | docstring | body
92
+
93
+ > Verbatim evidence
94
+
95
+ **How they differ:** <The observable disagreement.>
96
+
97
+ **Why these should agree:** <Evidence that both claims describe the same
98
+ concept.>
99
+
100
+ ### Symbol-contract findings
101
+
102
+ #### 1. <Summary>
103
+
104
+ <Use the same finding structure.>
105
+ ```
106
+
107
+ Keep both finding headings. If a group has no supported findings, state that
108
+ under its heading. Number findings independently within each group.
109
+
110
+ ## Examples
111
+
112
+ ### Vocabulary finding
113
+
114
+ #### 1. Customer lookup uses competing verbs
115
+
116
+ **Claim A** — `storage.py` · `fetch_customer` · signature
117
+
118
+ > `fetch_customer(customer_id: str) -> Customer`
119
+
120
+ **Claim B** — `adapter.py` · `load_customer` · signature
121
+
122
+ > `load_customer(customer_id: str) -> Customer`
123
+
124
+ **How they differ:** The same lookup uses `fetch` in one module and `load` in
125
+ another.
126
+
127
+ **Why these should agree:** Both signatures accept a customer ID and return a
128
+ customer through sibling adapters.
129
+
130
+ ### Symbol-contract finding
131
+
132
+ #### 1. Predicate name promises a boolean but returns a value
133
+
134
+ **Claim A** — `cache.py` · `is_cached` · name
135
+
136
+ > `is_cached`
137
+
138
+ **Claim B** — `cache.py` · `is_cached` · signature
139
+
140
+ > `is_cached(key: str) -> str | None`
141
+
142
+ **How they differ:** The name promises a predicate, while the return type holds
143
+ a cached value or absence.
144
+
145
+ **Why these should agree:** Both claims describe the contract of `is_cached`.
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: uncoded-doc-navigation
3
+ description: Load once per session, before the first search or read of a codebase's Markdown documentation indexed by uncoded. Covers locating which file and section cover a topic, or orienting to what documentation exists.
4
+ ---
5
+
6
+ <!-- Generated by uncoded — do not edit; regeneration overwrites. -->
7
+
8
+ # Documentation Navigation
9
+
10
+ This codebase uses [uncoded](https://github.com/alimanfoo/uncoded) to maintain a
11
+ documentation index.
12
+
13
+ **Step 1: Orient. Read the docs map first.** If the map is missing, run the
14
+ repository's configured `uncoded sync` command. Then, before answering the user,
15
+ before any other tool call:
16
+
17
+ ```text
18
+ Read .uncoded/docs.yaml
19
+ ```
20
+
21
+ `.uncoded/docs.yaml` is an orientation outline: it lists every Markdown file and
22
+ its heading hierarchy. Read it once, in full, at session start.
23
+
24
+ **Step 2: Navigate.** Headings in the map are literal text. Use `Read` or `grep`
25
+ to navigate to a specific section identified in the map.
26
+
27
+ **Step 3: Refresh.** After every modification to indexed Markdown, run the
28
+ repository's configured `uncoded sync` command before the next
29
+ documentation-navigation operation. The modification can change the heading map.
@@ -1,3 +1,10 @@
1
+ ---
2
+ name: uncoded-code-navigation
3
+ description: Load once per session, before the first search, read, or edit of Python source in a codebase indexed by uncoded. Covers locating a symbol, reading a definition, or checking references before you refactor, rename, or delete.
4
+ ---
5
+
6
+ <!-- Generated by uncoded — do not edit; regeneration overwrites. -->
7
+
1
8
  # Code Navigation
2
9
 
3
10
  This codebase uses [uncoded](https://github.com/alimanfoo/uncoded) to maintain a
@@ -10,23 +17,25 @@ for reading a symbol's body and `uncoded refs` for finding references.
10
17
  symbols are classes, functions, methods, attributes, and module-level constants.
11
18
  If it's a pattern, regex, or free-text phrase, use grep.**
12
19
 
13
- This applies to every tool call where you find code, not just the first in the
14
- session. The pretrained reflex for "find X" is grep, and that reflex is wrong
15
- here. Reaching for `grep -rn 'def parse_config'` to read a function's body is a
16
- case for `uncoded body`. Reaching for `grep -rn 'validate_input'` to check
17
- callers before a refactor is a case for `uncoded refs`. Reaching for `grep` then
18
- `Edit` to delete dead code is a case for `uncoded refs` to confirm the code is
19
- dead, then `Edit`. The grep version of any of these is noisier and less
20
- reliable. Grep matches comments, strings, and unrelated attributes. Grep misses
21
- re-exports, so caller and delete checks come back incomplete. Grep forces offset
22
- arithmetic to slice a body. The indexed tools don't.
20
+ This dispatch rule applies to every tool call where you find code, not just the
21
+ first in the session. The pretrained reflex for "find X" is grep, and that
22
+ reflex is wrong here. Reaching for `grep -rn 'def parse_config'` to read a
23
+ function's body is a case for `uncoded body`. Reaching for
24
+ `grep -rn 'validate_input'` to check callers before a refactor is a case for
25
+ `uncoded refs`. Reaching for `grep` then `Edit` to delete dead code is a case
26
+ for `uncoded refs` to confirm the code is dead, then `Edit`. The grep version of
27
+ any of these is noisier and less reliable. Grep matches comments, strings, and
28
+ unrelated attributes. Grep misses re-exports, so caller and delete checks come
29
+ back incomplete. Grep forces offset arithmetic to slice a body. The indexed
30
+ tools don't.
23
31
 
24
32
  ## How to execute the rule
25
33
 
26
- The index has two parts (a namespace map and per-file stubs) and three steps
27
- (orient, understand, act).
34
+ The index has two parts: a namespace map and per-file stubs. Follow this
35
+ sequence.
28
36
 
29
- **Step 1: Orient. Read the namespace map first.** Before answering the user,
37
+ **Step 1: Orient. Read the namespace map first.** If the map is missing, run the
38
+ repository's configured `uncoded sync` command. Then, before answering the user,
30
39
  before any other tool call:
31
40
 
32
41
  ```text
@@ -67,10 +76,11 @@ for a method and `function_name` for a top-level function. Per task:
67
76
 
68
77
  - **Find every reference to a symbol.**
69
78
  `uvx uncoded refs <name_path> --in <relative_path>`. Prints one reference per
70
- line as `file:line:col`, sorted. Grep on the name misses re-exports and adds
71
- false positives from comments, strings, and attribute lookups on other types.
72
- If the next move depends on the answer being complete, grep cannot give you
73
- that.
79
+ line as `<path>:<line>:<col>`, sorted by path, then line, then column. Each
80
+ path is relative to the current working directory when possible and otherwise
81
+ absolute. Grep on the name misses re-exports and adds false positives from
82
+ comments, strings, and attribute lookups on other types. If the next move
83
+ depends on the answer being complete, grep cannot give you that.
74
84
 
75
85
  - **Edit a symbol.** `uvx uncoded body <name_path> --in <relative_path>` gives
76
86
  the exact `old_string`; then `Edit` to apply the change.
@@ -81,6 +91,10 @@ for a method and `function_name` for a top-level function. Per task:
81
91
  - **Safely delete.** `uvx uncoded refs <name_path> --in <relative_path>` must
82
92
  return empty; then `Edit` to remove.
83
93
 
94
+ **Step 4: Refresh.** After every modification to indexed Python source, run the
95
+ repository's configured `uncoded sync` command before the next code-navigation
96
+ operation. The modification can change the namespace map and stubs.
97
+
84
98
  ## Where Read, Edit, and grep are still the right tools
85
99
 
86
100
  The rule is about source navigation by symbol name. Outside that, Read, Edit,
@@ -0,0 +1,145 @@
1
+ ---
2
+ name: uncoded-consistency-review
3
+ description: Review a Python codebase for semantic and naming consistency. It reports only concrete disagreements between two claims about the same concept, with verbatim evidence for each claim. It assumes uncoded is installed (.uncoded/namespace.yaml and .uncoded/stubs/ present).
4
+ ---
5
+
6
+ <!-- Generated by uncoded — do not edit; regeneration overwrites. -->
7
+
8
+ # Semantic Consistency Review
9
+
10
+ Review a Python codebase for concrete disagreements in its vocabulary and symbol
11
+ contracts. A finding must identify two claims about the same concept that ought
12
+ to agree, but do not.
13
+
14
+ ## Guardrails
15
+
16
+ Admit a finding only when the codebase supports both claims, their observable
17
+ difference, and the reason that they should agree. Quote both claims verbatim.
18
+ Omit a candidate when either claim or the reason for comparing them is
19
+ unsupported.
20
+
21
+ Review semantic and naming consistency, not formatting or style consistency. Do
22
+ not report general bugs, complexity, performance, security, or design
23
+ preferences unless they appear as a disagreement between two supported claims.
24
+ Do not report overgrown public surfaces, private imports, cross-domain imports,
25
+ zero-reference symbols, or redundant public surfaces merely because they exist.
26
+
27
+ ## Prerequisites
28
+
29
+ Run the repository's configured `uncoded sync` command. Read the repository's
30
+ agent instructions and follow its navigation rules.
31
+
32
+ ## Orientation
33
+
34
+ Read `.uncoded/namespace.yaml` in full. Use its package structure and symbol
35
+ names to map the codebase's main concepts and vocabulary.
36
+
37
+ ## Vocabulary sweep
38
+
39
+ Use the namespace and stubs to find candidates, then confirm semantic overlap
40
+ from signatures, docstrings, or bodies. Look for:
41
+
42
+ - **Competing terms:** different names for substantively the same concept.
43
+ - **Conflicting use:** the same term used incompatibly within a shared context.
44
+ - **Stale qualifiers:** names such as `legacy`, `v2`, or `final` whose
45
+ distinction conflicts with another symbol or a symbol's docstring.
46
+
47
+ Similar spelling, low vocabulary overlap, or the presence of a qualifier is not
48
+ evidence on its own. A finding needs two concrete claims that establish the
49
+ shared concept and the disagreement.
50
+
51
+ ## Symbol-contract sweep
52
+
53
+ Compare a symbol's name, signature, docstring, and, when needed, behaviour.
54
+ Findings may cover:
55
+
56
+ - name-signature disagreement
57
+ - name-docstring disagreement
58
+ - docstring-signature disagreement
59
+ - name-behaviour disagreement
60
+
61
+ Read each relevant source file's stub for names and signatures. Run the
62
+ repository's configured `uncoded body` command only when a docstring or
63
+ implementation is needed to confirm a candidate. Do not retrieve every symbol
64
+ body.
65
+
66
+ ## Report
67
+
68
+ Return the report directly as the final turn output.
69
+
70
+ Use this structure:
71
+
72
+ ```markdown
73
+ ## Semantic Consistency Review
74
+
75
+ ### Scope
76
+
77
+ <What was reviewed and intentionally omitted.>
78
+
79
+ ### Summary
80
+
81
+ <Two or three sentences that summarise the supported findings.>
82
+
83
+ ### Vocabulary findings
84
+
85
+ #### 1. <Summary>
86
+
87
+ **Claim A** — `<path>` · `<symbol>` · name | signature | docstring | body
88
+
89
+ > Verbatim evidence
90
+
91
+ **Claim B** — `<path>` · `<symbol>` · name | signature | docstring | body
92
+
93
+ > Verbatim evidence
94
+
95
+ **How they differ:** <The observable disagreement.>
96
+
97
+ **Why these should agree:** <Evidence that both claims describe the same
98
+ concept.>
99
+
100
+ ### Symbol-contract findings
101
+
102
+ #### 1. <Summary>
103
+
104
+ <Use the same finding structure.>
105
+ ```
106
+
107
+ Keep both finding headings. If a group has no supported findings, state that
108
+ under its heading. Number findings independently within each group.
109
+
110
+ ## Examples
111
+
112
+ ### Vocabulary finding
113
+
114
+ #### 1. Customer lookup uses competing verbs
115
+
116
+ **Claim A** — `storage.py` · `fetch_customer` · signature
117
+
118
+ > `fetch_customer(customer_id: str) -> Customer`
119
+
120
+ **Claim B** — `adapter.py` · `load_customer` · signature
121
+
122
+ > `load_customer(customer_id: str) -> Customer`
123
+
124
+ **How they differ:** The same lookup uses `fetch` in one module and `load` in
125
+ another.
126
+
127
+ **Why these should agree:** Both signatures accept a customer ID and return a
128
+ customer through sibling adapters.
129
+
130
+ ### Symbol-contract finding
131
+
132
+ #### 1. Predicate name promises a boolean but returns a value
133
+
134
+ **Claim A** — `cache.py` · `is_cached` · name
135
+
136
+ > `is_cached`
137
+
138
+ **Claim B** — `cache.py` · `is_cached` · signature
139
+
140
+ > `is_cached(key: str) -> str | None`
141
+
142
+ **How they differ:** The name promises a predicate, while the return type holds
143
+ a cached value or absence.
144
+
145
+ **Why these should agree:** Both claims describe the contract of `is_cached`.
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: uncoded-doc-navigation
3
+ description: Load once per session, before the first search or read of a codebase's Markdown documentation indexed by uncoded. Covers locating which file and section cover a topic, or orienting to what documentation exists.
4
+ ---
5
+
6
+ <!-- Generated by uncoded — do not edit; regeneration overwrites. -->
7
+
8
+ # Documentation Navigation
9
+
10
+ This codebase uses [uncoded](https://github.com/alimanfoo/uncoded) to maintain a
11
+ documentation index.
12
+
13
+ **Step 1: Orient. Read the docs map first.** If the map is missing, run the
14
+ repository's configured `uncoded sync` command. Then, before answering the user,
15
+ before any other tool call:
16
+
17
+ ```text
18
+ Read .uncoded/docs.yaml
19
+ ```
20
+
21
+ `.uncoded/docs.yaml` is an orientation outline: it lists every Markdown file and
22
+ its heading hierarchy. Read it once, in full, at session start.
23
+
24
+ **Step 2: Navigate.** Headings in the map are literal text. Use `Read` or `grep`
25
+ to navigate to a specific section identified in the map.
26
+
27
+ **Step 3: Refresh.** After every modification to indexed Markdown, run the
28
+ repository's configured `uncoded sync` command before the next
29
+ documentation-navigation operation. The modification can change the heading map.
@@ -32,6 +32,11 @@ repos:
32
32
  entry: uv run ty check src tests
33
33
  language: system
34
34
  pass_filenames: false
35
+ - id: complexipy
36
+ name: complexipy
37
+ entry: uv run complexipy src tests
38
+ language: system
39
+ pass_filenames: false
35
40
  # Runs before uncoded so the generated skill files are built from
36
41
  # already-formatted sources. The generated skill dirs are excluded
37
42
  # because uncoded sync owns those files.
@@ -47,4 +52,5 @@ repos:
47
52
  name: uncoded
48
53
  entry: uv run uncoded sync
49
54
  language: system
55
+ always_run: true
50
56
  pass_filenames: false
@@ -43,7 +43,7 @@ This project uses [uv](https://docs.astral.sh/uv/). Run all commands via
43
43
  install, which may have different behaviour.
44
44
 
45
45
  ```sh
46
- # Generate (or update) the namespace map, stub files, docs.yaml, and skill files
46
+ # Generate or update the navigation artefacts
47
47
  uv run uncoded sync
48
48
 
49
49
  # Verify the index without writing. It exits non-zero if any file would change
@@ -74,6 +74,7 @@ Clone and install dev dependencies:
74
74
  git clone https://github.com/alimanfoo/uncoded
75
75
  cd uncoded
76
76
  uv sync --extra dev
77
+ uv run uncoded sync
77
78
  uv run pre-commit install
78
79
  ```
79
80
 
@@ -83,8 +84,9 @@ packages such as pytest and hypothesis. Without the dev extras in the venv, ty
83
84
  cannot resolve those imports and reports spurious errors.
84
85
 
85
86
  This repo uses uncoded on itself. The pre-commit hook runs `uv run uncoded sync`
86
- on each commit. If the hook modifies generated files, the commit fails. Re-stage
87
- and commit again.
87
+ on each commit. The local `.uncoded/` index is ignored. If the hook modifies a
88
+ tracked generated skill file, the commit fails. Re-stage the skill file and
89
+ commit again.
88
90
 
89
91
  ### Windows
90
92
 
@@ -98,7 +100,8 @@ following the symlink.
98
100
  Run `uv run ruff check --fix` and `uv run ruff format` before committing. Both
99
101
  are pinned via the `dev` optional dependency. The pre-commit hooks run the same
100
102
  commands automatically. If a hook rewrites files, the commit fails. Re-stage the
101
- modified files and commit again. The uncoded sync hook follows the same pattern.
103
+ modified files and commit again. The uncoded sync hook follows the same pattern
104
+ for tracked generated skill files.
102
105
 
103
106
  Never commit with `--no-verify`. CI runs `pre-commit run --all-files` on every
104
107
  pull request and will fail a build where a hook was skipped.
@@ -106,8 +109,10 @@ pull request and will fail a build where a hook was skipped.
106
109
  Do not pass `--unsafe-fixes` unless a specific violation needs it and you have
107
110
  reviewed the change.
108
111
 
109
- A C901 violation means a function is too complex to pass the check. Refactor or
110
- flatten it rather than raising the `max-complexity` threshold.
112
+ A complexity-check violation means a function is too complex to pass. Refactor
113
+ or flatten it. Never suppress a complexity violation with an ignore comment and
114
+ never raise the threshold. The enabled checks and their thresholds are in
115
+ `pyproject.toml`.
111
116
 
112
117
  The ty pre-commit hook runs the type checker. It is pinned via the `dev`
113
118
  optional dependency, the same way ruff is.
@@ -132,8 +137,7 @@ This section names where each cross-cutting convention lives and what keeps it
132
137
  in place.
133
138
 
134
139
  **Provenance marker.** Every generated file carries `GENERATED_MARKER`, defined
135
- in `src/uncoded/markers.py`. `tests/test_markers.py` verifies that all four
136
- output kinds carry it.
140
+ in `src/uncoded/markers.py`. The tests verify that every output kind carries it.
137
141
 
138
142
  **Explicit encoding.** Every text read/write in the repository must pass
139
143
  `encoding=`. Configuration lives in `pyproject.toml` and
@@ -158,12 +162,14 @@ Run tests locally as `PYTHONWARNDEFAULTENCODING=1 uv run pytest`. The sentinel
158
162
  in `tests/test_encoding_gate.py` fails loudly if either the env var is unset or
159
163
  the filterwarnings escalation is removed.
160
164
 
161
- **Complexity ceiling.** The value is in `[tool.ruff.lint.mccabe]` in
162
- `pyproject.toml`. See [Linting and formatting](#linting-and-formatting) for the
163
- response to a C901 violation.
165
+ **Complexity ceiling.** The enabled complexity checks and their thresholds are
166
+ in `pyproject.toml`. See [Linting and formatting](#linting-and-formatting) for
167
+ the response to a violation.
164
168
 
165
- **Index committed.** Commit `.uncoded/` and keep it current with the pre-commit
166
- hook. See [Commands](#commands) and [Dev setup](#dev-setup).
169
+ **Index local.** `uncoded sync` writes `.uncoded/.gitignore`, which keeps the
170
+ whole index out of Git. Run `uv run uncoded sync` after every indexed source or
171
+ documentation change and before using the index again. The pre-commit hook is a
172
+ final refresh. See [Commands](#commands) and [Dev setup](#dev-setup).
167
173
 
168
174
  ## Releasing
169
175
 
@@ -185,7 +191,7 @@ PyPI.
185
191
 
186
192
  ## Before you start
187
193
 
188
- - Load the `uncoded-code-navigation` skill before searching, reading or editing
189
- any code.
190
- - Load the `uncoded-doc-navigation` skill before searching, reading or editing
191
- any docs.
194
+ - Load the `uncoded-code-navigation` skill once per session, before searching,
195
+ reading or editing any code.
196
+ - Load the `uncoded-doc-navigation` skill once per session, before searching,
197
+ reading or editing any docs.