agent-codinglanguage-mapper 1.0.0__tar.gz → 1.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/PKG-INFO +69 -5
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/README.md +68 -4
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/pyproject.toml +1 -1
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/__init__.py +6 -1
- agent_codinglanguage_mapper-1.1.0/src/agent_codinglanguage_mapper/_version.py +1 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/cli.py +62 -7
- agent_codinglanguage_mapper-1.1.0/src/agent_codinglanguage_mapper/formatting.py +476 -0
- agent_codinglanguage_mapper-1.1.0/src/agent_codinglanguage_mapper/guidelines.py +968 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/integration.py +1 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/lsp_server.py +1 -1
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/templates/opencode/plugins/codebase_map.ts +73 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/templates/skill/SKILL.md +10 -1
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper.egg-info/PKG-INFO +69 -5
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper.egg-info/SOURCES.txt +4 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/tests/test_cli.py +37 -1
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/tests/test_delphi_adapter.py +17 -0
- agent_codinglanguage_mapper-1.1.0/tests/test_guideline_formatting.py +342 -0
- agent_codinglanguage_mapper-1.1.0/tests/test_guidelines.py +378 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/tests/test_integration_install.py +14 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/tests/test_lsp_server.py +1 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/tests/test_opencode_e2e_harness.py +38 -5
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/tests/test_package_contract.py +23 -2
- agent_codinglanguage_mapper-1.0.0/src/agent_codinglanguage_mapper/_version.py +0 -2
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/LICENSE +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/setup.cfg +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/__main__.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/adapters/__init__.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/adapters/delphi.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/adapters/delphi_frontend/__init__.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/adapters/delphi_frontend/comment_builder.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/adapters/delphi_frontend/consts.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/adapters/delphi_frontend/grammar.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/adapters/delphi_frontend/lark_builder.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/adapters/delphi_frontend/lark_tokens.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/adapters/delphi_frontend/lsp_server.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/adapters/delphi_frontend/nodes.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/adapters/delphi_frontend/parser.py +1 -1
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/adapters/delphi_frontend/preprocessor.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/adapters/delphi_frontend/project_discovery.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/adapters/delphi_frontend/project_indexer.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/adapters/delphi_frontend/semantic.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/adapters/delphi_frontend/semantic_builder.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/adapters/delphi_frontend/source_reader.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/adapters/delphi_frontend/workspace.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/adapters/tree_sitter.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/discovery.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/indexer.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/lsp_service.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/mapper.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/models.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/protocol.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/rendering.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/worker.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper/workspace.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper.egg-info/dependency_links.txt +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper.egg-info/entry_points.txt +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper.egg-info/requires.txt +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/src/agent_codinglanguage_mapper.egg-info/top_level.txt +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/tests/test_adapters.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/tests/test_discovery.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/tests/test_ffi.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/tests/test_indexer.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/tests/test_language_matrix.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/tests/test_large_files.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/tests/test_lsp_service.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/tests/test_mapper_details.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/tests/test_performance_harness.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/tests/test_protocol.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/tests/test_rendering.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/tests/test_worker.py +0 -0
- {agent_codinglanguage_mapper-1.0.0 → agent_codinglanguage_mapper-1.1.0}/tests/test_workspace.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-codinglanguage-mapper
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: Agent-focused semantic mapping and language services for mixed-language codebases.
|
|
5
5
|
Author: Dark Light
|
|
6
6
|
License-Expression: MPL-2.0
|
|
@@ -47,7 +47,7 @@ Dynamic: license-file
|
|
|
47
47
|
|
|
48
48
|
# Agent Coding Language Mapper
|
|
49
49
|
|
|
50
|
-
`agent-codinglanguage-mapper` gives coding agents a bounded semantic view of mixed-language repositories. It maps Python, Rust, C#, Delphi, and C++ into one language-neutral index and exposes that index through a Python API, a command-line interface, Protocol 3, an LSP server, and an OpenCode skill/plugin pair.
|
|
50
|
+
`agent-codinglanguage-mapper` gives coding agents a bounded semantic view of mixed-language repositories. It maps Python, Rust, C#, Delphi, and C++ into one language-neutral index and exposes that index through a Python API, a command-line interface, Protocol 3, an LSP server, and an OpenCode skill/plugin pair. It also detects repository coding conventions, audits source against them, and produces reviewable formatting patches before any explicit write.
|
|
51
51
|
|
|
52
52
|
The mapper is designed for code investigation without sending whole files through `grep`, `cat`, or generic file-reading tools. Responses are paginated, carry stable target IDs and source citations, distinguish proven from partial relations, and preserve focus across follow-up requests.
|
|
53
53
|
|
|
@@ -99,6 +99,8 @@ The public types are:
|
|
|
99
99
|
- `Project` and `SourceFile`
|
|
100
100
|
- `Symbol`, `Reference`, and `Relation`
|
|
101
101
|
- `Problem` and `SourceRange`
|
|
102
|
+
- `CodingGuidelines`
|
|
103
|
+
- `GuidelineProfile`, `GuidelineFinding`, `GuidelineChange`, and `GuidelineReport`
|
|
102
104
|
|
|
103
105
|
Parser-native nodes are intentionally private. Ranges are zero-based and half-open. Rendered citations use one-based line numbers, for example `src/payment.py:42`.
|
|
104
106
|
|
|
@@ -124,6 +126,16 @@ codinglanguage-mapper index --root . --out .mapper/index.json
|
|
|
124
126
|
# Discovery and parser diagnostics
|
|
125
127
|
codinglanguage-mapper doctor --root . --format json
|
|
126
128
|
|
|
129
|
+
# Detect and audit repository coding conventions
|
|
130
|
+
codinglanguage-mapper guidelines detect --root . --format json
|
|
131
|
+
codinglanguage-mapper guidelines audit --root . --format json
|
|
132
|
+
|
|
133
|
+
# Preview a deterministic patch; this never changes source files
|
|
134
|
+
codinglanguage-mapper guidelines format --root .
|
|
135
|
+
|
|
136
|
+
# Apply the reviewed plan atomically
|
|
137
|
+
codinglanguage-mapper guidelines format --root . --write
|
|
138
|
+
|
|
127
139
|
# Language Server Protocol over stdio
|
|
128
140
|
codinglanguage-mapper lsp --root .
|
|
129
141
|
|
|
@@ -133,6 +145,43 @@ codinglanguage-mapper worker --root .
|
|
|
133
145
|
|
|
134
146
|
Available view layers are `overview`, `projects`, `languages`, `files`, `file`, `symbols`, `symbol`, `implementation`, `references`, and `problems`.
|
|
135
147
|
|
|
148
|
+
## Coding Guidelines and Formatting
|
|
149
|
+
|
|
150
|
+
The guidelines API uses the mapper's normal project discovery and language detection, so one request can audit a mixed Python, Rust, C#, Delphi, and C++ workspace. Detection is file-specific rather than one profile for the entire repository. Defaults are refined by language configuration and then by the nearest applicable `.editorconfig`, which has the highest precedence.
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
from agent_codinglanguage_mapper import CodingGuidelines
|
|
154
|
+
|
|
155
|
+
guidelines = CodingGuidelines.open(".", languages="auto")
|
|
156
|
+
detected = guidelines.detect()
|
|
157
|
+
audit = guidelines.audit()
|
|
158
|
+
|
|
159
|
+
# A stable unified diff for agent or human review; no files are changed.
|
|
160
|
+
patch = guidelines.patch()
|
|
161
|
+
print(patch)
|
|
162
|
+
|
|
163
|
+
# Mutation is rejected unless write=True is explicit.
|
|
164
|
+
plan = guidelines.plan()
|
|
165
|
+
applied = guidelines.apply(plan, write=True)
|
|
166
|
+
print(applied.to_mapping())
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
`detect()` reports the effective profile and its configuration sources. `audit()` returns exact zero-based, half-open ranges for line length, indentation, line endings, trailing whitespace, and final-newline findings. Invalid supported values and unsupported EditorConfig properties are reported as non-fixable configuration findings; affected rules retain their previous effective value. Agents can use those findings to make source-aware improvements that are outside the formatter's conservative scope. `plan()` records original-content hashes, the guideline-configuration revision, and the exact replacement bytes. `apply()` rejects stale plans after either source or configuration changes, workspace-escaping paths, and symlinks; accepted writes use a same-directory temporary file and atomic replacement.
|
|
170
|
+
|
|
171
|
+
The built-in formatter safely normalizes configured line endings, removes trailing whitespace outside protected multiline string literals, and applies the configured final-newline rule while preserving UTF-8 BOM, UTF-16, and legacy single-byte source encodings. When installed and runnable, the package delegates broader formatting to the language's established tool and validates the result with the mapper before planning it:
|
|
172
|
+
|
|
173
|
+
| Language | Detected configuration | Preferred formatter |
|
|
174
|
+
| --- | --- | --- |
|
|
175
|
+
| Python | `pyproject.toml` (`ruff`) and `.editorconfig` | Ruff, then Black |
|
|
176
|
+
| Rust | `rustfmt.toml`, `.rustfmt.toml`, and `.editorconfig` | `rustfmt` |
|
|
177
|
+
| C# | `.editorconfig` common whitespace rules | `dotnet format whitespace` in an isolated temporary copy |
|
|
178
|
+
| Delphi | RAD Studio-compatible defaults and `.editorconfig` | Built-in conservative formatter |
|
|
179
|
+
| C++ | `.clang-format`, `_clang-format`, and `.editorconfig` | `clang-format` |
|
|
180
|
+
|
|
181
|
+
Native formatter executables are optional and are never downloaded or installed by this package. A missing tool selects the built-in formatter. A timeout, nonzero exit, invalid output, or other native failure also falls back to the built-in formatter and emits a structured `native-formatter-failed` finding instead of discarding the audit. No formatter command is executed through a shell.
|
|
182
|
+
|
|
183
|
+
`guidelines audit` exits with status 1 when findings exist, making it suitable for CI. `guidelines format` without `--write` always prints the unified diff and leaves the workspace untouched. The only mutating CLI form is `guidelines format --write`.
|
|
184
|
+
|
|
136
185
|
## Protocol 3
|
|
137
186
|
|
|
138
187
|
Protocol 3 is the bounded request/response contract used by the worker and OpenCode plugin.
|
|
@@ -284,7 +333,20 @@ This creates:
|
|
|
284
333
|
opencode.json
|
|
285
334
|
```
|
|
286
335
|
|
|
287
|
-
The generated `mixed-codebase-navigator` agent denies all tools by default and permits only `skill` and `
|
|
336
|
+
The generated `mixed-codebase-navigator` agent denies all tools by default and permits only `skill`, `codebase_map`, and `code_guidelines`. The plugin maps the active OpenCode directory, serializes Protocol 3 requests through one worker, applies a hard timeout, reports bounded worker `stderr`, restarts after failure, and preserves focus plus warm parser indexes across short idle gaps. It stops the worker when the session is deleted or after 60 seconds without another mapper request.
|
|
337
|
+
|
|
338
|
+
`code_guidelines` exposes four actions: `detect`, `audit`, `patch`, and `apply`. The first three are read-only. `apply` is rejected unless its request contains `write: true`, so the agent must inspect a patch before it can opt into mutation.
|
|
339
|
+
|
|
340
|
+
```json
|
|
341
|
+
{
|
|
342
|
+
"permission": {
|
|
343
|
+
"*": "deny",
|
|
344
|
+
"skill": "allow",
|
|
345
|
+
"codebase_map": "allow",
|
|
346
|
+
"code_guidelines": "allow"
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
```
|
|
288
350
|
|
|
289
351
|
Run it with:
|
|
290
352
|
|
|
@@ -303,6 +365,8 @@ A typical investigation should:
|
|
|
303
365
|
5. Use `trace` only for explicit Protocol 3 relations.
|
|
304
366
|
6. Follow `next_cursor` when evidence is truncated.
|
|
305
367
|
|
|
368
|
+
A formatting task should first call `code_guidelines` with `detect`, then `audit`, then `patch`. The agent can either improve source-aware findings itself or apply the package plan with `action: apply` and `write: true`. It must finish with another `audit`; it must never use `apply` merely to discover what would change.
|
|
369
|
+
|
|
306
370
|
## Large-Workspace Performance
|
|
307
371
|
|
|
308
372
|
The release benchmark generates one valid file above 100,000 lines for each language and a mixed workspace above 500,000 lines. On the reference Apple Silicon Mac, release budgets are:
|
|
@@ -326,7 +390,7 @@ Private Linux CI records and uploads the same measurements with `--report-only`;
|
|
|
326
390
|
|
|
327
391
|
## Offline Ornith/OpenCode Evaluation
|
|
328
392
|
|
|
329
|
-
The repository contains
|
|
393
|
+
The repository contains seven release E2Es: Python, Rust, C#, Delphi, C++, a mixed-language FFI workspace, and a coding-guidelines write workflow. They use the pinned local Ornith revision through vLLM 0.23.0 and OpenCode 1.17.18. The guidelines scenario must detect and audit the profile, inspect a patch, explicitly apply it with `write: true`, and finish with a clean audit. The Python scenario continues the same session through a headless OpenCode server and must inspect the focused symbol in a second turn without another `find` or explicit `target_id`, proving that the plugin preserves its warm worker. It then opens an independent session whose target-less `inspect` must be empty, proving that focus never crosses chat boundaries. The harness fails if a model shard is missing, a download is attempted, an unapproved tool is called, any assistant message uses a different agent, model, or provider, a worker survives server shutdown, or required evidence is absent.
|
|
330
394
|
|
|
331
395
|
Inspect the plan without launching a model:
|
|
332
396
|
|
|
@@ -340,7 +404,7 @@ Verify the exact local executables, versions, model revision, and weight shards:
|
|
|
340
404
|
python scripts/run_opencode_e2e.py --verify-runtime
|
|
341
405
|
```
|
|
342
406
|
|
|
343
|
-
Run all
|
|
407
|
+
Run all seven scenarios and retain complete evidence:
|
|
344
408
|
|
|
345
409
|
```bash
|
|
346
410
|
HF_HUB_OFFLINE=1 \
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Agent Coding Language Mapper
|
|
2
2
|
|
|
3
|
-
`agent-codinglanguage-mapper` gives coding agents a bounded semantic view of mixed-language repositories. It maps Python, Rust, C#, Delphi, and C++ into one language-neutral index and exposes that index through a Python API, a command-line interface, Protocol 3, an LSP server, and an OpenCode skill/plugin pair.
|
|
3
|
+
`agent-codinglanguage-mapper` gives coding agents a bounded semantic view of mixed-language repositories. It maps Python, Rust, C#, Delphi, and C++ into one language-neutral index and exposes that index through a Python API, a command-line interface, Protocol 3, an LSP server, and an OpenCode skill/plugin pair. It also detects repository coding conventions, audits source against them, and produces reviewable formatting patches before any explicit write.
|
|
4
4
|
|
|
5
5
|
The mapper is designed for code investigation without sending whole files through `grep`, `cat`, or generic file-reading tools. Responses are paginated, carry stable target IDs and source citations, distinguish proven from partial relations, and preserve focus across follow-up requests.
|
|
6
6
|
|
|
@@ -52,6 +52,8 @@ The public types are:
|
|
|
52
52
|
- `Project` and `SourceFile`
|
|
53
53
|
- `Symbol`, `Reference`, and `Relation`
|
|
54
54
|
- `Problem` and `SourceRange`
|
|
55
|
+
- `CodingGuidelines`
|
|
56
|
+
- `GuidelineProfile`, `GuidelineFinding`, `GuidelineChange`, and `GuidelineReport`
|
|
55
57
|
|
|
56
58
|
Parser-native nodes are intentionally private. Ranges are zero-based and half-open. Rendered citations use one-based line numbers, for example `src/payment.py:42`.
|
|
57
59
|
|
|
@@ -77,6 +79,16 @@ codinglanguage-mapper index --root . --out .mapper/index.json
|
|
|
77
79
|
# Discovery and parser diagnostics
|
|
78
80
|
codinglanguage-mapper doctor --root . --format json
|
|
79
81
|
|
|
82
|
+
# Detect and audit repository coding conventions
|
|
83
|
+
codinglanguage-mapper guidelines detect --root . --format json
|
|
84
|
+
codinglanguage-mapper guidelines audit --root . --format json
|
|
85
|
+
|
|
86
|
+
# Preview a deterministic patch; this never changes source files
|
|
87
|
+
codinglanguage-mapper guidelines format --root .
|
|
88
|
+
|
|
89
|
+
# Apply the reviewed plan atomically
|
|
90
|
+
codinglanguage-mapper guidelines format --root . --write
|
|
91
|
+
|
|
80
92
|
# Language Server Protocol over stdio
|
|
81
93
|
codinglanguage-mapper lsp --root .
|
|
82
94
|
|
|
@@ -86,6 +98,43 @@ codinglanguage-mapper worker --root .
|
|
|
86
98
|
|
|
87
99
|
Available view layers are `overview`, `projects`, `languages`, `files`, `file`, `symbols`, `symbol`, `implementation`, `references`, and `problems`.
|
|
88
100
|
|
|
101
|
+
## Coding Guidelines and Formatting
|
|
102
|
+
|
|
103
|
+
The guidelines API uses the mapper's normal project discovery and language detection, so one request can audit a mixed Python, Rust, C#, Delphi, and C++ workspace. Detection is file-specific rather than one profile for the entire repository. Defaults are refined by language configuration and then by the nearest applicable `.editorconfig`, which has the highest precedence.
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from agent_codinglanguage_mapper import CodingGuidelines
|
|
107
|
+
|
|
108
|
+
guidelines = CodingGuidelines.open(".", languages="auto")
|
|
109
|
+
detected = guidelines.detect()
|
|
110
|
+
audit = guidelines.audit()
|
|
111
|
+
|
|
112
|
+
# A stable unified diff for agent or human review; no files are changed.
|
|
113
|
+
patch = guidelines.patch()
|
|
114
|
+
print(patch)
|
|
115
|
+
|
|
116
|
+
# Mutation is rejected unless write=True is explicit.
|
|
117
|
+
plan = guidelines.plan()
|
|
118
|
+
applied = guidelines.apply(plan, write=True)
|
|
119
|
+
print(applied.to_mapping())
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`detect()` reports the effective profile and its configuration sources. `audit()` returns exact zero-based, half-open ranges for line length, indentation, line endings, trailing whitespace, and final-newline findings. Invalid supported values and unsupported EditorConfig properties are reported as non-fixable configuration findings; affected rules retain their previous effective value. Agents can use those findings to make source-aware improvements that are outside the formatter's conservative scope. `plan()` records original-content hashes, the guideline-configuration revision, and the exact replacement bytes. `apply()` rejects stale plans after either source or configuration changes, workspace-escaping paths, and symlinks; accepted writes use a same-directory temporary file and atomic replacement.
|
|
123
|
+
|
|
124
|
+
The built-in formatter safely normalizes configured line endings, removes trailing whitespace outside protected multiline string literals, and applies the configured final-newline rule while preserving UTF-8 BOM, UTF-16, and legacy single-byte source encodings. When installed and runnable, the package delegates broader formatting to the language's established tool and validates the result with the mapper before planning it:
|
|
125
|
+
|
|
126
|
+
| Language | Detected configuration | Preferred formatter |
|
|
127
|
+
| --- | --- | --- |
|
|
128
|
+
| Python | `pyproject.toml` (`ruff`) and `.editorconfig` | Ruff, then Black |
|
|
129
|
+
| Rust | `rustfmt.toml`, `.rustfmt.toml`, and `.editorconfig` | `rustfmt` |
|
|
130
|
+
| C# | `.editorconfig` common whitespace rules | `dotnet format whitespace` in an isolated temporary copy |
|
|
131
|
+
| Delphi | RAD Studio-compatible defaults and `.editorconfig` | Built-in conservative formatter |
|
|
132
|
+
| C++ | `.clang-format`, `_clang-format`, and `.editorconfig` | `clang-format` |
|
|
133
|
+
|
|
134
|
+
Native formatter executables are optional and are never downloaded or installed by this package. A missing tool selects the built-in formatter. A timeout, nonzero exit, invalid output, or other native failure also falls back to the built-in formatter and emits a structured `native-formatter-failed` finding instead of discarding the audit. No formatter command is executed through a shell.
|
|
135
|
+
|
|
136
|
+
`guidelines audit` exits with status 1 when findings exist, making it suitable for CI. `guidelines format` without `--write` always prints the unified diff and leaves the workspace untouched. The only mutating CLI form is `guidelines format --write`.
|
|
137
|
+
|
|
89
138
|
## Protocol 3
|
|
90
139
|
|
|
91
140
|
Protocol 3 is the bounded request/response contract used by the worker and OpenCode plugin.
|
|
@@ -237,7 +286,20 @@ This creates:
|
|
|
237
286
|
opencode.json
|
|
238
287
|
```
|
|
239
288
|
|
|
240
|
-
The generated `mixed-codebase-navigator` agent denies all tools by default and permits only `skill` and `
|
|
289
|
+
The generated `mixed-codebase-navigator` agent denies all tools by default and permits only `skill`, `codebase_map`, and `code_guidelines`. The plugin maps the active OpenCode directory, serializes Protocol 3 requests through one worker, applies a hard timeout, reports bounded worker `stderr`, restarts after failure, and preserves focus plus warm parser indexes across short idle gaps. It stops the worker when the session is deleted or after 60 seconds without another mapper request.
|
|
290
|
+
|
|
291
|
+
`code_guidelines` exposes four actions: `detect`, `audit`, `patch`, and `apply`. The first three are read-only. `apply` is rejected unless its request contains `write: true`, so the agent must inspect a patch before it can opt into mutation.
|
|
292
|
+
|
|
293
|
+
```json
|
|
294
|
+
{
|
|
295
|
+
"permission": {
|
|
296
|
+
"*": "deny",
|
|
297
|
+
"skill": "allow",
|
|
298
|
+
"codebase_map": "allow",
|
|
299
|
+
"code_guidelines": "allow"
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
```
|
|
241
303
|
|
|
242
304
|
Run it with:
|
|
243
305
|
|
|
@@ -256,6 +318,8 @@ A typical investigation should:
|
|
|
256
318
|
5. Use `trace` only for explicit Protocol 3 relations.
|
|
257
319
|
6. Follow `next_cursor` when evidence is truncated.
|
|
258
320
|
|
|
321
|
+
A formatting task should first call `code_guidelines` with `detect`, then `audit`, then `patch`. The agent can either improve source-aware findings itself or apply the package plan with `action: apply` and `write: true`. It must finish with another `audit`; it must never use `apply` merely to discover what would change.
|
|
322
|
+
|
|
259
323
|
## Large-Workspace Performance
|
|
260
324
|
|
|
261
325
|
The release benchmark generates one valid file above 100,000 lines for each language and a mixed workspace above 500,000 lines. On the reference Apple Silicon Mac, release budgets are:
|
|
@@ -279,7 +343,7 @@ Private Linux CI records and uploads the same measurements with `--report-only`;
|
|
|
279
343
|
|
|
280
344
|
## Offline Ornith/OpenCode Evaluation
|
|
281
345
|
|
|
282
|
-
The repository contains
|
|
346
|
+
The repository contains seven release E2Es: Python, Rust, C#, Delphi, C++, a mixed-language FFI workspace, and a coding-guidelines write workflow. They use the pinned local Ornith revision through vLLM 0.23.0 and OpenCode 1.17.18. The guidelines scenario must detect and audit the profile, inspect a patch, explicitly apply it with `write: true`, and finish with a clean audit. The Python scenario continues the same session through a headless OpenCode server and must inspect the focused symbol in a second turn without another `find` or explicit `target_id`, proving that the plugin preserves its warm worker. It then opens an independent session whose target-less `inspect` must be empty, proving that focus never crosses chat boundaries. The harness fails if a model shard is missing, a download is attempted, an unapproved tool is called, any assistant message uses a different agent, model, or provider, a worker survives server shutdown, or required evidence is absent.
|
|
283
347
|
|
|
284
348
|
Inspect the plan without launching a model:
|
|
285
349
|
|
|
@@ -293,7 +357,7 @@ Verify the exact local executables, versions, model revision, and weight shards:
|
|
|
293
357
|
python scripts/run_opencode_e2e.py --verify-runtime
|
|
294
358
|
```
|
|
295
359
|
|
|
296
|
-
Run all
|
|
360
|
+
Run all seven scenarios and retain complete evidence:
|
|
297
361
|
|
|
298
362
|
```bash
|
|
299
363
|
HF_HUB_OFFLINE=1 \
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "agent-codinglanguage-mapper"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.1.0"
|
|
8
8
|
description = "Agent-focused semantic mapping and language services for mixed-language codebases."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10,<3.15"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from ._version import __version__
|
|
2
|
+
from .guidelines import CodingGuidelines, GuidelineChange, GuidelineFinding, GuidelineProfile, GuidelineReport
|
|
2
3
|
from .mapper import CodebaseMapper
|
|
3
4
|
from .models import Language, Problem, Project, Reference, Relation, SourceFile, SourceRange, Symbol
|
|
4
5
|
from .protocol import AgentRequest, AgentResponse
|
|
@@ -7,6 +8,11 @@ __all__ = [
|
|
|
7
8
|
"AgentRequest",
|
|
8
9
|
"AgentResponse",
|
|
9
10
|
"CodebaseMapper",
|
|
11
|
+
"CodingGuidelines",
|
|
12
|
+
"GuidelineChange",
|
|
13
|
+
"GuidelineFinding",
|
|
14
|
+
"GuidelineProfile",
|
|
15
|
+
"GuidelineReport",
|
|
10
16
|
"Language",
|
|
11
17
|
"Problem",
|
|
12
18
|
"Project",
|
|
@@ -17,4 +23,3 @@ __all__ = [
|
|
|
17
23
|
"Symbol",
|
|
18
24
|
"__version__",
|
|
19
25
|
]
|
|
20
|
-
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.1.0"
|
|
@@ -5,8 +5,9 @@ import json
|
|
|
5
5
|
import os
|
|
6
6
|
import sys
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import Sequence
|
|
8
|
+
from typing import BinaryIO, Sequence, TextIO, cast
|
|
9
9
|
|
|
10
|
+
from .guidelines import CodingGuidelines, GuidelineReport
|
|
10
11
|
from .integration import install_opencode, install_skill
|
|
11
12
|
from .mapper import CodebaseMapper
|
|
12
13
|
from .models import Language
|
|
@@ -59,6 +60,18 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
59
60
|
_root_argument(worker)
|
|
60
61
|
worker.add_argument("--project-file", type=Path)
|
|
61
62
|
|
|
63
|
+
guidelines = subparsers.add_parser("guidelines", help="Detect, audit, and apply coding guidelines.")
|
|
64
|
+
guideline_subparsers = guidelines.add_subparsers(dest="guidelines_command", required=True)
|
|
65
|
+
for name in ("detect", "audit"):
|
|
66
|
+
command = guideline_subparsers.add_parser(name)
|
|
67
|
+
_root_argument(command)
|
|
68
|
+
command.add_argument("--format", choices=("json", "text"), default="text")
|
|
69
|
+
command.add_argument("--language", dest="languages", action="append", choices=[item.value for item in Language])
|
|
70
|
+
guideline_format = guideline_subparsers.add_parser("format")
|
|
71
|
+
_root_argument(guideline_format)
|
|
72
|
+
guideline_format.add_argument("--language", dest="languages", action="append", choices=[item.value for item in Language])
|
|
73
|
+
guideline_format.add_argument("--write", action="store_true")
|
|
74
|
+
|
|
62
75
|
skill = subparsers.add_parser("skill", help="Install agent skills.")
|
|
63
76
|
skill_subparsers = skill.add_subparsers(dest="skill_command", required=True)
|
|
64
77
|
skill_install = skill_subparsers.add_parser("install")
|
|
@@ -85,6 +98,24 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
85
98
|
return 0
|
|
86
99
|
if args.command == "worker":
|
|
87
100
|
return serve_worker(args.root, sys.stdin, sys.stdout)
|
|
101
|
+
if args.command == "guidelines":
|
|
102
|
+
languages = tuple(Language(item) for item in (args.languages or ()))
|
|
103
|
+
selection: str | tuple[Language, ...] = languages or "auto"
|
|
104
|
+
guidelines = CodingGuidelines.open(args.root, languages=selection)
|
|
105
|
+
if args.guidelines_command == "detect":
|
|
106
|
+
guideline_report = guidelines.detect()
|
|
107
|
+
_print_guideline_report(guideline_report, args.format)
|
|
108
|
+
return 0
|
|
109
|
+
if args.guidelines_command == "audit":
|
|
110
|
+
guideline_report = guidelines.audit()
|
|
111
|
+
_print_guideline_report(guideline_report, args.format)
|
|
112
|
+
return 1 if guideline_report.findings else 0
|
|
113
|
+
if not args.write:
|
|
114
|
+
_write_patch(guidelines.patch())
|
|
115
|
+
return 0
|
|
116
|
+
guideline_report = guidelines.apply(write=True)
|
|
117
|
+
print(json.dumps(guideline_report.to_mapping(), indent=2, sort_keys=True))
|
|
118
|
+
return 0
|
|
88
119
|
if args.command == "skill":
|
|
89
120
|
path = install_skill(args.target, force=args.force)
|
|
90
121
|
print(path)
|
|
@@ -112,16 +143,27 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|
|
112
143
|
path = write_index(mapper, args.out)
|
|
113
144
|
print(json.dumps({"path": str(path), "revision": mapper.snapshot.revision}, sort_keys=True))
|
|
114
145
|
return 0
|
|
115
|
-
|
|
146
|
+
doctor_report = _doctor_report(mapper)
|
|
116
147
|
if args.format == "json":
|
|
117
|
-
print(json.dumps(
|
|
148
|
+
print(json.dumps(doctor_report, indent=2, sort_keys=True))
|
|
118
149
|
else:
|
|
119
|
-
status = "ready" if
|
|
150
|
+
status = "ready" if doctor_report["ok"] else "problems"
|
|
120
151
|
print(f"status: {status}")
|
|
121
152
|
print("languages: " + ", ".join(item.value for item in Language))
|
|
122
|
-
print(f"files: {
|
|
123
|
-
print(f"errors: {
|
|
124
|
-
|
|
153
|
+
print(f"files: {doctor_report['files']}")
|
|
154
|
+
print(f"errors: {doctor_report['errors']}")
|
|
155
|
+
return 0 if doctor_report["ok"] else 1
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _write_patch(patch: str, stream: TextIO | None = None) -> None:
|
|
159
|
+
output = stream or sys.stdout
|
|
160
|
+
binary = getattr(output, "buffer", None)
|
|
161
|
+
if binary is None:
|
|
162
|
+
output.write(patch)
|
|
163
|
+
output.flush()
|
|
164
|
+
return
|
|
165
|
+
cast(BinaryIO, binary).write(patch.encode("utf-8"))
|
|
166
|
+
cast(BinaryIO, binary).flush()
|
|
125
167
|
|
|
126
168
|
|
|
127
169
|
def _doctor_report(mapper: CodebaseMapper) -> dict[str, object]:
|
|
@@ -136,3 +178,16 @@ def _doctor_report(mapper: CodebaseMapper) -> dict[str, object]:
|
|
|
136
178
|
"problems": len(mapper.snapshot.problems),
|
|
137
179
|
"errors": len(errors),
|
|
138
180
|
}
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def _print_guideline_report(report: GuidelineReport, output_format: str) -> None:
|
|
184
|
+
if output_format == "json":
|
|
185
|
+
print(json.dumps(report.to_mapping(), indent=2, sort_keys=True))
|
|
186
|
+
return
|
|
187
|
+
print(f"workspace: {report.workspace}")
|
|
188
|
+
print(f"profiles: {len(report.profiles)}")
|
|
189
|
+
print(f"findings: {len(report.findings)}")
|
|
190
|
+
for finding in report.findings:
|
|
191
|
+
line = finding.range.start_line + 1
|
|
192
|
+
character = finding.range.start_character + 1
|
|
193
|
+
print(f"{finding.range.path}:{line}:{character}: {finding.severity} {finding.code}: {finding.message}")
|