codejury 0.14.0__tar.gz → 0.14.2__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.
Files changed (82) hide show
  1. {codejury-0.14.0 → codejury-0.14.2}/PKG-INFO +1 -1
  2. {codejury-0.14.0 → codejury-0.14.2}/codejury/cli.py +10 -83
  3. {codejury-0.14.0 → codejury-0.14.2}/codejury/diff/debate.py +1 -1
  4. {codejury-0.14.0 → codejury-0.14.2}/codejury/diff/engine.py +1 -1
  5. codejury-0.14.2/codejury/diff/runner.py +85 -0
  6. {codejury-0.14.0/codejury/fullreview → codejury-0.14.2/codejury/repo}/scaffold.py +8 -7
  7. {codejury-0.14.0 → codejury-0.14.2}/codejury.egg-info/PKG-INFO +1 -1
  8. {codejury-0.14.0 → codejury-0.14.2}/codejury.egg-info/SOURCES.txt +8 -9
  9. {codejury-0.14.0 → codejury-0.14.2}/pyproject.toml +1 -1
  10. {codejury-0.14.0 → codejury-0.14.2}/tests/test_cli_audit.py +8 -7
  11. {codejury-0.14.0 → codejury-0.14.2}/tests/test_json_parse.py +1 -1
  12. {codejury-0.14.0 → codejury-0.14.2}/tests/test_repo_model.py +1 -1
  13. codejury-0.14.0/tests/test_full_review_scaffold.py → codejury-0.14.2/tests/test_repo_scaffold.py +1 -1
  14. codejury-0.14.0/tests/test_diff_report.py → codejury-0.14.2/tests/test_report.py +1 -1
  15. codejury-0.14.0/codejury/analysis/__init__.py +0 -8
  16. codejury-0.14.0/codejury/infrastructure/__init__.py +0 -4
  17. {codejury-0.14.0 → codejury-0.14.2}/LICENSE +0 -0
  18. {codejury-0.14.0 → codejury-0.14.2}/README.md +0 -0
  19. {codejury-0.14.0 → codejury-0.14.2}/codejury/__init__.py +0 -0
  20. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/agent/full-review.md +0 -0
  21. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/agent/security-review-memory.md +0 -0
  22. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/entrypoints.yaml +0 -0
  23. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/SKILL.md +0 -0
  24. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/business-logic.md +0 -0
  25. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/code-injection.md +0 -0
  26. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/command-injection.md +0 -0
  27. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/cross-site-request-forgery.md +0 -0
  28. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/cross-site-scripting.md +0 -0
  29. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/hardcoded-secrets.md +0 -0
  30. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/http-response-splitting.md +0 -0
  31. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/improper-authentication.md +0 -0
  32. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/information-exposure.md +0 -0
  33. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/insecure-cryptography.md +0 -0
  34. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/insecure-deserialization.md +0 -0
  35. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/insecure-direct-object-reference.md +0 -0
  36. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/insecure-transport.md +0 -0
  37. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/jwt-validation.md +0 -0
  38. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/mass-assignment.md +0 -0
  39. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/missing-authorization.md +0 -0
  40. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/open-redirect.md +0 -0
  41. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/path-traversal.md +0 -0
  42. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/race-condition.md +0 -0
  43. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/replay-attack.md +0 -0
  44. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/server-side-request-forgery.md +0 -0
  45. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/server-side-template-injection.md +0 -0
  46. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/session-fixation.md +0 -0
  47. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/sql-injection.md +0 -0
  48. {codejury-0.14.0 → codejury-0.14.2}/codejury/data/rules/xml-external-entity.md +0 -0
  49. {codejury-0.14.0 → codejury-0.14.2}/codejury/diff/__init__.py +0 -0
  50. {codejury-0.14.0 → codejury-0.14.2}/codejury/diff/debate_prompts.py +0 -0
  51. {codejury-0.14.0 → codejury-0.14.2}/codejury/diff/findings_filter.py +0 -0
  52. {codejury-0.14.0 → codejury-0.14.2}/codejury/diff/prompts.py +0 -0
  53. {codejury-0.14.0 → codejury-0.14.2}/codejury/diff/rules.py +0 -0
  54. {codejury-0.14.0 → codejury-0.14.2}/codejury/domain/__init__.py +0 -0
  55. {codejury-0.14.0 → codejury-0.14.2}/codejury/domain/finding.py +0 -0
  56. {codejury-0.14.0/codejury/infrastructure → codejury-0.14.2/codejury}/json_parse.py +0 -0
  57. {codejury-0.14.0 → codejury-0.14.2}/codejury/providers/__init__.py +0 -0
  58. {codejury-0.14.0 → codejury-0.14.2}/codejury/providers/anthropic.py +0 -0
  59. {codejury-0.14.0 → codejury-0.14.2}/codejury/providers/base.py +0 -0
  60. {codejury-0.14.0 → codejury-0.14.2}/codejury/providers/factory.py +0 -0
  61. {codejury-0.14.0 → codejury-0.14.2}/codejury/providers/litellm.py +0 -0
  62. {codejury-0.14.0 → codejury-0.14.2}/codejury/providers/mock.py +0 -0
  63. {codejury-0.14.0 → codejury-0.14.2}/codejury/providers/openai.py +0 -0
  64. {codejury-0.14.0 → codejury-0.14.2}/codejury/providers/openai_format.py +0 -0
  65. {codejury-0.14.0 → codejury-0.14.2}/codejury/providers/retry.py +0 -0
  66. {codejury-0.14.0/codejury/fullreview → codejury-0.14.2/codejury/repo}/__init__.py +0 -0
  67. /codejury-0.14.0/codejury/analysis/repo_model.py → /codejury-0.14.2/codejury/repo/model.py +0 -0
  68. {codejury-0.14.0/codejury/diff → codejury-0.14.2/codejury}/report.py +0 -0
  69. {codejury-0.14.0 → codejury-0.14.2}/codejury/resources.py +0 -0
  70. {codejury-0.14.0 → codejury-0.14.2}/codejury.egg-info/dependency_links.txt +0 -0
  71. {codejury-0.14.0 → codejury-0.14.2}/codejury.egg-info/entry_points.txt +0 -0
  72. {codejury-0.14.0 → codejury-0.14.2}/codejury.egg-info/requires.txt +0 -0
  73. {codejury-0.14.0 → codejury-0.14.2}/codejury.egg-info/top_level.txt +0 -0
  74. {codejury-0.14.0 → codejury-0.14.2}/setup.cfg +0 -0
  75. {codejury-0.14.0 → codejury-0.14.2}/tests/test_anthropic_provider.py +0 -0
  76. {codejury-0.14.0 → codejury-0.14.2}/tests/test_diff_debate.py +0 -0
  77. {codejury-0.14.0 → codejury-0.14.2}/tests/test_diff_engine.py +0 -0
  78. {codejury-0.14.0 → codejury-0.14.2}/tests/test_litellm_provider.py +0 -0
  79. {codejury-0.14.0 → codejury-0.14.2}/tests/test_openai_format.py +0 -0
  80. {codejury-0.14.0 → codejury-0.14.2}/tests/test_openai_provider.py +0 -0
  81. {codejury-0.14.0 → codejury-0.14.2}/tests/test_retry_provider.py +0 -0
  82. {codejury-0.14.0 → codejury-0.14.2}/tests/test_rules.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codejury
3
- Version: 0.14.0
3
+ Version: 0.14.2
4
4
  Summary: AI code security review: an adversarial diff-audit engine and an agent-driven whole-repo review methodology, with security knowledge as rich rules
5
5
  Author: AISecLabs
6
6
  License-Expression: MIT
@@ -1,14 +1,15 @@
1
- """codejury CLI.
1
+ """codejury CLI: thin argument parsing and dispatch.
2
2
 
3
- Two entry points matched to their nature:
3
+ Two paths matched to their nature:
4
4
 
5
- - ``audit`` runs the coded diff engine over a unified diff: a single balanced
6
- call (standard) or the adversarial Finder/Challenger/Judge pass.
7
- - ``full-review`` scaffolds a workspace and prints the methodology for an
5
+ - ``review diff`` runs the coded diff engine over a unified diff: a single
6
+ balanced call (standard) or the adversarial Finder/Challenger/Judge pass.
7
+ - ``review repo`` scaffolds a workspace and prints the methodology for an
8
8
  interactive agent to run a whole-repo review (it does not run an LLM pipeline,
9
9
  which a single call cannot do for a whole codebase).
10
10
 
11
- ``dry-run`` exercises the diff engine with a mock provider and no API key.
11
+ ``review diff --dry-run`` exercises the engine with a mock provider and no key.
12
+ The audit orchestration itself lives in ``codejury.diff.runner``.
12
13
  """
13
14
 
14
15
  from __future__ import annotations
@@ -17,20 +18,9 @@ import argparse
17
18
  import subprocess
18
19
  import sys
19
20
 
20
- import dataclasses
21
-
22
21
  from codejury import __version__
23
- from codejury.diff.debate import AdversarialAuditRunner
24
- from codejury.diff.engine import AuditRunner
25
- from codejury.diff.findings_filter import FindingsFilter
26
- from codejury.diff.report import gate, render
27
- from codejury.diff.rules import allowed_categories, normalize_category
28
- from codejury.domain.finding import Finding
29
-
30
- # A diff larger than this is audited file-by-file so a big PR does not overflow
31
- # the model's context and silently truncate the reply.
32
- _MAX_DIFF_CHARS = 60_000
33
- from codejury.fullreview.scaffold import scaffold
22
+ from codejury.report import gate, render
23
+ from codejury.diff.runner import audit_diff
34
24
  from codejury.providers.factory import (
35
25
  DEFAULT_API_BASE,
36
26
  DEFAULT_API_KEY,
@@ -42,75 +32,12 @@ from codejury.providers.factory import (
42
32
  make_provider,
43
33
  )
44
34
  from codejury.providers.mock import MockProvider
35
+ from codejury.repo.scaffold import scaffold
45
36
 
46
37
  _FORMATS = ("text", "markdown", "json", "sarif")
47
38
  _FAIL_ON = ("critical", "high", "medium", "low")
48
39
 
49
40
 
50
- def _split_diff_by_file(diff: str) -> list[str]:
51
- """Split a unified diff into one diff per file (`diff --git ...` boundaries)."""
52
- chunks: list[str] = []
53
- cur: list[str] = []
54
- for line in diff.splitlines(keepends=True):
55
- if line.startswith("diff --git ") and cur:
56
- chunks.append("".join(cur))
57
- cur = []
58
- cur.append(line)
59
- if cur:
60
- chunks.append("".join(cur))
61
- return chunks or ([diff] if diff.strip() else [])
62
-
63
-
64
- def _dedup_findings(findings: list[Finding]) -> list[Finding]:
65
- seen: set = set()
66
- out: list[Finding] = []
67
- for f in findings:
68
- k = (f.file, f.line, f.category, f.description)
69
- if k not in seen:
70
- seen.add(k)
71
- out.append(f)
72
- return out
73
-
74
-
75
- def audit_diff(
76
- diff: str,
77
- *,
78
- provider,
79
- model: str,
80
- mode: str = "standard",
81
- max_rounds: int = 3,
82
- filter_findings: bool = True,
83
- finder_model: str | None = None,
84
- challenger_model: str | None = None,
85
- judge_model: str | None = None,
86
- exclude_paths: tuple[str, ...] = (),
87
- ) -> tuple[list[Finding], list[tuple[Finding, str]]]:
88
- """Audit a diff and return (kept findings, dropped (finding, reason)).
89
-
90
- A diff over the size budget is audited one file at a time so it does not
91
- overflow the context. Finding categories are normalized to the rule-id set.
92
- ``exclude_paths`` are operator-supplied path substrings to drop."""
93
- def _run_one(d: str) -> list[Finding]:
94
- if mode == "adversarial":
95
- return AdversarialAuditRunner(
96
- provider=provider, model=model,
97
- finder_model=finder_model, challenger_model=challenger_model, judge_model=judge_model,
98
- ).run(d, max_rounds=max_rounds).findings
99
- return AuditRunner(provider=provider, model=model).run(d)
100
-
101
- if len(diff) > _MAX_DIFF_CHARS:
102
- chunks = _split_diff_by_file(diff)
103
- findings = _dedup_findings([f for c in chunks for f in _run_one(c)])
104
- else:
105
- findings = _run_one(diff)
106
-
107
- allowed = set(allowed_categories())
108
- findings = [dataclasses.replace(f, category=normalize_category(f.category, allowed)) for f in findings]
109
- if filter_findings:
110
- return FindingsFilter(exclude_paths=exclude_paths).filter(findings)
111
- return findings, []
112
-
113
-
114
41
  def _read_diff(args) -> str:
115
42
  if args.diff_file:
116
43
  with open(args.diff_file, encoding="utf-8") as f:
@@ -21,7 +21,7 @@ from codejury.diff.debate_prompts import (
21
21
  )
22
22
  from codejury.diff.rules import rules_for_diff
23
23
  from codejury.domain.finding import Finding, findings_from_list
24
- from codejury.infrastructure.json_parse import extract_json_object
24
+ from codejury.json_parse import extract_json_object
25
25
  from codejury.providers.base import Message, Provider
26
26
 
27
27
 
@@ -10,7 +10,7 @@ from __future__ import annotations
10
10
  from codejury.domain.finding import Finding, findings_from_list
11
11
  from codejury.diff.prompts import SYSTEM, standard_audit_prompt
12
12
  from codejury.diff.rules import rules_for_diff
13
- from codejury.infrastructure.json_parse import extract_json_object
13
+ from codejury.json_parse import extract_json_object
14
14
  from codejury.providers.base import Message, Provider
15
15
 
16
16
 
@@ -0,0 +1,85 @@
1
+ """Diff-audit orchestration: run a diff through the engine and clean the result.
2
+
3
+ The library entry point behind `review diff`. Picks the standard or adversarial
4
+ engine, audits a large diff one file at a time so a big PR does not overflow the
5
+ model context, normalizes finding categories onto the rule-id set, and applies
6
+ the false-positive filter. Kept out of the CLI so it can be called as a library.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import dataclasses
12
+
13
+ from codejury.diff.debate import AdversarialAuditRunner
14
+ from codejury.diff.engine import AuditRunner
15
+ from codejury.diff.findings_filter import FindingsFilter
16
+ from codejury.diff.rules import allowed_categories, normalize_category
17
+ from codejury.domain.finding import Finding
18
+
19
+ # A diff larger than this is audited file-by-file so a big PR does not overflow
20
+ # the model's context and silently truncate the reply.
21
+ _MAX_DIFF_CHARS = 60_000
22
+
23
+
24
+ def split_diff_by_file(diff: str) -> list[str]:
25
+ """Split a unified diff into one diff per file (`diff --git ...` boundaries)."""
26
+ chunks: list[str] = []
27
+ cur: list[str] = []
28
+ for line in diff.splitlines(keepends=True):
29
+ if line.startswith("diff --git ") and cur:
30
+ chunks.append("".join(cur))
31
+ cur = []
32
+ cur.append(line)
33
+ if cur:
34
+ chunks.append("".join(cur))
35
+ return chunks or ([diff] if diff.strip() else [])
36
+
37
+
38
+ def dedup_findings(findings: list[Finding]) -> list[Finding]:
39
+ seen: set = set()
40
+ out: list[Finding] = []
41
+ for f in findings:
42
+ k = (f.file, f.line, f.category, f.description)
43
+ if k not in seen:
44
+ seen.add(k)
45
+ out.append(f)
46
+ return out
47
+
48
+
49
+ def audit_diff(
50
+ diff: str,
51
+ *,
52
+ provider,
53
+ model: str,
54
+ mode: str = "standard",
55
+ max_rounds: int = 3,
56
+ filter_findings: bool = True,
57
+ finder_model: str | None = None,
58
+ challenger_model: str | None = None,
59
+ judge_model: str | None = None,
60
+ exclude_paths: tuple[str, ...] = (),
61
+ ) -> tuple[list[Finding], list[tuple[Finding, str]]]:
62
+ """Audit a diff and return (kept findings, dropped (finding, reason)).
63
+
64
+ A diff over the size budget is audited one file at a time so it does not
65
+ overflow the context. Finding categories are normalized to the rule-id set.
66
+ ``exclude_paths`` are operator-supplied path substrings to drop."""
67
+ def _run_one(d: str) -> list[Finding]:
68
+ if mode == "adversarial":
69
+ return AdversarialAuditRunner(
70
+ provider=provider, model=model,
71
+ finder_model=finder_model, challenger_model=challenger_model, judge_model=judge_model,
72
+ ).run(d, max_rounds=max_rounds).findings
73
+ return AuditRunner(provider=provider, model=model).run(d)
74
+
75
+ if len(diff) > _MAX_DIFF_CHARS:
76
+ chunks = split_diff_by_file(diff)
77
+ findings = dedup_findings([f for c in chunks for f in _run_one(c)])
78
+ else:
79
+ findings = _run_one(diff)
80
+
81
+ allowed = set(allowed_categories())
82
+ findings = [dataclasses.replace(f, category=normalize_category(f.category, allowed)) for f in findings]
83
+ if filter_findings:
84
+ return FindingsFilter(exclude_paths=exclude_paths).filter(findings)
85
+ return findings, []
@@ -1,10 +1,11 @@
1
- """Full-review scaffold: set up the agent's workspace, do not run a pipeline.
1
+ """Whole-repo review scaffold: set up the agent's workspace, do not run a pipeline.
2
2
 
3
- Whole-repo review is too large for a single LLM call, so codejury does not run it
4
- as a pipeline. Instead it scaffolds a workspace for an interactive agent (Claude
5
- Code, Codex) and hands over the methodology: it creates the api/issues/analysis
6
- directories, copies the review-memory template, seeds the API inventory from a
7
- deterministic RepoModel scan, and returns the methodology text to print.
3
+ The `review repo` path. Whole-repo review is too large for a single LLM call, so
4
+ codejury does not run it as a pipeline. Instead it scaffolds a workspace for an
5
+ interactive agent (Claude Code, Codex) and hands over the methodology: it creates
6
+ the api/issues/analysis directories, copies the review-memory template, seeds the
7
+ API inventory from a deterministic RepoModel scan, and returns the methodology
8
+ text to print.
8
9
  """
9
10
 
10
11
  from __future__ import annotations
@@ -12,7 +13,7 @@ from __future__ import annotations
12
13
  from dataclasses import dataclass, field
13
14
  from pathlib import Path
14
15
 
15
- from codejury.analysis.repo_model import build_repo_model_from_dir
16
+ from codejury.repo.model import build_repo_model_from_dir
16
17
  from codejury.resources import AGENT_DIR
17
18
 
18
19
  _METHODOLOGY = AGENT_DIR / "full-review.md"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codejury
3
- Version: 0.14.0
3
+ Version: 0.14.2
4
4
  Summary: AI code security review: an adversarial diff-audit engine and an agent-driven whole-repo review methodology, with security knowledge as rich rules
5
5
  Author: AISecLabs
6
6
  License-Expression: MIT
@@ -3,6 +3,8 @@ README.md
3
3
  pyproject.toml
4
4
  codejury/__init__.py
5
5
  codejury/cli.py
6
+ codejury/json_parse.py
7
+ codejury/report.py
6
8
  codejury/resources.py
7
9
  codejury.egg-info/PKG-INFO
8
10
  codejury.egg-info/SOURCES.txt
@@ -10,8 +12,6 @@ codejury.egg-info/dependency_links.txt
10
12
  codejury.egg-info/entry_points.txt
11
13
  codejury.egg-info/requires.txt
12
14
  codejury.egg-info/top_level.txt
13
- codejury/analysis/__init__.py
14
- codejury/analysis/repo_model.py
15
15
  codejury/data/entrypoints.yaml
16
16
  codejury/data/agent/full-review.md
17
17
  codejury/data/agent/security-review-memory.md
@@ -47,14 +47,10 @@ codejury/diff/debate_prompts.py
47
47
  codejury/diff/engine.py
48
48
  codejury/diff/findings_filter.py
49
49
  codejury/diff/prompts.py
50
- codejury/diff/report.py
51
50
  codejury/diff/rules.py
51
+ codejury/diff/runner.py
52
52
  codejury/domain/__init__.py
53
53
  codejury/domain/finding.py
54
- codejury/fullreview/__init__.py
55
- codejury/fullreview/scaffold.py
56
- codejury/infrastructure/__init__.py
57
- codejury/infrastructure/json_parse.py
58
54
  codejury/providers/__init__.py
59
55
  codejury/providers/anthropic.py
60
56
  codejury/providers/base.py
@@ -64,16 +60,19 @@ codejury/providers/mock.py
64
60
  codejury/providers/openai.py
65
61
  codejury/providers/openai_format.py
66
62
  codejury/providers/retry.py
63
+ codejury/repo/__init__.py
64
+ codejury/repo/model.py
65
+ codejury/repo/scaffold.py
67
66
  tests/test_anthropic_provider.py
68
67
  tests/test_cli_audit.py
69
68
  tests/test_diff_debate.py
70
69
  tests/test_diff_engine.py
71
- tests/test_diff_report.py
72
- tests/test_full_review_scaffold.py
73
70
  tests/test_json_parse.py
74
71
  tests/test_litellm_provider.py
75
72
  tests/test_openai_format.py
76
73
  tests/test_openai_provider.py
77
74
  tests/test_repo_model.py
75
+ tests/test_repo_scaffold.py
76
+ tests/test_report.py
78
77
  tests/test_retry_provider.py
79
78
  tests/test_rules.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "codejury"
3
- version = "0.14.0"
3
+ version = "0.14.2"
4
4
  description = "AI code security review: an adversarial diff-audit engine and an agent-driven whole-repo review methodology, with security knowledge as rich rules"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -1,4 +1,4 @@
1
- """CLI audit_diff helpers: large-diff chunking and finding de-duplication.
1
+ """Diff-audit orchestration (codejury.diff.runner) plus the thin CLI surface.
2
2
 
3
3
  A diff over the size budget is split per file and audited one file at a time so a
4
4
  big PR does not overflow the model context and silently truncate the reply; the
@@ -7,7 +7,8 @@ per-file findings are then de-duplicated.
7
7
 
8
8
  import pytest
9
9
 
10
- from codejury.cli import _dedup_findings, _split_diff_by_file, audit_diff, main
10
+ from codejury.cli import main
11
+ from codejury.diff.runner import audit_diff, dedup_findings, split_diff_by_file
11
12
  from codejury.domain.finding import Finding
12
13
  from codejury.providers.mock import MockProvider
13
14
 
@@ -16,14 +17,14 @@ _FILE_B = "diff --git a/b.py b/b.py\n@@ -0,0 +1 @@\n+y = 2\n"
16
17
 
17
18
 
18
19
  def test_split_diff_by_file():
19
- chunks = _split_diff_by_file(_FILE_A + _FILE_B)
20
+ chunks = split_diff_by_file(_FILE_A + _FILE_B)
20
21
  assert chunks == [_FILE_A, _FILE_B]
21
22
 
22
23
 
23
24
  def test_split_diff_empty_and_unbounded():
24
- assert _split_diff_by_file("") == []
25
+ assert split_diff_by_file("") == []
25
26
  # a fragment with no `diff --git` boundary is returned as one chunk
26
- assert _split_diff_by_file("just text\n") == ["just text\n"]
27
+ assert split_diff_by_file("just text\n") == ["just text\n"]
27
28
 
28
29
 
29
30
  def test_dedup_findings_collapses_identical():
@@ -31,12 +32,12 @@ def test_dedup_findings_collapses_identical():
31
32
  description="d", confidence=0.9)
32
33
  g = Finding(file="a.py", line=2, severity="HIGH", category="sql-injection",
33
34
  description="d", confidence=0.9)
34
- assert _dedup_findings([f, f, g]) == [f, g]
35
+ assert dedup_findings([f, f, g]) == [f, g]
35
36
 
36
37
 
37
38
  def test_large_diff_is_audited_per_file(monkeypatch):
38
39
  # force the chunking path on a small diff
39
- monkeypatch.setattr("codejury.cli._MAX_DIFF_CHARS", 1)
40
+ monkeypatch.setattr("codejury.diff.runner._MAX_DIFF_CHARS", 1)
40
41
  resp = ('{"findings": [{"file": "a.py", "line": 1, "severity": "HIGH", '
41
42
  '"category": "sql_injection", "description": "x", "confidence": 0.9}]}')
42
43
  provider = MockProvider(default=resp)
@@ -1,6 +1,6 @@
1
1
  import pytest
2
2
 
3
- from codejury.infrastructure.json_parse import extract_json_object
3
+ from codejury.json_parse import extract_json_object
4
4
 
5
5
 
6
6
  def test_direct_object():
@@ -1,6 +1,6 @@
1
1
  """P6-01: the RepoModel entrypoint detection is deterministic and data-driven."""
2
2
 
3
- from codejury.analysis.repo_model import (
3
+ from codejury.repo.model import (
4
4
  Entrypoint,
5
5
  build_repo_model,
6
6
  build_repo_model_from_dir,
@@ -2,7 +2,7 @@
2
2
  analysis + memory + seeded entrypoints) and returns the methodology. It does not
3
3
  run an LLM pipeline."""
4
4
 
5
- from codejury.fullreview.scaffold import scaffold
5
+ from codejury.repo.scaffold import scaffold
6
6
 
7
7
  APP = '''
8
8
  from flask import Flask
@@ -5,7 +5,7 @@ from pathlib import Path
5
5
 
6
6
  import jsonschema
7
7
 
8
- from codejury.diff.report import (
8
+ from codejury.report import (
9
9
  gate,
10
10
  render,
11
11
  severity_breakdown,
@@ -1,8 +0,0 @@
1
- """Static analysis for provenance (P1).
2
-
3
- The code-graph / data-flow engine that gives the verifier provenance: whether a
4
- value reaching a sink is attacker-controlled, sanitized, or a trusted constant.
5
- It targets the taint precision floor that single-file LLM review cannot reach,
6
- see ROADMAP P1. Python AST based, currently intra-procedural plus a one-hop
7
- cross-file caller resolution, not yet a full code graph.
8
- """
@@ -1,4 +0,0 @@
1
- """codejury.infrastructure: Layer 1 cross-cutting utilities, json parsing and the verdict cache.
2
-
3
- Lowest layer: depends on nothing else in codejury, used by the layers above.
4
- """
File without changes
File without changes
File without changes
File without changes