witan-code 0.13.3__tar.gz → 0.13.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. {witan_code-0.13.3 → witan_code-0.13.4}/CHANGELOG.md +14 -0
  2. {witan_code-0.13.3 → witan_code-0.13.4}/PKG-INFO +1 -1
  3. {witan_code-0.13.3 → witan_code-0.13.4}/pyproject.toml +2 -2
  4. witan_code-0.13.4/tests/test_tool_schema.py +49 -0
  5. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/server.py +45 -0
  6. {witan_code-0.13.3 → witan_code-0.13.4}/.gitignore +0 -0
  7. {witan_code-0.13.3 → witan_code-0.13.4}/README.md +0 -0
  8. {witan_code-0.13.3 → witan_code-0.13.4}/config/claude.json +0 -0
  9. {witan_code-0.13.3 → witan_code-0.13.4}/config/copilot.json +0 -0
  10. {witan_code-0.13.3 → witan_code-0.13.4}/config/pi.json +0 -0
  11. {witan_code-0.13.3 → witan_code-0.13.4}/docs/BRANCH_INDEXING.md +0 -0
  12. {witan_code-0.13.3 → witan_code-0.13.4}/docs/CLI_REFERENCE.md +0 -0
  13. {witan_code-0.13.3 → witan_code-0.13.4}/docs/EDGE_PRECISION_TIERS.md +0 -0
  14. {witan_code-0.13.3 → witan_code-0.13.4}/docs/PACKAGE_MAP.md +0 -0
  15. {witan_code-0.13.3 → witan_code-0.13.4}/docs/STAGE2_STITCHING.md +0 -0
  16. {witan_code-0.13.3 → witan_code-0.13.4}/docs/SYMBOL_FORMAT.md +0 -0
  17. {witan_code-0.13.3 → witan_code-0.13.4}/docs/SYMBOL_TABLE.md +0 -0
  18. {witan_code-0.13.3 → witan_code-0.13.4}/docs/USER_GUIDE.md +0 -0
  19. {witan_code-0.13.3 → witan_code-0.13.4}/install.sh +0 -0
  20. {witan_code-0.13.3 → witan_code-0.13.4}/tests/__init__.py +0 -0
  21. {witan_code-0.13.3 → witan_code-0.13.4}/tests/conftest.py +0 -0
  22. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_batched_deletes.py +0 -0
  23. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_branches.py +0 -0
  24. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_bridge.py +0 -0
  25. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_chunked_load.py +0 -0
  26. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_cli_dispatch.py +0 -0
  27. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_cli_hooks.py +0 -0
  28. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_cli_output_format.py +0 -0
  29. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_config.py +0 -0
  30. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_config_targets.py +0 -0
  31. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_context.py +0 -0
  32. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_crossrepo.py +0 -0
  33. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_edges.py +0 -0
  34. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_elicit.py +0 -0
  35. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_enrichment.py +0 -0
  36. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_github_app.py +0 -0
  37. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_graph.py +0 -0
  38. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_hooks.py +0 -0
  39. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_identity.py +0 -0
  40. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_indexer.py +0 -0
  41. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_indexer_scope.py +0 -0
  42. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_ingest.py +0 -0
  43. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_languages.py +0 -0
  44. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_maintenance.py +0 -0
  45. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_package_map.py +0 -0
  46. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_reaper.py +0 -0
  47. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_remote_proxy.py +0 -0
  48. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_remote_store.py +0 -0
  49. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_repo.py +0 -0
  50. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_server.py +0 -0
  51. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_setup.py +0 -0
  52. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_stitch.py +0 -0
  53. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_store.py +0 -0
  54. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_symbol_table.py +0 -0
  55. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_tasks.py +0 -0
  56. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_views.py +0 -0
  57. {witan_code-0.13.3 → witan_code-0.13.4}/tests/test_visualize.py +0 -0
  58. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/__init__.py +0 -0
  59. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/__main__.py +0 -0
  60. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/bridge.py +0 -0
  61. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/bridge_extractors.py +0 -0
  62. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/cli.py +0 -0
  63. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/config.py +0 -0
  64. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/context.py +0 -0
  65. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/edges.py +0 -0
  66. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/elicit.py +0 -0
  67. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/extensions/pi/codegraph.ts +0 -0
  68. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/github_app.py +0 -0
  69. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/graph.py +0 -0
  70. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/hooks.py +0 -0
  71. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/identity.py +0 -0
  72. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/indexer.py +0 -0
  73. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/ingest.py +0 -0
  74. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/maintenance.py +0 -0
  75. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/output.py +0 -0
  76. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/package_map.py +0 -0
  77. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/queries/bridge.gq +0 -0
  78. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/queries/code_mutations.gq +0 -0
  79. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/queries/code_read.gq +0 -0
  80. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/queries/delete.gq +0 -0
  81. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/queries_ts/bash.scm +0 -0
  82. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/queries_ts/hcl.scm +0 -0
  83. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/queries_ts/python.scm +0 -0
  84. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/queries_ts/sql.scm +0 -0
  85. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/queries_ts/typescript.scm +0 -0
  86. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/queries_ts/yaml.scm +0 -0
  87. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/reaper.py +0 -0
  88. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/remote/__init__.py +0 -0
  89. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/remote/oidc.py +0 -0
  90. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/remote/proxy.py +0 -0
  91. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/remote/store.py +0 -0
  92. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/repo.py +0 -0
  93. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/schema/bridge-schema.pg +0 -0
  94. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/schema/code-schema.pg +0 -0
  95. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/setup.py +0 -0
  96. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/skills/witan-code/SKILL.md +0 -0
  97. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/stitch.py +0 -0
  98. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/store.py +0 -0
  99. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/views.py +0 -0
  100. {witan_code-0.13.3 → witan_code-0.13.4}/witan_code/visualize.py +0 -0
@@ -6,6 +6,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/) (pre-1.0:
7
7
  a MINOR bump may include breaking changes).
8
8
 
9
+ ## [0.13.4] - 2026-08-19
10
+
11
+ ### Changed
12
+
13
+ - **Every `code_*` tool parameter now carries a description in its JSON
14
+ Schema.** Seven parameters across seven tools had none — the `symbol_id`
15
+ argument of `code_callers`, `code_find_references`, `code_impact`, and
16
+ `code_cross_repo_impact`, the `repo` filter on `code_find_definition` and
17
+ `code_search_symbol`, and `branch` on `code_indexed_branches`. FastMCP
18
+ sends these schemas to the model, so an undescribed parameter leaves the
19
+ calling agent guessing. `symbol_id` in particular now says where the value
20
+ comes from (the `symbol_id` field of `code_find_definition` /
21
+ `code_search_symbol`) and what shape it has.
22
+
9
23
  ## [0.13.3] - 2026-08-18
10
24
 
11
25
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: witan-code
3
- Version: 0.13.3
3
+ Version: 0.13.4
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "witan-code"
3
- version = "0.13.3"
3
+ version = "0.13.4"
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"
@@ -162,7 +162,7 @@ testpaths = ["tests"]
162
162
  packages = ["witan_code"]
163
163
 
164
164
  [tool.bumpversion]
165
- current_version = "0.13.3"
165
+ current_version = "0.13.4"
166
166
  allow_dirty = true
167
167
 
168
168
  [[tool.bumpversion.files]]
@@ -0,0 +1,49 @@
1
+ """Every `code_*` tool parameter must carry a description in its schema.
2
+
3
+ The witan-council twin of this file explains the reasoning at length; briefly:
4
+ FastMCP derives each tool's JSON Schema from its docstring's numpydoc
5
+ ``Parameters`` section, and that schema is what the calling model sees. Seven
6
+ parameters here — including the ``symbol_id`` of ``code_callers``,
7
+ ``code_find_references``, ``code_impact`` and ``code_cross_repo_impact`` —
8
+ reached the model with nothing but a name and a type, and the existing
9
+ ``list_tools`` coverage asserts only that ``code_reindex`` exists, so a
10
+ regression would not have been reported.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import asyncio
16
+
17
+
18
+ def _tool_properties() -> list[tuple[str, str, dict]]:
19
+ """(tool, parameter, schema) for every exposed parameter of every tool."""
20
+ from witan_code import server as code_server
21
+
22
+ tools = asyncio.run(code_server.mcp._list_tools())
23
+ return [
24
+ (tool.name, name, schema)
25
+ for tool in tools
26
+ for name, schema in ((tool.parameters or {}).get("properties", {})).items()
27
+ ]
28
+
29
+
30
+ def test_every_tool_parameter_has_a_description():
31
+ missing = [
32
+ f"{tool}.{param}"
33
+ for tool, param, schema in _tool_properties()
34
+ if not (schema.get("description") or "").strip()
35
+ ]
36
+ assert not missing, (
37
+ f"{len(missing)} tool parameter(s) reach the model with no description. "
38
+ "Add a numpydoc `Parameters` entry for each in witan_code/server.py:\n "
39
+ + "\n ".join(sorted(missing))
40
+ )
41
+
42
+
43
+ def test_the_tool_surface_is_actually_being_inspected():
44
+ """Guard the guard — an empty listing would make the assertion vacuous."""
45
+ properties = _tool_properties()
46
+ assert len(properties) > 20, (
47
+ f"only {len(properties)} tool parameters found; the code_* surface is "
48
+ "larger than that, so the schema inspection is probably broken"
49
+ )
@@ -424,6 +424,12 @@ async def code_find_definition(
424
424
  ----------
425
425
  name:
426
426
  Bare name (``run``) or qualified name (``Service.run``).
427
+ repo:
428
+ Canonical repo URI to search. Defaults to the repo detected from the
429
+ checkout, and fans out across every indexed repo only when no repo is
430
+ detected at all. Note this differs from the witan memory/task tools:
431
+ ``repo=""`` does **not** force a fan-out here — it is falsy, so it
432
+ behaves exactly like omitting the argument.
427
433
  branch:
428
434
  Git branch whose indexed view to query (e.g. another agent's in-flight
429
435
  branch). Defaults to the checkout's branch when querying the current
@@ -464,6 +470,13 @@ async def code_find_references(
464
470
 
465
471
  Supersets code_callers (references includes calls); use code_callers when
466
472
  you want calls only. Heuristic — may miss or over-report.
473
+
474
+ Parameters
475
+ ----------
476
+ symbol_id:
477
+ The symbol to start from, as returned in the ``symbol_id`` field of
478
+ code_find_definition or code_search_symbol. Form:
479
+ ``<repo>#<path/to/file.py>::<QualifiedName>``.
467
480
  """
468
481
  client = _client_for_symbol(symbol_id)
469
482
  if client is None:
@@ -483,6 +496,13 @@ async def code_callers(symbol_id: str, ctx: Context | None = None) -> list[dict]
483
496
 
484
497
  Heuristic name-resolution based; not a precise call graph. For calls plus
485
498
  other references use code_find_references.
499
+
500
+ Parameters
501
+ ----------
502
+ symbol_id:
503
+ The symbol to start from, as returned in the ``symbol_id`` field of
504
+ code_find_definition or code_search_symbol. Form:
505
+ ``<repo>#<path/to/file.py>::<QualifiedName>``.
486
506
  """
487
507
  client = _client_for_symbol(symbol_id)
488
508
  if client is None:
@@ -508,6 +528,12 @@ async def code_impact(
508
528
 
509
529
  Parameters
510
530
  ----------
531
+ symbol_id:
532
+ The symbol to start from, as returned in the ``symbol_id`` field of
533
+ code_find_definition or code_search_symbol. Form:
534
+ ``<repo>#<path/to/file.py>::<QualifiedName>``.
535
+ This is the symbol you are about to change; the result is its blast
536
+ radius.
511
537
  max_depth:
512
538
  Maximum BFS depth (default 5).
513
539
  max_nodes:
@@ -635,6 +661,13 @@ def code_search_symbol(
635
661
  ``class``, ``module``, ``variable``, ``interface``, ``type``, ``enum``,
636
662
  ``key``, ``table``, ``cte``, or ``block``. Pass e.g. ``kind="function"``
637
663
  to exclude the many YAML ``key`` symbols when searching for code.
664
+ repo:
665
+ Canonical repo URI to search. Defaults to the repo detected from the
666
+ checkout, and fans out across every indexed repo only when no repo is
667
+ detected at all — ``repo=""`` does **not** force that, unlike the witan
668
+ memory/task tools; it is falsy and behaves like omitting the argument.
669
+ BM25 ranking is per-store, so a fan-out concatenates each store's
670
+ ranked results rather than producing one global ordering.
638
671
  branch:
639
672
  Git branch whose indexed view to query. Defaults to the checkout's
640
673
  branch when querying the current repo; when ``repo`` names a different
@@ -767,6 +800,11 @@ async def code_cross_repo_impact(
767
800
 
768
801
  Parameters
769
802
  ----------
803
+ symbol_id:
804
+ The symbol whose cross-repo surface to trace, as returned in the
805
+ ``symbol_id`` field of code_find_definition or code_search_symbol. Its
806
+ repo prefix also scopes the bridge read, so asking about another repo's
807
+ symbol does not pick up an unrelated overlay from your own checkout.
770
808
  min_precision:
771
809
  ``heuristic`` (default) | ``precise`` — see server instructions.
772
810
  """
@@ -1018,6 +1056,13 @@ def code_indexed_branches(branch: str | None = None) -> list[dict]:
1018
1056
  sanitized git branch it is a view of, ``actor`` its owner (null on a
1019
1057
  single-writer local store). ``views`` is null for a store that could not be
1020
1058
  listed.
1059
+
1060
+ Parameters
1061
+ ----------
1062
+ branch:
1063
+ A raw git branch name (not a view name) to filter by, showing every
1064
+ writer's view of that one branch — this is how you find a teammate's
1065
+ in-flight work. Omit to list every view of every indexed repo.
1021
1066
  """
1022
1067
  wanted = repo_module.branch_store_name(branch) if branch else None
1023
1068
 
File without changes
File without changes
File without changes
File without changes