uncoded 2.1.0__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.0/.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.0/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.0 → uncoded-3.0.0}/.github/workflows/ci.yml +2 -0
  8. {uncoded-2.1.0 → uncoded-3.0.0}/.pre-commit-config.yaml +19 -8
  9. uncoded-3.0.0/AGENTS.md +197 -0
  10. {uncoded-2.1.0 → uncoded-3.0.0}/PKG-INFO +65 -126
  11. {uncoded-2.1.0 → uncoded-3.0.0}/README.md +60 -124
  12. uncoded-3.0.0/dreamcatcher.toml +25 -0
  13. uncoded-3.0.0/pyproject.toml +121 -0
  14. {uncoded-2.1.0 → uncoded-3.0.0}/src/uncoded/body.py +1 -1
  15. {uncoded-2.1.0 → uncoded-3.0.0}/src/uncoded/cli.py +151 -104
  16. uncoded-2.1.0/.agents/skills/uncoded-code-navigation/SKILL.md → uncoded-3.0.0/src/uncoded/code_navigation.md +24 -24
  17. {uncoded-2.1.0 → uncoded-3.0.0}/src/uncoded/config.py +48 -40
  18. uncoded-3.0.0/src/uncoded/consistency_review.md +138 -0
  19. uncoded-3.0.0/src/uncoded/doc_navigation.md +22 -0
  20. {uncoded-2.1.0 → uncoded-3.0.0}/src/uncoded/docs_map.py +25 -23
  21. {uncoded-2.1.0 → uncoded-3.0.0}/src/uncoded/extract.py +23 -20
  22. {uncoded-2.1.0 → uncoded-3.0.0}/src/uncoded/namespace_map.py +1 -1
  23. {uncoded-2.1.0 → uncoded-3.0.0}/src/uncoded/read_helpers.py +3 -1
  24. {uncoded-2.1.0 → uncoded-3.0.0}/src/uncoded/refs.py +16 -15
  25. {uncoded-2.1.0 → uncoded-3.0.0}/src/uncoded/resolver.py +52 -35
  26. {uncoded-2.1.0 → uncoded-3.0.0}/src/uncoded/skill.py +69 -44
  27. {uncoded-2.1.0 → uncoded-3.0.0}/src/uncoded/stubs.py +105 -102
  28. {uncoded-2.1.0 → uncoded-3.0.0}/src/uncoded/sync.py +3 -4
  29. {uncoded-2.1.0 → uncoded-3.0.0}/src/uncoded/yaml_tree.py +1 -1
  30. {uncoded-2.1.0 → uncoded-3.0.0}/tests/test_body.py +62 -55
  31. {uncoded-2.1.0 → uncoded-3.0.0}/tests/test_cli.py +211 -104
  32. {uncoded-2.1.0 → uncoded-3.0.0}/tests/test_config.py +39 -36
  33. {uncoded-2.1.0 → uncoded-3.0.0}/tests/test_docs_map.py +9 -0
  34. uncoded-3.0.0/tests/test_encoding_gate.py +25 -0
  35. {uncoded-2.1.0 → uncoded-3.0.0}/tests/test_extract.py +17 -14
  36. uncoded-3.0.0/tests/test_markers.py +21 -0
  37. {uncoded-2.1.0 → uncoded-3.0.0}/tests/test_refs.py +54 -37
  38. {uncoded-2.1.0 → uncoded-3.0.0}/tests/test_skill.py +66 -67
  39. {uncoded-2.1.0 → uncoded-3.0.0}/tests/test_stubs.py +54 -30
  40. {uncoded-2.1.0 → uncoded-3.0.0}/tests/test_sync.py +12 -12
  41. {uncoded-2.1.0 → uncoded-3.0.0}/uv.lock +228 -0
  42. uncoded-2.1.0/.agents/skills/uncoded-coherence-review/SKILL.md +0 -371
  43. uncoded-2.1.0/.agents/skills/uncoded-doc-navigation/SKILL.md +0 -24
  44. uncoded-2.1.0/.claude/skills/uncoded-coherence-review/SKILL.md +0 -371
  45. uncoded-2.1.0/.claude/skills/uncoded-doc-navigation/SKILL.md +0 -24
  46. uncoded-2.1.0/.uncoded/docs.yaml +0 -32
  47. uncoded-2.1.0/.uncoded/namespace.yaml +0 -575
  48. uncoded-2.1.0/.uncoded/stubs/src/uncoded/__init__.pyi +0 -5
  49. uncoded-2.1.0/.uncoded/stubs/src/uncoded/ast_helpers.pyi +0 -9
  50. uncoded-2.1.0/.uncoded/stubs/src/uncoded/body.pyi +0 -12
  51. uncoded-2.1.0/.uncoded/stubs/src/uncoded/cli.pyi +0 -30
  52. uncoded-2.1.0/.uncoded/stubs/src/uncoded/config.pyi +0 -25
  53. uncoded-2.1.0/.uncoded/stubs/src/uncoded/docs_map.pyi +0 -27
  54. uncoded-2.1.0/.uncoded/stubs/src/uncoded/extract.pyi +0 -29
  55. uncoded-2.1.0/.uncoded/stubs/src/uncoded/markers.pyi +0 -3
  56. uncoded-2.1.0/.uncoded/stubs/src/uncoded/namespace_map.pyi +0 -14
  57. uncoded-2.1.0/.uncoded/stubs/src/uncoded/read_helpers.pyi +0 -14
  58. uncoded-2.1.0/.uncoded/stubs/src/uncoded/refs.pyi +0 -55
  59. uncoded-2.1.0/.uncoded/stubs/src/uncoded/resolver.pyi +0 -35
  60. uncoded-2.1.0/.uncoded/stubs/src/uncoded/skill.pyi +0 -31
  61. uncoded-2.1.0/.uncoded/stubs/src/uncoded/stubs.pyi +0 -87
  62. uncoded-2.1.0/.uncoded/stubs/src/uncoded/sync.pyi +0 -9
  63. uncoded-2.1.0/.uncoded/stubs/src/uncoded/yaml_tree.pyi +0 -10
  64. uncoded-2.1.0/.uncoded/stubs/tests/test_body.pyi +0 -148
  65. uncoded-2.1.0/.uncoded/stubs/tests/test_cli.pyi +0 -214
  66. uncoded-2.1.0/.uncoded/stubs/tests/test_config.pyi +0 -61
  67. uncoded-2.1.0/.uncoded/stubs/tests/test_docs_map.pyi +0 -150
  68. uncoded-2.1.0/.uncoded/stubs/tests/test_extract.pyi +0 -85
  69. uncoded-2.1.0/.uncoded/stubs/tests/test_namespace_map.pyi +0 -46
  70. uncoded-2.1.0/.uncoded/stubs/tests/test_refs.pyi +0 -88
  71. uncoded-2.1.0/.uncoded/stubs/tests/test_skill.pyi +0 -99
  72. uncoded-2.1.0/.uncoded/stubs/tests/test_stubs.pyi +0 -232
  73. uncoded-2.1.0/.uncoded/stubs/tests/test_sync.pyi +0 -53
  74. uncoded-2.1.0/.uncoded/stubs/tests/test_uncoded.pyi +0 -9
  75. uncoded-2.1.0/AGENTS.md +0 -80
  76. uncoded-2.1.0/pyproject.toml +0 -82
  77. uncoded-2.1.0/src/uncoded/coherence_review.md +0 -364
  78. uncoded-2.1.0/src/uncoded/doc_navigation.md +0 -17
  79. {uncoded-2.1.0 → uncoded-3.0.0}/.github/workflows/publish.yml +0 -0
  80. {uncoded-2.1.0 → uncoded-3.0.0}/.gitignore +0 -0
  81. {uncoded-2.1.0 → uncoded-3.0.0}/.markdownlint-cli2.yaml +0 -0
  82. {uncoded-2.1.0 → uncoded-3.0.0}/.prettierrc +0 -0
  83. {uncoded-2.1.0 → uncoded-3.0.0}/CLAUDE.md +0 -0
  84. {uncoded-2.1.0 → uncoded-3.0.0}/LICENSE +0 -0
  85. {uncoded-2.1.0 → uncoded-3.0.0}/src/uncoded/__init__.py +0 -0
  86. {uncoded-2.1.0 → uncoded-3.0.0}/src/uncoded/ast_helpers.py +0 -0
  87. {uncoded-2.1.0 → uncoded-3.0.0}/src/uncoded/markers.py +0 -0
  88. {uncoded-2.1.0 → uncoded-3.0.0}/tests/__init__.py +0 -0
  89. {uncoded-2.1.0 → uncoded-3.0.0}/tests/test_namespace_map.py +0 -0
  90. {uncoded-2.1.0 → 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.
@@ -31,3 +31,5 @@ jobs:
31
31
  - run: uv python install ${{ matrix.python-version }}
32
32
  - run: uv sync --extra dev
33
33
  - run: uv run pytest -v -m "integration or not integration"
34
+ env:
35
+ PYTHONWARNDEFAULTENCODING: "1"
@@ -13,18 +13,28 @@ repos:
13
13
  - id: check-toml
14
14
  - id: check-added-large-files
15
15
 
16
- - repo: https://github.com/astral-sh/ruff-pre-commit
17
- rev: v0.15.10
18
- hooks:
19
- - id: ruff
20
- args: [--fix]
21
- - id: ruff-format
22
-
23
16
  - repo: local
24
17
  hooks:
18
+ - id: ruff-check
19
+ name: ruff check
20
+ entry: uv run ruff check --fix --exit-non-zero-on-fix --show-fixes
21
+ language: system
22
+ types_or: [python, pyi]
23
+ pass_filenames: false
24
+ - id: ruff-format
25
+ name: ruff format
26
+ entry: uv run ruff format
27
+ language: system
28
+ types_or: [python, pyi]
29
+ pass_filenames: false
25
30
  - id: ty
26
31
  name: ty
27
- entry: uvx ty check src tests
32
+ entry: uv run ty check src tests
33
+ language: system
34
+ pass_filenames: false
35
+ - id: complexipy
36
+ name: complexipy
37
+ entry: uv run complexipy src tests
28
38
  language: system
29
39
  pass_filenames: false
30
40
  # Runs before uncoded so the generated skill files are built from
@@ -42,4 +52,5 @@ repos:
42
52
  name: uncoded
43
53
  entry: uv run uncoded sync
44
54
  language: system
55
+ always_run: true
45
56
  pass_filenames: false