agent-code-guard 0.1.0__py3-none-any.whl

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 (40) hide show
  1. agent_code_guard/__init__.py +1 -0
  2. agent_code_guard/analysis/__init__.py +13 -0
  3. agent_code_guard/analysis/adapters.py +608 -0
  4. agent_code_guard/analysis/errors.py +13 -0
  5. agent_code_guard/analysis/facts.py +101 -0
  6. agent_code_guard/analysis/language_specs.py +82 -0
  7. agent_code_guard/analysis/pipeline.py +37 -0
  8. agent_code_guard/analysis/provider.py +45 -0
  9. agent_code_guard/analysis/regions.py +108 -0
  10. agent_code_guard/code_guard.py +236 -0
  11. agent_code_guard/config_validation.py +90 -0
  12. agent_code_guard/file_selection.py +228 -0
  13. agent_code_guard/guards/__init__.py +1 -0
  14. agent_code_guard/guards/callable_size.py +79 -0
  15. agent_code_guard/guards/complexity.py +94 -0
  16. agent_code_guard/guards/loc.py +235 -0
  17. agent_code_guard/guards/markdown_document_size.py +66 -0
  18. agent_code_guard/guards/markdown_section_size.py +66 -0
  19. agent_code_guard/guards/nesting.py +109 -0
  20. agent_code_guard/markdown/__init__.py +6 -0
  21. agent_code_guard/markdown/facts.py +27 -0
  22. agent_code_guard/markdown/scanner.py +109 -0
  23. agent_code_guard/path_matching.py +25 -0
  24. agent_code_guard/reporting.py +11 -0
  25. agent_code_guard/result_model.py +128 -0
  26. agent_code_guard/skill_distribution.py +96 -0
  27. agent_code_guard-0.1.0.data/data/share/agent-code-guard/skill/LICENSE.txt +21 -0
  28. agent_code_guard-0.1.0.data/data/share/agent-code-guard/skill/SKILL.md +138 -0
  29. agent_code_guard-0.1.0.data/data/share/agent-code-guard/skill/agents/openai.yaml +8 -0
  30. agent_code_guard-0.1.0.data/data/share/agent-code-guard/skill/references/callable-size-policy.md +39 -0
  31. agent_code_guard-0.1.0.data/data/share/agent-code-guard/skill/references/complexity-policy.md +39 -0
  32. agent_code_guard-0.1.0.data/data/share/agent-code-guard/skill/references/loc-policy.md +40 -0
  33. agent_code_guard-0.1.0.data/data/share/agent-code-guard/skill/references/markdown-size-policy.md +16 -0
  34. agent_code_guard-0.1.0.data/data/share/agent-code-guard/skill/references/nesting-policy.md +37 -0
  35. agent_code_guard-0.1.0.dist-info/METADATA +206 -0
  36. agent_code_guard-0.1.0.dist-info/RECORD +40 -0
  37. agent_code_guard-0.1.0.dist-info/WHEEL +5 -0
  38. agent_code_guard-0.1.0.dist-info/entry_points.txt +2 -0
  39. agent_code_guard-0.1.0.dist-info/licenses/LICENSE +21 -0
  40. agent_code_guard-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,128 @@
1
+ """Normalized results shared by Code Guard runners and guard modules."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import asdict, dataclass
6
+ from typing import Any
7
+
8
+
9
+ STATE_RANK = {"pass": 0, "review": 1, "fail": 2}
10
+
11
+
12
+ @dataclass(frozen=True)
13
+ class Finding:
14
+ path: str
15
+ state: str
16
+ native_status: str
17
+ counted_loc: int
18
+ warn_at: int
19
+ fail_at: int
20
+ override_index: int | None = None
21
+ reason: str | None = None
22
+
23
+ def to_json(self) -> dict[str, Any]:
24
+ data = asdict(self)
25
+ return {
26
+ "path": data["path"],
27
+ "state": data["state"],
28
+ "nativeStatus": data["native_status"],
29
+ "countedLoc": data["counted_loc"],
30
+ "warnAt": data["warn_at"],
31
+ "failAt": data["fail_at"],
32
+ "overrideIndex": data["override_index"],
33
+ "reason": data["reason"],
34
+ }
35
+
36
+
37
+ @dataclass(frozen=True)
38
+ class CallableFinding:
39
+ """Additive result shape proven by analyzer research; unused by LOC."""
40
+
41
+ path: str
42
+ callable: str
43
+ start_line: int
44
+ end_line: int
45
+ measured: int
46
+ state: str
47
+ thresholds: dict[str, int] | None = None
48
+ details: dict[str, Any] | None = None
49
+ embedded_language: str | None = None
50
+
51
+ def to_json(self) -> dict[str, Any]:
52
+ value = {
53
+ "path": self.path,
54
+ "callable": self.callable,
55
+ "range": {"startLine": self.start_line, "endLine": self.end_line},
56
+ "measured": self.measured,
57
+ "state": self.state,
58
+ "thresholds": self.thresholds,
59
+ }
60
+ if self.details is not None:
61
+ value["details"] = self.details
62
+ if self.embedded_language is not None:
63
+ value["embeddedLanguage"] = self.embedded_language
64
+ return value
65
+
66
+
67
+ @dataclass(frozen=True)
68
+ class MarkdownDocumentFinding:
69
+ path: str
70
+ measured: int
71
+ state: str
72
+ thresholds: dict[str, int]
73
+
74
+ def to_json(self) -> dict[str, Any]:
75
+ return {
76
+ "path": self.path,
77
+ "measured": self.measured,
78
+ "state": self.state,
79
+ "thresholds": self.thresholds,
80
+ }
81
+
82
+
83
+ @dataclass(frozen=True)
84
+ class MarkdownSectionFinding:
85
+ path: str
86
+ heading: str
87
+ level: int
88
+ start_line: int
89
+ end_line: int
90
+ measured: int
91
+ state: str
92
+ thresholds: dict[str, int]
93
+
94
+ def to_json(self) -> dict[str, Any]:
95
+ return {
96
+ "path": self.path,
97
+ "heading": self.heading,
98
+ "level": self.level,
99
+ "range": {"startLine": self.start_line, "endLine": self.end_line},
100
+ "measured": self.measured,
101
+ "state": self.state,
102
+ "thresholds": self.thresholds,
103
+ }
104
+
105
+
106
+ @dataclass(frozen=True)
107
+ class GuardResult:
108
+ guard_id: str
109
+ state: str
110
+ findings: list[Finding | CallableFinding | MarkdownDocumentFinding | MarkdownSectionFinding]
111
+
112
+ @property
113
+ def required_policies(self) -> list[str]:
114
+ return [self.guard_id] if self.state in {"review", "fail"} else []
115
+
116
+ def to_json(self) -> dict[str, Any]:
117
+ return {
118
+ "state": self.state,
119
+ "findings": [finding.to_json() for finding in self.findings],
120
+ }
121
+
122
+
123
+ def aggregate_state(results: list[GuardResult]) -> str:
124
+ return max((result.state for result in results), key=STATE_RANK.get, default="pass")
125
+
126
+
127
+ def required_policies(results: list[GuardResult]) -> list[str]:
128
+ return sorted({policy for result in results for policy in result.required_policies})
@@ -0,0 +1,96 @@
1
+ """Locate and export the version-coupled Code Guard skill payload."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from importlib.metadata import distribution, version
6
+ import json
7
+ from pathlib import Path
8
+ import shutil
9
+ from urllib.parse import unquote, urlparse
10
+ from urllib.request import url2pathname
11
+
12
+
13
+ PAYLOAD_FILES = (
14
+ "SKILL.md",
15
+ "LICENSE.txt",
16
+ "agents/openai.yaml",
17
+ "references/callable-size-policy.md",
18
+ "references/complexity-policy.md",
19
+ "references/loc-policy.md",
20
+ "references/markdown-size-policy.md",
21
+ "references/nesting-policy.md",
22
+ )
23
+
24
+
25
+ def skill_path() -> Path:
26
+ """Return the installed canonical skill payload directory."""
27
+ package = distribution("agent-code-guard")
28
+ suffix = "share/agent-code-guard/skill/SKILL.md"
29
+ path = next(
30
+ (
31
+ Path(package.locate_file(item)).parent
32
+ for item in package.files or ()
33
+ if str(item).replace("\\", "/").endswith(suffix)
34
+ ),
35
+ None,
36
+ )
37
+ if path is None:
38
+ path = _editable_skill_path(package)
39
+ if path is None:
40
+ raise ValueError("installed distribution does not contain the Code Guard skill payload")
41
+ _validate_payload(path)
42
+ return path.resolve()
43
+
44
+
45
+ def export_skill(target: Path) -> Path:
46
+ """Copy the installed payload into an empty caller-owned directory."""
47
+ target = target.expanduser().resolve()
48
+ if target.exists():
49
+ if not target.is_dir():
50
+ raise ValueError(f"skill export target is not a directory: {target}")
51
+ if any(target.iterdir()):
52
+ raise ValueError(f"skill export target is not empty: {target}")
53
+ else:
54
+ target.mkdir(parents=True)
55
+
56
+ source_root = skill_path()
57
+ for relative in PAYLOAD_FILES:
58
+ source = source_root / relative
59
+ if source.is_symlink() or not source.is_file():
60
+ raise ValueError(f"installed skill payload has an unsafe or missing file: {relative}")
61
+ destination = target / relative
62
+ destination.parent.mkdir(parents=True, exist_ok=True)
63
+ shutil.copyfile(source, destination)
64
+ (target / ".agent-code-guard-version").write_text(
65
+ f'{version("agent-code-guard")}\n', encoding="utf-8", newline="\n",
66
+ )
67
+ return target
68
+
69
+
70
+ def _validate_payload(path: Path) -> None:
71
+ if path.is_symlink() or not path.is_dir():
72
+ raise ValueError(f"installed skill payload is missing: {path}")
73
+ for relative in PAYLOAD_FILES:
74
+ candidate = path / relative
75
+ relative_path = Path(relative)
76
+ parents = (
77
+ path.joinpath(*relative_path.parts[:index])
78
+ for index in range(1, len(relative_path.parts))
79
+ )
80
+ if any(parent.is_symlink() for parent in parents) or candidate.is_symlink() or not candidate.is_file():
81
+ raise ValueError(f"installed skill payload has an unsafe or missing file: {relative}")
82
+
83
+
84
+ def _editable_skill_path(package) -> Path | None:
85
+ """Use PEP 610 metadata when setuptools omits data-files from editable wheels."""
86
+ direct_url = package.read_text("direct_url.json")
87
+ if direct_url is None:
88
+ return None
89
+ metadata = json.loads(direct_url)
90
+ if not metadata.get("dir_info", {}).get("editable"):
91
+ return None
92
+ parsed = urlparse(metadata.get("url", ""))
93
+ if parsed.scheme != "file":
94
+ return None
95
+ checkout = Path(url2pathname(unquote(parsed.path)))
96
+ return checkout / "skills" / "code-guard"
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Stef Karyotidis
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,138 @@
1
+ ---
2
+ name: code-guard
3
+ description: Use when creating, editing, reviewing, or refactoring supported code or Markdown documentation to run deterministic guardrails and load only the policy guidance required by triggered findings.
4
+ license: Complete terms in LICENSE.txt
5
+ ---
6
+
7
+ # Code Guard
8
+
9
+ Use this skill whenever supported code or Markdown documentation artifacts are created, edited, reviewed, or refactored.
10
+
11
+ Code Guard provides deterministic measurements that act as anchors for agent judgment. The measurement is objective; the response to a `REVIEW` finding still requires design judgment.
12
+
13
+ ## Result states
14
+
15
+ - `PASS` — no special action is required.
16
+ - `REVIEW` — inspect the finding and either accept it with a meaningful justification or improve the code when doing so improves real clarity, cohesion, or boundaries.
17
+ - `FAIL` — do not declare normal completion until the condition is fixed or an explicitly permitted/user-approved exception applies.
18
+
19
+ ## Universal rules
20
+
21
+ 1. Never game a metric.
22
+ 2. Preserve readability and the repository's normal formatting/style conventions.
23
+ 3. Do not compress independent statements, remove useful structure/comments, obscure control flow, or minify handwritten source to lower a measurement.
24
+ 4. Do not create meaningless helpers, artificial files, unnecessary abstractions, or indirection mainly to reduce a metric.
25
+ 5. `REVIEW` is not an automatic refactor instruction.
26
+ 6. Refactor only when the change improves the code rather than merely improving the score.
27
+ 7. Do not create, broaden, or alter policy exceptions/configuration solely to make Code Guard pass without explicit user approval.
28
+ 8. Do not expand the current task to unrelated pre-existing debt. Normal development checks changed/current-work files; full-repository audit is separate.
29
+
30
+ ## Workflow
31
+
32
+ With Git, run the installed Code Guard command after supported code or Markdown documentation edits:
33
+
34
+ ```bash
35
+ code-guard . --changed-only
36
+ ```
37
+
38
+ An installed Agent Code Guard distribution provides both the command and this
39
+ version-matched skill payload. The skill's normal execution route is always the
40
+ installed `code-guard` command.
41
+
42
+ For repository development only, the compatibility runner remains available
43
+ directly from a checkout. It is not part of the externally installed skill
44
+ payload or the normal end-user execution route:
45
+
46
+ ```bash
47
+ python3 skills/code-guard/scripts/code_guard.py . --changed-only
48
+ ```
49
+
50
+ `pyproject.toml` canonically owns the production pins. Tree-sitter remains
51
+ dormant during LOC-only execution; failure to load a required provider or
52
+ grammar is a deterministic tool error during normal zero-config syntax analysis.
53
+ Disabling every syntax guard preserves the lazy no-Tree-sitter path. A strictly
54
+ LOC-only result also requires both Markdown guards to be explicitly disabled.
55
+
56
+ Without Git or another VCS that can provide changed scope, pass exactly the files you created or modified. You are responsible for supplying the complete edited-file set:
57
+
58
+ ```bash
59
+ code-guard src/Foo.py src/Bar.ts docs/guide.md
60
+ ```
61
+
62
+ Do not create a manifest or temporary scope file. Specific positional files mean “inspect these artifacts.” A directory or `.` means a deliberate recursive audit when no Git selector is used. Positional files/directories bound the candidates selected by `--changed-only`, `--staged`, or `--base-ref`; Git selection fails outside a Git repository and never falls back to an audit.
63
+
64
+ Recursive directory discovery does not follow symlinks. An explicitly supplied
65
+ file symlink is treated as caller intent; an explicit directory symlink is
66
+ rejected rather than recursively traversed.
67
+
68
+ Prefer normal zero-config scope and respect project `scope.exclude`; do not
69
+ remove or alter exclusions merely to silence findings. Repeated
70
+ `--scope-exclude` is caller-supplied all-guard scope policy and composes with
71
+ project exclusions. LOC `--exclude` remains LOC-specific. Explicit files may
72
+ intentionally inspect Git-ignored or built-in-pruned artifacts, unless Code
73
+ Guard `scope.exclude` or `--scope-exclude` removes them.
74
+
75
+ When all guards return `PASS`, no detailed policy file needs to be loaded.
76
+
77
+ When a guard returns `REVIEW` or `FAIL`, read only the policy file named by that finding. The runner returns required policy identifiers/files in both human-readable and JSON output.
78
+
79
+ Policy references:
80
+
81
+ - file LOC: `references/loc-policy.md`
82
+ - callable size: `references/callable-size-policy.md`
83
+ - nesting depth: `references/nesting-policy.md`
84
+ - cyclomatic complexity: `references/complexity-policy.md`
85
+ - Markdown document/section size: `references/markdown-size-policy.md`
86
+
87
+ Do not load unrelated guard policies merely because they exist.
88
+
89
+ ## Scope
90
+
91
+ Code Guard is intentionally limited to deterministic concerns that are broadly applicable across conventional programming languages.
92
+
93
+ Guards:
94
+
95
+ - file LOC (implemented and enabled by default);
96
+ - source/container and syntax facts (production infrastructure, not a guard);
97
+ - callable LOC (implemented and enabled by default; REVIEW greater than 80);
98
+ - structural nesting (implemented and enabled by default; REVIEW greater than 4);
99
+ - cyclomatic complexity (implemented and enabled by default; REVIEW greater than 15).
100
+ - Markdown document physical size (implemented for `.md` and enabled by default; REVIEW greater than 800);
101
+ - Markdown direct-section physical size (implemented for `.md` and enabled by default; REVIEW greater than 200).
102
+
103
+ Callable LOC needs no invented configuration to activate it. Omission or
104
+ `enabled: true` uses 80; an authorized positive-integer `reviewAt` overrides it,
105
+ and `enabled: false` disables it. Exactly the effective threshold passes;
106
+ larger callables review and never fail. Load
107
+ `references/callable-size-policy.md` only when `callableSize` appears in
108
+ `requiredPolicies`.
109
+
110
+ Structural nesting is executable control-flow depth, not visual, markup, brace,
111
+ or indentation depth. Omission or `enabled: true` uses 4; an authorized
112
+ positive-integer `reviewAt` overrides it, and `enabled: false` disables it.
113
+ Exactly the effective depth passes; greater depth reviews and never fails. Load `references/nesting-policy.md` only when `nesting`
114
+ appears in `requiredPolicies`.
115
+
116
+ Cyclomatic complexity is baseline 1 plus normalized decisions owned by the
117
+ callable. Omission or `enabled: true` uses 15; an authorized positive-integer
118
+ `reviewAt` overrides it, and `enabled: false` disables it. Short-circuit
119
+ booleans and fallback/null-aware constructs contribute zero. Lambda boundaries
120
+ are independent. Exactly the effective threshold passes; greater complexity
121
+ reviews and never fails. Load `references/complexity-policy.md` only when
122
+ `complexity` appears in `requiredPolicies`.
123
+
124
+ Markdown document and direct-section size count all physical lines. Sections
125
+ run from a supported heading through the line before the next heading of any
126
+ level, or EOF. Exact effective thresholds pass; greater measurements review and
127
+ never fail. Load `references/markdown-size-policy.md` when either
128
+ `markdownDocumentSize` or `markdownSectionSize` appears in `requiredPolicies`.
129
+ Review navigation and responsibility without mechanically splitting coherent
130
+ specifications or gaming headings/formatting.
131
+
132
+ Do not invent configuration, disable a guard, or raise its threshold
133
+ merely to silence a finding. Respect built-ins and only project/user-authorized overrides.
134
+ REVIEW requires inspection and justification, not mandatory refactoring.
135
+
136
+ Agent Code Guard is the canonical LOC implementation. Agent LOC Guard is the completed prototype/reference whose mature behavior was migrated from commit `75ab39d261dbc65f78815836fac90add16d265d1`.
137
+
138
+ Project-specific architecture rules, framework-specific checks, arbitrary style preferences, security scanners, and dependency auditing are outside the universal core.
@@ -0,0 +1,8 @@
1
+ interface:
2
+ display_name: "Code Guard"
3
+ short_description: "Deterministic code guardrails for agents"
4
+ brand_color: "#2563EB"
5
+ default_prompt: "Use $code-guard to check changed supported code and Markdown documentation, then load only the policies required by triggered findings."
6
+
7
+ policy:
8
+ allow_implicit_invocation: true
@@ -0,0 +1,39 @@
1
+ # Callable Size Policy
2
+
3
+ Callable size measures the physical LOC of a function, method, constructor, closure, or equivalent callable unit.
4
+
5
+ This guard exists because a source file can remain modest in size while one operation grows large enough to become difficult to understand or change safely.
6
+
7
+ ## Status
8
+
9
+ The calibrated universal default is REVIEW above 80 physical LOC. Exactly 80
10
+ passes. Authorized project/user configuration may supply a positive
11
+ `guards.callableSize.reviewAt` override or explicitly disable the guard. The
12
+ guard has no FAIL threshold.
13
+
14
+ ## On REVIEW
15
+
16
+ Inspect whether the callable:
17
+
18
+ - performs one coherent operation;
19
+ - mixes separable stages or responsibilities;
20
+ - contains large regions that have meaningful names and independent contracts;
21
+ - has accumulated error handling, branching, transformation, persistence, or orchestration that belongs elsewhere;
22
+ - is long mainly because the operation is legitimately linear and easier to understand in one place.
23
+
24
+ Extract code only when the extracted operation is genuinely cohesive and its name/interface improves comprehension.
25
+
26
+ REVIEW requires inspection, not automatic refactoring. Examine the callable's
27
+ cohesion, responsibility, and growth. Split it only when the resulting design is
28
+ clearer, and preserve the project's conventions.
29
+
30
+ ## Anti-gaming
31
+
32
+ Do not create tiny meaningless helper methods merely to reduce callable LOC. Do not move arbitrary chunks of a procedure behind names such as `ProcessPart1`, `HandleStuff`, or equivalent abstractions that add navigation without improving design.
33
+
34
+ Do not compress formatting or combine independent statements onto fewer physical lines to lower the measurement.
35
+
36
+ Do not alter the threshold or disable the guard merely to silence a finding.
37
+ Only respect such a change when the project or user has authorized it.
38
+
39
+ A lower callable LOC number is useful only when the resulting code is at least as readable and maintainable as before.
@@ -0,0 +1,39 @@
1
+ # Cyclomatic Complexity Policy
2
+
3
+ Cyclomatic complexity measures the number of independent control-flow paths through a callable.
4
+
5
+ This guard exists because a callable can be short and only lightly nested while still containing enough branching and decision logic to be difficult to reason about or test safely.
6
+
7
+ ## Status
8
+
9
+ Complexity is enabled by default. Exactly 15 passes and greater complexity
10
+ reviews. It is REVIEW-only and never fails. An authorized project/user positive
11
+ integer `reviewAt` may override the default, and explicit disablement is allowed.
12
+ Short-circuit booleans deliberately contribute zero. Agents must not weaken or
13
+ disable the guard merely to silence findings.
14
+
15
+ ## On REVIEW
16
+
17
+ Inspect whether complexity comes from:
18
+
19
+ - many genuinely independent execution paths;
20
+ - accumulated conditional branching;
21
+ - mixed responsibilities;
22
+ - mode/type/state switches that should perhaps be modeled explicitly;
23
+ - error handling mixed with core behavior;
24
+ - legitimate parsers, protocol handling, state machines, or rule evaluation where branching may be inherent.
25
+
26
+ Consider refactoring only when the resulting structure makes behavior easier to understand, test, or change.
27
+ REVIEW is an inspection request, not an automatic decomposition instruction.
28
+
29
+ ## Anti-gaming
30
+
31
+ Do not lower complexity by hiding decisions behind meaningless wrappers, opaque boolean expressions, lookup tricks, exception flow, or abstractions whose main purpose is changing the score.
32
+
33
+ Do not split one coherent decision process into scattered helpers when that makes the execution model harder to follow.
34
+
35
+ Do not convert clear branches into clever expressions or split coherent parsers,
36
+ state machines, and protocol handlers merely to lower the number. Preserve
37
+ project and language idioms.
38
+
39
+ A lower complexity score is not an improvement unless the resulting behavior and structure are clearer.
@@ -0,0 +1,40 @@
1
+ # File LOC Policy
2
+
3
+ This is the canonical Agent Code Guard policy for oversized handwritten source files. LOC is a deterministic review signal, not proof that every large file has poor architecture.
4
+
5
+ ## Core rule
6
+
7
+ - Up to 400 counted LOC: `PASS`.
8
+ - 401 through 600 counted LOC: `REVIEW`.
9
+ - More than 600 counted LOC: `FAIL` by default unless an explicit approved exemption applies.
10
+ - An existing applicable exemption is `PASS` with native `exempt` status and its reason retained.
11
+
12
+ Counting and selection follow the canonical runner. By default, LOC is non-blank physical lines and comments count. Normal development uses `--changed-only`: staged, unstaged, and untracked current work relative to `HEAD`. A scan without a selection flag is an explicit full-repository audit.
13
+
14
+ ## REVIEW interpretation
15
+
16
+ Inspect whether the file remains cohesive and single-responsibility, whether its size is necessary orchestration or linear structure, whether separable responsibilities are mixed, and whether expected near-term growth changes that judgment.
17
+
18
+ `REVIEW` does not automatically require refactoring. Split only when doing so improves real responsibility boundaries or clarity; accept the warning when the file remains cohesive and a split would add harmful indirection.
19
+
20
+ Report either `warning accepted with justification: ...` or `split performed because: ...`.
21
+
22
+ ## FAIL and exemptions
23
+
24
+ For `FAIL`, refactor below the hard cap when that improves the design or obtain explicit user approval for a justified exemption. Otherwise report `hard cap reached; user approval required`.
25
+
26
+ Existing `allowedLargeFiles` entries may be honored with their configured reasons. Agents must not create, broaden, modify, repurpose, or invent exemptions merely to pass. Threshold overrides are also explicit policy decisions; agents must not create, broaden, or relax them merely to bypass a finding without explicit approval or existing project policy.
27
+
28
+ Do not infer approval from inconvenience, historical size, a nearby exemption, time pressure, or a request to finish the coding task.
29
+
30
+ ## Do not game LOC
31
+
32
+ Project formatting conventions take priority. Never combine independent statements, compress control flow or expressions unusually, minify handwritten code, remove useful comments/structure, or fight the formatter merely to lower physical LOC.
33
+
34
+ Legitimate reductions improve the code: remove redundancy or dead code, simplify control flow, consolidate duplication when appropriate, or split cohesive responsibilities. Prefer cohesive modules over artificial fragmentation.
35
+
36
+ ## Scope discipline
37
+
38
+ Changed code is evaluated in its resulting form, including a legacy file modified by the task. Unrelated legacy debt belongs to explicit audit work and must not expand a normal change unnecessarily.
39
+
40
+ Test files may exceed the review threshold when clearly grouped and navigable. They still require explicit approval above the hard cap.
@@ -0,0 +1,16 @@
1
+ # Markdown Size Review Policy
2
+
3
+ Use this policy when `markdownDocumentSize` or `markdownSectionSize` appears in
4
+ `requiredPolicies`.
5
+
6
+ A Markdown size REVIEW is an instruction to inspect navigation and
7
+ responsibility, not an automatic instruction to split the document or section.
8
+ `reviewed; coherent; keep` is a valid outcome for cohesive specifications,
9
+ reference material, tables, procedures, and code-heavy sections.
10
+
11
+ Improve navigation or responsibility boundaries only when the result is
12
+ genuinely clearer. Do not add meaningless headings to lower section size,
13
+ mechanically split coherent material, compress formatting or remove useful
14
+ blank lines, or hide content in fenced code. Agents must not raise thresholds or
15
+ disable either guard merely to silence a finding; project or user authority is
16
+ required for configuration changes.
@@ -0,0 +1,37 @@
1
+ # Nesting Depth Policy
2
+
3
+ Nesting depth measures how deeply control-flow structures are nested within a callable.
4
+
5
+ This guard exists because deeply nested code can be difficult to reason about even when the file and callable are not especially long.
6
+
7
+ ## Status
8
+
9
+ The calibrated universal default is REVIEW above structural depth 4. Exactly 4
10
+ passes. Authorized project/user configuration may supply a positive
11
+ `guards.nesting.reviewAt` override or explicitly disable the guard. The guard
12
+ has no FAIL threshold.
13
+
14
+ ## On REVIEW
15
+
16
+ Inspect whether the nesting reflects:
17
+
18
+ - avoidable conditional pyramids;
19
+ - loops nested inside branches with additional branching;
20
+ - validation/error paths that could be expressed more clearly with guard clauses or early exits;
21
+ - multiple responsibilities entangled in one callable;
22
+ - state-machine, parser, traversal, or other logic where deeper nesting may be inherent and still readable.
23
+
24
+ REVIEW means inspect control-flow readability; it is not an automatic refactor.
25
+ Consider guard clauses or extraction only when they improve clarity. Preserve
26
+ idiomatic language and project structure.
27
+
28
+ ## Anti-gaming
29
+
30
+ Do not flatten code merely to reduce the measured depth if the result becomes harder to follow.
31
+
32
+ Do not hide nested decisions behind meaningless helper calls or obscure boolean expressions. Do not replace clear structured control flow with clever expressions, compressed conditionals, exception tricks, or other forms whose primary purpose is lowering the metric.
33
+
34
+ Do not change or disable the configured threshold merely to silence a finding.
35
+ Only respect such a change when the project or user has authorized it.
36
+
37
+ The preferred outcome is clearer control flow, not a smaller number at any cost.