T-WPBJ-labels-sdlc-stage-stage-sdlc-auto-stage-apply-manages-the
State: closed/done · Impact: medium · Complexity: medium
sdlc:stage/<stage> labels position, sdlc:auto/<stage> sets the autonomy ceiling; apply manages
the label vocabulary on the repo. Design: D-0019-sdlc-chain-stages-and-labels.
Approach
Section titled “Approach”- Add
gh labelsupport to@sksizer/easy-gh(packages/ts/easy-gh/):verbs.tsgains argv builders + JSON parsers forlabel list(gh label list --json name,color,description),label create(gh label create <name> --color <hex> --description <text>) andlabel edit(gh label edit <name> --color <hex> --description <text>);sync.ts’sGhclass gainslabelList()(query, returnsLabel[] | null),createLabel()andeditLabel()(mutations, throwCommandFailedon non-zero exit, same tri-modal pattern ascreatePr/editPr);types.ts’s existing (currently unused)Labeltype becomes the real return shape. - Add
solutions/ontological/lib/services/apply/labels.tsimplementing theApplierinterface (lib/services/apply/types.ts):name: 'labels'. The canonical 22-label vocabulary is derived, not hand-listed — importCHAIN_STAGE_NAMESfromlib/config/chain.ts(landed by T-8JJE; coordinate merge order, or take a short-lived local copy if T-8JJE hasn’t landed yet and switch to the import once it has) and buildsdlc:stage/<name>+sdlc:auto/<name>for each.plan(ctx)callsnew Gh(ctx.projectRoot, { runner: ctx.gh }).labelList(), diffs the live label set against the vocabulary (by name; a name-color-or-description mismatch is anupdateChange, a missing name is acreateChange), and returnsChange[]— never aremove(the applier does not delete labels it doesn’t own, including a repo’s pre-existing, non-sdlc:-prefixed labels).apply(ctx, changes)realizes exactly the changesplanreturned, viacreateLabel/editLabel. - Register the applier: add
'labels'toApplierNameandAPPLIER_NAMES(lib/config/meta.ts), add it to theAPPLIERSmap inlib/services/apply/registry.ts. No newsdlc.yamlconfig key is needed — the vocabulary has one source of truth (CHAIN_STAGE_NAMES), not a project-editable list. - Pick a small, fixed, deterministic color scheme (documented as a
comment in
labels.ts, not user-configurable): one hex per family (e.g. a blue for everysdlc:stage/*, an orange for everysdlc:auto/*) — the exact stage/ceiling within a family is carried by the label name, not the color, so one color per family is sufficient and keeps the diff logic simple. - Add
solutions/ontological/lib/services/apply/labels.test.tsfollowinghooks.test.ts’s direct-applier-call pattern: construct actxwith a fakeghCommandRunner(a stub.run(argv, opts)returning cannedgh label list --json ...output, recording calls made) — no realgh/network. Cover: empty repo (all 22 ascreate), a repo with some labels already correct (only the missing/mismatched ones as changes), andapply()issuing exactly the argvplan()promised for eachChangekind. sdlc apply --only labels --check/--dry-runexercise the new applier through the existing generic apply CLI surface (no new flags needed —--onlyalready takes an applier name).
| Area | Note |
|---|---|
packages/ts/easy-gh/verbs.ts | New label list/label create/label edit argv builders + parsers |
packages/ts/easy-gh/sync.ts | New Gh.labelList/createLabel/editLabel methods |
packages/ts/easy-gh/types.ts | Wire the existing Label type to real use |
solutions/ontological/lib/services/apply/labels.ts | New applier: plan/apply for the 22-label vocabulary |
solutions/ontological/lib/services/apply/registry.ts | Register the labels applier |
solutions/ontological/lib/config/meta.ts | Add 'labels' to APPLIER_NAMES |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1:
sdlc apply --only labels --checkagainst a fixture with nosdlc:*labels reports all 22 as pending (create), and exits 1 (thecheckconvention already established by the other appliers). - AC-2: Re-running
plan()against a fixture where all 22 already exist with the correct color/description returns zero changes (idempotent). - AC-3:
apply()never emits aremoveChange and never calls a delete/removegh labelverb, even when the fixture’s live label set has extra, non-sdlc:-prefixed labels. - AC-4:
bun test solutions/ontological/lib/services/apply/labels.test.tspasses using a fakectx.ghrunner only — no realghinvocation.
Out of scope
Section titled “Out of scope”- Wiring label reads/writes into actual stage transitions — that is the
issuesloop’s job (T-0AKS), which relabels an issue after a successful stage dispatch. This task only makes the vocabulary exist and be manageable viaapply. - A user-configurable label color scheme or a project-level opt-out of specific labels.
Dependencies
Section titled “Dependencies”solutions/ontological/lib/config/chain.ts(T-8JJE) forCHAIN_STAGE_NAMES, the single source of truth for the 22 label names. If T-8JJE has not landed yet when this task starts, take a short-lived local copy of the 11 stage names and switch to the import once it lands — never hand-maintain two separate stage-name lists past that point.