Skip to content

Decide the DLC's tracker contract on Azure DevOps #387

Closed

Description

@orioltf

Question

The Boxes' tracker contract was written against GitHub's object model. Installing the DLC into
DXP-DesignSystem (#376) surfaced four places where Azure DevOps does not answer it. They are one
decision, not four, because each is a consequence of the same choice: what the Harness hands a node
when it says "name TARGET_REPO explicitly".

Read the finding list on #376 first — it names the file and the node for each.

  1. Addressing. repo_ref is the origin URL, one string. Azure DevOps needs organisation,
    project and repository as three arguments. tracker.coords already holds all three, but only two
    nodes read it and neither is told to prefer it. Which of the two identifies the repository, and
    what is the other one for?
  2. Scope. A work item belongs to the project, not to a repository. dxp holds
    DXP-DesignSystem, DXP-Website and DXP-ProfileServices, so "file the issue on TARGET_REPO"
    has nothing to execute and spike-ticket's idempotency search matches the other two repositories'
    tickets. What second scope keeps three repositories apart inside one project — area path, tag, or
    something the config already carries?
  3. Linking. Nothing the DLC produces links back to a work item. Azure DevOps links by AB#<id>
    in the PR or commit text; the PR body template in unic-dlc-build.yaml open-pr carries no
    work-item reference and Archon's branch names carry no id. unic-dlc-pr-review.yaml prep then
    looks for "linked work items … from the PR body, branch name, or tracker links" and finds none.
    Where does the id enter the pipeline, and which node writes it?
  4. Classification. classification.labels fixes one axis per tier. On Azure DevOps the state
    tier collapses five of eight roles onto New and the type tier collapses three of five onto
    Task, so /triage cannot tell needs-triage from ready-for-agent — the one distinction the
    pipeline gates on. Tags carry all seventeen roles. Does a role gain a per-role axis, does the
    whole tier move to tags, or does the Harness stop asking a tracker to store its state?

Whatever is decided has to hold without a host CLI token, subcommand, flag or provider name in a Box
prompt — that rule is the reason a closed attempt shipped a subcommand that does not exist.

Activity

  1. orioltf commented on Aug 17, 2026

    @orioltf
    MemberAuthor

    How to start this session

    1. Run /wayfinder 373 #387 here to claim it. Invoke /grilling and /domain-modeling — this is a
      vocabulary decision as much as a wiring one.
    2. Read the finding list on Install unic-archon-dlc into DXP-DesignSystem by hand, on day 1 #376 before the body. It names the file and the node for each gap and
      carries the evidence (the bootstrap output, the archon complete warning, the ADO state list).
    3. The installed Consumer is the Consumer's clone on
      feature/42928_initial-DLC-installation. Read its .archon/unic-dlc.config.yaml — the collapsed
      classification.labels is question 4 made concrete.

    Traps

    • The four questions look separable and are not. Answering addressing without scope produces a
      contract that names a repository no work item belongs to.
    • Do not write a host CLI token, subcommand, flag or provider name into a Box prompt. That rule is
      why the gaps exist and it does not bend to close them.
    • unic-pr-review's ado-fetcher and ado-writer already solve the addressing and thread shapes
      against this tenant. Read how, then decide what the Harness owns — do not copy ADO code into a Box.
    • Decision 3 stands: the plugin is prose. The answer is a rule a node can read, not a module.

    Read the "Tenant facts" comment below this one before the body. It was gathered after this opener
    was written. Question 2 is already answered there — the repo discriminator is System.AreaPath, with
    the three exact strings — and question 4 carries measured tag usage plus the two roles that are
    actually load-bearing. Starting from the body alone re-derives all of it.

  2. orioltf commented on Aug 17, 2026

    @orioltf
    MemberAuthor

    Tenant facts, gathered 2026-08-17

    Read off the Consumer's Azure DevOps project before the grilling session, so it does not rediscover them. Every string below is quoted exactly as the API returned it.

    Question 2 is answered: the scope is System.AreaPath

    The Consumer manages every DXP repository in the one dxp project, and splits work by area. The area names the repository:

    dxp\DXP - <customer>\Website - PWA          → DXP-Website
    dxp\DXP - <customer>\PS - Profile Service   → DXP-ProfileServices
    dxp\DXP - <customer>\DS - Design System     → DXP-DesignSystem
    

    Note PS - Profile Service is two words. The DS - Design System area was created today for this effort; before that the design system had no area and its work items sat in dxp\DXP - <customer>\Unknown - New.

    So unic-dlc-qa.yaml uat-gate.on_reject and unic-dlc-explore.yaml spike-ticket need an area path, not a repository, and spike-ticket's idempotency search must filter on it or it will match the other repositories' tickets. What remains open is where the DLC learns the mapping — tracker.coords is the obvious home, but it currently holds {org, project, repo} and nothing that names an area.

    Question 4 is constrained: the tag namespace is real, large and inconsistent

    dxp carries 293 tags. Usage over the last 540 days, from a query capped at 1000 work items — these are floors, and the ranking is the signal, not the absolute number:

      49  Specification          ← the live spelling
      43  Spike
      42  Ref: FE
      20  Ref: BE
      16  Ref: All
       4  Ref: Specs
       3  Ref: UX
       2  Specs
       1  TriageNeeded
       1  readyForImplementation
       1  Documentation
       0  Ref: Spec · Tech-Debt · feature · Task · Blocked · Ref: Analytics
    

    Four spellings of one idea, one of which carries the weight. Adding seventeen dlc:-prefixed tags to this would be noise on noise. Adopting the names the Consumer already has costs nothing and collides with nothing.

    Only two roles are load-bearing

    A collapsed role costs something only when a Box reads the value back. Across the four installed Boxes, state and type are write-only — no node queries either. The round trip happens in /triage → /specs → /tickets → /build, and it turns on two roles.

    role who reads it verdict
    ready-for-agent /tickets writes it, /build dispatches from it needs a real value — without it there is no AFK queue
    needs-specs /specs picks up from it needs a real value
    needs-triage nothing New states it honestly; leave it
    needs-info, ready-for-human humans only the collapse onto New costs no Box anything
    resolved, closed, rejected — genuine ADO states already

    The two that need a value have a home in the Consumer's existing vocabulary:

    needs-specs      → Specification            (49 uses — adopt it, retire Specs / Ref: Spec / Ref: Specs)
    ready-for-agent  → readyForImplementation   (1 use — dormant, so adopting it collides with nothing)
    

    Both are Tags, while resolved / closed / rejected are States. That is the per-role axis this ticket's question 4 offers as its first option, and this is the evidence for it: a whole-tier answer either loses the AFK queue or writes a state ADO will reject.

    The type tier needs nothing

    ADO forces a work item type at creation, no Box reads type back, and feature / spike / tech-debt / docs collapsing onto User Story / Task costs the pipeline nothing. Spike at 43 uses is worth keeping as a human-facing tag, but that is board hygiene, not DLC wiring.

    Spike maps to the DLC type role spike, which unic-dlc-explore.yaml spike-ticket writes. It is not Matt's /prototype — that skill is interactive, /explore names it and deliberately never invokes it, and no config role points at it.

    Ref: * is a fourth axis the DLC has no tier for

    FE, BE, QA, UX, Analytics, All, Ops, FE-BE, FE-Ops. That is discipline, not state, type or priority. Recorded so nobody later reads it as the type tier. The Harness should not grow a tier for it.

    Not changed by any of this

    Question 1 (addressing) and question 3 (work-item linking) stand as written. Area answers which work items belong to this repository; it says nothing about how a node addresses the repository itself, and nothing writes AB#<id> yet.

  3. self-assigned this
    on Aug 17, 2026
  4. orioltf commented on Aug 17, 2026

    @orioltf
    MemberAuthor

    Resolution

    The tracker contract is two repo-local prose files, not a config schema. A Box names a role and a
    file. It never names a host word.

    The four questions were one question — where a host word is allowed to live — and the answer changes
    the container rather than widening the schema.

    What settled it

    setup-matt-pocock-skills has no Azure DevOps support. It offers GitHub, GitLab and local markdown,
    and for anything else it says: ask the user to describe the workflow in one paragraph, then write
    docs/agents/issue-tracker.md from scratch. So Matt has no ADO answer. He has a place to write ADO
    down — and his own GitHub template is full of gh issue create --title and gh api --method POST.
    The skill text stays generic; the repo's own doc carries every host word.

    That is the split the DLC wanted. The DLC built a different container for it: tracker.coords,
    classification.labels, project.pr_strategy, and ADR-0024's rule that a Box must not read
    docs/agents/issue-tracker.md.

    Two facts found while deciding, neither on #376:

    • Four Methods installed at the Consumer say "The issue tracker and triage label vocabulary should have been
      provided to you"
      — code-review, triage, to-spec, to-tickets. DXP-DesignSystem has no
      docs/agents/ directory. code-review, which /pr-review reads, is already looking for a file
      that is not there.
    • issues.json carries no tracker id. Issue.id is documented as "unique identifier for this issue
      within the file"
      . So nothing downstream can reference a tracker item on any host, and
      open-pr's PR body has no Closes #<n> either. The linking gap is not an ADO problem.

    The decision

    Two files, Matt's split, owned by DLC /setup.

    docs/agents/issue-tracker.md

    1. Access — which MCP server or skill serves this tracker. Read its current interface.
    2. Addressing — organisation, project, repository.
    3. Scope — the area path for this repository, and the rule that every search filters on it.
    4. Operations — conditional. Written only where no MCP and no skill can supply the how. Matt's
      GitHub template shape. The fallback, never the norm.

    docs/agents/triage-labels.md

    1. Roles — the 17 roles, each row naming its axis: State, Tag, Work Item Type, or the priority
      field.

    Matt's split is kept for compatibility: someone who knows his system looks in triage-labels.md for
    the vocabulary, and only code-review hard-codes a path (issue-tracker.md). Both files name DLC
    /setup as their owner at the top, because running setup-matt-pocock-skills over triage-labels.md
    reverts it to a five-role wontfix vocabulary.

    A section earns its place only if it is a fact about this tenant. An MCP server discovers an API.
    It cannot discover that the Consumer's area path is this repository's area, or that
    ready-for-agent means the tag readyForImplementation. So Create, Read, Search, Comment, Linking
    and PR-thread shape are all dropped: writing them down freezes a flag table in Markdown, which is the
    same defect ADR-0016 forbids in a Box prompt and harder to notice.

    What leaves the config

    Key Why it goes
    the whole tracker block type — nothing branches on it; spike-ticket binds it and then says "do NOT branch on which provider it names". access and coords — the doc carries them, and the Methods read the doc
    classification.labels triage-labels.md carries the roles, with an axis per role
    project.pr_strategy not a tracker concern and not a DLC concern. The host's branch policy wins when they disagree, and a team's merge rule already lives in its own CLAUDE.md
    repo_ref and the ambiguous-repo guard the doc names the repository, so deriving one from a URL and then guarding the derivation answers a question already answered

    MANDATORY_PATHS becomes project.branching alone.

    Linking

    Three separate things, all tracker-agnostic:

    1. /tickets writes the tracker id into issues.json. The prerequisite — without it nothing
      downstream can reference the tracker item on any host.
    2. open-pr links each work item through the registered skill's own link capability. Both PRs
      and work items carry a links collection and it is discoverable, so the Box says "link", not
      AB#<id>. Naming the text token in a doc would pick the weaker of the two and freeze it.
    3. The commit scope convention — DXP writes feat(42928): …, the loop writes feat(<slug>): … —
      is a repo convention, not a tracker contract. It goes in the Consumer's CLAUDE.md, beside the
      branch-naming rule already there.

    ADR-0024

    Amended in place, not superseded. Four Box prompts cite it by name, so it cannot vanish. Two things
    in it are now dead:

    • The compose rule — "Matt's own setup artifacts are never consulted in DLC flows" — is reversed.
      It solved a real two-writer problem by forbidding the read; this decision solves it by removing one
      writer.
    • The 2026-08-11 amendment's "the tier carries the axis" is disproved. It claimed a Box hands the
      tier alongside the string so the skill knows to write a System.State, a Jira status or a GitHub
      label. On dxp, needs-specs and ready-for-agent cannot be System.State values — they have to
      be Tags. The axis belongs to the role, not the tier.

    Findings closed

    From #376: 1 (addressing), 2 (URL spellings — the guard is deleted, not fixed), 3 (work
    items belong to the project), 5 (no axis wide enough), 6 and its correction (pr_strategy),
    7 (threads not comments — now a prose fix in unic-dlc-pr-review.yaml, since the shape is
    discoverable).

    Still work: 4 (linking), split into the three items above. Still Archon's: 8 and 9.

    Not decided here

    CONTEXT.md's Repository derivation entry describes repo_ref and its guard, both deleted by
    this decision. The glossary is not edited yet: it correctly describes the plugin as it stands today,
    and rewriting it before the code changes would make it lie. It belongs to the plugin ticket below.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions