Skip to content

tech-debt: PM-tool adapters implement neither assignee nor board membership — an item can be written and stay invisible #402

Description

@rucka

Story Statement

As a maintainer whose board is read filtered by assignee
I want every PM-tool implementation guide to document how an item becomes visible — both its membership in the tracked view and its assignee
So that a skill following the guide cannot produce an item that exists, is open, is green, and is invisible to the team

Where: knowledge/guidelines/collaboration/project-management-tool/ (the per-tool adapters + their contract in README.md), plus conformance coverage. Not the adoption: way-of-working.md:7 already names the project.

Epic Context

Parent Epic: nessuna — debito trasversale sul layer PM-tool adapter.
Status: Refined
Priority: P1 — the adoption rule already exists and is not executable; every further day produces invisible items.

Classification

risk:yellow · cost:green · coupling: not assessed — no domain artifacts

Matrix — per dimension
Dimension Tier Source Note
Service/domain criticality yellow KB default no Criticality Table declared ⇒ Medium (D21)
Change/diff risk yellow file ownership edits files with live hunks from two parked PRs (#389, #390) — surgical placement is a correctness requirement, not a preference
Business impact green subdomain class Integration & Process Standardization (Supporting); no product surface
Security relevance green path heuristic documentation + conformance test; no credential, no runtime code
Coupling balance not assessed absent no new integration point

Problem (evidence)

way-of-working.mdAssignment states that skills creating or updating items "set the assignee as part of the write, never as a follow-up step". Nothing implements it:

  • assigneezero occurrences in .skills/capability/write-issue/SKILL.md
  • assigneezero occurrences across every file in project-management-tool/

Second gap, with a reproduced failure. write-issue Step 7.3 writes the board status field "per the implementation guide". That presumes the item is already in the tracked view. On GitHub Projects it may not be — an issue and a project item are distinct objects, and membership is a separate addProjectV2ItemById call. github-implementation.mdUpdate Item StatusStep 2: Find the Item ID for the Issue has no branch for "not an item yet": it yields an empty id and Step 3 dies with

gh: Could not resolve to a node with the global id of ''

Worse than the hard failure: a caller that does not check the empty id skips the board write and reports success.

Observed 2026-07-30#384 and #372 were open, assigned, green, and absent from the board entirely. Found by hand while launching a batch; no gate caught it.

Why the adapter, not the skill

Membership-as-a-separate-step is GitHub-specific:

Adapter Membership
GitHub Projects explicitaddProjectV2ItemById; an issue exists without being an item
Linear implicit — an issue always belongs to a team
Filesystem implicit — the file's location is its membership

A generic "add the item first" rule in the skill would be false for two adapters out of three. And it is unnecessary: Step 7.2 already delegates ("Configure project field settings … per the implementation guide"), so a corrected guide is picked up through the existing delegation with no skill edit.

Acceptance Criteria

Functional Requirements

  1. Given an issue that is not yet a project item
    When a caller follows github-implementation.md to set its status
    Then the guide adds it as an item first and the status write succeeds — the empty-id failure above is unreachable by following the guide

  2. Given the item-id lookup yields nothing
    When a caller follows the guide
    Then that is an explicit branch, never an unhandled empty value and never a silently skipped board write reported as success

  3. Given any adapter's issue-create recipe
    When an item is created through it
    Then the recipe sets the assignee as part of the create, per the adoption's Assignment rule — so the rule becomes executable rather than remembered

  4. Given an adapter where membership is implicit (filesystem, azure-devops)
    When an agent reads it
    Then the guide says so explicitly — silence is what makes an agent invent an add-item step that does not exist for that tool

  5. Given the adapter contract in README.md
    When a new adapter is added
    Then documenting membership semantics and the assignee mechanic is a stated requirement, so an omission is visible instead of discovered in production

  6. Given the conformance suite
    When it runs
    Then it asserts membership + assignee coverage per adapter file present, data-driven, with no hardcoded adapter count[US-236] feat: code host separate from PM tool (WoW override) — GitHub + Linear reference case #389 adds a sixth (linear-implementation.md)

Business Rules

Edge Cases and Error Handling

  • Already a member: addProjectV2ItemById on an existing item returns that item rather than duplicating — document it, so the recipe is safe to run unconditionally.
  • Issue in more than one project: the adoption names the project — target that one, never guess or take the first.
  • No project configured at all (minimal board, D4): the membership step no-ops, consistent with the existing "no board state maps to this macrostate" degradation — it must not become a HALT for projects that legitimately have no board.
  • Assignee unresolvable (not a collaborator, org restriction): report it; never drop the assignee silently, which reproduces the invisibility this story removes.

Definition of Done Checklist

  • All acceptance criteria implemented and verified
  • Dataset edited first, then mirrored to root .pair/ with the transform applied — mirror-equality guard green
  • Conformance test in the existing per-artifact file, not a new story-named one (ADL 2026-07-18)
  • The conformance assertions are injection-tested: each goes red when the claim it pins is removed, so none is vacuous
  • pnpm quality-gate green and lint green before every push
  • PR follows pr-template.md and lists no expected rebase conflicts (placement is verified disjoint)

Dependencies

Notes

Filed during the launch of the #278/#384/#372 batch, from a failure hit while adding those two stories to the board by hand. Kept out of that batch deliberately: the area is the most contested in the repo right now, and the scope above is the part that survives hunk-level verification.

Task Breakdown

  • T-1: github-implementation.mdFind the Item ID gains the not-an-item-yet branch (addProjectV2ItemById, then set the field on the returned id) + the explicit empty-id branch
  • T-2: github-implementation.md — assignee in the create/update recipes, plus the "assignee ≠ membership, both required" statement
  • T-3: azure-devops-implementation.md + filesystem-implementation.md — membership stated as implicit, assignee equivalent documented
  • T-4: README.md — adapter contract requires documenting membership semantics + assignee mechanic
  • T-5: conformance coverage, data-driven over the adapter files present, injection-tested
  • T-6: mirror the dataset edits to root .pair/ with the transform; guard green

Dependency Graph

T-1 ──┬── T-2 ──┬── T-4 ── T-5 ── T-6
      └── T-3 ──┘

T-1 first: its shape (how the branch is expressed) is the pattern T-3 mirrors for the implicit-membership tools. T-5 after T-4, because the contract in README is what the conformance test pins. T-6 last, once dataset content is final.

AC Coverage

AC Tasks
1 — add-item-then-status T-1, T-6
2 — explicit empty-id branch T-1
3 — assignee in create recipe T-2, T-3
4 — implicit membership stated T-3
5 — adapter contract T-4
6 — data-driven conformance, no count T-5

Scope moved in from #403 (2026-07-31)

linear-implementation.md's Item Visibility section was originally deferred to #403, because the file did not exist on main. #389 then merged, bringing it — and this story's guard requires that section from every adapter present, so the obligation fell here rather than on a later story.

Delivered in bdd175c8: membership stated as implicit for a sharper reason than the filesystem adapter's — issueCreate requires teamId, so a Linear issue cannot exist without belonging to a team, and optional projectId groups within it rather than making the issue visible. Plus the assignee mechanic (assigneeId on create with the user-id lookup, idempotent on update, reported rather than dropped when unresolvable). Conformance 71 → 79.

#403's remaining scope is unchanged: the /write-issue contract ($assignee in the parameter table, the membership-precedes-state invariant, HALT on an unresolvable item). It is now unblocked#389 merged as 2da33a88.

Metadata

Metadata

Assignees

Labels

risk:yellowClassification: medium risk tiertech-debtTracked technical debt (living backlog, R7.2 — never blocks a PR)user storyWork item representing a user story

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions