witan-code 0.22.0__tar.gz → 0.24.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.
- {witan_code-0.22.0 → witan_code-0.24.0}/CHANGELOG.md +77 -1
- {witan_code-0.22.0 → witan_code-0.24.0}/PKG-INFO +32 -21
- {witan_code-0.22.0 → witan_code-0.24.0}/README.md +29 -18
- {witan_code-0.22.0 → witan_code-0.24.0}/conftest.py +1 -1
- {witan_code-0.22.0 → witan_code-0.24.0}/docs/EDGE_PRECISION_TIERS.md +8 -6
- {witan_code-0.22.0 → witan_code-0.24.0}/docs/PACKAGE_MAP.md +1 -1
- {witan_code-0.22.0 → witan_code-0.24.0}/docs/STAGE2_STITCHING.md +9 -4
- {witan_code-0.22.0 → witan_code-0.24.0}/docs/SYMBOL_FORMAT.md +6 -6
- {witan_code-0.22.0 → witan_code-0.24.0}/docs/SYMBOL_TABLE.md +1 -1
- {witan_code-0.22.0 → witan_code-0.24.0}/pyproject.toml +15 -6
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_branches.py +1 -2
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_bridge.py +163 -59
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_cli_hooks.py +6 -3
- witan_code-0.24.0/tests/test_cli_output_format.py +210 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_cli_selected_target.py +0 -3
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_config_targets.py +0 -1
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_context.py +22 -1
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_edges.py +1 -2
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_github_app.py +2 -1
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_hooks.py +6 -4
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_index_failure_diagnostics.py +22 -14
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_indexer_scope.py +1 -1
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_ingest.py +1 -2
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_maintenance.py +69 -5
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_remote_store.py +7 -3
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_repo.py +0 -1
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_setup.py +75 -11
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_store.py +4 -4
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_views.py +0 -1
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_visualize.py +4 -1
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/bridge.py +10 -6
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/bridge_extractors.py +71 -34
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/cli.py +148 -63
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/config.py +1 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/context.py +48 -12
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/extensions/pi/codegraph.ts +32 -9
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/github_app.py +2 -2
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/graph.py +2 -2
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/hooks.py +1 -1
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/identity.py +1 -1
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/indexer.py +14 -12
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/ingest.py +2 -2
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/maintenance.py +49 -6
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/remote/oidc.py +2 -1
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/remote/proxy.py +1 -1
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/remote/store.py +8 -7
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/server.py +8 -10
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/skills/witan-code/SKILL.md +15 -4
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/store.py +7 -7
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/visualize.py +6 -3
- witan_code-0.22.0/tests/test_cli_output_format.py +0 -95
- {witan_code-0.22.0 → witan_code-0.24.0}/.gitignore +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/changelog.d/README.md +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/config/claude.json +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/config/copilot.json +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/config/pi.json +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/docs/BRANCH_INDEXING.md +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/docs/CLI_REFERENCE.md +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/docs/USER_GUIDE.md +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/install.sh +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/__init__.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/conftest.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_batched_deletes.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_chunked_load.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_cli_dispatch.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_config.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_crossrepo.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_elicit.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_enrichment.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_graph.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_identity.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_index_reports_its_store.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_index_requires_a_repo_key.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_indexer.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_languages.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_package_map.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_reaper.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_rebuild_honours_the_repo_key.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_refusal_audit.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_remote_proxy.py +1 -1
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_server.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_stitch.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_symbol_table.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_tasks.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/tests/test_tool_schema.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/__init__.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/__main__.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/edges.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/elicit.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/output.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/package_map.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/queries/bridge.gq +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/queries/code_mutations.gq +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/queries/code_read.gq +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/queries/delete.gq +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/queries_ts/bash.scm +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/queries_ts/hcl.scm +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/queries_ts/python.scm +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/queries_ts/sql.scm +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/queries_ts/typescript.scm +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/queries_ts/yaml.scm +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/reaper.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/remote/__init__.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/repo.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/schema/bridge-schema.pg +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/schema/code-schema.pg +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/selected_target.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/setup.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/stitch.py +0 -0
- {witan_code-0.22.0 → witan_code-0.24.0}/witan_code/views.py +0 -0
|
@@ -8,6 +8,83 @@ a MINOR bump may include breaking changes).
|
|
|
8
8
|
|
|
9
9
|
<!-- scriv-insert-here -->
|
|
10
10
|
|
|
11
|
+
## [0.24.0] - 2026-10-02
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- `witan-code setup --force` replaces a symlink or non-directory occupying an install destination (e.g. a stale symlink under `~/.pi/agent/extensions`). Without it, `witan-code setup` now exits 2 with the conflicting path instead of a `FileNotFoundError` traceback.
|
|
16
|
+
|
|
17
|
+
- `witan-code inject-context --client pi-builtin` renders the code-tool
|
|
18
|
+
discovery line for Pi's built-in MCP: a `codemode` script that finds the
|
|
19
|
+
`mcp__<server>__code_*` name with `searchTools()` and calls it as
|
|
20
|
+
`tools.<name>()`. The Pi extension passes it unless pi-mcp-adapter's `mcp`
|
|
21
|
+
tool is registered, in which case it still passes `--client pi`, whose
|
|
22
|
+
output is unchanged.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- The `witan-code` skill describes calling the `code_*` tools under Pi's
|
|
27
|
+
built-in MCP as well as under pi-mcp-adapter, and `witan-code setup --agent
|
|
28
|
+
pi` no longer warns that pi-mcp-adapter is missing when Pi's built-in MCP
|
|
29
|
+
will read the witan-code entry.
|
|
30
|
+
- Requires `agent-config-kit>=0.12`, which has that check; with an older one,
|
|
31
|
+
`witan-code setup --agent pi` still printed the pi-mcp-adapter warning.
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- `witan-code checkpoint`'s background `optimize` now also runs `cleanup --older-than 30d` at most once per `WITAN_CODE_CLEANUP_INTERVAL` (default weekly; `0` disables). On omnigraph 0.11 `optimize` no longer reclaims the storage of branches deleted by `branches --prune` or `reap-views --apply`, and nothing ran `cleanup` unless done by hand. `witan-code optimize` gains `--cleanup-older-than` to run both in one process.
|
|
36
|
+
|
|
37
|
+
## [0.23.0] - 2026-09-28
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
|
|
41
|
+
- **Python package providers.** A `pyproject.toml` whose directory holds a
|
|
42
|
+
`mitol/<pkg>/__init__.py` namespace child now provides `mitol.<pkg>`, so
|
|
43
|
+
`mitol.*` imports join to ol-django. Previously only `@mitodl/*` npm
|
|
44
|
+
packages had a provider extractor and no Python import could form an edge.
|
|
45
|
+
An existing graph gains these providers on ol-django's next full-repo
|
|
46
|
+
`witan-code index` (the provider files are not source files, so the
|
|
47
|
+
unchanged-file skip does not apply to them); `witan-code reindex` on it
|
|
48
|
+
works too.
|
|
49
|
+
|
|
50
|
+
- **Repo-level provider files that stop producing bindings lose their old
|
|
51
|
+
rows.** A `pyproject.toml`, `package.json`, Pulumi config or OpenAPI spec
|
|
52
|
+
that emitted nothing on this run was never purged, so on a run that could
|
|
53
|
+
not purge by the collected file list (e.g. indexing outside a repository
|
|
54
|
+
root) its previous bindings stayed. Every such file scanned is now purged
|
|
55
|
+
before its fresh bindings are written.
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
|
|
59
|
+
- Allow cyclopts 5 (`cyclopts>=4,<6`). Under cyclopts 5, `--help` shows a
|
|
60
|
+
value placeholder after each option (e.g. `--target STR`), and a usage error
|
|
61
|
+
such as an unknown option exits with code 2 instead of 1.
|
|
62
|
+
|
|
63
|
+
### Fixed
|
|
64
|
+
|
|
65
|
+
- **`witan code` listings emit `rows: []` on an empty result under
|
|
66
|
+
`--output-format`.** `symbols`, `stitch`, `stitch --unresolved` and `repos`
|
|
67
|
+
each returned early with a Rich sentence on stdout before the format was
|
|
68
|
+
consulted, so an empty result was not JSON/TOML/YAML. `_render_table` now
|
|
69
|
+
takes the empty message and prints it in `txt` mode only. `branches` never
|
|
70
|
+
consulted the format at all and now dumps `{repo, views, error}` rows, with
|
|
71
|
+
`--prune`'s progress lines on stderr under a structured format; the `repos`
|
|
72
|
+
unreadable-store warning and `doctor`'s summary and error lines move to
|
|
73
|
+
stderr there too.
|
|
74
|
+
- **Table titles and cells are escaped for Rich.** A symbol, path or title
|
|
75
|
+
containing `[...]` was read as markup and lost from the rendered table.
|
|
76
|
+
|
|
77
|
+
- **Endpoint bindings form cross-repo edges again.** Every endpoint consumer
|
|
78
|
+
scored 0.0 because the extractor only matches relative paths and the
|
|
79
|
+
`relative_url` heuristic subtracted 0.5 from the 0.5 baseline, so
|
|
80
|
+
`code_repo_dependencies` and the other heuristic-tier views filtered every
|
|
81
|
+
one out at their 0.5 cutoff. The `relative_url` penalty, its unreachable
|
|
82
|
+
`explicit_hostname` boost, and the `generated_file` penalty are removed. A
|
|
83
|
+
generated client for a repo's own API is still suppressed by
|
|
84
|
+
`self_provided_key`. Stored confidences are computed at index time, so
|
|
85
|
+
existing graphs need `witan-code reindex` (not `index`, which skips
|
|
86
|
+
unchanged files) on the consumer repos before these edges appear.
|
|
87
|
+
|
|
11
88
|
## [0.22.0] - 2026-09-25
|
|
12
89
|
|
|
13
90
|
### Added
|
|
@@ -302,7 +379,6 @@ a MINOR bump may include breaking changes).
|
|
|
302
379
|
write threw". Deliberately still non-fatal — the per-repo index succeeds and
|
|
303
380
|
is worth keeping — but "non-fatal" and "unreported" are different claims.
|
|
304
381
|
|
|
305
|
-
|
|
306
382
|
- **The test suite no longer asserts an environment.** Four tests
|
|
307
383
|
(`test_branches.py`'s three branch-view assertions and
|
|
308
384
|
`test_graph.py::test_a_shared_branch_view_needs_an_identity_to_own_it`)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: witan-code
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.24.0
|
|
4
4
|
Summary: witan-code — tree-sitter code graph + cross-repo bridge (mounts under `witan code`)
|
|
5
5
|
Project-URL: Homepage, https://github.com/mitodl/agent-kit/tree/main/mcp/servers/witan-code
|
|
6
6
|
Project-URL: Repository, https://github.com/mitodl/agent-kit
|
|
@@ -10,8 +10,8 @@ License-Expression: BSD-3-Clause
|
|
|
10
10
|
Keywords: agent,code-graph,coding-agent,mcp,static-analysis,tree-sitter
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
12
|
Requires-Python: >=3.11
|
|
13
|
-
Requires-Dist: agent-config-kit<1,>=0.
|
|
14
|
-
Requires-Dist: cyclopts<
|
|
13
|
+
Requires-Dist: agent-config-kit<1,>=0.12
|
|
14
|
+
Requires-Dist: cyclopts<6,>=4
|
|
15
15
|
Requires-Dist: fastmcp<5,>=4
|
|
16
16
|
Requires-Dist: joserfc<2,>=1.0
|
|
17
17
|
Requires-Dist: pydantic<3,>=2
|
|
@@ -82,7 +82,7 @@ arbitration applies. See [`docs/BRANCH_INDEXING.md`](docs/BRANCH_INDEXING.md).
|
|
|
82
82
|
The two layers compose through **soft symbol-ID references**. A Layer-1 node
|
|
83
83
|
(e.g. a `lesson` or `agent_context`) can record symbol ids of the form:
|
|
84
84
|
|
|
85
|
-
```
|
|
85
|
+
```text
|
|
86
86
|
repo#relative/path.py::QualifiedName
|
|
87
87
|
e.g. https://github.com/mitodl/ol-django#app/svc.py::Service.run
|
|
88
88
|
```
|
|
@@ -136,7 +136,7 @@ edges):
|
|
|
136
136
|
|---|---|---|---|
|
|
137
137
|
| `env_var` | Pulumi `<app>:env_vars` keys in `Pulumi.*.yaml` | `get_string("NAME",…)` / `os.environ` / `process.env.X` / `env("NAME")` | the `UPPER_SNAKE` name |
|
|
138
138
|
| `endpoint` | drf-spectacular OpenAPI spec (`paths.<path>.<method>`) | `/api/…` path literals in TS (generated client / fetch) | normalized path (params → `{}`) |
|
|
139
|
-
| `package` | a repo whose `package.json` name is `@mitodl
|
|
139
|
+
| `package` | a repo whose `package.json` name is `@mitodl/*`, or a `pyproject.toml` next to a `mitol/<pkg>/__init__.py` namespace child (provides `mitol.<pkg>`) | `from mitol.*` / `include("mitol.*")` / `@mitodl/*` imports | the package name |
|
|
140
140
|
| `service` | `applications/<svc>/__main__.py` (repo / image / service name) | the deployed repo itself (key_norm = its canonical URI) | `repo:<uri>` / `image:…` / `name:…` |
|
|
141
141
|
|
|
142
142
|
Generic env names (`DEBUG`, `PORT`, `SECRET_KEY`, …) are flagged `generic` and
|
|
@@ -146,7 +146,7 @@ every repo.
|
|
|
146
146
|
The bridge is written in a **separate phase after the per-repo store write**, so
|
|
147
147
|
the two stores' advisory write locks never nest (no deadlock) and a bridge
|
|
148
148
|
failure never corrupts a per-repo store. A full-repo index runs the repo-level
|
|
149
|
-
provider extractors (OpenAPI / Pulumi / service / `package.json`) and clears
|
|
149
|
+
provider extractors (OpenAPI / Pulumi / service / `package.json` / `pyproject.toml`) and clears
|
|
150
150
|
bindings for files deleted from disk; all purging is per-file, so unchanged
|
|
151
151
|
(skipped) files — and, for a narrow target like the reindex hook, sibling
|
|
152
152
|
files — keep their bindings.
|
|
@@ -299,11 +299,12 @@ witan-code setup --dry-run # preview without writing
|
|
|
299
299
|
witan-code setup --author "Jane Doe" # attribution (default: git config user.name)
|
|
300
300
|
```
|
|
301
301
|
|
|
302
|
-
On Pi, the MCP server entry (`~/.pi/agent/mcp.json`) is read
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
302
|
+
On Pi, the MCP server entry (`~/.pi/agent/mcp.json`) is read by Pi's
|
|
303
|
+
built-in MCP support (Pi 0.99 and later), or by the pi-mcp-adapter Pi
|
|
304
|
+
package when that is installed; confirm with `pi mcp list` or `/mcp` inside
|
|
305
|
+
Pi. `witan-code setup --agent pi` warns when Pi's settings show neither one
|
|
306
|
+
would load it (the built-in turned off with `-builtin:mcp`, or a Pi older
|
|
307
|
+
than 0.99, and no adapter declared).
|
|
307
308
|
|
|
308
309
|
If `witan` is *also* installed and witan-code is importable in that same
|
|
309
310
|
environment (e.g. via the `--with` in the `uv tool install`/MCP server's
|
|
@@ -354,6 +355,7 @@ symlink alternative:
|
|
|
354
355
|
| `WITAN_AUTHOR` / `USER` | `unknown` | attribution string |
|
|
355
356
|
| `WITAN_REPO` | — | override the detected repo slug |
|
|
356
357
|
| `WITAN_CODE_OPTIMIZE_INTERVAL` | `86400` (daily) | throttle window (seconds) for `checkpoint`'s opportunistic store compaction; `0` disables it |
|
|
358
|
+
| `WITAN_CODE_CLEANUP_INTERVAL` | `604800` (weekly) | throttle window (seconds) for the `cleanup --older-than 30d` that rides a `checkpoint` compaction; `0` disables it |
|
|
357
359
|
| `WITAN_CODE_INDEX_ROLE` | `client` | `ci` designates this process the writer of a shared graph's default-branch view. Only meaningful against a shared cluster graph; local stores are unaffected. See [Branch indexing](docs/BRANCH_INDEXING.md#who-may-write-the-shared-default-branch-view) |
|
|
358
360
|
| `WITAN_ACTOR` | derived from the `witan login` session | the identity that owns the branch views this process writes; an `act-…` id or a raw OIDC `sub`. For a non-interactive writer (CI, a maintenance job). See [Branch indexing](docs/BRANCH_INDEXING.md#per-writer-branch-views) |
|
|
359
361
|
| `WITAN_CONFIG` | `~/.config/witan/config.toml` | config file path (see below) |
|
|
@@ -640,12 +642,18 @@ mechanisms keep this in check, mirroring that module (deliberately duplicated
|
|
|
640
642
|
- **Opportunistic**: the `witan-code checkpoint` Stop hook spawns a
|
|
641
643
|
throttled, detached `witan-code optimize` for the current repo's store and
|
|
642
644
|
the shared bridge store, at most once per `WITAN_CODE_OPTIMIZE_INTERVAL`
|
|
643
|
-
(default daily; `0` disables) each — see [Hooks](#hooks).
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
`
|
|
648
|
-
|
|
645
|
+
(default daily; `0` disables) each — see [Hooks](#hooks). At most once per
|
|
646
|
+
`WITAN_CODE_CLEANUP_INTERVAL` (default weekly) the run also cleans up
|
|
647
|
+
versions older than 30 days. On omnigraph 0.11 that is the only thing that
|
|
648
|
+
reclaims the storage of branches deleted by `branches --prune` or
|
|
649
|
+
`reap-views --apply`; `optimize` no longer does.
|
|
650
|
+
- **Scheduled**: `witan-code optimize [--store PATH | --bridge]
|
|
651
|
+
[--cleanup-older-than DURATION]` / `witan-code cleanup --yes` for
|
|
652
|
+
cron/systemd-timer driven maintenance on a busy store. `optimize` alone is
|
|
653
|
+
non-destructive and safe to run repeatedly. `cleanup` GCs old Lance versions
|
|
654
|
+
to reclaim disk and is destructive, so it requires `--yes`.
|
|
655
|
+
`--cleanup-older-than` makes `optimize` run that destructive cleanup
|
|
656
|
+
afterwards with no `--yes` prompt, which is how the Stop hook calls it.
|
|
649
657
|
|
|
650
658
|
## Rebuilding an unreadable store
|
|
651
659
|
|
|
@@ -721,10 +729,13 @@ A Pi equivalent of all four lives in one extension,
|
|
|
721
729
|
can tell "no cross-repo consumers" from "no cross-repo data"), and the
|
|
722
730
|
`ToolSearch` call that makes the `code_*` tools callable when the harness
|
|
723
731
|
delivers them deferred — followed by a `code_find_definition` →
|
|
724
|
-
`code_callers`/`code_impact` call template.
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
`
|
|
732
|
+
`code_callers`/`code_impact` call template. The Pi extension swaps the
|
|
733
|
+
`ToolSearch` step for Pi's calling convention: `--client pi-builtin`, for
|
|
734
|
+
Pi's built-in MCP, gives a `codemode` script (`searchTools(...)` for the
|
|
735
|
+
exact `mcp__<server>__` name, then `tools.<name>({...})`), and
|
|
736
|
+
`--client pi`, which it passes when pi-mcp-adapter's `mcp` tool is
|
|
737
|
+
registered, gives the adapter's proxy (`mcp({ search: ... })`, then
|
|
738
|
+
`mcp({ tool: ..., args: {...} })`). The default stays Claude's.
|
|
728
739
|
Independent of `witan`'s own `inject-context` hook (no cross-package
|
|
729
740
|
coupling) — register it alone for a witan-code-only install. Prints
|
|
730
741
|
nothing when the repo has neither a store nor an index in flight.
|
|
@@ -49,7 +49,7 @@ arbitration applies. See [`docs/BRANCH_INDEXING.md`](docs/BRANCH_INDEXING.md).
|
|
|
49
49
|
The two layers compose through **soft symbol-ID references**. A Layer-1 node
|
|
50
50
|
(e.g. a `lesson` or `agent_context`) can record symbol ids of the form:
|
|
51
51
|
|
|
52
|
-
```
|
|
52
|
+
```text
|
|
53
53
|
repo#relative/path.py::QualifiedName
|
|
54
54
|
e.g. https://github.com/mitodl/ol-django#app/svc.py::Service.run
|
|
55
55
|
```
|
|
@@ -103,7 +103,7 @@ edges):
|
|
|
103
103
|
|---|---|---|---|
|
|
104
104
|
| `env_var` | Pulumi `<app>:env_vars` keys in `Pulumi.*.yaml` | `get_string("NAME",…)` / `os.environ` / `process.env.X` / `env("NAME")` | the `UPPER_SNAKE` name |
|
|
105
105
|
| `endpoint` | drf-spectacular OpenAPI spec (`paths.<path>.<method>`) | `/api/…` path literals in TS (generated client / fetch) | normalized path (params → `{}`) |
|
|
106
|
-
| `package` | a repo whose `package.json` name is `@mitodl
|
|
106
|
+
| `package` | a repo whose `package.json` name is `@mitodl/*`, or a `pyproject.toml` next to a `mitol/<pkg>/__init__.py` namespace child (provides `mitol.<pkg>`) | `from mitol.*` / `include("mitol.*")` / `@mitodl/*` imports | the package name |
|
|
107
107
|
| `service` | `applications/<svc>/__main__.py` (repo / image / service name) | the deployed repo itself (key_norm = its canonical URI) | `repo:<uri>` / `image:…` / `name:…` |
|
|
108
108
|
|
|
109
109
|
Generic env names (`DEBUG`, `PORT`, `SECRET_KEY`, …) are flagged `generic` and
|
|
@@ -113,7 +113,7 @@ every repo.
|
|
|
113
113
|
The bridge is written in a **separate phase after the per-repo store write**, so
|
|
114
114
|
the two stores' advisory write locks never nest (no deadlock) and a bridge
|
|
115
115
|
failure never corrupts a per-repo store. A full-repo index runs the repo-level
|
|
116
|
-
provider extractors (OpenAPI / Pulumi / service / `package.json`) and clears
|
|
116
|
+
provider extractors (OpenAPI / Pulumi / service / `package.json` / `pyproject.toml`) and clears
|
|
117
117
|
bindings for files deleted from disk; all purging is per-file, so unchanged
|
|
118
118
|
(skipped) files — and, for a narrow target like the reindex hook, sibling
|
|
119
119
|
files — keep their bindings.
|
|
@@ -266,11 +266,12 @@ witan-code setup --dry-run # preview without writing
|
|
|
266
266
|
witan-code setup --author "Jane Doe" # attribution (default: git config user.name)
|
|
267
267
|
```
|
|
268
268
|
|
|
269
|
-
On Pi, the MCP server entry (`~/.pi/agent/mcp.json`) is read
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
269
|
+
On Pi, the MCP server entry (`~/.pi/agent/mcp.json`) is read by Pi's
|
|
270
|
+
built-in MCP support (Pi 0.99 and later), or by the pi-mcp-adapter Pi
|
|
271
|
+
package when that is installed; confirm with `pi mcp list` or `/mcp` inside
|
|
272
|
+
Pi. `witan-code setup --agent pi` warns when Pi's settings show neither one
|
|
273
|
+
would load it (the built-in turned off with `-builtin:mcp`, or a Pi older
|
|
274
|
+
than 0.99, and no adapter declared).
|
|
274
275
|
|
|
275
276
|
If `witan` is *also* installed and witan-code is importable in that same
|
|
276
277
|
environment (e.g. via the `--with` in the `uv tool install`/MCP server's
|
|
@@ -321,6 +322,7 @@ symlink alternative:
|
|
|
321
322
|
| `WITAN_AUTHOR` / `USER` | `unknown` | attribution string |
|
|
322
323
|
| `WITAN_REPO` | — | override the detected repo slug |
|
|
323
324
|
| `WITAN_CODE_OPTIMIZE_INTERVAL` | `86400` (daily) | throttle window (seconds) for `checkpoint`'s opportunistic store compaction; `0` disables it |
|
|
325
|
+
| `WITAN_CODE_CLEANUP_INTERVAL` | `604800` (weekly) | throttle window (seconds) for the `cleanup --older-than 30d` that rides a `checkpoint` compaction; `0` disables it |
|
|
324
326
|
| `WITAN_CODE_INDEX_ROLE` | `client` | `ci` designates this process the writer of a shared graph's default-branch view. Only meaningful against a shared cluster graph; local stores are unaffected. See [Branch indexing](docs/BRANCH_INDEXING.md#who-may-write-the-shared-default-branch-view) |
|
|
325
327
|
| `WITAN_ACTOR` | derived from the `witan login` session | the identity that owns the branch views this process writes; an `act-…` id or a raw OIDC `sub`. For a non-interactive writer (CI, a maintenance job). See [Branch indexing](docs/BRANCH_INDEXING.md#per-writer-branch-views) |
|
|
326
328
|
| `WITAN_CONFIG` | `~/.config/witan/config.toml` | config file path (see below) |
|
|
@@ -607,12 +609,18 @@ mechanisms keep this in check, mirroring that module (deliberately duplicated
|
|
|
607
609
|
- **Opportunistic**: the `witan-code checkpoint` Stop hook spawns a
|
|
608
610
|
throttled, detached `witan-code optimize` for the current repo's store and
|
|
609
611
|
the shared bridge store, at most once per `WITAN_CODE_OPTIMIZE_INTERVAL`
|
|
610
|
-
(default daily; `0` disables) each — see [Hooks](#hooks).
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
`
|
|
615
|
-
|
|
612
|
+
(default daily; `0` disables) each — see [Hooks](#hooks). At most once per
|
|
613
|
+
`WITAN_CODE_CLEANUP_INTERVAL` (default weekly) the run also cleans up
|
|
614
|
+
versions older than 30 days. On omnigraph 0.11 that is the only thing that
|
|
615
|
+
reclaims the storage of branches deleted by `branches --prune` or
|
|
616
|
+
`reap-views --apply`; `optimize` no longer does.
|
|
617
|
+
- **Scheduled**: `witan-code optimize [--store PATH | --bridge]
|
|
618
|
+
[--cleanup-older-than DURATION]` / `witan-code cleanup --yes` for
|
|
619
|
+
cron/systemd-timer driven maintenance on a busy store. `optimize` alone is
|
|
620
|
+
non-destructive and safe to run repeatedly. `cleanup` GCs old Lance versions
|
|
621
|
+
to reclaim disk and is destructive, so it requires `--yes`.
|
|
622
|
+
`--cleanup-older-than` makes `optimize` run that destructive cleanup
|
|
623
|
+
afterwards with no `--yes` prompt, which is how the Stop hook calls it.
|
|
616
624
|
|
|
617
625
|
## Rebuilding an unreadable store
|
|
618
626
|
|
|
@@ -688,10 +696,13 @@ A Pi equivalent of all four lives in one extension,
|
|
|
688
696
|
can tell "no cross-repo consumers" from "no cross-repo data"), and the
|
|
689
697
|
`ToolSearch` call that makes the `code_*` tools callable when the harness
|
|
690
698
|
delivers them deferred — followed by a `code_find_definition` →
|
|
691
|
-
`code_callers`/`code_impact` call template.
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
`
|
|
699
|
+
`code_callers`/`code_impact` call template. The Pi extension swaps the
|
|
700
|
+
`ToolSearch` step for Pi's calling convention: `--client pi-builtin`, for
|
|
701
|
+
Pi's built-in MCP, gives a `codemode` script (`searchTools(...)` for the
|
|
702
|
+
exact `mcp__<server>__` name, then `tools.<name>({...})`), and
|
|
703
|
+
`--client pi`, which it passes when pi-mcp-adapter's `mcp` tool is
|
|
704
|
+
registered, gives the adapter's proxy (`mcp({ search: ... })`, then
|
|
705
|
+
`mcp({ tool: ..., args: {...} })`). The default stays Claude's.
|
|
695
706
|
Independent of `witan`'s own `inject-context` hook (no cross-package
|
|
696
707
|
coupling) — register it alone for a witan-code-only install. Prints
|
|
697
708
|
nothing when the repo has neither a store nor an index in flight.
|
|
@@ -23,4 +23,4 @@ sys.path.insert(0, str(Path(__file__).resolve().parents[3]))
|
|
|
23
23
|
|
|
24
24
|
# The import is the point: `testsupport.hermetic` redirects the environment at
|
|
25
25
|
# module scope. The hook re-export is what lets this conftest report a leak.
|
|
26
|
-
from testsupport.hermetic import pytest_sessionfinish # noqa:
|
|
26
|
+
from testsupport.hermetic import pytest_sessionfinish # noqa: F401
|
|
@@ -35,12 +35,14 @@ up twice at two different trust levels.
|
|
|
35
35
|
|
|
36
36
|
```python
|
|
37
37
|
TypedEdge(
|
|
38
|
-
precision,
|
|
39
|
-
consumer_repo,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
precision, # "precise" | "heuristic" | "fuzzy"
|
|
39
|
+
consumer_repo,
|
|
40
|
+
provider_repo,
|
|
41
|
+
kind,
|
|
42
|
+
key_norm,
|
|
43
|
+
canonical_symbol, # consumer's symbol string; precise tier only, else None
|
|
44
|
+
confidence, # 1.0 for precise; the heuristic tier's score otherwise
|
|
45
|
+
evidence, # tuple[dict] of {repo, file, line} — see below
|
|
44
46
|
)
|
|
45
47
|
```
|
|
46
48
|
|
|
@@ -80,7 +80,7 @@ only makes it authoritative.
|
|
|
80
80
|
One `PackageMap` node per repo in the bridge store, keyed on the repo URI and
|
|
81
81
|
overwritten on every full-repo index (merge-by-slug):
|
|
82
82
|
|
|
83
|
-
```
|
|
83
|
+
```text
|
|
84
84
|
node PackageMap {
|
|
85
85
|
slug: String @key // canonical repo URI
|
|
86
86
|
repo: String @index
|
|
@@ -45,10 +45,15 @@ way a written edge could.
|
|
|
45
45
|
|
|
46
46
|
```python
|
|
47
47
|
PreciseEdge(
|
|
48
|
-
consumer_repo,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
consumer_repo,
|
|
49
|
+
consumer_symbol,
|
|
50
|
+
provider_repo,
|
|
51
|
+
provider_symbol,
|
|
52
|
+
kind,
|
|
53
|
+
scheme,
|
|
54
|
+
match_count,
|
|
55
|
+
preferred,
|
|
56
|
+
ambiguous_version,
|
|
52
57
|
)
|
|
53
58
|
```
|
|
54
59
|
|
|
@@ -13,7 +13,7 @@ the `:CALLS/heuristic` fallback.
|
|
|
13
13
|
|
|
14
14
|
## Format
|
|
15
15
|
|
|
16
|
-
```
|
|
16
|
+
```text
|
|
17
17
|
{scheme}:{manager}:{package}:{version}:{descriptor}
|
|
18
18
|
```
|
|
19
19
|
|
|
@@ -35,7 +35,7 @@ never encoded (they are terminal).
|
|
|
35
35
|
|
|
36
36
|
### `endpoint` → scheme `http`
|
|
37
37
|
|
|
38
|
-
```
|
|
38
|
+
```text
|
|
39
39
|
{METHOD} {normalized-path}
|
|
40
40
|
```
|
|
41
41
|
|
|
@@ -49,7 +49,7 @@ never encoded (they are terminal).
|
|
|
49
49
|
representation, not the resource, and no consumer/provider pair would agree
|
|
50
50
|
on them syntactically.
|
|
51
51
|
|
|
52
|
-
```
|
|
52
|
+
```text
|
|
53
53
|
provider: http:pypi:mit-learn:main:GET /api/v0/users/me
|
|
54
54
|
consumer: http:.:.:.:* /api/v0/users/me
|
|
55
55
|
```
|
|
@@ -58,7 +58,7 @@ consumer: http:.:.:.:* /api/v0/users/me
|
|
|
58
58
|
|
|
59
59
|
Descriptor is the variable name, verbatim.
|
|
60
60
|
|
|
61
|
-
```
|
|
61
|
+
```text
|
|
62
62
|
provider: env:.:mit-learn:main:MITOL_APP_BASE_URL
|
|
63
63
|
consumer: env:.:.:.:MITOL_APP_BASE_URL
|
|
64
64
|
```
|
|
@@ -69,7 +69,7 @@ The symbol identifies the package itself; the descriptor is `.`. Manager and
|
|
|
69
69
|
package name come from the import site (consumer) or the publishing repo's
|
|
70
70
|
package map / `package.json` (provider).
|
|
71
71
|
|
|
72
|
-
```
|
|
72
|
+
```text
|
|
73
73
|
provider: pkg:npm:@mitodl/course-search-utils:main:.
|
|
74
74
|
consumer: pkg:npm:@mitodl/course-search-utils:.:.
|
|
75
75
|
```
|
|
@@ -78,7 +78,7 @@ consumer: pkg:npm:@mitodl/course-search-utils:.:.
|
|
|
78
78
|
|
|
79
79
|
Descriptor is `{sub_kind}/{key_norm}` (sub_kind: `repo` | `image` | `name`).
|
|
80
80
|
|
|
81
|
-
```
|
|
81
|
+
```text
|
|
82
82
|
provider: svc:.:ol-infrastructure:main:repo/https://github.com/mitodl/mit-learn
|
|
83
83
|
```
|
|
84
84
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "witan-code"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.24.0"
|
|
4
4
|
description = "witan-code — tree-sitter code graph + cross-repo bridge (mounts under `witan code`)"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "BSD-3-Clause"
|
|
@@ -18,10 +18,19 @@ dependencies = [
|
|
|
18
18
|
# agent-config-kit by path — except there is NO `check-core-floor`
|
|
19
19
|
# equivalent for this dependency, so this line is the only guard.
|
|
20
20
|
# >=0.10: `witan-code setup`'s install report promises a warning when Pi
|
|
21
|
-
#
|
|
21
|
+
# cannot load MCP servers, which comes from `InstallResult.prerequisites`,
|
|
22
22
|
# added in 0.10.0. witan_core's `report_install` reads it with getattr, so
|
|
23
23
|
# an older resolution does not fail — it just silently drops the warning.
|
|
24
|
-
|
|
24
|
+
# >=0.11.1: `setup --force` passes `force` through to apply(), whose
|
|
25
|
+
# symlink guard (ConflictingPathError instead of FileNotFoundError) is
|
|
26
|
+
# new in 0.11.1. Older resolutions accept the flag but still crash on a
|
|
27
|
+
# dangling symlink. The workspace resolves by path, so no test here
|
|
28
|
+
# catches a stale floor.
|
|
29
|
+
# >=0.12: `witan-code setup --agent pi` only stops warning that
|
|
30
|
+
# pi-mcp-adapter is missing when Pi's built-in MCP will load the entry
|
|
31
|
+
# from 0.12.0. Older resolutions import and run, and print the false
|
|
32
|
+
# warning.
|
|
33
|
+
"agent-config-kit>=0.12,<1",
|
|
25
34
|
# `remote`: the ADR-0005 client stack (OIDC device grant + MCP-client
|
|
26
35
|
# proxy) behind `witan-code login` and the read commands' remote mode.
|
|
27
36
|
# Costs nothing extra in practice — fastmcp is already required here and
|
|
@@ -157,13 +166,13 @@ dependencies = [
|
|
|
157
166
|
# 0.38 its text never reaches the `mcp.tool_call` log line.
|
|
158
167
|
#
|
|
159
168
|
# ★ >=0.40 IS A BEHAVIOUR FLOOR too: `witan-code setup --agent pi` promises
|
|
160
|
-
# a warning when Pi
|
|
169
|
+
# a warning when Pi cannot load MCP servers, and
|
|
161
170
|
# `witan_core.cli.report_install` only prints `InstallResult.prerequisites`
|
|
162
171
|
# from 0.40.0. It reads the field with getattr, so 0.39 imports and runs —
|
|
163
172
|
# and silently drops the warning.
|
|
164
173
|
"witan-core[cli,remote,observability,sentry]>=0.40,<1",
|
|
165
174
|
"fastmcp>=4,<5",
|
|
166
|
-
"cyclopts>=4,<
|
|
175
|
+
"cyclopts>=4,<6",
|
|
167
176
|
# [targets.<name>] override models (config.py) — also transitively pulled
|
|
168
177
|
# in by fastmcp, declared explicitly since config.py imports it directly.
|
|
169
178
|
"pydantic>=2,<3",
|
|
@@ -244,7 +253,7 @@ testpaths = ["tests"]
|
|
|
244
253
|
packages = ["witan_code"]
|
|
245
254
|
|
|
246
255
|
[tool.bumpversion]
|
|
247
|
-
current_version = "0.
|
|
256
|
+
current_version = "0.24.0"
|
|
248
257
|
allow_dirty = true
|
|
249
258
|
|
|
250
259
|
[[tool.bumpversion.files]]
|