sheaf · sha:e9edfda · fragmentation scan · sheaf · 2026-06-08 19:24 UTC

13 Commands

Reference docs
92%
12 with doc evidence
show the 12
Tests
92%
12 with test evidence
show the 12
Usage
92%
12 in docs / RFCs
show the 12

63 Flags

Reference docs
100%
63 with doc evidence
show the 63
Tests
65%
41 with test evidence
show the 41
Usage
95%
60 in docs / RFCs
show the 60
Concept docs clearly reference 76 of 76 entities; the rest aren’t discussed in narrative docs (expected).

23 Gaps · Worklist

Docs cover 75 commands; tests cover 53; usage covers 72. Tests is the bottleneck — every Completed command needs all three. Closing the largest group would move 96% of the debt — the biggest single shift available.

53
Completed
DOCS TESTS EXAMPLES
all three surfaces aligned
sheaf coveragesheaf coverage --configsheaf coverage --elementsheaf coverage --formatsheaf coverage --reposheaf doctor
19
Shown
DOCS TESTS EXAMPLES
explained and demoed, but not verified
sheaf render --api-levelsheaf render --concept-docs-hrefsheaf render --from-snapshotsheaf render --header-stylesheaf render --quietsheaf render --source-url-template
3
Asserted
DOCS TESTS EXAMPLES
claim in docs, nothing verifies it
sheaf render --mock-overlapsheaf render --outputsheaf verify --expected-elements
1
Unclaimed
DOCS TESTS EXAMPLES
only the contract, nothing else
sheaf
1
REPLACE THE STUB Replace the inherited boilerplate with prose that explains the actual behavior.
22
CITE IT IN A TEST Name this element in an existing test (a t.Run label, a table-driven case name, a comment) or add a test that does.
sheaf render --api-level docs/cli/yaml/sheaf_render.yaml:1
sheaf render --concept-docs-href docs/cli/yaml/sheaf_render.yaml:1
sheaf render --from-snapshot docs/cli/yaml/sheaf_render.yaml:1
sheaf render --header-style docs/cli/yaml/sheaf_render.yaml:1
sheaf render --mock-overlap docs/cli/yaml/sheaf_render.yaml:1
sheaf render --output docs/cli/yaml/sheaf_render.yaml:1
sheaf render --quiet docs/cli/yaml/sheaf_render.yaml:1
sheaf render --source-url-template docs/cli/yaml/sheaf_render.yaml:1
sheaf verify --check-urls docs/cli/yaml/sheaf_verify.yaml:1
sheaf verify --config docs/cli/yaml/sheaf_verify.yaml:1
sheaf verify --disk docs/cli/yaml/sheaf_verify.yaml:1
sheaf verify --ecosystem docs/cli/yaml/sheaf_verify.yaml:1
sheaf verify --expected-elements docs/cli/yaml/sheaf_verify.yaml:1
sheaf verify --from-snapshot docs/cli/yaml/sheaf_verify.yaml:1
sheaf verify --json docs/cli/yaml/sheaf_verify.yaml:1
sheaf verify --ledger docs/cli/yaml/sheaf_verify.yaml:1
sheaf verify --library docs/cli/yaml/sheaf_verify.yaml:1
sheaf verify --low-coverage-threshold docs/cli/yaml/sheaf_verify.yaml:1
sheaf verify --max-disk-elements docs/cli/yaml/sheaf_verify.yaml:1
sheaf verify --repo docs/cli/yaml/sheaf_verify.yaml:1
sheaf verify --sample-assertions docs/cli/yaml/sheaf_verify.yaml:1
sheaf verify --strict docs/cli/yaml/sheaf_verify.yaml:1

Depth

Coverage counts the docs that exist; depth weighs what they actually say — from full behavioral prose down to a bare signature stub.

Full
92%
Brief
0%
Stub
0%
None
8%

Lag

How far the non-reference docs have fallen behind the code — measured in days, from git commit timestamps.

Fresh
100%
Recent
0%
Aging
0%
Stale
0%
i
0d median lag·P90 lag of 0 days·125 matched (element → doc) pairs·0 inline doc comments excluded (version-locked). 37% of pairs had unresolved git history and are not counted.

Evidence

1
REPLACE THE STUB Signature-only — documented in name only
sheaf
22
CITE IT IN A TEST Not named in any test
sheaf render --api-level
sheaf render --concept-docs-href
sheaf render --from-snapshot
sheaf render --header-style
sheaf render --mock-overlap
sheaf render --output
sheaf render --quiet
sheaf render --source-url-template
sheaf verify --check-urls
sheaf verify --config
sheaf verify --disk
sheaf verify --ecosystem
sheaf verify --expected-elements
sheaf verify --from-snapshot
sheaf verify --json
sheaf verify --ledger
sheaf verify --library
sheaf verify --low-coverage-threshold
sheaf verify --max-disk-elements
sheaf verify --repo
sheaf verify --sample-assertions
sheaf verify --strict
53
Bridged
sheaf coverage
sheaf coverage --config
sheaf coverage --element
sheaf coverage --format
sheaf coverage --repo
sheaf doctor
sheaf doctor --config
sheaf doctor --repo
sheaf gaps
sheaf gaps --config
sheaf gaps --format
sheaf gaps --kind
sheaf gaps --library
sheaf gaps --repo
sheaf gaps --severity
sheaf init
sheaf init --repo
sheaf init --template
sheaf render
sheaf render --commit
sheaf render --ecosystem
sheaf render --library
sheaf render --repo-root
sheaf report
sheaf report --config
sheaf report --format
sheaf report --output
sheaf report --repo
sheaf review
sheaf review --base
sheaf review --config
sheaf review --file-out
sheaf review --post
sheaf review --pr
sheaf review --repo
sheaf review --review
sheaf scan
sheaf scan --config
sheaf scan --quiet
sheaf scan --repo
sheaf serve
sheaf serve --bind
sheaf serve --config
sheaf serve --port
sheaf serve --repo
sheaf snapshot
sheaf snapshot --config
sheaf snapshot --library
sheaf snapshot --library-label
sheaf snapshot --out
sheaf snapshot --repo
sheaf verify
sheaf version
CONTRACT
command: sheaf
short: Sheaf — contract-coverage analysis.
long: |
  Sheaf finds the gaps between your contracts (APIs, CLIs), tests, docs,
DOCS

N/A

TESTS

N/A

EXAMPLES

N/A

WORKFLOWS

N/A

CONTRACT
command: sheaf coverage
short: Print the CoverageProfile for one element.
long: |
  Focused inverse of `sheaf report`. Runs the full pipeline, then
  emits the CoverageProfile for the single element named by --element
  as either pretty-printed text or JSON.
usage: sheaf coverage --element id [--config path] [--repo path] [--format fmt]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
    value_type: string
DOCS
sheaf_coverage.md:1Markdown · 178 words
docs/cli/sheaf.md:40Markdown · 25 words

`sheaf scan`, `sheaf gaps`, `sheaf coverage`, `sheaf report`, `sheaf snapshot`, `sheaf serve`, and `sheaf review` all run the full pipeline (config load → adapter dispatch → indexer → analyzers) before producing their output. `sheaf render` and `sheaf review-html` are pipeline-free — they render from a Snapshot JSON / `delta.json` that an earlier pipeline run already produced — as are `sheaf doctor`, `sheaf version`, and `sheaf init`.

+ 16 more paragraphs · read full section

- [`sheaf coverage`](sheaf_coverage.md) — the production version of single-element drill-in. - [`sheaf report`](sheaf_report.md) — bulk dump of every profile.

+ 1 more refs · open all in source
TESTS
internal/cli/coverage_test.go:10internal/cli/coverage_test::TestRunCoverage_UnknownElement · Go · 8 lines
func TestRunCoverage_UnknownElement(t *testing.T) {
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runCoverage(&out, &errOut, "", dir, "definitely-not-a-real-element", "text")
	if rc != 2 {
		t.Errorf("expected rc=2 for unknown element; got %d; stderr=%s", rc, errOut.String())
	}
}
internal/cli/coverage_test.go:19internal/cli/coverage_test::TestRunCoverage_FormatRepoFlags · Go · 11 lines
func TestRunCoverage_FormatRepoFlags(t *testing.T) {
	// --format json with a bogus --element still resolves the
	// pipeline and prints the no-profile error. Path coverage check
	// for the --repo + --format flag attribution.
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runCoverage(&out, &errOut, "", dir, "nope-not-real", "json")
	if rc != 2 {
		t.Errorf("expected rc=2; got %d", rc)
	}
}
internal/cli/coverage_test.go:31internal/cli/coverage_test::TestRunCoverage_MissingConfig · Go · 8 lines
func TestRunCoverage_MissingConfig(t *testing.T) {
	dir := t.TempDir()
	var out, errOut bytes.Buffer
	rc := runCoverage(&out, &errOut, "", dir, "anything", "text")
	if rc == 0 {
		t.Errorf("expected non-zero exit on missing config; out=%s err=%s", out.String(), errOut.String())
	}
}
+ 2 more tests · open all in source
WORKFLOWS

N/A

CONTRACT
command: sheaf coverage
short: Print the CoverageProfile for one element.
long: |
  Focused inverse of `sheaf report`. Runs the full pipeline, then
  emits the CoverageProfile for the single element named by --element
  as either pretty-printed text or JSON.
usage: sheaf coverage --element id [--config path] [--repo path] [--format fmt]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
    value_type: string
DOCS
docs/cli/sheaf.md:50Markdown · 27 words

**Coverage.** `sheaf coverage --element` is required — it names the contract element whose profile you want. `sheaf coverage --format` switches between the human-readable text dump and `json`, while `sheaf coverage --config` and `sheaf coverage --repo` locate the project the same way scan does.

+ 12 more paragraphs · read full section
sheaf_coverage.md:25Markdown · 5 words
TESTS
internal/cli/coverage_test.go:48internal/cli/coverage_test::TestCoverage_ArgvFlagParsing · Go · 17 lines
func TestCoverage_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so --config / --repo / --element /
	// --format are parsed from the command line. The runCoverage tests
	// above pass those values positionally, which never exercises the
	// flag wiring (nor attributes the flags in the self-scan); this
	// closes both gaps in one real end-to-end parse.
	dir := setupFixture(t)
	rc := Coverage([]string{
		"--config", dir + "/sheaf.textproto",
		"--repo", dir,
		"--element", "nope-not-real",
		"--format", "json",
	})
	if rc != 2 {
		t.Errorf("expected rc=2 for unknown --element via argv; got %d", rc)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf coverage
short: Print the CoverageProfile for one element.
long: |
  Focused inverse of `sheaf report`. Runs the full pipeline, then
  emits the CoverageProfile for the single element named by --element
  as either pretty-printed text or JSON.
usage: sheaf coverage --element id [--config path] [--repo path] [--format fmt]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
    value_type: string
DOCS
docs/cli/sheaf.md:50Markdown · 29 words

**Coverage.** `sheaf coverage --element` is required — it names the contract element whose profile you want. `sheaf coverage --format` switches between the human-readable text dump and `json`, while `sheaf coverage --config` and `sheaf coverage --repo` locate the project the same way scan does.

+ 12 more paragraphs · read full section
sheaf_coverage.md:24Markdown · 3 words
TESTS
internal/cli/coverage_test.go:40internal/cli/coverage_test::TestCoverage_RequiresElement · Go · 7 lines
func TestCoverage_RequiresElement(t *testing.T) {
	// Empty --element exits 2 from the public argv entry with the
	// required-flag message, before runCoverage is ever reached.
	if rc := Coverage([]string{"--repo", t.TempDir()}); rc != 2 {
		t.Errorf("expected rc=2 when --element is omitted; got %d", rc)
	}
}
internal/cli/coverage_test.go:48internal/cli/coverage_test::TestCoverage_ArgvFlagParsing · Go · 17 lines
func TestCoverage_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so --config / --repo / --element /
	// --format are parsed from the command line. The runCoverage tests
	// above pass those values positionally, which never exercises the
	// flag wiring (nor attributes the flags in the self-scan); this
	// closes both gaps in one real end-to-end parse.
	dir := setupFixture(t)
	rc := Coverage([]string{
		"--config", dir + "/sheaf.textproto",
		"--repo", dir,
		"--element", "nope-not-real",
		"--format", "json",
	})
	if rc != 2 {
		t.Errorf("expected rc=2 for unknown --element via argv; got %d", rc)
	}
}
WORKFLOWS

N/A

CONTRACT
command: sheaf coverage
short: Print the CoverageProfile for one element.
long: |
  Focused inverse of `sheaf report`. Runs the full pipeline, then
  emits the CoverageProfile for the single element named by --element
  as either pretty-printed text or JSON.
usage: sheaf coverage --element id [--config path] [--repo path] [--format fmt]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
    value_type: string
DOCS
docs/cli/sheaf.md:50Markdown · 27 words

**Coverage.** `sheaf coverage --element` is required — it names the contract element whose profile you want. `sheaf coverage --format` switches between the human-readable text dump and `json`, while `sheaf coverage --config` and `sheaf coverage --repo` locate the project the same way scan does.

+ 12 more paragraphs · read full section
sheaf_coverage.md:27Markdown · 5 words
TESTS
internal/cli/coverage_test.go:48internal/cli/coverage_test::TestCoverage_ArgvFlagParsing · Go · 17 lines
func TestCoverage_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so --config / --repo / --element /
	// --format are parsed from the command line. The runCoverage tests
	// above pass those values positionally, which never exercises the
	// flag wiring (nor attributes the flags in the self-scan); this
	// closes both gaps in one real end-to-end parse.
	dir := setupFixture(t)
	rc := Coverage([]string{
		"--config", dir + "/sheaf.textproto",
		"--repo", dir,
		"--element", "nope-not-real",
		"--format", "json",
	})
	if rc != 2 {
		t.Errorf("expected rc=2 for unknown --element via argv; got %d", rc)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf coverage
short: Print the CoverageProfile for one element.
long: |
  Focused inverse of `sheaf report`. Runs the full pipeline, then
  emits the CoverageProfile for the single element named by --element
  as either pretty-printed text or JSON.
usage: sheaf coverage --element id [--config path] [--repo path] [--format fmt]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
    value_type: string
DOCS
docs/cli/sheaf.md:50Markdown · 28 words

**Coverage.** `sheaf coverage --element` is required — it names the contract element whose profile you want. `sheaf coverage --format` switches between the human-readable text dump and `json`, while `sheaf coverage --config` and `sheaf coverage --repo` locate the project the same way scan does.

+ 12 more paragraphs · read full section
sheaf_coverage.md:26Markdown · 3 words
TESTS
internal/cli/coverage_test.go:40internal/cli/coverage_test::TestCoverage_RequiresElement · Go · 7 lines
func TestCoverage_RequiresElement(t *testing.T) {
	// Empty --element exits 2 from the public argv entry with the
	// required-flag message, before runCoverage is ever reached.
	if rc := Coverage([]string{"--repo", t.TempDir()}); rc != 2 {
		t.Errorf("expected rc=2 when --element is omitted; got %d", rc)
	}
}
internal/cli/coverage_test.go:48internal/cli/coverage_test::TestCoverage_ArgvFlagParsing · Go · 17 lines
func TestCoverage_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so --config / --repo / --element /
	// --format are parsed from the command line. The runCoverage tests
	// above pass those values positionally, which never exercises the
	// flag wiring (nor attributes the flags in the self-scan); this
	// closes both gaps in one real end-to-end parse.
	dir := setupFixture(t)
	rc := Coverage([]string{
		"--config", dir + "/sheaf.textproto",
		"--repo", dir,
		"--element", "nope-not-real",
		"--format", "json",
	})
	if rc != 2 {
		t.Errorf("expected rc=2 for unknown --element via argv; got %d", rc)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf doctor
short: Diagnose configuration and adapter health.
long: |
  Validates sheaf.textproto and categorization-rules.textproto, walks
  every configured adapter, and probes the LLM embedder. Use before the
  first scan on a new project, or whenever a scan starts producing
  surprising output.
usage: sheaf doctor [--config path] [--repo path]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
DOCS
sheaf_doctor.md:1Markdown · 204 words
docs/cli/sheaf.md:40Markdown · 28 words

`sheaf scan`, `sheaf gaps`, `sheaf coverage`, `sheaf report`, `sheaf snapshot`, `sheaf serve`, and `sheaf review` all run the full pipeline (config load → adapter dispatch → indexer → analyzers) before producing their output. `sheaf render` and `sheaf review-html` are pipeline-free — they render from a Snapshot JSON / `delta.json` that an earlier pipeline run already produced — as are `sheaf doctor`, `sheaf version`, and `sheaf init`.

+ 16 more paragraphs · read full section
docs/config.md:94Markdown · 28 words

Parse-time and resolve-time errors abort startup with a path-prefixed message (`contract_anchor[1].argh.crate_roots: missing required field`). Probe-time warnings appear in `sheaf doctor` output and at the top of `sheaf scan` runs but do not abort.

+ 190 more paragraphs · read full section
+ 7 more refs · open all in source
TESTS
internal/cli/doctor_test.go:14internal/cli/doctor_test::TestRunDoctor_FixtureProject · Go · 14 lines
func TestRunDoctor_FixtureProject(t *testing.T) {
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runDoctor(&out, &errOut, "", dir)
	if rc != 0 {
		t.Fatalf("runDoctor returned %d; stderr=%s", rc, errOut.String())
	}
	got := out.String()
	for _, want := range []string{"[OK]", "gtest", "markdown", "Project: demo"} {
		if !strings.Contains(got, want) {
			t.Errorf("output missing %q\n%s", want, got)
		}
	}
}
internal/cli/doctor_test.go:29internal/cli/doctor_test::TestRunDoctor_RulesMissingIsTolerated · Go · 14 lines
func TestRunDoctor_RulesMissingIsTolerated(t *testing.T) {
	dir := t.TempDir()
	if err := os.WriteFile(filepath.Join(dir, "sheaf.textproto"), []byte(fixtureConfig), 0o644); err != nil {
		t.Fatalf("write: %v", err)
	}
	var out, errOut bytes.Buffer
	rc := runDoctor(&out, &errOut, "", dir)
	if rc != 0 {
		t.Fatalf("runDoctor returned %d; stderr=%s", rc, errOut.String())
	}
	if !strings.Contains(out.String(), "[MISSING]") {
		t.Errorf("expected [MISSING] marker; got %s", out.String())
	}
}
internal/cli/doctor_test.go:44internal/cli/doctor_test::TestRunDoctor_RepoFlag · Go · 11 lines
func TestRunDoctor_RepoFlag(t *testing.T) {
	// Doctor's --repo flag drives the config + rules path resolution.
	// Confirm a non-default --repo still finds the fixture's
	// sheaf.textproto.
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runDoctor(&out, &errOut, "", dir)
	if rc != 0 {
		t.Fatalf("runDoctor(--repo) returned %d; stderr=%s", rc, errOut.String())
	}
}
+ 2 more tests · open all in source
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf doctor
short: Diagnose configuration and adapter health.
long: |
  Validates sheaf.textproto and categorization-rules.textproto, walks
  every configured adapter, and probes the LLM embedder. Use before the
  first scan on a new project, or whenever a scan starts producing
  surprising output.
usage: sheaf doctor [--config path] [--repo path]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
DOCS
docs/cli/sheaf.md:48Markdown · 28 words

**Doctor.** `sheaf doctor` validates the config and walks every adapter. `sheaf doctor --config` checks a config outside the repo root, and `sheaf doctor --repo` resolves the source map relative to a different tree.

+ 13 more paragraphs · read full section
sheaf_doctor.md:26Markdown · 5 words
TESTS
internal/cli/doctor_test.go:65internal/cli/doctor_test::TestDoctor_ArgvFlagParsing · Go · 9 lines
func TestDoctor_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so --config and --repo are parsed
	// from the command line (the runDoctor tests pass them positionally,
	// which neither exercises flag wiring nor attributes --config).
	dir := setupFixture(t)
	if rc := Doctor([]string{"--config", dir + "/sheaf.textproto", "--repo", dir}); rc != 0 {
		t.Errorf("Doctor(--config,--repo) returned %d; want 0", rc)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf doctor
short: Diagnose configuration and adapter health.
long: |
  Validates sheaf.textproto and categorization-rules.textproto, walks
  every configured adapter, and probes the LLM embedder. Use before the
  first scan on a new project, or whenever a scan starts producing
  surprising output.
usage: sheaf doctor [--config path] [--repo path]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
DOCS
docs/cli/sheaf.md:48Markdown · 28 words

**Doctor.** `sheaf doctor` validates the config and walks every adapter. `sheaf doctor --config` checks a config outside the repo root, and `sheaf doctor --repo` resolves the source map relative to a different tree.

+ 13 more paragraphs · read full section
sheaf_doctor.md:27Markdown · 3 words
TESTS
internal/cli/doctor_test.go:44internal/cli/doctor_test::TestRunDoctor_RepoFlag · Go · 11 lines
func TestRunDoctor_RepoFlag(t *testing.T) {
	// Doctor's --repo flag drives the config + rules path resolution.
	// Confirm a non-default --repo still finds the fixture's
	// sheaf.textproto.
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runDoctor(&out, &errOut, "", dir)
	if rc != 0 {
		t.Fatalf("runDoctor(--repo) returned %d; stderr=%s", rc, errOut.String())
	}
}
internal/cli/doctor_test.go:65internal/cli/doctor_test::TestDoctor_ArgvFlagParsing · Go · 9 lines
func TestDoctor_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so --config and --repo are parsed
	// from the command line (the runDoctor tests pass them positionally,
	// which neither exercises flag wiring nor attributes --config).
	dir := setupFixture(t)
	if rc := Doctor([]string{"--config", dir + "/sheaf.textproto", "--repo", dir}); rc != 0 {
		t.Errorf("Doctor(--config,--repo) returned %d; want 0", rc)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf gaps
short: List findings filterable by kind, library, and severity.
long: |
  Runs the same pipeline as `sheaf scan` and prints the resulting
  Finding list, filtered client-side. Output as text, json, or csv.
usage: sheaf gaps [--config path] [--repo path] [--kind k] [--library prefix] [--severity sev] [--format fmt]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
    value_type: string
    default_value: ""
DOCS
sheaf_gaps.md:1Markdown · 167 words
docs/cli/sheaf.md:52Markdown · 25 words

**Gaps.** `sheaf gaps` lists findings. Narrow them with `sheaf gaps --severity` (minimum `INFO`/`WARNING`/`ERROR`), `sheaf gaps --kind` (a specific finding kind), and `sheaf gaps --library` (one library or element-ID prefix). `sheaf gaps --format` emits `text`, `json`, or `csv`, and `sheaf gaps --config` selects a non-default config.

+ 11 more paragraphs · read full section
docs/cli/sheaf.md:40Markdown · 21 words

`sheaf scan`, `sheaf gaps`, `sheaf coverage`, `sheaf report`, `sheaf snapshot`, `sheaf serve`, and `sheaf review` all run the full pipeline (config load → adapter dispatch → indexer → analyzers) before producing their output. `sheaf render` and `sheaf review-html` are pipeline-free — they render from a Snapshot JSON / `delta.json` that an earlier pipeline run already produced — as are `sheaf doctor`, `sheaf version`, and `sheaf init`.

+ 16 more paragraphs · read full section
+ 1 more refs · open all in source
TESTS
internal/cli/gaps_test.go:11internal/cli/gaps_test::TestRunGaps_TextFormat · Go · 14 lines
func TestRunGaps_TextFormat(t *testing.T) {
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runGaps(&out, &errOut, "", dir, "", "", "INFO", "text")
	if rc != 0 {
		t.Fatalf("runGaps returned %d; stderr=%s", rc, errOut.String())
	}
	// The fixture project has no contract surface configured, so the
	// finding list is empty. The text formatter emits the "No findings."
	// sentinel in that case — confirm the success path stays runnable.
	if got := out.String(); !strings.Contains(got, "No findings.") && !strings.Contains(got, "findings:") {
		t.Errorf("expected gaps output; got %q", got)
	}
}
internal/cli/gaps_test.go:26internal/cli/gaps_test::TestRunGaps_CSVFormat · Go · 11 lines
func TestRunGaps_CSVFormat(t *testing.T) {
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runGaps(&out, &errOut, "", dir, "", "", "INFO", "csv")
	if rc != 0 {
		t.Fatalf("runGaps returned %d; stderr=%s", rc, errOut.String())
	}
	if !strings.Contains(out.String(), "id,kind,subject,severity,analyzer,message") {
		t.Errorf("expected CSV header; got %q", out.String())
	}
}
internal/cli/gaps_test.go:38internal/cli/gaps_test::TestRunGaps_LibraryRepoKindFlags · Go · 8 lines
func TestRunGaps_LibraryRepoKindFlags(t *testing.T) {
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runGaps(&out, &errOut, "", dir, "THIN_REFERENCE", "demo", "WARNING", "text")
	if rc != 0 {
		t.Fatalf("runGaps with --library/--repo/--kind returned %d; stderr=%s", rc, errOut.String())
	}
}
+ 3 more tests · open all in source
EXAMPLES
+ 1 more examples · open all in source
WORKFLOWS

N/A

CONTRACT
command: sheaf gaps
short: List findings filterable by kind, library, and severity.
long: |
  Runs the same pipeline as `sheaf scan` and prints the resulting
  Finding list, filtered client-side. Output as text, json, or csv.
usage: sheaf gaps [--config path] [--repo path] [--kind k] [--library prefix] [--severity sev] [--format fmt]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
    value_type: string
    default_value: ""
DOCS
docs/cli/sheaf.md:52Markdown · 25 words

**Gaps.** `sheaf gaps` lists findings. Narrow them with `sheaf gaps --severity` (minimum `INFO`/`WARNING`/`ERROR`), `sheaf gaps --kind` (a specific finding kind), and `sheaf gaps --library` (one library or element-ID prefix). `sheaf gaps --format` emits `text`, `json`, or `csv`, and `sheaf gaps --config` selects a non-default config.

+ 11 more paragraphs · read full section
sheaf_gaps.md:28Markdown · 5 words
TESTS
internal/cli/gaps_test.go:72internal/cli/gaps_test::TestGaps_ArgvFlagParsing · Go · 18 lines
func TestGaps_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so every gaps flag is parsed from the
	// command line. The runGaps tests pass these positionally, which
	// leaves --config / --format / --severity unattributed in the
	// self-scan even though they're exercised here end to end.
	dir := setupFixture(t)
	rc := Gaps([]string{
		"--config", dir + "/sheaf.textproto",
		"--repo", dir,
		"--severity", "WARNING",
		"--format", "csv",
		"--kind", "THIN_REFERENCE",
		"--library", "demo",
	})
	if rc != 0 {
		t.Errorf("Gaps(--config/--repo/--severity/--format/--kind/--library) returned %d; want 0", rc)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf gaps
short: List findings filterable by kind, library, and severity.
long: |
  Runs the same pipeline as `sheaf scan` and prints the resulting
  Finding list, filtered client-side. Output as text, json, or csv.
usage: sheaf gaps [--config path] [--repo path] [--kind k] [--library prefix] [--severity sev] [--format fmt]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
    value_type: string
    default_value: ""
DOCS
docs/cli/sheaf.md:52Markdown · 27 words

**Gaps.** `sheaf gaps` lists findings. Narrow them with `sheaf gaps --severity` (minimum `INFO`/`WARNING`/`ERROR`), `sheaf gaps --kind` (a specific finding kind), and `sheaf gaps --library` (one library or element-ID prefix). `sheaf gaps --format` emits `text`, `json`, or `csv`, and `sheaf gaps --config` selects a non-default config.

+ 11 more paragraphs · read full section
sheaf_gaps.md:33Markdown · 6 words
TESTS
internal/cli/gaps_test.go:72internal/cli/gaps_test::TestGaps_ArgvFlagParsing · Go · 18 lines
func TestGaps_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so every gaps flag is parsed from the
	// command line. The runGaps tests pass these positionally, which
	// leaves --config / --format / --severity unattributed in the
	// self-scan even though they're exercised here end to end.
	dir := setupFixture(t)
	rc := Gaps([]string{
		"--config", dir + "/sheaf.textproto",
		"--repo", dir,
		"--severity", "WARNING",
		"--format", "csv",
		"--kind", "THIN_REFERENCE",
		"--library", "demo",
	})
	if rc != 0 {
		t.Errorf("Gaps(--config/--repo/--severity/--format/--kind/--library) returned %d; want 0", rc)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf gaps
short: List findings filterable by kind, library, and severity.
long: |
  Runs the same pipeline as `sheaf scan` and prints the resulting
  Finding list, filtered client-side. Output as text, json, or csv.
usage: sheaf gaps [--config path] [--repo path] [--kind k] [--library prefix] [--severity sev] [--format fmt]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
    value_type: string
    default_value: ""
DOCS
docs/cli/sheaf.md:52Markdown · 24 words

**Gaps.** `sheaf gaps` lists findings. Narrow them with `sheaf gaps --severity` (minimum `INFO`/`WARNING`/`ERROR`), `sheaf gaps --kind` (a specific finding kind), and `sheaf gaps --library` (one library or element-ID prefix). `sheaf gaps --format` emits `text`, `json`, or `csv`, and `sheaf gaps --config` selects a non-default config.

+ 11 more paragraphs · read full section
sheaf_gaps.md:30Markdown · 3 words
TESTS
internal/cli/gaps_test.go:38internal/cli/gaps_test::TestRunGaps_LibraryRepoKindFlags · Go · 8 lines
func TestRunGaps_LibraryRepoKindFlags(t *testing.T) {
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runGaps(&out, &errOut, "", dir, "THIN_REFERENCE", "demo", "WARNING", "text")
	if rc != 0 {
		t.Fatalf("runGaps with --library/--repo/--kind returned %d; stderr=%s", rc, errOut.String())
	}
}
internal/cli/gaps_test.go:72internal/cli/gaps_test::TestGaps_ArgvFlagParsing · Go · 18 lines
func TestGaps_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so every gaps flag is parsed from the
	// command line. The runGaps tests pass these positionally, which
	// leaves --config / --format / --severity unattributed in the
	// self-scan even though they're exercised here end to end.
	dir := setupFixture(t)
	rc := Gaps([]string{
		"--config", dir + "/sheaf.textproto",
		"--repo", dir,
		"--severity", "WARNING",
		"--format", "csv",
		"--kind", "THIN_REFERENCE",
		"--library", "demo",
	})
	if rc != 0 {
		t.Errorf("Gaps(--config/--repo/--severity/--format/--kind/--library) returned %d; want 0", rc)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf gaps
short: List findings filterable by kind, library, and severity.
long: |
  Runs the same pipeline as `sheaf scan` and prints the resulting
  Finding list, filtered client-side. Output as text, json, or csv.
usage: sheaf gaps [--config path] [--repo path] [--kind k] [--library prefix] [--severity sev] [--format fmt]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
    value_type: string
    default_value: ""
DOCS
docs/cli/sheaf.md:52Markdown · 24 words

**Gaps.** `sheaf gaps` lists findings. Narrow them with `sheaf gaps --severity` (minimum `INFO`/`WARNING`/`ERROR`), `sheaf gaps --kind` (a specific finding kind), and `sheaf gaps --library` (one library or element-ID prefix). `sheaf gaps --format` emits `text`, `json`, or `csv`, and `sheaf gaps --config` selects a non-default config.

+ 11 more paragraphs · read full section
sheaf_gaps.md:31Markdown · 4 words
TESTS
internal/cli/gaps_test.go:38internal/cli/gaps_test::TestRunGaps_LibraryRepoKindFlags · Go · 8 lines
func TestRunGaps_LibraryRepoKindFlags(t *testing.T) {
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runGaps(&out, &errOut, "", dir, "THIN_REFERENCE", "demo", "WARNING", "text")
	if rc != 0 {
		t.Fatalf("runGaps with --library/--repo/--kind returned %d; stderr=%s", rc, errOut.String())
	}
}
internal/cli/gaps_test.go:72internal/cli/gaps_test::TestGaps_ArgvFlagParsing · Go · 18 lines
func TestGaps_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so every gaps flag is parsed from the
	// command line. The runGaps tests pass these positionally, which
	// leaves --config / --format / --severity unattributed in the
	// self-scan even though they're exercised here end to end.
	dir := setupFixture(t)
	rc := Gaps([]string{
		"--config", dir + "/sheaf.textproto",
		"--repo", dir,
		"--severity", "WARNING",
		"--format", "csv",
		"--kind", "THIN_REFERENCE",
		"--library", "demo",
	})
	if rc != 0 {
		t.Errorf("Gaps(--config/--repo/--severity/--format/--kind/--library) returned %d; want 0", rc)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf gaps
short: List findings filterable by kind, library, and severity.
long: |
  Runs the same pipeline as `sheaf scan` and prints the resulting
  Finding list, filtered client-side. Output as text, json, or csv.
usage: sheaf gaps [--config path] [--repo path] [--kind k] [--library prefix] [--severity sev] [--format fmt]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
    value_type: string
    default_value: ""
DOCS
sheaf_gaps.md:29Markdown · 3 words
TESTS
internal/cli/gaps_test.go:38internal/cli/gaps_test::TestRunGaps_LibraryRepoKindFlags · Go · 8 lines
func TestRunGaps_LibraryRepoKindFlags(t *testing.T) {
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runGaps(&out, &errOut, "", dir, "THIN_REFERENCE", "demo", "WARNING", "text")
	if rc != 0 {
		t.Fatalf("runGaps with --library/--repo/--kind returned %d; stderr=%s", rc, errOut.String())
	}
}
internal/cli/gaps_test.go:72internal/cli/gaps_test::TestGaps_ArgvFlagParsing · Go · 18 lines
func TestGaps_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so every gaps flag is parsed from the
	// command line. The runGaps tests pass these positionally, which
	// leaves --config / --format / --severity unattributed in the
	// self-scan even though they're exercised here end to end.
	dir := setupFixture(t)
	rc := Gaps([]string{
		"--config", dir + "/sheaf.textproto",
		"--repo", dir,
		"--severity", "WARNING",
		"--format", "csv",
		"--kind", "THIN_REFERENCE",
		"--library", "demo",
	})
	if rc != 0 {
		t.Errorf("Gaps(--config/--repo/--severity/--format/--kind/--library) returned %d; want 0", rc)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf gaps
short: List findings filterable by kind, library, and severity.
long: |
  Runs the same pipeline as `sheaf scan` and prints the resulting
  Finding list, filtered client-side. Output as text, json, or csv.
usage: sheaf gaps [--config path] [--repo path] [--kind k] [--library prefix] [--severity sev] [--format fmt]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
    value_type: string
    default_value: ""
DOCS
docs/cli/sheaf.md:52Markdown · 25 words

**Gaps.** `sheaf gaps` lists findings. Narrow them with `sheaf gaps --severity` (minimum `INFO`/`WARNING`/`ERROR`), `sheaf gaps --kind` (a specific finding kind), and `sheaf gaps --library` (one library or element-ID prefix). `sheaf gaps --format` emits `text`, `json`, or `csv`, and `sheaf gaps --config` selects a non-default config.

+ 11 more paragraphs · read full section
sheaf_gaps.md:32Markdown · 2 words
TESTS
internal/cli/gaps_test.go:72internal/cli/gaps_test::TestGaps_ArgvFlagParsing · Go · 18 lines
func TestGaps_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so every gaps flag is parsed from the
	// command line. The runGaps tests pass these positionally, which
	// leaves --config / --format / --severity unattributed in the
	// self-scan even though they're exercised here end to end.
	dir := setupFixture(t)
	rc := Gaps([]string{
		"--config", dir + "/sheaf.textproto",
		"--repo", dir,
		"--severity", "WARNING",
		"--format", "csv",
		"--kind", "THIN_REFERENCE",
		"--library", "demo",
	})
	if rc != 0 {
		t.Errorf("Gaps(--config/--repo/--severity/--format/--kind/--library) returned %d; want 0", rc)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf init
short: Scaffold a starter sheaf.textproto + categorization rules.
long: |
  Writes a starter pair of config files (sheaf.textproto and
  categorization-rules.textproto) into --repo. Refuses to overwrite
DOCS
sheaf_init.md:1Markdown · 187 words

**Do not edit a single file in this stage. Do not run `sheaf init`. The point is to understand the repo shape before letting a template push you toward the wrong adapter.**

+ 137 more paragraphs · read full section
docs/cli/sheaf.md:40Markdown · 28 words

`sheaf scan`, `sheaf gaps`, `sheaf coverage`, `sheaf report`, `sheaf snapshot`, `sheaf serve`, and `sheaf review` all run the full pipeline (config load → adapter dispatch → indexer → analyzers) before producing their output. `sheaf render` and `sheaf review-html` are pipeline-free — they render from a Snapshot JSON / `delta.json` that an earlier pipeline run already produced — as are `sheaf doctor`, `sheaf version`, and `sheaf init`.

+ 16 more paragraphs · read full section
+ 4 more refs · open all in source
TESTS
internal/cli/init_test.go:13internal/cli/init_test::TestRunInit_MinimalTemplate · Go · 17 lines
func TestRunInit_MinimalTemplate(t *testing.T) {
	dir := t.TempDir()
	var out, errOut bytes.Buffer
	rc := runInit(&out, &errOut, dir, "minimal")
	if rc != 0 {
		t.Fatalf("runInit returned %d; stderr=%s", rc, errOut.String())
	}
	for _, name := range []string{"sheaf.textproto", "categorization-rules.textproto"} {
		full := filepath.Join(dir, name)
		if _, err := os.Stat(full); err != nil {
			t.Errorf("init didn't write %s: %v", full, err)
		}
	}
	if !strings.Contains(out.String(), "Bootstrapped Sheaf config") {
		t.Errorf("expected bootstrap line; got %s", out.String())
	}
}
internal/cli/init_test.go:31internal/cli/init_test::TestRunInit_RefusesOverwrite · Go · 11 lines
func TestRunInit_RefusesOverwrite(t *testing.T) {
	dir := t.TempDir()
	if err := os.WriteFile(filepath.Join(dir, "sheaf.textproto"), []byte("preexisting"), 0o644); err != nil {
		t.Fatalf("seed: %v", err)
	}
	var out, errOut bytes.Buffer
	rc := runInit(&out, &errOut, dir, "minimal")
	if rc == 0 {
		t.Errorf("expected non-zero exit when sheaf.textproto exists; got 0, stderr=%s", errOut.String())
	}
}
internal/cli/init_test.go:43internal/cli/init_test::TestRunInit_UnknownTemplate · Go · 11 lines
func TestRunInit_UnknownTemplate(t *testing.T) {
	dir := t.TempDir()
	var out, errOut bytes.Buffer
	rc := runInit(&out, &errOut, dir, "definitely-not-a-template")
	if rc == 0 {
		t.Errorf("expected non-zero exit on unknown template; got 0")
	}
	if !strings.Contains(errOut.String(), "unknown template") {
		t.Errorf("expected unknown-template error; got %s", errOut.String())
	}
}
+ 5 more tests · open all in source
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf init
short: Scaffold a starter sheaf.textproto + categorization rules.
long: |
  Writes a starter pair of config files (sheaf.textproto and
  categorization-rules.textproto) into --repo. Refuses to overwrite
DOCS
docs/cli/sheaf.md:60Markdown · 28 words

**Init.** `sheaf init` scaffolds a starter config. `sheaf init --repo` chooses where the files are written.

+ 7 more paragraphs · read full section
sheaf_init.md:27Markdown · 6 words
TESTS
internal/cli/init_test.go:55internal/cli/init_test::TestRunInit_RepoFlag · Go · 13 lines
func TestRunInit_RepoFlag(t *testing.T) {
	dir := t.TempDir()
	var out, errOut bytes.Buffer
	rc := runInit(&out, &errOut, dir, "minimal")
	if rc != 0 {
		t.Fatalf("init --repo returned %d", rc)
	}
	for _, name := range []string{"sheaf.textproto", "categorization-rules.textproto"} {
		if _, err := os.Stat(filepath.Join(dir, name)); err != nil {
			t.Errorf("init didn't write %s", name)
		}
	}
}
internal/cli/init_test.go:129internal/cli/init_test::TestInit_ArgvFlagParsing · Go · 12 lines
func TestInit_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so --repo and --template are parsed
	// from the command line. The runInit tests pass the template
	// positionally, which never attributes the --template flag.
	dir := t.TempDir()
	if rc := Init([]string{"--repo", dir, "--template", "minimal"}); rc != 0 {
		t.Fatalf("Init(--repo,--template) returned %d; want 0", rc)
	}
	if _, err := os.Stat(filepath.Join(dir, "sheaf.textproto")); err != nil {
		t.Errorf("init via argv didn't write sheaf.textproto: %v", err)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf init
short: Scaffold a starter sheaf.textproto + categorization rules.
long: |
  Writes a starter pair of config files (sheaf.textproto and
  categorization-rules.textproto) into --repo. Refuses to overwrite
DOCS
sheaf_init.md:28Markdown · 5 words
TESTS
internal/cli/init_test.go:129internal/cli/init_test::TestInit_ArgvFlagParsing · Go · 12 lines
func TestInit_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so --repo and --template are parsed
	// from the command line. The runInit tests pass the template
	// positionally, which never attributes the --template flag.
	dir := t.TempDir()
	if rc := Init([]string{"--repo", dir, "--template", "minimal"}); rc != 0 {
		t.Fatalf("Init(--repo,--template) returned %d; want 0", rc)
	}
	if _, err := os.Stat(filepath.Join(dir, "sheaf.textproto")); err != nil {
		t.Errorf("init via argv didn't write sheaf.textproto: %v", err)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf render
short: Render an HTML report from a saved Snapshot JSON (in-process; no server).
DOCS
sheaf_render.md:1Markdown · 214 words

- **Wrong ecosystem view at render time.** Doctor doesn't know which `--ecosystem` flag you'll pass to `sheaf render`. Picking the wrong one is silent — the report renders, just with the wrong nouns and tiers (see Stage 6 below).

+ 40 more paragraphs · read full section

This is the in-process path — `sheaf snapshot` emits the library's Snapshot JSON and `sheaf render` turns it into a self-contained HTML file, no server. (The older `sheaf serve --port 7700 &` + `scanner --server http://127.0.0.1:7700 …` two-process flow still works and produces the same report, but the snapshot→render path is the lead recommendation.)

+ 30 more paragraphs · read full section
+ 5 more refs · open all in source
TESTS
internal/cli/render_test.go:60internal/cli/render_test::TestRunRender_DerivesCommitFromRepoRoot · Go · 23 lines
func TestRunRender_DerivesCommitFromRepoRoot(t *testing.T) {
	snap := snapshotForRender(t)
	// The sheaf repo itself is a git working tree; use it as the
	// --repo-root so gitShortCommit resolves a real short HEAD.
	repoRoot, err := filepath.Abs("../..")
	if err != nil {
		t.Fatalf("abs repo root: %v", err)
	}
	want := strings.TrimSpace(gitShortCommit(repoRoot))
	if want == "" {
		t.Skip("repo root is not a git tree (no HEAD); commit-derivation cannot be exercised")
	}
	out := filepath.Join(t.TempDir(), "report.html")
	html := renderToFile(t, out, []string{
		snap, "--library", "fuchsia.io", "--ecosystem", "fidl",
		"--repo-root", repoRoot, "-o", out,
	})
	wantSpan := "sha:" + want
	if !strings.Contains(html, wantSpan) {
		t.Errorf("rendered report does not carry the derived sha %q; "+
			"the regen render_one coverage reports would show no sha", wantSpan)
	}
}
internal/cli/render_test.go:84internal/cli/render_test::TestRunRender_ExplicitCommitOverridesDerivation · Go · 21 lines
func TestRunRender_ExplicitCommitOverridesDerivation(t *testing.T) {
	snap := snapshotForRender(t)
	repoRoot, err := filepath.Abs("../..")
	if err != nil {
		t.Fatalf("abs repo root: %v", err)
	}
	out := filepath.Join(t.TempDir(), "report.html")
	const pinned = "zzz9999"
	html := renderToFile(t, out, []string{
		snap, "--library", "fuchsia.io", "--ecosystem", "fidl",
		"--repo-root", repoRoot, "--commit", pinned, "-o", out,
	})
	if !strings.Contains(html, "sha:"+pinned) {
		t.Errorf("explicit --commit %q was not honored in the rendered report", pinned)
	}
	// The real HEAD must NOT leak in when an explicit commit is given.
	if real := strings.TrimSpace(gitShortCommit(repoRoot)); real != "" && real != pinned &&
		strings.Contains(html, "sha:"+real) {
		t.Errorf("derived sha %q leaked despite explicit --commit %q", real, pinned)
	}
}
internal/cli/render_test.go:106internal/cli/render_test::TestRunRender_NonGitRepoRootLeavesCommitEmpty · Go · 14 lines
func TestRunRender_NonGitRepoRootLeavesCommitEmpty(t *testing.T) {
	snap := snapshotForRender(t)
	// A plain temp dir is not a git tree, so gitShortCommit returns ""
	// and the report must render with no sha (deterministic).
	nonGit := t.TempDir()
	out := filepath.Join(t.TempDir(), "report.html")
	html := renderToFile(t, out, []string{
		snap, "--library", "fuchsia.io", "--ecosystem", "fidl",
		"--repo-root", nonGit, "-o", out,
	})
	if strings.Contains(html, "sha:") {
		t.Errorf("non-git --repo-root produced a sha; render must stay empty/deterministic")
	}
}
+ 5 more tests · open all in source
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf render
short: Render an HTML report from a saved Snapshot JSON (in-process; no server).
DOCS
docs/cli/sheaf.md:64Markdown · 25 words

**Render.** `sheaf render` turns a saved snapshot into the HTML report in-process — no server. `sheaf render --from-snapshot` names the snapshot and `sheaf render --library` overrides its label; `sheaf render --ecosystem` picks the rendering shape and `sheaf render --api-level` the target level for removed-element detection. `sheaf render --output` (alias `-o`) is the destination and `sheaf render --quiet` drops progress chatter. `sheaf render --repo-root` points at the git working tree — it enables the Lag section and the `{abs_path}` links that `sheaf render --source-url-template` can em…

+ 5 more paragraphs · read full section
sheaf_render.md:30Markdown · 10 words
TESTS

N/A

EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf render
short: Render an HTML report from a saved Snapshot JSON (in-process; no server).
DOCS
docs/cli/sheaf.md:64Markdown · 24 words

**Render.** `sheaf render` turns a saved snapshot into the HTML report in-process — no server. `sheaf render --from-snapshot` names the snapshot and `sheaf render --library` overrides its label; `sheaf render --ecosystem` picks the rendering shape and `sheaf render --api-level` the target level for removed-element detection. `sheaf render --output` (alias `-o`) is the destination and `sheaf render --quiet` drops progress chatter. `sheaf render --repo-root` points at the git working tree — it enables the Lag section and the `{abs_path}` links that `sheaf render --source-url-template` can em…

+ 5 more paragraphs · read full section
sheaf_render.md:36Markdown · 8 words
TESTS
internal/cli/render_test.go:84internal/cli/render_test::TestRunRender_ExplicitCommitOverridesDerivation · Go · 21 lines
func TestRunRender_ExplicitCommitOverridesDerivation(t *testing.T) {
	snap := snapshotForRender(t)
	repoRoot, err := filepath.Abs("../..")
	if err != nil {
		t.Fatalf("abs repo root: %v", err)
	}
	out := filepath.Join(t.TempDir(), "report.html")
	const pinned = "zzz9999"
	html := renderToFile(t, out, []string{
		snap, "--library", "fuchsia.io", "--ecosystem", "fidl",
		"--repo-root", repoRoot, "--commit", pinned, "-o", out,
	})
	if !strings.Contains(html, "sha:"+pinned) {
		t.Errorf("explicit --commit %q was not honored in the rendered report", pinned)
	}
	// The real HEAD must NOT leak in when an explicit commit is given.
	if real := strings.TrimSpace(gitShortCommit(repoRoot)); real != "" && real != pinned &&
		strings.Contains(html, "sha:"+real) {
		t.Errorf("derived sha %q leaked despite explicit --commit %q", real, pinned)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf render
short: Render an HTML report from a saved Snapshot JSON (in-process; no server).
DOCS
docs/cli/sheaf.md:64Markdown · 25 words

**Render.** `sheaf render` turns a saved snapshot into the HTML report in-process — no server. `sheaf render --from-snapshot` names the snapshot and `sheaf render --library` overrides its label; `sheaf render --ecosystem` picks the rendering shape and `sheaf render --api-level` the target level for removed-element detection. `sheaf render --output` (alias `-o`) is the destination and `sheaf render --quiet` drops progress chatter. `sheaf render --repo-root` points at the git working tree — it enables the Lag section and the `{abs_path}` links that `sheaf render --source-url-template` can em…

+ 5 more paragraphs · read full section
sheaf_render.md:37Markdown · 12 words
TESTS

N/A

EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf render
short: Render an HTML report from a saved Snapshot JSON (in-process; no server).
DOCS
docs/cli/sheaf.md:64Markdown · 27 words

**Render.** `sheaf render` turns a saved snapshot into the HTML report in-process — no server. `sheaf render --from-snapshot` names the snapshot and `sheaf render --library` overrides its label; `sheaf render --ecosystem` picks the rendering shape and `sheaf render --api-level` the target level for removed-element detection. `sheaf render --output` (alias `-o`) is the destination and `sheaf render --quiet` drops progress chatter. `sheaf render --repo-root` points at the git working tree — it enables the Lag section and the `{abs_path}` links that `sheaf render --source-url-template` can em…

+ 5 more paragraphs · read full section
sheaf_render.md:29Markdown · 1 words
+ 1 more refs · open all in source
TESTS
internal/cli/render_test.go:60internal/cli/render_test::TestRunRender_DerivesCommitFromRepoRoot · Go · 23 lines
func TestRunRender_DerivesCommitFromRepoRoot(t *testing.T) {
	snap := snapshotForRender(t)
	// The sheaf repo itself is a git working tree; use it as the
	// --repo-root so gitShortCommit resolves a real short HEAD.
	repoRoot, err := filepath.Abs("../..")
	if err != nil {
		t.Fatalf("abs repo root: %v", err)
	}
	want := strings.TrimSpace(gitShortCommit(repoRoot))
	if want == "" {
		t.Skip("repo root is not a git tree (no HEAD); commit-derivation cannot be exercised")
	}
	out := filepath.Join(t.TempDir(), "report.html")
	html := renderToFile(t, out, []string{
		snap, "--library", "fuchsia.io", "--ecosystem", "fidl",
		"--repo-root", repoRoot, "-o", out,
	})
	wantSpan := "sha:" + want
	if !strings.Contains(html, wantSpan) {
		t.Errorf("rendered report does not carry the derived sha %q; "+
			"the regen render_one coverage reports would show no sha", wantSpan)
	}
}
internal/cli/render_test.go:84internal/cli/render_test::TestRunRender_ExplicitCommitOverridesDerivation · Go · 21 lines
func TestRunRender_ExplicitCommitOverridesDerivation(t *testing.T) {
	snap := snapshotForRender(t)
	repoRoot, err := filepath.Abs("../..")
	if err != nil {
		t.Fatalf("abs repo root: %v", err)
	}
	out := filepath.Join(t.TempDir(), "report.html")
	const pinned = "zzz9999"
	html := renderToFile(t, out, []string{
		snap, "--library", "fuchsia.io", "--ecosystem", "fidl",
		"--repo-root", repoRoot, "--commit", pinned, "-o", out,
	})
	if !strings.Contains(html, "sha:"+pinned) {
		t.Errorf("explicit --commit %q was not honored in the rendered report", pinned)
	}
	// The real HEAD must NOT leak in when an explicit commit is given.
	if real := strings.TrimSpace(gitShortCommit(repoRoot)); real != "" && real != pinned &&
		strings.Contains(html, "sha:"+real) {
		t.Errorf("derived sha %q leaked despite explicit --commit %q", real, pinned)
	}
}
internal/cli/render_test.go:106internal/cli/render_test::TestRunRender_NonGitRepoRootLeavesCommitEmpty · Go · 14 lines
func TestRunRender_NonGitRepoRootLeavesCommitEmpty(t *testing.T) {
	snap := snapshotForRender(t)
	// A plain temp dir is not a git tree, so gitShortCommit returns ""
	// and the report must render with no sha (deterministic).
	nonGit := t.TempDir()
	out := filepath.Join(t.TempDir(), "report.html")
	html := renderToFile(t, out, []string{
		snap, "--library", "fuchsia.io", "--ecosystem", "fidl",
		"--repo-root", nonGit, "-o", out,
	})
	if strings.Contains(html, "sha:") {
		t.Errorf("non-git --repo-root produced a sha; render must stay empty/deterministic")
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf render
short: Render an HTML report from a saved Snapshot JSON (in-process; no server).
DOCS
docs/cli/sheaf.md:64Markdown · 29 words

**Render.** `sheaf render` turns a saved snapshot into the HTML report in-process — no server. `sheaf render --from-snapshot` names the snapshot and `sheaf render --library` overrides its label; `sheaf render --ecosystem` picks the rendering shape and `sheaf render --api-level` the target level for removed-element detection. `sheaf render --output` (alias `-o`) is the destination and `sheaf render --quiet` drops progress chatter. `sheaf render --repo-root` points at the git working tree — it enables the Lag section and the `{abs_path}` links that `sheaf render --source-url-template` can em…

+ 5 more paragraphs · read full section
docs/cli/workflows.md:75Markdown · 19 words

Saved snapshots let you re-render without restanding the server. The preferred path is fully in-process — no `sheaf serve`, no `scanner` — using `sheaf snapshot` to persist the Snapshot JSON and `sheaf render --from-snapshot` to render it:

+ 13 more paragraphs · read full section
sheaf_render.md:27Markdown · 10 words
+ 2 more refs · open all in source
TESTS

N/A

EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf render
short: Render an HTML report from a saved Snapshot JSON (in-process; no server).
DOCS
docs/cli/sheaf.md:64Markdown · 26 words

**Render.** `sheaf render` turns a saved snapshot into the HTML report in-process — no server. `sheaf render --from-snapshot` names the snapshot and `sheaf render --library` overrides its label; `sheaf render --ecosystem` picks the rendering shape and `sheaf render --api-level` the target level for removed-element detection. `sheaf render --output` (alias `-o`) is the destination and `sheaf render --quiet` drops progress chatter. `sheaf render --repo-root` points at the git working tree — it enables the Lag section and the `{abs_path}` links that `sheaf render --source-url-template` can em…

+ 5 more paragraphs · read full section
sheaf_render.md:35Markdown · 11 words
TESTS

N/A

EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf render
short: Render an HTML report from a saved Snapshot JSON (in-process; no server).
DOCS
docs/cli/sheaf.md:64Markdown · 26 words

**Render.** `sheaf render` turns a saved snapshot into the HTML report in-process — no server. `sheaf render --from-snapshot` names the snapshot and `sheaf render --library` overrides its label; `sheaf render --ecosystem` picks the rendering shape and `sheaf render --api-level` the target level for removed-element detection. `sheaf render --output` (alias `-o`) is the destination and `sheaf render --quiet` drops progress chatter. `sheaf render --repo-root` points at the git working tree — it enables the Lag section and the `{abs_path}` links that `sheaf render --source-url-template` can em…

+ 5 more paragraphs · read full section
sheaf_render.md:28Markdown · 5 words
TESTS
internal/cli/render_test.go:60internal/cli/render_test::TestRunRender_DerivesCommitFromRepoRoot · Go · 23 lines
func TestRunRender_DerivesCommitFromRepoRoot(t *testing.T) {
	snap := snapshotForRender(t)
	// The sheaf repo itself is a git working tree; use it as the
	// --repo-root so gitShortCommit resolves a real short HEAD.
	repoRoot, err := filepath.Abs("../..")
	if err != nil {
		t.Fatalf("abs repo root: %v", err)
	}
	want := strings.TrimSpace(gitShortCommit(repoRoot))
	if want == "" {
		t.Skip("repo root is not a git tree (no HEAD); commit-derivation cannot be exercised")
	}
	out := filepath.Join(t.TempDir(), "report.html")
	html := renderToFile(t, out, []string{
		snap, "--library", "fuchsia.io", "--ecosystem", "fidl",
		"--repo-root", repoRoot, "-o", out,
	})
	wantSpan := "sha:" + want
	if !strings.Contains(html, wantSpan) {
		t.Errorf("rendered report does not carry the derived sha %q; "+
			"the regen render_one coverage reports would show no sha", wantSpan)
	}
}
internal/cli/render_test.go:84internal/cli/render_test::TestRunRender_ExplicitCommitOverridesDerivation · Go · 21 lines
func TestRunRender_ExplicitCommitOverridesDerivation(t *testing.T) {
	snap := snapshotForRender(t)
	repoRoot, err := filepath.Abs("../..")
	if err != nil {
		t.Fatalf("abs repo root: %v", err)
	}
	out := filepath.Join(t.TempDir(), "report.html")
	const pinned = "zzz9999"
	html := renderToFile(t, out, []string{
		snap, "--library", "fuchsia.io", "--ecosystem", "fidl",
		"--repo-root", repoRoot, "--commit", pinned, "-o", out,
	})
	if !strings.Contains(html, "sha:"+pinned) {
		t.Errorf("explicit --commit %q was not honored in the rendered report", pinned)
	}
	// The real HEAD must NOT leak in when an explicit commit is given.
	if real := strings.TrimSpace(gitShortCommit(repoRoot)); real != "" && real != pinned &&
		strings.Contains(html, "sha:"+real) {
		t.Errorf("derived sha %q leaked despite explicit --commit %q", real, pinned)
	}
}
internal/cli/render_test.go:106internal/cli/render_test::TestRunRender_NonGitRepoRootLeavesCommitEmpty · Go · 14 lines
func TestRunRender_NonGitRepoRootLeavesCommitEmpty(t *testing.T) {
	snap := snapshotForRender(t)
	// A plain temp dir is not a git tree, so gitShortCommit returns ""
	// and the report must render with no sha (deterministic).
	nonGit := t.TempDir()
	out := filepath.Join(t.TempDir(), "report.html")
	html := renderToFile(t, out, []string{
		snap, "--library", "fuchsia.io", "--ecosystem", "fidl",
		"--repo-root", nonGit, "-o", out,
	})
	if strings.Contains(html, "sha:") {
		t.Errorf("non-git --repo-root produced a sha; render must stay empty/deterministic")
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf render
short: Render an HTML report from a saved Snapshot JSON (in-process; no server).
DOCS
docs/cli/sheaf.md:64Markdown · 24 words

**Render.** `sheaf render` turns a saved snapshot into the HTML report in-process — no server. `sheaf render --from-snapshot` names the snapshot and `sheaf render --library` overrides its label; `sheaf render --ecosystem` picks the rendering shape and `sheaf render --api-level` the target level for removed-element detection. `sheaf render --output` (alias `-o`) is the destination and `sheaf render --quiet` drops progress chatter. `sheaf render --repo-root` points at the git working tree — it enables the Lag section and the `{abs_path}` links that `sheaf render --source-url-template` can em…

+ 5 more paragraphs · read full section
sheaf_render.md:38Markdown · 12 words
TESTS

N/A

EXAMPLES

N/A

WORKFLOWS

N/A

CONTRACT
command: sheaf render
short: Render an HTML report from a saved Snapshot JSON (in-process; no server).
DOCS
docs/cli/sheaf.md:64Markdown · 25 words

**Render.** `sheaf render` turns a saved snapshot into the HTML report in-process — no server. `sheaf render --from-snapshot` names the snapshot and `sheaf render --library` overrides its label; `sheaf render --ecosystem` picks the rendering shape and `sheaf render --api-level` the target level for removed-element detection. `sheaf render --output` (alias `-o`) is the destination and `sheaf render --quiet` drops progress chatter. `sheaf render --repo-root` points at the git working tree — it enables the Lag section and the `{abs_path}` links that `sheaf render --source-url-template` can em…

+ 5 more paragraphs · read full section
sheaf_render.md:31Markdown · 3 words
TESTS

N/A

EXAMPLES

N/A

WORKFLOWS

N/A

CONTRACT
command: sheaf render
short: Render an HTML report from a saved Snapshot JSON (in-process; no server).
DOCS
docs/cli/sheaf.md:64Markdown · 26 words

**Render.** `sheaf render` turns a saved snapshot into the HTML report in-process — no server. `sheaf render --from-snapshot` names the snapshot and `sheaf render --library` overrides its label; `sheaf render --ecosystem` picks the rendering shape and `sheaf render --api-level` the target level for removed-element detection. `sheaf render --output` (alias `-o`) is the destination and `sheaf render --quiet` drops progress chatter. `sheaf render --repo-root` points at the git working tree — it enables the Lag section and the `{abs_path}` links that `sheaf render --source-url-template` can em…

+ 5 more paragraphs · read full section
sheaf_render.md:32Markdown · 4 words
TESTS

N/A

EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf render
short: Render an HTML report from a saved Snapshot JSON (in-process; no server).
DOCS
docs/cli/sheaf.md:64Markdown · 30 words

**Render.** `sheaf render` turns a saved snapshot into the HTML report in-process — no server. `sheaf render --from-snapshot` names the snapshot and `sheaf render --library` overrides its label; `sheaf render --ecosystem` picks the rendering shape and `sheaf render --api-level` the target level for removed-element detection. `sheaf render --output` (alias `-o`) is the destination and `sheaf render --quiet` drops progress chatter. `sheaf render --repo-root` points at the git working tree — it enables the Lag section and the `{abs_path}` links that `sheaf render --source-url-template` can em…

+ 5 more paragraphs · read full section
sheaf_render.md:34Markdown · 15 words
TESTS
internal/cli/render_test.go:60internal/cli/render_test::TestRunRender_DerivesCommitFromRepoRoot · Go · 23 lines
func TestRunRender_DerivesCommitFromRepoRoot(t *testing.T) {
	snap := snapshotForRender(t)
	// The sheaf repo itself is a git working tree; use it as the
	// --repo-root so gitShortCommit resolves a real short HEAD.
	repoRoot, err := filepath.Abs("../..")
	if err != nil {
		t.Fatalf("abs repo root: %v", err)
	}
	want := strings.TrimSpace(gitShortCommit(repoRoot))
	if want == "" {
		t.Skip("repo root is not a git tree (no HEAD); commit-derivation cannot be exercised")
	}
	out := filepath.Join(t.TempDir(), "report.html")
	html := renderToFile(t, out, []string{
		snap, "--library", "fuchsia.io", "--ecosystem", "fidl",
		"--repo-root", repoRoot, "-o", out,
	})
	wantSpan := "sha:" + want
	if !strings.Contains(html, wantSpan) {
		t.Errorf("rendered report does not carry the derived sha %q; "+
			"the regen render_one coverage reports would show no sha", wantSpan)
	}
}
internal/cli/render_test.go:84internal/cli/render_test::TestRunRender_ExplicitCommitOverridesDerivation · Go · 21 lines
func TestRunRender_ExplicitCommitOverridesDerivation(t *testing.T) {
	snap := snapshotForRender(t)
	repoRoot, err := filepath.Abs("../..")
	if err != nil {
		t.Fatalf("abs repo root: %v", err)
	}
	out := filepath.Join(t.TempDir(), "report.html")
	const pinned = "zzz9999"
	html := renderToFile(t, out, []string{
		snap, "--library", "fuchsia.io", "--ecosystem", "fidl",
		"--repo-root", repoRoot, "--commit", pinned, "-o", out,
	})
	if !strings.Contains(html, "sha:"+pinned) {
		t.Errorf("explicit --commit %q was not honored in the rendered report", pinned)
	}
	// The real HEAD must NOT leak in when an explicit commit is given.
	if real := strings.TrimSpace(gitShortCommit(repoRoot)); real != "" && real != pinned &&
		strings.Contains(html, "sha:"+real) {
		t.Errorf("derived sha %q leaked despite explicit --commit %q", real, pinned)
	}
}
internal/cli/render_test.go:106internal/cli/render_test::TestRunRender_NonGitRepoRootLeavesCommitEmpty · Go · 14 lines
func TestRunRender_NonGitRepoRootLeavesCommitEmpty(t *testing.T) {
	snap := snapshotForRender(t)
	// A plain temp dir is not a git tree, so gitShortCommit returns ""
	// and the report must render with no sha (deterministic).
	nonGit := t.TempDir()
	out := filepath.Join(t.TempDir(), "report.html")
	html := renderToFile(t, out, []string{
		snap, "--library", "fuchsia.io", "--ecosystem", "fidl",
		"--repo-root", nonGit, "-o", out,
	})
	if strings.Contains(html, "sha:") {
		t.Errorf("non-git --repo-root produced a sha; render must stay empty/deterministic")
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf render
short: Render an HTML report from a saved Snapshot JSON (in-process; no server).
DOCS
docs/cli/sheaf.md:64Markdown · 30 words

**Render.** `sheaf render` turns a saved snapshot into the HTML report in-process — no server. `sheaf render --from-snapshot` names the snapshot and `sheaf render --library` overrides its label; `sheaf render --ecosystem` picks the rendering shape and `sheaf render --api-level` the target level for removed-element detection. `sheaf render --output` (alias `-o`) is the destination and `sheaf render --quiet` drops progress chatter. `sheaf render --repo-root` points at the git working tree — it enables the Lag section and the `{abs_path}` links that `sheaf render --source-url-template` can em…

+ 5 more paragraphs · read full section
sheaf_render.md:33Markdown · 8 words
TESTS

N/A

EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf report
short: Bulk dump all coverage profiles as CSV, JSON, or HTML.
long: |
  Runs the full pipeline and emits every CoverageProfile in the corpus.
  CSV and JSON go to stdout; HTML is written as a multi-page browser
  into --output.
usage: sheaf report [--config path] [--repo path] [--format csv|json|html] [--output dir]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
    value_type: string
DOCS
sheaf_report.md:1Markdown · 189 words
docs/cli/sheaf.md:40Markdown · 26 words

`sheaf scan`, `sheaf gaps`, `sheaf coverage`, `sheaf report`, `sheaf snapshot`, `sheaf serve`, and `sheaf review` all run the full pipeline (config load → adapter dispatch → indexer → analyzers) before producing their output. `sheaf render` and `sheaf review-html` are pipeline-free — they render from a Snapshot JSON / `delta.json` that an earlier pipeline run already produced — as are `sheaf doctor`, `sheaf version`, and `sheaf init`.

+ 16 more paragraphs · read full section
docs/cli/sheaf.md:54Markdown · 23 words

**Report.** `sheaf report` bulk-dumps every coverage profile. `sheaf report --format` chooses `csv`, `json`, or `html`; when it is `html`, `sheaf report --output` names the directory the multi-page report is written to. `sheaf report --config` and `sheaf report --repo` locate the project.

+ 10 more paragraphs · read full section
+ 3 more refs · open all in source
TESTS
internal/cli/report_test.go:12internal/cli/report_test::TestRunReport_CSVFormat · Go · 11 lines
func TestRunReport_CSVFormat(t *testing.T) {
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runReport(&out, &errOut, "", dir, "csv", "")
	if rc != 0 {
		t.Fatalf("runReport returned %d; stderr=%s", rc, errOut.String())
	}
	if !strings.HasPrefix(out.String(), "element_id,tests,docs,examples,missing") {
		t.Errorf("expected CSV header at start; got %q", firstLine(out.String()))
	}
}
internal/cli/report_test.go:24internal/cli/report_test::TestRunReport_HTMLRequiresOutput · Go · 8 lines
func TestRunReport_HTMLRequiresOutput(t *testing.T) {
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runReport(&out, &errOut, "", dir, "html", "")
	if rc != 2 {
		t.Errorf("expected rc=2 when --format html lacks --output; got %d", rc)
	}
}
internal/cli/report_test.go:33internal/cli/report_test::TestRunReport_HTMLWritesIndex · Go · 12 lines
func TestRunReport_HTMLWritesIndex(t *testing.T) {
	dir := setupFixture(t)
	outDir := filepath.Join(t.TempDir(), "report")
	var out, errOut bytes.Buffer
	rc := runReport(&out, &errOut, "", dir, "html", outDir)
	if rc != 0 {
		t.Fatalf("runReport(html) returned %d; stderr=%s", rc, errOut.String())
	}
	if !strings.Contains(out.String(), "HTML report written") {
		t.Errorf("expected success line; got %q", out.String())
	}
}
+ 2 more tests · open all in source
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf report
short: Bulk dump all coverage profiles as CSV, JSON, or HTML.
long: |
  Runs the full pipeline and emits every CoverageProfile in the corpus.
  CSV and JSON go to stdout; HTML is written as a multi-page browser
  into --output.
usage: sheaf report [--config path] [--repo path] [--format csv|json|html] [--output dir]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
    value_type: string
DOCS
docs/cli/sheaf.md:54Markdown · 26 words

**Report.** `sheaf report` bulk-dumps every coverage profile. `sheaf report --format` chooses `csv`, `json`, or `html`; when it is `html`, `sheaf report --output` names the directory the multi-page report is written to. `sheaf report --config` and `sheaf report --repo` locate the project.

+ 10 more paragraphs · read full section
sheaf_report.md:27Markdown · 5 words
TESTS
internal/cli/report_test.go:46internal/cli/report_test::TestRunReport_RepoConfigFlags · Go · 8 lines
func TestRunReport_RepoConfigFlags(t *testing.T) {
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runReport(&out, &errOut, dir+"/sheaf.textproto", dir, "csv", "")
	if rc != 0 {
		t.Fatalf("runReport(--config,--repo) returned %d", rc)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf report
short: Bulk dump all coverage profiles as CSV, JSON, or HTML.
long: |
  Runs the full pipeline and emits every CoverageProfile in the corpus.
  CSV and JSON go to stdout; HTML is written as a multi-page browser
  into --output.
usage: sheaf report [--config path] [--repo path] [--format csv|json|html] [--output dir]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
    value_type: string
DOCS
docs/cli/sheaf.md:54Markdown · 25 words

**Report.** `sheaf report` bulk-dumps every coverage profile. `sheaf report --format` chooses `csv`, `json`, or `html`; when it is `html`, `sheaf report --output` names the directory the multi-page report is written to. `sheaf report --config` and `sheaf report --repo` locate the project.

+ 10 more paragraphs · read full section
sheaf_report.md:29Markdown · 4 words
TESTS
internal/cli/report_test.go:24internal/cli/report_test::TestRunReport_HTMLRequiresOutput · Go · 8 lines
func TestRunReport_HTMLRequiresOutput(t *testing.T) {
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runReport(&out, &errOut, "", dir, "html", "")
	if rc != 2 {
		t.Errorf("expected rc=2 when --format html lacks --output; got %d", rc)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf report
short: Bulk dump all coverage profiles as CSV, JSON, or HTML.
long: |
  Runs the full pipeline and emits every CoverageProfile in the corpus.
  CSV and JSON go to stdout; HTML is written as a multi-page browser
  into --output.
usage: sheaf report [--config path] [--repo path] [--format csv|json|html] [--output dir]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
    value_type: string
DOCS
docs/cli/sheaf.md:54Markdown · 28 words

**Report.** `sheaf report` bulk-dumps every coverage profile. `sheaf report --format` chooses `csv`, `json`, or `html`; when it is `html`, `sheaf report --output` names the directory the multi-page report is written to. `sheaf report --config` and `sheaf report --repo` locate the project.

+ 10 more paragraphs · read full section
sheaf_report.md:30Markdown · 10 words
TESTS
internal/cli/report_test.go:24internal/cli/report_test::TestRunReport_HTMLRequiresOutput · Go · 8 lines
func TestRunReport_HTMLRequiresOutput(t *testing.T) {
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runReport(&out, &errOut, "", dir, "html", "")
	if rc != 2 {
		t.Errorf("expected rc=2 when --format html lacks --output; got %d", rc)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf report
short: Bulk dump all coverage profiles as CSV, JSON, or HTML.
long: |
  Runs the full pipeline and emits every CoverageProfile in the corpus.
  CSV and JSON go to stdout; HTML is written as a multi-page browser
  into --output.
usage: sheaf report [--config path] [--repo path] [--format csv|json|html] [--output dir]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
    value_type: string
DOCS
docs/cli/sheaf.md:54Markdown · 27 words

**Report.** `sheaf report` bulk-dumps every coverage profile. `sheaf report --format` chooses `csv`, `json`, or `html`; when it is `html`, `sheaf report --output` names the directory the multi-page report is written to. `sheaf report --config` and `sheaf report --repo` locate the project.

+ 10 more paragraphs · read full section
sheaf_report.md:28Markdown · 3 words
TESTS
internal/cli/report_test.go:46internal/cli/report_test::TestRunReport_RepoConfigFlags · Go · 8 lines
func TestRunReport_RepoConfigFlags(t *testing.T) {
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runReport(&out, &errOut, dir+"/sheaf.textproto", dir, "csv", "")
	if rc != 0 {
		t.Fatalf("runReport(--config,--repo) returned %d", rc)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf review
short: Render a PR review comment from base + head corpora.
long: |
  Scans two checkouts of the same project (--base = PR target, --repo
  = PR head) using the same sheaf.textproto, builds a delta, and
DOCS
sheaf_review.md:1Markdown · 327 words
docs/cli/sheaf.md:40Markdown · 27 words

`sheaf scan`, `sheaf gaps`, `sheaf coverage`, `sheaf report`, `sheaf snapshot`, `sheaf serve`, and `sheaf review` all run the full pipeline (config load → adapter dispatch → indexer → analyzers) before producing their output. `sheaf render` and `sheaf review-html` are pipeline-free — they render from a Snapshot JSON / `delta.json` that an earlier pipeline run already produced — as are `sheaf doctor`, `sheaf version`, and `sheaf init`.

+ 16 more paragraphs · read full section
docs/cli/sheaf.md:58Markdown · 26 words

**Review.** `sheaf review` renders a PR-coverage-delta comment. It needs a base tree via `sheaf review --base`; `sheaf review --repo` is the PR head and `sheaf review --pr` is the reference printed in the comment header. `sheaf review --review` overrides the configured review adapter (`noop`/`file`/`gerrit`/`github`), `sheaf review --file-out` is where the `file` adapter writes, and `sheaf review --post` actually posts the comment instead of printing it. `sheaf review --config` selects the config used for both base and head.

+ 8 more paragraphs · read full section
+ 3 more refs · open all in source
TESTS
internal/cli/review_test.go:14internal/cli/review_test::TestReview_RequiresBase · Go · 7 lines
func TestReview_RequiresBase(t *testing.T) {
	// The public entry refuses to run without --base; we exercise it
	// through Review() so the flag-required branch is covered.
	if rc := Review([]string{"--repo", "."}); rc != 2 {
		t.Errorf("expected rc=2 when --base missing; got %d", rc)
	}
}
internal/cli/review_test.go:22internal/cli/review_test::TestRunReview_MissingConfig · Go · 9 lines
func TestRunReview_MissingConfig(t *testing.T) {
	headDir := t.TempDir()
	baseDir := t.TempDir()
	var out, errOut bytes.Buffer
	rc := runReview(&out, &errOut, "", headDir, baseDir, "PR#1", false, "", "", "", "", "", "", "")
	if rc == 0 {
		t.Errorf("expected non-zero exit on missing config; out=%s err=%s", out.String(), errOut.String())
	}
}
internal/cli/review_test.go:32internal/cli/review_test::TestBuildReviewAdapter_NoopOverride · Go · 10 lines
func TestBuildReviewAdapter_NoopOverride(t *testing.T) {
	cfg := &configpb.Config{}
	a, err := buildReviewAdapter(cfg, "noop", "")
	if err != nil {
		t.Fatalf("buildReviewAdapter: %v", err)
	}
	if a == nil || a.Name() != "noop" {
		t.Errorf("expected noop adapter; got %#v", a)
	}
}
+ 13 more tests · open all in source
EXAMPLES
+ 1 more examples · open all in source
WORKFLOWS

N/A

CONTRACT
command: sheaf review
short: Render a PR review comment from base + head corpora.
long: |
  Scans two checkouts of the same project (--base = PR target, --repo
  = PR head) using the same sheaf.textproto, builds a delta, and
DOCS
docs/cli/sheaf.md:58Markdown · 30 words

**Review.** `sheaf review` renders a PR-coverage-delta comment. It needs a base tree via `sheaf review --base`; `sheaf review --repo` is the PR head and `sheaf review --pr` is the reference printed in the comment header. `sheaf review --review` overrides the configured review adapter (`noop`/`file`/`gerrit`/`github`), `sheaf review --file-out` is where the `file` adapter writes, and `sheaf review --post` actually posts the comment instead of printing it. `sheaf review --config` selects the config used for both base and head.

+ 8 more paragraphs · read full section
sheaf_review.md:36Markdown · 5 words
+ 1 more refs · open all in source
TESTS
internal/cli/review_test.go:14internal/cli/review_test::TestReview_RequiresBase · Go · 7 lines
func TestReview_RequiresBase(t *testing.T) {
	// The public entry refuses to run without --base; we exercise it
	// through Review() so the flag-required branch is covered.
	if rc := Review([]string{"--repo", "."}); rc != 2 {
		t.Errorf("expected rc=2 when --base missing; got %d", rc)
	}
}
internal/cli/review_test.go:55internal/cli/review_test::TestReview_FileOutRepoBaseFlags · Go · 20 lines
func TestReview_FileOutRepoBaseFlags(t *testing.T) {
	// --base + --repo + --review file + --file-out: confirm the flag
	// wiring parses, even though the pipeline fails on missing config.
	headDir := t.TempDir()
	baseDir := t.TempDir()
	fileOut := filepath.Join(t.TempDir(), "out.md")
	rc := Review([]string{
		"--base", baseDir,
		"--repo", headDir,
		"--review", "file",
		"--file-out", fileOut,
		"--pr", "PR#unit",
	})
	// rc != 2 (would be parse error); 3 expected because config
	// loading fails on the empty repo. We just need flag parsing
	// to land.
	if rc == 2 {
		t.Errorf("flag parse failed for review --base/--repo/--review/--file-out; rc=2")
	}
}
internal/cli/review_test.go:83internal/cli/review_test::TestReview_ConfigPostFlags · Go · 20 lines
func TestReview_ConfigPostFlags(t *testing.T) {
	// Drive --config + --post through the public argv entry alongside a
	// noop review adapter. Config loading fails on the empty repo (rc=3),
	// so the run never reaches the post step — but the flags parse, which
	// attributes --config and --post without any external side effect.
	headDir := t.TempDir()
	baseDir := t.TempDir()
	rc := Review([]string{
		"--base", baseDir,
		"--repo", headDir,
		"--config", headDir + "/sheaf.textproto",
		"--review", "noop",
		"--post",
	})
	// rc == 2 would be a flag-parse error; we expect the later config-load
	// failure (rc=3) instead, proving the flags landed.
	if rc == 2 {
		t.Errorf("flag parse failed for review --config/--post; rc=2")
	}
}
EXAMPLES
+ 1 more examples · open all in source
WORKFLOWS

N/A

CONTRACT
command: sheaf review
short: Render a PR review comment from base + head corpora.
long: |
  Scans two checkouts of the same project (--base = PR target, --repo
  = PR head) using the same sheaf.textproto, builds a delta, and
DOCS
docs/cli/sheaf.md:58Markdown · 29 words

**Review.** `sheaf review` renders a PR-coverage-delta comment. It needs a base tree via `sheaf review --base`; `sheaf review --repo` is the PR head and `sheaf review --pr` is the reference printed in the comment header. `sheaf review --review` overrides the configured review adapter (`noop`/`file`/`gerrit`/`github`), `sheaf review --file-out` is where the `file` adapter writes, and `sheaf review --post` actually posts the comment instead of printing it. `sheaf review --config` selects the config used for both base and head.

+ 8 more paragraphs · read full section
sheaf_review.md:38Markdown · 5 words
TESTS
internal/cli/review_test.go:83internal/cli/review_test::TestReview_ConfigPostFlags · Go · 20 lines
func TestReview_ConfigPostFlags(t *testing.T) {
	// Drive --config + --post through the public argv entry alongside a
	// noop review adapter. Config loading fails on the empty repo (rc=3),
	// so the run never reaches the post step — but the flags parse, which
	// attributes --config and --post without any external side effect.
	headDir := t.TempDir()
	baseDir := t.TempDir()
	rc := Review([]string{
		"--base", baseDir,
		"--repo", headDir,
		"--config", headDir + "/sheaf.textproto",
		"--review", "noop",
		"--post",
	})
	// rc == 2 would be a flag-parse error; we expect the later config-load
	// failure (rc=3) instead, proving the flags landed.
	if rc == 2 {
		t.Errorf("flag parse failed for review --config/--post; rc=2")
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf review
short: Render a PR review comment from base + head corpora.
long: |
  Scans two checkouts of the same project (--base = PR target, --repo
  = PR head) using the same sheaf.textproto, builds a delta, and
DOCS
docs/cli/sheaf.md:58Markdown · 23 words

**Review.** `sheaf review` renders a PR-coverage-delta comment. It needs a base tree via `sheaf review --base`; `sheaf review --repo` is the PR head and `sheaf review --pr` is the reference printed in the comment header. `sheaf review --review` overrides the configured review adapter (`noop`/`file`/`gerrit`/`github`), `sheaf review --file-out` is where the `file` adapter writes, and `sheaf review --post` actually posts the comment instead of printing it. `sheaf review --config` selects the config used for both base and head.

+ 8 more paragraphs · read full section
sheaf_review.md:42Markdown · 3 words
TESTS
internal/cli/review_test.go:55internal/cli/review_test::TestReview_FileOutRepoBaseFlags · Go · 20 lines
func TestReview_FileOutRepoBaseFlags(t *testing.T) {
	// --base + --repo + --review file + --file-out: confirm the flag
	// wiring parses, even though the pipeline fails on missing config.
	headDir := t.TempDir()
	baseDir := t.TempDir()
	fileOut := filepath.Join(t.TempDir(), "out.md")
	rc := Review([]string{
		"--base", baseDir,
		"--repo", headDir,
		"--review", "file",
		"--file-out", fileOut,
		"--pr", "PR#unit",
	})
	// rc != 2 (would be parse error); 3 expected because config
	// loading fails on the empty repo. We just need flag parsing
	// to land.
	if rc == 2 {
		t.Errorf("flag parse failed for review --base/--repo/--review/--file-out; rc=2")
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf review
short: Render a PR review comment from base + head corpora.
long: |
  Scans two checkouts of the same project (--base = PR target, --repo
  = PR head) using the same sheaf.textproto, builds a delta, and
DOCS
docs/cli/sheaf.md:58Markdown · 26 words

**Review.** `sheaf review` renders a PR-coverage-delta comment. It needs a base tree via `sheaf review --base`; `sheaf review --repo` is the PR head and `sheaf review --pr` is the reference printed in the comment header. `sheaf review --review` overrides the configured review adapter (`noop`/`file`/`gerrit`/`github`), `sheaf review --file-out` is where the `file` adapter writes, and `sheaf review --post` actually posts the comment instead of printing it. `sheaf review --config` selects the config used for both base and head.

+ 8 more paragraphs · read full section
sheaf_review.md:40Markdown · 8 words
TESTS
internal/cli/review_test.go:83internal/cli/review_test::TestReview_ConfigPostFlags · Go · 20 lines
func TestReview_ConfigPostFlags(t *testing.T) {
	// Drive --config + --post through the public argv entry alongside a
	// noop review adapter. Config loading fails on the empty repo (rc=3),
	// so the run never reaches the post step — but the flags parse, which
	// attributes --config and --post without any external side effect.
	headDir := t.TempDir()
	baseDir := t.TempDir()
	rc := Review([]string{
		"--base", baseDir,
		"--repo", headDir,
		"--config", headDir + "/sheaf.textproto",
		"--review", "noop",
		"--post",
	})
	// rc == 2 would be a flag-parse error; we expect the later config-load
	// failure (rc=3) instead, proving the flags landed.
	if rc == 2 {
		t.Errorf("flag parse failed for review --config/--post; rc=2")
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf review
short: Render a PR review comment from base + head corpora.
long: |
  Scans two checkouts of the same project (--base = PR target, --repo
  = PR head) using the same sheaf.textproto, builds a delta, and
DOCS
docs/cli/sheaf.md:58Markdown · 30 words

**Review.** `sheaf review` renders a PR-coverage-delta comment. It needs a base tree via `sheaf review --base`; `sheaf review --repo` is the PR head and `sheaf review --pr` is the reference printed in the comment header. `sheaf review --review` overrides the configured review adapter (`noop`/`file`/`gerrit`/`github`), `sheaf review --file-out` is where the `file` adapter writes, and `sheaf review --post` actually posts the comment instead of printing it. `sheaf review --config` selects the config used for both base and head.

+ 8 more paragraphs · read full section
sheaf_review.md:39Markdown · 7 words
+ 1 more refs · open all in source
TESTS
internal/cli/review_test.go:55internal/cli/review_test::TestReview_FileOutRepoBaseFlags · Go · 20 lines
func TestReview_FileOutRepoBaseFlags(t *testing.T) {
	// --base + --repo + --review file + --file-out: confirm the flag
	// wiring parses, even though the pipeline fails on missing config.
	headDir := t.TempDir()
	baseDir := t.TempDir()
	fileOut := filepath.Join(t.TempDir(), "out.md")
	rc := Review([]string{
		"--base", baseDir,
		"--repo", headDir,
		"--review", "file",
		"--file-out", fileOut,
		"--pr", "PR#unit",
	})
	// rc != 2 (would be parse error); 3 expected because config
	// loading fails on the empty repo. We just need flag parsing
	// to land.
	if rc == 2 {
		t.Errorf("flag parse failed for review --base/--repo/--review/--file-out; rc=2")
	}
}
EXAMPLES
+ 1 more examples · open all in source
WORKFLOWS

N/A

CONTRACT
command: sheaf review
short: Render a PR review comment from base + head corpora.
long: |
  Scans two checkouts of the same project (--base = PR target, --repo
  = PR head) using the same sheaf.textproto, builds a delta, and
DOCS
docs/cli/sheaf.md:58Markdown · 31 words

**Review.** `sheaf review` renders a PR-coverage-delta comment. It needs a base tree via `sheaf review --base`; `sheaf review --repo` is the PR head and `sheaf review --pr` is the reference printed in the comment header. `sheaf review --review` overrides the configured review adapter (`noop`/`file`/`gerrit`/`github`), `sheaf review --file-out` is where the `file` adapter writes, and `sheaf review --post` actually posts the comment instead of printing it. `sheaf review --config` selects the config used for both base and head.

+ 8 more paragraphs · read full section
sheaf_review.md:37Markdown · 5 words
+ 1 more refs · open all in source
TESTS
internal/cli/review_test.go:14internal/cli/review_test::TestReview_RequiresBase · Go · 7 lines
func TestReview_RequiresBase(t *testing.T) {
	// The public entry refuses to run without --base; we exercise it
	// through Review() so the flag-required branch is covered.
	if rc := Review([]string{"--repo", "."}); rc != 2 {
		t.Errorf("expected rc=2 when --base missing; got %d", rc)
	}
}
internal/cli/review_test.go:55internal/cli/review_test::TestReview_FileOutRepoBaseFlags · Go · 20 lines
func TestReview_FileOutRepoBaseFlags(t *testing.T) {
	// --base + --repo + --review file + --file-out: confirm the flag
	// wiring parses, even though the pipeline fails on missing config.
	headDir := t.TempDir()
	baseDir := t.TempDir()
	fileOut := filepath.Join(t.TempDir(), "out.md")
	rc := Review([]string{
		"--base", baseDir,
		"--repo", headDir,
		"--review", "file",
		"--file-out", fileOut,
		"--pr", "PR#unit",
	})
	// rc != 2 (would be parse error); 3 expected because config
	// loading fails on the empty repo. We just need flag parsing
	// to land.
	if rc == 2 {
		t.Errorf("flag parse failed for review --base/--repo/--review/--file-out; rc=2")
	}
}
internal/cli/review_test.go:83internal/cli/review_test::TestReview_ConfigPostFlags · Go · 20 lines
func TestReview_ConfigPostFlags(t *testing.T) {
	// Drive --config + --post through the public argv entry alongside a
	// noop review adapter. Config loading fails on the empty repo (rc=3),
	// so the run never reaches the post step — but the flags parse, which
	// attributes --config and --post without any external side effect.
	headDir := t.TempDir()
	baseDir := t.TempDir()
	rc := Review([]string{
		"--base", baseDir,
		"--repo", headDir,
		"--config", headDir + "/sheaf.textproto",
		"--review", "noop",
		"--post",
	})
	// rc == 2 would be a flag-parse error; we expect the later config-load
	// failure (rc=3) instead, proving the flags landed.
	if rc == 2 {
		t.Errorf("flag parse failed for review --config/--post; rc=2")
	}
}
EXAMPLES
+ 1 more examples · open all in source
WORKFLOWS

N/A

CONTRACT
command: sheaf review
short: Render a PR review comment from base + head corpora.
long: |
  Scans two checkouts of the same project (--base = PR target, --repo
  = PR head) using the same sheaf.textproto, builds a delta, and
DOCS
docs/cli/sheaf.md:58Markdown · 24 words

**Review.** `sheaf review` renders a PR-coverage-delta comment. It needs a base tree via `sheaf review --base`; `sheaf review --repo` is the PR head and `sheaf review --pr` is the reference printed in the comment header. `sheaf review --review` overrides the configured review adapter (`noop`/`file`/`gerrit`/`github`), `sheaf review --file-out` is where the `file` adapter writes, and `sheaf review --post` actually posts the comment instead of printing it. `sheaf review --config` selects the config used for both base and head.

+ 8 more paragraphs · read full section
sheaf_review.md:41Markdown · 5 words
TESTS
internal/cli/review_test.go:55internal/cli/review_test::TestReview_FileOutRepoBaseFlags · Go · 20 lines
func TestReview_FileOutRepoBaseFlags(t *testing.T) {
	// --base + --repo + --review file + --file-out: confirm the flag
	// wiring parses, even though the pipeline fails on missing config.
	headDir := t.TempDir()
	baseDir := t.TempDir()
	fileOut := filepath.Join(t.TempDir(), "out.md")
	rc := Review([]string{
		"--base", baseDir,
		"--repo", headDir,
		"--review", "file",
		"--file-out", fileOut,
		"--pr", "PR#unit",
	})
	// rc != 2 (would be parse error); 3 expected because config
	// loading fails on the empty repo. We just need flag parsing
	// to land.
	if rc == 2 {
		t.Errorf("flag parse failed for review --base/--repo/--review/--file-out; rc=2")
	}
}
internal/cli/review_test.go:76internal/cli/review_test::TestBuildReviewAdapter_UnknownOverride · Go · 6 lines
func TestBuildReviewAdapter_UnknownOverride(t *testing.T) {
	cfg := &configpb.Config{}
	if _, err := buildReviewAdapter(cfg, "definitely-not-an-adapter", ""); err == nil {
		t.Errorf("expected error for unknown --review value")
	}
}
internal/cli/review_test.go:83internal/cli/review_test::TestReview_ConfigPostFlags · Go · 20 lines
func TestReview_ConfigPostFlags(t *testing.T) {
	// Drive --config + --post through the public argv entry alongside a
	// noop review adapter. Config loading fails on the empty repo (rc=3),
	// so the run never reaches the post step — but the flags parse, which
	// attributes --config and --post without any external side effect.
	headDir := t.TempDir()
	baseDir := t.TempDir()
	rc := Review([]string{
		"--base", baseDir,
		"--repo", headDir,
		"--config", headDir + "/sheaf.textproto",
		"--review", "noop",
		"--post",
	})
	// rc == 2 would be a flag-parse error; we expect the later config-load
	// failure (rc=3) instead, proving the flags landed.
	if rc == 2 {
		t.Errorf("flag parse failed for review --config/--post; rc=2")
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf scan
short: Run the scan pipeline against a project and print a summary.
long: |
  Loads sheaf.textproto, dispatches every configured contract-anchor,
  test-parser, doc-parser, rendered-reference, and implements-map
  adapter, builds the cross-reference index, runs every enabled
  analyzer, and prints a per-stage timing summary plus a per-finding-kind
  histogram. The workhorse subcommand.
usage: sheaf scan [--config path] [--repo path] [--quiet]
pname: sheaf
plink: sheaf.yaml
options:
DOCS
sheaf_scan.md:1Markdown · 491 words
docs/config.md:94Markdown · 31 words

Parse-time and resolve-time errors abort startup with a path-prefixed message (`contract_anchor[1].argh.crate_roots: missing required field`). Probe-time warnings appear in `sheaf doctor` output and at the top of `sheaf scan` runs but do not abort.

+ 190 more paragraphs · read full section
docs/config.md:446Markdown · 29 words

**Severity meanings.** `INFO` is reported but never blocks; `WARNING` increments the warning count (`sheaf scan` exit code 1 if any); `ERROR` increments the error count (exit code 2). The PR-bot routes severity into comment-section ordering (errors first).

+ 131 more paragraphs · read full section
+ 8 more refs · open all in source
TESTS
internal/cli/scan_test.go:13internal/cli/scan_test::TestRunScan_FixtureProject · Go · 19 lines
func TestRunScan_FixtureProject(t *testing.T) {
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runScan(&out, &errOut, "", dir, false)
	if rc != 0 {
		t.Fatalf("runScan returned %d; stderr=%s", rc, errOut.String())
	}
	got := out.String()
	for _, want := range []string{
		"Contract elements: 0",
		"Test cases:        1",
		"Doc claims:",
		"FooTest.BarReturnsTrue",
	} {
		if !strings.Contains(got, want) {
			t.Errorf("output missing %q\n--- got ---\n%s", want, got)
		}
	}
}
internal/cli/scan_test.go:33internal/cli/scan_test::TestRunScan_MissingConfig · Go · 8 lines
func TestRunScan_MissingConfig(t *testing.T) {
	dir := t.TempDir()
	var out, errOut bytes.Buffer
	rc := runScan(&out, &errOut, "", dir, false)
	if rc == 0 {
		t.Errorf("expected non-zero exit on missing config; out=%s err=%s", out.String(), errOut.String())
	}
}
internal/cli/scan_test.go:42internal/cli/scan_test::TestRunScan_RepoConfigFlags · Go · 12 lines
func TestRunScan_RepoConfigFlags(t *testing.T) {
	// Exercise the --repo + --config wiring: a config path provided
	// explicitly should be honored even when --repo names a directory
	// that itself contains no sheaf.textproto.
	dir := setupFixture(t)
	otherRepo := t.TempDir()
	var out, errOut bytes.Buffer
	rc := runScan(&out, &errOut, dir+"/sheaf.textproto", otherRepo, true)
	if rc != 0 {
		t.Fatalf("runScan(--config) returned %d; stderr=%s", rc, errOut.String())
	}
}
+ 2 more tests · open all in source
EXAMPLES
+ 2 more examples · open all in source
WORKFLOWS

N/A

CONTRACT
command: sheaf scan
short: Run the scan pipeline against a project and print a summary.
long: |
  Loads sheaf.textproto, dispatches every configured contract-anchor,
  test-parser, doc-parser, rendered-reference, and implements-map
  adapter, builds the cross-reference index, runs every enabled
  analyzer, and prints a per-stage timing summary plus a per-finding-kind
  histogram. The workhorse subcommand.
usage: sheaf scan [--config path] [--repo path] [--quiet]
pname: sheaf
plink: sheaf.yaml
options:
DOCS
docs/cli/sheaf.md:46Markdown · 27 words

**Scan.** A bare `sheaf scan` runs against `<repo>/sheaf.textproto`. Point `sheaf scan --config` at a config that lives elsewhere, set the project root with `sheaf scan --repo`, and pass `sheaf scan --quiet` to drop the per-adapter sample blocks when you only want the corpus summary.

+ 14 more paragraphs · read full section
sheaf_scan.md:30Markdown · 5 words
TESTS
internal/cli/scan_test.go:42internal/cli/scan_test::TestRunScan_RepoConfigFlags · Go · 12 lines
func TestRunScan_RepoConfigFlags(t *testing.T) {
	// Exercise the --repo + --config wiring: a config path provided
	// explicitly should be honored even when --repo names a directory
	// that itself contains no sheaf.textproto.
	dir := setupFixture(t)
	otherRepo := t.TempDir()
	var out, errOut bytes.Buffer
	rc := runScan(&out, &errOut, dir+"/sheaf.textproto", otherRepo, true)
	if rc != 0 {
		t.Fatalf("runScan(--config) returned %d; stderr=%s", rc, errOut.String())
	}
}
internal/cli/scan_test.go:67internal/cli/scan_test::TestScan_ArgvFlagParsing · Go · 10 lines
func TestScan_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so --repo and --config are parsed from
	// the command line. The runScan tests name --config in a string only
	// incidentally and --repo only in a comment, so --repo never gets
	// attributed; this exercises the real flag wiring end to end.
	dir := setupFixture(t)
	if rc := Scan([]string{"--config", dir + "/sheaf.textproto", "--repo", dir, "--quiet"}); rc != 0 {
		t.Errorf("Scan(--config,--repo,--quiet) returned %d; want 0", rc)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf scan
short: Run the scan pipeline against a project and print a summary.
long: |
  Loads sheaf.textproto, dispatches every configured contract-anchor,
  test-parser, doc-parser, rendered-reference, and implements-map
  adapter, builds the cross-reference index, runs every enabled
  analyzer, and prints a per-stage timing summary plus a per-finding-kind
  histogram. The workhorse subcommand.
usage: sheaf scan [--config path] [--repo path] [--quiet]
pname: sheaf
plink: sheaf.yaml
options:
DOCS
docs/cli/sheaf.md:46Markdown · 31 words

**Scan.** A bare `sheaf scan` runs against `<repo>/sheaf.textproto`. Point `sheaf scan --config` at a config that lives elsewhere, set the project root with `sheaf scan --repo`, and pass `sheaf scan --quiet` to drop the per-adapter sample blocks when you only want the corpus summary.

+ 14 more paragraphs · read full section
sheaf_scan.md:32Markdown · 5 words
TESTS
internal/cli/scan_test.go:55internal/cli/scan_test::TestRunScan_QuietSuppressesSamples · Go · 11 lines
func TestRunScan_QuietSuppressesSamples(t *testing.T) {
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runScan(&out, &errOut, "", dir, true /* quiet */)
	if rc != 0 {
		t.Fatalf("runScan returned %d; stderr=%s", rc, errOut.String())
	}
	if strings.Contains(out.String(), "Sample tests:") || strings.Contains(out.String(), "Sample doc mentions:") {
		t.Errorf("--quiet did not suppress sample blocks; got %s", out.String())
	}
}
internal/cli/scan_test.go:67internal/cli/scan_test::TestScan_ArgvFlagParsing · Go · 10 lines
func TestScan_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so --repo and --config are parsed from
	// the command line. The runScan tests name --config in a string only
	// incidentally and --repo only in a comment, so --repo never gets
	// attributed; this exercises the real flag wiring end to end.
	dir := setupFixture(t)
	if rc := Scan([]string{"--config", dir + "/sheaf.textproto", "--repo", dir, "--quiet"}); rc != 0 {
		t.Errorf("Scan(--config,--repo,--quiet) returned %d; want 0", rc)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf scan
short: Run the scan pipeline against a project and print a summary.
long: |
  Loads sheaf.textproto, dispatches every configured contract-anchor,
  test-parser, doc-parser, rendered-reference, and implements-map
  adapter, builds the cross-reference index, runs every enabled
  analyzer, and prints a per-stage timing summary plus a per-finding-kind
  histogram. The workhorse subcommand.
usage: sheaf scan [--config path] [--repo path] [--quiet]
pname: sheaf
plink: sheaf.yaml
options:
DOCS
docs/cli/sheaf.md:46Markdown · 31 words

**Scan.** A bare `sheaf scan` runs against `<repo>/sheaf.textproto`. Point `sheaf scan --config` at a config that lives elsewhere, set the project root with `sheaf scan --repo`, and pass `sheaf scan --quiet` to drop the per-adapter sample blocks when you only want the corpus summary.

+ 14 more paragraphs · read full section
sheaf_scan.md:31Markdown · 16 words
TESTS
internal/cli/scan_test.go:67internal/cli/scan_test::TestScan_ArgvFlagParsing · Go · 10 lines
func TestScan_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so --repo and --config are parsed from
	// the command line. The runScan tests name --config in a string only
	// incidentally and --repo only in a comment, so --repo never gets
	// attributed; this exercises the real flag wiring end to end.
	dir := setupFixture(t)
	if rc := Scan([]string{"--config", dir + "/sheaf.textproto", "--repo", dir, "--quiet"}); rc != 0 {
		t.Errorf("Scan(--config,--repo,--quiet) returned %d; want 0", rc)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf serve
short: Start the MCP server.
long: |
  Run the ingest → index pipeline once and then keep the corpus live
  behind an MCP server. Coding agents and the scanner binary consume
  the server's contract-element lookup, coverage-profile lookup,
  worked-example retrieval, library_snapshot, and review_pr ops.
usage: sheaf serve [--config path] [--repo path] [--bind host] [--port n]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
DOCS
sheaf_serve.md:1Markdown · 291 words

- [`sheaf serve`](sheaf_serve.md) — the MCP server the scanner connects to. - [`sheaf snapshot`](sheaf_snapshot.md) — the preferred, in-process way to persist a Snapshot JSON (replaces `scanner --snapshot-out`). - [`sheaf render`](sheaf_render.md) — the preferred, in-process way to render a saved Snapshot JSON.

docs/config.md:1189Markdown · 30 words

- **C5.** Hot reload on config change during `sheaf serve`: nice to have, v2. - **C6.** mTLS support for the MCP server (currently `BEARER` is the only non-NONE auth). Defer until pulled. - **C7.** `analyzer.config { key, *_value }` free-form fallback: should sustained use of free-form keys for the same analyzer auto-promote into a typed oneof case at code-gen time? Probably overengineering; just promote manually when patterns emerge.

+ 16 more refs · open all in source
TESTS
internal/cli/serve_test.go:12internal/cli/serve_test::TestServe_FlagParseFailure · Go · 7 lines
func TestServe_FlagParseFailure(t *testing.T) {
	// Bad flag: ContinueOnError + flag.Parse returns 2 from the
	// public entry point. Use a value the flag set rejects.
	if rc := Serve([]string{"--unknown-flag"}); rc != 2 {
		t.Errorf("expected rc=2 on bad flag; got %d", rc)
	}
}
internal/cli/serve_test.go:20internal/cli/serve_test::TestServe_BindPortRepoConfigFlags · Go · 11 lines
func TestServe_BindPortRepoConfigFlags(t *testing.T) {
	// Drive the public Serve entry with --bind/--port/--config/--repo
	// against a directory that has no sheaf.textproto. The pipeline
	// fails early on config load (rc=3); the assertion here is that
	// the binding flags parse without error.
	dir := t.TempDir()
	rc := Serve([]string{"--bind", "127.0.0.1", "--port", "0", "--repo", dir, "--config", dir + "/missing.textproto"})
	if rc == 0 {
		t.Errorf("expected non-zero exit with missing config; got 0")
	}
}
internal/cli/serve_test.go:32internal/cli/serve_test::TestServe_MissingConfig · Go · 6 lines
func TestServe_MissingConfig(t *testing.T) {
	dir := t.TempDir()
	if rc := Serve([]string{"--repo", dir}); rc == 0 {
		t.Errorf("expected non-zero exit on missing config")
	}
}
EXAMPLES
+ 1 more examples · open all in source
WORKFLOWS

N/A

CONTRACT
command: sheaf serve
short: Start the MCP server.
long: |
  Run the ingest → index pipeline once and then keep the corpus live
  behind an MCP server. Coding agents and the scanner binary consume
  the server's contract-element lookup, coverage-profile lookup,
  worked-example retrieval, library_snapshot, and review_pr ops.
usage: sheaf serve [--config path] [--repo path] [--bind host] [--port n]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
DOCS
docs/cli/sheaf.md:56Markdown · 26 words

**Serve.** `sheaf serve` starts the MCP server. `sheaf serve --bind` sets the listen address (default `127.0.0.1`) and `sheaf serve --config` selects the config whose corpus is served.

+ 9 more paragraphs · read full section
docs/config.md:116Markdown · 26 words

value, the flag wins. Example: `sheaf serve --bind` / `--port` override `mcp_server.bind` / `mcp_server.port` (`internal/cli/extra.go:491`). - **Credentials are environment-only.** API keys and tokens are never read from the config file. `ANTHROPIC_API_KEY` has no config field at all; the `*_token_env` fields hold the *name* of an env var, not the secret. See §3.6. - **One config-beats-env exception — the LLM model.** The model tag resolves config before env: an explicit `--model` / `llm.model` wins, and `ANTHROPIC_MODEL` is consulted only when neither is set, ahead of the per-backend defau…

+ 184 more paragraphs · read full section
sheaf_serve.md:32Markdown · 2 words
+ 1 more refs · open all in source
TESTS
internal/cli/serve_test.go:20internal/cli/serve_test::TestServe_BindPortRepoConfigFlags · Go · 11 lines
func TestServe_BindPortRepoConfigFlags(t *testing.T) {
	// Drive the public Serve entry with --bind/--port/--config/--repo
	// against a directory that has no sheaf.textproto. The pipeline
	// fails early on config load (rc=3); the assertion here is that
	// the binding flags parse without error.
	dir := t.TempDir()
	rc := Serve([]string{"--bind", "127.0.0.1", "--port", "0", "--repo", dir, "--config", dir + "/missing.textproto"})
	if rc == 0 {
		t.Errorf("expected non-zero exit with missing config; got 0")
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf serve
short: Start the MCP server.
long: |
  Run the ingest → index pipeline once and then keep the corpus live
  behind an MCP server. Coding agents and the scanner binary consume
  the server's contract-element lookup, coverage-profile lookup,
  worked-example retrieval, library_snapshot, and review_pr ops.
usage: sheaf serve [--config path] [--repo path] [--bind host] [--port n]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
DOCS
docs/cli/sheaf.md:56Markdown · 25 words

**Serve.** `sheaf serve` starts the MCP server. `sheaf serve --bind` sets the listen address (default `127.0.0.1`) and `sheaf serve --config` selects the config whose corpus is served.

+ 9 more paragraphs · read full section
sheaf_serve.md:30Markdown · 5 words
TESTS
internal/cli/serve_test.go:20internal/cli/serve_test::TestServe_BindPortRepoConfigFlags · Go · 11 lines
func TestServe_BindPortRepoConfigFlags(t *testing.T) {
	// Drive the public Serve entry with --bind/--port/--config/--repo
	// against a directory that has no sheaf.textproto. The pipeline
	// fails early on config load (rc=3); the assertion here is that
	// the binding flags parse without error.
	dir := t.TempDir()
	rc := Serve([]string{"--bind", "127.0.0.1", "--port", "0", "--repo", dir, "--config", dir + "/missing.textproto"})
	if rc == 0 {
		t.Errorf("expected non-zero exit with missing config; got 0")
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf serve
short: Start the MCP server.
long: |
  Run the ingest → index pipeline once and then keep the corpus live
  behind an MCP server. Coding agents and the scanner binary consume
  the server's contract-element lookup, coverage-profile lookup,
  worked-example retrieval, library_snapshot, and review_pr ops.
usage: sheaf serve [--config path] [--repo path] [--bind host] [--port n]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
TESTS
internal/cli/serve_test.go:20internal/cli/serve_test::TestServe_BindPortRepoConfigFlags · Go · 11 lines
func TestServe_BindPortRepoConfigFlags(t *testing.T) {
	// Drive the public Serve entry with --bind/--port/--config/--repo
	// against a directory that has no sheaf.textproto. The pipeline
	// fails early on config load (rc=3); the assertion here is that
	// the binding flags parse without error.
	dir := t.TempDir()
	rc := Serve([]string{"--bind", "127.0.0.1", "--port", "0", "--repo", dir, "--config", dir + "/missing.textproto"})
	if rc == 0 {
		t.Errorf("expected non-zero exit with missing config; got 0")
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf serve
short: Start the MCP server.
long: |
  Run the ingest → index pipeline once and then keep the corpus live
  behind an MCP server. Coding agents and the scanner binary consume
  the server's contract-element lookup, coverage-profile lookup,
  worked-example retrieval, library_snapshot, and review_pr ops.
usage: sheaf serve [--config path] [--repo path] [--bind host] [--port n]
pname: sheaf
plink: sheaf.yaml
options:
  - option: config
TESTS
internal/cli/serve_test.go:20internal/cli/serve_test::TestServe_BindPortRepoConfigFlags · Go · 11 lines
func TestServe_BindPortRepoConfigFlags(t *testing.T) {
	// Drive the public Serve entry with --bind/--port/--config/--repo
	// against a directory that has no sheaf.textproto. The pipeline
	// fails early on config load (rc=3); the assertion here is that
	// the binding flags parse without error.
	dir := t.TempDir()
	rc := Serve([]string{"--bind", "127.0.0.1", "--port", "0", "--repo", dir, "--config", dir + "/missing.textproto"})
	if rc == 0 {
		t.Errorf("expected non-zero exit with missing config; got 0")
	}
}
internal/cli/serve_test.go:32internal/cli/serve_test::TestServe_MissingConfig · Go · 6 lines
func TestServe_MissingConfig(t *testing.T) {
	dir := t.TempDir()
	if rc := Serve([]string{"--repo", dir}); rc == 0 {
		t.Errorf("expected non-zero exit on missing config")
	}
}
EXAMPLES
+ 1 more examples · open all in source
WORKFLOWS

N/A

CONTRACT
command: sheaf snapshot
short: Emit a library's Snapshot JSON (in-process; pipe to scanner --from-snapshot).
DOCS
sheaf_snapshot.md:1Markdown · 289 words
docs/cli/sheaf.md:40Markdown · 28 words

`sheaf scan`, `sheaf gaps`, `sheaf coverage`, `sheaf report`, `sheaf snapshot`, `sheaf serve`, and `sheaf review` all run the full pipeline (config load → adapter dispatch → indexer → analyzers) before producing their output. `sheaf render` and `sheaf review-html` are pipeline-free — they render from a Snapshot JSON / `delta.json` that an earlier pipeline run already produced — as are `sheaf doctor`, `sheaf version`, and `sheaf init`.

+ 16 more paragraphs · read full section
docs/cli/workflows.md:75Markdown · 27 words

Saved snapshots let you re-render without restanding the server. The preferred path is fully in-process — no `sheaf serve`, no `scanner` — using `sheaf snapshot` to persist the Snapshot JSON and `sheaf render --from-snapshot` to render it:

+ 13 more paragraphs · read full section
+ 7 more refs · open all in source
TESTS
internal/cli/snapshot_test.go:15internal/cli/snapshot_test::TestRunSnapshot_RequiresLibrary · Go · 8 lines
func TestRunSnapshot_RequiresLibrary(t *testing.T) {
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runSnapshot(&out, &errOut, "", dir, "", "", "")
	if rc != 2 {
		t.Errorf("expected rc=2 when --library is empty; got %d", rc)
	}
}
internal/cli/snapshot_test.go:24internal/cli/snapshot_test::TestRunSnapshot_StdoutEmitsVersionedJSON · Go · 22 lines
func TestRunSnapshot_StdoutEmitsVersionedJSON(t *testing.T) {
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runSnapshot(&out, &errOut, "", dir, "fuchsia.io", "", "")
	if rc != 0 {
		t.Fatalf("runSnapshot returned %d; stderr=%s", rc, errOut.String())
	}
	var snap struct {
		SchemaVersion int              `json:"schema_version"`
		Library       string           `json:"library"`
		Elements      []map[string]any `json:"elements"`
	}
	if err := json.Unmarshal(out.Bytes(), &snap); err != nil {
		t.Fatalf("snapshot stdout is not valid JSON: %v", err)
	}
	if snap.SchemaVersion != librarysnapshot.SchemaVersion {
		t.Errorf("schema_version = %d; want %d", snap.SchemaVersion, librarysnapshot.SchemaVersion)
	}
	if snap.Library != "fuchsia.io" {
		t.Errorf("library = %q; want %q", snap.Library, "fuchsia.io")
	}
}
internal/cli/snapshot_test.go:47internal/cli/snapshot_test::TestRunSnapshot_OutWritesFile · Go · 22 lines
func TestRunSnapshot_OutWritesFile(t *testing.T) {
	dir := setupFixture(t)
	outPath := filepath.Join(t.TempDir(), "nested", "snap.json")
	var out, errOut bytes.Buffer
	rc := runSnapshot(&out, &errOut, "", dir, "fuchsia.io", "", outPath)
	if rc != 0 {
		t.Fatalf("runSnapshot(--out) returned %d; stderr=%s", rc, errOut.String())
	}
	data, err := os.ReadFile(outPath)
	if err != nil {
		t.Fatalf("snapshot file not written: %v", err)
	}
	var snap struct {
		SchemaVersion int `json:"schema_version"`
	}
	if err := json.Unmarshal(data, &snap); err != nil {
		t.Fatalf("snapshot file is not valid JSON: %v", err)
	}
	if snap.SchemaVersion != librarysnapshot.SchemaVersion {
		t.Errorf("schema_version = %d; want %d", snap.SchemaVersion, librarysnapshot.SchemaVersion)
	}
}
+ 2 more tests · open all in source
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf snapshot
short: Emit a library's Snapshot JSON (in-process; pipe to scanner --from-snapshot).
DOCS
docs/cli/sheaf.md:62Markdown · 24 words

**Snapshot.** `sheaf snapshot` emits a library's Snapshot JSON for the server-free render path. `sheaf snapshot --library` names the library (a comma-separated list rolls several into one snapshot, labelled by `sheaf snapshot --library-label`), `sheaf snapshot --out` is the destination file, and `sheaf snapshot --config` / `sheaf snapshot --repo` locate the project.

+ 6 more paragraphs · read full section
sheaf_snapshot.md:41Markdown · 5 words
TESTS
internal/cli/snapshot_test.go:79internal/cli/snapshot_test::TestSnapshot_ArgvFlagParsing · Go · 21 lines
func TestSnapshot_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so --config / --repo / --library-label
	// are parsed from the command line. The runSnapshot tests pass these
	// positionally, leaving those three flags unattributed in the
	// self-scan even though they're exercised here.
	dir := setupFixture(t)
	outPath := filepath.Join(t.TempDir(), "snap.json")
	rc := Snapshot([]string{
		"--config", dir + "/sheaf.textproto",
		"--repo", dir,
		"--library", "fuchsia.io",
		"--library-label", "demo",
		"--out", outPath,
	})
	if rc != 0 {
		t.Fatalf("Snapshot(--config/--repo/--library/--library-label/--out) returned %d; want 0", rc)
	}
	if _, err := os.Stat(outPath); err != nil {
		t.Errorf("snapshot via argv didn't write --out file: %v", err)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf snapshot
short: Emit a library's Snapshot JSON (in-process; pipe to scanner --from-snapshot).
DOCS
docs/cli/sheaf.md:62Markdown · 27 words

**Snapshot.** `sheaf snapshot` emits a library's Snapshot JSON for the server-free render path. `sheaf snapshot --library` names the library (a comma-separated list rolls several into one snapshot, labelled by `sheaf snapshot --library-label`), `sheaf snapshot --out` is the destination file, and `sheaf snapshot --config` / `sheaf snapshot --repo` locate the project.

+ 6 more paragraphs · read full section
sheaf_snapshot.md:43Markdown · 9 words
+ 1 more refs · open all in source
TESTS
internal/cli/snapshot_test.go:15internal/cli/snapshot_test::TestRunSnapshot_RequiresLibrary · Go · 8 lines
func TestRunSnapshot_RequiresLibrary(t *testing.T) {
	dir := setupFixture(t)
	var out, errOut bytes.Buffer
	rc := runSnapshot(&out, &errOut, "", dir, "", "", "")
	if rc != 2 {
		t.Errorf("expected rc=2 when --library is empty; got %d", rc)
	}
}
internal/cli/snapshot_test.go:79internal/cli/snapshot_test::TestSnapshot_ArgvFlagParsing · Go · 21 lines
func TestSnapshot_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so --config / --repo / --library-label
	// are parsed from the command line. The runSnapshot tests pass these
	// positionally, leaving those three flags unattributed in the
	// self-scan even though they're exercised here.
	dir := setupFixture(t)
	outPath := filepath.Join(t.TempDir(), "snap.json")
	rc := Snapshot([]string{
		"--config", dir + "/sheaf.textproto",
		"--repo", dir,
		"--library", "fuchsia.io",
		"--library-label", "demo",
		"--out", outPath,
	})
	if rc != 0 {
		t.Fatalf("Snapshot(--config/--repo/--library/--library-label/--out) returned %d; want 0", rc)
	}
	if _, err := os.Stat(outPath); err != nil {
		t.Errorf("snapshot via argv didn't write --out file: %v", err)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf snapshot
short: Emit a library's Snapshot JSON (in-process; pipe to scanner --from-snapshot).
DOCS
docs/cli/sheaf.md:62Markdown · 26 words

**Snapshot.** `sheaf snapshot` emits a library's Snapshot JSON for the server-free render path. `sheaf snapshot --library` names the library (a comma-separated list rolls several into one snapshot, labelled by `sheaf snapshot --library-label`), `sheaf snapshot --out` is the destination file, and `sheaf snapshot --config` / `sheaf snapshot --repo` locate the project.

+ 6 more paragraphs · read full section
sheaf_snapshot.md:44Markdown · 10 words
TESTS
internal/cli/snapshot_test.go:79internal/cli/snapshot_test::TestSnapshot_ArgvFlagParsing · Go · 21 lines
func TestSnapshot_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so --config / --repo / --library-label
	// are parsed from the command line. The runSnapshot tests pass these
	// positionally, leaving those three flags unattributed in the
	// self-scan even though they're exercised here.
	dir := setupFixture(t)
	outPath := filepath.Join(t.TempDir(), "snap.json")
	rc := Snapshot([]string{
		"--config", dir + "/sheaf.textproto",
		"--repo", dir,
		"--library", "fuchsia.io",
		"--library-label", "demo",
		"--out", outPath,
	})
	if rc != 0 {
		t.Fatalf("Snapshot(--config/--repo/--library/--library-label/--out) returned %d; want 0", rc)
	}
	if _, err := os.Stat(outPath); err != nil {
		t.Errorf("snapshot via argv didn't write --out file: %v", err)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf snapshot
short: Emit a library's Snapshot JSON (in-process; pipe to scanner --from-snapshot).
DOCS

1. **Server-backed (default).** Connect to `--server`, list libraries, prompt for a selection (skipped when `--library` is set), pull a `library_snapshot`, and render. `--snapshot-out <path>` persists the snapshot for offline replay, but is **deprecated** — prefer `sheaf snapshot --out`, which produces the same JSON in-process without a server. 2. **Offline (`--from-snapshot <path>`).** Skip the server entirely and render directly from a previously-saved snapshot JSON. Use when iterating on the report template, when the source server is no longer running, or when you need a hermetic build.

+ 14 more paragraphs · read full section
docs/cli/sheaf.md:62Markdown · 25 words

**Snapshot.** `sheaf snapshot` emits a library's Snapshot JSON for the server-free render path. `sheaf snapshot --library` names the library (a comma-separated list rolls several into one snapshot, labelled by `sheaf snapshot --library-label`), `sheaf snapshot --out` is the destination file, and `sheaf snapshot --config` / `sheaf snapshot --repo` locate the project.

+ 6 more paragraphs · read full section

| `--snapshot-out <path>` | `""` | **DEPRECATED** — persist the fetched snapshot to disk for later replay. Prefer `sheaf snapshot --out` (in-process, no server). | | `--from-snapshot <path>` | `""` | Render from a saved snapshot; skips the server connect entirely. |

+ 12 more paragraphs · read full section
+ 3 more refs · open all in source
TESTS
internal/cli/snapshot_test.go:47internal/cli/snapshot_test::TestRunSnapshot_OutWritesFile · Go · 22 lines
func TestRunSnapshot_OutWritesFile(t *testing.T) {
	dir := setupFixture(t)
	outPath := filepath.Join(t.TempDir(), "nested", "snap.json")
	var out, errOut bytes.Buffer
	rc := runSnapshot(&out, &errOut, "", dir, "fuchsia.io", "", outPath)
	if rc != 0 {
		t.Fatalf("runSnapshot(--out) returned %d; stderr=%s", rc, errOut.String())
	}
	data, err := os.ReadFile(outPath)
	if err != nil {
		t.Fatalf("snapshot file not written: %v", err)
	}
	var snap struct {
		SchemaVersion int `json:"schema_version"`
	}
	if err := json.Unmarshal(data, &snap); err != nil {
		t.Fatalf("snapshot file is not valid JSON: %v", err)
	}
	if snap.SchemaVersion != librarysnapshot.SchemaVersion {
		t.Errorf("schema_version = %d; want %d", snap.SchemaVersion, librarysnapshot.SchemaVersion)
	}
}
internal/cli/snapshot_test.go:79internal/cli/snapshot_test::TestSnapshot_ArgvFlagParsing · Go · 21 lines
func TestSnapshot_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so --config / --repo / --library-label
	// are parsed from the command line. The runSnapshot tests pass these
	// positionally, leaving those three flags unattributed in the
	// self-scan even though they're exercised here.
	dir := setupFixture(t)
	outPath := filepath.Join(t.TempDir(), "snap.json")
	rc := Snapshot([]string{
		"--config", dir + "/sheaf.textproto",
		"--repo", dir,
		"--library", "fuchsia.io",
		"--library-label", "demo",
		"--out", outPath,
	})
	if rc != 0 {
		t.Fatalf("Snapshot(--config/--repo/--library/--library-label/--out) returned %d; want 0", rc)
	}
	if _, err := os.Stat(outPath); err != nil {
		t.Errorf("snapshot via argv didn't write --out file: %v", err)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf snapshot
short: Emit a library's Snapshot JSON (in-process; pipe to scanner --from-snapshot).
DOCS
docs/cli/sheaf.md:62Markdown · 27 words

**Snapshot.** `sheaf snapshot` emits a library's Snapshot JSON for the server-free render path. `sheaf snapshot --library` names the library (a comma-separated list rolls several into one snapshot, labelled by `sheaf snapshot --library-label`), `sheaf snapshot --out` is the destination file, and `sheaf snapshot --config` / `sheaf snapshot --repo` locate the project.

+ 6 more paragraphs · read full section
sheaf_snapshot.md:42Markdown · 3 words
TESTS
internal/cli/snapshot_test.go:79internal/cli/snapshot_test::TestSnapshot_ArgvFlagParsing · Go · 21 lines
func TestSnapshot_ArgvFlagParsing(t *testing.T) {
	// Drive the public argv entry so --config / --repo / --library-label
	// are parsed from the command line. The runSnapshot tests pass these
	// positionally, leaving those three flags unattributed in the
	// self-scan even though they're exercised here.
	dir := setupFixture(t)
	outPath := filepath.Join(t.TempDir(), "snap.json")
	rc := Snapshot([]string{
		"--config", dir + "/sheaf.textproto",
		"--repo", dir,
		"--library", "fuchsia.io",
		"--library-label", "demo",
		"--out", outPath,
	})
	if rc != 0 {
		t.Fatalf("Snapshot(--config/--repo/--library/--library-label/--out) returned %d; want 0", rc)
	}
	if _, err := os.Stat(outPath); err != nil {
		t.Errorf("snapshot via argv didn't write --out file: %v", err)
	}
}
EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf verify
short: Adversarially check a snapshot's top-line numbers (vs the join + disk) before a report is shown.
DOCS
sheaf_verify.md:1Markdown · 583 words
README.md:32Markdown · 29 words

> **Onboard your repo with the `sheaf-onboard` skill (recommended).** Your agent does the reconnaissance and config, runs the scan, then runs `sheaf verify` to check every headline number against disk *before* it shows you the report, so your spot-check is a confirmation, not a discovery. If config alone can't reach a surface, it offers a `sheaf-build-adapter` handoff instead of quietly under-counting. > > ```sh > docs/examples/sheaf-onboard/install.sh # then, in Claude / Cursor / Cline: /sheaf-onboard > ``` > > Any agentic CLI (Gemini, Codex) drives it via [`AGENTS.md`](docs/examples/sheaf-on…

+ 28 more paragraphs · read full section
docs/cli/sheaf.md:66Markdown · 25 words

**Verify.** `sheaf verify` adversarially re-checks a scan's headline numbers before the report is shown. It reads a snapshot via `sheaf verify --from-snapshot` and reconciles it — or, as a one-shot, `sheaf verify --config` builds the snapshot in-process (with `sheaf verify --library`) and verifies it in a single step. `sheaf verify --repo` points at the source tree, `sheaf verify --ecosystem` selects the view shape, and `sheaf verify --low-coverage-threshold` sets the suspicion line. `sheaf verify --disk` runs the on-disk oracle — `sheaf verify --check-urls` adds dead-link resolution, `she…

+ 4 more paragraphs · read full section
+ 1 more refs · open all in source
TESTS
internal/verify/verify_test.go:55internal/verify/verify_test::TestReconcileTests_MismatchIsError · Go · 16 lines
func TestReconcileTests_MismatchIsError(t *testing.T) {
	rd := &scanner.ReportData{
		Total:     2,
		TestCount: 1,
		Methods:   []scanner.MethodRow{{Name: "a", Test: 1}, {Name: "b", Test: 0}},
	}
	profByID := map[string]map[string]any{
		"a": testProfile(0),
		"b": testProfile(0),
	}
	rep := &Report{}
	reconcileTests(rep, rd, profByID)
	if !hasCategory(rep, CatReconcile) {
		t.Fatalf("expected a reconcile finding, got %+v", rep.Findings)
	}
}
internal/verify/verify_test.go:72internal/verify/verify_test::TestReconcileTests_ConsistentIsClean · Go · 16 lines
func TestReconcileTests_ConsistentIsClean(t *testing.T) {
	rd := &scanner.ReportData{
		Total:     2,
		TestCount: 1,
		Methods:   []scanner.MethodRow{{Name: "a", Test: 3}, {Name: "b", Test: 0}},
	}
	profByID := map[string]map[string]any{
		"a": testProfile(3, "a_test.go", "a2_test.go"),
		"b": testProfile(0),
	}
	rep := &Report{}
	reconcileTests(rep, rd, profByID)
	if hasCategory(rep, CatReconcile) {
		t.Fatalf("expected no reconcile finding, got %+v", rep.Findings)
	}
}
internal/verify/verify_test.go:93internal/verify/verify_test::TestDecompose_ZeroSurfaceWarnsNotErrors · Go · 18 lines
func TestDecompose_ZeroSurfaceWarnsNotErrors(t *testing.T) {
	rd := &scanner.ReportData{
		Total: 48, ShowTestTile: true,
		TestCount: 10, TestPct: 21,
		PrimaryTotal: 11, PrimaryNoun: "Commands", PrimaryTestN: 10, PrimaryTestPct: 91,
		ModifierTotal: 37, ModifierNoun: "Flags", ModifierTestN: 0, ModifierTestPct: 0,
	}
	rep := &Report{}
	decomposeTiers(rep, rd, 0.15)
	if !hasCategoryTier(rep, CatZeroSurface, "modifier") {
		t.Fatalf("expected zero_surface on the modifier tier, got %+v", rep.Findings)
	}
	for _, f := range rep.Findings {
		if f.Category == CatZeroSurface && f.Severity != SeverityWarn {
			t.Fatalf("a 0%% surface must be a WARNING pre-disk, got severity %q", f.Severity)
		}
	}
}
+ 8 more tests · open all in source
EXAMPLES
+ 2 more examples · open all in source
WORKFLOWS

N/A

CONTRACT
command: sheaf verify
short: Adversarially check a snapshot's top-line numbers (vs the join + disk) before a report is shown.
DOCS
docs/cli/sheaf.md:66Markdown · 25 words

**Verify.** `sheaf verify` adversarially re-checks a scan's headline numbers before the report is shown. It reads a snapshot via `sheaf verify --from-snapshot` and reconciles it — or, as a one-shot, `sheaf verify --config` builds the snapshot in-process (with `sheaf verify --library`) and verifies it in a single step. `sheaf verify --repo` points at the source tree, `sheaf verify --ecosystem` selects the view shape, and `sheaf verify --low-coverage-threshold` sets the suspicion line. `sheaf verify --disk` runs the on-disk oracle — `sheaf verify --check-urls` adds dead-link resolution, `she…

+ 4 more paragraphs · read full section
sheaf_verify.md:59Markdown · 11 words
TESTS

N/A

EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf verify
short: Adversarially check a snapshot's top-line numbers (vs the join + disk) before a report is shown.
DOCS
docs/cli/sheaf.md:66Markdown · 27 words

**Verify.** `sheaf verify` adversarially re-checks a scan's headline numbers before the report is shown. It reads a snapshot via `sheaf verify --from-snapshot` and reconciles it — or, as a one-shot, `sheaf verify --config` builds the snapshot in-process (with `sheaf verify --library`) and verifies it in a single step. `sheaf verify --repo` points at the source tree, `sheaf verify --ecosystem` selects the view shape, and `sheaf verify --low-coverage-threshold` sets the suspicion line. `sheaf verify --disk` runs the on-disk oracle — `sheaf verify --check-urls` adds dead-link resolution, `she…

+ 4 more paragraphs · read full section
sheaf_verify.md:53Markdown · 23 words
TESTS

N/A

EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf verify
short: Adversarially check a snapshot's top-line numbers (vs the join + disk) before a report is shown.
DOCS
docs/cli/sheaf.md:66Markdown · 24 words

**Verify.** `sheaf verify` adversarially re-checks a scan's headline numbers before the report is shown. It reads a snapshot via `sheaf verify --from-snapshot` and reconciles it — or, as a one-shot, `sheaf verify --config` builds the snapshot in-process (with `sheaf verify --library`) and verifies it in a single step. `sheaf verify --repo` points at the source tree, `sheaf verify --ecosystem` selects the view shape, and `sheaf verify --low-coverage-threshold` sets the suspicion line. `sheaf verify --disk` runs the on-disk oracle — `sheaf verify --check-urls` adds dead-link resolution, `she…

+ 4 more paragraphs · read full section
sheaf_verify.md:58Markdown · 6 words
TESTS

N/A

EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf verify
short: Adversarially check a snapshot's top-line numbers (vs the join + disk) before a report is shown.
DOCS
docs/cli/sheaf.md:66Markdown · 28 words

**Verify.** `sheaf verify` adversarially re-checks a scan's headline numbers before the report is shown. It reads a snapshot via `sheaf verify --from-snapshot` and reconciles it — or, as a one-shot, `sheaf verify --config` builds the snapshot in-process (with `sheaf verify --library`) and verifies it in a single step. `sheaf verify --repo` points at the source tree, `sheaf verify --ecosystem` selects the view shape, and `sheaf verify --low-coverage-threshold` sets the suspicion line. `sheaf verify --disk` runs the on-disk oracle — `sheaf verify --check-urls` adds dead-link resolution, `she…

+ 4 more paragraphs · read full section
sheaf_verify.md:56Markdown · 1 words
TESTS

N/A

EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf verify
short: Adversarially check a snapshot's top-line numbers (vs the join + disk) before a report is shown.
DOCS
docs/cli/sheaf.md:66Markdown · 24 words

**Verify.** `sheaf verify` adversarially re-checks a scan's headline numbers before the report is shown. It reads a snapshot via `sheaf verify --from-snapshot` and reconciles it — or, as a one-shot, `sheaf verify --config` builds the snapshot in-process (with `sheaf verify --library`) and verifies it in a single step. `sheaf verify --repo` points at the source tree, `sheaf verify --ecosystem` selects the view shape, and `sheaf verify --low-coverage-threshold` sets the suspicion line. `sheaf verify --disk` runs the on-disk oracle — `sheaf verify --check-urls` adds dead-link resolution, `she…

+ 4 more paragraphs · read full section
sheaf_verify.md:62Markdown · 13 words
TESTS

N/A

EXAMPLES

N/A

WORKFLOWS

N/A

CONTRACT
command: sheaf verify
short: Adversarially check a snapshot's top-line numbers (vs the join + disk) before a report is shown.
DOCS
docs/cli/sheaf.md:66Markdown · 32 words

**Verify.** `sheaf verify` adversarially re-checks a scan's headline numbers before the report is shown. It reads a snapshot via `sheaf verify --from-snapshot` and reconciles it — or, as a one-shot, `sheaf verify --config` builds the snapshot in-process (with `sheaf verify --library`) and verifies it in a single step. `sheaf verify --repo` points at the source tree, `sheaf verify --ecosystem` selects the view shape, and `sheaf verify --low-coverage-threshold` sets the suspicion line. `sheaf verify --disk` runs the on-disk oracle — `sheaf verify --check-urls` adds dead-link resolution, `she…

+ 4 more paragraphs · read full section
sheaf_verify.md:52Markdown · 11 words
TESTS

N/A

EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf verify
short: Adversarially check a snapshot's top-line numbers (vs the join + disk) before a report is shown.
DOCS
docs/cli/sheaf.md:66Markdown · 24 words

**Verify.** `sheaf verify` adversarially re-checks a scan's headline numbers before the report is shown. It reads a snapshot via `sheaf verify --from-snapshot` and reconciles it — or, as a one-shot, `sheaf verify --config` builds the snapshot in-process (with `sheaf verify --library`) and verifies it in a single step. `sheaf verify --repo` points at the source tree, `sheaf verify --ecosystem` selects the view shape, and `sheaf verify --low-coverage-threshold` sets the suspicion line. `sheaf verify --disk` runs the on-disk oracle — `sheaf verify --check-urls` adds dead-link resolution, `she…

+ 4 more paragraphs · read full section
sheaf_verify.md:63Markdown · 7 words
TESTS

N/A

EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf verify
short: Adversarially check a snapshot's top-line numbers (vs the join + disk) before a report is shown.
DOCS
docs/cli/sheaf.md:66Markdown · 27 words

**Verify.** `sheaf verify` adversarially re-checks a scan's headline numbers before the report is shown. It reads a snapshot via `sheaf verify --from-snapshot` and reconciles it — or, as a one-shot, `sheaf verify --config` builds the snapshot in-process (with `sheaf verify --library`) and verifies it in a single step. `sheaf verify --repo` points at the source tree, `sheaf verify --ecosystem` selects the view shape, and `sheaf verify --low-coverage-threshold` sets the suspicion line. `sheaf verify --disk` runs the on-disk oracle — `sheaf verify --check-urls` adds dead-link resolution, `she…

+ 4 more paragraphs · read full section
sheaf_verify.md:64Markdown · 6 words
TESTS

N/A

EXAMPLES
+ 1 more examples · open all in source
WORKFLOWS

N/A

CONTRACT
command: sheaf verify
short: Adversarially check a snapshot's top-line numbers (vs the join + disk) before a report is shown.
DOCS
docs/cli/sheaf.md:66Markdown · 30 words

**Verify.** `sheaf verify` adversarially re-checks a scan's headline numbers before the report is shown. It reads a snapshot via `sheaf verify --from-snapshot` and reconciles it — or, as a one-shot, `sheaf verify --config` builds the snapshot in-process (with `sheaf verify --library`) and verifies it in a single step. `sheaf verify --repo` points at the source tree, `sheaf verify --ecosystem` selects the view shape, and `sheaf verify --low-coverage-threshold` sets the suspicion line. `sheaf verify --disk` runs the on-disk oracle — `sheaf verify --check-urls` adds dead-link resolution, `she…

+ 4 more paragraphs · read full section
sheaf_verify.md:54Markdown · 7 words
TESTS

N/A

EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf verify
short: Adversarially check a snapshot's top-line numbers (vs the join + disk) before a report is shown.
DOCS
docs/cli/sheaf.md:66Markdown · 29 words

**Verify.** `sheaf verify` adversarially re-checks a scan's headline numbers before the report is shown. It reads a snapshot via `sheaf verify --from-snapshot` and reconciles it — or, as a one-shot, `sheaf verify --config` builds the snapshot in-process (with `sheaf verify --library`) and verifies it in a single step. `sheaf verify --repo` points at the source tree, `sheaf verify --ecosystem` selects the view shape, and `sheaf verify --low-coverage-threshold` sets the suspicion line. `sheaf verify --disk` runs the on-disk oracle — `sheaf verify --check-urls` adds dead-link resolution, `she…

+ 4 more paragraphs · read full section
sheaf_verify.md:57Markdown · 11 words
TESTS

N/A

EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf verify
short: Adversarially check a snapshot's top-line numbers (vs the join + disk) before a report is shown.
DOCS
docs/cli/sheaf.md:66Markdown · 24 words

**Verify.** `sheaf verify` adversarially re-checks a scan's headline numbers before the report is shown. It reads a snapshot via `sheaf verify --from-snapshot` and reconciles it — or, as a one-shot, `sheaf verify --config` builds the snapshot in-process (with `sheaf verify --library`) and verifies it in a single step. `sheaf verify --repo` points at the source tree, `sheaf verify --ecosystem` selects the view shape, and `sheaf verify --low-coverage-threshold` sets the suspicion line. `sheaf verify --disk` runs the on-disk oracle — `sheaf verify --check-urls` adds dead-link resolution, `she…

+ 4 more paragraphs · read full section
sheaf_verify.md:60Markdown · 10 words
TESTS

N/A

EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf verify
short: Adversarially check a snapshot's top-line numbers (vs the join + disk) before a report is shown.
DOCS
docs/cli/sheaf.md:66Markdown · 29 words

**Verify.** `sheaf verify` adversarially re-checks a scan's headline numbers before the report is shown. It reads a snapshot via `sheaf verify --from-snapshot` and reconciles it — or, as a one-shot, `sheaf verify --config` builds the snapshot in-process (with `sheaf verify --library`) and verifies it in a single step. `sheaf verify --repo` points at the source tree, `sheaf verify --ecosystem` selects the view shape, and `sheaf verify --low-coverage-threshold` sets the suspicion line. `sheaf verify --disk` runs the on-disk oracle — `sheaf verify --check-urls` adds dead-link resolution, `she…

+ 4 more paragraphs · read full section
sheaf_verify.md:55Markdown · 12 words
TESTS

N/A

EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf verify
short: Adversarially check a snapshot's top-line numbers (vs the join + disk) before a report is shown.
DOCS
docs/cli/sheaf.md:66Markdown · 25 words

**Verify.** `sheaf verify` adversarially re-checks a scan's headline numbers before the report is shown. It reads a snapshot via `sheaf verify --from-snapshot` and reconciles it — or, as a one-shot, `sheaf verify --config` builds the snapshot in-process (with `sheaf verify --library`) and verifies it in a single step. `sheaf verify --repo` points at the source tree, `sheaf verify --ecosystem` selects the view shape, and `sheaf verify --low-coverage-threshold` sets the suspicion line. `sheaf verify --disk` runs the on-disk oracle — `sheaf verify --check-urls` adds dead-link resolution, `she…

+ 4 more paragraphs · read full section
sheaf_verify.md:61Markdown · 11 words
TESTS

N/A

EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf verify
short: Adversarially check a snapshot's top-line numbers (vs the join + disk) before a report is shown.
DOCS
docs/cli/sheaf.md:66Markdown · 27 words

**Verify.** `sheaf verify` adversarially re-checks a scan's headline numbers before the report is shown. It reads a snapshot via `sheaf verify --from-snapshot` and reconciles it — or, as a one-shot, `sheaf verify --config` builds the snapshot in-process (with `sheaf verify --library`) and verifies it in a single step. `sheaf verify --repo` points at the source tree, `sheaf verify --ecosystem` selects the view shape, and `sheaf verify --low-coverage-threshold` sets the suspicion line. `sheaf verify --disk` runs the on-disk oracle — `sheaf verify --check-urls` adds dead-link resolution, `she…

+ 4 more paragraphs · read full section
sheaf_verify.md:65Markdown · 10 words
TESTS

N/A

EXAMPLES
WORKFLOWS

N/A

CONTRACT
command: sheaf version
short: Print version information.
long: |
  Print the linked build version (set via -ldflags at link time,
  defaulting to 0.1.0-dev) and exit. Takes no flags and runs no
DOCS
sheaf_version.md:1Markdown · 69 words
docs/cli/sheaf.md:40Markdown · 28 words

`sheaf scan`, `sheaf gaps`, `sheaf coverage`, `sheaf report`, `sheaf snapshot`, `sheaf serve`, and `sheaf review` all run the full pipeline (config load → adapter dispatch → indexer → analyzers) before producing their output. `sheaf render` and `sheaf review-html` are pipeline-free — they render from a Snapshot JSON / `delta.json` that an earlier pipeline run already produced — as are `sheaf doctor`, `sheaf version`, and `sheaf init`.

+ 16 more paragraphs · read full section
TESTS
internal/cli/version_test.go:7internal/cli/version_test::TestVersion · Go · 5 lines
func TestVersion(t *testing.T) {
	if rc := Version(nil); rc != 0 {
		t.Errorf("Version rc = %d", rc)
	}
}
EXAMPLES
WORKFLOWS

N/A

5 Workflows

Recipes name the command, not the flag — 85% of commands appear in at least one workflow, only 44% of flags do.

Commands in ≥1 workflow
85%
Flags in ≥1 workflow
44%
Length distribution
2 cmd 0
3 cmd 0
4 cmd 1
5 cmd 0
6+ cmd 4
Freshness
workflows.md · 26 steps current
README.md · 4 steps current
README.md · 8 steps current
PROCEDURE.md · 6 steps current
onboard-a-new-repo.md · 11 steps current
sheaf scanner · 76 commands & flags · cli surface · 2026-06-08 19:24 UTC