codejury 0.20.0__tar.gz → 0.21.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.
Files changed (102) hide show
  1. {codejury-0.20.0 → codejury-0.21.0}/PKG-INFO +11 -12
  2. {codejury-0.20.0 → codejury-0.21.0}/README.md +10 -11
  3. {codejury-0.20.0 → codejury-0.21.0}/codejury/cli.py +30 -22
  4. codejury-0.20.0/codejury/data/commands/codejury-review.md → codejury-0.21.0/codejury/data/commands/codejury-review-repo.md +1 -1
  5. {codejury-0.20.0/codejury → codejury-0.21.0/codejury/review}/diff/debate.py +2 -2
  6. {codejury-0.20.0/codejury → codejury-0.21.0/codejury/review}/diff/debate_prompts.py +1 -1
  7. {codejury-0.20.0/codejury → codejury-0.21.0/codejury/review}/diff/engine.py +2 -2
  8. {codejury-0.20.0/codejury → codejury-0.21.0/codejury/review}/diff/prompts.py +1 -1
  9. {codejury-0.20.0/codejury → codejury-0.21.0/codejury/review}/diff/runner.py +4 -4
  10. codejury-0.21.0/codejury/review/repo/__init__.py +0 -0
  11. {codejury-0.20.0/codejury → codejury-0.21.0/codejury/review}/repo/scaffold.py +1 -1
  12. {codejury-0.20.0 → codejury-0.21.0}/codejury.egg-info/PKG-INFO +11 -12
  13. {codejury-0.20.0 → codejury-0.21.0}/codejury.egg-info/SOURCES.txt +13 -12
  14. {codejury-0.20.0 → codejury-0.21.0}/pyproject.toml +1 -1
  15. {codejury-0.20.0 → codejury-0.21.0}/tests/test_cli_audit.py +8 -8
  16. {codejury-0.20.0 → codejury-0.21.0}/tests/test_diff_debate.py +2 -2
  17. {codejury-0.20.0 → codejury-0.21.0}/tests/test_diff_engine.py +6 -6
  18. {codejury-0.20.0 → codejury-0.21.0}/tests/test_repo_model.py +1 -1
  19. {codejury-0.20.0 → codejury-0.21.0}/tests/test_repo_scaffold.py +1 -1
  20. {codejury-0.20.0 → codejury-0.21.0}/tests/test_vulnerabilities.py +1 -1
  21. {codejury-0.20.0 → codejury-0.21.0}/LICENSE +0 -0
  22. {codejury-0.20.0 → codejury-0.21.0}/codejury/__init__.py +0 -0
  23. {codejury-0.20.0 → codejury-0.21.0}/codejury/__main__.py +0 -0
  24. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/detection.yaml +0 -0
  25. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/frameworks/go/echo.md +0 -0
  26. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/frameworks/go/gin.md +0 -0
  27. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/frameworks/javascript/express.md +0 -0
  28. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/frameworks/javascript/nestjs.md +0 -0
  29. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/frameworks/python/celery.md +0 -0
  30. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/frameworks/python/django.md +0 -0
  31. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/frameworks/python/fastapi.md +0 -0
  32. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/frameworks/python/flask.md +0 -0
  33. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/languages/go.md +0 -0
  34. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/languages/javascript.md +0 -0
  35. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/languages/python.md +0 -0
  36. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/languages/typescript.md +0 -0
  37. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/methodologies/repo-review.md +0 -0
  38. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/methodologies/security-review-memory.md +0 -0
  39. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/protocols/oauth.md +0 -0
  40. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/SKILL.md +0 -0
  41. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/business-logic.md +0 -0
  42. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/code-injection.md +0 -0
  43. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/command-injection.md +0 -0
  44. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/cross-site-request-forgery.md +0 -0
  45. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/cross-site-scripting.md +0 -0
  46. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/hardcoded-secrets.md +0 -0
  47. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/http-response-splitting.md +0 -0
  48. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/improper-authentication.md +0 -0
  49. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/information-exposure.md +0 -0
  50. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/insecure-cryptography.md +0 -0
  51. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/insecure-deserialization.md +0 -0
  52. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/insecure-direct-object-reference.md +0 -0
  53. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/insecure-transport.md +0 -0
  54. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/jwt-validation.md +0 -0
  55. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/mass-assignment.md +0 -0
  56. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/missing-authorization.md +0 -0
  57. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/open-redirect.md +0 -0
  58. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/path-traversal.md +0 -0
  59. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/race-condition.md +0 -0
  60. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/replay-attack.md +0 -0
  61. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/server-side-request-forgery.md +0 -0
  62. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/server-side-template-injection.md +0 -0
  63. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/session-fixation.md +0 -0
  64. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/sql-injection.md +0 -0
  65. {codejury-0.20.0 → codejury-0.21.0}/codejury/data/vulnerabilities/xml-external-entity.md +0 -0
  66. {codejury-0.20.0 → codejury-0.21.0}/codejury/detection.py +0 -0
  67. {codejury-0.20.0 → codejury-0.21.0}/codejury/domain/__init__.py +0 -0
  68. {codejury-0.20.0 → codejury-0.21.0}/codejury/domain/finding.py +0 -0
  69. {codejury-0.20.0 → codejury-0.21.0}/codejury/guides.py +0 -0
  70. {codejury-0.20.0 → codejury-0.21.0}/codejury/json_parse.py +0 -0
  71. {codejury-0.20.0 → codejury-0.21.0}/codejury/mddoc.py +0 -0
  72. {codejury-0.20.0 → codejury-0.21.0}/codejury/providers/__init__.py +0 -0
  73. {codejury-0.20.0 → codejury-0.21.0}/codejury/providers/anthropic.py +0 -0
  74. {codejury-0.20.0 → codejury-0.21.0}/codejury/providers/base.py +0 -0
  75. {codejury-0.20.0 → codejury-0.21.0}/codejury/providers/factory.py +0 -0
  76. {codejury-0.20.0 → codejury-0.21.0}/codejury/providers/litellm.py +0 -0
  77. {codejury-0.20.0 → codejury-0.21.0}/codejury/providers/mock.py +0 -0
  78. {codejury-0.20.0 → codejury-0.21.0}/codejury/providers/openai.py +0 -0
  79. {codejury-0.20.0 → codejury-0.21.0}/codejury/providers/openai_format.py +0 -0
  80. {codejury-0.20.0 → codejury-0.21.0}/codejury/providers/retry.py +0 -0
  81. {codejury-0.20.0 → codejury-0.21.0}/codejury/report.py +0 -0
  82. {codejury-0.20.0 → codejury-0.21.0}/codejury/resources.py +0 -0
  83. {codejury-0.20.0/codejury/diff → codejury-0.21.0/codejury/review}/__init__.py +0 -0
  84. {codejury-0.20.0/codejury/repo → codejury-0.21.0/codejury/review/diff}/__init__.py +0 -0
  85. {codejury-0.20.0/codejury → codejury-0.21.0/codejury/review}/diff/findings_filter.py +0 -0
  86. {codejury-0.20.0/codejury → codejury-0.21.0/codejury/review}/diff/vulnerabilities.py +0 -0
  87. {codejury-0.20.0/codejury → codejury-0.21.0/codejury/review}/repo/model.py +0 -0
  88. {codejury-0.20.0 → codejury-0.21.0}/codejury.egg-info/dependency_links.txt +0 -0
  89. {codejury-0.20.0 → codejury-0.21.0}/codejury.egg-info/entry_points.txt +0 -0
  90. {codejury-0.20.0 → codejury-0.21.0}/codejury.egg-info/requires.txt +0 -0
  91. {codejury-0.20.0 → codejury-0.21.0}/codejury.egg-info/top_level.txt +0 -0
  92. {codejury-0.20.0 → codejury-0.21.0}/setup.cfg +0 -0
  93. {codejury-0.20.0 → codejury-0.21.0}/tests/test_anthropic_provider.py +0 -0
  94. {codejury-0.20.0 → codejury-0.21.0}/tests/test_detection.py +0 -0
  95. {codejury-0.20.0 → codejury-0.21.0}/tests/test_guides.py +0 -0
  96. {codejury-0.20.0 → codejury-0.21.0}/tests/test_json_parse.py +0 -0
  97. {codejury-0.20.0 → codejury-0.21.0}/tests/test_litellm_provider.py +0 -0
  98. {codejury-0.20.0 → codejury-0.21.0}/tests/test_mddoc.py +0 -0
  99. {codejury-0.20.0 → codejury-0.21.0}/tests/test_openai_format.py +0 -0
  100. {codejury-0.20.0 → codejury-0.21.0}/tests/test_openai_provider.py +0 -0
  101. {codejury-0.20.0 → codejury-0.21.0}/tests/test_report.py +0 -0
  102. {codejury-0.20.0 → codejury-0.21.0}/tests/test_retry_provider.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codejury
3
- Version: 0.20.0
3
+ Version: 0.21.0
4
4
  Summary: AI code security review for diffs and whole repositories.
5
5
  Author: AISecLabs
6
6
  License-Expression: MIT
@@ -67,34 +67,34 @@ codejury install-slash-command # Claude Code, ~/.claude/commands/
67
67
  codejury install-slash-command --agent codex # Codex, ~/.codex/prompts/
68
68
  ```
69
69
 
70
- `install-slash-command` copies the `/codejury-review` command into the agent's
70
+ `install-slash-command` copies the `/codejury-review-repo` command into the agent's
71
71
  command directory. The command body is the same for every agent, only the
72
72
  directory differs, so pass `--dir` for any other agent. The repo review itself is
73
- agent neutral, so even without the command you can run `codejury review` and
73
+ agent neutral, so even without the command you can run `codejury review repo` and
74
74
  tell any agent to follow the methodology it writes.
75
75
 
76
76
  ## Diff Review
77
77
 
78
78
  ```bash
79
79
  # audit a diff file
80
- codejury diff --diff-file changes.diff
80
+ codejury review diff --file changes.diff
81
81
 
82
82
  # audit a git range in a repo
83
- codejury diff --repo /path/to/app --git-range origin/main...HEAD
83
+ codejury review diff --repo /path/to/app --git-range origin/main...HEAD
84
84
 
85
85
  # from stdin
86
- git diff HEAD~1 | codejury diff
86
+ git diff HEAD~1 | codejury review diff
87
87
 
88
88
  # adversarial mode, more recall on subtle flaws, about 3x the cost
89
- codejury diff --diff-file changes.diff --mode adversarial
89
+ codejury review diff --file changes.diff --mode adversarial
90
90
 
91
91
  # CI gate and SARIF
92
- codejury diff --diff-file changes.diff --format sarif --fail-on high
92
+ codejury review diff --file changes.diff --format sarif --fail-on high
93
93
  ```
94
94
 
95
95
  Configure a backend with `--provider`, `--model`, `--api-key`, `--api-base`, or
96
96
  the `CODEJURY_API_KEY`, `CODEJURY_MODEL`, and `CODEJURY_API_BASE` environment
97
- variables. `codejury diff --dry-run` exercises the engine with a mock
97
+ variables. `codejury review diff --dry-run` exercises the engine with a mock
98
98
  provider and no key, and falls back to a built in demo diff when you pass none.
99
99
 
100
100
  ### Choosing a Model and Mode
@@ -134,7 +134,7 @@ run, because a whole repository needs many rounds of reading, cross-file tracing
134
134
  and PoC work that an agent does, not a single call.
135
135
 
136
136
  ```bash
137
- codejury review /path/to/your/repo
137
+ codejury review repo /path/to/your/repo
138
138
  ```
139
139
 
140
140
  This detects the stack, seeds the entrypoint inventory and the downstream trace
@@ -153,7 +153,7 @@ security-review-memory.md
153
153
  Then run it with an interactive agent. In Claude Code or Codex:
154
154
 
155
155
  ```
156
- /codejury-review /path/to/your/repo
156
+ /codejury-review-repo /path/to/your/repo
157
157
  ```
158
158
 
159
159
  Any agent works, the slash command is just a shortcut. Without it, tell the agent
@@ -194,4 +194,3 @@ change.
194
194
  entrypoint markers, and downstream logic layers.
195
195
  - A protocol such as OAuth: `codejury/data/protocols/<name>.md`, detected by
196
196
  language neutral content tokens.
197
- ```
@@ -36,34 +36,34 @@ codejury install-slash-command # Claude Code, ~/.claude/commands/
36
36
  codejury install-slash-command --agent codex # Codex, ~/.codex/prompts/
37
37
  ```
38
38
 
39
- `install-slash-command` copies the `/codejury-review` command into the agent's
39
+ `install-slash-command` copies the `/codejury-review-repo` command into the agent's
40
40
  command directory. The command body is the same for every agent, only the
41
41
  directory differs, so pass `--dir` for any other agent. The repo review itself is
42
- agent neutral, so even without the command you can run `codejury review` and
42
+ agent neutral, so even without the command you can run `codejury review repo` and
43
43
  tell any agent to follow the methodology it writes.
44
44
 
45
45
  ## Diff Review
46
46
 
47
47
  ```bash
48
48
  # audit a diff file
49
- codejury diff --diff-file changes.diff
49
+ codejury review diff --file changes.diff
50
50
 
51
51
  # audit a git range in a repo
52
- codejury diff --repo /path/to/app --git-range origin/main...HEAD
52
+ codejury review diff --repo /path/to/app --git-range origin/main...HEAD
53
53
 
54
54
  # from stdin
55
- git diff HEAD~1 | codejury diff
55
+ git diff HEAD~1 | codejury review diff
56
56
 
57
57
  # adversarial mode, more recall on subtle flaws, about 3x the cost
58
- codejury diff --diff-file changes.diff --mode adversarial
58
+ codejury review diff --file changes.diff --mode adversarial
59
59
 
60
60
  # CI gate and SARIF
61
- codejury diff --diff-file changes.diff --format sarif --fail-on high
61
+ codejury review diff --file changes.diff --format sarif --fail-on high
62
62
  ```
63
63
 
64
64
  Configure a backend with `--provider`, `--model`, `--api-key`, `--api-base`, or
65
65
  the `CODEJURY_API_KEY`, `CODEJURY_MODEL`, and `CODEJURY_API_BASE` environment
66
- variables. `codejury diff --dry-run` exercises the engine with a mock
66
+ variables. `codejury review diff --dry-run` exercises the engine with a mock
67
67
  provider and no key, and falls back to a built in demo diff when you pass none.
68
68
 
69
69
  ### Choosing a Model and Mode
@@ -103,7 +103,7 @@ run, because a whole repository needs many rounds of reading, cross-file tracing
103
103
  and PoC work that an agent does, not a single call.
104
104
 
105
105
  ```bash
106
- codejury review /path/to/your/repo
106
+ codejury review repo /path/to/your/repo
107
107
  ```
108
108
 
109
109
  This detects the stack, seeds the entrypoint inventory and the downstream trace
@@ -122,7 +122,7 @@ security-review-memory.md
122
122
  Then run it with an interactive agent. In Claude Code or Codex:
123
123
 
124
124
  ```
125
- /codejury-review /path/to/your/repo
125
+ /codejury-review-repo /path/to/your/repo
126
126
  ```
127
127
 
128
128
  Any agent works, the slash command is just a shortcut. Without it, tell the agent
@@ -163,4 +163,3 @@ change.
163
163
  entrypoint markers, and downstream logic layers.
164
164
  - A protocol such as OAuth: `codejury/data/protocols/<name>.md`, detected by
165
165
  language neutral content tokens.
166
- ```
@@ -2,14 +2,14 @@
2
2
 
3
3
  Two paths matched to their nature:
4
4
 
5
- - ``diff`` runs the coded diff engine over a unified diff: a single balanced call
6
- (standard) or the adversarial Finder/Challenger/Judge pass.
7
- - ``review <dir>`` 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 <dir>`` 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
- ``diff --dry-run`` exercises the engine with a mock provider and no key.
12
- The audit orchestration itself lives in ``codejury.diff.runner``.
11
+ ``review diff --dry-run`` exercises the engine with a mock provider and no key.
12
+ The audit orchestration itself lives in ``codejury.review.diff.runner``.
13
13
  """
14
14
 
15
15
  from __future__ import annotations
@@ -21,7 +21,7 @@ from pathlib import Path
21
21
 
22
22
  from codejury import __version__
23
23
  from codejury.report import gate, render
24
- from codejury.diff.runner import audit_diff
24
+ from codejury.review.diff.runner import audit_diff
25
25
  from codejury.providers.factory import (
26
26
  DEFAULT_API_BASE,
27
27
  DEFAULT_API_KEY,
@@ -33,15 +33,15 @@ from codejury.providers.factory import (
33
33
  make_provider,
34
34
  )
35
35
  from codejury.providers.mock import MockProvider
36
- from codejury.repo.scaffold import scaffold
36
+ from codejury.review.repo.scaffold import scaffold
37
37
 
38
38
  _FORMATS = ("text", "markdown", "json", "sarif")
39
39
  _FAIL_ON = ("critical", "high", "medium", "low")
40
40
 
41
41
 
42
42
  def _read_diff(args) -> str:
43
- if args.diff_file:
44
- with open(args.diff_file, encoding="utf-8") as f:
43
+ if args.file:
44
+ with open(args.file, encoding="utf-8") as f:
45
45
  return f.read()
46
46
  if args.git_range:
47
47
  return subprocess.run(
@@ -66,7 +66,7 @@ _MOCK_REPLY = (
66
66
 
67
67
  def _add_audit_args(p) -> None:
68
68
  """The diff-audit flags for `review diff`."""
69
- p.add_argument("--diff-file", default=None, help="unified diff file (default: read stdin)")
69
+ p.add_argument("--file", default=None, help="unified diff file (default: read stdin)")
70
70
  p.add_argument("--repo", default=None, help="repo path for --git-range")
71
71
  p.add_argument("--git-range", default=None, help="git range to diff, e.g. origin/main...HEAD")
72
72
  p.add_argument("--dry-run", action="store_true",
@@ -93,14 +93,15 @@ def main(argv: list[str] | None = None) -> int:
93
93
  parser.add_argument("--version", action="version", version=f"codejury {__version__}")
94
94
  sub = parser.add_subparsers(dest="command")
95
95
 
96
- _add_audit_args(sub.add_parser("diff", help="audit a unified diff (the coded engine)"))
97
-
98
- review = sub.add_parser("review", help="scaffold a whole-repo review for an interactive agent")
99
- review.add_argument("directory", help="target repository to review")
100
- review.add_argument("--workspace", default="codejury-review", help="where to create the review workspace")
96
+ review = sub.add_parser("review", help="review code for security findings")
97
+ rsub = review.add_subparsers(dest="scope")
98
+ _add_audit_args(rsub.add_parser("diff", help="audit a unified diff (the coded engine)"))
99
+ repo = rsub.add_parser("repo", help="scaffold a whole-repo review for an interactive agent")
100
+ repo.add_argument("directory", help="target repository to review")
101
+ repo.add_argument("--workspace", default="codejury-review", help="where to create the review workspace")
101
102
 
102
103
  inst = sub.add_parser("install-slash-command",
103
- help="install the /codejury-review slash command for an agent")
104
+ help="install the /codejury-review-repo slash command for an agent")
104
105
  inst.add_argument("--agent", choices=("claude", "codex"), default="claude",
105
106
  help="which agent's command directory to install into")
106
107
  inst.add_argument("--dir", default=None, help="explicit target directory, overrides --agent")
@@ -115,12 +116,13 @@ def main(argv: list[str] | None = None) -> int:
115
116
 
116
117
 
117
118
  def _dispatch(args, parser) -> int:
118
- if args.command == "diff":
119
+ scope = getattr(args, "scope", None)
120
+ if args.command == "review" and scope == "diff":
119
121
  if args.dry_run:
120
122
  provider = MockProvider(default=_MOCK_REPLY)
121
123
  model = "mock"
122
124
  # zero-config smoke test: fall back to a built-in demo diff when none is supplied
123
- diff = _read_diff(args) if (args.diff_file or args.git_range) else _dry_run_diff()
125
+ diff = _read_diff(args) if (args.file or args.git_range) else _dry_run_diff()
124
126
  else:
125
127
  provider = make_provider(args.provider, api_key=args.api_key, api_base=args.api_base, retries=args.retries)
126
128
  model = args.model
@@ -134,7 +136,7 @@ def _dispatch(args, parser) -> int:
134
136
  print(render(args.fmt, kept))
135
137
  return 1 if gate(kept, args.fail_on) else 0
136
138
 
137
- if args.command == "review":
139
+ if args.command == "review" and scope == "repo":
138
140
  res = scaffold(args.directory, args.workspace)
139
141
  (Path(res.workspace) / "METHODOLOGY.md").write_text(res.methodology, encoding="utf-8")
140
142
  print(f"Workspace ready: {res.workspace}", file=sys.stderr)
@@ -146,7 +148,7 @@ def _dispatch(args, parser) -> int:
146
148
  print(
147
149
  "This command sets up the review, it does not find the issues itself. Next, have an "
148
150
  f"interactive agent follow {res.workspace}/METHODOLOGY.md to run the review, or use the "
149
- "/codejury-review command in Claude Code or Codex. Findings are written to "
151
+ "/codejury-review-repo command in Claude Code or Codex. Findings are written to "
150
152
  f"{res.workspace}/issues/."
151
153
  )
152
154
  return 0
@@ -160,13 +162,19 @@ def _dispatch(args, parser) -> int:
160
162
  }
161
163
  target_dir = Path(args.dir) if args.dir else agent_dirs[args.agent]
162
164
  target_dir.mkdir(parents=True, exist_ok=True)
163
- name = "codejury-review.md"
165
+ name = "codejury-review-repo.md"
164
166
  dst = target_dir / name
165
167
  dst.write_text((COMMANDS_DIR / name).read_text(encoding="utf-8"), encoding="utf-8")
166
168
  print(f"Installed slash command to {dst}")
167
- print("Run it in the agent with: /codejury-review <repository>")
169
+ print("Run it in the agent with: /codejury-review-repo <repository>")
168
170
  return 0
169
171
 
172
+ if args.command == "review": # no scope given
173
+ print("usage: codejury review {diff,repo} ...", file=sys.stderr)
174
+ print(" diff audit a unified diff for security findings", file=sys.stderr)
175
+ print(" repo scaffold a whole-repo review for an interactive agent", file=sys.stderr)
176
+ return 1
177
+
170
178
  parser.print_help()
171
179
  return 1
172
180
 
@@ -6,7 +6,7 @@ Run a codejury whole-repository security review of: $ARGUMENTS
6
6
  1. Scaffold the workspace:
7
7
 
8
8
  ```
9
- codejury review $ARGUMENTS --workspace /tmp/codejury-review
9
+ codejury review repo $ARGUMENTS --workspace /tmp/codejury-review
10
10
  ```
11
11
 
12
12
  If `codejury` is not on PATH it is a pip-installed console script, so activate
@@ -11,7 +11,7 @@ from __future__ import annotations
11
11
 
12
12
  from dataclasses import dataclass, field
13
13
 
14
- from codejury.diff.debate_prompts import (
14
+ from codejury.review.diff.debate_prompts import (
15
15
  CHALLENGER_SYSTEM,
16
16
  FINDER_SYSTEM,
17
17
  JUDGE_SYSTEM,
@@ -19,7 +19,7 @@ from codejury.diff.debate_prompts import (
19
19
  finder_prompt,
20
20
  judge_prompt,
21
21
  )
22
- from codejury.diff.vulnerabilities import vulnerabilities_for_diff
22
+ from codejury.review.diff.vulnerabilities import vulnerabilities_for_diff
23
23
  from codejury.domain.finding import Finding, findings_from_list
24
24
  from codejury.json_parse import extract_json_object
25
25
  from codejury.providers.base import Message, Provider
@@ -16,7 +16,7 @@ from __future__ import annotations
16
16
 
17
17
  import json
18
18
 
19
- from codejury.diff.prompts import DO_NOT_REPORT, FOCUS, category_block
19
+ from codejury.review.diff.prompts import DO_NOT_REPORT, FOCUS, category_block
20
20
 
21
21
  _FINDING_FIELDS = (
22
22
  '{"file": "path", "line": 0, "severity": "CRITICAL|HIGH|MEDIUM|LOW", '
@@ -10,8 +10,8 @@ from __future__ import annotations
10
10
  import re
11
11
 
12
12
  from codejury.domain.finding import Finding, findings_from_list
13
- from codejury.diff.prompts import SYSTEM, standard_audit_prompt
14
- from codejury.diff.vulnerabilities import vulnerabilities_for_diff
13
+ from codejury.review.diff.prompts import SYSTEM, standard_audit_prompt
14
+ from codejury.review.diff.vulnerabilities import vulnerabilities_for_diff
15
15
  from codejury.guides import select_guides
16
16
  from codejury.json_parse import extract_json_object
17
17
  from codejury.providers.base import Message, Provider
@@ -46,7 +46,7 @@ _JSON_SHAPE = (
46
46
 
47
47
  def category_block() -> str:
48
48
  """The closed category set the model must choose from, the vulnerability ids."""
49
- from codejury.diff.vulnerabilities import allowed_categories
49
+ from codejury.review.diff.vulnerabilities import allowed_categories
50
50
 
51
51
  cats = allowed_categories()
52
52
  return (
@@ -10,10 +10,10 @@ from __future__ import annotations
10
10
 
11
11
  import dataclasses
12
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.vulnerabilities import allowed_categories, normalize_category
13
+ from codejury.review.diff.debate import AdversarialAuditRunner
14
+ from codejury.review.diff.engine import AuditRunner
15
+ from codejury.review.diff.findings_filter import FindingsFilter
16
+ from codejury.review.diff.vulnerabilities import allowed_categories, normalize_category
17
17
  from codejury.domain.finding import Finding
18
18
 
19
19
  # A diff larger than this is audited file-by-file so a big PR does not overflow
File without changes
@@ -21,7 +21,7 @@ from codejury.guides import (
21
21
  logic_layer_globs,
22
22
  select_guides,
23
23
  )
24
- from codejury.repo.model import build_repo_model_from_dir, candidate_entrypoint_files, logic_layer_files
24
+ from codejury.review.repo.model import build_repo_model_from_dir, candidate_entrypoint_files, logic_layer_files
25
25
  from codejury.resources import METHODOLOGIES_DIR
26
26
 
27
27
  _METHODOLOGY = METHODOLOGIES_DIR / "repo-review.md"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codejury
3
- Version: 0.20.0
3
+ Version: 0.21.0
4
4
  Summary: AI code security review for diffs and whole repositories.
5
5
  Author: AISecLabs
6
6
  License-Expression: MIT
@@ -67,34 +67,34 @@ codejury install-slash-command # Claude Code, ~/.claude/commands/
67
67
  codejury install-slash-command --agent codex # Codex, ~/.codex/prompts/
68
68
  ```
69
69
 
70
- `install-slash-command` copies the `/codejury-review` command into the agent's
70
+ `install-slash-command` copies the `/codejury-review-repo` command into the agent's
71
71
  command directory. The command body is the same for every agent, only the
72
72
  directory differs, so pass `--dir` for any other agent. The repo review itself is
73
- agent neutral, so even without the command you can run `codejury review` and
73
+ agent neutral, so even without the command you can run `codejury review repo` and
74
74
  tell any agent to follow the methodology it writes.
75
75
 
76
76
  ## Diff Review
77
77
 
78
78
  ```bash
79
79
  # audit a diff file
80
- codejury diff --diff-file changes.diff
80
+ codejury review diff --file changes.diff
81
81
 
82
82
  # audit a git range in a repo
83
- codejury diff --repo /path/to/app --git-range origin/main...HEAD
83
+ codejury review diff --repo /path/to/app --git-range origin/main...HEAD
84
84
 
85
85
  # from stdin
86
- git diff HEAD~1 | codejury diff
86
+ git diff HEAD~1 | codejury review diff
87
87
 
88
88
  # adversarial mode, more recall on subtle flaws, about 3x the cost
89
- codejury diff --diff-file changes.diff --mode adversarial
89
+ codejury review diff --file changes.diff --mode adversarial
90
90
 
91
91
  # CI gate and SARIF
92
- codejury diff --diff-file changes.diff --format sarif --fail-on high
92
+ codejury review diff --file changes.diff --format sarif --fail-on high
93
93
  ```
94
94
 
95
95
  Configure a backend with `--provider`, `--model`, `--api-key`, `--api-base`, or
96
96
  the `CODEJURY_API_KEY`, `CODEJURY_MODEL`, and `CODEJURY_API_BASE` environment
97
- variables. `codejury diff --dry-run` exercises the engine with a mock
97
+ variables. `codejury review diff --dry-run` exercises the engine with a mock
98
98
  provider and no key, and falls back to a built in demo diff when you pass none.
99
99
 
100
100
  ### Choosing a Model and Mode
@@ -134,7 +134,7 @@ run, because a whole repository needs many rounds of reading, cross-file tracing
134
134
  and PoC work that an agent does, not a single call.
135
135
 
136
136
  ```bash
137
- codejury review /path/to/your/repo
137
+ codejury review repo /path/to/your/repo
138
138
  ```
139
139
 
140
140
  This detects the stack, seeds the entrypoint inventory and the downstream trace
@@ -153,7 +153,7 @@ security-review-memory.md
153
153
  Then run it with an interactive agent. In Claude Code or Codex:
154
154
 
155
155
  ```
156
- /codejury-review /path/to/your/repo
156
+ /codejury-review-repo /path/to/your/repo
157
157
  ```
158
158
 
159
159
  Any agent works, the slash command is just a shortcut. Without it, tell the agent
@@ -194,4 +194,3 @@ change.
194
194
  entrypoint markers, and downstream logic layers.
195
195
  - A protocol such as OAuth: `codejury/data/protocols/<name>.md`, detected by
196
196
  language neutral content tokens.
197
- ```
@@ -17,7 +17,7 @@ codejury.egg-info/entry_points.txt
17
17
  codejury.egg-info/requires.txt
18
18
  codejury.egg-info/top_level.txt
19
19
  codejury/data/detection.yaml
20
- codejury/data/commands/codejury-review.md
20
+ codejury/data/commands/codejury-review-repo.md
21
21
  codejury/data/frameworks/go/echo.md
22
22
  codejury/data/frameworks/go/gin.md
23
23
  codejury/data/frameworks/javascript/express.md
@@ -59,14 +59,6 @@ codejury/data/vulnerabilities/server-side-template-injection.md
59
59
  codejury/data/vulnerabilities/session-fixation.md
60
60
  codejury/data/vulnerabilities/sql-injection.md
61
61
  codejury/data/vulnerabilities/xml-external-entity.md
62
- codejury/diff/__init__.py
63
- codejury/diff/debate.py
64
- codejury/diff/debate_prompts.py
65
- codejury/diff/engine.py
66
- codejury/diff/findings_filter.py
67
- codejury/diff/prompts.py
68
- codejury/diff/runner.py
69
- codejury/diff/vulnerabilities.py
70
62
  codejury/domain/__init__.py
71
63
  codejury/domain/finding.py
72
64
  codejury/providers/__init__.py
@@ -78,9 +70,18 @@ codejury/providers/mock.py
78
70
  codejury/providers/openai.py
79
71
  codejury/providers/openai_format.py
80
72
  codejury/providers/retry.py
81
- codejury/repo/__init__.py
82
- codejury/repo/model.py
83
- codejury/repo/scaffold.py
73
+ codejury/review/__init__.py
74
+ codejury/review/diff/__init__.py
75
+ codejury/review/diff/debate.py
76
+ codejury/review/diff/debate_prompts.py
77
+ codejury/review/diff/engine.py
78
+ codejury/review/diff/findings_filter.py
79
+ codejury/review/diff/prompts.py
80
+ codejury/review/diff/runner.py
81
+ codejury/review/diff/vulnerabilities.py
82
+ codejury/review/repo/__init__.py
83
+ codejury/review/repo/model.py
84
+ codejury/review/repo/scaffold.py
84
85
  tests/test_anthropic_provider.py
85
86
  tests/test_cli_audit.py
86
87
  tests/test_detection.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "codejury"
3
- version = "0.20.0"
3
+ version = "0.21.0"
4
4
  description = "AI code security review for diffs and whole repositories."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -1,4 +1,4 @@
1
- """Diff-audit orchestration (codejury.diff.runner) plus the thin CLI surface.
1
+ """Diff-audit orchestration (codejury.review.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
@@ -8,7 +8,7 @@ per-file findings are then de-duplicated.
8
8
  import pytest
9
9
 
10
10
  from codejury.cli import main
11
- from codejury.diff.runner import audit_diff, dedup_findings, split_diff_by_file
11
+ from codejury.review.diff.runner import audit_diff, dedup_findings, split_diff_by_file
12
12
  from codejury.domain.finding import Finding
13
13
  from codejury.providers.mock import MockProvider
14
14
 
@@ -37,7 +37,7 @@ def test_dedup_findings_collapses_identical():
37
37
 
38
38
  def test_large_diff_is_audited_per_file(monkeypatch):
39
39
  # force the chunking path on a small diff
40
- monkeypatch.setattr("codejury.diff.runner._MAX_DIFF_CHARS", 1)
40
+ monkeypatch.setattr("codejury.review.diff.runner._MAX_DIFF_CHARS", 1)
41
41
  resp = ('{"findings": [{"file": "a.py", "line": 1, "severity": "HIGH", '
42
42
  '"category": "sql_injection", "description": "x", "confidence": 0.9}]}')
43
43
  provider = MockProvider(default=resp)
@@ -68,13 +68,13 @@ def test_version_flag_exits_zero(capsys):
68
68
 
69
69
  def test_review_diff_dry_run_is_zero_config(capsys):
70
70
  # no diff input, no key: the built-in demo diff runs through the mock provider
71
- rc = main(["diff", "--dry-run"])
71
+ rc = main(["review", "diff", "--dry-run"])
72
72
  assert rc == 0
73
73
  assert "sql-injection" in capsys.readouterr().out
74
74
 
75
75
 
76
76
  def test_review_diff_dry_run_respects_exclude(capsys):
77
- rc = main(["diff", "--dry-run", "--exclude", "app.py"])
77
+ rc = main(["review", "diff", "--dry-run", "--exclude", "app.py"])
78
78
  assert rc == 0
79
79
  assert "no findings" in capsys.readouterr().out
80
80
 
@@ -89,7 +89,7 @@ def test_review_repo_writes_methodology_to_workspace(tmp_path):
89
89
  # the agent can read it, alongside printing it
90
90
  repo = tmp_path / "svc"; repo.mkdir(); (repo / "app.py").write_text("x = 1\n")
91
91
  ws = tmp_path / "ws"
92
- rc = main(["review", str(repo), "--workspace", str(ws)])
92
+ rc = main(["review", "repo", str(repo), "--workspace", str(ws)])
93
93
  assert rc == 0
94
94
  assert (ws / "svc" / "METHODOLOGY.md").is_file()
95
95
 
@@ -104,5 +104,5 @@ def test_python_dash_m_codejury_runs():
104
104
  def test_install_slash_command_writes_the_file(tmp_path):
105
105
  rc = main(["install-slash-command", "--dir", str(tmp_path)])
106
106
  assert rc == 0
107
- f = tmp_path / "codejury-review.md"
108
- assert f.is_file() and "codejury review" in f.read_text()
107
+ f = tmp_path / "codejury-review-repo.md"
108
+ assert f.is_file() and "codejury review repo" in f.read_text()
@@ -3,8 +3,8 @@ a MockProvider whose responses are consumed in role order per round."""
3
3
 
4
4
  import json
5
5
 
6
- from codejury.diff.debate import AdversarialAuditRunner
7
- from codejury.diff.debate_prompts import challenger_prompt, finder_prompt, judge_prompt
6
+ from codejury.review.diff.debate import AdversarialAuditRunner
7
+ from codejury.review.diff.debate_prompts import challenger_prompt, finder_prompt, judge_prompt
8
8
  from codejury.providers.mock import MockProvider
9
9
 
10
10
  _DIFF = "+++ b/app.py\n@@ -0,0 +1 @@\n+cursor.execute('SELECT * FROM u WHERE n=' + name)\n"
@@ -3,9 +3,9 @@ false-positive filter. Deterministic with a MockProvider, no key."""
3
3
 
4
4
  import json
5
5
 
6
- from codejury.diff.engine import AuditRunner
7
- from codejury.diff.findings_filter import FindingsFilter
8
- from codejury.diff.prompts import standard_audit_prompt
6
+ from codejury.review.diff.engine import AuditRunner
7
+ from codejury.review.diff.findings_filter import FindingsFilter
8
+ from codejury.review.diff.prompts import standard_audit_prompt
9
9
  from codejury.domain.finding import Finding, finding_from_dict, findings_from_list
10
10
  from codejury.providers.mock import MockProvider
11
11
 
@@ -65,7 +65,7 @@ def test_engine_raises_on_unparseable_reply():
65
65
  # reported as a clean audit, it is a failure
66
66
  import pytest
67
67
 
68
- from codejury.diff.engine import AuditError
68
+ from codejury.review.diff.engine import AuditError
69
69
 
70
70
  with pytest.raises(AuditError):
71
71
  AuditRunner(provider=MockProvider(default="not json"), model="m").run(_DIFF)
@@ -77,7 +77,7 @@ def test_engine_raises_on_wrong_shape_json():
77
77
  # valid JSON but no `findings` key is a malformed reply, not a clean audit
78
78
  import pytest
79
79
 
80
- from codejury.diff.engine import AuditError
80
+ from codejury.review.diff.engine import AuditError
81
81
 
82
82
  for bad in ("{}", '{"result": "ok"}'):
83
83
  with pytest.raises(AuditError):
@@ -85,7 +85,7 @@ def test_engine_raises_on_wrong_shape_json():
85
85
 
86
86
 
87
87
  def test_guides_for_diff_selects_by_path_and_content():
88
- from codejury.diff.engine import guides_for_diff
88
+ from codejury.review.diff.engine import guides_for_diff
89
89
  diff = ("diff --git a/app/urls.py b/app/urls.py\n"
90
90
  "+from django.urls import path\n+urlpatterns = []\n")
91
91
  notes = guides_for_diff(diff)
@@ -1,7 +1,7 @@
1
1
  """RepoModel is a language-agnostic file map. Candidate entrypoint files are
2
2
  flagged by guide-declared globs, not by parsing code."""
3
3
 
4
- from codejury.repo.model import (
4
+ from codejury.review.repo.model import (
5
5
  build_repo_model,
6
6
  build_repo_model_from_dir,
7
7
  candidate_entrypoint_files,
@@ -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.repo.scaffold import scaffold
5
+ from codejury.review.repo.scaffold import scaffold
6
6
 
7
7
  APP = '''
8
8
  from flask import Flask
@@ -1,7 +1,7 @@
1
1
  """RW-3: the rich vulnerability-class library loads, and trigger-based selection
2
2
  picks the relevant classes for a diff to inject into the audit prompt."""
3
3
 
4
- from codejury.diff.vulnerabilities import (
4
+ from codejury.review.diff.vulnerabilities import (
5
5
  Vulnerability,
6
6
  allowed_categories,
7
7
  load_vulnerabilities,
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes