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.
- {leyline_code-0.9.1 → leyline_code-0.10.0}/PKG-INFO +10 -2
- {leyline_code-0.9.1 → leyline_code-0.10.0}/README.md +9 -1
- {leyline_code-0.9.1 → leyline_code-0.10.0}/docs/changes.md +36 -1
- {leyline_code-0.9.1 → leyline_code-0.10.0}/docs/indexing.md +25 -1
- {leyline_code-0.9.1 → leyline_code-0.10.0}/docs/mcp-tools.md +23 -11
- {leyline_code-0.9.1 → leyline_code-0.10.0}/docs/quick-reference.md +4 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/docs/understanding.md +36 -2
- leyline_code-0.10.0/openspec/changes/asset-edges/leyline.md +517 -0
- leyline_code-0.10.0/openspec/changes/asset-edges/proposal.md +37 -0
- leyline_code-0.10.0/openspec/changes/asset-edges/specs/indexing/spec.md +90 -0
- leyline_code-0.10.0/openspec/changes/asset-edges/tasks.md +57 -0
- leyline_code-0.10.0/openspec/changes/context-bodies/leyline.md +411 -0
- leyline_code-0.10.0/openspec/changes/context-bodies/proposal.md +36 -0
- leyline_code-0.10.0/openspec/changes/context-bodies/specs/understanding/spec.md +70 -0
- leyline_code-0.10.0/openspec/changes/context-bodies/tasks.md +31 -0
- leyline_code-0.10.0/openspec/changes/hash-fallback/leyline.md +276 -0
- leyline_code-0.10.0/openspec/changes/hash-fallback/proposal.md +17 -0
- leyline_code-0.10.0/openspec/changes/hash-fallback/specs/indexing/spec.md +8 -0
- leyline_code-0.10.0/openspec/changes/hash-fallback/tasks.md +3 -0
- leyline_code-0.10.0/openspec/changes/node-summaries/leyline.md +403 -0
- leyline_code-0.10.0/openspec/changes/node-summaries/proposal.md +30 -0
- leyline_code-0.10.0/openspec/changes/node-summaries/specs/understanding/spec.md +49 -0
- leyline_code-0.10.0/openspec/changes/node-summaries/tasks.md +30 -0
- leyline_code-0.10.0/openspec/changes/orientation-from-named-parts/leyline.md +386 -0
- leyline_code-0.10.0/openspec/changes/orientation-from-named-parts/proposal.md +30 -0
- leyline_code-0.10.0/openspec/changes/orientation-from-named-parts/specs/orientation/spec.md +31 -0
- leyline_code-0.10.0/openspec/changes/orientation-from-named-parts/tasks.md +21 -0
- leyline_code-0.10.0/openspec/changes/outline-splits-large-group/leyline.md +245 -0
- leyline_code-0.10.0/openspec/changes/outline-splits-large-group/proposal.md +26 -0
- leyline_code-0.10.0/openspec/changes/outline-splits-large-group/specs/outline/spec.md +22 -0
- leyline_code-0.10.0/openspec/changes/outline-splits-large-group/tasks.md +8 -0
- leyline_code-0.10.0/openspec/changes/read-tool-budgets/leyline.md +315 -0
- leyline_code-0.10.0/openspec/changes/read-tool-budgets/proposal.md +21 -0
- leyline_code-0.10.0/openspec/changes/read-tool-budgets/specs/mcp/spec.md +22 -0
- leyline_code-0.10.0/openspec/changes/read-tool-budgets/tasks.md +13 -0
- leyline_code-0.10.0/openspec/changes/server-in-another-checkout/leyline.md +323 -0
- leyline_code-0.10.0/openspec/changes/server-in-another-checkout/proposal.md +29 -0
- leyline_code-0.10.0/openspec/changes/server-in-another-checkout/specs/mcp/spec.md +30 -0
- leyline_code-0.10.0/openspec/changes/server-in-another-checkout/tasks.md +20 -0
- leyline_code-0.10.0/openspec/changes/show-tests-reaching/leyline.md +371 -0
- leyline_code-0.10.0/openspec/changes/show-tests-reaching/proposal.md +23 -0
- leyline_code-0.10.0/openspec/changes/show-tests-reaching/specs/understanding/spec.md +23 -0
- leyline_code-0.10.0/openspec/changes/show-tests-reaching/tasks.md +10 -0
- leyline_code-0.10.0/openspec/changes/unasserted-changes/leyline.md +472 -0
- leyline_code-0.10.0/openspec/changes/unasserted-changes/proposal.md +49 -0
- leyline_code-0.10.0/openspec/changes/unasserted-changes/specs/verdicts/spec.md +105 -0
- leyline_code-0.10.0/openspec/changes/unasserted-changes/tasks.md +54 -0
- leyline_code-0.10.0/openspec/leyline-anchors.json +2748 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/pyproject.toml +1 -1
- {leyline_code-0.9.1 → leyline_code-0.10.0}/skills/leyline-ask/SKILL.md +8 -3
- {leyline_code-0.9.1 → leyline_code-0.10.0}/skills/leyline-explain-flow/SKILL.md +4 -2
- {leyline_code-0.9.1 → leyline_code-0.10.0}/skills/leyline-spec/SKILL.md +8 -1
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/__init__.py +1 -1
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/adapters/__init__.py +6 -3
- leyline_code-0.10.0/src/leyline/adapters/godot.py +94 -0
- leyline_code-0.10.0/src/leyline/adapters/unity.py +77 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/cli.py +62 -3
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/context.py +303 -13
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/coverage.py +6 -2
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/explain.py +30 -42
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/export.py +18 -13
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/fncoupling.py +2 -1
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/incremental.py +43 -11
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/indexer.py +232 -16
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/loop.py +102 -18
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/model.py +12 -0
- leyline_code-0.10.0/src/leyline/mutants.py +669 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/outline.py +101 -17
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/query.py +115 -2
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/server.py +182 -49
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/spec.py +37 -2
- leyline_code-0.10.0/src/leyline/summaries.py +97 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/tours.py +25 -3
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/verdicts.py +13 -4
- leyline_code-0.10.0/tests/test_assets.py +400 -0
- leyline_code-0.10.0/tests/test_bodies.py +308 -0
- leyline_code-0.10.0/tests/test_budgets.py +97 -0
- leyline_code-0.10.0/tests/test_checkouts.py +127 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_flows_explain.py +4 -4
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_incremental.py +17 -0
- leyline_code-0.10.0/tests/test_mutants.py +440 -0
- leyline_code-0.10.0/tests/test_orientation.py +113 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_outline.py +71 -0
- leyline_code-0.10.0/tests/test_reaching.py +109 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_server.py +37 -0
- leyline_code-0.10.0/tests/test_summaries.py +171 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_verdicts.py +1 -1
- {leyline_code-0.9.1 → leyline_code-0.10.0}/.github/workflows/publish.yml +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/.github/workflows/test.yml +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/.gitignore +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/LICENSE +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/skills/leyline-adversarial-review/SKILL.md +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/skills/leyline-change-impact/SKILL.md +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/skills/leyline-explore-module/SKILL.md +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/skills/leyline-pr-review/SKILL.md +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/skills/leyline-quick-change/SKILL.md +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/skills/leyline-tour/SKILL.md +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/adapters/csharp.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/adapters/generic.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/adapters/python.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/adapters/typescript.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/affected.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/agent_skills.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/change.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/channels.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/cluster.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/coupling.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/diagrams.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/diff.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/drift.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/exact.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/formats.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/grade.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/learnings.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/packing.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/patterns.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/pr.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/props.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/quick.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/related.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/removal.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/renames.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/rereview.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/roslyn_refs/Program.cs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/roslyn_refs/RoslynRefs.csproj +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/rules.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/schema.sql +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/scip_pb2.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/store.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/src/leyline/viewer/viewer.html +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/conftest.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/App/App.csproj +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/App/Checks.cs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/App/Program.cs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/Lib/Bus.cs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/Lib/Lib.csproj +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/Lib/Program.cs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/Lib/Shapes.cs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/scripts/launch.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/scripts/run.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture/scripts/util.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/cs/Mod/Boxes.cs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/cs/Mod/Fluent.cs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/cs/Mod/Hard.cs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/cs/Mod/Made.cs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/cs/Mod/Mod.csproj +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/cs/Mod/Reports.cs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/cs/Mod/Runner.cs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/cs/Mod/Shapes.cs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/cs/Mod/State.cs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/py/src/pkg/__init__.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/py/src/pkg/core.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/py/tests/conftest.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/py/tests/test_engine.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/py/web/app.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture2/py/web/client.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture3/package.json +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture3/pkg/app/package.json +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture3/pkg/app/src/main.test.ts +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture3/pkg/app/src/main.tsx +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture3/pkg/app/src/server.ts +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture3/pkg/core/package.json +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture3/pkg/core/src/graph.ts +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture3/pkg/core/src/ids.ts +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture3/pkg/core/src/index.ts +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture4/go/go.mod +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture4/go/main.go +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture4/go/main_test.go +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture4/go/shapes/shape.go +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture4/java/com/acme/App.java +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture4/java/com/acme/Counter.java +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture4/rs/Cargo.toml +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture4/rs/src/geo.rs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture4/rs/src/main.rs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/app.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/audit.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/client.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/consumer.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/container.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/db.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/migrations/0001_audit.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/models.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/tasks.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/py/tests/test_models.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/rpc/py/client.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/rpc/py/server.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/shop/Billing.cs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/shop/OrderService.cs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/shop/Program.cs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/shop/Shop.csproj +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/shop/Store.cs +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/ts/events.ts +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/ts/nest.ts +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/ts/repo.ts +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture5/ts/subs.ts +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture6/tests/test_web.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture6/web/__init__.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture6/web/app.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture6/web/config.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture6/web/globals.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_props/fastcheck_vitest_tap.txt +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_props/fscheck_dotnet_test.txt +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_props/hypothesis_6.100.txt +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_props/hypothesis_6.168.txt +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_ws/wsapp/pyproject.toml +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_ws/wsapp/src/apppkg/__init__.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_ws/wsapp/src/apppkg/main.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_ws/wsapp/tests/test_main.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_ws/wslib/pyproject.toml +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_ws/wslib/src/libpkg/__init__.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/fixture_ws/wslib/src/libpkg/core.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/store_identity.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_adapters.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_before.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_channels.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_context.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_coupling.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_diagrams.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_drift.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_fixes.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_fncoupling.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_formats.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_handlers.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_index.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_learnings.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_learnings_synonyms.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_learnings_workspace.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_memory.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_pr.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_props.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_quick.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_rereview.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_resolve.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_robust.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_scenario_coverage.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_security.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_shapes.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_signalfix.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_skills.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_state.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_surface.py +0 -0
- {leyline_code-0.9.1 → leyline_code-0.10.0}/tests/test_trust.py +0 -0
- {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.
|
|
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
|
|
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`,
|
|
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.
|
|
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.
|
|
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
|