NAME
App::FuguBench::Doctor - the doctor verb of fugubench
SYNOPSIS
$ fugubench doctor
ok version: fugubench 0.0.0 (Fugu 0.5.0)
ok git: /usr/bin/git
ok make: /usr/bin/make
ok downloader: /usr/bin/curl
ok hooks: none
ok library: absent
$ fugubench [-C <root>] doctor --fix
DESCRIPTION
App::FuguBench::Doctor reports the state of one checkout. Each check writes one line to standard output, ok <check>: <detail> or problem <check>: <detail>. The verb returns 1 when it wrote one problem line, so a make target can gate on the report.
The verb reads the state of the checkout, and it changes nothing. --fix repairs one shape of that state, and the section below states the shape.
The report holds the facts of the other verbs. The version line comes from the version verb. The settings path, the keys of that file, the entries, and the worktree settings come from the hook verb, so this module holds no assumption of Claude Code. The shape of a session page, and the body of one, come from the wiki verb.
The library directory is the one fact that the verb reads for itself. It reads the two keys that the wiki verb reads, and a key that names no library gives the line ok library: absent. The wiki verb reports the reason on its own call.
THE CHECKS
version holds the line of the version verb: the version of the program, and the version of the Fugu library beside it. The check never fails, because the program answered.
git and make hold the path of the tool on PATH. An absent tool gives absent from PATH.
downloader holds the path of the first of curl, wget, and ftp on PATH, because Fugu::Curl searches them in that order. Without one of the three the detail is no curl, wget, or ftp on PATH.
hooks reads the settings file that the hook verb names. A checkout that holds no event of the four gives ok hooks: none, and an absent file gives that same line. Most checkouts install no hook, and that is no problem.
A checkout that holds one event of the four gives one hook <event> line for each of the four. The detail is installed for an entry that equals the entry of hook install, absent for an event that the file lost, and differs from hook install for every other entry.
A checkout that holds one event gives one worktree.baseRef line too. A worktree key that holds no object gives the problem line of that key in its place. hook install writes the base reference beside the entries. Without the hooks, the built-in creation of a worktree branches from origin/main and skips the bootstrap. The detail is installed, absent, or differs from hook install, as the detail of an event is.
Each file that stops hook install is a problem: the file that does not read, the file that holds no JSON object, a hooks key that holds no object, and a worktree key that holds no object. The worktree line names the last one, and the hooks line names the other three.
THE LIBRARY
The library is wiki.dir under the home of wiki.origin, as the wiki verb reads the two keys. The library detail is absent when the checkout names no library, and when the directory holds no clone. The detail of a clean clone is the path of the clone.
A clone that holds an uncommitted change gives changes with the files. Every capture of the wiki verb commits, so a change that stays is the debris of a capture that stopped.
A clone in a stopped rebase gives stopped rebase, the pending commit adds <page>. The verb finds that rebase through the state directory of git, rebase-merge or rebase-apply. REBASE_HEAD tells no stopped rebase: git writes that reference when a rebase stops, and a rebase that runs to its end leaves the reference behind.
THE FIX
--fix runs git rebase --skip in the clone, for a pending commit of one shape. That commit adds one file, the file is a session page, and the page holds no observation. Two sessions of one day take one page name, and each one pushes a header alone. The commit that loses the race carries no work, so the skip destroys nothing.
The Closed: line of wiki close is no observation. close appends that line at the end of the page, under the heading ## Observations, and the body test drops it. A commit that adds a page with that line, and no other text under the heading, takes the fix.
The detail of a fix that ended the rebase is skipped the pending commit <page>. Every other pending commit is a refusal, stopped rebase, fix refused: with the reason. A commit that no git call reads gives the reason of git. The operator then resolves the rebase by hand.
The fix takes one pending commit. A rebase of several commits stops again at the next one, and the detail is then skipped the pending commit <page>, the rebase stopped again. That line is a problem line, because the clone still needs the operator. The next run of the verb reports the new pending commit.
command
command($verb) returns the entry of the Fugu::CLI table. The module holds one verb, so it ignores the name.
RETURN VALUES
command returns a hash reference.
The verb returns 0 when every line of the report starts with ok, and 1 when one line starts with problem. An argument after the verb gives the usage error and returns 2. The verb returns 3 when no .toolingrc sits above the start of the walk.
SEE ALSO
App::FuguBench, App::FuguBench::Checkout, App::FuguBench::Hook, App::FuguBench::Version, App::FuguBench::Wiki, Fugu::CLI, Fugu::Curl, Fugu::File, Fugu::Process
AUTHORS
Dick Olsson <hi@senzilla.io>