Skip to content

issues-cli

Provenance

  • Source: .spec/spexcode/spec-cli/issues/issues-cli/spec.md
  • Source SHA-256: c27f83c249cea7c2c5904c2073945a9d24dfcf0ec148b829e9db3c941cd4cb2e

issues-cli

raw source

These handlers used to live inside issues.ts and localIssues.ts — the modules the eval package imports. A CLI surface is by definition the topmost layer: it reads argv, prints, and returns an exit code. Hosting one inside a store/feature module gave those files two altitudes at once, and that is what held the spec↔eval package cycle in place. The loop-in's candidate resolution needs eval knowledge; its only callers were these handlers; and from below the eval layer they could not reach it. Every cheap alternative failed on the same wall — moving a store primitive down, lifting the loop-in, extracting the read projection — because each moved a LEAF of the ring while the ring was held by a module hosting several heights.

expanded spec

issues-cli owns the spex issue and spex remark verb surfaces: flag parsing, the flag-decides-the-parse discriminators, human-readable output, and exit codes. It owns no store state and no issue semantics — it calls the read/write verbs that issues.ts and localIssues.ts export, and it renders what they return. The split is by ALTITUDE, not by domain: the issue domain still belongs to [[issues]] and the local store to [[local-issues]]; what moved is the part that talks to a terminal.

Its position is what makes it useful. Sitting above both the store modules and the eval layer, it is a place where a value composed from both can legally be assembled — which is what the remaining half of the cycle work needs and what no module below eval could offer. Its own imports of issues.ts are therefore ordinary STATIC imports; the deferred await import('./issues.js') that localIssues.ts used to carry existed only because a handler down there had to reach a module that imported it back, and it is gone with the handler.

This module is deliberately NOT merged into cli.ts. That file is the thin dispatch hub ([[cli-surface]]), whose roughly eighty lazy import sites keep a single invocation from loading every verb's implementation; folding 265 lines of verb bodies in would trade one two-altitude module for another and cost the startup property that discipline exists to buy. The hub reaches this module the same way it reaches every other verb: one lazy line.

The argv helpers travel WITH the surface rather than being exported to it. fl, hasFlag, bare, readBody, repeated and the value-flag set are parsing concerns, so they belong at parsing altitude; two byte-identical copies of fl existed while the surface was split across two modules, and one copy is what remains. A helper that both this module and a store module need is a signal to re-examine which of them is really asking, not a reason to widen a store module's exports.