Skip to content

needs-eval

Provenance

  • Source: .spec/spexcode/spec-forge/needs-eval/spec.md
  • Source SHA-256: cbdd86a86365aa549128b17efd6fb8918c01d67f02ff259a4e0235ca44ab0b37

The seam where [[spec-forge]] feeds [[spec-eval]]. Read the system as one optimization: a spec is a loss-function design, an issue/PR is the optimizer, and yatsu is the evaluator that re-reads the loss. An OPEN issue can therefore carry one fact beyond which node it serves — that the node owes a fresh evaluation: a fix is landing, a behavior moved, a repro wants re-reading. This node recognizes that flag and surfaces node → evaluation-pending, the list the measurement-layer lint (spex eval lint) folds in beside its own stale-reading findings.

The flag — two forms, one meaning. An issue is marked needs-eval by either a label of that name or a body line that is the bare marker (case-insensitive, any indent, an optional trailing colon — Spec:-styled but argument-less). The two are symmetric: a caller never learns which form a given forge prefers. The marker is a predicate, not a router — it says re-evaluate, never which node. (The label was needs-yatsu-eval before v0.3.0; the GitHub label was renamed via the API — a label rename propagates server-side to every issue carrying it — while a body-line marker in a pre-rename issue is archive text and simply no longer matches.)

Which node — one resolution authority. Routing is delegated wholesale to [[links]] (resolveLinks): the issue's Spec: <id> marker, or transitively through a node/<id> PR that closes it. So there is exactly one place a node is named, and the keystone falls out for free — a bug issue labeled needs-eval plus its closing node/<id> PR is routed with no marker at all (via: 'pr'). A flag that resolves to no node links nothing, the same silent drop as a typo'd Spec: marker — never an invented node. A body line that trails content (needs-eval: foo) is intentionally not a flag, so routing can never be smuggled in beside the predicate.

Only OPEN, only flagged. resolveEvalPending narrows each resolved node's issues to the open and flagged ones: open because a closed issue's eval is no longer owed (its A→B step is already bracketed by the closing PR — the [[spec-eval]] keystone), flagged because that is the whole signal. Each surviving entry is the LinkedIssue [[links]] already produced, so it keeps via (marker vs the inferred PR).

The shape, two consumers. NodeEvalPending[] — the eval-pending list keyed by node — is the single output. spec-forge/src/needs-eval.ts is pure and host-agnostic (it consumes whatever a driver fetched and writes nothing), so [[spec-eval]]'s measurement lint can later import resolveEvalPending directly. The [[forge-cli]] exposes the same shape on the real surface as spex issue links --pending [--store github] [--node <id>] [--json] (the --json is exactly that list). Read-only end to end — git/.spec stays the single source of truth; this never writes a node's version or status.

Out of scope (later/sibling): wiring spex eval lint to actually call this (a [[spec-eval]] concern), and surfacing eval-pending in the dashboard.