open-code-review-toolkit 0.1.0__tar.gz → 0.2.0__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.
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/CHANGELOG.md +22 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/PKG-INFO +11 -3
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/README.md +10 -2
- open_code_review_toolkit-0.2.0/changelog.d/README.md +3 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/docs/codex/AGENT_EXECUTION_PITFALLS.md +16 -0
- open_code_review_toolkit-0.2.0/docs/codex/TASKS_BACKLOG.md +87 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/docs/configuration.md +23 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/docs/engineering/project_principles.md +5 -1
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/docs/gitlab.md +5 -1
- open_code_review_toolkit-0.2.0/docs/operations.md +83 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/docs/release.md +17 -2
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/docs/security.md +7 -1
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/examples/gitlab/ocr-review.gitlab-ci.yml +4 -2
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/pyproject.toml +1 -1
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/_version.py +2 -2
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/posting/formatting.py +1 -1
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/posting/markers.py +9 -7
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/posting/snapshot.py +31 -34
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/posting/workflow.py +21 -17
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/preflight.py +1 -1
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/tests/test_context_helpers.py +14 -3
- open_code_review_toolkit-0.2.0/tests/test_install_local_artifact.py +67 -0
- open_code_review_toolkit-0.2.0/tests/test_operations_docs.py +58 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/tests/test_posting_helpers.py +129 -21
- open_code_review_toolkit-0.2.0/tests/test_quality_script.py +12 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/tests/test_release_authorization.py +18 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/tests/test_release_notes.py +8 -0
- open_code_review_toolkit-0.2.0/tests/test_release_process_docs.py +30 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/tests/test_runtime_helpers.py +2 -2
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/tests/test_testpypi_preview.py +36 -4
- open_code_review_toolkit-0.1.0/changelog.d/README.md +0 -3
- open_code_review_toolkit-0.1.0/docs/codex/TASKS_BACKLOG.md +0 -45
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/.gitignore +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/CONTRIBUTING.md +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/LICENSE +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/SECURITY.md +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/docs/development.md +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/examples/gitlab/rules.json +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/__init__.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/cli.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/common/__init__.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/common/language.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/common/markdown.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/common/redaction.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/config_writer.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/configure.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/context/__init__.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/context/__main__.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/context/ansible.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/context/categorize.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/context/instructions.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/context/manifests.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/context/planner.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/context/render.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/context/repo.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/context/settings.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/mcp_config.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/posting/__init__.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/posting/__main__.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/posting/comments.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/posting/gitlab.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/posting/payloads.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/posting/result.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/posting/settings.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/py.typed +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/tests/__init__.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/tests/support.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/tests/test_cli.py +0 -0
- {open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/tests/test_common_helpers.py +0 -0
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
## 0.2.0 - 2026-07-21
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
- Target Open Code Review 1.7.14 in preflight validation and the checksum-pinned GitLab CI example. ([#11](https://github.com/xeonvs/open-code-review-toolkit/issues/11))
|
|
6
|
+
- Replace the ambiguous `/ocr keep` and `/ocr skip` discussion replies with `/ocr resolve` and `/ocr suppress`, preserve human-owned deduplication, and document the complete GitLab review lifecycle for developers and CI operators. ([#8](https://github.com/xeonvs/open-code-review-toolkit/issues/8))
|
|
7
|
+
|
|
8
|
+
### Bug fixes
|
|
9
|
+
|
|
10
|
+
- Allow stable release verification to coexist with previously published development builds of the same base version on TestPyPI. ([#10](https://github.com/xeonvs/open-code-review-toolkit/issues/10))
|
|
11
|
+
- Treat ordinary merged pull requests as a successful no-op in the production release workflow while keeping release-branch authorization fail-closed. ([#7](https://github.com/xeonvs/open-code-review-toolkit/issues/7))
|
|
12
|
+
|
|
13
|
+
### Security
|
|
14
|
+
|
|
15
|
+
- Mark every source-distribution smoke install as hash-required while retaining the no-dependency boundary, and document the single-maintainer security posture and Scorecard triage policy. ([#6](https://github.com/xeonvs/open-code-review-toolkit/issues/6))
|
|
16
|
+
|
|
17
|
+
### Documentation
|
|
18
|
+
|
|
19
|
+
- Reduce the routine Ubuntu CI matrix to the supported Python 3.10 and 3.14 endpoints, matching the macOS matrix. ([#10](https://github.com/xeonvs/open-code-review-toolkit/issues/10))
|
|
20
|
+
- Document accepted project decisions, their optional `ocr-accept` marker convention, and the guard that prevents a merge request from whitelisting its own findings. ([#11](https://github.com/xeonvs/open-code-review-toolkit/issues/11))
|
|
21
|
+
|
|
22
|
+
|
|
1
23
|
## 0.1.0 - 2026-07-20
|
|
2
24
|
|
|
3
25
|
### Features
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: open-code-review-toolkit
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Unofficial GitLab CI integration layer for Open Code Review
|
|
5
5
|
Project-URL: Homepage, https://github.com/xeonvs/open-code-review-toolkit
|
|
6
6
|
Project-URL: Repository, https://github.com/xeonvs/open-code-review-toolkit
|
|
@@ -243,11 +243,19 @@ ocr --version
|
|
|
243
243
|
ocr-ci --help
|
|
244
244
|
```
|
|
245
245
|
|
|
246
|
-
The current compatibility target is OCR `1.7.
|
|
246
|
+
The current compatibility target is OCR `1.7.14`. CI should pin the release and verify its published checksum before execution.
|
|
247
247
|
Review output defaults to English. Set `OCR_REVIEW_LANGUAGE=Russian` to use Russian consistently in both OCR configuration and generated review context.
|
|
248
248
|
|
|
249
249
|
Stable distributions are published to [PyPI](https://pypi.org/project/open-code-review-toolkit/) and mirrored as checksum-listed, provenance-attested assets in the corresponding [GitHub Release](https://github.com/xeonvs/open-code-review-toolkit/releases). Development snapshots are published only to TestPyPI.
|
|
250
250
|
|
|
251
|
+
## How reviews evolve
|
|
252
|
+
|
|
253
|
+
On a successful rerun, the toolkit replaces untouched OCR-only notes instead of accumulating stale reviews. A human reply transfers that discussion to the team: the conversation is preserved and a matching finding is suppressed. Reply with `/ocr suppress` to keep a discussion open without future repeats, or `/ocr resolve` to suppress it and resolve the discussion after the next successful posting transaction.
|
|
254
|
+
|
|
255
|
+
Suppression uses both the GitLab diff position and a stable finding fingerprint, so ordinary line shifts do not normally bring the same bug back. A materially changed finding can still receive a new discussion. See [GitLab review operations](docs/operations.md) for the complete lifecycle, posting modes, permissions, failure behavior, and Mermaid state diagram.
|
|
256
|
+
|
|
257
|
+
Project-wide accepted tradeoffs can be recorded separately in `.opencodereview/accepted-decisions.md`; the context generator supplies them to OCR only when the current merge request is not changing that file. See [Accepted project decisions](docs/configuration.md#accepted-project-decisions) for the entry format, inline marker convention, security boundary, and limitations.
|
|
258
|
+
|
|
251
259
|
## GitLab CI quick start
|
|
252
260
|
|
|
253
261
|
1. Configure protected/masked `GITLAB_API_TOKEN` and LLM variables in GitLab.
|
|
@@ -264,7 +272,7 @@ ocr-ci context --output .review-context/dependencies.md
|
|
|
264
272
|
ocr-ci post --result /tmp/ocr-result.json --stderr /tmp/ocr-stderr.log
|
|
265
273
|
```
|
|
266
274
|
|
|
267
|
-
See the fully synthetic [`examples/gitlab/ocr-review.gitlab-ci.yml`](examples/gitlab/ocr-review.gitlab-ci.yml)
|
|
275
|
+
See the fully synthetic [`examples/gitlab/ocr-review.gitlab-ci.yml`](examples/gitlab/ocr-review.gitlab-ci.yml), the [GitLab setup guide](docs/gitlab.md), and [GitLab review operations](docs/operations.md).
|
|
268
276
|
|
|
269
277
|
## Configuration and safety
|
|
270
278
|
|
|
@@ -15,11 +15,19 @@ ocr --version
|
|
|
15
15
|
ocr-ci --help
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
The current compatibility target is OCR `1.7.
|
|
18
|
+
The current compatibility target is OCR `1.7.14`. CI should pin the release and verify its published checksum before execution.
|
|
19
19
|
Review output defaults to English. Set `OCR_REVIEW_LANGUAGE=Russian` to use Russian consistently in both OCR configuration and generated review context.
|
|
20
20
|
|
|
21
21
|
Stable distributions are published to [PyPI](https://pypi.org/project/open-code-review-toolkit/) and mirrored as checksum-listed, provenance-attested assets in the corresponding [GitHub Release](https://github.com/xeonvs/open-code-review-toolkit/releases). Development snapshots are published only to TestPyPI.
|
|
22
22
|
|
|
23
|
+
## How reviews evolve
|
|
24
|
+
|
|
25
|
+
On a successful rerun, the toolkit replaces untouched OCR-only notes instead of accumulating stale reviews. A human reply transfers that discussion to the team: the conversation is preserved and a matching finding is suppressed. Reply with `/ocr suppress` to keep a discussion open without future repeats, or `/ocr resolve` to suppress it and resolve the discussion after the next successful posting transaction.
|
|
26
|
+
|
|
27
|
+
Suppression uses both the GitLab diff position and a stable finding fingerprint, so ordinary line shifts do not normally bring the same bug back. A materially changed finding can still receive a new discussion. See [GitLab review operations](docs/operations.md) for the complete lifecycle, posting modes, permissions, failure behavior, and Mermaid state diagram.
|
|
28
|
+
|
|
29
|
+
Project-wide accepted tradeoffs can be recorded separately in `.opencodereview/accepted-decisions.md`; the context generator supplies them to OCR only when the current merge request is not changing that file. See [Accepted project decisions](docs/configuration.md#accepted-project-decisions) for the entry format, inline marker convention, security boundary, and limitations.
|
|
30
|
+
|
|
23
31
|
## GitLab CI quick start
|
|
24
32
|
|
|
25
33
|
1. Configure protected/masked `GITLAB_API_TOKEN` and LLM variables in GitLab.
|
|
@@ -36,7 +44,7 @@ ocr-ci context --output .review-context/dependencies.md
|
|
|
36
44
|
ocr-ci post --result /tmp/ocr-result.json --stderr /tmp/ocr-stderr.log
|
|
37
45
|
```
|
|
38
46
|
|
|
39
|
-
See the fully synthetic [`examples/gitlab/ocr-review.gitlab-ci.yml`](examples/gitlab/ocr-review.gitlab-ci.yml)
|
|
47
|
+
See the fully synthetic [`examples/gitlab/ocr-review.gitlab-ci.yml`](examples/gitlab/ocr-review.gitlab-ci.yml), the [GitLab setup guide](docs/gitlab.md), and [GitLab review operations](docs/operations.md).
|
|
40
48
|
|
|
41
49
|
## Configuration and safety
|
|
42
50
|
|
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Agent Execution Pitfalls
|
|
2
2
|
|
|
3
|
+
## Closing a public-contract change after only the feature merge
|
|
4
|
+
|
|
5
|
+
**Failure mode:** A feature changes a public command or integration contract, its pull request merges, and a TestPyPI `.devN` build succeeds. The plan is then marked completed even though stable PyPI users still receive the old behavior.
|
|
6
|
+
|
|
7
|
+
**Why it happens:** Implementation, preview publication, and stable delivery are treated as separate mental tasks even when the user asked for one outcome. SCM-derived versions also make the source tree appear ready for the next version without proving that a stable tag or package exists.
|
|
8
|
+
|
|
9
|
+
**Required prevention:**
|
|
10
|
+
|
|
11
|
+
1. Classify the work at plan start and write the target stable version into `PLANS.md`.
|
|
12
|
+
2. Treat feature merge and TestPyPI `.devN` verification as intermediate receipts.
|
|
13
|
+
3. When release is required, prepare the version/changelog release PR immediately after the development build is verified.
|
|
14
|
+
4. Keep the objective active until the release workflow publishes and independent readback confirms PyPI, TestPyPI, the signed tag, immutable GitHub Release, hashes, attestations, and supported-Python installs.
|
|
15
|
+
5. If publication is intentionally deferred, record who deferred it, why, and the exact command or PR needed to resume.
|
|
16
|
+
|
|
17
|
+
**Closure question:** "Can a user installing from production PyPI obtain the promised behavior now?" If not, the stable-release objective is not complete.
|
|
18
|
+
|
|
3
19
|
This note records recurring execution mistake patterns discovered during real work. Record generalized lessons, not one-off complaints.
|
|
4
20
|
|
|
5
21
|
## Planning And Context Discipline
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Tasks Backlog
|
|
2
|
+
|
|
3
|
+
This file tracks future work that is not active. Active extraction work is owned by `PLANS.md`.
|
|
4
|
+
|
|
5
|
+
## Backlog Item: Native fuzzing campaign
|
|
6
|
+
|
|
7
|
+
Status: parked
|
|
8
|
+
Priority: medium
|
|
9
|
+
|
|
10
|
+
### Activation Trigger
|
|
11
|
+
|
|
12
|
+
- A supported Python fuzzing backend is selected with reproducible local execution, bounded CI resources, and corpus ownership.
|
|
13
|
+
|
|
14
|
+
### Goal
|
|
15
|
+
|
|
16
|
+
Fuzz the untrusted-input boundaries with meaningful targets for result normalization, context rendering, GitLab payload parsing, and registry metadata validation. Integrate a public fuzzing service only after the targets demonstrate useful coverage and stable crash minimization.
|
|
17
|
+
|
|
18
|
+
### Next Safe Action
|
|
19
|
+
|
|
20
|
+
1. Compare Atheris with property-based alternatives across Python 3.10-3.14 and design a small synthetic seed corpus without adding a runtime dependency.
|
|
21
|
+
|
|
22
|
+
### Exit Criteria
|
|
23
|
+
|
|
24
|
+
- Native targets run locally and in bounded CI, retain minimized synthetic regressions, publish no repository or provider secrets, and are recognized by the selected fuzzing service.
|
|
25
|
+
|
|
26
|
+
## Backlog Item: OpenSSF Best Practices registration
|
|
27
|
+
|
|
28
|
+
Status: owner action
|
|
29
|
+
Priority: low
|
|
30
|
+
|
|
31
|
+
### Activation Trigger
|
|
32
|
+
|
|
33
|
+
- The owner is ready to authenticate at `bestpractices.dev` and attest every passing-level criterion truthfully.
|
|
34
|
+
|
|
35
|
+
### Goal
|
|
36
|
+
|
|
37
|
+
Register the public repository for an OpenSSF Best Practices badge without guessing owner-only governance or project-usage answers.
|
|
38
|
+
|
|
39
|
+
### Next Safe Action
|
|
40
|
+
|
|
41
|
+
1. Complete the passing-level questionnaire with evidence links to the public repository and leave unsupported criteria unmet.
|
|
42
|
+
|
|
43
|
+
### Exit Criteria
|
|
44
|
+
|
|
45
|
+
- The public badge record exists, all answers have current evidence, and the README displays only the earned status.
|
|
46
|
+
|
|
47
|
+
## Backlog Item: Additional provider adapters
|
|
48
|
+
|
|
49
|
+
Status: parked
|
|
50
|
+
Priority: low
|
|
51
|
+
|
|
52
|
+
### Activation Trigger
|
|
53
|
+
|
|
54
|
+
- A provider-neutral core has shipped and a concrete provider integration has an owner and testable API contract.
|
|
55
|
+
|
|
56
|
+
### Goal
|
|
57
|
+
|
|
58
|
+
Add another code-hosting adapter without weakening the provider-neutral core or GitLab behavior.
|
|
59
|
+
|
|
60
|
+
### Next Safe Action
|
|
61
|
+
|
|
62
|
+
1. Write an adapter contract proposal based on the shipped GitLab boundary and validate it against synthetic fixtures.
|
|
63
|
+
|
|
64
|
+
### Exit Criteria
|
|
65
|
+
|
|
66
|
+
- The new adapter has isolated tests, documentation, and no provider-specific leakage into core modules.
|
|
67
|
+
|
|
68
|
+
## Backlog Item: File-based user configuration
|
|
69
|
+
|
|
70
|
+
Status: parked
|
|
71
|
+
Priority: low
|
|
72
|
+
|
|
73
|
+
### Activation Trigger
|
|
74
|
+
|
|
75
|
+
- Environment-only configuration becomes a demonstrated usability constraint after v0.1.
|
|
76
|
+
|
|
77
|
+
### Goal
|
|
78
|
+
|
|
79
|
+
Evaluate a versioned user configuration file without silently changing environment precedence or secret handling.
|
|
80
|
+
|
|
81
|
+
### Next Safe Action
|
|
82
|
+
|
|
83
|
+
1. Draft a schema and threat model; do not implement until compatibility and migration behavior are agreed.
|
|
84
|
+
|
|
85
|
+
### Exit Criteria
|
|
86
|
+
|
|
87
|
+
- Schema, precedence, migration, secret handling, and validation behavior are documented and tested.
|
|
@@ -41,4 +41,27 @@ Posting requires `GITLAB_API_TOKEN`, `CI_SERVER_URL`, `CI_PROJECT_ID`, and `CI_M
|
|
|
41
41
|
|
|
42
42
|
The `OCR_CONTEXT_*` family bounds files, bytes, changed paths, instructions, manifest content, dependency output, and generated background size. `OCR_BACKGROUND_MAX_CHARS` defaults to and is capped at `7950`; `OCR_BACKGROUND_MAX_BYTES` independently enforces the UTF-8 byte budget. The default output is `.review-context/dependencies.md`. The generator rejects symlink escapes and prunes common vendor/build directories.
|
|
43
43
|
|
|
44
|
+
### Accepted project decisions
|
|
45
|
+
|
|
46
|
+
Use `.opencodereview/accepted-decisions.md` for a reviewed, project-wide decision that OCR would otherwise report repeatedly. Each entry should have a stable slug, a concise rationale, an explicit scope, and an inline marker that ties the decision to the relevant code or configuration:
|
|
47
|
+
|
|
48
|
+
```markdown
|
|
49
|
+
## generated-client-timeout
|
|
50
|
+
|
|
51
|
+
The generated client keeps the provider's 90-second timeout so regenerated
|
|
52
|
+
code remains reproducible. Do not report that timeout in `src/client/generated.py`.
|
|
53
|
+
|
|
54
|
+
Look for `# ocr-accept: generated-client-timeout` at the configured value.
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
REQUEST_TIMEOUT = 90 # ocr-accept: generated-client-timeout
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`ocr-accept` is a human-readable convention, not a source-code parser or blanket linter suppression. The complete, byte-bounded Markdown file is sanitized, redacted, and included under `Accepted project decisions` in the generated review background; OCR is instructed not to raise matching findings. Keep the rationale narrow and name the affected paths or behavior so unrelated findings remain reviewable.
|
|
62
|
+
|
|
63
|
+
The decision file must already exist on the target branch and pass normal review. If the current merge request changes `.opencodereview/accepted-decisions.md`, or changed-file discovery fails, the toolkit omits all accepted decisions for that run to prevent self-whitelisting. A decision reduces repeated model findings but is not a deterministic static-analysis exemption: reviewers should still use `/ocr suppress` or `/ocr resolve` for a concrete GitLab discussion, and should update or remove stale decisions when the underlying tradeoff changes.
|
|
64
|
+
|
|
65
|
+
Use the default `OCR_POST_MODE=draft` for normal CI so all current notes are created as drafts before they are published and replaceable notes from the previous run are removed. Draft publication is sequential rather than atomic; the previous review is preserved unless every current draft publishes. Set `OCR_STRICT_POSTING=true` when the review job is a required merge gate; keep the default `false` only for advisory pipelines where GitLab posting availability must not block the pipeline. Reviewer commands and the complete repeated-run contract are documented in [GitLab review operations](operations.md).
|
|
66
|
+
|
|
44
67
|
Run `ocr-ci --help` and each subcommand's help for command arguments. Secret values are redacted from operational error text.
|
|
@@ -14,6 +14,10 @@ This is the short index of stable cross-cutting engineering rules for Open Code
|
|
|
14
14
|
8. Use coherent production-quality slices when work must be decomposed; do not leave placeholder architecture as a milestone.
|
|
15
15
|
9. Require changelog fragments for user-visible 0.1.x changes and SCM tags for versions.
|
|
16
16
|
10. Treat TestPyPI as public disclosure and preserve the manual privacy/license gate before publishing.
|
|
17
|
+
11. Treat automated security scores as evidence to classify, not targets to game; remediate concrete repository-owned risk and document temporal or governance constraints truthfully.
|
|
18
|
+
12. Version public behavior deliberately. An incompatible pre-1.0 contract change may select the next minor version, but it is not delivered to stable users until the versioned package and release artifacts are published and independently verified.
|
|
19
|
+
13. Keep implementation and release as one traceable objective whenever stable publication is requested or required. Feature validation proves readiness; registry and GitHub readback prove delivery.
|
|
20
|
+
14. A deferral is a blocked or pending release state, not successful closure. Preserve the exact continuation point so a later agent does not infer that a development build satisfied a stable-release promise.
|
|
17
21
|
|
|
18
22
|
## Documentation Ownership
|
|
19
23
|
|
|
@@ -22,5 +26,5 @@ This is the short index of stable cross-cutting engineering rules for Open Code
|
|
|
22
26
|
- `docs/gitlab.md` owns GitLab installation and operating guidance.
|
|
23
27
|
- `docs/security.md` owns the runtime trust model; `SECURITY.md` owns vulnerability reporting.
|
|
24
28
|
- `docs/development.md` owns local contributor commands.
|
|
25
|
-
- `docs/release.md` owns
|
|
29
|
+
- `docs/release.md` owns release classification, delivery, and disclosure.
|
|
26
30
|
- `AGENTS.md`, `PLANS.md`, and `docs/codex/` own agent workflow rather than product behavior.
|
|
@@ -4,7 +4,7 @@ The toolkit's first provider adapter posts review results to GitLab merge reques
|
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
|
-
Install `open-code-review-toolkit` from PyPI. The example obtains the expected toolkit wheel digest from the matching immutable GitHub Release, then uses pip hash-checking and a local install. Install Open Code Review separately and pin `v1.7.
|
|
7
|
+
Install `open-code-review-toolkit` from PyPI. The example obtains the expected toolkit wheel digest from the matching immutable GitHub Release, then uses pip hash-checking and a local install. Install Open Code Review separately and pin `v1.7.14`; verify the release checksum before making the binary executable. The package never downloads OCR.
|
|
8
8
|
|
|
9
9
|
Copy and adapt [the synthetic CI example](../examples/gitlab/ocr-review.gitlab-ci.yml). Keep the lint stage before the AI review stage so failed project checks block review. The example downloads a pinned toolkit wheel with bounded retries/timeouts, verifies its SHA-256 before a local `--no-deps` install, generates one background file, and passes it once with `--background-file`.
|
|
10
10
|
|
|
@@ -22,6 +22,10 @@ Store secrets as masked, protected CI variables. Do not place them in YAML, comm
|
|
|
22
22
|
|
|
23
23
|
`ocr-ci preflight` validates the installed OCR version, GitLab access, and configured LLM model. `configure` and `context` resolve the same `OCR_REVIEW_LANGUAGE` value, so the OCR system prompt and review background cannot disagree. `configure` and `mcp-config` write OCR configuration without invoking a config subprocess. `context` creates bounded Markdown. `post` interprets a JSON artifact and publishes bounded notes with rollback and ownership safeguards.
|
|
24
24
|
|
|
25
|
+
Repeated reviews have a reviewer-controlled lifecycle rather than appending the same notes indefinitely. Untouched OCR-only notes are replaced after a successful run, human-touched discussions are preserved, and `/ocr suppress` or `/ocr resolve` controls future matching findings. Read [GitLab review operations](operations.md) for the complete state machine, deduplication boundaries, posting modes, permissions, limits, and failure semantics.
|
|
26
|
+
|
|
27
|
+
For a deliberate project-wide tradeoff that should be supplied to every review, add a narrowly scoped entry to `.opencodereview/accepted-decisions.md` in an earlier reviewed merge request. The [configuration reference](configuration.md#accepted-project-decisions) documents its `ocr-accept` marker convention, prompt-level semantics, and self-whitelisting guard.
|
|
28
|
+
|
|
25
29
|
OCR is configured through its `openai-responses` provider. Optional stdio bridge tools are supplied with `OCR_MCP_SERVERS_JSON`; treat every configured MCP command as privileged code.
|
|
26
30
|
|
|
27
31
|
Use merge-request source and base SHAs, not a merge-result commit, when choosing the reviewed range. Keep the self-test job manual. See [docs/security.md](security.md) for trust boundaries and [docs/configuration.md](configuration.md) for every input.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# GitLab review operations
|
|
2
|
+
|
|
3
|
+
This guide is for developers and CI operators who connect Open Code Review Toolkit to a GitLab merge-request pipeline and need to understand what happens after the first review. Installation remains in [gitlab.md](gitlab.md); the complete environment contract is in [configuration.md](configuration.md).
|
|
4
|
+
|
|
5
|
+
## What one review run publishes
|
|
6
|
+
|
|
7
|
+
The toolkit reads the previous OCR-owned notes and discussions before it writes anything. It fingerprints new findings, removes findings already owned or suppressed by reviewers, and publishes:
|
|
8
|
+
|
|
9
|
+
- inline GitLab discussions when a finding has a valid diff position;
|
|
10
|
+
- bounded fallback notes when GitLab cannot accept a position, for example after relevant lines moved outside the current diff;
|
|
11
|
+
- one summary note with counts, warnings, omitted findings, review effort, reviewed commit identity, and available token/tool usage.
|
|
12
|
+
|
|
13
|
+
`OCR_MAX_POST_COMMENTS` limits individually published findings. The default is 50 and the hard limit is 200. Omitted findings are counted in the summary rather than silently disappearing.
|
|
14
|
+
|
|
15
|
+
## Discussion lifecycle
|
|
16
|
+
|
|
17
|
+
```mermaid
|
|
18
|
+
flowchart LR
|
|
19
|
+
finding[OCR finding] --> position{Valid diff position?}
|
|
20
|
+
position -- No --> fallback[Fallback MR note]
|
|
21
|
+
position -- Yes --> open[Open OCR discussion]
|
|
22
|
+
|
|
23
|
+
open --> action{Reviewer action before rerun}
|
|
24
|
+
action -- No action --> replace[Replace after successful rerun]
|
|
25
|
+
replace --> open
|
|
26
|
+
action -- Human reply --> owned[Human-owned and suppressed]
|
|
27
|
+
action -- Resolve in GitLab --> resolved[Resolved and suppressed]
|
|
28
|
+
action -- OCR command --> command{Command}
|
|
29
|
+
command -- suppress --> suppressed[Open and suppressed]
|
|
30
|
+
command -- resolve --> pending[Resolve requested]
|
|
31
|
+
pending -- Publish succeeds --> resolved
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
If posting fails, the transition does not complete: the previous review and every human-owned, suppressed, or resolve-requested discussion keep their prior state. Matching findings remain suppressed on later runs.
|
|
35
|
+
|
|
36
|
+
An untouched open OCR discussion is bot-owned. A successful rerun replaces bot-owned notes with the current review instead of accumulating stale copies. Once a person replies, the discussion becomes human-owned: the toolkit preserves the complete conversation and suppresses a finding at the recorded inline position or with a compatible fingerprint.
|
|
37
|
+
|
|
38
|
+
A discussion resolved with GitLab's normal Resolve action is also preserved and suppresses a matching future finding. The toolkit never reopens a discussion.
|
|
39
|
+
|
|
40
|
+
## Reviewer commands
|
|
41
|
+
|
|
42
|
+
Reply inside an OCR-created discussion with exactly one command. Commands are case-insensitive, but the whole reply must contain only the command and optional surrounding whitespace. A command inside prose or a code block is ignored. If reviewers post several recognized commands, the newest one wins. Bot and GitLab system notes cannot issue commands.
|
|
43
|
+
|
|
44
|
+
| Command | Discussion after the command | Matching finding on future runs |
|
|
45
|
+
| --- | --- | --- |
|
|
46
|
+
| `/ocr suppress` | Remains open | Suppressed |
|
|
47
|
+
| `/ocr resolve` | Resolved after the next successful posting transaction | Suppressed |
|
|
48
|
+
| Ordinary human reply | Remains in its current state and becomes human-owned | Matching position or fingerprint suppressed |
|
|
49
|
+
| GitLab Resolve action | Resolved | Suppressed |
|
|
50
|
+
|
|
51
|
+
The command is applied when the next pipeline reads the discussion. `/ocr resolve` waits until all notes created for the current review have published successfully before resolving the old discussion. A failed run therefore does not close it prematurely.
|
|
52
|
+
|
|
53
|
+
`/ocr keep` and `/ocr skip` were removed in 0.2.0 and are not aliases. An existing reply containing an old command still counts as an ordinary human reply: its conversation is preserved and matching future findings remain suppressed, but it does not request automatic resolution.
|
|
54
|
+
|
|
55
|
+
## Will OCR report the same bug again?
|
|
56
|
+
|
|
57
|
+
Every OCR note contains an invisible toolkit marker and a stable finding fingerprint. The current fingerprint combines the repository path, normalized finding text, and the existing-code fragment when OCR supplies one. This lets suppression survive an ordinary line shift. Backward-compatible fingerprints keep review decisions made by earlier toolkit versions usable.
|
|
58
|
+
|
|
59
|
+
Suppression checks both the recorded inline position and compatible fingerprints. A new finding anchored to the same recorded path and line is suppressed even if its text changes; elsewhere, the fingerprint prevents ordinary line movement from bypassing the decision. Suppression is intentionally not a permanent rule for an entire file: a materially different explanation, code fragment, path, or duplicate occurrence at another location can become a new finding and receive a new discussion. When identical findings occur more than once, occurrence-aware fingerprints prevent suppressing every occurrence after a reviewer acts on only one of them.
|
|
60
|
+
|
|
61
|
+
## Posting modes and blocking behavior
|
|
62
|
+
|
|
63
|
+
`OCR_POST_MODE=draft` is the safe default. The toolkit creates this run's notes as GitLab draft notes, publishes only those drafts one by one, and removes replaceable notes from the previous successful review only after every publish succeeds. If creation fails, drafts from the current attempt are removed and the previous review remains visible. Draft mode avoids exposing an incomplete review during the creation phase, but GitLab does not provide an atomic bulk-publish transaction.
|
|
64
|
+
|
|
65
|
+
`OCR_POST_MODE=direct` writes notes immediately. It exists as an emergency compatibility override. The toolkit still performs best-effort rollback, but an ambiguous network timeout can mean GitLab accepted a write that the runner cannot confirm. Prefer `draft` for normal CI.
|
|
66
|
+
|
|
67
|
+
`OCR_STRICT_POSTING=false` is the advisory default: an OCR or posting error remains visible in the job log and, when possible, in an MR note, but the posting helper exits successfully. Set `OCR_STRICT_POSTING=true` when OCR review is a required merge gate so OCR failures, an unavailable GitLab API, an unsafe previous-state snapshot, an invalid OCR result, or failed publication make the job fail.
|
|
68
|
+
|
|
69
|
+
## GitLab identity and permissions
|
|
70
|
+
|
|
71
|
+
Use a dedicated project access token with `api` scope and at least the Developer role. Store it in `GITLAB_API_TOKEN`. The toolkit needs to read merge-request notes, discussions, diff refs, and the current token identity; create and delete its own notes or drafts; publish drafts; and resolve discussions requested by reviewers.
|
|
72
|
+
|
|
73
|
+
The toolkit calls `GET /user` before posting and refuses to write if it cannot identify the token owner. It treats a note as bot-owned only when both the invisible OCR marker and the actual GitLab author ID match. Text that merely imitates an OCR marker is not enough to claim or delete another user's note.
|
|
74
|
+
|
|
75
|
+
## Reruns, failures, and fallback notes
|
|
76
|
+
|
|
77
|
+
Before a rerun, the toolkit takes a bounded snapshot of OCR-owned notes, discussions, and drafts. If it cannot collect that state reliably, it refuses to publish a replacement so resolved, suppressed, and human-owned decisions are not lost. Reads and writes have bounded response sizes and timeouts; writes are retried only when retrying is safe.
|
|
78
|
+
|
|
79
|
+
The previous review is deleted only after the new review has been created and, in draft mode, published. A definite write failure rolls back notes known to belong to the current attempt. An ambiguous draft-publish failure does not delete possibly published notes because the runner cannot prove which writes GitLab accepted.
|
|
80
|
+
|
|
81
|
+
When GitLab rejects an inline position as invalid, the toolkit moves that finding into one or more bounded fallback notes. Ambiguous write failures do not use fallback, because doing so could duplicate a discussion that GitLab already accepted.
|
|
82
|
+
|
|
83
|
+
Source and base merge-request SHAs define the reviewed range. A merge-result commit is not treated as the source branch head. The summary records the reviewed SHA and warns when the current MR head has moved, so reviewers can distinguish a current review from a stale pipeline result.
|
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
# Releases
|
|
2
2
|
|
|
3
|
-
Production versions come from SCM tags through hatch-vcs. The tracked `.release-version` and `.release-source-date-epoch` files authorize one reproducible stable build, while `.next-version` defines the next TestPyPI development line. Public interfaces may evolve before 1.0, but every user-visible 0.
|
|
3
|
+
Production versions come from SCM tags through hatch-vcs. The tracked `.release-version` and `.release-source-date-epoch` files authorize one reproducible stable build, while `.next-version` defines the next TestPyPI development line. Public interfaces may evolve before 1.0, but every user-visible 0.x change still requires a Towncrier fragment.
|
|
4
|
+
|
|
5
|
+
## Release-required changes
|
|
6
|
+
|
|
7
|
+
A change is release-required when it removes or incompatibly changes a public CLI, environment variable, generated schema, reviewer command, or documented integration behavior, or when the user explicitly requests stable publication. Select the target version before implementation closure and keep one active plan through both development and release delivery. Other user-visible fixes and features must still be classified explicitly; they are not automatically entitled to a stable release after every merge.
|
|
8
|
+
|
|
9
|
+
The delivery sequence is:
|
|
10
|
+
|
|
11
|
+
1. merge the feature through protected `main`;
|
|
12
|
+
2. verify the deterministic `.devN` wheel and sdist on TestPyPI;
|
|
13
|
+
3. prepare a signed `release/vX.Y.Z` pull request containing the stable version marker, deterministic epoch, generated Towncrier changelog, and next development line;
|
|
14
|
+
4. use release-PR merge as the human authorization gate;
|
|
15
|
+
5. monitor TestPyPI stable publication, production PyPI publication, signed tag, provenance, and immutable GitHub Release;
|
|
16
|
+
6. independently compare artifact hashes and smoke-install the wheel on Python 3.10 and the sdist on Python 3.14.
|
|
17
|
+
|
|
18
|
+
Do not mark the objective complete after step 1 or 2. If the owner explicitly defers stable publication, record the target version and exact resume point in `PLANS.md`.
|
|
4
19
|
|
|
5
20
|
## Development builds
|
|
6
21
|
|
|
7
|
-
Every non-release push to protected `main` runs the **TestPyPI development build** workflow. The immutable workflow run number produces `0.
|
|
22
|
+
Every non-release push to protected `main` runs the **TestPyPI development build** workflow. The immutable workflow run number produces `<next-version>.devN` (for example `0.3.0.devN` after the 0.2.0 release); rerunning the same run reuses the version and succeeds only when the already-published filenames and SHA-256 values match the reviewed artifacts. The workflow uses TestPyPI Trusted Publishing, publishes attestations, verifies bounded HTTPS downloads, and smoke-installs the exact wheel and sdist locally with `--no-deps`.
|
|
8
23
|
|
|
9
24
|
Development builds never create tags or GitHub Releases and never publish to production PyPI. TestPyPI is public disclosure, so only reviewed pull requests may reach `main`.
|
|
10
25
|
|
|
@@ -18,6 +18,12 @@ The toolkit bridges four trust domains: repository content, OCR and its LLM/MCP
|
|
|
18
18
|
|
|
19
19
|
Use a dedicated bot identity and least-privilege `GITLAB_API_TOKEN`. Protect and mask credentials. Do not expose secrets to pipelines for untrusted forks. Begin with manual execution for trusted contributors, review generated notes, and enable automatic posting only after the repository's threat model is accepted.
|
|
20
20
|
|
|
21
|
-
Pin Open Code Review `v1.7.
|
|
21
|
+
Pin Open Code Review `v1.7.14` and verify its checksum. Pin Python dependencies through `uv.lock` and GitHub Actions by immutable commit SHA. MCP servers are privileged child processes; allow only reviewed commands and tools.
|
|
22
|
+
|
|
23
|
+
## Repository security posture
|
|
24
|
+
|
|
25
|
+
Protected `main` requires pull requests, signed commits, a current branch, resolved review threads, and the complete CI, package-build, dependency, secret, and CodeQL check set. The project currently has one maintainer, so it cannot truthfully require an independent human approval for maintainer-authored changes. This is an explicit residual risk: automated review does not replace a second human. External contributions still receive maintainer review, and independent approval will become mandatory when a second active maintainer can provide it without blocking security fixes.
|
|
26
|
+
|
|
27
|
+
OpenSSF Scorecard findings are interpreted as supply-chain posture signals rather than vulnerability reports. Repository-age and historical-coverage checks improve only with time and repeated runs; badge registration requires owner attestations; a useful fuzzing integration requires native fuzz targets and infrastructure rather than a workflow added only to satisfy a scanner. Actionable repository-owned findings are fixed through normal signed pull requests.
|
|
22
28
|
|
|
23
29
|
The detailed environment contract is in [configuration.md](configuration.md). Vulnerability reporting is in [SECURITY.md](../SECURITY.md).
|
|
@@ -6,10 +6,12 @@ default:
|
|
|
6
6
|
image: python:3.12-slim
|
|
7
7
|
|
|
8
8
|
variables:
|
|
9
|
-
OCR_VERSION: "v1.7.
|
|
9
|
+
OCR_VERSION: "v1.7.14"
|
|
10
10
|
OCR_TOOLKIT_VERSION: "0.1.0"
|
|
11
11
|
OCR_TOOLKIT_CHECKSUMS_URL: "https://github.com/xeonvs/open-code-review-toolkit/releases/download/v0.1.0/SHA256SUMS"
|
|
12
|
-
OCR_SHA256: "
|
|
12
|
+
OCR_SHA256: "f5ee3118b72fe702c94457aa466ebad82b8d4bf6ced6e0347534f4cfdbcc5f8b"
|
|
13
|
+
OCR_POST_MODE: "draft"
|
|
14
|
+
OCR_STRICT_POSTING: "true"
|
|
13
15
|
OCR_LLM_VALIDATE_MODEL: "false"
|
|
14
16
|
OCR_LLM_ALLOWED_MODELS: ""
|
|
15
17
|
OCR_RUN_HELPER_TESTS: "false"
|
{open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/_version.py
RENAMED
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.
|
|
22
|
-
__version_tuple__ = version_tuple = (0,
|
|
21
|
+
__version__ = version = '0.2.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 2, 0)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -234,7 +234,7 @@ def format_omitted_comments_summary(
|
|
|
234
234
|
|
|
235
235
|
return (
|
|
236
236
|
"**Open Code Review omitted comments**\n\n"
|
|
237
|
-
f"After reviewer
|
|
237
|
+
f"After reviewer suppression filters, Open Code Review has "
|
|
238
238
|
f"{publishable_total} publishable comment(s). This CI job publishes "
|
|
239
239
|
f"at most {publish_limit} comment(s) per run. The remaining {omitted} "
|
|
240
240
|
"comment(s) were "
|
{open_code_review_toolkit-0.1.0 → open_code_review_toolkit-0.2.0}/src/ocr_toolkit/posting/markers.py
RENAMED
|
@@ -19,7 +19,9 @@ MARKER_WITH_FINGERPRINT_RE = re.compile(
|
|
|
19
19
|
)
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
OCR_REPLY_COMMAND_RE = re.compile(
|
|
22
|
+
OCR_REPLY_COMMAND_RE = re.compile(
|
|
23
|
+
r"(?i)\A[ \t]*/ocr[ \t]+(suppress|resolve)[ \t]*(?:\r?\n[ \t]*)*\Z"
|
|
24
|
+
)
|
|
23
25
|
|
|
24
26
|
|
|
25
27
|
FINGERPRINT_LEN = 32 # hex characters (= 16 raw bytes from blake2b)
|
|
@@ -94,7 +96,7 @@ def comment_fingerprint(comment: dict[str, Any]) -> str | None:
|
|
|
94
96
|
|
|
95
97
|
The hash combines path, normalized review text, and the commented code
|
|
96
98
|
fragment (`existing_code`) when OCR provides it. It omits the anchor line
|
|
97
|
-
only when that code anchor exists, so resolved findings and `/ocr
|
|
99
|
+
only when that code anchor exists, so resolved findings and `/ocr suppress`
|
|
98
100
|
survive ordinary line shifts without broadening generic no-code comments
|
|
99
101
|
across a whole file. Returns None for comments missing a usable path.
|
|
100
102
|
|
|
@@ -162,8 +164,8 @@ def legacy_comment_fingerprint(comment: dict[str, Any]) -> str | None:
|
|
|
162
164
|
"""Return the pre-migration 16-hex fingerprint for one OCR finding.
|
|
163
165
|
|
|
164
166
|
Why: markers produced before the 8→16 byte digest migration are still
|
|
165
|
-
stored in resolved
|
|
166
|
-
`/ocr
|
|
167
|
+
stored in resolved or suppressed discussions. Without this companion,
|
|
168
|
+
`/ocr suppress` decisions made under the old length would silently stop
|
|
167
169
|
suppressing their findings after the migration. Same line-based
|
|
168
170
|
payload as the previous fingerprint implementation, narrower digest.
|
|
169
171
|
"""
|
|
@@ -180,7 +182,7 @@ def comment_fingerprint_candidates(comment: dict[str, Any]) -> set[str]:
|
|
|
180
182
|
annotated = comment.get("_ocr_fingerprint")
|
|
181
183
|
if isinstance(annotated, str) and annotated:
|
|
182
184
|
# For duplicate findings, the annotated marker is the current run's
|
|
183
|
-
# identity. Do not also include the base hash:
|
|
185
|
+
# identity. Do not also include the base hash: suppressing the first
|
|
184
186
|
# duplicate would suppress every later duplicate in the same file.
|
|
185
187
|
candidates = {annotated}
|
|
186
188
|
if line_number(comment.get("start_line") or comment.get("line")) > 0:
|
|
@@ -249,8 +251,8 @@ def is_diff_note(note: dict[str, Any]) -> bool:
|
|
|
249
251
|
|
|
250
252
|
Such notes are owned by the /discussions cycle and must NOT be
|
|
251
253
|
deleted via DELETE /notes/{id}, otherwise a reviewer-preserved
|
|
252
|
-
thread (resolved, /ocr
|
|
253
|
-
decision to
|
|
254
|
+
thread (resolved, /ocr suppress, /ocr resolve) gets destroyed despite our
|
|
255
|
+
decision to preserve it.
|
|
254
256
|
"""
|
|
255
257
|
|
|
256
258
|
if note.get("type") == "DiffNote":
|