~/bend-docscommunity

src/doctor/plan.bend checks

raw source on the hub · import 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/plan.bend as Plan

doctor/plan: ez doctor as a pure planner. It reads a World (doctor/world.bend) and returns either the questions it still needs answered (step) or a Plan: the lines to print and how the command ends (plan). The interpreter (doctor/run.bend) loops on step, answering each question by IO, until nothing is left to ask, then prints the plan.

Doctor says what would stop this project from building. Each line reports what was found rather than a tick, because the useful answers here are values: which bend, which compiler, which packages are on disk, and which hashes the source and the ledger disagree about. A line that is a problem fails the command, as cargo check fails on the first thing it cannot build, though doctor goes on to say everything it found.

The plan is lines said and an outcome, and nothing else: doctor writes no file, lays no tree and removes nothing (EZ-VEN-4). The questions it asks write nothing either: a program asked for its version, ls of the library, git's listing of the tracked sources, and a package's files read from under BEND_LIB.

A named import, import <name>@<version>/..., is read the same way: its name is what the import line names, reported when no dependency of the ledger records it, and a dependency recorded by a name is used when an import line names it by that name or by its hash. Each name the lock records has its file under BEND_LIB/names, which bend reads the name's hash from before it asks the hub; one missing, or naming another hash, is reported with the library, and fails the command.

The drift report is the ledger against the import lines. A package's 0x hash is written in two places, the [deps.<name>] section of ez.toml and the import 0x... line that uses it, so the two can disagree. ez treats the ledger as the record and the import lines as the truth, and reports the disagreement both ways rather than rewriting anyone's source (EZ-VEN-5). An import line is one the lock reads as one: in the header of a .bend file git tracks outside .ez/, found by the package walk's own scan (P.roots), so doctor and ez lock never disagree about what the source imports. A ledger's [tools.*] pins are not dependencies, and the report never reads them (EZ-LED-5).

The lock is checked the way cargo --locked and uv lock --check check one, without the network: doctor puts a plain ez lock to the lock's own planner (lock/plan.bend), over the ledger as it is, tools and all, the sources git lists, and the trees BEND_LIB holds, and compares the text it would write with ez.lock.toml byte for byte (EZ-VEN-6). So every hash, source, file sum and tool pin the lock records is checked, by the code that writes them. A package the lock would read and BEND_LIB lacks is one doctor cannot see, and the lock is then said to be unchecked rather than guessed at; that, a lock ez lock would refuse to write, and a lock it would write otherwise, each fail the command.

The Effect, Plan and Outcome types are the lock's (lock/plan.bend), as for the other commands.

8 imports
import Base
import ../toml/toml.bend as T
import ./world.bend as DW
import ../lock/plan.bend as P
import ../lock/world.bend as W
import ../lock/lock.bend as L
import ../ledger/manifest.bend as M
import ../share/args.bend as Args

Types

type Note source · line 62 · raw

Data

one thing doctor looked at: what to print, and whether it is a problem

type Locked source · line 165 · raw

Data

what the lock turned out to be: the packages it records, or why it could not be read, or no lock at all

type Step source · line 957 · raw

Data

the questions still open, or the plan once there are none

Definitions

def plural source · line 66 · raw

@+count:Nat -> @one:String -> @many:String -> String

a count with its noun, kept in agreement

def answered source · line 71 · raw

@ok:Bool -> @+text:String -> List<&2, String>

the lines a run printed, or none when it failed, so a program's complaint on stderr is never mistaken for an answer

def banner.of source · line 82 · raw

@ls:List<&2, String> -> String

the first line of what a program printed

def probe.note source · line 94 · raw

@ok:Bool -> @name:String -> @+text:String -> Note

what a version run said about the program it ran

def probe.answer source · line 102 · raw

@answer:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Answer -> @+name:String -> Note

what the answer to a version question says

def probe.heard source · line 110 · raw

@got:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Heard -> @+name:String -> Note

a program's line, once it was asked

def cc.name source · line 120 · raw

@+var:String -> String

the C compiler the native lane will use: $CC when it is set, else cc. Same source and a different compiler is a different binary, so doctor names it.

def programs source · line 126 · raw

@+cc:String -> List<&2, String>

the programs doctor asks for their versions. bend's check report changed wording in 2.0.32, which the proof gate reads, and the native lane needs a C compiler, so the version is the finding.

def probes source · line 130 · raw

@ns:List<&2, String> -> @+rs:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Reply> -> List<&2, Note>

every program's line

def deps.of source · line 141 · raw

@manifest:0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Manifest -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Dep>

the dependencies of a ledger that was read

def deps.count source · line 146 · raw

@ledger:0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Read -> Nat

how many dependencies a ledger names; one that did not read names none

def ledger.note source · line 154 · raw

@ledger:0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Read -> Note

what the ledger turned out to be

def locked.pick source · line 171 · raw

@ok:Bool -> @why:String -> @ss:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/toml/toml.Sect> -> Locked

the verdict on a parse, with the answer in hand

def locked.parsed source · line 179 · raw

@toml:0x74799d3f846634a3d7461d4336d7c9d4/src/toml/toml.Toml -> Locked

a lock that parsed, by the packages it records; one that did not, by why

def locked.of source · line 184 · raw

@got:Maybe<&2, String> -> Locked

the lock's text, read

def locked.hashes source · line 192 · raw

@lk:Locked -> List<&2, String>

the packages a lock records; none when it did not read or is not there

def lock.needs source · line 202 · raw

@deps:Nat -> Bool

whether a ledger with this many dependencies needs a lock that names some

def lock.wrong source · line 212 · raw

@deps:Nat -> @hs:List<&2, String> -> Bool

whether the lock is a problem: it names no package while the ledger has dependencies it should have resolved. A project with no dependencies has nothing to lock, so a lock naming nothing, or no lock at all, is its due.

def lock.note source · line 222 · raw

@+deps:Nat -> @lk:Locked -> Note

what the lock amounts to. A lock that is there and does not parse is a problem whatever the ledger holds, since ez fetch refuses it, as cargo refuses a Cargo.lock it cannot read.

def lib.at source · line 242 · raw

@+var:String -> String

where the packages this build resolves against live. It is what ez itself passes to every bend it starts, so an unset BEND_LIB is not a finding: the default is .ez/lib beside the project, and what matters is what is in it.

def lib.have source · line 246 · raw

@got:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Heard -> List<&2, String>

the names ls gave for the library, none when it gave none

def has.step source · line 260 · raw

@here:Bool -> @rest:(@_:Unit -> Bool) -> Bool

the rest of a scan only when this one was not it. Bool.or reduces both of its sides, so a scan written with it reads the whole list even when the first entry answers. The rest arrives as a thunk.

def has source · line 268 · raw

@ss:List<&2, String> -> @+want:String -> Bool

whether a list holds this string

def missing.put source · line 276 · raw

@hit:Bool -> @item:String -> @rest:List<&2, String> -> List<&2, String>

a string kept when the other list lacks it

def missing source · line 284 · raw

@xs:List<&2, String> -> @+known:List<&2, String> -> List<&2, String>

the strings of xs that known does not hold

def lock.names source · line 293 · raw

@lock:Maybe<&2, String> -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/lock.Name>

the names the lock records, with the hash each names; none when there is no lock, or when it does not read

def name.held source · line 302 · raw

@same:Bool -> @+nv:String -> @+hash:String -> @+was:String -> List<&2, String>

what a name's file says against the lock: nothing when it holds the lock's hash, as bend trims it, and the fault otherwise

def name.got source · line 309 · raw

@got:Maybe<&2, String> -> @+nv:String -> @+hash:String -> List<&2, String>

def name.heard source · line 317 · raw

@got:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Heard -> @+nv:String -> @+hash:String -> List<&2, String>

def names.wrong source · line 331 · raw

@ns:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/lock.Name> -> @+rs:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Reply> -> List<&2, String>

every name of the lock whose file under BEND_LIB is missing, or names another hash than the lock does, which bend would read instead of asking the hub

def names.said source · line 339 · raw

@+count:Nat -> String

what the library holds of the lock's names, said after its packages

def lib.faults source · line 347 · raw

@gone:List<&2, String> -> @bad:List<&2, String> -> String

what is wrong with the library, each fault in its place

def lib.said source · line 362 · raw

@all:Bool -> @+dir:String -> @+count:Nat -> @+names:Nat -> @gone:List<&2, String> -> @bad:List<&2, String> -> Note

BEND_LIB judged against the lock: every package the lock names has to be on disk, because bend resolves a hub import during the check and a sandbox has no network to fall back on, and so does every name's file, since bend would otherwise ask the hub what the name names

def lib.judge source · line 371 · raw

@+dir:String -> @+want:List<&2, String> -> @+ns:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/lock.Name> -> @have:List<&2, String> -> @+rs:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Reply> -> Note

the verdict, once what is wanted and what is there are both known

def lib.note source · line 384 · raw

@+dir:String -> @+want:List<&2, String> -> @+ns:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/lock.Name> -> @+rs:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Reply> -> Note

the library's line

def once.put source · line 391 · raw

@dup:Bool -> @item:String -> @rest:List<&2, String> -> List<&2, String>

a head kept when the rest does not hold it again

def once source · line 399 · raw

@ss:List<&2, String> -> List<&2, String>

every string of a list once, each where it last stands

def imports source · line 409 · raw

@+fs:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Source> -> List<&2, String>

every hub package the project's sources import, each once, by hash and by name. These are the lock's roots: the header imports of every tracked .bend file outside .ez/, as the package walk scans them.

def pinned.at source · line 413 · raw

@none:Bool -> @nv:String -> @rest:List<&2, String> -> List<&2, String>

a dependency's name, when the ledger records it by one

def pinned.nv source · line 420 · raw

@+nv:String -> @rest:List<&2, String> -> List<&2, String>

def pinned source · line 424 · raw

@ds:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Dep> -> List<&2, String>

the hashes a ledger's dependencies name, and the names it records them by

def used source · line 432 · raw

@+hs:List<&2, String> -> @+dependency:0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Dep -> Bool

whether an import line names a dependency, by its hash or by its name

def unrecorded.line source · line 438 · raw

@+hash:String -> String

how a hash imported and not in the ledger reads

def unrecorded source · line 442 · raw

@hs:List<&2, String> -> List<&2, String>

every hash imported that the ledger does not name

def unused.line source · line 450 · raw

@+dependency:0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Dep -> String

how a ledger entry nobody imports reads

def unused.put source · line 455 · raw

@hit:Bool -> @+dependency:0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Dep -> @rest:List<&2, String> -> List<&2, String>

a dependency reported when nothing imports it

def unused source · line 463 · raw

@ds:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Dep> -> @+hs:List<&2, String> -> List<&2, String>

every dependency of the ledger that no import line uses

def drift source · line 472 · raw

@+hs:List<&2, String> -> @+ds:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Dep> -> List<&2, String>

both directions of the disagreement: a hash the source imports that the ledger never names, and a ledger entry no import line uses

def flag source · line 476 · raw

@ls:List<&2, String> -> List<&2, Note>

every line of a report, each a problem

def drift.notes source · line 484 · raw

@+hs:List<&2, String> -> @lines:List<&2, String> -> List<&2, Note>

the report, or the one line that says there is nothing to report

def listing.notes source · line 493 · raw

@listing:0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Listing -> @+ds:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Dep> -> List<&2, Note>

the report over what git listed, or why it could not list

def sources.notes source · line 502 · raw

@got:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Heard -> @+ds:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Dep> -> List<&2, Note>

the report, once the sources were asked for

def imports.notes source · line 515 · raw

@ledger:0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Read -> @got:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Heard -> List<&2, Note>

the report over a ledger. One that did not read is its own problem, and there is nothing to compare the source with.

def tree.how source · line 531 · raw

@src:0x74799d3f846634a3d7461d4336d7c9d4/src/lock/lock.Src -> 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.How

how a tree read from BEND_LIB arrived, as the lock judges it. A git package's tree under BEND_LIB is one ez lock reads from there too. A hub package's is one ez lock would have the hub serve: its name is the digest of its manifest and each file is checked against its sum, so bytes that pass are the bytes the hub serves under that name, and bytes that do not are refused either way.

def ask.src source · line 539 · raw

@ask:0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Ask -> 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/lock.Src

the source a lock question names

def tree.put source · line 550 · raw

@+ask:0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Ask -> @answer:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Answer -> @rest:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Reply> -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Reply>

a tree BEND_LIB held, as the answer the lock reads, ahead of the rest. One it did not hold answers nothing, so the lock goes on asking for it.

def tree.reply source · line 558 · raw

@ask:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask -> @answer:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Answer -> @rest:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Reply> -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Reply>

a reply kept when it answers a lock question

def trees source · line 566 · raw

@rs:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Reply> -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Reply>

every tree BEND_LIB held, as the lock's answers

def lock.text source · line 574 · raw

@lock:Maybe<&2, String> -> String

the lock's text, "" when there is none, as the lock's own question reads it

def name.put source · line 584 · raw

@+nv:String -> @got:Maybe<&2, String> -> @rest:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Reply> -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Reply>

a name's file BEND_LIB held, as the answer the lock reads for the name, ahead of the rest. One it did not hold answers nothing, so the lock goes on asking for it.

def name.reply source · line 592 · raw

@ask:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask -> @answer:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Answer -> @rest:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Reply> -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Reply>

a reply kept when it answers a name's question

def held source · line 604 · raw

@rs:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Reply> -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Reply>

every name's file BEND_LIB held, as the lock's answers

def relock.world source · line 617 · raw

@ledger:Maybe<&2, String> -> @lock:Maybe<&2, String> -> @listing:0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Listing -> @+rs:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Reply> -> 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.World

the World doctor puts to the lock planner: a plain lock over the ledger's text as it is, the sources as git listed them, the lock as it is, which answers the lock's question about the names it records, every tree BEND_LIB held, and every name's file it held, never the network. The directory a lock runs in only anchors the questions it asks, which doctor answers by hash from BEND_LIB, so it is left empty.

def relock source · line 628 · raw

@+world:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.World -> @fs:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Source> -> 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.World

that World, over the sources as a list of files

def fresh.line source · line 632 · raw

String

the line for a lock ez lock would write as it is

def stale.line source · line 636 · raw

String

the line for one it would write otherwise

def fresh.said source · line 640 · raw

@same:Bool -> Note

the verdict, once the two texts were compared

def fresh.doc source · line 649 · raw

@doc:0x74799d3f846634a3d7461d4336d7c9d4/src/lock/plan.Doc -> @+text:String -> Note

the lock against what the lock planner decided: the text it would write, or why it would write none

def ask.hashes source · line 657 · raw

@as:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Ask> -> List<&2, String>

the hashes of lock questions

def fresh.named source · line 667 · raw

@as:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Ask> -> @+lw:0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.World -> @+text:String -> Note

the lock, once every name the lock planner asks about is known: when none is left, what it decided; when some are, their files are not under BEND_LIB, and doctor does not ask the hub for them

def fresh.away source · line 679 · raw

@as:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Ask> -> @+lw:0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.World -> @+text:String -> Note

the lock, once every question the lock planner asks is known: when none is left, its names, then what it decided; when some are, they are about packages BEND_LIB does not hold, and doctor does not ask the network for them

def fresh.listing source · line 689 · raw

@+world:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.World -> @listing:0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Listing -> @+text:String -> List<&2, Note>

the check over the sources git listed. Sources git could not list are the drift report's to say.

def fresh.heard source · line 699 · raw

@got:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Heard -> @+world:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.World -> @+text:String -> List<&2, Note>

the check, once the sources were heard. They are asked for only when the ledger reads, so a ledger that does not is not checked against.

def fresh.notes source · line 712 · raw

@lock:Maybe<&2, String> -> @+world:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.World -> List<&2, Note>

the check over a lock that is there. With no lock there is nothing to compare, and the lock's own line says whether that is a problem.

def checked source · line 720 · raw

@+world:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.World -> List<&2, Note>

what doctor says of the lock against the lock ez lock would write

def trees.asked source · line 724 · raw

@as:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Ask> -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask>

each lock question, put to BEND_LIB

def names.asked source · line 733 · raw

@as:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Ask> -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask>

each of the lock's name questions, put to BEND_LIB as the name's file. The lock's own question never reaches here, since the World answers it.

def trees.world source · line 741 · raw

@+lw:0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.World -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask>

the lock questions over the sources git listed, packages and then names

def trees.listing source · line 744 · raw

@ledger:Maybe<&2, String> -> @lock:Maybe<&2, String> -> @listing:0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Listing -> @rs:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Reply> -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask>

def trees.heard source · line 757 · raw

@got:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Heard -> @ledger:Maybe<&2, String> -> @lock:Maybe<&2, String> -> @rs:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Reply> -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask>

the lock questions, once the sources were heard

def trees.of source · line 776 · raw

@ledger:Maybe<&2, String> -> @lock:Maybe<&2, String> -> @held:Maybe<&2, String> -> @+rs:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Reply> -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask>

every package and name the lock planner asks about, while there is a lock to check. These depend on the sources and on the trees already read, so they come in rounds, as the lock's own do.

def ledger.seen source · line 795 · raw

@ledger:0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Read -> 0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Read

the ledger as doctor sees it: its package, its entry and its dependencies. Its [tools.*] pins are not dependencies, so they are dropped before anything but the lock check is decided (EZ-LED-5). The lock check reads the ledger's text as ez lock does, since the lock records the pins.

def head.notes source · line 805 · raw

@+ledger:0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Read -> @+cc:String -> @+lib:String -> @+lock:Maybe<&2, String> -> @+rs:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Reply> -> @cs:List<&2, Note> -> List<&2, Note>

the toolchain, the ledger, the lock and the library, each on its line, and the lock check's line after them

def notes.of source · line 822 · raw

@+ledger:0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Read -> @got:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Heard -> @+cc:String -> @+lib:String -> @lock:Maybe<&2, String> -> @+rs:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Reply> -> @cs:List<&2, Note> -> List<&2, Note>

every line doctor says, in order: the toolchain, the ledger, the lock, the library, the lock check, and last the drift report over the sources as they were heard

def note.wrong source · line 834 · raw

@finding:Note -> Bool

whether a note is a problem

def wrong source · line 840 · raw

@ns:List<&2, Note> -> Bool

whether anything found was a problem. The rest arrives as a thunk and only the arm that wants it applies it.

def says source · line 848 · raw

@ns:List<&2, Note> -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/plan.Effect>

each line said

def outcome.of source · line 857 · raw

@bad:Bool -> 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/plan.Outcome

a problem must fail the command, or a script around it learns nothing. The lines already said what the problem is.

def plan.notes source · line 866 · raw

@+ns:List<&2, Note> -> 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/plan.Plan

the plan for these notes: every line said, and the command failed when one of them is a problem

def plan.of source · line 871 · raw

@+ledger:0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Read -> @+cc:String -> @+lib:String -> @lock:Maybe<&2, String> -> @+rs:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Reply> -> @cs:List<&2, Note> -> 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/plan.Plan

the plan over what a World read, field by field, with the lock check's lines

def plan source · line 882 · raw

@+world:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.World -> 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/plan.Plan

ez doctor over a World

def refuses.plan source · line 887 · raw

@pl:0x74799d3f846634a3d7461d4336d7c9d4/src/lock/plan.Plan -> Bool

whether a plan ends in a refusal

def refuses source · line 896 · raw

@+world:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.World -> Bool

whether ez doctor fails on a World

def open.put source · line 903 · raw

@got:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Heard -> @ask:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask -> @rest:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask> -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask>

a question kept when it has no answer yet

def open source · line 911 · raw

@asks:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask> -> @+rs:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Reply> -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask>

the questions of a list that have no answer yet

def probe.asks source · line 919 · raw

@ns:List<&2, String> -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask>

a version question for every program

def lib.asks source · line 927 · raw

@+dir:String -> @hs:List<&2, String> -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask>

the library is looked in only when the lock names a package to look for

def sources.asks source · line 935 · raw

@ledger:0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Read -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask>

the sources are read only when there is a ledger to compare them with

def names.asks source · line 943 · raw

@ns:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/lock.Name> -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask>

a question for every name's file the lock records

def asks.of source · line 951 · raw

@ledger:0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Read -> @+cc:String -> @+lib:String -> @+lock:Maybe<&2, String> -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask>

every question doctor asks on what a World read, besides the lock check's

def step.asks source · line 962 · raw

@asks:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask> -> @+ledger:0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Read -> @+cc:String -> @+lib:String -> @lock:Maybe<&2, String> -> @+rs:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Reply> -> @cs:List<&2, Note> -> Step

the step, once the open questions are known

def step.of source · line 981 · raw

@+ledger:0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Read -> @+cc:String -> @+lib:String -> @+lock:Maybe<&2, String> -> @+rs:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Reply> -> @ts:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask> -> @cs:List<&2, Note> -> Step

the step over what a World read, field by field, with the lock check's questions and lines. The first round asks everything but the lock check's trees, which follow the sources and each other, as the lock's own questions do.

def step source · line 994 · raw

@+world:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.World -> Step

what the interpreter does next on a World

def wants source · line 1000 · raw

@+world:0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.World -> List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/doctor/world.Ask>

the questions a World still leaves open

def said.one source · line 1009 · raw

@effect:0x74799d3f846634a3d7461d4336d7c9d4/src/lock/plan.Effect -> @+line:String -> Bool

whether an effect says this line

def said.in source · line 1023 · raw

@es:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/plan.Effect> -> @+line:String -> Bool

whether a list of effects says this line

def said source · line 1031 · raw

@pl:0x74799d3f846634a3d7461d4336d7c9d4/src/lock/plan.Plan -> @+line:String -> Bool

whether a plan says this line

def drift.of source · line 1037 · raw

@fs:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/lock/world.Source> -> @+ds:List<&2, 0x74799d3f846634a3d7461d4336d7c9d4/src/ledger/manifest.Dep> -> List<&2, String>

the drift report doctor makes of a World's sources against a ledger's dependencies