Skip to content

needs-yatsu-eval

The forge half of spex yatsu scan — recognizes OPEN issues flagged needs-yatsu-eval (a label or a Spec:-style body line), resolves each to its node via the existing link sources, and exposes node → evaluation-pending. Read-only.

The seam where spec-forge feeds spec-yatsu. 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 spex yatsu scan folds in beside its own stale-reading findings.

The flag — two forms, one meaning. An issue is marked needs-yatsu-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.

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-yatsu-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-yatsu-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-yatsu 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-yatsu-eval.ts is pure and host-agnostic (it consumes whatever a driver fetched and writes nothing), so spec-yatsu's scan can later import resolveEvalPending directly. The forge-cli exposes the same shape on the real surface as spex forge eval-pending [--host 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 yatsu scan to actually call this (a spec-yatsu concern), and surfacing eval-pending in the dashboard.