Skip to content

feat(selector): one selector API for writ and lore; directory names follow os-release's lineage - #992

Merged
David-Noble-at-work merged 3 commits into
developfrom
feature/944-one-selector-api-writ-and-lore
Sep 30, 2026
Merged

David-Noble-at-work merged 3 commits into
developfrom
feature/944-one-selector-api-writ-and-lore

Conversation

@David-Noble-at-work

@David-Noble-at-work David-Noble-at-work commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Lane 19 of #949, alone, straight after #959 (ruled 2026-09-30: "we'll do lane 18 followed by lane 22. two prs and at the end we'll be done with selectors. we'll have common selectors for writ and lore.").

  • One package, pkg/selector: it detects the host and answers which of a list of directory names apply to it, and in what order. writ and lore both use it. The rules are stated once, in docs/guides/selectors.md.
  • The grammar: [<project>][.<os>][.<arch>][.<extra>...]. Order is significant, a name carries one OS word, and the vocabulary is closed. common.Debian is the form, and common.Linux.Debian is refused.
  • The chain follows os-release's lineage: Unix, Linux, ID_LIKE reversed, then ID. On Ubuntu, Linux, Debian and Ubuntu apply. macOS is Unix, Darwin; the BSDs are Unix, then the OS; Windows is Windows.
  • Grammar errors refuse the run before anything changes, all listed at once: out of order, two words for one part, a word no part holds. Another machine's well-formed name is excluded silently.
  • One total order; the last applied wins: projects as the command line reads (implicit, recorded and not named, named left to right); within a project, the OS word's depth, then the architecture, then the extras; layers base, team, personal. Naming an implicit project (writ deploy common included) or naming a project twice is a command-line error; the bare form is writ deploy (ruled 2026-09-30).
  • Collisions say why: each carries both directories' ranks and the part that decided: a later layer, a later project, a more specific OS word, the architecture, or a named segment.
  • writ's extra segments: declared in writ.segments with their values and validated. They're set by --segment NAME=value or WRIT_SEGMENT_<NAME> on deploy, upgrade, reconcile and adopt. This resolves writ upgrade and reconcile do not see the segments deploy was given: -s is deploy-only, and reconcile's Config.Segments is never read #970, the segments upgrade and reconcile didn't see.
  • lore: a package's platform directories are selected the same way, with Common first; every applicable phase script runs, general to specific. lore deploy plans every package before any deploys, so a grammar error in any package refuses the run. Native packages resolve by the platform's default purl type, pacman included, and lore search labels hits by the same mapping (rpm and alpm hits were labeled apt).
  • pkg/platform: it detects through the selector, and falls back along ID_LIKE for package managers (Pop!_OS takes Ubuntu's apt). Its token and lore's detectPlatform are gone.
  • writ segment matching ignores its own suffix grammar: order unvalidated, dimensions unchecked, ties undefined #369 (the suffix grammar's enforcement) is resolved here. Its plan is set abandoned, because this one supersedes it.

Also: #959's plan takes its last box and is complete; plans that described the token or the retired Linux.Debian form carry dated notes; the 2.5 architecture status records two places where the document and the code disagree.

  • Plan — docs/plans/feature/944-one-selector-api-writ-and-lore.md. It stays active: its last boxes are DANOBLE-UD24-1's convergence and the follow-up issues.

Resolves #944
Resolves #369
Resolves #970

Test plan

  • pkg/selector: the chains per distribution, the spelling table, the vocabulary, every grammar error, the ranking, and the segment declarations' refusals
  • writ: the most specific link wins, Darwin beats Unix, projects apply in command-line order, grammar errors refuse the build, a collision says what decided it; the implicit and duplicate refusals; adopt's --platform
  • lore: platform directories follow the host's chain with Common first; a leftover Linux.Debian refuses the package, and a grammar error in any package refuses lore deploy before anything deploys; phase scripts run general to specific; purl types map to sources
  • A review of the whole diff, each finding checked by an independent skeptic: nine confirmed and fixed, four refuted
  • make test; make test-scenario, whose lineage step asserts that each ID_LIKE ancestor's consumer deploys on this host
  • gofmt; make vet-all and make lint-all on linux, darwin and windows, 0 issues; star lint go; star lint shell; the guides' frontmatter
  • After the merge: DANOBLE-UD24-1 converges on the official pre-release; Home/common.Debian's four files deploy on this Ubuntu host, and no other link changes

Time

Marker UTC Elapsed
opened (first commit) 2026-09-30T16:07:27Z —
submitted (PR opened) 2026-09-30T18:22:55Z 2.3 h after opened
merged 2026-09-30T18:35:46Z 0.2 h after submitted; 2.5 h in all

Computed by the algorithm of noblefactor-ops#188 at merge.

One package detects the host (os-release, the chain Unix -> Linux ->
ID_LIKE reversed -> ID) and selects and orders directory names by one
ordered grammar, [<project>][.<os>][.<arch>][.<extra>...], against a
closed vocabulary. Grammar errors refuse the run. Extras are declared in
configuration with their values. writ, lore and pkg/platform all go
through it. Resolves #944, #369 and #970 when done; lane 19 of #949.
The owner's rulings of 2026-09-30 are recorded in the plan.

Claude-Session: https://claude.ai/code/session_01DuNfZFyfxBoD9pdaiDEMrY
…ollow os-release's lineage

pkg/selector detects the host and selects and orders directory names
for both programs. The grammar is [<project>][.<os>][.<arch>][.<extra>...]:
order is significant, a name carries one OS word, and the vocabulary is
closed. The chain runs Unix, Linux, ID_LIKE reversed, then ID, from
os-release, so on Ubuntu a directory suffixed Linux, Debian or Ubuntu
applies. common.Debian is the form; common.Linux.Debian is refused.

A name that breaks the grammar (out of order, two words for one part,
a word no part holds) refuses the run before anything changes, and the
refusal lists every one. Another machine's well-formed name is excluded
silently.

Directories apply in one total order, and the last applied wins:
projects as the command line reads (implicit, then recorded and not
named, then named, left to right); within a project, the OS word's
depth in the chain, then the architecture, then the extras in their
configured order; layers base, team, personal. Naming an implicit
project, writ deploy common included, or naming a project twice is a
command-line error. The bare form is writ deploy.

writ: extra segments are declared in writ.segments with every value
they may take, validated, and set by --segment NAME=value or
WRIT_SEGMENT_<NAME> on deploy, upgrade, reconcile and adopt. The tree
builder applies the selector's order, and a collision carries both
directories' ranks and says what put the winner after the loser: a
later layer, a later project, a more specific OS word, the
architecture, or a named segment.

lore: a package's platform directories are selected the same way, with
Common first, and every applicable directory's phase script runs,
general to specific. lore deploy plans every package before any
deploys, so a grammar error in any package refuses the run. A native
package resolves through the platform's default purl type, pacman
included, and lore search labels its hits by the same mapping: rpm and
alpm hits were labeled apt.

pkg/platform detects through the selector, and a distribution devlore
doesn't list takes the package managers of its closest listed ID_LIKE
ancestor: Pop!_OS takes Ubuntu's apt. Its token is gone.

docs/guides/selectors.md states the rules once; writ's and lore's guides
link it. #959's plan takes its last box and is complete.

Resolves #944
Resolves #369
Resolves #970

Claude-Session: https://claude.ai/code/session_01DuNfZFyfxBoD9pdaiDEMrY
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment