leyline-code 0.9.1__tar.gz → 0.10.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (243) hide show
  1. {leyline_code-0.9.1 → leyline_code-0.10.0}/PKG-INFO +10 -2
  2. {leyline_code-0.9.1 → leyline_code-0.10.0}/README.md +9 -1
  3. {leyline_code-0.9.1 → leyline_code-0.10.0}/docs/changes.md +36 -1
  4. {leyline_code-0.9.1 → leyline_code-0.10.0}/docs/indexing.md +25 -1
  5. {leyline_code-0.9.1 → leyline_code-0.10.0}/docs/mcp-tools.md +23 -11
  6. {leyline_code-0.9.1 → leyline_code-0.10.0}/docs/quick-reference.md +4 -0
  7. {leyline_code-0.9.1 → leyline_code-0.10.0}/docs/understanding.md +36 -2
  8. leyline_code-0.10.0/openspec/changes/asset-edges/leyline.md +517 -0
  9. leyline_code-0.10.0/openspec/changes/asset-edges/proposal.md +37 -0
  10. leyline_code-0.10.0/openspec/changes/asset-edges/specs/indexing/spec.md +90 -0
  11. leyline_code-0.10.0/openspec/changes/asset-edges/tasks.md +57 -0
  12. leyline_code-0.10.0/openspec/changes/context-bodies/leyline.md +411 -0
  13. leyline_code-0.10.0/openspec/changes/context-bodies/proposal.md +36 -0
  14. leyline_code-0.10.0/openspec/changes/context-bodies/specs/understanding/spec.md +70 -0
  15. leyline_code-0.10.0/openspec/changes/context-bodies/tasks.md +31 -0
  16. leyline_code-0.10.0/openspec/changes/hash-fallback/leyline.md +276 -0
  17. leyline_code-0.10.0/openspec/changes/hash-fallback/proposal.md +17 -0
  18. leyline_code-0.10.0/openspec/changes/hash-fallback/specs/indexing/spec.md +8 -0
  19. leyline_code-0.10.0/openspec/changes/hash-fallback/tasks.md +3 -0
  20. leyline_code-0.10.0/openspec/changes/node-summaries/leyline.md +403 -0
  21. leyline_code-0.10.0/openspec/changes/node-summaries/proposal.md +30 -0
  22. leyline_code-0.10.0/openspec/changes/node-summaries/specs/understanding/spec.md +49 -0
  23. leyline_code-0.10.0/openspec/changes/node-summaries/tasks.md +30 -0
  24. leyline_code-0.10.0/openspec/changes/orientation-from-named-parts/leyline.md +386 -0
  25. leyline_code-0.10.0/openspec/changes/orientation-from-named-parts/proposal.md +30 -0
  26. leyline_code-0.10.0/openspec/changes/orientation-from-named-parts/specs/orientation/spec.md +31 -0
  27. leyline_code-0.10.0/openspec/changes/orientation-from-named-parts/tasks.md +21 -0
  28. leyline_code-0.10.0/openspec/changes/outline-splits-large-group/leyline.md +245 -0
  29. leyline_code-0.10.0/openspec/changes/outline-splits-large-group/proposal.md +26 -0
  30. leyline_code-0.10.0/openspec/changes/outline-splits-large-group/specs/outline/spec.md +22 -0
  31. leyline_code-0.10.0/openspec/changes/outline-splits-large-group/tasks.md +8 -0
  32. leyline_code-0.10.0/openspec/changes/read-tool-budgets/leyline.md +315 -0
  33. leyline_code-0.10.0/openspec/changes/read-tool-budgets/proposal.md +21 -0
  34. leyline_code-0.10.0/openspec/changes/read-tool-budgets/specs/mcp/spec.md +22 -0
  35. leyline_code-0.10.0/openspec/changes/read-tool-budgets/tasks.md +13 -0
  36. leyline_code-0.10.0/openspec/changes/server-in-another-checkout/leyline.md +323 -0
  37. leyline_code-0.10.0/openspec/changes/server-in-another-checkout/proposal.md +29 -0
  38. leyline_code-0.10.0/openspec/changes/server-in-another-checkout/specs/mcp/spec.md +30 -0
  39. leyline_code-0.10.0/openspec/changes/server-in-another-checkout/tasks.md +20 -0
  40. leyline_code-0.10.0/openspec/changes/show-tests-reaching/leyline.md +371 -0
  41. leyline_code-0.10.0/openspec/changes/show-tests-reaching/proposal.md +23 -0
  42. leyline_code-0.10.0/openspec/changes/show-tests-reaching/specs/understanding/spec.md +23 -0
  43. leyline_code-0.10.0/openspec/changes/show-tests-reaching/tasks.md +10 -0
  44. leyline_code-0.10.0/openspec/changes/unasserted-changes/leyline.md +472 -0
  45. leyline_code-0.10.0/openspec/changes/unasserted-changes/proposal.md +49 -0
  46. leyline_code-0.10.0/openspec/changes/unasserted-changes/specs/verdicts/spec.md +105 -0
  47. leyline_code-0.10.0/openspec/changes/unasserted-changes/tasks.md +54 -0
  48. leyline_code-0.10.0/openspec/leyline-anchors.json +2748 -0
  49. {leyline_code-0.9.1 → leyline_code-0.10.0}/pyproject.toml +1 -1
  50. {leyline_code-0.9.1 → leyline_code-0.10.0}/skills/leyline-ask/SKILL.md +8 -3
  51. {leyline_code-0.9.1 → leyline_code-0.10.0}/skills/leyline-explain-flow/SKILL.md +4 -2
  52. {leyline_code-0.9.1 → leyline_code-0.10.0}/skills/leyline-spec/SKILL.md +8 -1
  53. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/__init__.py +1 -1
  54. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/adapters/__init__.py +6 -3
  55. leyline_code-0.10.0/src/leyline/adapters/godot.py +94 -0
  56. leyline_code-0.10.0/src/leyline/adapters/unity.py +77 -0
  57. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/cli.py +62 -3
  58. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/context.py +303 -13
  59. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/coverage.py +6 -2
  60. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/explain.py +30 -42
  61. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/export.py +18 -13
  62. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/fncoupling.py +2 -1
  63. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/incremental.py +43 -11
  64. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/indexer.py +232 -16
  65. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/loop.py +102 -18
  66. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/model.py +12 -0
  67. leyline_code-0.10.0/src/leyline/mutants.py +669 -0
  68. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/outline.py +101 -17
  69. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/query.py +115 -2
  70. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/server.py +182 -49
  71. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/spec.py +37 -2
  72. leyline_code-0.10.0/src/leyline/summaries.py +97 -0
  73. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/tours.py +25 -3
  74. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/verdicts.py +13 -4
  75. leyline_code-0.10.0/tests/test_assets.py +400 -0
  76. leyline_code-0.10.0/tests/test_bodies.py +308 -0
  77. leyline_code-0.10.0/tests/test_budgets.py +97 -0
  78. leyline_code-0.10.0/tests/test_checkouts.py +127 -0
  79. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_flows_explain.py +4 -4
  80. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_incremental.py +17 -0
  81. leyline_code-0.10.0/tests/test_mutants.py +440 -0
  82. leyline_code-0.10.0/tests/test_orientation.py +113 -0
  83. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_outline.py +71 -0
  84. leyline_code-0.10.0/tests/test_reaching.py +109 -0
  85. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_server.py +37 -0
  86. leyline_code-0.10.0/tests/test_summaries.py +171 -0
  87. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_verdicts.py +1 -1
  88. {leyline_code-0.9.1 → leyline_code-0.10.0}/.github/workflows/publish.yml +0 -0
  89. {leyline_code-0.9.1 → leyline_code-0.10.0}/.github/workflows/test.yml +0 -0
  90. {leyline_code-0.9.1 → leyline_code-0.10.0}/.gitignore +0 -0
  91. {leyline_code-0.9.1 → leyline_code-0.10.0}/LICENSE +0 -0
  92. {leyline_code-0.9.1 → leyline_code-0.10.0}/skills/leyline-adversarial-review/SKILL.md +0 -0
  93. {leyline_code-0.9.1 → leyline_code-0.10.0}/skills/leyline-change-impact/SKILL.md +0 -0
  94. {leyline_code-0.9.1 → leyline_code-0.10.0}/skills/leyline-explore-module/SKILL.md +0 -0
  95. {leyline_code-0.9.1 → leyline_code-0.10.0}/skills/leyline-pr-review/SKILL.md +0 -0
  96. {leyline_code-0.9.1 → leyline_code-0.10.0}/skills/leyline-quick-change/SKILL.md +0 -0
  97. {leyline_code-0.9.1 → leyline_code-0.10.0}/skills/leyline-tour/SKILL.md +0 -0
  98. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/adapters/csharp.py +0 -0
  99. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/adapters/generic.py +0 -0
  100. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/adapters/python.py +0 -0
  101. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/adapters/typescript.py +0 -0
  102. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/affected.py +0 -0
  103. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/agent_skills.py +0 -0
  104. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/change.py +0 -0
  105. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/channels.py +0 -0
  106. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/cluster.py +0 -0
  107. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/coupling.py +0 -0
  108. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/diagrams.py +0 -0
  109. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/diff.py +0 -0
  110. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/drift.py +0 -0
  111. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/exact.py +0 -0
  112. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/formats.py +0 -0
  113. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/grade.py +0 -0
  114. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/learnings.py +0 -0
  115. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/packing.py +0 -0
  116. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/patterns.py +0 -0
  117. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/pr.py +0 -0
  118. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/props.py +0 -0
  119. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/quick.py +0 -0
  120. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/related.py +0 -0
  121. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/removal.py +0 -0
  122. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/renames.py +0 -0
  123. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/rereview.py +0 -0
  124. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/roslyn_refs/Program.cs +0 -0
  125. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/roslyn_refs/RoslynRefs.csproj +0 -0
  126. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/rules.py +0 -0
  127. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/schema.sql +0 -0
  128. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/scip_pb2.py +0 -0
  129. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/store.py +0 -0
  130. {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/viewer/viewer.html +0 -0
  131. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/conftest.py +0 -0
  132. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/App/App.csproj +0 -0
  133. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/App/Checks.cs +0 -0
  134. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/App/Program.cs +0 -0
  135. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/Lib/Bus.cs +0 -0
  136. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/Lib/Lib.csproj +0 -0
  137. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/Lib/Program.cs +0 -0
  138. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/Lib/Shapes.cs +0 -0
  139. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/scripts/launch.py +0 -0
  140. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/scripts/run.py +0 -0
  141. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/scripts/util.py +0 -0
  142. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/cs/Mod/Boxes.cs +0 -0
  143. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/cs/Mod/Fluent.cs +0 -0
  144. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/cs/Mod/Hard.cs +0 -0
  145. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/cs/Mod/Made.cs +0 -0
  146. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/cs/Mod/Mod.csproj +0 -0
  147. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/cs/Mod/Reports.cs +0 -0
  148. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/cs/Mod/Runner.cs +0 -0
  149. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/cs/Mod/Shapes.cs +0 -0
  150. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/cs/Mod/State.cs +0 -0
  151. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/py/src/pkg/__init__.py +0 -0
  152. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/py/src/pkg/core.py +0 -0
  153. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/py/tests/conftest.py +0 -0
  154. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/py/tests/test_engine.py +0 -0
  155. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/py/web/app.py +0 -0
  156. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/py/web/client.py +0 -0
  157. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture3/package.json +0 -0
  158. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture3/pkg/app/package.json +0 -0
  159. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture3/pkg/app/src/main.test.ts +0 -0
  160. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture3/pkg/app/src/main.tsx +0 -0
  161. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture3/pkg/app/src/server.ts +0 -0
  162. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture3/pkg/core/package.json +0 -0
  163. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture3/pkg/core/src/graph.ts +0 -0
  164. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture3/pkg/core/src/ids.ts +0 -0
  165. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture3/pkg/core/src/index.ts +0 -0
  166. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture4/go/go.mod +0 -0
  167. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture4/go/main.go +0 -0
  168. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture4/go/main_test.go +0 -0
  169. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture4/go/shapes/shape.go +0 -0
  170. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture4/java/com/acme/App.java +0 -0
  171. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture4/java/com/acme/Counter.java +0 -0
  172. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture4/rs/Cargo.toml +0 -0
  173. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture4/rs/src/geo.rs +0 -0
  174. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture4/rs/src/main.rs +0 -0
  175. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/app.py +0 -0
  176. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/audit.py +0 -0
  177. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/client.py +0 -0
  178. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/consumer.py +0 -0
  179. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/container.py +0 -0
  180. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/db.py +0 -0
  181. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/migrations/0001_audit.py +0 -0
  182. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/models.py +0 -0
  183. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/tasks.py +0 -0
  184. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/tests/test_models.py +0 -0
  185. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/rpc/py/client.py +0 -0
  186. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/rpc/py/server.py +0 -0
  187. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/shop/Billing.cs +0 -0
  188. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/shop/OrderService.cs +0 -0
  189. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/shop/Program.cs +0 -0
  190. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/shop/Shop.csproj +0 -0
  191. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/shop/Store.cs +0 -0
  192. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/ts/events.ts +0 -0
  193. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/ts/nest.ts +0 -0
  194. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/ts/repo.ts +0 -0
  195. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/ts/subs.ts +0 -0
  196. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture6/tests/test_web.py +0 -0
  197. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture6/web/__init__.py +0 -0
  198. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture6/web/app.py +0 -0
  199. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture6/web/config.py +0 -0
  200. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture6/web/globals.py +0 -0
  201. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_props/fastcheck_vitest_tap.txt +0 -0
  202. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_props/fscheck_dotnet_test.txt +0 -0
  203. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_props/hypothesis_6.100.txt +0 -0
  204. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_props/hypothesis_6.168.txt +0 -0
  205. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_ws/wsapp/pyproject.toml +0 -0
  206. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_ws/wsapp/src/apppkg/__init__.py +0 -0
  207. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_ws/wsapp/src/apppkg/main.py +0 -0
  208. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_ws/wsapp/tests/test_main.py +0 -0
  209. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_ws/wslib/pyproject.toml +0 -0
  210. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_ws/wslib/src/libpkg/__init__.py +0 -0
  211. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_ws/wslib/src/libpkg/core.py +0 -0
  212. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/store_identity.py +0 -0
  213. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_adapters.py +0 -0
  214. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_before.py +0 -0
  215. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_channels.py +0 -0
  216. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_context.py +0 -0
  217. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_coupling.py +0 -0
  218. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_diagrams.py +0 -0
  219. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_drift.py +0 -0
  220. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_fixes.py +0 -0
  221. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_fncoupling.py +0 -0
  222. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_formats.py +0 -0
  223. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_handlers.py +0 -0
  224. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_index.py +0 -0
  225. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_learnings.py +0 -0
  226. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_learnings_synonyms.py +0 -0
  227. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_learnings_workspace.py +0 -0
  228. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_memory.py +0 -0
  229. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_pr.py +0 -0
  230. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_props.py +0 -0
  231. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_quick.py +0 -0
  232. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_rereview.py +0 -0
  233. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_resolve.py +0 -0
  234. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_robust.py +0 -0
  235. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_scenario_coverage.py +0 -0
  236. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_security.py +0 -0
  237. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_shapes.py +0 -0
  238. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_signalfix.py +0 -0
  239. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_skills.py +0 -0
  240. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_state.py +0 -0
  241. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_surface.py +0 -0
  242. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_trust.py +0 -0
  243. {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_viewer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: leyline-code
3
- Version: 0.9.1
3
+ Version: 0.10.0
4
4
  Summary: Map a codebase so a person can plan a change, have an agent write the code, and check that it was done as agreed.
5
5
  Project-URL: Homepage, https://github.com/Orbitope/leyline
6
6
  Project-URL: Issues, https://github.com/Orbitope/leyline/issues
@@ -212,7 +212,9 @@ claude mcp add -s user leyline -- leyline serve # or: every project you
212
212
 
213
213
  and `leyline skills install` to give Claude Code the skills (see [Working through an agent](#working-through-an-agent)).
214
214
 
215
- Claude Code starts the server in the directory it was opened in, and the server reads the store there,
215
+ Claude Code starts the server in the directory it was opened in, and the server reads the store there (an agent that
216
+ works in another checkout of the same repository, a git worktree, passes that checkout's absolute path to `map`: it is mapped
217
+ as itself, its store is the one inside it, and the server reads that store until it restarts),
216
218
  `.leyline/leyline.db`, or, from a folder inside the repository, the nearest such store above it. Nothing needs to be mapped first: the agent's first call is `map`. If `leyline` is
217
219
  installed in a virtual environment, give its full path (`-- /path/to/venv/bin/leyline serve`); for a
218
220
  store elsewhere, such as a workspace mapped from another directory, add `-e LEYLINE_DB=/full/path/leyline.db`
@@ -237,10 +239,16 @@ Every record belongs to one of three layers:
237
239
  - **inferred**: written by an LLM, with evidence and a confidence
238
240
  - **intent**: written by you, such as boundaries and rules
239
241
 
242
+ Every function and type also carries one line saying what it is for: its author's comment or docstring, or the
243
+ `responsibility` an agent wrote after reading it (see [understanding.md](docs/understanding.md#what-a-function-or-type-is-for)).
244
+
240
245
  This version builds the fact layer for C# and Python, proposes systems by clustering, labels design
241
246
  patterns by their shape, generates an orientation tour, assesses a described change before it is made,
242
247
  reviews it after, and checks architecture rules.
243
248
 
249
+ Godot scenes and Unity prefabs are on the map too, linked to the scripts they run and the methods their signals and
250
+ events name, so renaming a method shows the scene that wires it ([indexing.md](docs/indexing.md#game-engine-assets)).
251
+
244
252
  ## Use
245
253
 
246
254
  ```bash
@@ -179,7 +179,9 @@ claude mcp add -s user leyline -- leyline serve # or: every project you
179
179
 
180
180
  and `leyline skills install` to give Claude Code the skills (see [Working through an agent](#working-through-an-agent)).
181
181
 
182
- Claude Code starts the server in the directory it was opened in, and the server reads the store there,
182
+ Claude Code starts the server in the directory it was opened in, and the server reads the store there (an agent that
183
+ works in another checkout of the same repository, a git worktree, passes that checkout's absolute path to `map`: it is mapped
184
+ as itself, its store is the one inside it, and the server reads that store until it restarts),
183
185
  `.leyline/leyline.db`, or, from a folder inside the repository, the nearest such store above it. Nothing needs to be mapped first: the agent's first call is `map`. If `leyline` is
184
186
  installed in a virtual environment, give its full path (`-- /path/to/venv/bin/leyline serve`); for a
185
187
  store elsewhere, such as a workspace mapped from another directory, add `-e LEYLINE_DB=/full/path/leyline.db`
@@ -204,10 +206,16 @@ Every record belongs to one of three layers:
204
206
  - **inferred**: written by an LLM, with evidence and a confidence
205
207
  - **intent**: written by you, such as boundaries and rules
206
208
 
209
+ Every function and type also carries one line saying what it is for: its author's comment or docstring, or the
210
+ `responsibility` an agent wrote after reading it (see [understanding.md](docs/understanding.md#what-a-function-or-type-is-for)).
211
+
207
212
  This version builds the fact layer for C# and Python, proposes systems by clustering, labels design
208
213
  patterns by their shape, generates an orientation tour, assesses a described change before it is made,
209
214
  reviews it after, and checks architecture rules.
210
215
 
216
+ Godot scenes and Unity prefabs are on the map too, linked to the scripts they run and the methods their signals and
217
+ events name, so renaming a method shows the scene that wires it ([indexing.md](docs/indexing.md#game-engine-assets)).
218
+
211
219
  ## Use
212
220
 
213
221
  ```bash
@@ -61,7 +61,9 @@ After implementation and a re-index, `verify` (inside `check`) marks each task f
61
61
  from its test's recorded result, lists edits outside the spec, new links between modules and rules
62
62
  newly broken, and appends the result to `leyline.md`. It exits 0 only when the change was done as
63
63
  agreed. A new function that only code named in the spec calls is listed as a helper, not as an edit
64
- outside the spec.
64
+ outside the spec. A new link between modules whose target the change names in backticks (in its proposal, design, tasks
65
+ or specs, such as the standard library module a task says it will use) was planned: it is listed, and does not hold
66
+ the verdict up. One it does not name does.
65
67
 
66
68
  Each task and scenario gets one verdict, shown in the tables, counted under them ("7 proven, 1 needs
67
69
  you, 1 inconclusive"), and given as `verdict` and `verdict_why` in the MCP `check` answer:
@@ -333,6 +335,39 @@ checks a diagram of the code as it is). A baseline taken by an older Leyline kep
333
335
  what order: it still compares, and the code as it was is listed, not drawn. Keeping the order made a baseline of
334
336
  Parlance about 22% larger (8.2 MB to 10.0 MB).
335
337
 
338
+ ### Covered, but not asserted: a mutation plan
339
+
340
+ A test can run every changed line and assert nothing about them; coverage cannot see it. A mutation can: break a changed
341
+ line on purpose and see whether the scenario's own tests fail.
342
+
343
+ ```
344
+ leyline mutants <change> # after the change is written: the plan, under .leyline/mutants/<change>/
345
+ python .leyline/mutants/<change>/run.py # runs the project's tests with each mutant applied; may be stopped and resumed
346
+ <run the tests> | leyline check <change> --tests - --mutants .leyline/mutants/<change>/results.jsonl
347
+ ```
348
+
349
+ The plan is for a spec change only. It holds at most 30 small breaks (a comparison flipped, `and` turned into `or`, a
350
+ `not` dropped, a returned value replaced with None, an integer one more, `+` turned into `-`), at most 3 to a line, one to
351
+ each edited function first so no function is left out while another has three. They are made only on the lines whose text
352
+ is new in the functions the change edited, in Python product code: a function that only moved has none, tests have none,
353
+ and other languages are named in the plan as having no operators yet. Each is a patch (in the file's own line endings,
354
+ for `git apply` from the repository's top), with the tests that reach its function in two stages: the tests of the
355
+ scenarios first, then up to 40 others.
356
+
357
+ Leyline writes the plan and reads the results; it never runs the code. `run.py` (standard library only) is what runs
358
+ it: the tests unmutated first (what fails there is never counted), then for each mutant its patch, the scenarios' own
359
+ tests in full and, if none failed, the others until one does, under a timeout of twice the unmutated run (at least 30
360
+ seconds; `LEYLINE_MUTANT_TIMEOUT` sets it). It always puts the file back, also after an error, a timeout or Ctrl-C, and a
361
+ run that was killed puts it back the next time. One line per mutant goes to `results.jsonl`: `killed`, `survived`,
362
+ `timeout` or `error`, and which tests failed.
363
+
364
+ `check --mutants` refuses results made for another plan or for code that has changed since (which also catches a patch left
365
+ applied). Then, for each passing scenario, it looks at the changed functions its tests reach: if every mutant of them ran
366
+ and none failed the scenario's own tests (another test failing it does not count), the scenario is `unasserted`, which
367
+ does not block unless the project lists it under `[check] blocking`. A mutant that was not run leaves the scenario unjudged. A
368
+ person may append `{"plan": "<id>", "id": "m-3", "status": "equivalent", "why": "..."}` for a mutant that cannot change
369
+ behavior, and it counts for nothing. The page lists the survivors under "Covered, but not asserted".
370
+
336
371
  ### Reviewing a change after it is made
337
372
 
338
373
  The first `propose_change` of a change keeps a baseline in `.leyline/snapshots/<change id>.db` (what the
@@ -13,7 +13,8 @@ instead, leaving out what git would: the patterns of your global excludes file (
13
13
  git reads them, so a file kept out of git such as `.env` stays off the map and its page. Some files are left out, and `map` names them with
14
14
  the reason: other people's code (`node_modules`, a Go or Composer `vendor`), submodules and nested
15
15
  repositories, symlinks to directories or out of the repository, files git lists that are gone, and source
16
- files that are binary, minified, unreadable or larger than 5 MB (`LEYLINE_MAX_FILE_MB` changes that). A
16
+ files that are binary, minified, unreadable or larger than 5 MB (`LEYLINE_MAX_FILE_MB` changes that; engine assets
17
+ have their own limit, below). A
17
18
  file that does not parse is kept on the map as a file, without its contents, and named too.
18
19
 
19
20
  Large repositories are parsed in worker processes (`LEYLINE_JOBS` sets how many). A worker that crashes
@@ -40,6 +41,29 @@ overloads, field reads and writes, events, routes. They are used for those langu
40
41
  `LEYLINE_GENERIC=1`. For other languages, a **SCIP index** (from the language's own indexer,
41
42
  `--scip FILE`) replaces the generic adapter's guesses with the compiler's links.
42
43
 
44
+ #### Game engine assets
45
+
46
+ Godot scenes and resources (`.tscn`, `.tres`) and Unity scenes, prefabs and assets (`.unity`, `.prefab`, `.asset`, in
47
+ text serialization) are files on the map too, read whatever `LEYLINE_GENERIC` says. They hold no functions; what they
48
+ name is what the map keeps. A scene or prefab links to the script a node or component runs, to the scene or prefab
49
+ it includes (`imports`, exact), and to the methods its signal connections (Godot) or persistent events (Unity) call
50
+ by name (`communicates` on the channel `asset`, heuristic: found by name, one edge to a method however many
51
+ connections name it). A method counts as the script's when its class or a base class on the map has it.
52
+
53
+ - A Godot script is found by its `res://` path, read from the folder of the `project.godot` above the scene, not from
54
+ the repository. Reading a `.gd` script's methods needs the GDScript grammar (`pip install 'leyline-code[languages]'`).
55
+ - A Unity script, scene or prefab is found by its GUID, from the `.meta` file beside it, read only when the repository
56
+ holds a Unity asset. A `.meta` that is added, changed or gone counts as a change to `plan`, `check` and `map`.
57
+ - `impact` of a script's class, method or field reaches the assets that run it, and `impact` of a scene or prefab
58
+ the assets that include it. An asset sits in the module of the nearest folder above it that holds code; a folder of
59
+ scenes alone is not a module.
60
+ - What cannot be tied to code is not guessed. The extractor's coverage (`overview`) counts it by reason and names
61
+ the first few: a script or prefab outside the repository, a GUID two `.meta` files claim, a method the script does
62
+ not have, a script in a language that is not read, and calls on built-in components (counted apart, not missing).
63
+ - An asset is read in a stream, never held as lines, up to 64 MB (`LEYLINE_MAX_ASSET_MB`; code keeps 5), binary ones
64
+ are left out and named, an unchanged one is not read again, and the map's page holds their names and links but not
65
+ their text.
66
+
43
67
  `leyline grade <repo> <index.scip | roslyn>` measures either adapter against a compiler. Precision
44
68
  counts only call sites the compiler resolved; recall counts the compiler's links between functions
45
69
  on the map.
@@ -6,26 +6,27 @@ Part of Leyline's documentation: the [README](../README.md) is the start, and [q
6
6
 
7
7
  | Tool | Returns |
8
8
  | --- | --- |
9
- | `map(paths?)` | Step 1: index the code (or map again what the store holds); counts, the map page, `next` |
9
+ | `map(paths?)` | Step 1: index the code (or map again what the store holds); counts, the map page, `next`. One checkout that is not the server's own (a git worktree) gets the store inside it, which the server reads from then on until it restarts (`store_note`) |
10
10
  | `plan(change, test_output?, test_results?, new_baseline?)` | Step 2: the one page for a change, `status.blocking`, `next`; records the tests from before; `new_baseline` compares from the code as it is now |
11
- | `check(change, test_output?, test_results?, coverage_path?)` | Step 3: re-index, record the tests from after, the verdict and `next`; with the run's coverage, whether each scenario's test ran the changed code |
11
+ | `check(change, test_output?, test_results?, coverage_path?, mutants_path?)` | Step 3: re-index, record the tests from after, the verdict and `next`; with the run's coverage, whether each scenario's test ran the changed code; with the results of the change's mutation plan, whether its own tests failed a mutant of it |
12
+ | `mutants(change, max_mutants?)` | A plan of small breaks of the code a spec change edited, written under `.leyline/mutants/<change>/` (a patch for each, `plan.json`, and `run.py`, which someone runs; Leyline never does): the mutants, the tests that reach each, and how to run it. Spec changes only |
12
13
  | `affected_tests(change)` | The tests to run for a change or a `pr-<id>` review, and the command that runs them |
13
- | `overview(scope?, limit?)` | Repos, modules with sizes, module-to-module dependencies by edge kind, systems, external packages, extractors that ran |
14
+ | `overview(scope?, limit?, budget_tokens?)` | Repos, modules with sizes, module-to-module dependencies by edge kind, systems, external packages, extractors that ran |
14
15
  | `cross_repo(limit?)` | In a workspace of several repositories: links between them, functions most called across, flows that cross and come back |
15
16
  | `search(text, kind?, limit?)` | Node ids matching a name, qualified name or path |
16
- | `expand(node_id, limit?)` | One node in detail: contents, dependencies, dependents, callers and callees |
17
- | `neighbors(node_id, direction?, kinds?, limit?)` | Raw edges around a node, by kind |
17
+ | `expand(node_id, limit?, budget_tokens?)` | One node in detail: contents, dependencies, dependents, callers and callees |
18
+ | `neighbors(node_id, direction?, kinds?, limit?, budget_tokens?)` | Raw edges around a node, by kind |
18
19
  | `source(node_id, max_lines?)` | The node's source text |
19
- | `context(focus, budget_tokens?)` | A short outline of the code around a focus (ids, names, paths, a change, or words), most related first, cut to a token budget |
20
- | `module_outline(module?, depth?)` | A large module split into at most 12 parts (folders, or groups of files where a folder is flat): each part's size, entry points, links in and out, channels, busiest functions, risks and name; drill in with a part's id |
20
+ | `context(focus, budget_tokens?, bodies?)` | A short outline of the code around a focus (ids, names, paths, a change, or words), most related first, cut to a token budget; with `bodies`, the code too: the focus's body, the types it takes, and the lines around each call to it |
21
+ | `module_outline(module?, depth?, budget_tokens?)` | A large module split into at most 12 parts (folders, or groups of files where a folder is flat): each part's size, entry points, links in and out, channels, busiest functions, risks and name; drill in with a part's id |
21
22
  | `name_part(part_id, name, summary?, evidence?, layer?)` | Name a part from the outline with a one-line summary; kept across maps, shown as "may be stale" when the part changes a lot |
22
23
  | `flows(kind?, through?, limit?, offset?)` | Flows walked from each entry point and test; `through` keeps flows that pass a node |
23
24
  | `flow(flow_id, max_steps?, offset?)` | One flow step by step, in source order, with call depth |
24
25
  | `trace(from_id, to_id)` | The shortest chain of calls and channels between two functions |
25
- | `find_flows(description, limit?)` | Where a behavior described in words could start: entry points, route, UI and message handlers, tests named for it, functions; each with why it matched, its kind, file:line and the flows that start there, or else the entry points' flows (`reached_from`) and the tests' (`tests_reaching`) that reach it |
26
- | `explain_path(start, to?, through?, max_steps?)` | An ordered walk across calls and channels from `start` (its main flow, the shortest path `to` a node, or the path `through` one), each step with how it was reached, the calling line and the declaration; data written for later marked; a Mermaid diagram of the walk |
26
+ | `find_flows(description, limit?, budget_tokens?)` | Where a behavior described in words could start: entry points, route, UI and message handlers, tests named for it, functions; each with why it matched, its kind, file:line and the flows that start there, or else the entry points' flows (`reached_from`) and the tests' (`tests_reaching`) that reach it |
27
+ | `explain_path(start, to?, through?, max_steps?, budget_tokens?)` | An ordered walk across calls and channels from `start` (its main flow, the shortest path `to` a node, or the path `through` one), each step with how it was reached, the calling line and the declaration; data written for later marked; a Mermaid diagram of the walk |
27
28
  | `diagram(ids)` | A Mermaid sequence diagram of how execution reaches some functions or types and what they call |
28
- | `impact(node_id, max_depth?, limit?)` | What can reach a node: callers by module and the flows through it |
29
+ | `impact(node_id, max_depth?, limit?, budget_tokens?)` | What can reach a node: callers by module and the flows through it |
29
30
  | `annotate(node_id, key, value, evidence?, confidence?, layer?)` | Write an inferred or intent statement about a node |
30
31
  | `propose_change(intent, targets, title?, depth?)` | Assess a change without an OpenSpec folder and save its blast-radius view |
31
32
  | `save_view(title, narrative, marks, legend?)` | Save any set of marked nodes as a view |
@@ -49,8 +50,19 @@ Part of Leyline's documentation: the [README](../README.md) is the start, and [q
49
50
  | `views()`, `view(view_id, limit?)` | List saved views, or read one |
50
51
  | `skills(skill?)` | The skills that ship with Leyline, each with when to use it, or one skill's text. Each is also an MCP prompt of the same name |
51
52
 
53
+ `search` and `expand` rows, the steps of `explain_path`, the busiest functions, key types and key functions of
54
+ `module_outline`, and the `--` lines of `context` carry `summary`: what the function or type is for, from a
55
+ `responsibility` annotation (the intent layer first, stale ones passed over) or else the comment or docstring its
56
+ author wrote (`doc`, kept when the file is mapped). See [What a function or type is for](understanding.md#what-a-function-or-type-is-for).
57
+
58
+ `overview`, `expand`, `impact`, `module_outline`, `explain_path`, `find_flows` and `neighbors` also take
59
+ `budget_tokens` (600 to 6,000; a token is four characters): the answer is cut to the smaller of that and the tool's
60
+ usual size, `cut` says what was cut, and `more` names the budget. The budget is applied after the answer is worked
61
+ out, so it saves the agent's context, not time; `explain_path` and `module_outline` also walk fewer steps or levels
62
+ to fit it. `context` sizes its own outline with its `budget_tokens` and is not cut again; with `bodies` the outline takes a third of the budget, which is at least 600 tokens, and the code follows in the same text, with `bodies` describing each piece without repeating it.
63
+
52
64
  `change` is a change folder or its id. A tool that cannot answer returns an error saying what to do
53
65
  instead (no store yet: call `map`; an unknown id: find it with `search`). Each answer is at most about
54
- 24,000 characters (30,000 for `module_outline` and `explain_path`, 36,000 for `context`): lists show their
66
+ 24,000 characters (30,000 for `module_outline` and `explain_path`, 44,000 for `context`): lists show their
55
67
  first items and their total, `cut` names any list that was shortened, and `more` says how to see the rest
56
68
  (`limit`, `offset`, `scope`, or a narrower id).
@@ -97,6 +97,7 @@ Only you resolve a finding. A rejection with a reason becomes a learning.
97
97
  | contradicted | the named code didn't change, but other code did | its test fails | yes |
98
98
  | inconclusive | the map can't place the code, or nothing changed | no result recorded | yes |
99
99
  | needs a person | it names no code | it passes, but doesn't reach the changed code | no |
100
+ | unasserted | | it passes, but none of its own tests failed a mutant of the changed code it reaches (only with `--mutants`) | no |
100
101
 
101
102
  A tick in `tasks.md` never counts. Change which verdicts block in `openspec/leyline.toml`:
102
103
 
@@ -105,6 +106,9 @@ A tick in `tasks.md` never counts. Change which verdicts block in `openspec/leyl
105
106
  blocking = ["contradicted", "inconclusive", "partial", "needs a person"]
106
107
  ```
107
108
 
109
+ `unasserted` is the one a project may add (`"unasserted"`) once it trusts its mutation results: a mutant that changes
110
+ nothing (an equivalent one) looks the same as a test that asserts nothing, so it does not block by default.
111
+
108
112
  ## Writing a spec Leyline can read
109
113
 
110
114
  - Name code in backticks in `tasks.md`: `` `Engine.start` ``. A name that isn't on the map is new code.
@@ -4,6 +4,27 @@ What the map finds and how to ask it: exact references from a compiler, measured
4
4
 
5
5
  Part of Leyline's documentation: the [README](../README.md) is the start, and [quick-reference.md](quick-reference.md) is one page of what to ask.
6
6
 
7
+ ### What a function or type is for
8
+
9
+ Every function and type carries one line saying what it is for, so an answer does not stop at who calls it. Two
10
+ sources, the one written by a reader first:
11
+
12
+ - **A `responsibility` annotation** (`annotate`, or `name_part` for a part's type), the intent layer before the
13
+ inferred one. One marked stale, because the code behind its evidence changed, is passed over.
14
+ - **The author's own words**: the comment above a declaration, or a Python docstring inside it, read when the file is
15
+ mapped and kept in the node's attributes as `doc`. A comment edit re-reads its own file and nothing else.
16
+
17
+ The summary is the first sentence of whichever applies, cut to 200 characters (120 under a step of a walk, a busiest
18
+ function or a neighbour in a context outline). `search` and `expand` rows carry it as `summary` (and the `search` and
19
+ `show` commands print it), `context` prints it as a `--` line under the focus and the code linked directly to it,
20
+ `module_outline` carries it on busiest functions, key types and key functions, and each step of `explain_path` says
21
+ what it does. `find_flows` ranks by it: the comment is one of the fields a word is looked for in, an annotation is read
22
+ on each call (so one written after the map is found at once, under "its note"), and a function whose own words answer
23
+ two or more words of the question counts for more than one that matches a single word of its name.
24
+
25
+ An agent that has read some code should leave a sentence for the next one: `annotate(node, "responsibility", "...",
26
+ evidence)` on the function, or `name_part` on a part.
27
+
7
28
  ### Exact references
8
29
 
9
30
  The syntax resolvers below work without a compiler and are sometimes wrong. Where a compiler's view
@@ -119,7 +140,11 @@ flow, a pattern, a saved view) with a few sentences on what to notice. `leyline
119
140
  orientation tour from the graph alone: what the repository is, where it starts, the modules from the
120
141
  most depended-on outward, the main abstractions and boundaries, one test path worth tracing, how it
121
142
  is tested, and what the map cannot see. Every sentence in it is a count or a name the store can
122
- back. An agent can write further tours with `save_tour`; `skills/leyline-tour/SKILL.md` says how.
143
+ back. A module of 30 files or more (the size the map page splits) is described by its parts, as `leyline outline`
144
+ splits it: the ones an agent named with `name_part`, with what each does, in the outline's order and marked when a name
145
+ may be stale, and how many are still to name. A smaller module, and a module whose parts could not be worked out, is
146
+ described by the groups the map proposed. `leyline map` says the same at the end of its `Next:` line when the largest
147
+ product module has parts with no name, and the `map` tool lists the orientation steps in its `next`. An agent can write further tours with `save_tour`; `skills/leyline-tour/SKILL.md` says how.
123
148
 
124
149
  ### Change coupling
125
150
 
@@ -191,7 +216,16 @@ marked) or words to search for. Every function, type, field and test is ranked b
191
216
  over calls, channel links, type use and containment, each way, with a small boost for code a test reaches and code an
192
217
  entry point runs first. The outline shows declaration lines, not bodies, file by file, most related file first: the focus
193
218
  marked `>`, each channel end in words ("answers GET /api/x", "writes table t"), and what calls the focus or what it calls
194
- said so. The last lines say how much was left out and name the nearest of it. The ranking visits only code near the focus,
219
+ said so. The last lines say how much was left out and name the nearest of it. With `bodies` (`leyline context <focus> --bodies`, or the tool's `bodies` argument) the code itself follows the outline,
220
+ which then takes a third of the budget (the budget is raised to 600 tokens if it is smaller, and the answer says so).
221
+ It holds, in this order: the whole body of each focus function, at most three and cut after 80 lines; each type the focus
222
+ takes as a parameter or returns, as its declaration and at most 12 field lines, never its methods; and, for each direct
223
+ caller (those that are not test code first, nearest in the rank first), the 40 lines around the call, or 16 for a call made
224
+ from the top level of a file. A caller found by a guess says so, and so does one of a method the focus overrides. A text is
225
+ shown once, a function defined twice shows each definition, and no sibling method comes with any of them. What fits is
226
+ decided from the lengths the map holds before a file is read, and packing stops after ten bodies are too long for what is
227
+ left; those and the rest are named under "Bodies left out". A file that has become a link out of the repository is not
228
+ read, and a function edited since the map is not shown (it is named as changed since the map). The ranking visits only code near the focus,
195
229
  and the graph is read once per map run: on Parlance (160,000 lines) the first call takes 0.3 s and later ones 0.05 s.
196
230
 
197
231
  ### Asking how something works