cite

package
v0.13.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 10, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package cite is the live half of the citation gate: the on-demand refresh that fetches every cited URL and writes the committed baseline the zero-network docs lint then enforces offline.

The split is spc-17's whole design bet. Fetching is non-deterministic and needs the network; deciding whether a commit is allowed must be neither. So this package is the ONLY place abcd dials out on behalf of documentation, it runs when a maintainer asks it to, and everything it learns arrives at the gate as a reviewable committed record rather than as whatever the network happened to answer during CI.

It writes nothing it did not establish. A source that refuses automated fetchers produces no entry at all — not a guess, not a "probably fine" — because the one thing a committed record must never contain is a receipt nobody earned. Those URLs go to a human instead, and the confirm verb records that a human cleared them and when, never how.

Index

Constants

View Source
const DefaultTimeout = 20 * time.Second

DefaultTimeout bounds one whole attempt — connect, TLS, and response headers. It is the ceiling on what a single unreachable citation can cost a run.

View Source
const ReceiptSchemaVersion = 1

ReceiptSchemaVersion is the only receipt schema this build understands.

Variables

This section is empty.

Functions

This section is empty.

Types

type CheckOutcome

type CheckOutcome struct {
	URL      string `json:"url"`
	Status   Status `json:"status"`
	FinalURL string `json:"final_url,omitempty"`
	// Detail is for the operator's terminal. It is deliberately NOT persisted:
	// the baseline records what is true about a link, not the transcript of
	// finding out.
	Detail string `json:"detail,omitempty"`
	// Answered records that a host replied — any status line at all, including a
	// 404 or a 403. It is the bit that separates "this citation is dead" from
	// "this machine reached nothing", which StatusBroken alone cannot express:
	// a DNS failure, a refused connection and a genuine 404 all land there. The
	// refresh reads it to tell a broken corpus from a broken network, and
	// nothing persists it.
	Answered bool `json:"answered,omitempty"`
}

CheckOutcome is one URL's result. It carries a classification, the address the request ended at, and a short human-readable reason — never page content, and never anything that reaches the committed baseline except FinalURL.

type Checker

type Checker interface {
	Check(rawURL string) CheckOutcome
}

Checker is the refresh seam. spc-17 fixes the baseline schema and the lint rules as the contract and leaves the producer replaceable, so a specialist link checker can later arrive as an adapter satisfying this one method without any gate semantics changing.

An implementer owes two things beyond the obvious. The Status must be one of the three declared values — anything else stops the run rather than being quietly dropped. And on StatusBroken it should set Answered to say whether a host actually replied, because that is the bit the refresh uses to tell a dead citation from a dead network, and nothing else can recover it. Omitting it on StatusOK or StatusBlocked is harmless: those two entail an answer.

type ConfirmError

type ConfirmError struct {
	// contains filtered or unexported fields
}

ConfirmError is a refused confirmation — a distinct type so a caller can tell a bad receipt from an I/O fault without string matching.

func (*ConfirmError) Error

func (e *ConfirmError) Error() string

type ConfirmRequest

type ConfirmRequest struct {
	RepoRoot string
	Config   lint.Config
	Receipt  Receipt
	Now      time.Time
}

ConfirmRequest is the input to one confirm call.

type ConfirmResult

type ConfirmResult struct {
	BaselinePath string   `json:"baseline_path"`
	Recorded     []string `json:"recorded"`
}

ConfirmResult reports what was recorded.

func Confirm

func Confirm(req ConfirmRequest) (ConfirmResult, error)

Confirm records a human's confirmations in the baseline.

Every line is validated against the docs' cited set BEFORE anything is written, and one bad line refuses the whole receipt. Confirming is the single place a receipt enters the record without a fetch, so it must not become a door through which arbitrary entries arrive — and a batch that half-applied would leave a maintainer unable to tell which half.

type ConfirmedCitation

type ConfirmedCitation struct {
	// URL is the cited address, exactly as the docs write it.
	URL string `json:"url"`
	// FinalURL is where the human found the document, when it differs from the
	// cited address. Empty means it did not move.
	FinalURL string `json:"final_url,omitempty"`
	// VerifiedOn is the date the human checked, YYYY-MM-DD. Empty means today.
	// It is a declared date rather than an implicit "now" because a receipt for
	// last week's work must age from last week — the clock AC 3 puts human and
	// machine verifications on is the same one.
	VerifiedOn string `json:"verified_on,omitempty"`
}

ConfirmedCitation is one cleared queue line.

type HTTPChecker

type HTTPChecker struct {
	// contains filtered or unexported fields
}

HTTPChecker is the native, dependency-free implementation of Checker.

func (*HTTPChecker) Check

func (c *HTTPChecker) Check(rawURL string) CheckOutcome

Check performs one bounded attempt and classifies the result.

type Outcome

type Outcome struct {
	URL      string `json:"url"`
	Status   Status `json:"status"`
	FinalURL string `json:"final_url,omitempty"`
	Detail   string `json:"detail,omitempty"`
}

Outcome is one cited URL's disposition in a run.

type QueueItem

type QueueItem struct {
	URL    string              `json:"url"`
	Detail string              `json:"detail"`
	Sites  []lint.CitationSite `json:"sites"`
}

QueueItem is one line of the manual checklist (spc-17's rung 1): a URL an automated fetcher may not read, and where the docs cite it.

type Receipt

type Receipt struct {
	SchemaVersion int                 `json:"schema_version"`
	Confirmed     []ConfirmedCitation `json:"confirmed"`
}

Receipt is what a human — or the generated checklist page — hands back.

func LoadReceipt

func LoadReceipt(path string) (Receipt, error)

LoadReceipt reads and parses a receipt file.

type RefreshError

type RefreshError struct {
	// contains filtered or unexported fields
}

RefreshError is a refused refresh — a distinct type so a caller can tell a refusal to write from an I/O fault without string matching.

func (*RefreshError) Error

func (e *RefreshError) Error() string

type RefreshRequest

type RefreshRequest struct {
	// RepoRoot is the repository to refresh.
	RepoRoot string
	// Config supplies the roots to walk and the citation policy (baseline path
	// and staleness thresholds) — the same config the gate reads, so the verb
	// and the gate can never disagree about either.
	Config lint.Config
	// Checker is the refresh seam. Nil means the native bounded fetcher.
	Checker Checker
	// Now is the clock. Supplied by the caller so a run's record is a function
	// of its inputs.
	Now time.Time
	// Parallel bounds concurrent checks; zero means defaultParallel.
	Parallel int
}

RefreshRequest is the input to one refresh run.

type RefreshResult

type RefreshResult struct {
	// BaselinePath is repo-relative — never absolute, so machine output carries
	// no developer-identity path.
	BaselinePath string `json:"baseline_path"`
	Cited        int    `json:"cited"`
	// Fetched counts the URLs actually requested this run; Preserved counts the
	// current manual receipts left untouched. They sum to Cited.
	Fetched   int       `json:"fetched"`
	Preserved int       `json:"preserved"`
	Outcomes  []Outcome `json:"outcomes"`
	// Queue is the manual checklist: everything a human must clear.
	Queue []QueueItem `json:"queue"`
	// Dropped lists entries removed because the docs no longer cite them.
	Dropped []string `json:"dropped,omitempty"`
}

RefreshResult is the record of one run, for the operator's transcript and for `--json`.

func Refresh

func Refresh(req RefreshRequest) (RefreshResult, error)

Refresh checks every cited URL and rewrites the baseline.

The merge is where the honesty rules live, and there are three:

  • A current MANUAL receipt is preserved verbatim and its URL is not even requested. Re-fetching it could only produce a worse answer (the source blocks robots, which is why a human looked in the first place), and overwriting a human's confirmation with a robot's failure is the exact downgrade the record must never suffer.
  • A STALE manual receipt is re-checked, because AC 3 puts human and machine verifications on one clock: once it ages out it stops being authoritative. If the re-check succeeds the entry becomes a fresh automatic one; if the source still blocks, the stale receipt is KEPT (so the gate keeps warning truthfully) and the URL re-enters the queue.
  • A BLOCKED URL with no prior entry writes nothing. The gate then reports it as unreceipted, which is precisely the truth, and the queue names it.

Entries whose URLs the docs no longer cite are dropped: the baseline answers for what is published today.

func (RefreshResult) Counts

func (r RefreshResult) Counts() (ok, broken, blocked, preserved int)

Counts summarises the outcomes by status, for a one-line report.

type Status

type Status string

Status is what one check established about one citation.

const (
	// StatusOK means the address resolved to a live document.
	StatusOK Status = "ok"
	// StatusBroken means it did not: a 4xx/5xx, an unresolvable host, a refused
	// connection, a timeout, or a redirect chain past the bound.
	StatusBroken Status = "broken"
	// StatusBlocked means the source refused an automated fetcher. That is not
	// evidence the citation is dead, so it routes to the manual queue rather than
	// into the record.
	StatusBlocked Status = "blocked"
)
const StatusPreserved Status = "preserved"

StatusPreserved is the fourth disposition a REFRESH can report, distinct from the three a checker can return: the entry was not checked at all, because a human's receipt for it is still current.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL