Provider-neutral tracker automation CLI and library #16

Open
opened 2026-08-17 17:30:27 -04:00 by steve · 1 comment
Owner

Problem Statement

AI agents currently perform triage by issuing raw provider-specific CLI commands. A single user request can cause several exploratory queries, repeated attempts, provider-specific syntax errors, and incomplete recovery. Common operations also have hidden prerequisites: for example, applying a label in Gitea requires the label to exist first. GitHub, GitLab, and Gitea use different names, flags, output shapes, numbering rules, comment commands, and relationship APIs. The current repository documents those differences but provides no executable abstraction.

The result is slow, unreliable triage and unnecessary tool-call churn. The agent needs one dependable operation at the level of the user's intent, rather than a sequence of low-level gh, glab, or tea commands.

Solution

Create a standalone provider-neutral tracker package with a JSON-producing CLI. The package exposes a common operation vocabulary and delegates repository work to the configured provider CLI: gh for GitHub, glab for GitLab, and tea for Gitea.

Each high-level command performs its complete action, including safe prerequisites such as ensuring a missing label exists. Provider selection is explicit when requested, otherwise resolved from the current repository. The CLI has this precedence:

  1. --provider github|gitlab|gitea
  2. TRACKER_PROVIDER=github|gitlab|gitea
  3. provider detection from the repository's Git remote

The package exposes the same behavior as a reusable library and as an agent-facing CLI. Success and failure are returned through a stable JSON contract. Operations are idempotent where practical, retries are bounded and limited to transient failures, and authentication remains delegated to the provider CLIs.

The common surface covers every operation described by the existing GitHub tracker guide, normalized for GitHub, GitLab, and Gitea: issues, pull requests/merge requests, labels, comments, triage filtering, provider-specific numbering, wayfinding maps and child tickets, dependencies, frontier queries, claiming, and resolution.

User Stories

  1. As an AI agent, I want to create an issue with one command, so that I do not need to translate a request into provider-specific CLI syntax.
  2. As an AI agent, I want to create a pull request or merge request with one command, so that the user receives the requested change surface without extra discovery calls.
  3. As an AI agent, I want to read an issue with its comments and labels, so that I have the complete triage context in one response.
  4. As an AI agent, I want to read a pull request or merge request with its comments, labels, and diff, so that I can triage it without separate provider commands.
  5. As an AI agent, I want to list issues by state and label, so that I can find actionable work deterministically.
  6. As an AI agent, I want to list pull requests or merge requests by state, so that I can inspect the correct request surface.
  7. As an AI agent, I want list results in a common JSON shape, so that the same skill logic works across providers.
  8. As an AI agent, I want to add a label to an issue or request, so that I can classify work consistently.
  9. As an AI agent, I want to remove a label from an issue or request, so that stale classification can be corrected consistently.
  10. As an AI agent, I want to ensure a label exists before applying it, so that a missing provider label does not cause a failed triage action.
  11. As an AI agent, I want label creation and assignment to be one high-level action, so that I do not need a separate existence query.
  12. As a maintainer, I want existing label colors and descriptions preserved by default, so that an ensure operation does not unexpectedly rewrite shared metadata.
  13. As a maintainer, I want newly created labels to receive deterministic defaults, so that behavior is repeatable across providers.
  14. As an AI agent, I want to assign an issue or request to a user, so that claiming work does not require provider-specific syntax.
  15. As an AI agent, I want to post a comment or note, so that decisions and triage explanations are recorded consistently.
  16. As an AI agent, I want to close an issue or request with an explanation, so that closing remains a complete user-intent operation.
  17. As an AI agent, I want to distinguish issues from pull requests explicitly, so that shared GitHub and Gitea number spaces cannot select the wrong resource.
  18. As an AI agent, I want an explicit resolve operation for ambiguous issue-or-request references, so that shared number spaces can be handled intentionally.
  19. As an AI agent, I want GitLab merge requests represented as pull requests in the common contract, so that provider naming does not leak into generic workflows.
  20. As an AI agent, I want the tool to infer the provider from the repository remote, so that normal use requires no provider-specific setup.
  21. As an AI agent, I want to override provider detection with a CLI argument, so that mirrored repositories and unusual remotes remain usable.
  22. As an AI agent, I want to override provider detection with an environment variable, so that skills and automation can control the provider without changing every command.
  23. As an AI agent, I want CLI and environment overrides to take precedence over remote detection, so that an explicit choice is never silently ignored.
  24. As an AI agent, I want ambiguous or unsupported provider detection to fail clearly, so that I do not retry the same wrong command in different forms.
  25. As an AI agent, I want the tool to use the configured gh, glab, or tea credentials, so that the automation does not duplicate token management.
  26. As an AI agent, I want missing authentication reported as a structured actionable error, so that I can ask the human for setup instead of guessing.
  27. As an AI agent, I want transient CLI or network failures retried a bounded number of times, so that temporary failures recover without runaway repetition.
  28. As an AI agent, I want semantic failures such as invalid issue numbers to avoid automatic retries, so that the tool does not repeat an impossible action.
  29. As an AI agent, I want idempotent operations to be safe when repeated, so that recovering from an uncertain result does not duplicate labels, comments, or assignments where duplication can be avoided.
  30. As an AI agent, I want every result to identify the provider and operation, so that logs and follow-up decisions are understandable.
  31. As an AI agent, I want successful results to include normalized resource data and provider-specific details when available, so that generic skills can act without losing useful context.
  32. As an AI agent, I want failures to include a stable error code, human-readable message, retryability, provider, operation, and details, so that recovery is deterministic.
  33. As a maintainer, I want stdout reserved for machine-readable JSON, so that an agent can parse results reliably.
  34. As a maintainer, I want diagnostics kept separate from the JSON result, so that debug output cannot corrupt the protocol.
  35. As an AI agent, I want to create a wayfinding map issue, so that a large effort has one canonical tracker artifact.
  36. As an AI agent, I want to create a child ticket linked to a wayfinding map, so that decisions remain discoverable from the map.
  37. As an AI agent, I want child tickets to carry a normalized wayfinder type, so that research, prototype, grilling, and task tickets are consistently classified.
  38. As an AI agent, I want native child-issue relationships used where supported, so that the tracker UI displays the map structure.
  39. As an AI agent, I want a documented fallback when native child relationships are unavailable, so that wayfinding still works on lower-tier or incompatible providers.
  40. As an AI agent, I want to add a native blocking dependency where supported, so that the tracker shows the true frontier.
  41. As an AI agent, I want a documented body or task-list fallback for blocking relationships, so that blocked work remains machine-discoverable without native dependencies.
  42. As an AI agent, I want to query the open, unblocked, unassigned children of a map, so that I can select the next frontier ticket without repeated manual filtering.
  43. As an AI agent, I want frontier ordering to be deterministic, so that concurrent sessions choose predictable work.
  44. As an AI agent, I want to claim a ticket before working on it, so that concurrent agents do not duplicate effort.
  45. As an AI agent, I want to resolve a ticket by posting its answer, closing it, and updating the map pointer, so that resolution is recorded atomically from the workflow's perspective.
  46. As an AI agent, I want provider-specific comment/note terminology hidden behind the common comment operation, so that skills do not branch on GitLab versus GitHub.
  47. As an AI agent, I want GitHub and Gitea shared number spaces handled consistently, so that issue and pull-request lookups do not silently resolve the wrong object.
  48. As an AI agent, I want GitLab's separate issue and merge-request number spaces respected, so that valid references are not rejected as ambiguous.
  49. As an AI agent, I want external pull requests and merge requests filtered according to repository policy, so that maintainer work is not incorrectly triaged as incoming work.
  50. As a maintainer, I want the external-request policy configurable, so that each repository can define whether PRs/MRs are a request surface.
  51. As a maintainer, I want provider author-association rules normalized, so that GitHub contributor associations and GitLab/Gitea membership rules produce equivalent triage results.
  52. As a maintainer, I want unsupported provider metadata to produce an explicit capability result, so that the tool does not make unsafe membership guesses.
  53. As a package consumer, I want a reusable library API over the same operations as the CLI, so that another agent integration can avoid shell parsing.
  54. As a package consumer, I want the CLI and library to share one operation contract, so that behavior does not diverge between integrations.
  55. As a maintainer, I want provider adapters isolated behind the common contract, so that adding or correcting one provider does not change agent-facing workflows.
  56. As a maintainer, I want tests to run without live credentials, so that normal development and CI are deterministic.
  57. As a test author, I want fake gh, glab, and tea executables to capture invocation sequences, so that high-level operations can prove they perform prerequisites exactly once.
  58. As a test author, I want provider contract fixtures for success, missing capability, authentication failure, invalid input, rate limiting, and transient transport failure, so that error behavior is stable.
  59. As a maintainer, I want optional live smoke tests separated from unit and contract tests, so that credentials and network availability do not gate normal validation.
  60. As a skills maintainer, I want the existing provider-specific tracker documentation to reference the common tool, so that agents stop issuing raw repeated provider commands.
  61. As a skills maintainer, I want provider-specific details retained as adapter documentation, so that fallback and capability differences remain discoverable.
  62. As a future provider maintainer, I want a provider contract test suite, so that a new tracker adapter must prove the same external behavior before being supported.

Implementation Decisions

  • Implement a standalone Python package with an agent-facing command-line interface and a reusable library API. The package is separate from this Markdown-only skills repository; the existing skills can adopt it without embedding provider logic.
  • Expose a provider-neutral command vocabulary for issues, pull requests, labels, comments, assignments, dependencies, and wayfinding operations. Use pr in the common interface and map GitLab merge requests to it.
  • Keep the highest test seam at the public CLI/library operation boundary. Inject or replace the subprocess runner beneath that boundary so tests can use fake provider executables without testing private implementation details.
  • Use provider adapters to translate the common operation model into gh, glab, and tea invocations and to normalize their output. Provider adapters may use the provider CLI's API passthrough for capabilities not exposed by a high-level subcommand, but the package must not become a direct HTTP client or token manager.
  • Resolve providers in this order: explicit --provider, then TRACKER_PROVIDER, then Git remote autodetection. Accepted provider values are github, gitlab, and gitea. An ambiguous or unsupported remote is a non-retryable structured error.
  • Infer the repository from the current Git checkout by default, matching the existing provider CLI conventions. Explicit provider selection must work for mirrored remotes and repositories whose remote hostname is not canonical.
  • Normalize issue and pull-request data into a common result model while preserving provider-specific metadata in an additional details field. Resource commands remain explicit; an issue and a pull request are not interchangeable merely because they share a number.
  • Provide create, read, list, comment, edit, label, assign, close, and diff operations for issues and pull requests/merge requests wherever the provider supports them. Provider gaps must be reported through capabilities or structured errors rather than silently omitted.
  • Implement label ensure as a first-class operation and as a prerequisite for label application. Match labels by exact name, preserve existing metadata by default, and use deterministic defaults only when creating a missing label. Label creation and assignment must be safe to retry.
  • Normalize comments and GitLab notes behind one comment operation. Normalize GitHub pull requests, GitLab merge requests, and Gitea pull requests behind the common pull-request resource.
  • Support configurable external-request triage policy. GitHub association values of CONTRIBUTOR, FIRST_TIME_CONTRIBUTOR, and NONE are external by default; owner, member, and collaborator associations are excluded. GitLab and Gitea adapters must use available membership/ownership metadata or return an explicit unsupported-capability result rather than guessing.
  • Implement wayfinding map creation, child-ticket creation, wayfinder labels, native child relationships where available, native blocking dependencies where available, frontier queries, claiming, and resolution updates. Use the documented task-list, parent-body, or Blocked by: fallbacks when native relationships are unavailable.
  • Keep wayfinding operations provider-neutral while retaining provider-specific relationship details in results. GitLab note quick actions, GitHub dependency identifiers, and Gitea API dependency parameters are adapter concerns.
  • Define frontier as open, unblocked, unassigned child tickets belonging to a map. Use map order as the deterministic tie-breaker. Native dependency state and fallback body conventions must both be supported.
  • Define claim as assignment to the current authenticated user, with an explicit provider error when the current user cannot be determined or assignment is unsupported.
  • Define resolve as posting the resolution, closing the ticket, and appending a concise context pointer to the map. If a later step fails, return the completed steps and a structured recovery state rather than pretending the operation was atomic.
  • Return one JSON envelope for every invocation. Successful results include ok, provider, operation, normalized result, and optional details. Failures include ok: false and an error object with stable code, message, retryable, provider, operation, and provider details.
  • Reserve stdout for the JSON envelope and send human diagnostics to stderr. Use process exit status zero for successful operations and nonzero for failures, while keeping the JSON error available for agent recovery.
  • Retry only bounded transient failures such as transport failures, rate limits, and explicitly retryable provider CLI failures. Do not retry invalid input, missing resources, authorization failures, unsupported capabilities, or semantic conflicts. The retry budget must be finite and visible in diagnostics/results.
  • Preserve idempotency for ensure, label, assignment, claim, and relationship operations wherever the provider allows it. Do not silently deduplicate comments; if comment duplication is possible after an uncertain result, return an uncertain-outcome error so the agent can decide.
  • Delegate authentication, credential storage, and login flows to gh, glab, and tea. The package must not accept or persist provider tokens as part of this feature.
  • Provide repository-level configuration for external-request policy and any provider membership/ownership rules needed to safely classify incoming requests. Configuration must not override explicit provider selection.
  • Keep the existing provider-specific tracker guides as reference material while adding common-tool guidance and migration instructions. The tool is the execution seam; the guides remain the source for provider-specific capability and fallback semantics.

Testing Decisions

  • Tests must assert externally visible behavior through the public operation boundary: normalized JSON, exit status, provider selection, retry behavior, and the sequence of provider CLI calls. Tests must not assert private class structure or internal helper names.
  • The primary seam is a fake subprocess runner or fake gh, glab, and tea executables. Each fake records arguments, returns controlled stdout/stderr, and can simulate transient and semantic failures.
  • Test provider detection independently through the public interface using CLI overrides, TRACKER_PROVIDER, canonical remotes, mirrored remotes, unsupported remotes, and ambiguous remotes. Assert the documented precedence.
  • Test issue and pull-request operations against provider fixtures for create, read, list, comment/note, label, assignment, close, and diff behavior.
  • Test label ensure behavior for existing labels, missing labels, metadata mismatches, repeated ensure calls, creation followed by assignment, and provider-specific label command failures.
  • Test common normalization across GitHub issues/PRs, GitLab issues/MRs, and Gitea issues/PRs, including shared versus separate number spaces and provider-specific comment terminology.
  • Test external-request filtering using GitHub author associations, GitLab/Gitea membership data, excluded maintainers, external contributors, missing metadata, and unsupported capability results.
  • Test wayfinding behavior for map creation, child linkage, native and fallback relationships, blocking dependencies, frontier filtering, deterministic ordering, claims, and resolution partial failure recovery.
  • Test retry policy with transient transport failures, rate limits, exhausted retry budgets, non-retryable semantic errors, and uncertain outcomes after a provider command may have completed.
  • Test JSON success and failure envelopes, stdout/stderr separation, stable error codes, retryability flags, and nonzero exit statuses.
  • Test idempotency by replaying ensure-label, assignment, claim, and relationship operations and asserting no duplicate side effects.
  • Include provider contract fixtures so each adapter must satisfy the same externally visible contract. Add optional live smoke tests behind an explicit credential/network gate.
  • This repository has no existing runtime modules, package manager, build system, or test suite; it is currently a Markdown skill repository. The new standalone package must establish its own test harness. There is no relevant prior test seam to reuse beyond the provider-specific behavioral documentation that serves as the contract source.

Out of Scope

  • Automatically merging pull requests or merge requests.
  • Managing provider credentials, tokens, login sessions, or authentication setup.
  • Replacing gh, glab, or tea as general-purpose provider clients.
  • A direct HTTP API client or provider-specific web service.
  • Supporting providers other than GitHub, GitLab, and Gitea.
  • A web UI, hosted service, daemon, or background workflow scheduler.
  • Unbounded retries, speculative alternate commands, or autonomous recovery from ambiguous side effects.
  • Deduplicating arbitrary comments or editing user-authored issue content without an explicit operation.
  • General project-management features not described by the existing tracker guides.
  • Implementing the package inside the current Markdown-only repository as part of this specification; adoption guidance for the skills is in scope, but package delivery remains a separate implementation boundary.

Further Notes

  • The canonical domain terms are GitHub, GitLab, Gitea, provider CLI, issue, pull request, merge request, label, note/comment, map, child ticket, blocker, dependency, frontier, claim, and resolution.
  • The existing tracker guides document provider-specific command shapes and wayfinding fallbacks. The implementation should treat their behavioral intent as the compatibility contract, not copy their raw commands into agent prompts.
  • The Gitea tracker is the issue tracker for this repository, and the published issue should carry the ready-for-agent triage label. Only that triage label should be active.
  • The implementation should be delivered with a migration note for agent skills so future triage actions call one high-level operation instead of issuing exploratory provider commands.
## Problem Statement AI agents currently perform triage by issuing raw provider-specific CLI commands. A single user request can cause several exploratory queries, repeated attempts, provider-specific syntax errors, and incomplete recovery. Common operations also have hidden prerequisites: for example, applying a label in Gitea requires the label to exist first. GitHub, GitLab, and Gitea use different names, flags, output shapes, numbering rules, comment commands, and relationship APIs. The current repository documents those differences but provides no executable abstraction. The result is slow, unreliable triage and unnecessary tool-call churn. The agent needs one dependable operation at the level of the user's intent, rather than a sequence of low-level `gh`, `glab`, or `tea` commands. ## Solution Create a standalone provider-neutral tracker package with a JSON-producing CLI. The package exposes a common operation vocabulary and delegates repository work to the configured provider CLI: `gh` for GitHub, `glab` for GitLab, and `tea` for Gitea. Each high-level command performs its complete action, including safe prerequisites such as ensuring a missing label exists. Provider selection is explicit when requested, otherwise resolved from the current repository. The CLI has this precedence: 1. `--provider github|gitlab|gitea` 2. `TRACKER_PROVIDER=github|gitlab|gitea` 3. provider detection from the repository's Git remote The package exposes the same behavior as a reusable library and as an agent-facing CLI. Success and failure are returned through a stable JSON contract. Operations are idempotent where practical, retries are bounded and limited to transient failures, and authentication remains delegated to the provider CLIs. The common surface covers every operation described by the existing GitHub tracker guide, normalized for GitHub, GitLab, and Gitea: issues, pull requests/merge requests, labels, comments, triage filtering, provider-specific numbering, wayfinding maps and child tickets, dependencies, frontier queries, claiming, and resolution. ## User Stories 1. As an AI agent, I want to create an issue with one command, so that I do not need to translate a request into provider-specific CLI syntax. 2. As an AI agent, I want to create a pull request or merge request with one command, so that the user receives the requested change surface without extra discovery calls. 3. As an AI agent, I want to read an issue with its comments and labels, so that I have the complete triage context in one response. 4. As an AI agent, I want to read a pull request or merge request with its comments, labels, and diff, so that I can triage it without separate provider commands. 5. As an AI agent, I want to list issues by state and label, so that I can find actionable work deterministically. 6. As an AI agent, I want to list pull requests or merge requests by state, so that I can inspect the correct request surface. 7. As an AI agent, I want list results in a common JSON shape, so that the same skill logic works across providers. 8. As an AI agent, I want to add a label to an issue or request, so that I can classify work consistently. 9. As an AI agent, I want to remove a label from an issue or request, so that stale classification can be corrected consistently. 10. As an AI agent, I want to ensure a label exists before applying it, so that a missing provider label does not cause a failed triage action. 11. As an AI agent, I want label creation and assignment to be one high-level action, so that I do not need a separate existence query. 12. As a maintainer, I want existing label colors and descriptions preserved by default, so that an ensure operation does not unexpectedly rewrite shared metadata. 13. As a maintainer, I want newly created labels to receive deterministic defaults, so that behavior is repeatable across providers. 14. As an AI agent, I want to assign an issue or request to a user, so that claiming work does not require provider-specific syntax. 15. As an AI agent, I want to post a comment or note, so that decisions and triage explanations are recorded consistently. 16. As an AI agent, I want to close an issue or request with an explanation, so that closing remains a complete user-intent operation. 17. As an AI agent, I want to distinguish issues from pull requests explicitly, so that shared GitHub and Gitea number spaces cannot select the wrong resource. 18. As an AI agent, I want an explicit resolve operation for ambiguous issue-or-request references, so that shared number spaces can be handled intentionally. 19. As an AI agent, I want GitLab merge requests represented as pull requests in the common contract, so that provider naming does not leak into generic workflows. 20. As an AI agent, I want the tool to infer the provider from the repository remote, so that normal use requires no provider-specific setup. 21. As an AI agent, I want to override provider detection with a CLI argument, so that mirrored repositories and unusual remotes remain usable. 22. As an AI agent, I want to override provider detection with an environment variable, so that skills and automation can control the provider without changing every command. 23. As an AI agent, I want CLI and environment overrides to take precedence over remote detection, so that an explicit choice is never silently ignored. 24. As an AI agent, I want ambiguous or unsupported provider detection to fail clearly, so that I do not retry the same wrong command in different forms. 25. As an AI agent, I want the tool to use the configured `gh`, `glab`, or `tea` credentials, so that the automation does not duplicate token management. 26. As an AI agent, I want missing authentication reported as a structured actionable error, so that I can ask the human for setup instead of guessing. 27. As an AI agent, I want transient CLI or network failures retried a bounded number of times, so that temporary failures recover without runaway repetition. 28. As an AI agent, I want semantic failures such as invalid issue numbers to avoid automatic retries, so that the tool does not repeat an impossible action. 29. As an AI agent, I want idempotent operations to be safe when repeated, so that recovering from an uncertain result does not duplicate labels, comments, or assignments where duplication can be avoided. 30. As an AI agent, I want every result to identify the provider and operation, so that logs and follow-up decisions are understandable. 31. As an AI agent, I want successful results to include normalized resource data and provider-specific details when available, so that generic skills can act without losing useful context. 32. As an AI agent, I want failures to include a stable error code, human-readable message, retryability, provider, operation, and details, so that recovery is deterministic. 33. As a maintainer, I want stdout reserved for machine-readable JSON, so that an agent can parse results reliably. 34. As a maintainer, I want diagnostics kept separate from the JSON result, so that debug output cannot corrupt the protocol. 35. As an AI agent, I want to create a wayfinding map issue, so that a large effort has one canonical tracker artifact. 36. As an AI agent, I want to create a child ticket linked to a wayfinding map, so that decisions remain discoverable from the map. 37. As an AI agent, I want child tickets to carry a normalized wayfinder type, so that research, prototype, grilling, and task tickets are consistently classified. 38. As an AI agent, I want native child-issue relationships used where supported, so that the tracker UI displays the map structure. 39. As an AI agent, I want a documented fallback when native child relationships are unavailable, so that wayfinding still works on lower-tier or incompatible providers. 40. As an AI agent, I want to add a native blocking dependency where supported, so that the tracker shows the true frontier. 41. As an AI agent, I want a documented body or task-list fallback for blocking relationships, so that blocked work remains machine-discoverable without native dependencies. 42. As an AI agent, I want to query the open, unblocked, unassigned children of a map, so that I can select the next frontier ticket without repeated manual filtering. 43. As an AI agent, I want frontier ordering to be deterministic, so that concurrent sessions choose predictable work. 44. As an AI agent, I want to claim a ticket before working on it, so that concurrent agents do not duplicate effort. 45. As an AI agent, I want to resolve a ticket by posting its answer, closing it, and updating the map pointer, so that resolution is recorded atomically from the workflow's perspective. 46. As an AI agent, I want provider-specific comment/note terminology hidden behind the common comment operation, so that skills do not branch on GitLab versus GitHub. 47. As an AI agent, I want GitHub and Gitea shared number spaces handled consistently, so that issue and pull-request lookups do not silently resolve the wrong object. 48. As an AI agent, I want GitLab's separate issue and merge-request number spaces respected, so that valid references are not rejected as ambiguous. 49. As an AI agent, I want external pull requests and merge requests filtered according to repository policy, so that maintainer work is not incorrectly triaged as incoming work. 50. As a maintainer, I want the external-request policy configurable, so that each repository can define whether PRs/MRs are a request surface. 51. As a maintainer, I want provider author-association rules normalized, so that GitHub contributor associations and GitLab/Gitea membership rules produce equivalent triage results. 52. As a maintainer, I want unsupported provider metadata to produce an explicit capability result, so that the tool does not make unsafe membership guesses. 53. As a package consumer, I want a reusable library API over the same operations as the CLI, so that another agent integration can avoid shell parsing. 54. As a package consumer, I want the CLI and library to share one operation contract, so that behavior does not diverge between integrations. 55. As a maintainer, I want provider adapters isolated behind the common contract, so that adding or correcting one provider does not change agent-facing workflows. 56. As a maintainer, I want tests to run without live credentials, so that normal development and CI are deterministic. 57. As a test author, I want fake `gh`, `glab`, and `tea` executables to capture invocation sequences, so that high-level operations can prove they perform prerequisites exactly once. 58. As a test author, I want provider contract fixtures for success, missing capability, authentication failure, invalid input, rate limiting, and transient transport failure, so that error behavior is stable. 59. As a maintainer, I want optional live smoke tests separated from unit and contract tests, so that credentials and network availability do not gate normal validation. 60. As a skills maintainer, I want the existing provider-specific tracker documentation to reference the common tool, so that agents stop issuing raw repeated provider commands. 61. As a skills maintainer, I want provider-specific details retained as adapter documentation, so that fallback and capability differences remain discoverable. 62. As a future provider maintainer, I want a provider contract test suite, so that a new tracker adapter must prove the same external behavior before being supported. ## Implementation Decisions - Implement a standalone Python package with an agent-facing command-line interface and a reusable library API. The package is separate from this Markdown-only skills repository; the existing skills can adopt it without embedding provider logic. - Expose a provider-neutral command vocabulary for issues, pull requests, labels, comments, assignments, dependencies, and wayfinding operations. Use `pr` in the common interface and map GitLab merge requests to it. - Keep the highest test seam at the public CLI/library operation boundary. Inject or replace the subprocess runner beneath that boundary so tests can use fake provider executables without testing private implementation details. - Use provider adapters to translate the common operation model into `gh`, `glab`, and `tea` invocations and to normalize their output. Provider adapters may use the provider CLI's API passthrough for capabilities not exposed by a high-level subcommand, but the package must not become a direct HTTP client or token manager. - Resolve providers in this order: explicit `--provider`, then `TRACKER_PROVIDER`, then Git remote autodetection. Accepted provider values are `github`, `gitlab`, and `gitea`. An ambiguous or unsupported remote is a non-retryable structured error. - Infer the repository from the current Git checkout by default, matching the existing provider CLI conventions. Explicit provider selection must work for mirrored remotes and repositories whose remote hostname is not canonical. - Normalize issue and pull-request data into a common result model while preserving provider-specific metadata in an additional details field. Resource commands remain explicit; an issue and a pull request are not interchangeable merely because they share a number. - Provide create, read, list, comment, edit, label, assign, close, and diff operations for issues and pull requests/merge requests wherever the provider supports them. Provider gaps must be reported through capabilities or structured errors rather than silently omitted. - Implement label ensure as a first-class operation and as a prerequisite for label application. Match labels by exact name, preserve existing metadata by default, and use deterministic defaults only when creating a missing label. Label creation and assignment must be safe to retry. - Normalize comments and GitLab notes behind one comment operation. Normalize GitHub pull requests, GitLab merge requests, and Gitea pull requests behind the common pull-request resource. - Support configurable external-request triage policy. GitHub association values of `CONTRIBUTOR`, `FIRST_TIME_CONTRIBUTOR`, and `NONE` are external by default; owner, member, and collaborator associations are excluded. GitLab and Gitea adapters must use available membership/ownership metadata or return an explicit unsupported-capability result rather than guessing. - Implement wayfinding map creation, child-ticket creation, wayfinder labels, native child relationships where available, native blocking dependencies where available, frontier queries, claiming, and resolution updates. Use the documented task-list, parent-body, or `Blocked by:` fallbacks when native relationships are unavailable. - Keep wayfinding operations provider-neutral while retaining provider-specific relationship details in results. GitLab note quick actions, GitHub dependency identifiers, and Gitea API dependency parameters are adapter concerns. - Define frontier as open, unblocked, unassigned child tickets belonging to a map. Use map order as the deterministic tie-breaker. Native dependency state and fallback body conventions must both be supported. - Define claim as assignment to the current authenticated user, with an explicit provider error when the current user cannot be determined or assignment is unsupported. - Define resolve as posting the resolution, closing the ticket, and appending a concise context pointer to the map. If a later step fails, return the completed steps and a structured recovery state rather than pretending the operation was atomic. - Return one JSON envelope for every invocation. Successful results include `ok`, `provider`, `operation`, normalized `result`, and optional `details`. Failures include `ok: false` and an error object with stable `code`, `message`, `retryable`, `provider`, `operation`, and provider details. - Reserve stdout for the JSON envelope and send human diagnostics to stderr. Use process exit status zero for successful operations and nonzero for failures, while keeping the JSON error available for agent recovery. - Retry only bounded transient failures such as transport failures, rate limits, and explicitly retryable provider CLI failures. Do not retry invalid input, missing resources, authorization failures, unsupported capabilities, or semantic conflicts. The retry budget must be finite and visible in diagnostics/results. - Preserve idempotency for ensure, label, assignment, claim, and relationship operations wherever the provider allows it. Do not silently deduplicate comments; if comment duplication is possible after an uncertain result, return an uncertain-outcome error so the agent can decide. - Delegate authentication, credential storage, and login flows to `gh`, `glab`, and `tea`. The package must not accept or persist provider tokens as part of this feature. - Provide repository-level configuration for external-request policy and any provider membership/ownership rules needed to safely classify incoming requests. Configuration must not override explicit provider selection. - Keep the existing provider-specific tracker guides as reference material while adding common-tool guidance and migration instructions. The tool is the execution seam; the guides remain the source for provider-specific capability and fallback semantics. ## Testing Decisions - Tests must assert externally visible behavior through the public operation boundary: normalized JSON, exit status, provider selection, retry behavior, and the sequence of provider CLI calls. Tests must not assert private class structure or internal helper names. - The primary seam is a fake subprocess runner or fake `gh`, `glab`, and `tea` executables. Each fake records arguments, returns controlled stdout/stderr, and can simulate transient and semantic failures. - Test provider detection independently through the public interface using CLI overrides, `TRACKER_PROVIDER`, canonical remotes, mirrored remotes, unsupported remotes, and ambiguous remotes. Assert the documented precedence. - Test issue and pull-request operations against provider fixtures for create, read, list, comment/note, label, assignment, close, and diff behavior. - Test label ensure behavior for existing labels, missing labels, metadata mismatches, repeated ensure calls, creation followed by assignment, and provider-specific label command failures. - Test common normalization across GitHub issues/PRs, GitLab issues/MRs, and Gitea issues/PRs, including shared versus separate number spaces and provider-specific comment terminology. - Test external-request filtering using GitHub author associations, GitLab/Gitea membership data, excluded maintainers, external contributors, missing metadata, and unsupported capability results. - Test wayfinding behavior for map creation, child linkage, native and fallback relationships, blocking dependencies, frontier filtering, deterministic ordering, claims, and resolution partial failure recovery. - Test retry policy with transient transport failures, rate limits, exhausted retry budgets, non-retryable semantic errors, and uncertain outcomes after a provider command may have completed. - Test JSON success and failure envelopes, stdout/stderr separation, stable error codes, retryability flags, and nonzero exit statuses. - Test idempotency by replaying ensure-label, assignment, claim, and relationship operations and asserting no duplicate side effects. - Include provider contract fixtures so each adapter must satisfy the same externally visible contract. Add optional live smoke tests behind an explicit credential/network gate. - This repository has no existing runtime modules, package manager, build system, or test suite; it is currently a Markdown skill repository. The new standalone package must establish its own test harness. There is no relevant prior test seam to reuse beyond the provider-specific behavioral documentation that serves as the contract source. ## Out of Scope - Automatically merging pull requests or merge requests. - Managing provider credentials, tokens, login sessions, or authentication setup. - Replacing `gh`, `glab`, or `tea` as general-purpose provider clients. - A direct HTTP API client or provider-specific web service. - Supporting providers other than GitHub, GitLab, and Gitea. - A web UI, hosted service, daemon, or background workflow scheduler. - Unbounded retries, speculative alternate commands, or autonomous recovery from ambiguous side effects. - Deduplicating arbitrary comments or editing user-authored issue content without an explicit operation. - General project-management features not described by the existing tracker guides. - Implementing the package inside the current Markdown-only repository as part of this specification; adoption guidance for the skills is in scope, but package delivery remains a separate implementation boundary. ## Further Notes - The canonical domain terms are GitHub, GitLab, Gitea, provider CLI, issue, pull request, merge request, label, note/comment, map, child ticket, blocker, dependency, frontier, claim, and resolution. - The existing tracker guides document provider-specific command shapes and wayfinding fallbacks. The implementation should treat their behavioral intent as the compatibility contract, not copy their raw commands into agent prompts. - The Gitea tracker is the issue tracker for this repository, and the published issue should carry the `ready-for-agent` triage label. Only that triage label should be active. - The implementation should be delivered with a migration note for agent skills so future triage actions call one high-level operation instead of issuing exploratory provider commands.
steve added the ready-for-agent label 2026-08-17 17:30:27 -04:00
steve added in-progress and removed ready-for-agent labels 2026-08-17 22:08:46 -04:00
Author
Owner

PR opened: #25

PR opened: http://gitea.sagacity.ca/steve/skills/pulls/25
steve added needs-review and removed in-progress labels 2026-08-17 22:37:05 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: steve/skills#16