@sema-agent/wiki-gate
v7.68.3
Published
The sema wiki gates as a library: one reader module with three gate entries (anchors, freshness, coverage) and the stamp, over a repository you name. The repository's own readers and generators are handed in; the rules are the package's.
Readme
@sema-agent/wiki-gate
The sema wiki gates: one reader module with three gate entries — anchors, freshness, coverage — and the stamp tool, over the repository a configuration object names. A wiki page carries sentences marked with their evidence level and the refs they rest on; the gates answer whether every claim is marked, whether every ref still resolves to what was stamped, and whether every source the repository requires (for the wiki genre, also the shipped feature rows) is on some page.
One rule set
The gate holds every page directory it is pointed at — docs/wiki and docs/manual alike — to one rule set: the
genre, and with it the directory, is chosen by the entry's configuration object, never by a page's own header, and the
package opens no second interface for another genre. The genre is a word of the package's frozen genre table, GENRES
(wiki → docs/wiki, manual → docs/manual); a row names its directory, its readers, the evidence levels it admits
and the coverage it requires of its own. The wiki is read by embedders, deployers and callers, admits G, P, V and
I, and requires the shipped feature rows; the manual is read by users, scripters and admins, admits G, U, P and
I, and requires nothing of its own. A U sentence cites one crit:<repo>@<X.Y.Z>:<cell> key, and it is evidence only
while the acceptance index judges that cell pass and no later cell supersedes or retires it. A word the table does not
hold is every entry's refusal (exit 2), by name — there is no default genre and no directory member to name instead.
The rules — page shape, markers, refs, digests, severities, corrections, the stamp — are the package's and read the same
in every repository. A repository hands in its own readers (its export surface, its closed-set and contract-sentence
registries, its configuration catalog, its literal tables, its internal work-item name form, its test reader when its
tests are not vitest, its acceptance index and its criteria as it publishes them) and its own generators. A ref whose
kind needs a reader the repository does not configure is an anchors finding that says so. A source the repository names
among its required or reported sources comes with its reader: one named without a reader is every entry's refusal
(exit 2), and the coverage verdict line names each required source with its coverage. The page index (page-index),
the genre table (genre-table) and the table of knob fields (knob-fields) are the package's own generators, held by
every repository; a repository generator spelled like any of them is every entry's refusal.
A generator whose region is a table of configuration knobs names the fields its columns render with rowFields, out of
KNOB_FIELDS. The anchors gate then holds the region to that table: an unknown field, a field named twice, a missing
required field (name, readPoints) and a header row of another width are findings, and so is a knob row whose
readPoints cell holds no path:line coordinate. The gate reads the shape of a coordinate, never whether the file
and the line exist, and it judges a generator only by what the generator declares: a table rendered without a
rowFields declaration is not read as a table of knobs. The package scans no source for read points; the generator of
the repository that owns the catalog computes them.
Install
npm install --save-dev @sema-agent/wiki-gateES modules only ("type": "module"), Node >= 20.18.1. One entry, .; there are no deep paths. Its one dependency is
typescript at an exact version: the digests a stamp writes are read through that compiler's printer, so another
version could read the same declaration to another digest.
Use
import { wikiAnchors, wikiFreshness, wikiCoverage, runWikiGate } from "@sema-agent/wiki-gate";
const config = {
root: "/path/to/repo", // every path is relative to it
genre: "wiki", // its row of GENRES names the page directory ("manual" = docs/manual, the same rules)
redFrom: { wiki: "7.69.0" }, // per genre: below it a finding warns, from it on a finding fails
readers: { /* snapshot, closedSets, contracts, catalog, tableValues, workItemName, pin, acceptanceIndex, criterionText */ },
generators: (read) => ({ /* name → { render: (...args) => ({ text, refs }), covers?, rowFields? } */ }),
required: { /* source name → its reader; one named without a reader cannot be judged */ },
reported: { /* source name → its reader; counted, never failed */ },
// optional: identity, releaseDistance, bans, preflight
};
const r = wikiAnchors(config, { strict: true });
// r.exit: 0 = no failure (warnings counted), 1 = at least one failure, 2 = cannot judge (r.couldNotJudge says why)
// r.line: the verdict line every run speaks — a gate that judged nothing never looks like a green onerunWikiGate(config, { argv }) is the command line over the same entries and the stamp:
anchors|freshness [--strict] [<page.md> …], coverage [--strict] [--comms <dir>] [--report], stamp <page.md> …; each
also takes --test <dir> (the acceptance checkout) and --corrections <dir> (the correction-record checkout).
--report prints the coverage report as a table (source, cited, size, cited %). An option a command does not take is
refused by name (exit 2).
citedByPages(tree, pages) is the one reading of "what the pages cite" (feature rows on feats:, and for each source the
ids cited through a ref of its kind or covered by a generated region); the coverage gate counts from it, and a
repository's release tooling can ask it whether a name a release moved is on a page.
A finding is a warning while the repository's own package.json version is below its redFrom version for the page's
genre and a failure from that version on; strict takes the version out. A severity a finding carries of its own holds
under every reading: a crit: cell that is not a passing, current one, and an open correction, fail under every
reading; an old V run, or an old U cell, is a warning.
Version
@sema-agent/[email protected] is cut with @sema-agent/[email protected]: the same version number, built from the same
commit. A package version moves with every core release whether or not the gates changed. It does not take core.
Source and package
In the sema-core repository the gates run through that repository's own binding, which loads this package's source
(tsx's tsImport) with the repository's readers, so a gate run needs no build. The package published from the same
source is its tsc output, and the two do not differ: the package's frozen export surface
(test/export-surface.snapshot.json), and the tarball test that imports the three entries from a packed tarball and
judges the same sample pages green and broken pages red, are the proof.
