uncoded 3.0.0__tar.gz → 3.0.1__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.
- {uncoded-3.0.0 → uncoded-3.0.1}/.agents/skills/uncoded-code-navigation/SKILL.md +11 -11
- {uncoded-3.0.0 → uncoded-3.0.1}/.claude/skills/uncoded-code-navigation/SKILL.md +11 -11
- {uncoded-3.0.0 → uncoded-3.0.1}/.github/workflows/ci.yml +2 -2
- uncoded-3.0.1/.github/workflows/docs.yml +43 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/.pre-commit-config.yaml +6 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/AGENTS.md +1 -6
- uncoded-3.0.1/PKG-INFO +35 -0
- uncoded-3.0.1/README.md +19 -0
- uncoded-3.0.1/docs/agent-workflow.md +73 -0
- uncoded-3.0.1/docs/architecture.md +43 -0
- uncoded-3.0.1/docs/commands.md +85 -0
- uncoded-3.0.1/docs/configuration.md +57 -0
- uncoded-3.0.1/docs/contributing.md +73 -0
- uncoded-3.0.1/docs/getting-started.md +83 -0
- uncoded-3.0.1/docs/index.md +79 -0
- uncoded-3.0.1/docs/keeping-current.md +48 -0
- uncoded-3.0.1/docs/stylesheets/extra.css +214 -0
- uncoded-3.0.1/docs/upgrading.md +64 -0
- uncoded-3.0.1/dreamcatcher.toml +39 -0
- uncoded-3.0.1/mkdocs.yml +71 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/pyproject.toml +4 -2
- {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/code_navigation.md +11 -11
- {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/refs.py +6 -3
- {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_refs.py +21 -0
- uncoded-3.0.1/uv.lock +1101 -0
- uncoded-3.0.0/PKG-INFO +0 -318
- uncoded-3.0.0/README.md +0 -294
- uncoded-3.0.0/dreamcatcher.toml +0 -25
- uncoded-3.0.0/uv.lock +0 -580
- {uncoded-3.0.0 → uncoded-3.0.1}/.agents/skills/uncoded-consistency-review/SKILL.md +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/.agents/skills/uncoded-doc-navigation/SKILL.md +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/.claude/skills/uncoded-consistency-review/SKILL.md +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/.claude/skills/uncoded-doc-navigation/SKILL.md +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/.github/workflows/publish.yml +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/.gitignore +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/.markdownlint-cli2.yaml +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/.prettierrc +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/CLAUDE.md +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/LICENSE +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/__init__.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/ast_helpers.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/body.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/cli.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/config.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/consistency_review.md +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/doc_navigation.md +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/docs_map.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/extract.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/markers.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/namespace_map.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/read_helpers.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/resolver.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/skill.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/stubs.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/sync.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/src/uncoded/yaml_tree.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/tests/__init__.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_body.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_cli.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_config.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_docs_map.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_encoding_gate.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_extract.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_markers.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_namespace_map.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_skill.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_stubs.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_sync.py +0 -0
- {uncoded-3.0.0 → uncoded-3.0.1}/tests/test_uncoded.py +0 -0
|
@@ -31,8 +31,8 @@ tools don't.
|
|
|
31
31
|
|
|
32
32
|
## How to execute the rule
|
|
33
33
|
|
|
34
|
-
The index has two parts: a namespace map and per-file stubs.
|
|
35
|
-
|
|
34
|
+
The index has two parts: a namespace map and per-file stubs. Start with the map
|
|
35
|
+
and add detail only when the task needs it.
|
|
36
36
|
|
|
37
37
|
**Step 1: Orient. Read the namespace map first.** If the map is missing, run the
|
|
38
38
|
repository's configured `uncoded sync` command. Then, before answering the user,
|
|
@@ -55,18 +55,18 @@ src/foo/bar.py → .uncoded/stubs/src/foo/bar.pyi
|
|
|
55
55
|
tests/test_foo.py → .uncoded/stubs/tests/test_foo.pyi
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
and
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
The stub contains imports, parameter names and annotations, return types,
|
|
59
|
+
module-level assignments, and class attributes. It omits parameter defaults,
|
|
60
|
+
decorators, docstrings, and function bodies. Read source when the task depends
|
|
61
|
+
on an omitted detail or needs exact code. If no stub exists at the expected
|
|
62
|
+
path, the file has no symbols indexed. In that narrow case, read source
|
|
63
|
+
directly.
|
|
64
64
|
|
|
65
65
|
**Step 3: Act.** Use `uncoded body` to read a symbol's body. Use `uncoded refs`
|
|
66
66
|
to find every reference to a symbol. Use `Edit` (with `uncoded body`'s output as
|
|
67
|
-
`old_string`) to change a symbol.
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
`old_string`) to change a symbol. Use the exact `relative_path` and `name_path`
|
|
68
|
+
from the map. Use `ClassName/method` for a method and `function_name` for a
|
|
69
|
+
top-level function. Per task:
|
|
70
70
|
|
|
71
71
|
- **Read a symbol's body.** `uvx uncoded body <name_path> --in <relative_path>`
|
|
72
72
|
prints the symbol's source text to stdout, byte-identical to disk. Returns
|
|
@@ -31,8 +31,8 @@ tools don't.
|
|
|
31
31
|
|
|
32
32
|
## How to execute the rule
|
|
33
33
|
|
|
34
|
-
The index has two parts: a namespace map and per-file stubs.
|
|
35
|
-
|
|
34
|
+
The index has two parts: a namespace map and per-file stubs. Start with the map
|
|
35
|
+
and add detail only when the task needs it.
|
|
36
36
|
|
|
37
37
|
**Step 1: Orient. Read the namespace map first.** If the map is missing, run the
|
|
38
38
|
repository's configured `uncoded sync` command. Then, before answering the user,
|
|
@@ -55,18 +55,18 @@ src/foo/bar.py → .uncoded/stubs/src/foo/bar.pyi
|
|
|
55
55
|
tests/test_foo.py → .uncoded/stubs/tests/test_foo.pyi
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
and
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
The stub contains imports, parameter names and annotations, return types,
|
|
59
|
+
module-level assignments, and class attributes. It omits parameter defaults,
|
|
60
|
+
decorators, docstrings, and function bodies. Read source when the task depends
|
|
61
|
+
on an omitted detail or needs exact code. If no stub exists at the expected
|
|
62
|
+
path, the file has no symbols indexed. In that narrow case, read source
|
|
63
|
+
directly.
|
|
64
64
|
|
|
65
65
|
**Step 3: Act.** Use `uncoded body` to read a symbol's body. Use `uncoded refs`
|
|
66
66
|
to find every reference to a symbol. Use `Edit` (with `uncoded body`'s output as
|
|
67
|
-
`old_string`) to change a symbol.
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
`old_string`) to change a symbol. Use the exact `relative_path` and `name_path`
|
|
68
|
+
from the map. Use `ClassName/method` for a method and `function_name` for a
|
|
69
|
+
top-level function. Per task:
|
|
70
70
|
|
|
71
71
|
- **Read a symbol's body.** `uvx uncoded body <name_path> --in <relative_path>`
|
|
72
72
|
prints the symbol's source text to stdout, byte-identical to disk. Returns
|
|
@@ -15,7 +15,7 @@ jobs:
|
|
|
15
15
|
fetch-depth: 0
|
|
16
16
|
- uses: astral-sh/setup-uv@v6
|
|
17
17
|
- run: uv python install 3.12
|
|
18
|
-
- run: uv sync
|
|
18
|
+
- run: uv sync
|
|
19
19
|
- run: uv run pre-commit run --all-files
|
|
20
20
|
|
|
21
21
|
test:
|
|
@@ -29,7 +29,7 @@ jobs:
|
|
|
29
29
|
fetch-depth: 0
|
|
30
30
|
- uses: astral-sh/setup-uv@v6
|
|
31
31
|
- run: uv python install ${{ matrix.python-version }}
|
|
32
|
-
- run: uv sync
|
|
32
|
+
- run: uv sync
|
|
33
33
|
- run: uv run pytest -v -m "integration or not integration"
|
|
34
34
|
env:
|
|
35
35
|
PYTHONWARNDEFAULTENCODING: "1"
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: Docs
|
|
2
|
+
|
|
3
|
+
# The site is already built in strict mode by the pull request checks. This
|
|
4
|
+
# workflow repeats that build from main and publishes its output.
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: pages
|
|
15
|
+
cancel-in-progress: false
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
build:
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
22
|
+
with:
|
|
23
|
+
fetch-depth: 0
|
|
24
|
+
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
25
|
+
- run: uv sync --locked
|
|
26
|
+
- run: uv run mkdocs build
|
|
27
|
+
- uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
|
|
28
|
+
with:
|
|
29
|
+
path: site
|
|
30
|
+
|
|
31
|
+
deploy:
|
|
32
|
+
needs: build
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
permissions:
|
|
35
|
+
actions: read
|
|
36
|
+
pages: write
|
|
37
|
+
id-token: write
|
|
38
|
+
environment:
|
|
39
|
+
name: github-pages
|
|
40
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
41
|
+
steps:
|
|
42
|
+
- id: deployment
|
|
43
|
+
uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1
|
|
@@ -48,6 +48,12 @@ repos:
|
|
|
48
48
|
args: ["--write"]
|
|
49
49
|
files: \.md$
|
|
50
50
|
exclude: ^(CLAUDE\.md|(\.claude|\.agents)/skills/.*)$
|
|
51
|
+
- id: mkdocs
|
|
52
|
+
name: build documentation
|
|
53
|
+
entry: uv run mkdocs build
|
|
54
|
+
language: system
|
|
55
|
+
always_run: true
|
|
56
|
+
pass_filenames: false
|
|
51
57
|
- id: uncoded
|
|
52
58
|
name: uncoded
|
|
53
59
|
entry: uv run uncoded sync
|
|
@@ -73,16 +73,11 @@ Clone and install dev dependencies:
|
|
|
73
73
|
```sh
|
|
74
74
|
git clone https://github.com/alimanfoo/uncoded
|
|
75
75
|
cd uncoded
|
|
76
|
-
uv sync
|
|
76
|
+
uv sync
|
|
77
77
|
uv run uncoded sync
|
|
78
78
|
uv run pre-commit install
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
-
Run `uv sync --extra dev` before the first pre-commit run in a clean checkout.
|
|
82
|
-
The ty hook type-checks `src` and `tests`. The test modules import dev-only
|
|
83
|
-
packages such as pytest and hypothesis. Without the dev extras in the venv, ty
|
|
84
|
-
cannot resolve those imports and reports spurious errors.
|
|
85
|
-
|
|
86
81
|
This repo uses uncoded on itself. The pre-commit hook runs `uv run uncoded sync`
|
|
87
82
|
on each commit. The local `.uncoded/` index is ignored. If the hook modifies a
|
|
88
83
|
tracked generated skill file, the commit fails. Re-stage the skill file and
|
uncoded-3.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: uncoded
|
|
3
|
+
Version: 3.0.1
|
|
4
|
+
Summary: Symbol index with associated code reading tools for AI coding agent navigation
|
|
5
|
+
Project-URL: Homepage, https://github.com/alimanfoo/uncoded
|
|
6
|
+
Project-URL: Repository, https://github.com/alimanfoo/uncoded
|
|
7
|
+
Author-email: Alistair Miles <alimanfoo@googlemail.com>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Requires-Python: >=3.12
|
|
14
|
+
Requires-Dist: pyyaml>=6.0
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# uncoded
|
|
18
|
+
|
|
19
|
+
AI coding agents navigate codebases poorly. They grep for guessed keywords, skim
|
|
20
|
+
the first few lines of files, and fill gaps from pretraining rather than reading
|
|
21
|
+
the actual code. The result is plausible-looking output built on a hallucinated
|
|
22
|
+
understanding of the code.
|
|
23
|
+
|
|
24
|
+
**uncoded** builds a static navigation index that gives coding agents
|
|
25
|
+
progressively deeper views of a codebase. Agents start with the namespace map,
|
|
26
|
+
read compact stubs when they need parameters and types, and retrieve only the
|
|
27
|
+
symbol bodies that they need. Each view adds detail without making the agent
|
|
28
|
+
read whole source files.
|
|
29
|
+
|
|
30
|
+
The `uncoded body` command retrieves symbol bodies, and `uncoded refs` finds
|
|
31
|
+
every reference to a symbol. References cover callers, dead-symbol checks, and
|
|
32
|
+
the full set of sites to update before a rename.
|
|
33
|
+
|
|
34
|
+
Read the [documentation](https://alimanfoo.github.io/uncoded/) for installation,
|
|
35
|
+
configuration, command reference, upgrades, and contributor guidance.
|
uncoded-3.0.1/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# uncoded
|
|
2
|
+
|
|
3
|
+
AI coding agents navigate codebases poorly. They grep for guessed keywords, skim
|
|
4
|
+
the first few lines of files, and fill gaps from pretraining rather than reading
|
|
5
|
+
the actual code. The result is plausible-looking output built on a hallucinated
|
|
6
|
+
understanding of the code.
|
|
7
|
+
|
|
8
|
+
**uncoded** builds a static navigation index that gives coding agents
|
|
9
|
+
progressively deeper views of a codebase. Agents start with the namespace map,
|
|
10
|
+
read compact stubs when they need parameters and types, and retrieve only the
|
|
11
|
+
symbol bodies that they need. Each view adds detail without making the agent
|
|
12
|
+
read whole source files.
|
|
13
|
+
|
|
14
|
+
The `uncoded body` command retrieves symbol bodies, and `uncoded refs` finds
|
|
15
|
+
every reference to a symbol. References cover callers, dead-symbol checks, and
|
|
16
|
+
the full set of sites to update before a rename.
|
|
17
|
+
|
|
18
|
+
Read the [documentation](https://alimanfoo.github.io/uncoded/) for installation,
|
|
19
|
+
configuration, command reference, upgrades, and contributor guidance.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Agent workflow
|
|
2
|
+
|
|
3
|
+
The generated skills tell your agent when to load the index, read source, and
|
|
4
|
+
check references. Once you have [set up the repository](getting-started.md), the
|
|
5
|
+
agent follows this workflow during a coding task.
|
|
6
|
+
|
|
7
|
+
## Start a task
|
|
8
|
+
|
|
9
|
+
The agent loads `.uncoded/namespace.yaml` in full to learn the Python symbols
|
|
10
|
+
that exist. For a documentation task, it loads `.uncoded/docs.yaml` to find the
|
|
11
|
+
relevant file and heading.
|
|
12
|
+
|
|
13
|
+
Navigation skills load once per session. Their instructions apply throughout the
|
|
14
|
+
session.
|
|
15
|
+
|
|
16
|
+
## Read code
|
|
17
|
+
|
|
18
|
+
The agent adds detail only when the task needs it. This progressive disclosure
|
|
19
|
+
keeps broad work on compact views and limits source reads to the implementations
|
|
20
|
+
that matter.
|
|
21
|
+
|
|
22
|
+
1. The namespace map shows every indexed symbol and its file. It is often enough
|
|
23
|
+
for questions about structure or where a feature lives.
|
|
24
|
+
2. The file's stub under `.uncoded/stubs/` adds imports, parameter names and
|
|
25
|
+
annotations, return types, constants, and attributes. It omits parameter
|
|
26
|
+
defaults, decorators, docstrings, and function bodies. It is often enough for
|
|
27
|
+
questions about names and types.
|
|
28
|
+
3. `uncoded body` returns one symbol's exact source when the task needs it:
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
uvx uncoded body greet --in src/greetings.py
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
This example assumes `greet` is defined in `src/greetings.py`. For a method, use
|
|
35
|
+
`ClassName/method_name`. See [the command reference](commands.md#body) for
|
|
36
|
+
supported symbols and paths.
|
|
37
|
+
|
|
38
|
+
A file with no indexed symbols has no stub, so the agent reads the file
|
|
39
|
+
directly. Free text and patterns still belong in a text search.
|
|
40
|
+
|
|
41
|
+
## Change a symbol
|
|
42
|
+
|
|
43
|
+
Before renaming, changing a signature, or deleting a symbol, the agent checks
|
|
44
|
+
its references:
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
uvx uncoded refs greet --in src/greetings.py
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The results identify the sites to inspect and update. After changing indexed
|
|
51
|
+
Python or Markdown files, the agent runs `uncoded sync` before navigating again.
|
|
52
|
+
|
|
53
|
+
## Review consistency
|
|
54
|
+
|
|
55
|
+
With `source-roots` configured, uncoded also generates a consistency review
|
|
56
|
+
skill. It looks for concrete disagreements between names, signatures,
|
|
57
|
+
docstrings, and behavior. Every finding must quote both conflicting claims and
|
|
58
|
+
show that they describe the same concept.
|
|
59
|
+
|
|
60
|
+
Invoke it with `$uncoded-consistency-review` in Codex or
|
|
61
|
+
`/uncoded-consistency-review` in Claude Code.
|
|
62
|
+
|
|
63
|
+
## Know the limits
|
|
64
|
+
|
|
65
|
+
The code index describes static Python structure. It does not run imports or
|
|
66
|
+
resolve runtime registration. Files that cannot be parsed or decoded are skipped
|
|
67
|
+
with a warning.
|
|
68
|
+
|
|
69
|
+
The documentation index records headings that begin with `#`. It excludes
|
|
70
|
+
underlined headings and headings inside fenced code blocks. Read documentation
|
|
71
|
+
sections directly; `body` and `refs` operate on Python symbols.
|
|
72
|
+
|
|
73
|
+
Keep using tests and type checks to verify changes.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
uncoded builds static code and documentation indexes. The CLI reads the
|
|
4
|
+
configuration, validates roots, and coordinates extraction and file writes.
|
|
5
|
+
|
|
6
|
+
## Sync pipeline
|
|
7
|
+
|
|
8
|
+
| Module | Responsibility |
|
|
9
|
+
| ------------------ | ----------------------------------------------------------------------------------------- |
|
|
10
|
+
| `config.py` | Finds the nearest configuration and resolves the project root. |
|
|
11
|
+
| `cli.py` | Validates roots and dispatches the configured work. |
|
|
12
|
+
| `extract.py` | Extracts symbols from parseable Python files. |
|
|
13
|
+
| `namespace_map.py` | Renders the Python hierarchy as YAML. |
|
|
14
|
+
| `stubs.py` | Extracts imports, signatures, and assignments into a mirrored `.pyi` tree. |
|
|
15
|
+
| `docs_map.py` | Extracts Markdown headings and renders their hierarchy as YAML. |
|
|
16
|
+
| `skill.py` | Writes navigation and consistency review skills to both agent directories. |
|
|
17
|
+
| `sync.py` | Writes and removes files only when needed; reports changes without writing in check mode. |
|
|
18
|
+
|
|
19
|
+
Code and documentation indexes are independent. Removing a root type removes its
|
|
20
|
+
generated index and skills on the next sync.
|
|
21
|
+
|
|
22
|
+
The skill instructions ship as Markdown package resources. `skill.py` renders
|
|
23
|
+
them into repository skill files. `markers.py` defines the provenance marker
|
|
24
|
+
shared by every generated output.
|
|
25
|
+
|
|
26
|
+
## Symbol tools
|
|
27
|
+
|
|
28
|
+
`resolver.py` locates a named Python symbol in the abstract syntax tree and
|
|
29
|
+
records its source position. `body.py` uses that location to return the original
|
|
30
|
+
source text.
|
|
31
|
+
|
|
32
|
+
`refs.py` sends the position to a one-shot `ty` language server, then sorts and
|
|
33
|
+
formats the returned references. `ty` resolves the references; uncoded provides
|
|
34
|
+
the command and output format.
|
|
35
|
+
|
|
36
|
+
## Path boundary
|
|
37
|
+
|
|
38
|
+
`sync` and `check` anchor all generated files at the configuration file's parent
|
|
39
|
+
directory. Every configured root must remain inside that directory after
|
|
40
|
+
resolving symbolic links.
|
|
41
|
+
|
|
42
|
+
`body` and `refs` resolve their `--in` paths from the current working directory.
|
|
43
|
+
They can operate without a project configuration.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Commands
|
|
2
|
+
|
|
3
|
+
Run uncoded with `uvx uncoded`. Contributors use `uv run uncoded` to run the
|
|
4
|
+
code in their checkout.
|
|
5
|
+
|
|
6
|
+
| To… | Use |
|
|
7
|
+
| ------------------------------------- | --------------------------------------- |
|
|
8
|
+
| Build or refresh the index and skills | `uvx uncoded sync` |
|
|
9
|
+
| Check generated files without writing | `uvx uncoded check` |
|
|
10
|
+
| Read a Python symbol's source | `uvx uncoded body <symbol> --in <file>` |
|
|
11
|
+
| Find references to a Python symbol | `uvx uncoded refs <symbol> --in <file>` |
|
|
12
|
+
|
|
13
|
+
## `sync`
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
uvx uncoded sync
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Builds or refreshes every configured index and navigation skill. Output lists
|
|
20
|
+
files created, updated, or removed. Running it from a subdirectory produces
|
|
21
|
+
output at the same project root.
|
|
22
|
+
|
|
23
|
+
Files that cannot be parsed or decoded are skipped with a warning. Invalid
|
|
24
|
+
configuration or roots cause exit status `1`.
|
|
25
|
+
|
|
26
|
+
## `check`
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
uvx uncoded check
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Runs the same pipeline as `sync` without changing files.
|
|
33
|
+
|
|
34
|
+
| Status | Meaning |
|
|
35
|
+
| ------ | ------------------------------------------------------------------------------ |
|
|
36
|
+
| `0` | All generated files match a fresh build. |
|
|
37
|
+
| `1` | A file would be created, updated, or removed, or the configuration is invalid. |
|
|
38
|
+
|
|
39
|
+
Run `sync` first in a fresh checkout. The local index is not committed.
|
|
40
|
+
|
|
41
|
+
## `body`
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
uvx uncoded body greet --in src/greetings.py
|
|
45
|
+
uvx uncoded body Greeter/greet --in src/greetings.py
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Prints the named symbol's source to standard output, exactly as written in the
|
|
49
|
+
file. These examples assume a `greet` function or a `Greeter.greet` method in
|
|
50
|
+
`src/greetings.py`.
|
|
51
|
+
|
|
52
|
+
Use one name for a top-level function, class, module assignment, or Python 3.12
|
|
53
|
+
`type` alias. Use `Class/member` for a method or class attribute. Deeper paths
|
|
54
|
+
and empty segments are unsupported.
|
|
55
|
+
|
|
56
|
+
The `--in` path is relative to your current directory, not the configuration
|
|
57
|
+
file. No project configuration is required.
|
|
58
|
+
|
|
59
|
+
## `refs`
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
uvx uncoded refs greet --in src/greetings.py
|
|
63
|
+
uvx uncoded refs Greeter/greet --in src/greetings.py
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Finds references to the symbol. Names and `--in` paths follow the same rules as
|
|
67
|
+
`body`. Each result is printed as:
|
|
68
|
+
|
|
69
|
+
```text
|
|
70
|
+
path:line:column
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Positions are one-based. Results are sorted by path and position. Paths within
|
|
74
|
+
the current directory are relative; other paths are absolute. Empty output with
|
|
75
|
+
exit status `0` means no references were found.
|
|
76
|
+
|
|
77
|
+
Reference resolution uses the pinned `ty` language server through `uvx`. The
|
|
78
|
+
first call may download it. `uvx` must be on `PATH`.
|
|
79
|
+
|
|
80
|
+
## Lookup errors
|
|
81
|
+
|
|
82
|
+
`body` and `refs` exit with status `1` if the source cannot be read or parsed,
|
|
83
|
+
the symbol is missing, or its name path is unsupported. A reference lookup also
|
|
84
|
+
fails if the language server fails. Missing required arguments exit with status
|
|
85
|
+
`2`.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
Use one configuration file in your repository root. Choose the directories
|
|
4
|
+
containing Python code and the files or directories containing Markdown docs.
|
|
5
|
+
|
|
6
|
+
## Choose a configuration file
|
|
7
|
+
|
|
8
|
+
For a standalone configuration, use `.uncoded.toml`:
|
|
9
|
+
|
|
10
|
+
```toml title=".uncoded.toml"
|
|
11
|
+
source-roots = ["src", "tests"]
|
|
12
|
+
doc-roots = ["README.md", "docs"]
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
To keep the settings in `pyproject.toml`, add a section there instead:
|
|
16
|
+
|
|
17
|
+
```toml title="pyproject.toml"
|
|
18
|
+
[tool.uncoded]
|
|
19
|
+
source-roots = ["src", "tests"]
|
|
20
|
+
doc-roots = ["README.md", "docs"]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Both formats work in Python and non-Python repositories. At least one root list
|
|
24
|
+
must be non-empty. You can configure either type on its own.
|
|
25
|
+
|
|
26
|
+
## Settings
|
|
27
|
+
|
|
28
|
+
| Setting | Accepted paths | Indexed content |
|
|
29
|
+
| -------------- | ------------------------------------- | ------------------------------ |
|
|
30
|
+
| `source-roots` | Directories | Python symbols and signatures. |
|
|
31
|
+
| `doc-roots` | Directories or individual `.md` files | Markdown headings. |
|
|
32
|
+
|
|
33
|
+
Every path is relative to the configuration file's directory and must exist.
|
|
34
|
+
Paths that resolve outside that directory are rejected, including through
|
|
35
|
+
symbolic links.
|
|
36
|
+
|
|
37
|
+
uncoded searches upwards from the current directory and uses the nearest
|
|
38
|
+
configuration. In one directory, `.uncoded.toml` takes precedence over a
|
|
39
|
+
`pyproject.toml` without `[tool.uncoded]`. If both files configure uncoded, the
|
|
40
|
+
command fails. Keep the settings in one file.
|
|
41
|
+
|
|
42
|
+
## Generated files
|
|
43
|
+
|
|
44
|
+
| Output | When generated | Commit it? |
|
|
45
|
+
| --------------------------------------------- | ---------------------- | ---------- |
|
|
46
|
+
| `.uncoded/namespace.yaml` | `source-roots` is set. | No. |
|
|
47
|
+
| `.uncoded/stubs/` | `source-roots` is set. | No. |
|
|
48
|
+
| `.uncoded/docs.yaml` | `doc-roots` is set. | No. |
|
|
49
|
+
| Code navigation and consistency review skills | `source-roots` is set. | Yes. |
|
|
50
|
+
| Documentation navigation skill | `doc-roots` is set. | Yes. |
|
|
51
|
+
|
|
52
|
+
The index's generated `.gitignore` keeps `.uncoded/` out of Git. Skills are
|
|
53
|
+
written to both `.agents/skills/` and `.claude/skills/`.
|
|
54
|
+
|
|
55
|
+
When you remove a root type and run `sync`, uncoded removes that type's index
|
|
56
|
+
and skills. Every generated file has a provenance marker. Change generated files
|
|
57
|
+
by running `sync`, rather than editing them by hand.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Use Python 3.12 or later and [uv](https://docs.astral.sh/uv/).
|
|
4
|
+
|
|
5
|
+
## Set up a checkout
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
git clone https://github.com/alimanfoo/uncoded
|
|
9
|
+
cd uncoded
|
|
10
|
+
uv sync
|
|
11
|
+
uv run uncoded sync
|
|
12
|
+
uv run pre-commit install
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The development dependency group includes tests, linting, type checking,
|
|
16
|
+
documentation, and pre-commit tools. The local index is ignored by Git, so build
|
|
17
|
+
it before navigating the checkout.
|
|
18
|
+
|
|
19
|
+
On Windows, enable symbolic links before cloning:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
git config --global core.symlinks true
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This lets Git check out `CLAUDE.md` as the symbolic link to `AGENTS.md`.
|
|
26
|
+
|
|
27
|
+
## Run the tests
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
uv run python -X warn_default_encoding -m pytest -q --tb=short
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The suite requires complete branch coverage. The Python option enables
|
|
34
|
+
`EncodingWarning`, which the test configuration turns into an error.
|
|
35
|
+
|
|
36
|
+
For a focused run without the repository-wide coverage gate:
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
uv run python -X warn_default_encoding -m pytest -q --tb=short tests/test_stubs.py --no-cov
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Run the checks
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
uv run pre-commit run --all-files
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The suite runs formatters, linters, type and complexity checks, the strict
|
|
49
|
+
documentation build, and `uncoded sync`. If a hook changes files, stage the
|
|
50
|
+
changes and run the suite again. Never commit with `--no-verify`.
|
|
51
|
+
|
|
52
|
+
## Edit the docs
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
uv run mkdocs serve
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Preview the site at `http://127.0.0.1:8000/`. Run `uv run mkdocs build` to check
|
|
59
|
+
links, anchors, and navigation. The strict build treats warnings as errors.
|
|
60
|
+
|
|
61
|
+
## Change indexed content
|
|
62
|
+
|
|
63
|
+
After editing Python code or indexed Markdown, run `uv run uncoded sync` before
|
|
64
|
+
navigating again. Commit any changed generated skill files with the sources that
|
|
65
|
+
produced them. Read
|
|
66
|
+
[AGENTS.md](https://github.com/alimanfoo/uncoded/blob/main/AGENTS.md) for the
|
|
67
|
+
code and testing conventions.
|
|
68
|
+
|
|
69
|
+
## Release
|
|
70
|
+
|
|
71
|
+
Publish a GitHub release from its version tag. `.github/workflows/publish.yml`
|
|
72
|
+
builds the source distribution and wheel and uploads them with PyPI Trusted
|
|
73
|
+
Publishing. The repository does not store a PyPI token.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Get started
|
|
2
|
+
|
|
3
|
+
Set up uncoded in your repository, then ask your agent to use the index. You
|
|
4
|
+
need [uv](https://docs.astral.sh/uv/getting-started/installation/). `uvx` runs
|
|
5
|
+
uncoded on demand; there is no separate install step.
|
|
6
|
+
|
|
7
|
+
<span id="install-uv"></span> <span id="choose-a-configuration-file"></span>
|
|
8
|
+
|
|
9
|
+
## 1. Choose what to index
|
|
10
|
+
|
|
11
|
+
Create `.uncoded.toml` in your repository root:
|
|
12
|
+
|
|
13
|
+
```toml title=".uncoded.toml"
|
|
14
|
+
source-roots = ["src", "tests"]
|
|
15
|
+
doc-roots = ["README.md", "docs"]
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Replace these paths with directories and files that exist in your repository.
|
|
19
|
+
`source-roots` indexes Python files. `doc-roots` indexes Markdown headings.
|
|
20
|
+
Remove either line if you only need the other index.
|
|
21
|
+
|
|
22
|
+
<span id="build-the-index"></span>
|
|
23
|
+
|
|
24
|
+
## 2. Build the index
|
|
25
|
+
|
|
26
|
+
Run from your repository root:
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
uvx uncoded sync
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The command prints the files it creates. With both root types configured, you
|
|
33
|
+
will find:
|
|
34
|
+
|
|
35
|
+
| Output | Purpose |
|
|
36
|
+
| --------------------------------------- | ------------------------------------------------------- |
|
|
37
|
+
| `.uncoded/namespace.yaml` | Lists Python symbols and their locations. |
|
|
38
|
+
| `.uncoded/stubs/` | Records imports, signatures, constants, and attributes. |
|
|
39
|
+
| `.uncoded/docs.yaml` | Lists Markdown files and headings. |
|
|
40
|
+
| `.agents/skills/` and `.claude/skills/` | Give agents the navigation instructions. |
|
|
41
|
+
|
|
42
|
+
Commit the generated skill files. The `.uncoded/` index stays local and is
|
|
43
|
+
ignored by Git.
|
|
44
|
+
|
|
45
|
+
<span id="tell-agents-to-use-the-skills"></span>
|
|
46
|
+
|
|
47
|
+
## 3. Tell your agent to use it
|
|
48
|
+
|
|
49
|
+
Add these instructions to your repository's `AGENTS.md` or `CLAUDE.md`:
|
|
50
|
+
|
|
51
|
+
```text title="Agent instructions"
|
|
52
|
+
## Before you start
|
|
53
|
+
|
|
54
|
+
- Load the `uncoded-code-navigation` skill once per session, before searching, reading or editing any code.
|
|
55
|
+
- Load the `uncoded-doc-navigation` skill once per session, before searching, reading or editing any docs.
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Keep only the lines for the root types you configured.
|
|
59
|
+
|
|
60
|
+
## 4. Try a task
|
|
61
|
+
|
|
62
|
+
Start a new agent session in the repository and ask:
|
|
63
|
+
|
|
64
|
+
```text title="Example prompt"
|
|
65
|
+
Explain this repository using the uncoded navigation skills.
|
|
66
|
+
Read the index first, then show me one function or documentation section
|
|
67
|
+
that explains how the project works.
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
For Python code, the agent should move from `.uncoded/namespace.yaml` to a
|
|
71
|
+
matching stub and then to `uncoded body` as it needs more detail. The agent can
|
|
72
|
+
stop after the map or stub when that view answers the question. For
|
|
73
|
+
documentation, it should load `.uncoded/docs.yaml` and read the relevant
|
|
74
|
+
section.
|
|
75
|
+
|
|
76
|
+
<span id="keep-the-index-current"></span>
|
|
77
|
+
|
|
78
|
+
When you change indexed code or docs, run `uvx uncoded sync` again before
|
|
79
|
+
navigating. [Keep the index current](keeping-current.md) explains how to
|
|
80
|
+
automate this with pre-commit.
|
|
81
|
+
|
|
82
|
+
See [Configuration](configuration.md) to use `pyproject.toml` or change the
|
|
83
|
+
indexed paths.
|