leyline-code 0.8.1__py3-none-any.whl

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 (65) hide show
  1. leyline/__init__.py +3 -0
  2. leyline/adapters/__init__.py +19 -0
  3. leyline/adapters/csharp.py +1026 -0
  4. leyline/adapters/generic.py +844 -0
  5. leyline/adapters/python.py +929 -0
  6. leyline/adapters/typescript.py +1512 -0
  7. leyline/affected.py +509 -0
  8. leyline/agent_skills.py +311 -0
  9. leyline/change.py +500 -0
  10. leyline/channels.py +1782 -0
  11. leyline/cli.py +1029 -0
  12. leyline/cluster.py +149 -0
  13. leyline/context.py +531 -0
  14. leyline/coupling.py +485 -0
  15. leyline/coverage.py +376 -0
  16. leyline/diagrams.py +680 -0
  17. leyline/diff.py +1078 -0
  18. leyline/drift.py +747 -0
  19. leyline/exact.py +410 -0
  20. leyline/explain.py +973 -0
  21. leyline/export.py +673 -0
  22. leyline/fncoupling.py +328 -0
  23. leyline/formats.py +923 -0
  24. leyline/grade.py +207 -0
  25. leyline/incremental.py +931 -0
  26. leyline/indexer.py +3733 -0
  27. leyline/learnings.py +743 -0
  28. leyline/loop.py +584 -0
  29. leyline/model.py +142 -0
  30. leyline/outline.py +1066 -0
  31. leyline/packing.py +86 -0
  32. leyline/patterns.py +478 -0
  33. leyline/pr.py +1249 -0
  34. leyline/props.py +255 -0
  35. leyline/query.py +683 -0
  36. leyline/quick.py +853 -0
  37. leyline/related.py +266 -0
  38. leyline/removal.py +231 -0
  39. leyline/renames.py +231 -0
  40. leyline/rereview.py +375 -0
  41. leyline/roslyn_refs/Program.cs +179 -0
  42. leyline/roslyn_refs/RoslynRefs.csproj +16 -0
  43. leyline/rules.py +171 -0
  44. leyline/schema.sql +178 -0
  45. leyline/scip_pb2.py +97 -0
  46. leyline/server.py +1230 -0
  47. leyline/skills/leyline-adversarial-review/SKILL.md +121 -0
  48. leyline/skills/leyline-ask/SKILL.md +57 -0
  49. leyline/skills/leyline-change-impact/SKILL.md +79 -0
  50. leyline/skills/leyline-explain-flow/SKILL.md +70 -0
  51. leyline/skills/leyline-explore-module/SKILL.md +55 -0
  52. leyline/skills/leyline-pr-review/SKILL.md +77 -0
  53. leyline/skills/leyline-quick-change/SKILL.md +63 -0
  54. leyline/skills/leyline-spec/SKILL.md +179 -0
  55. leyline/skills/leyline-tour/SKILL.md +46 -0
  56. leyline/spec.py +1819 -0
  57. leyline/store.py +560 -0
  58. leyline/tours.py +352 -0
  59. leyline/verdicts.py +390 -0
  60. leyline/viewer/viewer.html +1622 -0
  61. leyline_code-0.8.1.dist-info/METADATA +1325 -0
  62. leyline_code-0.8.1.dist-info/RECORD +65 -0
  63. leyline_code-0.8.1.dist-info/WHEEL +4 -0
  64. leyline_code-0.8.1.dist-info/entry_points.txt +2 -0
  65. leyline_code-0.8.1.dist-info/licenses/LICENSE +674 -0
@@ -0,0 +1,121 @@
1
+ ---
2
+ name: leyline-adversarial-review
3
+ description: Attack a change as a logic reviewer or a performance reviewer, using a Leyline map as evidence. Use on a spec after its brief exists and before any code is written, or on a pull request or branch someone else wrote (no spec needed), or when asked to review, challenge or stress-test a change.
4
+ ---
5
+
6
+ # Review a change adversarially with Leyline
7
+
8
+ Two kinds of change can be reviewed: a **spec** (an OpenSpec folder, before any code is written) and a **pull
9
+ request** (code someone already wrote, with no spec; see the section below). Your job is to find what is
10
+ wrong with a change before it costs anything. You are not the author
11
+ and you are not trying to help it pass. Run as a fresh agent that has not seen the spec being
12
+ written. If you cannot start one, do the review as a separate pass: put aside what you know of how
13
+ the spec was written, re-read only the change folder and `leyline.md`, and say in your report that
14
+ the review was not done by a fresh agent. Do one review per run: logic or performance.
15
+
16
+ It works with the Leyline MCP server or with the `leyline` command alone. Without the server:
17
+ `spec_review_facts` is `leyline spec facts <id> --reviewer logic` (or `performance`), which prints
18
+ the same facts as JSON and records that the review ran; `spec_finding` is `leyline spec finding <id>
19
+ --reviewer logic --severity medium --claim "..." --evidence <node id> ... --proposal "..."`;
20
+ `source`, `expand`, `search` and `impact` are `leyline source <id>`, `leyline expand <id>`,
21
+ `leyline search <text>` and `leyline impact <name>`. If neither is there, say so and stop.
22
+
23
+ ## Steps
24
+
25
+ 1. Read the change folder: `proposal.md`, the spec deltas, `tasks.md`, `leyline.md`. For a pull request,
26
+ read its page (`.leyline/reviews/pr-<id>.md`) and the diff.
27
+ 2. Call `spec_review_facts` with the folder and `reviewer` (logic or performance). It returns what
28
+ the graph knows, arranged as the questions below, and records that your review ran, so a review
29
+ that files nothing still shows on the plan.
30
+ - Read `learnings_that_apply` first: past findings on this code that a person rejected, with their reason.
31
+ A finding you file that repeats one comes back with `learned`; it is kept and marked on the page.
32
+ A learning marked `stale` is about code that has changed since the decision (`edited` and `gone` name
33
+ the nodes). It is a question for the person, not an answer: read the new code, and file what you find
34
+ as usual. Do not drop a finding because a stale learning matches it, and do not refile one to get
35
+ around it. Say in your report which stale learnings you met, so the person can confirm or retire them.
36
+ A learning whose `code` is unknown was kept before Leyline recorded its code: treat it as current.
37
+ 3. For every item in your section, read the code (`source`, `expand`, `flow`, or the file itself)
38
+ before deciding. A fact from the graph is a lead, not a finding.
39
+ 4. File each real problem with `spec_finding`: one sentence a person can check, a severity, the node
40
+ ids that show it, and the change to the spec you propose. No node, no finding.
41
+ 5. Report the count by severity and the one finding you would fix first. Stop there.
42
+
43
+ ## A pull request: set it up first
44
+
45
+ When the person asked for the whole review of a pull request, follow the leyline-pr-review skill: it runs this
46
+ one twice and writes the summary. Alone, this skill is the attack step.
47
+
48
+ 1. Check the branch out (`gh pr checkout <number>`), then call `review_pr` with `base` (the branch it merges
49
+ into) and `about` (its title and description, and each linked issue's title and body), or `github` with the
50
+ number; without the server, `leyline pr <base> --about "..."` or `leyline pr --github <number>`. It returns the review's id,
51
+ `pr-<id>`, and a page: what changed, what it reaches and did not change, its tests.
52
+ 2. Use `pr-<id>` wherever the steps below say the change folder: `spec_review_facts` with it gives the facts
53
+ (`leyline spec facts pr-<id> --reviewer logic`), and `spec_finding` files against it. Read the files under
54
+ `house_rules_to_read_first` before anything else: a pull request breaks the repository's own rules more
55
+ often than it breaks the code.
56
+ 3. In the questions below, read "the spec" as "the description". The first logic question for a pull request
57
+ is whether the code does what the description says, all of it and nothing else: name each edit the
58
+ description does not explain, and each thing it promises that no edit does. `proposal` in a finding is the
59
+ change to the code (or the description) you propose.
60
+ 4. The facts for a pull request use the same questions under names without "task": `other_ends_of_those_channels_not_edited`,
61
+ `callers_of_changed_functions_left_alone`, `state_shared_with_unchanged_code`; and add
62
+ `signature_changed_callers_not_edited`, `removed_but_still_called` and `tests.likely_to_fail_unedited`.
63
+ 5. A finding whose evidence is not on the change's blast radius comes back with a warning. Either add the node
64
+ that links it to the change, or ask yourself whether you wandered.
65
+ 6. On a re-review (new commits since the last one; the facts' `since_last_review` names the previous head), start
66
+ from `since_last_review`: read the code changed since then and its `new_facts` first, re-check each finding under
67
+ `may_be_fixed` and tell the person which ones the new code fixed, and do not refile findings under `still_applies`.
68
+
69
+ ## Logic reviewer: answer each of these
70
+
71
+ - Which callers, implementers or overriders must change and have no task? (A pull request:
72
+ `signature_changed_callers_not_edited` and `removed_but_still_called`. Each is a likely break; confirm it
73
+ in the code.)
74
+ - Which channel does the change cross (process, HTTP, file, event), and does the spec say what the
75
+ other end must do? `other_ends_of_those_channels_no_task_names` lists the other launchers, callers or
76
+ readers of the same end: does each one need the change too?
77
+ - Which shared field gains a writer, or changes meaning for its existing readers?
78
+ - Which new member is named like one its type already has (`new_members_named_like_existing_ones`)?
79
+ Read every user of the existing one: does it need the new one too?
80
+ - Who else calls each changed function (`callers_of_changed_functions_the_spec_leaves_alone`)? Does
81
+ the change alter what those callers get or can assume?
82
+ - Which state do the changed functions use that other, unchanged functions also use?
83
+ - For each scenario: would its test still pass if the task it is meant to prove were left out?
84
+ - Which scenario has no test? Which requirement has no scenario?
85
+ - What do the scenarios leave out: the error path, the empty case, ordering, the second caller,
86
+ what happens to data written before the change?
87
+ - Which existing rule or pattern does the design break, and is that said?
88
+ - Does any task contradict another, or the proposal?
89
+
90
+ ## Performance reviewer: answer each of these
91
+
92
+ - Which changed functions do the most flows pass through, and which sit inside the main loop? Read
93
+ the callers to confirm: the count of flows is a proxy.
94
+ - Does the change add work per call, per item or per tick on those functions?
95
+ - Does it add allocation, I/O, serialisation, a lock or a process hop on a hot path?
96
+ - Does it grow a message or a structure that crosses a channel on every step?
97
+ - What is the measured baseline, and which test would show a regression? If none exists, that is a
98
+ finding.
99
+
100
+ ## Severity
101
+
102
+ - **high**: the change will be wrong, or will break something the spec does not mention, if
103
+ implemented as written.
104
+ - **medium**: a gap that will probably cost a second round.
105
+ - **low**: worth a sentence in the spec.
106
+
107
+ ## Rules
108
+
109
+ - Do not rewrite the spec, or push to someone else's branch. Propose the change in the finding and let the
110
+ person decide.
111
+ - Do not file style or naming preferences.
112
+ - Do not refile what a learning already settled, unless the code changed in a way its reason did not cover.
113
+ Then say in the claim what changed.
114
+ - A finding whose claim starts "/opsx:verify:" was filed from OpenSpec's verify (the leyline-spec skill says how).
115
+ It is an LLM's opinion: read the code behind it like any other lead, and do not file it again. It does not
116
+ change `check`'s verdict, and `check` passing does not settle it.
117
+ - A stale learning settles nothing on its own. Keep the finding it matches; the page shows the person that
118
+ the code changed, and they decide (`learnings` with `confirm` or `retire`, only on their word).
119
+ - If the facts are empty and you found nothing after reading the code, say so in one line. A review
120
+ that finds nothing is a valid result.
121
+ - Say what you could not check and why.
@@ -0,0 +1,57 @@
1
+ ---
2
+ name: leyline-ask
3
+ description: Answer a question about a mapped codebase from its Leyline map and its source, citing the code. Use when asked how something works, what happens when something runs, what a part of the code holds, where something is, who calls it, or what changing it would affect.
4
+ ---
5
+
6
+ # Answer a question about the code with Leyline
7
+
8
+ Answer from the map and the source, never from memory. Every claim names the code it rests on.
9
+
10
+ It works with the Leyline MCP server or with the `leyline` command alone:
11
+
12
+ | MCP tool | Command |
13
+ | --- | --- |
14
+ | `map` | `leyline map <repo>` |
15
+ | `overview`, `search`, `expand`, `source` | `leyline overview`, `leyline search <text>`, `leyline expand <id>`, `leyline source <id>` |
16
+ | `neighbors` | `leyline neighbors <id> --direction in --kinds calls` |
17
+ | `impact` | `leyline impact <name or id>` |
18
+ | `context` | `leyline context <name, path or id> --tokens 2000` |
19
+ | `module_outline` | `leyline outline [module]` |
20
+ | `trace`, `flows`, `flow` | none; use the server |
21
+
22
+ If neither is there, say so and stop. If a tool says nothing is mapped, call `map` first.
23
+
24
+ ## Route the question
25
+
26
+ | The question | Do this |
27
+ | --- | --- |
28
+ | How does X work? What happens when Y? | the leyline-explain-flow skill |
29
+ | What is in this part? Where do I start? | the leyline-explore-module skill |
30
+ | What would changing X affect? | the leyline-change-impact skill (`impact` alone for a quick answer) |
31
+ | Who calls X? Where is X? What does X use? | the steps below |
32
+
33
+ ## Steps
34
+
35
+ 1. **Find the code.** `search` with one distinctive word of the name, then `expand` the best hit to confirm it.
36
+ If two things fit, say which you picked and why, or ask.
37
+ 2. **Use the narrowest tool.** Who calls it: `neighbors` (direction in, kinds calls). Everything that can reach
38
+ it: `impact`. What it calls and the fields it touches: `expand`. The code around it: `context`. How one
39
+ function reaches another: `trace`.
40
+ 3. **Read before you claim.** Call `source` on each thing you will say something about. The map says that A
41
+ calls B, not why or under what condition.
42
+ 4. **Answer** in a few sentences, then the evidence.
43
+
44
+ ## Say how sure you are
45
+
46
+ - Cite each claim with its node id, or `path:line`.
47
+ - Say which links are exact (a compiler confirmed them), which come from syntax, and which are guesses
48
+ (marked `guess` or `guessed`). A guessed link is a lead to check in the source, not a fact.
49
+ - Say what the map cannot see: calls by reflection or a name built at run time, a channel whose other end is
50
+ built at run time, files in a language with no adapter, extractors that did not run (`overview` lists them).
51
+ - Say what you did not read.
52
+
53
+ ## Rules
54
+
55
+ - No node, no claim. Never guess a node id: take it from `search`, `overview` or `expand`.
56
+ - Answer what was asked. Offer the next question; do not answer it unasked.
57
+ - Do not edit code or write views while answering a question.
@@ -0,0 +1,79 @@
1
+ ---
2
+ name: leyline-change-impact
3
+ description: Assess a described code change against a Leyline map and save a blast-radius view, review an implemented change against its proposal, or save any custom view of the code. Use when asked what a change will touch, break or need tested, or whether a change went as planned.
4
+ ---
5
+
6
+ # Assess a change with Leyline
7
+
8
+ Use this when the user describes a change (a spec, a ticket, a sentence) and wants to know what it
9
+ touches before any code is written, or asks for a picture of some slice of the codebase. It needs the
10
+ Leyline MCP server connected and the repository indexed. If the `overview` tool is missing, say so and
11
+ stop: do not guess the impact from memory.
12
+
13
+ A question about the code with no change in mind goes to the leyline-ask skill. A change to plan and check with a
14
+ spec is the leyline-spec skill; a one-line fix, leyline-quick-change.
15
+
16
+ Leyline computes reach; you decide which nodes the words refer to. Keep those two jobs separate and
17
+ tell the user which is which.
18
+
19
+ ## Steps
20
+
21
+ 1. **Read the change.** Restate it in one sentence. If it could mean two different things in this
22
+ codebase, ask before going on.
23
+ 2. **Orient.** Call `overview` once. Note the modules, the systems and which extractors did not run:
24
+ anything marked not analyzed is a blind spot for this assessment.
25
+ 3. **Find the targets.** For each thing the change mentions, use `search`, then `expand` to confirm
26
+ it is the right node. Read `source` when the name alone does not settle it. Prefer functions over
27
+ whole types: a type target counts every function inside it and inflates the result.
28
+ 4. **Choose an action for each target.**
29
+ - `behavior`: same parameters and return type, different result or side effect
30
+ - `signature`: parameters or return type change
31
+ - `rename`, `remove`
32
+ - `add`: something new. Give its `name`, the `parent` it goes in, what it `uses` and what is `used_by` it.
33
+ 5. **Look across channels yourself.** If a target sends or receives data over a process pipe, an
34
+ event, a file or the network, the code on the other side has no link to it in the graph. Find the
35
+ reader or writer on the far side (`search`, `source`) and add it as a target with a note that says
36
+ what it must do. Leyline flags that a channel is involved; it cannot tell you which function
37
+ parses the bytes.
38
+ 6. **Call `propose_change`** with the user's intent in their words, a short title and the targets.
39
+ Give every target a `note` saying what changes there.
40
+ 7. **Read the result before reporting.** Check that `must_edit` makes sense. If it is empty for a
41
+ breaking change, or huge for a small one, a target is probably wrong: fix it and call again.
42
+ Follow up with `impact` or `flow` on anything surprising.
43
+ 8. **Report** in this order: what must be edited, the risks as flagged, the tests to run, what no
44
+ test covers, and what Leyline could not see. Tell the user the view is saved under the title you
45
+ gave it and appears in the map's Views tab after a refresh.
46
+
47
+ ## After the change is implemented
48
+
49
+ Do this when the user asks whether a change went as planned, or when you implemented it yourself.
50
+
51
+ 1. Before editing, run the tests and call `record_test_run` with run `before`. If the edits are
52
+ already made, skip this and say the review has no test baseline.
53
+ 2. After the edits, run the tests again and record run `after`. Ask for the repository to be
54
+ re-indexed (`leyline index`); the review compares stores, not files.
55
+ 3. Call `review_change` with the change id and the two run labels.
56
+ 4. Report the findings first. Then, for each edit that was not predicted, read its `source` and say
57
+ whether it was a needed follow-on the proposal missed or drift outside the change. For each
58
+ predicted edit that did not happen, say whether the prediction was wrong or the work is unfinished.
59
+ 5. A new link between modules or a newly broken rule is a design decision: put it to the user, do
60
+ not wave it through.
61
+
62
+ To record a design constraint, call `add_rule`. Pass `confirmed=true` only when the user stated the
63
+ rule themselves; a rule you inferred from the code or the docs is a suggestion, with your `reason`.
64
+
65
+ ## Custom views
66
+
67
+ When the user wants to see something that is not a change (how a feature works end to end, two
68
+ design options side by side, everything that touches one concept), collect the node ids and call
69
+ `save_view`. Group marks with short `role` labels, give each a one-line `note`, describe the roles in
70
+ `legend`, and explain the view in `narrative`. To compare design options, save one view per option
71
+ with the same role names so they read alike.
72
+
73
+ ## Rules
74
+
75
+ - Never present the reach as proof the change is safe. It is static: it shows what can be affected,
76
+ not whether behavior stays correct.
77
+ - Say when a link in the result is marked guessed.
78
+ - Do not write annotations or views about code you did not look at.
79
+ - After the change is implemented, ask for the repository to be re-indexed before assessing again.
@@ -0,0 +1,70 @@
1
+ ---
2
+ name: leyline-explain-flow
3
+ description: Answer "how does X work" or "what happens when Y" about a mapped codebase by finding where the behavior starts and walking it step by step on a Leyline map, reading the code at each step. Use when asked to find, trace, follow or explain a flow, a request, a feature or a code path from a description, especially in a large repository.
4
+ ---
5
+
6
+ # Explain a flow with Leyline
7
+
8
+ The person describes a behavior in words. Leyline finds where it could start and walks the calls and channels from
9
+ there; you decide which start fits, read the code, and write the answer. Leyline holds no language model: every step
10
+ it gives is a link on the map, and every sentence you write must rest on one of those steps or on code you read.
11
+
12
+ It works with the Leyline MCP server or with the `leyline` command alone:
13
+
14
+ | MCP tool | Command |
15
+ | --- | --- |
16
+ | `find_flows(description)` | `leyline find-flows "<description>"` |
17
+ | `explain_path(start, to?, through?, max_steps?)` | `leyline explain-path <start> [--to X] [--through Y] [--steps N]` |
18
+ | `diagram(ids)` | `leyline diagram <id or name> ...` |
19
+ | `source(node_id)` | `leyline source <id>` |
20
+ | `save_tour(title, stops)` | none: the server only |
21
+ | `map` | `leyline map <repo>` |
22
+
23
+ Add `--json` to a command for the same fields the tool returns. If neither the server nor the command is there, say so
24
+ and stop. If a tool says nothing is mapped, run `map` first.
25
+
26
+ ## Steps
27
+
28
+ 1. **Restate the question** in one sentence, in the code's terms if you know them ("what happens when a writer saves
29
+ a dialogue: from the editor's Save to the file on disk").
30
+ 2. **Call `find_flows`** with the question in plain words. Each candidate has its kind (route handler, UI event
31
+ handler, program entry, message handler, test, function), `at` (file:line), `why` it matched, and the flows that
32
+ start there (`flows`); where none starts, the entry points' flows that reach it (`reached_from`) and the tests'
33
+ (`tests_reaching`).
34
+ 3. **Pick the start.** When `ambiguous` is true, or the first few candidates are different things (a UI handler, a
35
+ route, a test), show the person two to four of them, one line each, and ask which they mean; or pick one and say
36
+ why in a sentence. A UI or command handler is usually the best start for "what happens when"; a route handler when
37
+ the question is about the server; a test whose name states the behavior when nothing else fits. If no candidate
38
+ fits, call `find_flows` again with the words the code would use, or use `search`.
39
+ 4. **Call `explain_path`** from that start. With nothing else it follows the main flow; give `to` when the question
40
+ names an end ("until it is written to disk") and `through` when it names a stop on the way. Raise `max_steps`, or
41
+ walk again from a later step, when `left_out` hides the part that matters.
42
+ 5. **Read the code** (`source`) at every step you will say something about: the start, each step that crosses a
43
+ channel (`crosses`), each `later_elsewhere`, and each step whose name does not say what it does. The excerpt in a
44
+ step (`call`, `declaration`) is one line; it is not enough to say what a function does.
45
+ 6. **Write the answer** as a short numbered walk, one step a line, each naming the code and where it is:
46
+
47
+ > 1. The Save button's handler `DialogueCanvas.save` (DialogueCanvas.tsx:230) calls `saveEntity` in the store.
48
+ > 2. `performSave` (store.ts:867) sends `PUT /api/entities/:type/:id` to the host, a separate process.
49
+ > 3. The host's handler for that route (server.ts:361) checks the entity's shape, then `saveOne` writes the file.
50
+ > 4. It then calls `scheduleValidation` (validation.ts:161); validation runs later, off the request.
51
+
52
+ Say where the walk crosses into another process, program or service, and where data is written for something
53
+ that reads it later. Skip steps that add nothing (a helper that formats a string); keep the ones a person would
54
+ need to change the behavior.
55
+ 7. **Include the diagram**: the `mermaid` text of the walk, in a ```` ```mermaid ```` block. Use `diagram` for a
56
+ different set of functions.
57
+ 8. **Say what the map could not see**: the `not_seen` notes that apply (calls through callbacks or frameworks, an
58
+ interface whose implementation is picked at run time, links guessed by name, messages sent over a program's pipes,
59
+ a walk cut at its depth limit), in one or two sentences.
60
+ 9. **Offer to save it as a tour** so it can be reopened from the map page. If the person agrees, call `save_tour`
61
+ with one stop per step you wrote, each `{"title", "kind": "node", "ref": <step id>, "narrative": <your sentence>}`.
62
+
63
+ ## Rules
64
+
65
+ - Every claim cites a node: its name and file:line, from a step or from code you read.
66
+ - Never invent a step the map or the code does not show. If the walk stops where the behavior clearly goes on, say
67
+ where it stops and why (`not_seen`), and read the code to find the next step yourself; say that you found it by
68
+ reading, not on the map.
69
+ - A step marked `guessed` is a link the map found by name: check it in the code before relying on it.
70
+ - Keep the answer short: a walk of 4 to 10 steps, the diagram, and the blind spots. Offer more depth, do not pad.
@@ -0,0 +1,55 @@
1
+ ---
2
+ name: leyline-explore-module
3
+ description: Explore one large module of a mapped codebase with Leyline, name its parts from their code, and give the person a one-screen guide to it. Use when asked what a module or folder holds, where to start reading in it, how its parts connect, or which parts are risky to change.
4
+ ---
5
+
6
+ # Explore a large module with Leyline
7
+
8
+ On a large repository one module can hold hundreds of files. Leyline splits it into at most twelve parts
9
+ (folders, or groups of files that work together where a folder is flat). You read each part, name it, and
10
+ give the person a guide they can read in one screen.
11
+
12
+ It works with the Leyline MCP server or with the `leyline` command alone:
13
+
14
+ | MCP tool | Command |
15
+ | --- | --- |
16
+ | `module_outline` | `leyline outline [module or part id] --depth 2` (`--json` for the ids) |
17
+ | `name_part` | `leyline name-part <part id> "<name>" --summary "<one line>" --evidence <node ids>` |
18
+ | `source`, `context` | `leyline source <id>`, `leyline context <name or path> --tokens 2000` |
19
+ | `search`, `expand` | `leyline search <text>`, `leyline expand <id>` |
20
+ | `save_tour` | none; use the server |
21
+
22
+ If neither is there, say so and stop. If a tool says nothing is mapped, call `map` first.
23
+
24
+ ## Steps
25
+
26
+ 1. **Pick the module.** Take the one the person names. If they name none, call `module_outline` with no
27
+ module and take the largest. A part id from an earlier outline works too.
28
+ 2. **Get the outline.** `module_outline(module)`. It gives each part's size, entry points, what it uses and
29
+ what uses it, channels, busiest functions, key types and risks. Note the parts that already have a name:
30
+ do not rename one the person named (`named_by`), and read again any marked `stale`.
31
+ 3. **Read each part.** For each part without a name, read the code that tells you what it is for: its
32
+ busiest functions and key types (`source` on their ids), its entry points, and for a folder its main
33
+ file. `context` on a part's key function shows the code around it. Read at least two items per part.
34
+ 4. **Name each part.** `name_part(part_id, name, summary, evidence)`: a short name a person would use
35
+ ("Validation rules", not "validation folder"), a one-line summary of what it does, and as evidence the
36
+ node ids you read. Skip a `@more` part: it only holds the rest of the level.
37
+ 5. **Go one level down where it helps.** A part with many files and no clear purpose: call
38
+ `module_outline` with its id, and repeat steps 3 and 4 for its parts. Stop at two levels unless asked.
39
+ 6. **Write the guide.** Call `module_outline(module)` again so the names show, then give the person one
40
+ screen:
41
+ - one line on what the module does;
42
+ - the parts, each with its name and summary, largest first;
43
+ - how they connect: which parts call which, and the channels to other modules (routes, files, events);
44
+ - where to start reading for two or three common tasks, each a part and a function or type in it;
45
+ - which parts are risky to change: busy (on the most flows), many dependents, or few tests (from
46
+ `risky`), and why.
47
+ 7. **Offer to save it as a tour** (the leyline-tour skill, `save_tour`), one stop per part, in reading order.
48
+
49
+ ## Rules
50
+
51
+ - Names come from reading code, never from folder names alone. Cite the nodes you read for each part.
52
+ - One screen per level. Put detail behind a drill-down, not in the guide.
53
+ - Say what the outline cannot see: a part reached only through a framework, a callback or a channel the map
54
+ did not follow can look unused.
55
+ - Do not edit code while exploring.
@@ -0,0 +1,77 @@
1
+ ---
2
+ name: leyline-pr-review
3
+ description: Review a pull request or branch someone else wrote, with no spec, using a Leyline map. Maps what changed and what it reaches, runs an adversarial logic and performance review, and gives the person a short summary with the one finding to fix first. Use when asked to review a pull request, a branch or someone's changes, or to review one again after new commits.
4
+ ---
5
+
6
+ # Review a pull request with Leyline
7
+
8
+ The code exists; what it was meant to do is a title and a paragraph. Leyline reads the change from the code.
9
+ Your job is to tell the person what it does, what it breaks or leaves undone, and what to fix first.
10
+
11
+ It works with the Leyline MCP server or with the `leyline` command alone:
12
+
13
+ | MCP tool | Command |
14
+ | --- | --- |
15
+ | `review_pr` (`base`, `about`) | `leyline pr <base> --about "<title and description>"` |
16
+ | `review_pr` (`github`) | `leyline pr --github <number>` |
17
+ | `review_pr` (`gate_passed`, `blocking`) | `leyline pr <base> --gate` (exits 1 while something blocks) |
18
+ | `spec_review_facts` | `leyline spec facts pr-<id> --reviewer logic` (or `performance`) |
19
+ | `spec_finding` | `leyline spec finding pr-<id> --reviewer logic --severity high --claim "..." --evidence <node id> --proposal "..."` |
20
+ | `spec_findings` | `leyline spec findings pr-<id>` |
21
+ | `affected_tests` | `leyline affected-tests pr-<id>` |
22
+ | `source`, `expand`, `impact` | `leyline source <id>`, `leyline expand <id>`, `leyline impact <name>` |
23
+
24
+ If neither is there, say so and stop.
25
+
26
+ ## Steps
27
+
28
+ 1. **Check the branch out** (`gh pr checkout <number>`, or `git switch <branch>`). Leyline reads the working
29
+ tree, so review the checkout, not a diff pasted in.
30
+ 2. **Read what it was meant to do.** `gh pr view <number> --json title,body,closingIssuesReferences`, then
31
+ `gh issue view <m> --json title,body` for each linked issue. If `gh` is not there or no issue is linked, say so
32
+ and go on with the title and description alone.
33
+ 3. **Call `review_pr`** with `base` (the branch it merges into) and `about`: the title and description, then each
34
+ linked issue's title and body (`--about-file` for long text). With `github`, still pass `about` when there are
35
+ linked issues. Keep the `change_id` (`pr-<id>`). Read the page, and the files under
36
+ `house_rules` before anything else: a pull request breaks the repository's own rules more often than the code.
37
+ 4. **Run the leyline-adversarial-review skill** on `pr-<id>` twice: once as the logic reviewer, once as the
38
+ performance reviewer. Fresh agents are best; if you cannot start one, do two separate passes and say so.
39
+ Each files its findings with `spec_finding`.
40
+ 5. **Hold the code against each linked issue.** Decide from the page's "What changed" and the code, not from the
41
+ description, whether it addresses the issue. Where the code and an issue disagree, file a logic finding with
42
+ `spec_finding`, the issue's number in the claim.
43
+ 6. **Call `spec_findings`** with `pr-<id>`: everything filed, with ids.
44
+ 7. **Call `review_pr` again** so the gate counts the findings just filed. It returns `gate_passed` and
45
+ `blocking`: what holds up the merge under the project's `[pr] blocking` in `openspec/leyline.toml` (by
46
+ default unedited callers of a changed signature, removed code still called, confirmed error rules newly
47
+ failing, and open high findings).
48
+ 8. **Summarize for the person**, in this order, on one screen:
49
+ - **Gate**: passes, or blocked, with each line of `blocking` and what to do about the first (the page's
50
+ `Next:` line). Say which config it ran under (the default, or `openspec/leyline.toml`).
51
+ - **What changed**: two sentences, from the page's "What changed", not from the description.
52
+ - **Linked issues**: one line each: addressed, partly or not, citing "What changed". Or say there were none, or
53
+ that `gh` was not there.
54
+ - **What it breaks or leaves**: callers of a changed signature left alone, removed code still called, other
55
+ ends of a channel not edited, changed code no test runs. One line each, with the node.
56
+ - **Findings**: high, then medium, then low; one line each, with its id and its evidence.
57
+ - **Fix first**: the one finding to fix first, and why.
58
+ - **Not checked**: what you could not check, and why.
59
+ 9. Point to the page (`written`) for the whole review. Ask the person to decide each finding; record a decision
60
+ they state with `spec_resolve`.
61
+
62
+ ## Review it again after new commits
63
+
64
+ Check the new commits out and call `review_pr` again, with the same `review_id` or `github` number. The page
65
+ opens with "Since the last review", and the facts carry `since_last_review`:
66
+
67
+ 1. Start there: the functions edited since the last head, and its `new_facts`.
68
+ 2. Re-check each finding under `may_be_fixed` in the new code, and tell the person which the new commits fix.
69
+ 3. Do not file again what is under `still_applies`.
70
+ 4. Review only the new code adversarially. Open the summary with what changed since the last review, and
71
+ whether the gate result changed: it is judged again from the new code and the findings as they stand.
72
+
73
+ ## Rules
74
+
75
+ - Do not push to the author's branch or edit their code. Propose; the person decides.
76
+ - Do not resolve a finding on your own judgment.
77
+ - Describe the change from the code. Where the description, or a linked issue, and the code disagree, that is a finding.
@@ -0,0 +1,63 @@
1
+ ---
2
+ name: leyline-quick-change
3
+ description: Make a small code change (a constant, one function and its caller) on a mapped codebase with no spec folder, and have Leyline say whether it was done. Use when asked for a one-line fix, a changed value or a small tweak, and to decide when a change has grown and needs a spec.
4
+ ---
5
+
6
+ # Make a quick change with Leyline
7
+
8
+ `quick` gives a small change the same answers as a spec, with no folder: what it will touch, what it reaches,
9
+ and whether it was done. Three steps: `quick` before, the edit, `quick` with `done` after.
10
+
11
+ It works with the Leyline MCP server or with the `leyline` command alone:
12
+
13
+ | MCP tool | Command |
14
+ | --- | --- |
15
+ | `quick` (`what`, `names`, `test_output`) | `<test command> \| leyline quick "<what>" --about <names> --tests -` |
16
+ | `quick` (`done`, `test_output`) | `<test command> \| leyline quick --done quick-<slug> --tests -` |
17
+ | `quick` (`done`, `names`) | `leyline quick --done quick-<slug> --about <name>` |
18
+ | `search`, `expand`, `source` | `leyline search <text>`, `leyline expand <id>`, `leyline source <id>` |
19
+ | `affected_tests` | `leyline affected-tests quick-<slug>` |
20
+ | none | `leyline quick --to-spec <id> quick-<slug>` |
21
+
22
+ If neither is there, say so and stop.
23
+
24
+ ## Is it quick?
25
+
26
+ Quick fits a value or one or two functions, with no design to agree. Use the leyline-spec skill instead when:
27
+
28
+ - the person has to choose between designs, or agree what "done" means;
29
+ - it adds a feature, a public API or a data format;
30
+ - it changes what crosses a channel (a route, an event, a queue, a table, a file, a program's input): both ends
31
+ must agree.
32
+
33
+ ## Steps
34
+
35
+ 1. **Find the code.** `search`, then `expand` to confirm. Use names as the code writes them: `Owner.method`,
36
+ `module.func`, a constant.
37
+ 2. **Before the edit.** Run the tests. Call `quick` with `what` (one sentence), `names` and `test_output`. If
38
+ you cannot run the tests, say so: without them `done` cannot tell a test the change broke from one that
39
+ already failed.
40
+ 3. **Read the answer:** what it will touch, what must be edited with it, the channels, the tests that run it.
41
+ Tell the person anything bigger than they said. If `grown` is not empty, stop and escalate (below).
42
+ 4. **Edit** the named code, and what the answer says must be edited with it. Nothing else.
43
+ 5. **After the edit.** Run the tests (`affected_tests` names the ones to run), then call `quick` with `done` (the
44
+ `change_id`) and `test_output`.
45
+ 6. **Report the verdict as it comes:** `done`, then each item with its verdict and why. An edit that belonged
46
+ but was not named: call `quick` again with `done` and `names` to add it. Do not leave it out of the report.
47
+ 7. If `grown` is not empty now, escalate.
48
+
49
+ ## Escalate to a spec
50
+
51
+ `grown` says why: too many pieces of code, callers that must change, or a channel crossed. Then:
52
+
53
+ 1. Tell the person why the change grew, in a sentence.
54
+ 2. Write `openspec/changes/<id>/` with the leyline-spec skill.
55
+ 3. Run `leyline quick --to-spec <id> quick-<slug>`: the spec starts from this baseline and the tests from before.
56
+ 4. Go on with `plan` and `check`, as leyline-spec says.
57
+
58
+ ## Rules
59
+
60
+ - Never call the change done from your own account. `quick` with `done` reads the code.
61
+ - Do not widen the edit to tidy nearby code. That is a second change.
62
+ - For a review, use the change id as a spec's: `spec_review_facts` with `quick-<slug>`. The person resolves
63
+ findings, not you.