Skip to content

dev runner: scope x labels with derived defaults; retire the dev.yml runner block - #162

Merged
JPDuchesne merged 3 commits into
mainfrom
jpd/dev-161-runner-scope-labels
Sep 13, 2026
Merged

dev runner: scope x labels with derived defaults; retire the dev.yml runner block#162
JPDuchesne merged 3 commits into
mainfrom
jpd/dev-161-runner-scope-labels

Conversation

@JPDuchesne

Copy link
Copy Markdown
Contributor

Closes #161. Design settled in review discussion (plans#26 doctrine: enrollment state is inspected, never recorded).

What changed

dev runner register                     # repo scope; label derived from the project name
dev runner register --labels ue-engine  # repo scope, custom roles
dev runner register --org --ai-flow     # org agent host: the full ai-flow label set
dev runner register --org --labels ai-build   # org custom pool
dev runner status                       # THIS machine's enrollments + host facts
  • Derived repo label: ProjectManifest#slug — the dev.yml name: normalized (Cellbound3Dcellbound3d). The manifest name is the package identity (the ecosystem norm: gemspec/package.json/Cargo name); the org is the registry giving it uniqueness.
  • --ai-flow: LabelContracts::AI_FLOW_LABELS (ai-ask ai-edit ai-split ai-build ai-learn) — dev's documented mirror of ai-flow's vocabulary (defined by its reusable workflow; named as the contract in README: name the ai-flow label vocabulary as the defining contract ai-flow#80), same cross-repo-literal category as the agent user name.
  • Idempotent + self-healing: register discovers an existing enrollment at the target scope (RunnerDiscovery — every ~/actions-runner-*/.runner, so dir names never matter) and amends labels in place on GitHub (RunnerRegistry PUT) instead of re-enrolling; contracts converge every run; a runner GitHub has lost re-enrolls into its same dir. Fresh scope → full ceremony (unchanged RunnerSetup).
  • status is the machine's view: discovered enrollments (scope/name from .runner, offline-safe), labels from GitHub (their single home — unknown when offline, flagged when gone server-side), agent-contract facts per agent-labeled enrollment, host tooling. No dev.yml reads.
  • Retired: the dev.yml runner: block (warns and is ignored — existing GitHub enrollments keep working), RUNNER_HOST_KEYS, the manifest/context runner fields. runner is now ungated, projectless catalog included (--org needs no checkout); runner-setup stays an alias. ProjectContext carries the manifest name.
  • README: demand/supply routing semantics (no repo-beats-org priority; pooling vs label-set partition), the three vocabularies, the rewritten register/status contract.

Verification

rake test (1349 tests, 0 failures) + srb tc (no errors) + rubocop (311 files, no offenses), one chain under shadowenv.

Follow-ups: cellbound-3d and unreal-engine drop their runner: blocks; release cut; the plans#36 ceremony opens with dev runner register --org --ai-flow.

Made with Cursor

JPDuchesne and others added 2 commits September 12, 2026 20:06
…ecorded

Two read seams for runner enrollment state (plans#26): RunnerDiscovery
enumerates this host's actions-runner dirs and parses each .runner record
(scope + name, BOM-aware) — offline by construction, spanning every dir so
an org enrollment living in a repo-named dir (its pre-org history) is
still found. RunnerRegistry is the GitHub-side view over the gh Executor
seam: find a runner by scope+name (custom labels only — read-only ones
are GitHub's), amend its custom labels in place via PUT, loud QueryError
vs nil so callers can tell offline from gone. Refs #161.

Co-authored-by: Cursor <cursoragent@cursor.com>
…runner block

Enrollment identity is a machine fact, not a repo declaration (plans#26):

- Bare `dev runner register` enrolls repo-scoped with the label derived
  from the manifest name (ProjectManifest#slug — the name is the package
  identity, the org the registry); --org composes with --ai-flow (the
  full ai-flow vocabulary, mirrored as LabelContracts::AI_FLOW_LABELS)
  or --labels. --org needs no checkout; runner is ungated (projectless
  catalog included) and runner-setup stays an alias.
- Idempotent and self-healing: register discovers an existing enrollment
  at the target scope (RunnerDiscovery over every local runner dir) and
  amends its labels in place on GitHub (RunnerRegistry PUT) instead of
  re-enrolling; contracts converge every run; a stale local dir whose
  runner is gone server-side re-enrolls into the same dir.
- status is discovery-based — the machine's view, never a repo's:
  scope/name from .runner records (offline-safe), labels from GitHub
  (unknown when offline, flagged when gone), agent facts per agent-
  labeled enrollment.
- dev.yml `runner:` is retired (warns and is ignored); RUNNER_HOST_KEYS
  and the manifest/context runner fields are gone; RunnerSetupConfig is
  now flag-resolved only. ProjectContext carries the manifest name.

Closes #161.

Co-authored-by: Cursor <cursoragent@cursor.com>
@codecov

codecov Bot commented Sep 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

The rewrite dropped the default-factories test, leaving the three
default lambdas (setup/contracts/status) uncovered. Restored for the
new wiring: construction boundaries intercepted, discovery redirected
at an empty home so the run never reads this machine's enrollments.

Co-authored-by: Cursor <cursoragent@cursor.com>
@JPDuchesne
JPDuchesne merged commit 10ae6fc into main Sep 13, 2026
5 checks passed
@JPDuchesne
JPDuchesne deleted the jpd/dev-161-runner-scope-labels branch September 13, 2026 01:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

dev runner: scope x labels with derived defaults; retire the dev.yml runner block

1 participant