agent-code-guard 0.3.0__tar.gz → 0.4.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 (57) hide show
  1. {agent_code_guard-0.3.0/src/agent_code_guard.egg-info → agent_code_guard-0.4.0}/PKG-INFO +33 -22
  2. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/README.md +32 -21
  3. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/pyproject.toml +1 -1
  4. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/skills/code-guard/SKILL.md +20 -2
  5. agent_code_guard-0.4.0/skills/code-guard/references/markdown-size-policy.md +33 -0
  6. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/analysis/adapters.py +4 -4
  7. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/analysis/callable_identity.py +1 -2
  8. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/analysis/facts.py +21 -1
  9. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/analysis/pipeline.py +15 -9
  10. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/analysis/regions.py +24 -14
  11. agent_code_guard-0.4.0/src/agent_code_guard/baseline_files.py +139 -0
  12. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/code_guard.py +107 -56
  13. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/config_validation.py +17 -19
  14. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/file_selection.py +42 -17
  15. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/guards/callable_size.py +14 -20
  16. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/guards/complexity.py +14 -19
  17. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/guards/loc.py +27 -36
  18. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/guards/markdown_document_size.py +35 -23
  19. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/guards/markdown_section_size.py +16 -18
  20. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/guards/nesting.py +14 -19
  21. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/human_output.py +8 -3
  22. agent_code_guard-0.4.0/src/agent_code_guard/invocation.py +54 -0
  23. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/loc_baseline.py +20 -115
  24. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/markdown/facts.py +1 -0
  25. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/markdown/scanner.py +15 -6
  26. agent_code_guard-0.4.0/src/agent_code_guard/markdown_baseline.py +171 -0
  27. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/result_model.py +9 -1
  28. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0/src/agent_code_guard.egg-info}/PKG-INFO +33 -22
  29. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard.egg-info/SOURCES.txt +3 -0
  30. agent_code_guard-0.3.0/skills/code-guard/references/markdown-size-policy.md +0 -16
  31. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/LICENSE +0 -0
  32. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/MANIFEST.in +0 -0
  33. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/setup.cfg +0 -0
  34. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/skills/code-guard/LICENSE.txt +0 -0
  35. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/skills/code-guard/agents/openai.yaml +0 -0
  36. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/skills/code-guard/references/callable-size-policy.md +0 -0
  37. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/skills/code-guard/references/complexity-policy.md +0 -0
  38. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/skills/code-guard/references/loc-policy.md +0 -0
  39. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/skills/code-guard/references/nesting-policy.md +0 -0
  40. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/__init__.py +0 -0
  41. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/analysis/__init__.py +0 -0
  42. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/analysis/branch_normalization.py +0 -0
  43. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/analysis/csharp_compat.py +0 -0
  44. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/analysis/errors.py +0 -0
  45. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/analysis/language_specs.py +0 -0
  46. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/analysis/provider.py +0 -0
  47. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/analysis/syntax_nodes.py +0 -0
  48. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/doctor.py +0 -0
  49. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/guards/__init__.py +0 -0
  50. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/markdown/__init__.py +0 -0
  51. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/path_matching.py +0 -0
  52. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/reporting.py +0 -0
  53. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard/skill_distribution.py +0 -0
  54. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard.egg-info/dependency_links.txt +0 -0
  55. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard.egg-info/entry_points.txt +0 -0
  56. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard.egg-info/requires.txt +0 -0
  57. {agent_code_guard-0.3.0 → agent_code_guard-0.4.0}/src/agent_code_guard.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-code-guard
3
- Version: 0.3.0
3
+ Version: 0.4.0
4
4
  Summary: Deterministic cross-language guardrails for agent-assisted development
5
5
  License-Expression: MIT
6
6
  Project-URL: Source, https://github.com/stef-k/agent-code-guard
@@ -21,9 +21,13 @@ Dynamic: license-file
21
21
  Deterministic maintainability guardrails for source code and Markdown changed by
22
22
  a human or coding agent.
23
23
 
24
+ [Documentation](https://stef-k.github.io/agent-code-guard/) ·
25
+ [Get started](https://stef-k.github.io/agent-code-guard/#get-started) ·
26
+ [Releases](https://github.com/stef-k/agent-code-guard/releases)
27
+
24
28
  [![Production Analysis](https://github.com/stef-k/agent-code-guard/actions/workflows/analysis.yml/badge.svg)](https://github.com/stef-k/agent-code-guard/actions/workflows/analysis.yml)
25
29
  [![PyPI](https://img.shields.io/pypi/v/agent-code-guard?logo=pypi&logoColor=white)](https://pypi.org/project/agent-code-guard/)
26
- [![Python 3.10–3.14](https://img.shields.io/badge/Python-3.10%E2%80%933.14-3776AB?logo=python&logoColor=white)](https://github.com/stef-k/agent-code-guard/blob/main/docs/platform-support.md)
30
+ [![Python 3.10–3.14](https://img.shields.io/badge/Python-3.10%E2%80%933.14-3776AB?logo=python&logoColor=white)](https://stef-k.github.io/agent-code-guard/platform-support.html)
27
31
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/stef-k/agent-code-guard/blob/main/LICENSE)
28
32
 
29
33
  Agent Code Guard measures file size, callable size, structural nesting,
@@ -75,7 +79,7 @@ code-guard doctor
75
79
  ```
76
80
 
77
81
  `--version` confirms the installed distribution identity. `doctor` checks the
78
- active installation's health. See the [usage guide](https://github.com/stef-k/agent-code-guard/blob/main/docs/usage.md) for virtual
82
+ active installation's health. See the [usage guide](https://stef-k.github.io/agent-code-guard/usage.html) for virtual
79
83
  environment, uv, and developer alternatives.
80
84
 
81
85
  ### Ask your agent to adopt it
@@ -89,13 +93,13 @@ Copy this prompt to a coding agent:
89
93
  > activating or exporting its installed, version-matched skill for the current
90
94
  > agent environment. Verify `code-guard --version` and run `code-guard doctor`,
91
95
  > then locate the skill with `code-guard --skill-path`. Follow the
92
- > [skill activation guide](https://github.com/stef-k/agent-code-guard/blob/main/docs/skill-distribution.md):
96
+ > [skill activation guide](https://stef-k.github.io/agent-code-guard/skill-distribution.html):
93
97
  > activate that installed path when the platform supports it, or export it with
94
98
  > `code-guard --export-skill <target-directory>` to the platform's documented
95
99
  > skill directory. Do not guess a target or overwrite an existing export; verify
96
100
  > that `.agent-code-guard-version` matches the installed distribution. Follow the
97
- > [agent workflow](https://github.com/stef-k/agent-code-guard/blob/main/docs/agent-workflow.md)
98
- > without creating a LOC baseline. After meaningful source or Markdown edits, run
101
+ > [agent workflow](https://stef-k.github.io/agent-code-guard/agent-workflow.html)
102
+ > without creating an adoption baseline. After meaningful source or Markdown edits, run
99
103
  > `code-guard . --changed-only --json --json-mode compact`; outside Git, pass the
100
104
  > exact edited files. Inspect REVIEW and FAIL findings, make only genuine
101
105
  > improvements, rerun the check, and report the result. Never weaken thresholds,
@@ -118,7 +122,7 @@ No configuration is needed. A REVIEW asks for inspection and judgment, not an
118
122
  automatic refactor. Outside Git, pass the exact edited files instead, such as
119
123
  `code-guard src/app.py docs/guide.md`.
120
124
 
121
- See the [agent workflow guide](https://github.com/stef-k/agent-code-guard/blob/main/docs/agent-workflow.md) for repeated human and
125
+ See the [agent workflow guide](https://stef-k.github.io/agent-code-guard/agent-workflow.html) for repeated human and
122
126
  agent use.
123
127
 
124
128
  ## Recommended workflow
@@ -140,7 +144,7 @@ report the result before completion
140
144
  Use `code-guard . --changed-only --json --json-mode compact` for a structured,
141
145
  low-noise manual agent check. Hooks are optional, platform-owned, and require
142
146
  user authorization; Code Guard does not install them. The
143
- [workflow guide](https://github.com/stef-k/agent-code-guard/blob/main/docs/agent-workflow.md) owns the complete manual and
147
+ [workflow guide](https://stef-k.github.io/agent-code-guard/agent-workflow.html) owns the complete manual and
144
148
  hook-assisted process.
145
149
 
146
150
  ## Interpreting results
@@ -177,7 +181,7 @@ measurement. A REVIEW is not proof of a defect or a mandatory refactor.
177
181
  Comparisons are strictly greater-than, so equality passes. All guards except
178
182
  file LOC are REVIEW-only; only file LOC can FAIL. A new guard must provide
179
183
  distinct, deterministic value rather than duplicate conventional tooling. See
180
- [Guard admission](https://github.com/stef-k/agent-code-guard/blob/main/docs/guard-admission.md).
184
+ [Guard admission](https://stef-k.github.io/agent-code-guard/guard-admission.html).
181
185
 
182
186
  ### Result and JSON reference
183
187
 
@@ -186,7 +190,7 @@ all-guard-excluded file counts. Bare `--json` is the compatible full output;
186
190
  `--json-mode debug` is byte-identical for the same completed invocation, while
187
191
  `--json-mode compact` removes only normalized `pass` findings and retains the
188
192
  result, scope, required policies, guards, ordering, and actionable findings.
189
- Named modes require `--json`. See [Usage](https://github.com/stef-k/agent-code-guard/blob/main/docs/usage.md) for the schema and
193
+ Named modes require `--json`. See [Usage](https://stef-k.github.io/agent-code-guard/usage.html) for the schema and
190
194
  option contract.
191
195
 
192
196
  Known per-file syntax or provider failures instead produce `overall:
@@ -221,7 +225,7 @@ Generic `.h` files are not syntax-dispatched; `.markdown` is not enabled; Vue
221
225
  template and style regions are not executable syntax input; and unsupported
222
226
  artifacts are inapplicable. Malformed applicable syntax or a required provider
223
227
  failure is unavailable evidence, distinct from both an inapplicable file and a
224
- completed FAIL finding. See [Language support](https://github.com/stef-k/agent-code-guard/blob/main/docs/language-support.md).
228
+ completed FAIL finding. See [Language support](https://stef-k.github.io/agent-code-guard/language-support.html).
225
229
 
226
230
  ### Skill integration
227
231
 
@@ -233,38 +237,45 @@ code-guard --export-skill <target-directory>
233
237
  ```
234
238
 
235
239
  Skill activation is platform-specific and is not performed by pipx or Code
236
- Guard. See [Skill distribution](https://github.com/stef-k/agent-code-guard/blob/main/docs/skill-distribution.md). The checkout
240
+ Guard. See [Skill distribution](https://stef-k.github.io/agent-code-guard/skill-distribution.html). The checkout
237
241
  compatibility runner is for repository development, not normal installation.
238
242
 
239
243
  ### Configuration
240
244
 
241
245
  Built-in defaults require no configuration. Configure a project only for a
242
- concrete policy reason; see the [configuration guide](https://github.com/stef-k/agent-code-guard/blob/main/docs/configuration.md).
246
+ concrete policy reason; see the [configuration guide](https://stef-k.github.io/agent-code-guard/configuration.html).
243
247
  The LOC baseline is an explicit adoption tool for established legacy
244
248
  repositories, not an ordinary-use requirement or a way to silence findings.
245
249
  Its default `ratchetAt: "fail"` policy freezes files above `failAt`; choose
246
250
  `ratchetAt: "review"` only when every established file above `warnAt` must be
247
251
  non-increasing while ordinary findings in that range remain REVIEW.
248
252
 
253
+ Reviewed oversized Markdown documents have a separate, explicit
254
+ [document-size ratchet](https://stef-k.github.io/agent-code-guard/usage.html#reviewed-markdown-document-ratchet).
255
+ `--create-markdown-baseline` records accepted physical-line counts;
256
+ `--update-markdown-baseline` only lowers or prunes them. Documents within their
257
+ allowance pass the document-size guard; growth produces REVIEW. Section
258
+ findings remain active, and ordinary analysis never writes either baseline.
259
+
249
260
  ## Trust, CI, and platform support
250
261
 
251
262
  CI installs Agent Code Guard and analyzes its own real checkout. REVIEW findings
252
263
  remain visible but non-blocking, while FAIL findings and tool errors block the
253
- workflow; the repository intentionally uses no LOC baseline.
264
+ workflow; the repository intentionally uses no adoption baseline.
254
265
 
255
266
  The maintained interpreter range is **CPython 3.10–3.14**. See
256
- [Platform support](https://github.com/stef-k/agent-code-guard/blob/main/docs/platform-support.md) for supported binary platforms and
267
+ [Platform support](https://stef-k.github.io/agent-code-guard/platform-support.html) for supported binary platforms and
257
268
  source-build boundaries.
258
269
 
259
270
  ## Documentation
260
271
 
261
- - [Documentation index](https://github.com/stef-k/agent-code-guard/blob/main/docs/README.md)
262
- - [Agent workflow](https://github.com/stef-k/agent-code-guard/blob/main/docs/agent-workflow.md)
263
- - [Usage and CLI reference](https://github.com/stef-k/agent-code-guard/blob/main/docs/usage.md)
264
- - [Configuration](https://github.com/stef-k/agent-code-guard/blob/main/docs/configuration.md)
265
- - [Language support](https://github.com/stef-k/agent-code-guard/blob/main/docs/language-support.md)
266
- - [Platform support](https://github.com/stef-k/agent-code-guard/blob/main/docs/platform-support.md)
267
- - [Skill distribution](https://github.com/stef-k/agent-code-guard/blob/main/docs/skill-distribution.md)
272
+ - [Documentation index](https://stef-k.github.io/agent-code-guard/)
273
+ - [Agent workflow](https://stef-k.github.io/agent-code-guard/agent-workflow.html)
274
+ - [Usage and CLI reference](https://stef-k.github.io/agent-code-guard/usage.html)
275
+ - [Configuration](https://stef-k.github.io/agent-code-guard/configuration.html)
276
+ - [Language support](https://stef-k.github.io/agent-code-guard/language-support.html)
277
+ - [Platform support](https://stef-k.github.io/agent-code-guard/platform-support.html)
278
+ - [Skill distribution](https://stef-k.github.io/agent-code-guard/skill-distribution.html)
268
279
 
269
280
  ## Feedback, security, and license
270
281
 
@@ -7,9 +7,13 @@
7
7
  Deterministic maintainability guardrails for source code and Markdown changed by
8
8
  a human or coding agent.
9
9
 
10
+ [Documentation](https://stef-k.github.io/agent-code-guard/) ·
11
+ [Get started](https://stef-k.github.io/agent-code-guard/#get-started) ·
12
+ [Releases](https://github.com/stef-k/agent-code-guard/releases)
13
+
10
14
  [![Production Analysis](https://github.com/stef-k/agent-code-guard/actions/workflows/analysis.yml/badge.svg)](https://github.com/stef-k/agent-code-guard/actions/workflows/analysis.yml)
11
15
  [![PyPI](https://img.shields.io/pypi/v/agent-code-guard?logo=pypi&logoColor=white)](https://pypi.org/project/agent-code-guard/)
12
- [![Python 3.10–3.14](https://img.shields.io/badge/Python-3.10%E2%80%933.14-3776AB?logo=python&logoColor=white)](https://github.com/stef-k/agent-code-guard/blob/main/docs/platform-support.md)
16
+ [![Python 3.10–3.14](https://img.shields.io/badge/Python-3.10%E2%80%933.14-3776AB?logo=python&logoColor=white)](https://stef-k.github.io/agent-code-guard/platform-support.html)
13
17
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/stef-k/agent-code-guard/blob/main/LICENSE)
14
18
 
15
19
  Agent Code Guard measures file size, callable size, structural nesting,
@@ -61,7 +65,7 @@ code-guard doctor
61
65
  ```
62
66
 
63
67
  `--version` confirms the installed distribution identity. `doctor` checks the
64
- active installation's health. See the [usage guide](https://github.com/stef-k/agent-code-guard/blob/main/docs/usage.md) for virtual
68
+ active installation's health. See the [usage guide](https://stef-k.github.io/agent-code-guard/usage.html) for virtual
65
69
  environment, uv, and developer alternatives.
66
70
 
67
71
  ### Ask your agent to adopt it
@@ -75,13 +79,13 @@ Copy this prompt to a coding agent:
75
79
  > activating or exporting its installed, version-matched skill for the current
76
80
  > agent environment. Verify `code-guard --version` and run `code-guard doctor`,
77
81
  > then locate the skill with `code-guard --skill-path`. Follow the
78
- > [skill activation guide](https://github.com/stef-k/agent-code-guard/blob/main/docs/skill-distribution.md):
82
+ > [skill activation guide](https://stef-k.github.io/agent-code-guard/skill-distribution.html):
79
83
  > activate that installed path when the platform supports it, or export it with
80
84
  > `code-guard --export-skill <target-directory>` to the platform's documented
81
85
  > skill directory. Do not guess a target or overwrite an existing export; verify
82
86
  > that `.agent-code-guard-version` matches the installed distribution. Follow the
83
- > [agent workflow](https://github.com/stef-k/agent-code-guard/blob/main/docs/agent-workflow.md)
84
- > without creating a LOC baseline. After meaningful source or Markdown edits, run
87
+ > [agent workflow](https://stef-k.github.io/agent-code-guard/agent-workflow.html)
88
+ > without creating an adoption baseline. After meaningful source or Markdown edits, run
85
89
  > `code-guard . --changed-only --json --json-mode compact`; outside Git, pass the
86
90
  > exact edited files. Inspect REVIEW and FAIL findings, make only genuine
87
91
  > improvements, rerun the check, and report the result. Never weaken thresholds,
@@ -104,7 +108,7 @@ No configuration is needed. A REVIEW asks for inspection and judgment, not an
104
108
  automatic refactor. Outside Git, pass the exact edited files instead, such as
105
109
  `code-guard src/app.py docs/guide.md`.
106
110
 
107
- See the [agent workflow guide](https://github.com/stef-k/agent-code-guard/blob/main/docs/agent-workflow.md) for repeated human and
111
+ See the [agent workflow guide](https://stef-k.github.io/agent-code-guard/agent-workflow.html) for repeated human and
108
112
  agent use.
109
113
 
110
114
  ## Recommended workflow
@@ -126,7 +130,7 @@ report the result before completion
126
130
  Use `code-guard . --changed-only --json --json-mode compact` for a structured,
127
131
  low-noise manual agent check. Hooks are optional, platform-owned, and require
128
132
  user authorization; Code Guard does not install them. The
129
- [workflow guide](https://github.com/stef-k/agent-code-guard/blob/main/docs/agent-workflow.md) owns the complete manual and
133
+ [workflow guide](https://stef-k.github.io/agent-code-guard/agent-workflow.html) owns the complete manual and
130
134
  hook-assisted process.
131
135
 
132
136
  ## Interpreting results
@@ -163,7 +167,7 @@ measurement. A REVIEW is not proof of a defect or a mandatory refactor.
163
167
  Comparisons are strictly greater-than, so equality passes. All guards except
164
168
  file LOC are REVIEW-only; only file LOC can FAIL. A new guard must provide
165
169
  distinct, deterministic value rather than duplicate conventional tooling. See
166
- [Guard admission](https://github.com/stef-k/agent-code-guard/blob/main/docs/guard-admission.md).
170
+ [Guard admission](https://stef-k.github.io/agent-code-guard/guard-admission.html).
167
171
 
168
172
  ### Result and JSON reference
169
173
 
@@ -172,7 +176,7 @@ all-guard-excluded file counts. Bare `--json` is the compatible full output;
172
176
  `--json-mode debug` is byte-identical for the same completed invocation, while
173
177
  `--json-mode compact` removes only normalized `pass` findings and retains the
174
178
  result, scope, required policies, guards, ordering, and actionable findings.
175
- Named modes require `--json`. See [Usage](https://github.com/stef-k/agent-code-guard/blob/main/docs/usage.md) for the schema and
179
+ Named modes require `--json`. See [Usage](https://stef-k.github.io/agent-code-guard/usage.html) for the schema and
176
180
  option contract.
177
181
 
178
182
  Known per-file syntax or provider failures instead produce `overall:
@@ -207,7 +211,7 @@ Generic `.h` files are not syntax-dispatched; `.markdown` is not enabled; Vue
207
211
  template and style regions are not executable syntax input; and unsupported
208
212
  artifacts are inapplicable. Malformed applicable syntax or a required provider
209
213
  failure is unavailable evidence, distinct from both an inapplicable file and a
210
- completed FAIL finding. See [Language support](https://github.com/stef-k/agent-code-guard/blob/main/docs/language-support.md).
214
+ completed FAIL finding. See [Language support](https://stef-k.github.io/agent-code-guard/language-support.html).
211
215
 
212
216
  ### Skill integration
213
217
 
@@ -219,38 +223,45 @@ code-guard --export-skill <target-directory>
219
223
  ```
220
224
 
221
225
  Skill activation is platform-specific and is not performed by pipx or Code
222
- Guard. See [Skill distribution](https://github.com/stef-k/agent-code-guard/blob/main/docs/skill-distribution.md). The checkout
226
+ Guard. See [Skill distribution](https://stef-k.github.io/agent-code-guard/skill-distribution.html). The checkout
223
227
  compatibility runner is for repository development, not normal installation.
224
228
 
225
229
  ### Configuration
226
230
 
227
231
  Built-in defaults require no configuration. Configure a project only for a
228
- concrete policy reason; see the [configuration guide](https://github.com/stef-k/agent-code-guard/blob/main/docs/configuration.md).
232
+ concrete policy reason; see the [configuration guide](https://stef-k.github.io/agent-code-guard/configuration.html).
229
233
  The LOC baseline is an explicit adoption tool for established legacy
230
234
  repositories, not an ordinary-use requirement or a way to silence findings.
231
235
  Its default `ratchetAt: "fail"` policy freezes files above `failAt`; choose
232
236
  `ratchetAt: "review"` only when every established file above `warnAt` must be
233
237
  non-increasing while ordinary findings in that range remain REVIEW.
234
238
 
239
+ Reviewed oversized Markdown documents have a separate, explicit
240
+ [document-size ratchet](https://stef-k.github.io/agent-code-guard/usage.html#reviewed-markdown-document-ratchet).
241
+ `--create-markdown-baseline` records accepted physical-line counts;
242
+ `--update-markdown-baseline` only lowers or prunes them. Documents within their
243
+ allowance pass the document-size guard; growth produces REVIEW. Section
244
+ findings remain active, and ordinary analysis never writes either baseline.
245
+
235
246
  ## Trust, CI, and platform support
236
247
 
237
248
  CI installs Agent Code Guard and analyzes its own real checkout. REVIEW findings
238
249
  remain visible but non-blocking, while FAIL findings and tool errors block the
239
- workflow; the repository intentionally uses no LOC baseline.
250
+ workflow; the repository intentionally uses no adoption baseline.
240
251
 
241
252
  The maintained interpreter range is **CPython 3.10–3.14**. See
242
- [Platform support](https://github.com/stef-k/agent-code-guard/blob/main/docs/platform-support.md) for supported binary platforms and
253
+ [Platform support](https://stef-k.github.io/agent-code-guard/platform-support.html) for supported binary platforms and
243
254
  source-build boundaries.
244
255
 
245
256
  ## Documentation
246
257
 
247
- - [Documentation index](https://github.com/stef-k/agent-code-guard/blob/main/docs/README.md)
248
- - [Agent workflow](https://github.com/stef-k/agent-code-guard/blob/main/docs/agent-workflow.md)
249
- - [Usage and CLI reference](https://github.com/stef-k/agent-code-guard/blob/main/docs/usage.md)
250
- - [Configuration](https://github.com/stef-k/agent-code-guard/blob/main/docs/configuration.md)
251
- - [Language support](https://github.com/stef-k/agent-code-guard/blob/main/docs/language-support.md)
252
- - [Platform support](https://github.com/stef-k/agent-code-guard/blob/main/docs/platform-support.md)
253
- - [Skill distribution](https://github.com/stef-k/agent-code-guard/blob/main/docs/skill-distribution.md)
258
+ - [Documentation index](https://stef-k.github.io/agent-code-guard/)
259
+ - [Agent workflow](https://stef-k.github.io/agent-code-guard/agent-workflow.html)
260
+ - [Usage and CLI reference](https://stef-k.github.io/agent-code-guard/usage.html)
261
+ - [Configuration](https://stef-k.github.io/agent-code-guard/configuration.html)
262
+ - [Language support](https://stef-k.github.io/agent-code-guard/language-support.html)
263
+ - [Platform support](https://stef-k.github.io/agent-code-guard/platform-support.html)
264
+ - [Skill distribution](https://stef-k.github.io/agent-code-guard/skill-distribution.html)
254
265
 
255
266
  ## Feedback, security, and license
256
267
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "agent-code-guard"
7
- version = "0.3.0"
7
+ version = "0.4.0"
8
8
  description = "Deterministic cross-language guardrails for agent-assisted development"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -148,8 +148,9 @@ reviews and never fails. Load `references/complexity-policy.md` only when
148
148
 
149
149
  Markdown document and direct-section size count all physical lines. Sections
150
150
  run from a supported heading through the line before the next heading of any
151
- level, or EOF. Exact effective thresholds pass; greater measurements review and
152
- never fail. Load `references/markdown-size-policy.md` when either
151
+ level, or EOF. Exact effective thresholds pass; greater measurements normally
152
+ review and never fail. A document measurement within an explicitly accepted
153
+ Markdown document baseline passes the document-size guard. Load `references/markdown-size-policy.md` when either
153
154
  `markdownDocumentSize` or `markdownSectionSize` appears in `requiredPolicies`.
154
155
  Review navigation and responsibility without mechanically splitting coherent
155
156
  specifications or gaming headings/formatting.
@@ -161,3 +162,20 @@ REVIEW requires inspection and justification, not mandatory refactoring.
161
162
  Agent Code Guard is the canonical LOC implementation. Agent LOC Guard is the completed prototype/reference whose mature behavior was migrated from commit `75ab39d261dbc65f78815836fac90add16d265d1`.
162
163
 
163
164
  Project-specific architecture rules, framework-specific checks, arbitrary style preferences, security scanners, and dependency auditing are outside the universal core.
165
+
166
+ ## Reviewed Markdown document baselines
167
+
168
+ After explicit acceptance of a cohesive oversized document, use
169
+ `code-guard docs/architecture.md --create-markdown-baseline` to record its current
170
+ physical-line count in `.agent-tools/code-guard.markdown-baseline.json` at the
171
+ analysis root. Normal analysis reads this file without writing. Unchanged or
172
+ smaller accepted documents pass `markdownDocumentSize`; growth above both the
173
+ allowance and effective threshold returns REVIEW. `markdownSectionSize` remains
174
+ independent and has no baseline support.
175
+
176
+ `--update-markdown-baseline` only lowers or prunes existing allowances within
177
+ positional bounds; it never adds or increases one. Neither write command is
178
+ part of routine checks. Do not create, replace, remove, or increase allowances
179
+ merely to silence findings. Review and commit explicit acceptance decisions.
180
+ Human/full JSON output retains acceptance context; compact omits accepted PASS
181
+ findings. Load the Markdown policy for actionable document or section reviews.
@@ -0,0 +1,33 @@
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.
17
+
18
+ ## Explicit document acceptance
19
+
20
+ An explicitly reviewed, cohesive oversized document may use a source-controlled
21
+ allowance created with `--create-markdown-baseline`. The separate
22
+ `.agent-tools/code-guard.markdown-baseline.json` records exact root-relative paths
23
+ and current physical-line counts. Within that allowance the document finding
24
+ passes; growth above both the allowance and effective threshold is REVIEW,
25
+ never FAIL. At or below the ordinary threshold, an allowance is no longer needed.
26
+
27
+ This applies only to `markdownDocumentSize`. Inspect section REVIEW findings
28
+ independently; document acceptance does not exempt sections. Normal analysis
29
+ never changes a baseline. After reductions or deletions,
30
+ `--update-markdown-baseline` can explicitly lower or prune existing entries but
31
+ cannot add or increase allowances. Agents must not create or replace baselines,
32
+ remove allowances, raise thresholds, or add exclusions merely to silence growth.
33
+ Baseline acceptance requires explicit authority and source-control review.
@@ -116,11 +116,11 @@ def _range_end_node(node, language: str):
116
116
 
117
117
  def _callable_range(node, region: ExecutableRegion) -> SourceRange:
118
118
  """Snapshot provider points once before mapping them to original source."""
119
- start_row, start_column = callable_source_start(node, region.language).start_point
120
- end_row, end_column = _range_end_node(node, region.language).end_point
119
+ start = callable_source_start(node, region.language)
120
+ end = _range_end_node(node, region.language)
121
121
  return SourceRange(
122
- region.original_point(start_row, start_column),
123
- region.original_point(end_row, end_column),
122
+ region.original_point_at_byte(start.start_byte),
123
+ region.original_point_at_byte(end.end_byte),
124
124
  )
125
125
 
126
126
 
@@ -272,8 +272,7 @@ def _javascript_lexical_name(node, source: bytes) -> str | None:
272
272
 
273
273
 
274
274
  def _callback_name(node, region: ExecutableRegion) -> str:
275
- row, column = node.start_point
276
- point = region.original_point(row, column)
275
+ point = region.original_point_at_byte(node.start_byte)
277
276
  return f"<callback@{point.line}:{point.byte_column}>"
278
277
 
279
278
 
@@ -2,8 +2,10 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from dataclasses import dataclass
5
+ from dataclasses import dataclass, field
6
6
  from pathlib import Path
7
+ from types import MappingProxyType
8
+ from typing import Mapping
7
9
 
8
10
 
9
11
  @dataclass(frozen=True, order=True)
@@ -82,11 +84,20 @@ class FileFacts:
82
84
  controls: tuple[ControlFlowFact, ...]
83
85
  decisions: tuple[DecisionFact, ...]
84
86
  region_count: int
87
+ reporting_path: str | None = None
85
88
 
86
89
 
87
90
  @dataclass(frozen=True)
88
91
  class AnalysisFacts:
89
92
  files: tuple[FileFacts, ...]
93
+ _reporting_paths: Mapping[Path, str] = field(init=False, repr=False, compare=False)
94
+
95
+ def __post_init__(self) -> None:
96
+ object.__setattr__(self, "_reporting_paths", MappingProxyType({
97
+ file.path: file.reporting_path
98
+ for file in self.files
99
+ if file.reporting_path is not None
100
+ }))
90
101
 
91
102
  @property
92
103
  def callables(self) -> tuple[CallableFact, ...]:
@@ -99,3 +110,12 @@ class AnalysisFacts:
99
110
  @property
100
111
  def decisions(self) -> tuple[DecisionFact, ...]:
101
112
  return tuple(fact for file in self.files for fact in file.decisions)
113
+
114
+ def reporting_path_for(self, path: Path, root: Path | None = None) -> str:
115
+ stored = self._reporting_paths.get(path)
116
+ if stored is not None:
117
+ return stored
118
+ try:
119
+ return path.relative_to(root).as_posix() if root is not None else path.as_posix()
120
+ except ValueError:
121
+ return path.as_posix()
@@ -5,6 +5,8 @@ from __future__ import annotations
5
5
  from dataclasses import dataclass
6
6
  from pathlib import Path
7
7
 
8
+ from ..invocation import SelectedFile
9
+
8
10
  from .adapters import extract_facts
9
11
  from .csharp_compat import corrected_csharp_root
10
12
  from .errors import ProviderUnavailableError, SyntaxAnalysisError
@@ -13,16 +15,20 @@ from .provider import ParserProvider, TreeSitterProvider
13
15
  from .regions import executable_regions, is_applicable
14
16
 
15
17
 
16
- def analyze_files(files: tuple[Path, ...] | list[Path], provider: ParserProvider | None = None) -> AnalysisFacts:
18
+ def analyze_files(files: tuple[SelectedFile, ...] | list[SelectedFile], provider: ParserProvider | None = None) -> AnalysisFacts:
17
19
  """Analyze only applicable entries from the already-resolved caller scope."""
18
20
  active_provider = provider or TreeSitterProvider()
19
- results = [_analyze_file(Path(path), active_provider) for path in files if is_applicable(Path(path))]
21
+ results = [
22
+ _analyze_file(selected.physical_path, active_provider, selected.reporting_path)
23
+ for selected in files if is_applicable(selected.physical_path)
24
+ ]
20
25
  return AnalysisFacts(tuple(results))
21
26
 
22
27
 
23
28
  @dataclass(frozen=True)
24
29
  class UnavailableAnalysis:
25
30
  path: Path
31
+ reporting_path: str
26
32
  language: str
27
33
  kind: str
28
34
  message: str
@@ -35,27 +41,27 @@ class BatchAnalysis:
35
41
 
36
42
 
37
43
  def analyze_files_for_runner(
38
- files: tuple[Path, ...] | list[Path], provider: ParserProvider | None = None,
44
+ files: tuple[SelectedFile, ...], provider: ParserProvider | None = None,
39
45
  ) -> BatchAnalysis:
40
46
  """Analyze selected files independently while retaining only known unavailable evidence."""
41
47
  active_provider = provider or TreeSitterProvider()
42
48
  results: list[FileFacts] = []
43
49
  unavailable: list[UnavailableAnalysis] = []
44
- for value in files:
45
- path = Path(value)
50
+ for selected in files:
51
+ path = selected.physical_path
46
52
  if not is_applicable(path):
47
53
  continue
48
54
  try:
49
- results.append(_analyze_file(path, active_provider))
55
+ results.append(_analyze_file(path, active_provider, selected.reporting_path))
50
56
  except (SyntaxAnalysisError, ProviderUnavailableError) as exc:
51
57
  if exc.language is None:
52
58
  raise
53
59
  kind = "syntax" if isinstance(exc, SyntaxAnalysisError) else "provider"
54
- unavailable.append(UnavailableAnalysis(path, exc.language, kind, str(exc)))
60
+ unavailable.append(UnavailableAnalysis(path, selected.reporting_path, exc.language, kind, str(exc)))
55
61
  return BatchAnalysis(AnalysisFacts(tuple(results)), tuple(unavailable))
56
62
 
57
63
 
58
- def _analyze_file(path: Path, provider: ParserProvider) -> FileFacts:
64
+ def _analyze_file(path: Path, provider: ParserProvider, reporting_path: str | None = None) -> FileFacts:
59
65
  callables = []
60
66
  controls = []
61
67
  decisions = []
@@ -83,4 +89,4 @@ def _analyze_file(path: Path, provider: ParserProvider) -> FileFacts:
83
89
  callables.extend(region_callables)
84
90
  controls.extend(region_controls)
85
91
  decisions.extend(region_decisions)
86
- return FileFacts(path, tuple(callables), tuple(controls), tuple(decisions), len(regions))
92
+ return FileFacts(path, tuple(callables), tuple(controls), tuple(decisions), len(regions), reporting_path)
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from dataclasses import dataclass
6
+ from bisect import bisect_right
6
7
  from pathlib import Path
7
8
 
8
9
  from .errors import SyntaxAnalysisError
@@ -29,21 +30,31 @@ class ExecutableRegion:
29
30
  source: bytes
30
31
  original_source: bytes
31
32
  original_byte_offset: int = 0
33
+ original_line_starts: tuple[int, ...] | None = None
34
+ local_line_starts: tuple[int, ...] | None = None
35
+
36
+ def __post_init__(self) -> None:
37
+ if self.original_line_starts is None:
38
+ object.__setattr__(self, "original_line_starts", _line_starts(self.original_source))
39
+ if self.local_line_starts is None:
40
+ object.__setattr__(self, "local_line_starts", _line_starts(self.source))
32
41
 
33
42
  def original_point(self, local_row: int, local_byte_column: int) -> SourcePoint:
34
- absolute = self.original_byte_offset + _byte_at_point(self.source, local_row, local_byte_column)
35
- prefix = self.original_source[:absolute]
36
- line = prefix.count(b"\n") + 1
37
- newline = prefix.rfind(b"\n")
38
- byte_column = absolute + 1 if newline < 0 else absolute - newline
43
+ local_offset = self.local_line_starts[local_row] + local_byte_column
44
+ return self.original_point_at_byte(local_offset)
45
+
46
+ def original_point_at_byte(self, local_byte_offset: int) -> SourcePoint:
47
+ """Map a parser byte offset without reconstructing its local row prefix."""
48
+ absolute = self.original_byte_offset + local_byte_offset
49
+ row = bisect_right(self.original_line_starts, absolute) - 1
50
+ line = row + 1
51
+ byte_column = absolute - self.original_line_starts[row] + 1
39
52
  return SourcePoint(line, byte_column, absolute)
40
53
 
41
54
  def original_range(self, node) -> SourceRange:
42
- start_row, start_column = node.start_point
43
- end_row, end_column = node.end_point
44
55
  return SourceRange(
45
- self.original_point(start_row, start_column),
46
- self.original_point(end_row, end_column),
56
+ self.original_point_at_byte(node.start_byte),
57
+ self.original_point_at_byte(node.end_byte),
47
58
  )
48
59
 
49
60
 
@@ -69,6 +80,7 @@ def _vue_regions(path: Path, source: bytes, provider: ParserProvider) -> tuple[E
69
80
  f"unable to parse {path}: Vue container syntax tree contains errors", language="vue",
70
81
  )
71
82
  regions: list[ExecutableRegion] = []
83
+ original_line_starts = _line_starts(source)
72
84
  for element in root.named_children:
73
85
  if element.type != "script_element":
74
86
  continue
@@ -83,15 +95,13 @@ def _vue_regions(path: Path, source: bytes, provider: ParserProvider) -> tuple[E
83
95
  if raw_text is not None:
84
96
  regions.append(ExecutableRegion(
85
97
  path, language, source[raw_text.start_byte:raw_text.end_byte], source, raw_text.start_byte,
98
+ original_line_starts,
86
99
  ))
87
100
  return tuple(regions)
88
101
 
89
102
 
90
- def _byte_at_point(source: bytes, row: int, column: int) -> int:
91
- position = 0
92
- for _ in range(row):
93
- position = source.index(b"\n", position) + 1
94
- return position + column
103
+ def _line_starts(source: bytes) -> tuple[int, ...]:
104
+ return (0, *(index + 1 for index, value in enumerate(source) if value == 10))
95
105
 
96
106
 
97
107
  def _attributes(start_tag, source: bytes) -> dict[str, str | None]: