|
| 1 | +# Contributing to IssueLens |
| 2 | + |
| 3 | +Thanks for helping improve IssueLens. Contributions to code, agent behavior, |
| 4 | +tests, documentation, and examples are welcome. |
| 5 | + |
| 6 | +## Before you start |
| 7 | + |
| 8 | +- Search existing issues and pull requests before starting work. For a larger |
| 9 | + change, open an issue to discuss the problem and proposed approach. |
| 10 | +- For bug reports, include reproduction steps, expected and actual behavior, |
| 11 | + and relevant versions. Remove credentials and private repository content |
| 12 | + from examples and logs. |
| 13 | +- Report security vulnerabilities through [SECURITY.md](SECURITY.md), not a |
| 14 | + public issue. |
| 15 | + |
| 16 | +## Development setup |
| 17 | + |
| 18 | +Fork and clone the repository, then create a branch for your change. Use |
| 19 | +**Python 3.13** to match the hosted runtime. The standalone MCP package also |
| 20 | +supports Python 3.12. |
| 21 | + |
| 22 | +Run commands from the repository root. In Bash: |
| 23 | + |
| 24 | +```bash |
| 25 | +python3.13 -m venv .venv |
| 26 | +source .venv/bin/activate |
| 27 | +python -m pip install -r requirements.txt -r requirements-ci.txt |
| 28 | +``` |
| 29 | + |
| 30 | +Or in PowerShell: |
| 31 | + |
| 32 | +```powershell |
| 33 | +py -3.13 -m venv .venv |
| 34 | +.\.venv\Scripts\Activate.ps1 |
| 35 | +python -m pip install -r requirements.txt -r requirements-ci.txt |
| 36 | +``` |
| 37 | + |
| 38 | +**You do not need a `.env` file, Azure credentials, a GitHub App, or a live model |
| 39 | +to run the tests.** Dependencies require network access to install; tests use |
| 40 | +local fixtures and mocked services. |
| 41 | + |
| 42 | +To run the agent itself, follow the separate [local setup guide](docs/guide.md#running-locally). |
| 43 | +Live requests may perform authorized writes, so use a test repository. Never |
| 44 | +commit tokens, private keys, `.env` files, or secret-bearing notification URLs. |
| 45 | +Editing or testing a change does not authorize deployment; deployment requires |
| 46 | +separate explicit approval. |
| 47 | + |
| 48 | +## Find your way around |
| 49 | + |
| 50 | +| Path | Purpose | |
| 51 | +| --- | --- | |
| 52 | +| `main.py` | Hosted server, protocol handling, and explicit agent/skill registration | |
| 53 | +| `agents/` | Runtime prompts for the orchestrator and four specialist agents | |
| 54 | +| `skills/` | Capability instructions for triage, planning, change analysis, and memory | |
| 55 | +| `github_app_mcp/` | GitHub App MCP server, packaging, and isolated tests | |
| 56 | +| `tests/` | Application, prompt-contract, workflow, and documentation tests | |
| 57 | +| `.github/actions/issuelens/` | Reusable GitHub Actions integration and request helpers | |
| 58 | +| `.github/workflows/` | CI, deployment, and operational workflows | |
| 59 | +| `examples/` and `schemas/` | Target-repository configuration examples and schema | |
| 60 | +| `docs/` and `observability/` | Setup, operations, and reporting resources | |
| 61 | + |
| 62 | +For protocol and operational details, see the [setup and usage guide](docs/guide.md). |
| 63 | +For tool contracts and standalone package development, see the |
| 64 | +[MCP reference](github_app_mcp/README.md). |
| 65 | + |
| 66 | +## Changing agents and skills |
| 67 | + |
| 68 | +The `issuelens` orchestrator routes work to `triage`, `find-criticals`, `plan`, |
| 69 | +and `team-memory`. Prompts live under `agents/` and are loaded explicitly in |
| 70 | +`main.py` for both protocols. Prefer changing the owning skill or agent prompt |
| 71 | +before adding host logic, and update the corresponding tests. |
| 72 | + |
| 73 | +Runtime prompts are application assets, not contributor instructions. Their |
| 74 | +restrictions on implementation, pull requests, and deployment describe the |
| 75 | +deployed product, not contributors maintaining it. Keep runtime prompts out of |
| 76 | +`AGENTS.md` (including lowercase `agents.md`); the orchestrator prompt stays in |
| 77 | +`agents/issuelens.md`. Repository maintenance guidance is in |
| 78 | +[`.github/copilot-instructions.md`](.github/copilot-instructions.md). |
| 79 | + |
| 80 | +To add a skill, create `skills/<name>/SKILL.md` with frontmatter and instructions: |
| 81 | + |
| 82 | +```markdown |
| 83 | +--- |
| 84 | +name: my-skill |
| 85 | +description: What this skill does. |
| 86 | +--- |
| 87 | + |
| 88 | +# My skill |
| 89 | + |
| 90 | +Instructions for the agent when this skill is active. |
| 91 | +``` |
| 92 | + |
| 93 | +Register new runtime components explicitly in `main.py` where needed. Preserve |
| 94 | +role ownership: triage owns issue follow-up, planning owns planning artifacts, |
| 95 | +and only the team-memory agent owns separately authorized wiki maintenance. |
| 96 | +All agents can retrieve memory through the shared read-only skill. |
| 97 | + |
| 98 | +Keep behavior consistent across chat and automation. Preserve scoped GitHub |
| 99 | +App access, explicit write authorization, validated repository policy, and |
| 100 | +wiki destination/base preconditions. Tools perform one logical operation; |
| 101 | +recovery belongs to the owning agent, and uncertain writes must not be reported |
| 102 | +as successful. The [MCP execution contract](github_app_mcp/README.md#execution-contract) |
| 103 | +documents these boundaries. |
| 104 | + |
| 105 | +## Run checks |
| 106 | + |
| 107 | +Start with the tests covering your change, then run the relevant suite before |
| 108 | +submitting. For example, run one application test module with: |
| 109 | + |
| 110 | +```bash |
| 111 | +python -m unittest discover -s tests -p 'test_issue_triage_workflow.py' -v |
| 112 | +``` |
| 113 | + |
| 114 | +The complete application checks are: |
| 115 | + |
| 116 | +```bash |
| 117 | +python -m compileall -q *.py .github/actions/issuelens github_app_mcp/src github_app_mcp/scripts tests github_app_mcp/tests |
| 118 | +python -m unittest discover -s tests -p 'test_*.py' -v |
| 119 | +``` |
| 120 | + |
| 121 | +The syntax command above uses Bash glob expansion. In PowerShell, pass root |
| 122 | +Python files explicitly: |
| 123 | + |
| 124 | +```powershell |
| 125 | +$rootModules = Get-ChildItem -File -Filter *.py | Select-Object -ExpandProperty Name |
| 126 | +python -m compileall -q $rootModules .github\actions\issuelens github_app_mcp\src github_app_mcp\scripts tests github_app_mcp\tests |
| 127 | +``` |
| 128 | + |
| 129 | +### Standalone MCP tests and package checks |
| 130 | + |
| 131 | +Use isolated environments so application dependencies do not mask package |
| 132 | +issues. Run these Bash commands with Python 3.12, then repeat with `python3.13` |
| 133 | +in place of `python3.12`: |
| 134 | + |
| 135 | +```bash |
| 136 | +MCP_CHECK_DIR="$(mktemp -d)" |
| 137 | +python3.12 -m venv "$MCP_CHECK_DIR/tests" |
| 138 | +( |
| 139 | + source "$MCP_CHECK_DIR/tests/bin/activate" |
| 140 | + python -m pip install ./github_app_mcp -r requirements-ci.txt |
| 141 | + python -m unittest discover -s github_app_mcp/tests -p 'test_*.py' -v |
| 142 | +) |
| 143 | +python3.12 -m venv "$MCP_CHECK_DIR/build" |
| 144 | +( |
| 145 | + source "$MCP_CHECK_DIR/build/bin/activate" |
| 146 | + python -m pip install -r requirements-ci.txt |
| 147 | + python -m build --outdir "$MCP_CHECK_DIR/dist" github_app_mcp |
| 148 | + python -m venv "$MCP_CHECK_DIR/wheel" |
| 149 | + "$MCP_CHECK_DIR/wheel/bin/python" -m pip install -c constraints-ci.txt "$MCP_CHECK_DIR"/dist/*.whl |
| 150 | + "$MCP_CHECK_DIR/wheel/bin/python" -m pip check |
| 151 | + "$MCP_CHECK_DIR/wheel/bin/python" -I - <<'PY' |
| 152 | +from importlib.metadata import distribution |
| 153 | +
|
| 154 | +dist = distribution("issuelens-github-mcp") |
| 155 | +entry, = (ep for ep in dist.entry_points if ep.group == "console_scripts" and ep.name == "issuelens-github-mcp") |
| 156 | +assert entry.value == "issuelens_github_mcp.server:main" |
| 157 | +assert callable(entry.load()) |
| 158 | +print(f"Installed {dist.metadata['Name']} {dist.version}; entry point imports successfully") |
| 159 | +PY |
| 160 | +) |
| 161 | +rm -rf "$MCP_CHECK_DIR" |
| 162 | +``` |
| 163 | + |
| 164 | +### Workflow validation |
| 165 | + |
| 166 | +[actionlint](https://github.com/rhysd/actionlint) v1.7.12 checks workflow syntax, |
| 167 | +expressions, job dependencies, and action inputs. With Go 1.25+ installed, run |
| 168 | +these Bash commands: |
| 169 | + |
| 170 | +```bash |
| 171 | +go install github.com/rhysd/actionlint/cmd/actionlint@914e7df21a07ef503a81201c76d2b11c789d3fca |
| 172 | +"$(go env GOPATH)/bin/actionlint" -shellcheck= -pyflakes= .github/workflows/*.yml |
| 173 | +``` |
| 174 | + |
| 175 | +Optional ShellCheck and Pyflakes integrations are disabled to keep local and CI |
| 176 | +scope the same. [`.github/actionlint.yaml`](.github/actionlint.yaml) suppresses |
| 177 | +only the unknown `copilot-requests` permission diagnostic in the manual billing |
| 178 | +probe; remove that exception when actionlint supports the scope. Deployment |
| 179 | +workflow regression tests also require Bash and jq, available on CI's Ubuntu |
| 180 | +runner; run those checks in a matching environment. |
| 181 | + |
| 182 | +## Continuous integration |
| 183 | + |
| 184 | +[`.github/workflows/ci.yml`](.github/workflows/ci.yml) runs on every pull request |
| 185 | +and push to `main`, separately from operational workflows. |
| 186 | + |
| 187 | +| Check | Scope | |
| 188 | +| --- | --- | |
| 189 | +| `Application tests (Python 3.13)` | Python syntax validation and all `tests/`; matches the hosted runtime. | |
| 190 | +| `MCP tests (Python 3.12)` | All `github_app_mcp/tests/` at the standalone package's minimum Python version. | |
| 191 | +| `MCP tests (Python 3.13)` | The same MCP suite on the hosted Python version. | |
| 192 | +| `MCP package build/install (Python 3.12)` | Build an sdist, build its wheel, install into a clean environment, check dependencies and import the console entry point. | |
| 193 | +| `MCP package build/install (Python 3.13)` | The same distributable validation on Python 3.13. | |
| 194 | +| `Workflow validation` | actionlint validation of all `.github/workflows/*.yml`. | |
| 195 | + |
| 196 | +CI uses ordinary `pull_request`, not `pull_request_target`, with only |
| 197 | +`contents: read`, no persisted checkout credentials, and no secrets or |
| 198 | +environment approvals. Fork PRs are supported, subject to GitHub's maintainer |
| 199 | +approval for first-time contributors. CI does not invoke IssueLens, deploy |
| 200 | +agents, publish packages, or write issues or wikis. The wheel smoke test imports |
| 201 | +but does not start the MCP server. |
| 202 | + |
| 203 | +Jobs have 10-15 minute timeouts; newer runs cancel superseded runs for the same |
| 204 | +PR/ref. Python jobs cache pip downloads by runtime and dependency manifests. |
| 205 | +Matrix failures remain failing checks without cancelling the other Python |
| 206 | +version. Maintainers can make the check names above required after observing |
| 207 | +successful Actions runs. Local checks do not establish live Actions execution, |
| 208 | +OIDC/RBAC access, hosted readiness, or wiki publication. |
| 209 | + |
| 210 | +### Dependency and tool versions |
| 211 | + |
| 212 | +[`requirements-ci.txt`](requirements-ci.txt) pins PyYAML, `packaging`, and PyPA |
| 213 | +`build`. [`constraints-ci.txt`](constraints-ci.txt), loaded by the CI |
| 214 | +requirements and clean wheel installation, fixes the tested MCP baseline at |
| 215 | +`mcp==2.0.1`, within both runtime manifests' supported range. This is not a full |
| 216 | +dependency lock or coverage of every newer MCP release. MCP 2.2.0 masks |
| 217 | +tool-error details asserted by existing wiki protocol tests; review the |
| 218 | +constraint when updating SDK support rather than weakening those assertions. |
| 219 | +`compileall` checks syntax, not formatting, types, or style. |
| 220 | + |
| 221 | +Actions and actionlint source are pinned to immutable commits. Dependabot |
| 222 | +proposes action updates; review upgrades, update version comments, pins, tests, |
| 223 | +and documentation together, then rerun validation. Go is used only to install |
| 224 | +actionlint; Go caching is disabled because this repository has no Go module. |
| 225 | + |
| 226 | +## Submit a pull request |
| 227 | + |
| 228 | +Keep changes focused and include a clear explanation of the problem, approach, |
| 229 | +and any behavior changes. Link the relevant issue, add or update tests, and |
| 230 | +describe the checks you ran and any limitations. Update documentation and |
| 231 | +examples when configuration, commands, tool contracts, or behavior change. |
| 232 | + |
| 233 | +Review your diff for secrets, unrelated edits, and generated files before |
| 234 | +opening the pull request. Keep the [README](README.md) a short project overview; |
| 235 | +put contributor instructions here and setup or operational details in the |
| 236 | +[guide](docs/guide.md). |
0 commit comments