lgtmaybe 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lgtmaybe-0.0.1/.claude/settings.local.json +26 -0
- lgtmaybe-0.0.1/.env.development +0 -0
- lgtmaybe-0.0.1/.env.development.local +0 -0
- lgtmaybe-0.0.1/.env.local +0 -0
- lgtmaybe-0.0.1/.env.production +0 -0
- lgtmaybe-0.0.1/.env.production.local +0 -0
- lgtmaybe-0.0.1/.env.test +0 -0
- lgtmaybe-0.0.1/.env.test.local +0 -0
- lgtmaybe-0.0.1/.github/workflows/ci.yml +33 -0
- lgtmaybe-0.0.1/.gitignore +218 -0
- lgtmaybe-0.0.1/.gitmodules +0 -0
- lgtmaybe-0.0.1/.npmrc +0 -0
- lgtmaybe-0.0.1/.yarnrc +0 -0
- lgtmaybe-0.0.1/.yarnrc.yml +0 -0
- lgtmaybe-0.0.1/CLAUDE.md +100 -0
- lgtmaybe-0.0.1/Dockerfile +13 -0
- lgtmaybe-0.0.1/LICENSE +21 -0
- lgtmaybe-0.0.1/PKG-INFO +33 -0
- lgtmaybe-0.0.1/README.md +21 -0
- lgtmaybe-0.0.1/bunfig.toml +0 -0
- lgtmaybe-0.0.1/manual-steps.md +53 -0
- lgtmaybe-0.0.1/package-lock.json +0 -0
- lgtmaybe-0.0.1/package.json +0 -0
- lgtmaybe-0.0.1/pnpm-lock.yaml +0 -0
- lgtmaybe-0.0.1/pyproject.toml +46 -0
- lgtmaybe-0.0.1/src/lgtmaybe/__init__.py +3 -0
- lgtmaybe-0.0.1/src/lgtmaybe/__main__.py +20 -0
- lgtmaybe-0.0.1/src/lgtmaybe/cli/__init__.py +1 -0
- lgtmaybe-0.0.1/src/lgtmaybe/config/__init__.py +1 -0
- lgtmaybe-0.0.1/src/lgtmaybe/core/__init__.py +1 -0
- lgtmaybe-0.0.1/src/lgtmaybe/core/logging.py +88 -0
- lgtmaybe-0.0.1/src/lgtmaybe/core/models.py +104 -0
- lgtmaybe-0.0.1/src/lgtmaybe/core/ports.py +49 -0
- lgtmaybe-0.0.1/src/lgtmaybe/engine/__init__.py +1 -0
- lgtmaybe-0.0.1/src/lgtmaybe/github/__init__.py +1 -0
- lgtmaybe-0.0.1/src/lgtmaybe/providers/__init__.py +1 -0
- lgtmaybe-0.0.1/src/lgtmaybe/py.typed +0 -0
- lgtmaybe-0.0.1/tests/__init__.py +0 -0
- lgtmaybe-0.0.1/tests/fakes/__init__.py +7 -0
- lgtmaybe-0.0.1/tests/fakes/engine.py +28 -0
- lgtmaybe-0.0.1/tests/fakes/github.py +29 -0
- lgtmaybe-0.0.1/tests/fakes/provider.py +39 -0
- lgtmaybe-0.0.1/tests/snapshots/PRContext.json +43 -0
- lgtmaybe-0.0.1/tests/snapshots/ProviderResult.json +30 -0
- lgtmaybe-0.0.1/tests/snapshots/ReviewConfig.json +79 -0
- lgtmaybe-0.0.1/tests/snapshots/ReviewFinding.json +69 -0
- lgtmaybe-0.0.1/tests/test_fakes_wiring.py +29 -0
- lgtmaybe-0.0.1/tests/test_logging.py +53 -0
- lgtmaybe-0.0.1/tests/test_models.py +80 -0
- lgtmaybe-0.0.1/tests/test_ports.py +18 -0
- lgtmaybe-0.0.1/uv.lock +400 -0
- lgtmaybe-0.0.1/yarn.lock +0 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(uv --version)",
|
|
5
|
+
"Bash(uv sync *)",
|
|
6
|
+
"Bash(uv run *)",
|
|
7
|
+
"Bash(git check-ignore *)",
|
|
8
|
+
"Bash(gh auth *)",
|
|
9
|
+
"Bash(git ls-remote *)",
|
|
10
|
+
"Bash(gh repo *)",
|
|
11
|
+
"Bash(git ls-tree *)",
|
|
12
|
+
"Bash(git checkout *)",
|
|
13
|
+
"Bash(git add *)",
|
|
14
|
+
"Bash(git commit *)",
|
|
15
|
+
"Bash(git push *)",
|
|
16
|
+
"Bash(gh pr create --base main --head foundation --title 'foundation: freeze contracts, fakes, structured logging, CI' --body ' *)",
|
|
17
|
+
"Bash(gh pr *)",
|
|
18
|
+
"Bash(echo \"--- exit: $? ---\")",
|
|
19
|
+
"Bash(git pull *)",
|
|
20
|
+
"Bash(env)",
|
|
21
|
+
"Bash(curl -s -o /dev/null -w \"%{http_code}\" https://pypi.org/pypi/lgtmaybe/json)",
|
|
22
|
+
"Bash(uv build *)",
|
|
23
|
+
"Bash(uvx twine *)"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
lgtmaybe-0.0.1/.env.test
ADDED
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
check:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
|
|
14
|
+
- name: Install uv
|
|
15
|
+
uses: astral-sh/setup-uv@v5
|
|
16
|
+
with:
|
|
17
|
+
python-version: "3.12"
|
|
18
|
+
enable-cache: true
|
|
19
|
+
|
|
20
|
+
- name: Sync (with dev deps)
|
|
21
|
+
run: uv sync --dev
|
|
22
|
+
|
|
23
|
+
- name: Lint
|
|
24
|
+
run: uv run ruff check .
|
|
25
|
+
|
|
26
|
+
- name: Format check
|
|
27
|
+
run: uv run ruff format --check .
|
|
28
|
+
|
|
29
|
+
- name: Types
|
|
30
|
+
run: uv run mypy
|
|
31
|
+
|
|
32
|
+
- name: Tests
|
|
33
|
+
run: uv run pytest -q
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py.cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
# Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
# uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
# poetry.lock
|
|
109
|
+
# poetry.toml
|
|
110
|
+
|
|
111
|
+
# pdm
|
|
112
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
113
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
114
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
115
|
+
# pdm.lock
|
|
116
|
+
# pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# pixi
|
|
121
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
122
|
+
# pixi.lock
|
|
123
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
124
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
125
|
+
.pixi
|
|
126
|
+
|
|
127
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
128
|
+
__pypackages__/
|
|
129
|
+
|
|
130
|
+
# Celery stuff
|
|
131
|
+
celerybeat-schedule
|
|
132
|
+
celerybeat.pid
|
|
133
|
+
|
|
134
|
+
# Redis
|
|
135
|
+
*.rdb
|
|
136
|
+
*.aof
|
|
137
|
+
*.pid
|
|
138
|
+
|
|
139
|
+
# RabbitMQ
|
|
140
|
+
mnesia/
|
|
141
|
+
rabbitmq/
|
|
142
|
+
rabbitmq-data/
|
|
143
|
+
|
|
144
|
+
# ActiveMQ
|
|
145
|
+
activemq-data/
|
|
146
|
+
|
|
147
|
+
# SageMath parsed files
|
|
148
|
+
*.sage.py
|
|
149
|
+
|
|
150
|
+
# Environments
|
|
151
|
+
.env
|
|
152
|
+
.envrc
|
|
153
|
+
.venv
|
|
154
|
+
env/
|
|
155
|
+
venv/
|
|
156
|
+
ENV/
|
|
157
|
+
env.bak/
|
|
158
|
+
venv.bak/
|
|
159
|
+
|
|
160
|
+
# Spyder project settings
|
|
161
|
+
.spyderproject
|
|
162
|
+
.spyproject
|
|
163
|
+
|
|
164
|
+
# Rope project settings
|
|
165
|
+
.ropeproject
|
|
166
|
+
|
|
167
|
+
# mkdocs documentation
|
|
168
|
+
/site
|
|
169
|
+
|
|
170
|
+
# mypy
|
|
171
|
+
.mypy_cache/
|
|
172
|
+
.dmypy.json
|
|
173
|
+
dmypy.json
|
|
174
|
+
|
|
175
|
+
# Pyre type checker
|
|
176
|
+
.pyre/
|
|
177
|
+
|
|
178
|
+
# pytype static type analyzer
|
|
179
|
+
.pytype/
|
|
180
|
+
|
|
181
|
+
# Cython debug symbols
|
|
182
|
+
cython_debug/
|
|
183
|
+
|
|
184
|
+
# PyCharm
|
|
185
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
186
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
187
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
188
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
189
|
+
# .idea/
|
|
190
|
+
|
|
191
|
+
# Abstra
|
|
192
|
+
# Abstra is an AI-powered process automation framework.
|
|
193
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
194
|
+
# Learn more at https://abstra.io/docs
|
|
195
|
+
.abstra/
|
|
196
|
+
|
|
197
|
+
# Visual Studio Code
|
|
198
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
199
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
200
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
201
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
202
|
+
# .vscode/
|
|
203
|
+
# Temporary file for partial code execution
|
|
204
|
+
tempCodeRunnerFile.py
|
|
205
|
+
|
|
206
|
+
# Ruff stuff:
|
|
207
|
+
.ruff_cache/
|
|
208
|
+
|
|
209
|
+
# PyPI configuration file
|
|
210
|
+
.pypirc
|
|
211
|
+
|
|
212
|
+
# Marimo
|
|
213
|
+
marimo/_static/
|
|
214
|
+
marimo/_lsp/
|
|
215
|
+
__marimo__/
|
|
216
|
+
|
|
217
|
+
# Streamlit
|
|
218
|
+
.streamlit/secrets.toml
|
|
File without changes
|
lgtmaybe-0.0.1/.npmrc
ADDED
|
File without changes
|
lgtmaybe-0.0.1/.yarnrc
ADDED
|
File without changes
|
|
File without changes
|
lgtmaybe-0.0.1/CLAUDE.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
Guidance for agents working in **lgtmaybe** — a provider-agnostic PR reviewer.
|
|
4
|
+
Read this before writing code. It encodes decisions that are **made, not options**.
|
|
5
|
+
|
|
6
|
+
## What this is
|
|
7
|
+
|
|
8
|
+
A PR reviewer that posts inline review comments + a summary. The user picks the
|
|
9
|
+
LLM backend with a `--provider` flag, drops a key into GitHub secrets (or wires
|
|
10
|
+
OIDC/WIF for cloud providers), and gets a review. One core, two distribution
|
|
11
|
+
variants:
|
|
12
|
+
|
|
13
|
+
- **PyPI CLI** — `pip install lgtmaybe`
|
|
14
|
+
- **GitHub Action** — Docker container action pulling a GHCR image
|
|
15
|
+
|
|
16
|
+
**The wedge:** first-class **Bedrock + Vertex with keyless OIDC/WIF**. Five
|
|
17
|
+
providers, one flag, no keys in secrets for cloud. We do not try to out-feature
|
|
18
|
+
pr-agent; we win on auth + simplicity. Reuse its proven mechanics, don't clone
|
|
19
|
+
its surface.
|
|
20
|
+
|
|
21
|
+
## Non-negotiables
|
|
22
|
+
|
|
23
|
+
- **TDD, always: red → green → refactor.** Write the acceptance test from a
|
|
24
|
+
task's stated in/out *first*, watch it fail, write the minimum code to pass,
|
|
25
|
+
then refactor. CI rejects a PR whose diff adds code without a test.
|
|
26
|
+
- **Structured output only.** The model returns JSON (`severity`, `file`,
|
|
27
|
+
`line`, `body`, `suggestion`). Never parse prose.
|
|
28
|
+
- **Fork safety.** Trigger on `pull_request_target` so the review has secrets,
|
|
29
|
+
but **never check out or execute PR code** — fetch the diff via API only.
|
|
30
|
+
Treat all diff content as untrusted input.
|
|
31
|
+
- **No static cloud keys.** Bedrock uses ambient AWS creds; Vertex uses ambient
|
|
32
|
+
GCP creds. Never accept or require a service-account JSON or static AWS key.
|
|
33
|
+
|
|
34
|
+
## Key decisions (do not relitigate)
|
|
35
|
+
|
|
36
|
+
- **Language:** Python.
|
|
37
|
+
- **Provider spine:** [litellm] — normalises openai, openrouter, anthropic,
|
|
38
|
+
bedrock, vertex, ollama to one `completion()` call. A thin wrapper on top adds
|
|
39
|
+
retries / fallback / cost.
|
|
40
|
+
- **License:** MIT (already in `LICENSE`).
|
|
41
|
+
- **Posting:** REST review API — batched inline comments + one summary.
|
|
42
|
+
Idempotent updates via a hidden marker comment.
|
|
43
|
+
|
|
44
|
+
### Auth model — resolved by provider (chain of responsibility)
|
|
45
|
+
|
|
46
|
+
| Provider | Auth |
|
|
47
|
+
|------------------------|------------------------------------------------------------------|
|
|
48
|
+
| openai / openrouter / anthropic | API key from `secrets.*` / env / `--api-key` |
|
|
49
|
+
| bedrock | ambient AWS creds (GitHub OIDC role, or local `~/.aws`); IAM `bedrock:InvokeModel*` only |
|
|
50
|
+
| vertex | ambient GCP creds (WIF, or local ADC) |
|
|
51
|
+
| ollama | none — just an `api_base` (localhost, host.docker.internal, tailscale host); fully local, zero cost |
|
|
52
|
+
|
|
53
|
+
Resolver order: chosen provider → try ambient cloud creds if that's its native
|
|
54
|
+
mode → else API key → ollama needs neither → else **fail with a clear "how to
|
|
55
|
+
auth this provider" message**.
|
|
56
|
+
|
|
57
|
+
## Architecture — ports & adapters (hexagonal)
|
|
58
|
+
|
|
59
|
+
This is what lets tracks build in parallel against frozen contracts.
|
|
60
|
+
|
|
61
|
+
- `core/ports.py` — the ports (interfaces). **Frozen in the foundation step.**
|
|
62
|
+
- litellm / github classes — the adapters.
|
|
63
|
+
- **Engine is a pipeline:** `fetch → compress → prompt → parse → post`, as
|
|
64
|
+
composable stages.
|
|
65
|
+
- **Provider choice:** strategy + factory. The `--provider` flag selects a
|
|
66
|
+
strategy; a small factory builds the `ProviderClient` (litellm keeps it tiny).
|
|
67
|
+
- **Credential resolution:** chain of responsibility (see auth table).
|
|
68
|
+
- **Dependency injection:** inject ports into the engine — this is what makes
|
|
69
|
+
fakes + dry-run drop in.
|
|
70
|
+
|
|
71
|
+
**Deliberately skipped** (don't add without a written reason): repository
|
|
72
|
+
pattern, event bus, plugin framework.
|
|
73
|
+
|
|
74
|
+
## Parallel build structure
|
|
75
|
+
|
|
76
|
+
1. **Foundation (sequential, first):** freeze the contracts in `core/ports.py`,
|
|
77
|
+
plus structured logging for CI debugging. Everything downstream codes against
|
|
78
|
+
these frozen ports.
|
|
79
|
+
2. **Parallel tracks**, each against frozen contracts:
|
|
80
|
+
- **Track A** — provider/litellm wrapper: retries, fallback, **cost reporting**.
|
|
81
|
+
- **Track B** — github adapter + diff handling; **skip generated/binary files**
|
|
82
|
+
(lockfiles, minified, vendored).
|
|
83
|
+
- **Track C** — hardening: **prompt-injection defense** (PR text trying to
|
|
84
|
+
steer the reviewer), **secret redaction in diffs before they leave for the
|
|
85
|
+
LLM**, fork-PR exposure (already handled by `pull_request_target` + no checkout).
|
|
86
|
+
- **CLI track** — PyPI packaging, `--dry-run` for local dev.
|
|
87
|
+
3. **Integration (sequential, last):** wire stages; surface errors (**a failed
|
|
88
|
+
review posts a comment, never fails silently**); fold cost into the summary.
|
|
89
|
+
|
|
90
|
+
Every task carries its inputs/outputs and an acceptance test so an agent can
|
|
91
|
+
self-verify without asking. The acceptance test *is* the red step — start there.
|
|
92
|
+
|
|
93
|
+
## Conventions
|
|
94
|
+
|
|
95
|
+
- **Docs:** `manual-steps.md` holds the human-only setup (cloud roles,
|
|
96
|
+
registries, marketplace).
|
|
97
|
+
- Treat diff content as untrusted everywhere it flows.
|
|
98
|
+
- Errors surface to the user; never swallow them.
|
|
99
|
+
|
|
100
|
+
[litellm]: https://github.com/BerriAI/litellm
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Container action image (published to GHCR). The CLI track wires the real
|
|
2
|
+
# entrypoint; this builds the skeleton into a runnable image today.
|
|
3
|
+
FROM python:3.12-slim
|
|
4
|
+
|
|
5
|
+
COPY --from=ghcr.io/astral-sh/uv:0.10.6 /uv /uvx /bin/
|
|
6
|
+
|
|
7
|
+
WORKDIR /app
|
|
8
|
+
COPY pyproject.toml README.md ./
|
|
9
|
+
COPY src ./src
|
|
10
|
+
|
|
11
|
+
RUN uv sync --no-dev
|
|
12
|
+
|
|
13
|
+
ENTRYPOINT ["uv", "run", "python", "-m", "lgtmaybe"]
|
lgtmaybe-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Matt Coles
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
lgtmaybe-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lgtmaybe
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Provider-agnostic PR reviewer — five providers, one flag, no keys in secrets for cloud.
|
|
5
|
+
Project-URL: Homepage, https://github.com/lgtmaybe/lgtmaybe
|
|
6
|
+
Author: Matt Coles
|
|
7
|
+
License: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Python: >=3.12
|
|
10
|
+
Requires-Dist: pydantic>=2.7
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# lgtmaybe
|
|
14
|
+
|
|
15
|
+
Provider-agnostic PR reviewer. Five providers, one flag, no keys in secrets for
|
|
16
|
+
cloud. Posts inline review comments + a summary.
|
|
17
|
+
|
|
18
|
+
> Status: under construction. See `CLAUDE.md` for the build plan and
|
|
19
|
+
> `manual-steps.md` for the human-only setup.
|
|
20
|
+
|
|
21
|
+
## Providers
|
|
22
|
+
|
|
23
|
+
`openai` · `openrouter` · `anthropic` · `bedrock` (keyless OIDC) ·
|
|
24
|
+
`vertex` (keyless WIF) · `ollama` (local, zero cost)
|
|
25
|
+
|
|
26
|
+
## Distribution
|
|
27
|
+
|
|
28
|
+
- **CLI** — `pip install lgtmaybe`
|
|
29
|
+
- **GitHub Action** — Docker container action from GHCR
|
|
30
|
+
|
|
31
|
+
## License
|
|
32
|
+
|
|
33
|
+
MIT — see `LICENSE`.
|
lgtmaybe-0.0.1/README.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# lgtmaybe
|
|
2
|
+
|
|
3
|
+
Provider-agnostic PR reviewer. Five providers, one flag, no keys in secrets for
|
|
4
|
+
cloud. Posts inline review comments + a summary.
|
|
5
|
+
|
|
6
|
+
> Status: under construction. See `CLAUDE.md` for the build plan and
|
|
7
|
+
> `manual-steps.md` for the human-only setup.
|
|
8
|
+
|
|
9
|
+
## Providers
|
|
10
|
+
|
|
11
|
+
`openai` · `openrouter` · `anthropic` · `bedrock` (keyless OIDC) ·
|
|
12
|
+
`vertex` (keyless WIF) · `ollama` (local, zero cost)
|
|
13
|
+
|
|
14
|
+
## Distribution
|
|
15
|
+
|
|
16
|
+
- **CLI** — `pip install lgtmaybe`
|
|
17
|
+
- **GitHub Action** — Docker container action from GHCR
|
|
18
|
+
|
|
19
|
+
## License
|
|
20
|
+
|
|
21
|
+
MIT — see `LICENSE`.
|
|
File without changes
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# lgtmaybe — manual steps
|
|
2
|
+
|
|
3
|
+
things an agent cant do for you. work top to bottom; each block says *when* in the build it's needed.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## A. before any code (day one)
|
|
8
|
+
- [ ] create github org/repo `lgtmaybe` (confirm `lgtm-ai` isnt yours — it's a different project).
|
|
9
|
+
- [ ] `pip install build twine` and push a `0.0.1` placeholder to pypi to hold the name. real release comes later.
|
|
10
|
+
- [ ] enable branch protection on `main`: require CI green, require a PR.
|
|
11
|
+
|
|
12
|
+
## B. provider credentials (needed to run a real review)
|
|
13
|
+
pick whichever providers you'll actually demo. you do **not** need all five.
|
|
14
|
+
|
|
15
|
+
### key-based (openai / openrouter / anthropic)
|
|
16
|
+
- [ ] generate an api key in that provider's console.
|
|
17
|
+
- [ ] add it as a github **repo secret** (e.g. `OPENAI_KEY`, `ANTHROPIC_KEY`, `OPENROUTER_KEY`).
|
|
18
|
+
|
|
19
|
+
### bedrock (keyless, via OIDC) — the wedge, worth doing
|
|
20
|
+
- [ ] in AWS, create an IAM **OIDC identity provider** for `token.actions.githubusercontent.com`.
|
|
21
|
+
- [ ] create an IAM **role** with a trust policy scoped to your repo (`repo:<org>/lgtmaybe:*`).
|
|
22
|
+
- [ ] attach a least-privilege policy: `bedrock:InvokeModel` + `bedrock:InvokeModelWithResponseStream` on the specific model ARNs only.
|
|
23
|
+
- [ ] note the **role ARN** — it becomes the `aws_role_arn` action input. no static key is ever stored.
|
|
24
|
+
- [ ] confirm the models you want are enabled in the target region (model access request in the Bedrock console).
|
|
25
|
+
|
|
26
|
+
### vertex (keyless, via workload identity federation)
|
|
27
|
+
- [ ] create a GCP **workload identity pool** + a github provider in it.
|
|
28
|
+
- [ ] create a service account with `roles/aiplatform.user` (or narrower).
|
|
29
|
+
- [ ] grant the github principal permission to impersonate that SA, scoped to your repo.
|
|
30
|
+
- [ ] note the **WIF provider resource name** — it becomes `gcp_wif_provider`.
|
|
31
|
+
|
|
32
|
+
## C. repo permissions for the action
|
|
33
|
+
- [ ] the workflow needs `permissions: id-token: write` (for OIDC) and `pull-requests: write` (to post comments).
|
|
34
|
+
- [ ] decide the trigger: `pull_request_target` (so secrets are available) — and confirm the action never checks out PR code, only reads the diff.
|
|
35
|
+
|
|
36
|
+
## D. publishing (step 4 of the plan)
|
|
37
|
+
|
|
38
|
+
### pypi CLI via trusted publishing (no token in secrets)
|
|
39
|
+
- [ ] on pypi, add a **trusted publisher** for the repo + the release workflow name + environment.
|
|
40
|
+
- [ ] no `PYPI_TOKEN` secret needed — the release workflow authenticates via OIDC.
|
|
41
|
+
|
|
42
|
+
### GHCR image
|
|
43
|
+
- [ ] confirm `packages: write` permission in the release workflow; GHCR uses the built-in `GITHUB_TOKEN`, nothing manual beyond that.
|
|
44
|
+
|
|
45
|
+
### marketplace listing
|
|
46
|
+
- [ ] add an `action.yml` with `name`, `description`, `branding` (icon + colour).
|
|
47
|
+
- [ ] tag a release (`v1.0.0`) and a floating `v1`.
|
|
48
|
+
- [ ] from the release page, tick **"Publish this Action to the GitHub Marketplace"**, accept terms, pick categories (`code-review`, `continuous-integration`).
|
|
49
|
+
|
|
50
|
+
## E. before you announce / blog it
|
|
51
|
+
- [ ] run lgtmaybe on its own repo (dogfood) so the README screenshot is real.
|
|
52
|
+
- [ ] write the data/privacy statement: which provider sees the diff, and that cloud variants send no static keys.
|
|
53
|
+
- [ ] sanity-check the least-privilege IAM/WIF scopes one more time before the repo goes public.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "lgtmaybe"
|
|
3
|
+
version = "0.0.1"
|
|
4
|
+
description = "Provider-agnostic PR reviewer — five providers, one flag, no keys in secrets for cloud."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = { text = "MIT" }
|
|
7
|
+
requires-python = ">=3.12"
|
|
8
|
+
authors = [{ name = "Matt Coles" }]
|
|
9
|
+
dependencies = [
|
|
10
|
+
"pydantic>=2.7",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
[project.urls]
|
|
14
|
+
Homepage = "https://github.com/lgtmaybe/lgtmaybe"
|
|
15
|
+
|
|
16
|
+
[dependency-groups]
|
|
17
|
+
dev = [
|
|
18
|
+
"pytest>=8",
|
|
19
|
+
"ruff>=0.5",
|
|
20
|
+
"mypy>=1.10",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[build-system]
|
|
24
|
+
requires = ["hatchling"]
|
|
25
|
+
build-backend = "hatchling.build"
|
|
26
|
+
|
|
27
|
+
[tool.hatch.build.targets.wheel]
|
|
28
|
+
packages = ["src/lgtmaybe"]
|
|
29
|
+
|
|
30
|
+
[tool.ruff]
|
|
31
|
+
line-length = 100
|
|
32
|
+
target-version = "py312"
|
|
33
|
+
src = ["src", "tests"]
|
|
34
|
+
|
|
35
|
+
[tool.ruff.lint]
|
|
36
|
+
select = ["E", "F", "I", "UP", "B"]
|
|
37
|
+
|
|
38
|
+
[tool.pytest.ini_options]
|
|
39
|
+
testpaths = ["tests"]
|
|
40
|
+
pythonpath = ["src"]
|
|
41
|
+
|
|
42
|
+
[tool.mypy]
|
|
43
|
+
python_version = "3.12"
|
|
44
|
+
packages = ["lgtmaybe"]
|
|
45
|
+
mypy_path = "src"
|
|
46
|
+
strict = true
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Module entrypoint placeholder.
|
|
2
|
+
|
|
3
|
+
The real CLI is wired in the CLI track. For now this keeps `python -m lgtmaybe`
|
|
4
|
+
(and the Docker ENTRYPOINT) runnable on the skeleton.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
from . import __version__
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def main(argv: list[str] | None = None) -> int:
|
|
15
|
+
print(f"lgtmaybe {__version__} — CLI not wired yet (see CLAUDE.md)")
|
|
16
|
+
return 0
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
if __name__ == "__main__":
|
|
20
|
+
sys.exit(main(sys.argv[1:]))
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""cli — populated by its track (see CLAUDE.md)."""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""config — populated by its track (see CLAUDE.md)."""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Core: frozen data contracts and boundary interfaces (ports)."""
|