Skip to content

Support GitHub-based community lint rule discovery and lifecycle management #616

Closed
4 of 4 issues completed

Description

@Teakowa

Goal

Let Wright users discover, install, update, and version community lint rule packages hosted in GitHub repositories. Reuse Magpie's GitHub discovery and Skill Library lifecycle-management approach, but apply it only to Wright lint rules.

Context

#309 / WRI-480 defines the declarative lint rule and project policy boundaries while explicitly deferring remote distribution. Community rule authors should be able to publish and maintain compatible rules independently of Wright releases.

Magpie provides working reference mechanisms:

Magpie's Skill and agent functionality is not a Wright product requirement.

Scope

  • Discover public lint-rule repositories by a Wright-specific GitHub Topic; also support installation by explicit repository URL without requiring the Topic.
  • Identify and validate installable rules against Wright's approved declarative lint-rule contract; support multiple rules in one repository without inventing a second rule format.
  • Manage installed packages in a Wright-owned local location. Retain source repository, package/path identity, and immutable installed Git revision.
  • Expose user-facing install, list, check-updates, update (one/all), and remove operations. Update checks must report changes without applying them.
  • Keep managed files separate from user-authored rules. Never silently overwrite locally changed files or unrelated content.
  • Allow projects and CI to select reproducible rule-package revisions, so unrelated global updates cannot silently change effective lint behavior.
  • Surface missing sources, incompatible rule schemas, namespace collisions, and remote check failures explicitly. Reuse existing rule IDs, policy levels, and structured findings.
  • Use existing Wright update/configuration mechanisms where suitable; add only the minimum GitHub querying/caching necessary for practical use.

Proposed community repository format

Treat one GitHub repository as one lint package. A public community package uses the GitHub Topic wrightkit-lint (proposed naming); direct repository URLs work without the Topic.

example-lint-repo/
├── README.md         # community description and instructions
├── LICENSE           # terms for redistribution
├── rules/            # only required machine-readable entry point
│   ├── short-wait.yaml
│   └── repeated-effect.yml
└── tests/            # optional, conventional runnable tests
  • rules/ contains one declarative rule per .yaml or .yml file, with files directly inside the directory. Follow Wright's existing lexically ordered, non-recursive --rule rules/ loader.
  • Each file uses the existing SPEC-309 rule schema: id, optional document-level locale (default en-US), metadata, and matcher. Required metadata currently includes summary, rationale, documentation, known-limits, and tags.
  • IDs retain the existing <namespace>/<rule-id> contract, with wright reserved. Recommend one consistent namespace per repository, without adding a new package-to-namespace mapping protocol; reject duplicate effective rule IDs.
  • Rule files never specify project severity or enabled; those belong to the consuming project's existing lint policy. Installing a package must not automatically activate it in unrelated projects.
  • Use the GitHub owner/repo as package identity and a resolved commit SHA as the installed version. Git tags may be user-facing selectors but must resolve to immutable commits. Do not require package.json, a new lint-package.yaml, dependency graph, or rule-level version fields.
  • README.md and LICENSE are publication requirements for community discovery. Rule validation itself only needs rules/ and compatible YAML files. tests/ is optional and may use ordinary Wright CLI integration tests; do not invent another test description format.
  • Repository content is data, not executable code. Ignore other repository files during rule loading. Refuse empty, malformed, incompatible, or conflicting packages with explicit diagnostics.
  • The project pin/selection mechanism is part of this issue's distribution design; it may extend existing project lint configuration as needed, but must not silently redefine the already accepted YAML rule syntax. Avoid a second lock/manifest unless a concrete reproducibility requirement needs it.

Example rule

id: workshop-performance/short-wait
locale: en-US
metadata:
  summary: A while loop contains a 0.1-second Wait
  rationale: Short waits in loops can warrant inspection.
  documentation: Reports a static match; it does not measure runtime cost.
  known-limits: A matching wait is not necessarily a performance defect.
  tags: [performance]
matcher:
  scope: while
  actions:
    - kind: call
      name: Wait
      args:
        - number: 0.1
      count: { min: 1 }

This is a proposed distribution convention, not a claim that remote packages or project pinning already work. Validate it against the current rule loader and at least one realistic community repository before freezing the public package contract.

Non-goals

  • Installing/managing community Agent Skills or syncing any content to coding agents.
  • A general plugin host, JS/WASM/native rule execution, or arbitrary repository code execution.
  • A new lint matcher DSL, independent semantic model, or changes to Workshop/OPY/DEL ownership.
  • A hosted marketplace, new central registry, or automatic background upgrades.
  • Copying Magpie's complete library data model, backup system, or multi-agent synchronization.

Acceptance criteria

  • A compatible rule package is discoverable by Topic or installable via repository URL, with its source and installed revision inspectable.
  • Wright can load installed declarative rules through the approved lint execution path, without bypassing its semantic ownership or policy contract.
  • Users can check for and explicitly apply individual or bulk updates; unchanged, updated, and unavailable/error states are distinguished.
  • Updates/removal preserve user-owned files, and locally edited managed content is not silently replaced.
  • Project rule selection is reproducible in CI after other local/global packages change.
  • Invalid/incompatible rules, duplicate identities, and network failures produce actionable results without unverified lint findings.
  • Focused tests cover discovery, install/update/remove, revision pinning, collision/failure behavior, and project reproducibility.
  • An independent design ablation verifies that additional manifests, global state, copy layers, or backup machinery are strictly necessary before retaining them.

Ownership / dependencies

  • wright: community discovery, installation/update lifecycle, version resolution, rule selection, lint integration, and user-facing commands.
  • workshop-rs / source-language owners: canonical/source semantics; community rules may consume only supported Wright-exposed semantic/query contracts.
  • Dependency: Define an extensible analysis and lint rule contract #309's accepted rule format and execution contract. Do not assume historical Issue closure proves that the current loader/runtime is implemented. Inspect current code before implementation.

Activity

  1. e54-bot commented on Oct 20, 2026

    @e54-bot
    Collaborator

    Owner decisions (2026-10-20). The scope stays as written in this issue (discovery, install, list, outdated, update, remove, project pinning); these fix the open design points:

    • Commands. wright lint package <search|install|list|outdated|update|remove>. outdated is the update check: it reports changes and applies nothing. update applies one package or all.
    • Storage and activation. Installed packages live in a Wright-owned cache directory, immutable per <owner>/<repo>/<full-sha>/. Installing never activates a package. A project activates one by listing repo and full commit SHA under a packages entry of its existing lint configuration; that configuration is the lock, so there is no second lock file. A tag or branch is resolved to a SHA when it is installed and only the SHA is stored. CI fetches a missing SHA on demand. Locally edited managed files are never overwritten, and user-authored rules stay outside the managed directory.
    • Fetching, with no dependency on git. Install downloads the tarball for the full SHA from codeload.github.com (it does not count against the anonymous API limit), reusing the workspace's reqwest. Resolving a tag or branch and checking for updates use the commits API with ETag conditional requests. search uses the repository Search API (topic:wrightkit-lint archived:false fork:false). GITHUB_TOKEN is optional: it raises limits and reads private repositories, and is sent to the API host only. Only rules/*.yaml|yml is read; repository code is never executed.
    • Topic. wrightkit-lint. Installing by explicit repository URL does not need it.
    • Unchanged from this issue. One repository is one package; rules follow SPEC-309 with no new format; a rule file never sets severity or enabled; empty, malformed, incompatible, or colliding packages and network failures produce explicit diagnostics and no unverified findings.

    Before the public package contract is frozen, it is validated against the current loader and one realistic community repository, as the body requires. Next step: split this issue into executable sub-issues (package store and fetch, project config pinning, commands) under this parent. ready-for-implementation added.

  2. added
    enhancementNew feature or request
    ready-for-implementationContract settled; an Engineer can implement without inventing a decision
    on Oct 20, 2026
  3. e54-bot commented on Oct 20, 2026

    @e54-bot
    Collaborator

    Owner addendum (2026-10-20): Wright's own lint rules move onto the same package mechanism, so official rules can change without a Wright release.

    • What moves. Only built-in rules that the current declarative vocabulary (SPEC-309) can express. The first step is an inventory of the built-in rules (registry.rs) that classifies each as expressible or native-only, recorded in the PR. Rules that need a native analysis (for example expression equality or cost) stay in the binary. The vocabulary is not widened for this; widening needs its own decision backed by real rules.
    • Where. A separate first-party package repository in the community package format, so the official package dogfoods that format. Wright records a full commit SHA for it in its own repository and embeds that revision at build time, so a fresh install works offline. A user can install a newer official revision with wright lint package without upgrading Wright.
    • IDs and override. The official package keeps the existing bare rule IDs, so no user configuration changes; it is the only package allowed bare IDs, and every other package must use namespace/rule-id with wright reserved. A project that lists the official repository with a SHA under packages replaces the embedded default instead of colliding with it. Collisions between any other packages remain errors.
    • Support classification. The official package may declare evidence class and default severity in its rule metadata. Community packages still cannot (ADR-0015). The embedded revision is trusted because it is pinned by Wright.
    • Docs. ADR-0015 and SPEC-309 are amended in the same change (bare IDs for the official package, official-only evidence declaration, replace-on-override).

    Sequencing: the package store, fetch, and project pinning land first; the official package and the move follow on top, so the working lint path is never broken. Updated sub-issue split: (1) package store and fetch; (2) project config pinning and override semantics; (3) wright lint package commands; (4) built-in rule inventory and the first-party package with build-time embedding.

  4. e54-bot commented on Oct 20, 2026

    @e54-bot
    Collaborator

    Closing. The store and fetch (#857), project pinning (#858) and wright lint package commands (#861) have merged, each with tests. The validation against a realistic community repository could not be done: no community package repository exists yet (the only repository with the wrightkit-lint topic is the empty first-party wrightkit/wright-lint-rules). #845 closed as not planned because no built-in rule is expressible in the current declarative vocabulary. Open a new issue when the first real community package needs a contract change.

  5. removed
    ready-for-implementationContract settled; an Engineer can implement without inventing a decision
    on Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions