open-code-review-toolkit 0.8.2__tar.gz → 0.8.3__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.8.2 → open_code_review_toolkit-0.8.3}/PKG-INFO +1 -1
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/_version.py +2 -2
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/ocr_result.py +17 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/posting/formatting.py +43 -54
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/posting/settings.py +0 -6
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/review_runner.py +56 -58
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/.gitignore +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/LICENSE +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/README.md +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/pyproject.toml +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/__init__.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/cli.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/common/__init__.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/common/filesystem.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/common/git.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/common/language.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/common/markdown.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/common/redaction.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/config_writer.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/configure.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/context/__init__.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/context/adapters.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/context/broker.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/context/contracts.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/context/dlp.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/context/mcp.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/context/policy.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/context/recognizers.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/context/store.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/__init__.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/__main__.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/actions.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/artifacts.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/categorize.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/collect.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/collectors/__init__.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/collectors/graphs.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/collectors/orchestration.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/collectors/projections.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/collectors/registry.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/collectors/sources.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/coverage.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/ecosystems/__init__.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/ecosystems/ansible/__init__.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/ecosystems/ansible/requirements.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/ecosystems/ansible/topology.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/ecosystems/contracts.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/ecosystems/go.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/ecosystems/javascript.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/ecosystems/php.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/ecosystems/python.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/frameworks/__init__.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/frameworks/contracts.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/frameworks/detection.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/frameworks/providers/__init__.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/frameworks/providers/frontend.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/frameworks/providers/go.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/frameworks/providers/php.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/frameworks/providers/python.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/frameworks/registry.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/frameworks/schema.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/frameworks/templates.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/infrastructure.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/invocation.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/mcp.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/model.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/policy/__init__.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/policy/contracts.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/policy/decisions.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/policy/guidance.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/policy/registry.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/policy/schema.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/policy/scopes.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/project.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/repository.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/review_context.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/store/__init__.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/store/atomic.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/store/contracts.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/store/core.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/store/readback.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/store/values.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/mcp_config.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/posting/__init__.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/posting/__main__.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/posting/approval.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/posting/comments.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/posting/gitlab.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/posting/gitlab_approval.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/posting/markers.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/posting/payloads.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/posting/reconciliation.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/posting/result.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/posting/snapshot.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/posting/suggestions.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/posting/transaction.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/posting/workflow.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/pre_execution.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/preflight.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/provider_config.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/provider_failure.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/providers/__init__.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/providers/gitlab.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/providers/gitlab_context.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/providers/gitlab_discussions.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/providers/gitlab_identity.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/providers/gitlab_remediation.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/py.typed +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/result_contract.py +0 -0
- {open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/result_usage.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: open-code-review-toolkit
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.3
|
|
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
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/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.8.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 8,
|
|
21
|
+
__version__ = version = '0.8.3'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 8, 3)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/ocr_result.py
RENAMED
|
@@ -27,6 +27,23 @@ MAX_TOOLKIT_MCP_TOOL_NAME_CHARS = 4_096
|
|
|
27
27
|
MAX_TOOLKIT_MCP_USAGE_COUNT = 1_000_000_000
|
|
28
28
|
TOOLKIT_MCP_SERVER_NAME_RE = re.compile(r"^[A-Za-z0-9_-]{1,64}$")
|
|
29
29
|
|
|
30
|
+
# Closed names whose numeric call counts may appear in the public review summary.
|
|
31
|
+
# Dynamic external MCP tools remain represented by the receipt's verified
|
|
32
|
+
# per-server aggregate so provider-controlled names do not cross into GitLab.
|
|
33
|
+
PUBLIC_REVIEW_TOOL_CALL_NAMES = frozenset(
|
|
34
|
+
{
|
|
35
|
+
"code_comment",
|
|
36
|
+
"code_search",
|
|
37
|
+
"context_get",
|
|
38
|
+
"context_list",
|
|
39
|
+
"file_find",
|
|
40
|
+
"file_read",
|
|
41
|
+
"file_read_diff",
|
|
42
|
+
"ocr_toolkit_evidence",
|
|
43
|
+
"task_done",
|
|
44
|
+
}
|
|
45
|
+
)
|
|
46
|
+
|
|
30
47
|
|
|
31
48
|
class OcrResultMissing(Exception):
|
|
32
49
|
"""The OCR result artifact is missing or unreadable on disk."""
|
|
@@ -20,6 +20,7 @@ from ocr_toolkit.common.redaction import redact_sensitive
|
|
|
20
20
|
from ocr_toolkit.ocr_result import (
|
|
21
21
|
MAX_TOOLKIT_MCP_USAGE_COUNT,
|
|
22
22
|
MAX_TOOLKIT_MCP_USAGE_SERVERS,
|
|
23
|
+
PUBLIC_REVIEW_TOOL_CALL_NAMES,
|
|
23
24
|
SUPPORTED_TOOLKIT_RESULT_SCHEMA_VERSIONS,
|
|
24
25
|
TOOLKIT_MCP_SERVER_NAME_RE,
|
|
25
26
|
)
|
|
@@ -45,8 +46,6 @@ from ocr_toolkit.posting.settings import (
|
|
|
45
46
|
MAX_REVIEWER_GUIDE_LABEL_CHARS,
|
|
46
47
|
MAX_REVIEWER_GUIDE_LOCATION_CHARS,
|
|
47
48
|
MAX_REVIEWER_GUIDE_TEXT_CHARS,
|
|
48
|
-
MAX_TOOL_CALL_NAME_CHARS,
|
|
49
|
-
MAX_TOOL_CALL_SUMMARY_TOOLS,
|
|
50
49
|
SUGGESTION_HEADER,
|
|
51
50
|
post_badges,
|
|
52
51
|
post_emoji,
|
|
@@ -374,32 +373,25 @@ def nonnegative_int(value: Any) -> int | None:
|
|
|
374
373
|
return None
|
|
375
374
|
|
|
376
375
|
|
|
377
|
-
def truncate_tool_call_name(name: str) -> str:
|
|
378
|
-
"""Return a compact tool name for one-line MR summaries."""
|
|
379
|
-
|
|
380
|
-
if len(name) <= MAX_TOOL_CALL_NAME_CHARS:
|
|
381
|
-
return name
|
|
382
|
-
|
|
383
|
-
return name[: MAX_TOOL_CALL_NAME_CHARS - 3].rstrip() + "..."
|
|
384
|
-
|
|
385
|
-
|
|
386
376
|
def tool_call_name(value: Any) -> str:
|
|
387
|
-
"""Extract
|
|
377
|
+
"""Extract one closed public tool name from common OCR call shapes."""
|
|
388
378
|
|
|
389
379
|
if isinstance(value, str):
|
|
390
|
-
|
|
380
|
+
name = clean_text(value)
|
|
381
|
+
return name if name in PUBLIC_REVIEW_TOOL_CALL_NAMES else ""
|
|
391
382
|
|
|
392
383
|
if not isinstance(value, dict):
|
|
393
384
|
return ""
|
|
394
385
|
|
|
395
386
|
for key in ("name", "tool", "tool_name"):
|
|
396
387
|
name = clean_text(value.get(key))
|
|
397
|
-
if name:
|
|
388
|
+
if name in PUBLIC_REVIEW_TOOL_CALL_NAMES:
|
|
398
389
|
return name
|
|
399
390
|
|
|
400
391
|
function_value = value.get("function")
|
|
401
392
|
if isinstance(function_value, dict):
|
|
402
|
-
|
|
393
|
+
name = clean_text(function_value.get("name"))
|
|
394
|
+
return name if name in PUBLIC_REVIEW_TOOL_CALL_NAMES else ""
|
|
403
395
|
|
|
404
396
|
return ""
|
|
405
397
|
|
|
@@ -407,14 +399,17 @@ def tool_call_name(value: Any) -> str:
|
|
|
407
399
|
def tool_call_counts_from_items(
|
|
408
400
|
items: list[Any],
|
|
409
401
|
) -> tuple[int | None, list[tuple[str, int]]]:
|
|
410
|
-
"""Summarize a list-style OCR
|
|
402
|
+
"""Summarize admitted calls from a legacy list-style OCR payload."""
|
|
411
403
|
|
|
412
404
|
counts: dict[str, int] = {}
|
|
413
405
|
for item in items:
|
|
414
406
|
name = tool_call_name(item)
|
|
415
407
|
if not name:
|
|
416
408
|
continue
|
|
417
|
-
|
|
409
|
+
count = counts.get(name, 0) + 1
|
|
410
|
+
if count > MAX_TOOLKIT_MCP_USAGE_COUNT:
|
|
411
|
+
return None, []
|
|
412
|
+
counts[name] = count
|
|
418
413
|
|
|
419
414
|
total = sum(counts.values())
|
|
420
415
|
if total == 0 and items:
|
|
@@ -424,51 +419,52 @@ def tool_call_counts_from_items(
|
|
|
424
419
|
|
|
425
420
|
|
|
426
421
|
def format_tool_calls_summary(tool_calls: Any) -> str:
|
|
427
|
-
"""Return one bounded MR
|
|
422
|
+
"""Return one bounded MR line for admitted non-zero OCR tool counts."""
|
|
428
423
|
|
|
429
424
|
entries: list[tuple[str, int]]
|
|
430
425
|
total: int | None
|
|
431
|
-
|
|
432
|
-
if scalar_total is not None:
|
|
433
|
-
total = scalar_total
|
|
434
|
-
entries = []
|
|
435
|
-
elif isinstance(tool_calls, list):
|
|
426
|
+
if isinstance(tool_calls, list):
|
|
436
427
|
total, entries = tool_call_counts_from_items(tool_calls)
|
|
437
428
|
elif isinstance(tool_calls, dict):
|
|
438
429
|
by_tool_value = tool_calls.get("by_tool")
|
|
439
430
|
entries = []
|
|
440
|
-
|
|
441
|
-
valid_by_tool_count = False
|
|
431
|
+
admitted_total = 0
|
|
442
432
|
|
|
443
433
|
if isinstance(by_tool_value, dict):
|
|
444
434
|
for raw_name, raw_count in by_tool_value.items():
|
|
445
|
-
|
|
446
|
-
if count is None:
|
|
435
|
+
if not isinstance(raw_name, str) or raw_name not in PUBLIC_REVIEW_TOOL_CALL_NAMES:
|
|
447
436
|
continue
|
|
448
|
-
|
|
449
|
-
|
|
437
|
+
if (
|
|
438
|
+
not isinstance(raw_count, int)
|
|
439
|
+
or isinstance(raw_count, bool)
|
|
440
|
+
or not 0 < raw_count <= MAX_TOOLKIT_MCP_USAGE_COUNT
|
|
441
|
+
):
|
|
450
442
|
continue
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
443
|
+
admitted_total += raw_count
|
|
444
|
+
if admitted_total > MAX_TOOLKIT_MCP_USAGE_COUNT:
|
|
445
|
+
return ""
|
|
446
|
+
entries.append((raw_name, raw_count))
|
|
455
447
|
|
|
456
448
|
calls_value = tool_calls.get("calls")
|
|
457
|
-
if
|
|
458
|
-
list_total = None
|
|
459
|
-
elif isinstance(calls_value, list):
|
|
449
|
+
if not by_tool_value and isinstance(calls_value, list):
|
|
460
450
|
list_total, entries = tool_call_counts_from_items(calls_value)
|
|
461
451
|
else:
|
|
462
452
|
list_total = None
|
|
463
453
|
|
|
464
|
-
total
|
|
465
|
-
|
|
466
|
-
if
|
|
467
|
-
|
|
468
|
-
|
|
454
|
+
if "total" in tool_calls:
|
|
455
|
+
raw_total = tool_calls["total"]
|
|
456
|
+
if (
|
|
457
|
+
not isinstance(raw_total, int)
|
|
458
|
+
or isinstance(raw_total, bool)
|
|
459
|
+
or not 0 < raw_total <= MAX_TOOLKIT_MCP_USAGE_COUNT
|
|
460
|
+
):
|
|
461
|
+
return ""
|
|
462
|
+
total = raw_total
|
|
463
|
+
else:
|
|
464
|
+
if list_total is not None:
|
|
469
465
|
total = list_total
|
|
470
|
-
elif
|
|
471
|
-
total =
|
|
466
|
+
elif entries:
|
|
467
|
+
total = admitted_total
|
|
472
468
|
else:
|
|
473
469
|
return ""
|
|
474
470
|
else:
|
|
@@ -476,21 +472,14 @@ def format_tool_calls_summary(tool_calls: Any) -> str:
|
|
|
476
472
|
|
|
477
473
|
if total is None:
|
|
478
474
|
return ""
|
|
479
|
-
if total == 0:
|
|
475
|
+
if total == 0 or not entries:
|
|
476
|
+
return ""
|
|
477
|
+
if sum(count for _name, count in entries) > total:
|
|
480
478
|
return ""
|
|
481
479
|
|
|
482
480
|
line = f"- all OCR tool calls: {total} total"
|
|
483
|
-
if not entries:
|
|
484
|
-
return line
|
|
485
|
-
|
|
486
481
|
entries.sort(key=lambda item: (-item[1], item[0]))
|
|
487
|
-
|
|
488
|
-
detail_parts = [
|
|
489
|
-
f"{inline_code(truncate_tool_call_name(name))}: {count}" for name, count in shown_entries
|
|
490
|
-
]
|
|
491
|
-
omitted_entries = len(entries) - len(shown_entries)
|
|
492
|
-
if omitted_entries > 0:
|
|
493
|
-
detail_parts.append(f"+{omitted_entries} more")
|
|
482
|
+
detail_parts = [f"{inline_code(name)}: {count}" for name, count in entries]
|
|
494
483
|
|
|
495
484
|
return f"{line} ({', '.join(detail_parts)})"
|
|
496
485
|
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/review_runner.py
RENAMED
|
@@ -75,6 +75,7 @@ from ocr_toolkit.evidence.review_context import (
|
|
|
75
75
|
from ocr_toolkit.evidence.store import EvidenceStore, EvidenceStoreError
|
|
76
76
|
from ocr_toolkit.ocr_result import (
|
|
77
77
|
MAX_TOOLKIT_MCP_USAGE_COUNT,
|
|
78
|
+
PUBLIC_REVIEW_TOOL_CALL_NAMES,
|
|
78
79
|
TOOLKIT_RESULT_KEY,
|
|
79
80
|
TOOLKIT_RESULT_SCHEMA_VERSION,
|
|
80
81
|
OcrResultMalformed,
|
|
@@ -117,6 +118,10 @@ BACKGROUND_SOFT_WARNING_RE = re.compile(
|
|
|
117
118
|
r"\[ocr\] --background-file content is ([0-9]{1,12}) characters, exceeding the "
|
|
118
119
|
r"recommended ([0-9]{1,12}) \(continuing but review quality might be impacted\)\n?\Z"
|
|
119
120
|
)
|
|
121
|
+
MAX_TOOLS_NORMALIZATION_RE = re.compile(
|
|
122
|
+
r"\[ocr\] --max-tools ([0-9]{1,12}) is below minimum ([0-9]{1,12}), "
|
|
123
|
+
r"using ([0-9]{1,12})\n?\Z"
|
|
124
|
+
)
|
|
120
125
|
BACKGROUND_HARD_CHARACTER_RE = re.compile(
|
|
121
126
|
r"Error: background content is ([0-9]{1,12}) characters, exceeding the hard limit of "
|
|
122
127
|
r"([0-9]{1,12}) \(aborting\)\n?\Z"
|
|
@@ -149,9 +154,10 @@ class ReviewRunnerError(Exception):
|
|
|
149
154
|
|
|
150
155
|
@dataclass(frozen=True, slots=True)
|
|
151
156
|
class BackgroundQualification:
|
|
152
|
-
"""Carry
|
|
157
|
+
"""Carry closed toolkit-authored projections of installed OCR diagnostics."""
|
|
153
158
|
|
|
154
159
|
warning: str | None = None
|
|
160
|
+
operator_notices: tuple[str, ...] = ()
|
|
155
161
|
|
|
156
162
|
|
|
157
163
|
class BackgroundQualificationRejected(ReviewRunnerError):
|
|
@@ -593,22 +599,6 @@ def _publication_sinks(payload: dict[str, object]) -> list[object]:
|
|
|
593
599
|
warnings = payload.get("warnings")
|
|
594
600
|
if warnings is not None:
|
|
595
601
|
sinks.append(warnings)
|
|
596
|
-
tool_calls = payload.get("tool_calls")
|
|
597
|
-
if isinstance(tool_calls, list):
|
|
598
|
-
for item in tool_calls:
|
|
599
|
-
if not isinstance(item, dict):
|
|
600
|
-
continue
|
|
601
|
-
sinks.extend(item.get(key) for key in ("name", "tool", "tool_name") if key in item)
|
|
602
|
-
function = item.get("function")
|
|
603
|
-
if isinstance(function, dict) and "name" in function:
|
|
604
|
-
sinks.append(function.get("name"))
|
|
605
|
-
elif isinstance(tool_calls, dict):
|
|
606
|
-
by_tool = tool_calls.get("by_tool")
|
|
607
|
-
if isinstance(by_tool, dict):
|
|
608
|
-
sinks.extend(by_tool)
|
|
609
|
-
calls = tool_calls.get("calls")
|
|
610
|
-
if isinstance(calls, list):
|
|
611
|
-
sinks.extend(_publication_sinks({"tool_calls": calls}))
|
|
612
602
|
manifest = payload.get("manifest")
|
|
613
603
|
coverage = manifest.get("coverage") if isinstance(manifest, dict) else None
|
|
614
604
|
failed = coverage.get("failed") if isinstance(coverage, dict) else None
|
|
@@ -633,23 +623,6 @@ def _is_publication_sink_path(path: tuple[object, ...]) -> bool:
|
|
|
633
623
|
and path[2] in QUARANTINE_COMMENT_FIELDS
|
|
634
624
|
):
|
|
635
625
|
return True
|
|
636
|
-
if len(path) == 3 and path[:2] == ("tool_calls", "by_tool"):
|
|
637
|
-
return True
|
|
638
|
-
if (
|
|
639
|
-
len(path) == 4
|
|
640
|
-
and path[0] == "tool_calls"
|
|
641
|
-
and isinstance(path[1], int)
|
|
642
|
-
and path[2] == "function"
|
|
643
|
-
and path[3] == "name"
|
|
644
|
-
):
|
|
645
|
-
return True
|
|
646
|
-
if (
|
|
647
|
-
len(path) == 3
|
|
648
|
-
and path[0] == "tool_calls"
|
|
649
|
-
and isinstance(path[1], int)
|
|
650
|
-
and path[2] in {"name", "tool", "tool_name"}
|
|
651
|
-
):
|
|
652
|
-
return True
|
|
653
626
|
return bool(
|
|
654
627
|
len(path) >= 5
|
|
655
628
|
and path[:3] == ("manifest", "coverage", "failed")
|
|
@@ -658,6 +631,16 @@ def _is_publication_sink_path(path: tuple[object, ...]) -> bool:
|
|
|
658
631
|
)
|
|
659
632
|
|
|
660
633
|
|
|
634
|
+
def _is_static_public_tool_key_path(path: tuple[object, ...]) -> bool:
|
|
635
|
+
"""Return whether a map key is one compile-time public tool label."""
|
|
636
|
+
|
|
637
|
+
return bool(
|
|
638
|
+
len(path) == 3
|
|
639
|
+
and path[:2] == ("tool_calls", "by_tool")
|
|
640
|
+
and path[2] in PUBLIC_REVIEW_TOOL_CALL_NAMES
|
|
641
|
+
)
|
|
642
|
+
|
|
643
|
+
|
|
661
644
|
def _sanitize_nonpublication_fields(
|
|
662
645
|
payload: dict[str, object], *, budgets: TextBudgets, matcher: ForbiddenMatcher
|
|
663
646
|
) -> tuple[dict[str, object], Counter[str], int]:
|
|
@@ -679,7 +662,9 @@ def _sanitize_nonpublication_fields(
|
|
|
679
662
|
child_path = (*path, key)
|
|
680
663
|
if isinstance(source, dict):
|
|
681
664
|
assert isinstance(key, str)
|
|
682
|
-
if not _is_publication_sink_path(
|
|
665
|
+
if not _is_publication_sink_path(
|
|
666
|
+
child_path
|
|
667
|
+
) and not _is_static_public_tool_key_path(child_path):
|
|
683
668
|
checked_key = check_text(
|
|
684
669
|
key,
|
|
685
670
|
budgets=budgets,
|
|
@@ -783,6 +768,7 @@ def _closed_tool_calls(value: object, *, allowed_tools: frozenset[str]) -> dict[
|
|
|
783
768
|
tool: count
|
|
784
769
|
for tool, count in by_tool.items()
|
|
785
770
|
if tool in allowed_tools
|
|
771
|
+
and tool in PUBLIC_REVIEW_TOOL_CALL_NAMES
|
|
786
772
|
and isinstance(count, int)
|
|
787
773
|
and not isinstance(count, bool)
|
|
788
774
|
and 0 < count <= MAX_TOOLKIT_MCP_USAGE_COUNT
|
|
@@ -809,17 +795,9 @@ def _canonical_result_projection(payload: dict[str, object]) -> bytes:
|
|
|
809
795
|
else comment
|
|
810
796
|
for comment in comments
|
|
811
797
|
]
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
total = tool_calls.get("total")
|
|
816
|
-
by_tool = tool_calls.get("by_tool")
|
|
817
|
-
projected_tool_calls = {
|
|
818
|
-
"total": total,
|
|
819
|
-
"by_tool": (dict(sorted(by_tool.items())) if isinstance(by_tool, dict) else by_tool),
|
|
820
|
-
}
|
|
821
|
-
else:
|
|
822
|
-
projected_tool_calls = tool_calls
|
|
798
|
+
projected_tool_calls = _closed_tool_calls(
|
|
799
|
+
payload.get("tool_calls"), allowed_tools=PUBLIC_REVIEW_TOOL_CALL_NAMES
|
|
800
|
+
)
|
|
823
801
|
projection = {
|
|
824
802
|
"outcome": {
|
|
825
803
|
"status": outcome.status,
|
|
@@ -953,9 +931,7 @@ def _finalize_ocr_result(
|
|
|
953
931
|
filtered = False
|
|
954
932
|
publication: dict[str, object] = {"state": "passed"}
|
|
955
933
|
usage: dict[str, int] = {}
|
|
956
|
-
allowed_tools =
|
|
957
|
-
tool for capability in composition.capabilities for tool in capability.tools
|
|
958
|
-
)
|
|
934
|
+
allowed_tools = PUBLIC_REVIEW_TOOL_CALL_NAMES
|
|
959
935
|
|
|
960
936
|
def finalize(payload: dict[str, object]) -> dict[str, object]:
|
|
961
937
|
nonlocal filtered, publication, usage
|
|
@@ -1160,7 +1136,7 @@ def _read_bounded_artifact(path: Path, *, limit: int, label: str) -> bytes:
|
|
|
1160
1136
|
|
|
1161
1137
|
|
|
1162
1138
|
def _parse_background_preview(*, returncode: int, stderr: bytes) -> BackgroundQualification:
|
|
1163
|
-
"""Classify only exact installed-OCR
|
|
1139
|
+
"""Classify only exact installed-OCR preview diagnostics consumed by the toolkit."""
|
|
1164
1140
|
|
|
1165
1141
|
try:
|
|
1166
1142
|
text = stderr.decode("utf-8", errors="strict")
|
|
@@ -1170,21 +1146,41 @@ def _parse_background_preview(*, returncode: int, stderr: bytes) -> BackgroundQu
|
|
|
1170
1146
|
soft_matches = [
|
|
1171
1147
|
match for line in lines if (match := BACKGROUND_SOFT_WARNING_RE.fullmatch(line)) is not None
|
|
1172
1148
|
]
|
|
1149
|
+
max_tools_matches = [
|
|
1150
|
+
match for line in lines if (match := MAX_TOOLS_NORMALIZATION_RE.fullmatch(line)) is not None
|
|
1151
|
+
]
|
|
1173
1152
|
hard_character = BACKGROUND_HARD_CHARACTER_RE.fullmatch(text)
|
|
1174
1153
|
hard_file = BACKGROUND_HARD_FILE_RE.fullmatch(text)
|
|
1175
1154
|
if returncode == 0:
|
|
1176
|
-
if
|
|
1155
|
+
if (
|
|
1156
|
+
len(soft_matches) + len(max_tools_matches) != len(lines)
|
|
1157
|
+
or len(soft_matches) > 1
|
|
1158
|
+
or len(max_tools_matches) > 1
|
|
1159
|
+
):
|
|
1177
1160
|
raise ReviewRunnerError("OCR background preview returned ambiguous diagnostics")
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
warning=(
|
|
1161
|
+
warning: str | None = None
|
|
1162
|
+
if soft_matches:
|
|
1163
|
+
actual, limit = (int(value) for value in soft_matches[0].groups())
|
|
1164
|
+
if not 0 < limit < actual:
|
|
1165
|
+
raise ReviewRunnerError("OCR background preview returned invalid thresholds")
|
|
1166
|
+
warning = (
|
|
1185
1167
|
f"Installed OCR reported a {actual}-character review background above its "
|
|
1186
1168
|
f"recommended {limit}-character threshold; review continued."
|
|
1187
1169
|
)
|
|
1170
|
+
operator_notices: tuple[str, ...] = ()
|
|
1171
|
+
if max_tools_matches:
|
|
1172
|
+
requested, minimum, normalized = (int(value) for value in max_tools_matches[0].groups())
|
|
1173
|
+
if not 0 < requested < minimum or normalized != minimum:
|
|
1174
|
+
raise ReviewRunnerError("OCR background preview returned invalid tool limits")
|
|
1175
|
+
operator_notices = (
|
|
1176
|
+
"Installed OCR reported "
|
|
1177
|
+
f"--max-tools {requested} below its CLI minimum and a normalization target "
|
|
1178
|
+
f"of {normalized}; the installed OCR template remains authoritative for the "
|
|
1179
|
+
"effective tool-call limit.",
|
|
1180
|
+
)
|
|
1181
|
+
return BackgroundQualification(
|
|
1182
|
+
warning=warning,
|
|
1183
|
+
operator_notices=operator_notices,
|
|
1188
1184
|
)
|
|
1189
1185
|
if hard_character is not None:
|
|
1190
1186
|
actual, limit = (int(value) for value in hard_character.groups())
|
|
@@ -1304,6 +1300,8 @@ def _run_background_qualified_review(
|
|
|
1304
1300
|
f"OCR background qualification warning: {qualification.warning}",
|
|
1305
1301
|
file=sys.stderr,
|
|
1306
1302
|
)
|
|
1303
|
+
for notice in qualification.operator_notices:
|
|
1304
|
+
print(f"OCR argument qualification notice: {notice}", file=sys.stderr)
|
|
1307
1305
|
return (
|
|
1308
1306
|
run_review(
|
|
1309
1307
|
result_path,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/common/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/common/git.py
RENAMED
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/common/language.py
RENAMED
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/common/markdown.py
RENAMED
|
File without changes
|
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/config_writer.py
RENAMED
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/configure.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/context/broker.py
RENAMED
|
File without changes
|
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/context/dlp.py
RENAMED
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/context/mcp.py
RENAMED
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/context/policy.py
RENAMED
|
File without changes
|
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/context/store.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/mcp.py
RENAMED
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/evidence/model.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/mcp_config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/posting/gitlab.py
RENAMED
|
File without changes
|
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/posting/markers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/posting/result.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/pre_execution.py
RENAMED
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/preflight.py
RENAMED
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/provider_config.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/result_contract.py
RENAMED
|
File without changes
|
{open_code_review_toolkit-0.8.2 → open_code_review_toolkit-0.8.3}/src/ocr_toolkit/result_usage.py
RENAMED
|
File without changes
|