plan-auditor 2.4.2__tar.gz → 2.4.4__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.

Potentially problematic release.


This version of plan-auditor might be problematic. Click here for more details.

Files changed (119) hide show
  1. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/.gitignore +5 -0
  2. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/CHANGELOG.md +296 -25
  3. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/CITATION.cff +2 -2
  4. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/CONTRIBUTING.md +2 -2
  5. plan_auditor-2.4.4/PKG-INFO +290 -0
  6. plan_auditor-2.4.4/README.md +247 -0
  7. plan_auditor-2.4.4/SECURITY.md +158 -0
  8. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/SKILL.md +1 -1
  9. plan_auditor-2.4.4/bin/prepublish_gate.js +429 -0
  10. plan_auditor-2.4.4/bin/prepublish_gate_contract.test.js +285 -0
  11. plan_auditor-2.4.4/bin/prepublish_lifecycle.test.js +220 -0
  12. plan_auditor-2.4.4/bin/publish_mode_contract.test.js +208 -0
  13. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/docs/benchmark.md +22 -22
  14. plan_auditor-2.4.4/docs/check_attestation_claims.py +482 -0
  15. plan_auditor-2.4.4/docs/check_readme_size.py +151 -0
  16. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/docs/cli.md +21 -7
  17. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/docs/deployment-isolation.md +19 -9
  18. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/docs/index.md +9 -6
  19. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/docs/integrations.md +1 -1
  20. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/docs/quickstart.md +27 -26
  21. plan_auditor-2.4.4/docs/readme_size_baseline.json +15 -0
  22. plan_auditor-2.4.4/docs/release-status.md +120 -0
  23. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/docs/threat-model.md +10 -0
  24. plan_auditor-2.4.4/docs/workspace-artifacts.md +72 -0
  25. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/mkdocs.yml +2 -0
  26. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/package.json +7 -5
  27. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/pyproject.toml +1 -1
  28. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/scripts/audit_check.py +158 -150
  29. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/scripts/contract.py +3 -3
  30. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/__init__.py +1 -1
  31. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_audit_check.py +13 -13
  32. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_doc_transcripts.py +29 -16
  33. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_docs_metadata.py +87 -11
  34. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_exec_trust_gate.py +4 -4
  35. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_full_contract_hardening.py +1 -1
  36. plan_auditor-2.4.4/tests/test_hmac_check_environment.py +52 -0
  37. plan_auditor-2.4.4/tests/test_npm_registry_visibility.py +359 -0
  38. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_readme_quickstart.py +115 -0
  39. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_runtime_root_hardening.py +2 -2
  40. plan_auditor-2.4.2/PKG-INFO +0 -520
  41. plan_auditor-2.4.2/README.md +0 -477
  42. plan_auditor-2.4.2/SECURITY.md +0 -89
  43. plan_auditor-2.4.2/bin/check_tarball_contents.js +0 -124
  44. plan_auditor-2.4.2/bin/verify_installed_launcher.js +0 -196
  45. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/CODE_OF_CONDUCT.md +0 -0
  46. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/LICENSE +0 -0
  47. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/bin/launcher_contract.test.js +0 -0
  48. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/bin/plan-auditor.js +0 -0
  49. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/docs/architecture.md +0 -0
  50. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/docs/dependency-graph.md +0 -0
  51. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/docs/formal-planning.md +0 -0
  52. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/examples/fib/.plan-auditor/plan.json +0 -0
  53. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/examples/fib/fib.py +0 -0
  54. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/examples/fib/request-source.json +0 -0
  55. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/examples/fib/test_fib.py +0 -0
  56. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/hooks/README.md +0 -0
  57. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/hooks/gate_hook.py +0 -0
  58. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/index.js +0 -0
  59. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/references/plan-format.md +0 -0
  60. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/scripts/__init__.py +0 -0
  61. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/scripts/exec_trust.py +0 -0
  62. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/scripts/integrity.py +0 -0
  63. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/scripts/plan_graph.py +0 -0
  64. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/scripts/stop_gate.py +0 -0
  65. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/adversarial.py +0 -0
  66. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/agents.py +0 -0
  67. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/agents_hardening.py +0 -0
  68. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/audit_session.py +0 -0
  69. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/cli.py +0 -0
  70. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/config.py +0 -0
  71. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/contracts.py +0 -0
  72. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/control_plane.py +0 -0
  73. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/coverage.py +0 -0
  74. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/daemon.py +0 -0
  75. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/events.py +0 -0
  76. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/evidence.py +0 -0
  77. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/formal_compiler.py +0 -0
  78. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/formal_planning.py +0 -0
  79. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/formal_semantics.py +0 -0
  80. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/gate.py +0 -0
  81. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/goals.py +0 -0
  82. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/integrity.py +0 -0
  83. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/lifecycle.py +0 -0
  84. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/lock_hardening.py +0 -0
  85. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/orchestrator.py +0 -0
  86. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/plan_verifier.py +0 -0
  87. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/plans.py +0 -0
  88. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/policies.py +0 -0
  89. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/priority.py +0 -0
  90. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/request_contract.py +0 -0
  91. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/requirements.py +0 -0
  92. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/seal_migration.py +0 -0
  93. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/sealing.py +0 -0
  94. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/watchdog.py +0 -0
  95. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/supervisor/workspace.py +0 -0
  96. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/request_fixture.py +0 -0
  97. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_adversarial.py +0 -0
  98. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_agent_registry_chain.py +0 -0
  99. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_agents_gate.py +0 -0
  100. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_authenticated_integrity.py +0 -0
  101. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_cli.py +0 -0
  102. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_console_scripts.py +0 -0
  103. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_core_layers.py +0 -0
  104. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_daemon.py +0 -0
  105. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_dependency_graph.py +0 -0
  106. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_events.py +0 -0
  107. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_extra_layers.py +0 -0
  108. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_failure_injection.py +0 -0
  109. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_formal_compiler.py +0 -0
  110. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_formal_planning.py +0 -0
  111. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_formal_semantics.py +0 -0
  112. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_hooks.py +0 -0
  113. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_integration_hardening.py +0 -0
  114. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_npm_launcher.py +0 -0
  115. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_registry_lock_partial.py +0 -0
  116. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_request_contract_hardening.py +0 -0
  117. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/test_root_cause_fixes_v220.py +0 -0
  118. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/trusted_workspace.py +0 -0
  119. {plan_auditor-2.4.2 → plan_auditor-2.4.4}/tests/wheel_cli_smoke.py +0 -0
@@ -44,3 +44,8 @@ pack.json
44
44
  # mypy cache from the type ratchet job
45
45
  .mypy_cache/
46
46
  .ruff_cache/
47
+
48
+ # Upstream commit lookups cached by .github/scripts/check_action_pins.py. The
49
+ # cache exists so repeated local runs and a cold CI runner do not re-query the
50
+ # API; it is machine-local state and must never be committed.
51
+ .action-pin-cache/
@@ -2,6 +2,274 @@
2
2
 
3
3
  All notable changes to plan-auditor. Versions are published to PyPI and npm.
4
4
 
5
+ ## Unreleased
6
+
7
+ ## 2.4.4 — HMAC check subprocess boundary
8
+
9
+ ### Security
10
+
11
+ - Do not inherit `PLAN_AUDITOR_HMAC_KEY` or `PLAN_AUDITOR_HMAC_KEY_FILE`
12
+ into project-controlled behavioral-check subprocesses. The supervisor
13
+ retains these credentials to authenticate the resulting audit evidence.
14
+ - Add regression tests for both credential variables, benign environment
15
+ preservation, parent environment preservation, and the public `run_check`
16
+ path.
17
+ - Clarify that environment sanitisation is defense in depth, **not** OS
18
+ sandboxing: an untrusted child running as the supervisor's user can still
19
+ open any HMAC key file that user can read. Deliberately hostile agents need
20
+ a separately isolated, keyless check-execution identity/container.
21
+
22
+ ### Documentation
23
+
24
+ - **README reduced from 362 to 248 lines with no surface lost.** The previous
25
+ release traded a line target for coverage and stopped at 356, on the reasoning
26
+ that the layer table, command tables and artifact list were the coverage gap.
27
+ That was right about the priority and wrong about the arithmetic: the reduction
28
+ had not been attempted. Detail now lives on the docs site and the README keeps a
29
+ scannable map plus links. Measured against the same 66-surface checklist derived
30
+ from the code, **0 surfaces are undocumented**: 37 still appear in the README and
31
+ 29 moved to a named docs page.
32
+ - The L0-L14 layer table became a five-row band map. It still names all fifteen
33
+ layers, and the two facts that carry the design are now stated in the prose
34
+ rather than buried in a row: **L10 (`scripts/audit_check.py`) is the only
35
+ component that can mark a step `verified`** and **L13 (`gate.py`) is the only
36
+ one that emits a final `PASS`/`FAIL`/`UNKNOWN`**. Per-layer detail was already
37
+ in `docs/architecture.md`.
38
+ - The fourteen workspace artifacts moved to a new **`docs/workspace-artifacts.md`**,
39
+ which also records what is *not* written and why the files are separated
40
+ (append-only evidence, host-owned input separate from agent-owned state, and a
41
+ stale verdict being detectable). The README still says the tool writes under
42
+ `.plan-auditor/` and links the page.
43
+ - The full command table was already in `docs/cli.md`; the README now names the
44
+ four entry points and the five check types, and `docs/cli.md` gained an explicit
45
+ `0`/`1`/`2`/`3` exit-code legend so the codes have one canonical home.
46
+ - `## Reference` was folded into `## Documentation` rather than kept as a second
47
+ index. The heading name is unchanged on purpose: a test splits the README on it.
48
+ - The `## Use it in CI` yaml block became one prose line pointing at
49
+ `docs/integrations.md`.
50
+ - The quick start keeps the structure `tests/test_readme_quickstart.py` requires:
51
+ exactly two JSON blocks, one console block, and the same four commands. Both
52
+ plan files and the transcript were compressed using the `...` elision the test
53
+ already tolerates. **The `request_sha256` changed** because the documented
54
+ `task` string was shortened, and it was re-derived by running the walkthrough,
55
+ not computed: `d39e577eb0577d8c0c81231fdd7fc559d1c6045ecc5e5bd3a00e7e8f2f49197b`.
56
+ - `docs/index.md` now links `workspace-artifacts.md` and `release-status.md`,
57
+ which it did not, so the docs home is a real index rather than a partial one.
58
+
59
+ - **`docs/check_readme_size.py` guards against re-inflation.** It fails when
60
+ `README.md` exceeds a recorded line and word budget, **and** when any single
61
+ `## ` section exceeds its own budget, so one section cannot quietly absorb the
62
+ whole allowance. `docs/readme_size_baseline.json` holds the recorded budget
63
+ (248 lines, 1490 words) and `--update` re-records it, printing a warning when a
64
+ budget is raised rather than lowered. Verified by mutation: appending twelve
65
+ invented bullets to `Honest limits` exits 1 naming that section, and a four-line
66
+ prose expansion of `Documentation` exits 1 naming lines, words and that section.
67
+ **It is not wired into CI by this change** — adding the job means editing
68
+ `.github/workflows/`, which is outside this work's file ownership. Until it is
69
+ wired, the guard only runs when invoked by hand.
70
+
71
+ - The `2.4.3` attestation facts were re-measured rather than assumed: the PyPI
72
+ per-file provenance endpoint returns `200` for both the wheel and the sdist, and
73
+ the npm attestations endpoint returns `404`. The README keeps the two-line
74
+ statement naming both channels, and `test_readme_states_the_npm_attestation_gap`
75
+ still passes against it.
76
+
77
+ ### Fixed
78
+
79
+ - **Supply-chain claims are now measured, scoped and separated by mechanism.** The three
80
+ things that get blurred into "attested" are now named separately wherever they appear
81
+ in `README.md`, `SECURITY.md` and `docs/release-status.md`:
82
+ 1. a **digest** (`dist.integrity`, `digests.sha256`) proves the bytes match what was
83
+ published and says nothing about the build;
84
+ 2. npm's **`dist.signatures`** is a registry *transport* signature over the packument,
85
+ present for every package whether or not it was built in CI, and is never build
86
+ provenance;
87
+ 3. a **build attestation** (Sigstore/in-toto on npm, PEP 740 on PyPI) is the only one of
88
+ the three that names a workflow, repository and commit.
89
+ - **The current version was stale at `2.4.2` in the release-status claims** while `2.4.3` is
90
+ the release on both registries. Refreshed, with the npm `shasum`, integrity, file count
91
+ and unpacked size, and the PyPI wheel and sdist SHA-256, all re-measured. The npm values
92
+ were re-checked by running `npm pack` on `main` (`45fd5ee`): integrity reproduces exactly.
93
+ - **The PyPI integrity URL shape is called out explicitly**, because reading the wrong shape
94
+ is how a false negative gets reported. PyPI serves attestations **per file**, so the path
95
+ ends in `/<filename>/provenance`. `https://pypi.org/integrity/plan-auditor/2.4.3/` is not
96
+ an endpoint and returns `404`; that `404` means "no such URL", **not** "no attestation".
97
+ The per-file endpoint returns `200` with an in-toto v1 statement, predicate type
98
+ `https://docs.pypi.org/attestations/publish/v1`, publisher
99
+ `kind=GitHub, repository=Furox-Art/plan-auditor, workflow=release.yml, environment=pypi`,
100
+ whose subject digest equals the SHA-256 PyPI serves for the file.
101
+ - **The condition for npm provenance is stated as pending**, with the four facts it needs:
102
+ a trusted publisher on npmjs.com for owner `Furox-Art`, package `plan-auditor`, workflow
103
+ filename `npm-publish.yml`, and the environment the publish job declares. Nothing in this
104
+ repository needs to change. Until that record exists, npm consumers verify by digest and
105
+ the docs keep saying so.
106
+ - `SECURITY.md` gained the per-channel verification commands and the mechanism table, so a
107
+ reader can check a claim without trusting this repository.
108
+
109
+ ### Added
110
+
111
+ - **`docs/check_attestation_claims.py`** — a regression guard for supply-chain claims, with
112
+ its own negative control. It rejects any attestation claim that names no channel, that
113
+ states no definite status, that presents `dist.signatures` as provenance, or that calls a
114
+ stale version current. Run it three ways:
115
+
116
+ ```bash
117
+ python docs/check_attestation_claims.py # scan the docs
118
+ python docs/check_attestation_claims.py --online # also re-measure both registries
119
+ python docs/check_attestation_claims.py --self-test # negative control
120
+ ```
121
+
122
+ The negative control feeds the guard five deliberately false claims and fails unless all
123
+ five are rejected, plus one correct claim it must accept and two same-word-different-meaning
124
+ cases (`docs/benchmark.md` measurement provenance, `docs/formal-planning.md` source
125
+ provenance) it must not flag. A guard that cannot be shown to reject a known lie is not a
126
+ guard, so `--self-test` is part of the deliverable rather than a nicety.
127
+
128
+ It is not wired into CI, because this change set does not touch workflows. Adding one step
129
+ to `.github/workflows/plan-audit.yml` that runs
130
+ `python docs/check_attestation_claims.py --self-test && python docs/check_attestation_claims.py`
131
+ would close that; until then it runs on demand.
132
+
133
+ ### Not claimed
134
+
135
+ - No security claim is weakened anywhere. npm is still described as digest-only, and the
136
+ PyPI attestation is still described as present, because that is what the registries
137
+ return.
138
+
139
+ ## v2.4.3 - 2026-10-04
140
+
141
+ A documentation release. The README restructure and the three corrections below
142
+ land on PyPI's project page for the first time: `2.4.2`'s `long_description` is
143
+ the old 499-line README and still carries the "so it cannot drift from reality"
144
+ claim that this release removes. PyPI serves `description` per release, so only
145
+ a new release can change it.
146
+
147
+ **No behaviour change in `supervisor/`, in the deterministic core, or in the npm
148
+ launcher.** Verified against the published artifacts, not the working tree:
149
+ `supervisor/` has no commit since `311f4dc`, and the `index.js` and
150
+ `bin/plan-auditor.js` inside the PyPI `2.4.2` wheel are byte-identical to those
151
+ on `main`.
152
+
153
+ Two packaging changes do reach users. Both are already live on npm at `2.4.2`,
154
+ which was published at 16:16:46Z -- after #29 landed at 16:14:02Z -- so this is
155
+ the first release in which they reach PyPI:
156
+
157
+ - **The wheel's embedded `package.json` now declares `engines.node >=22.14.0`.**
158
+ The `2.4.2` wheel says `>=18`, because it was uploaded 2026-10-02T23:06:40Z and
159
+ therefore predates #27. Anyone copying the bundled launcher out of this wheel
160
+ onto Node 18 or 20 now gets npm's engine warning.
161
+ - **The sdist and npm tarball carry `bin/prepublish_gate.js`** in place of the
162
+ `bin/check_tarball_contents.js` and `bin/verify_installed_launcher.js` it
163
+ replaces. Both old scripts only ran under `prepublishOnly`; so does the new
164
+ one. Installed behaviour is unchanged -- what a publisher executes differs.
165
+
166
+
167
+ - **Three false claims in the README and quickstart are corrected.**
168
+ - The quick-start transcript documented `request_sha256`
169
+ `7b347f48...0db55f`. The CLI has never printed that value: `request_contract.py`
170
+ stamps `plan_contract_sha256s` into the request before hashing, so the printed
171
+ digest is not a hash of the source file. Running the documented walkthrough in
172
+ a clean virtualenv yields `d7d47e409fc1c53b9830346740bac2a20e716aefc71e7396ad3db0ebbdd837f2`.
173
+ Fixed in `README.md` and `docs/quickstart.md`. The value was unaffected by
174
+ reformatting the JSON, because the digest is taken over the parsed contract
175
+ rather than the file bytes.
176
+ - The README claimed the transcript "cannot drift from reality" because
177
+ `tests/test_readme_quickstart.py` executes it. It could. `_mask()` rewrites
178
+ every 64-hex string to `<sha256>` and the transcript check is a subset test, so
179
+ substituting `dead0000...` for the real digest left the suite green: measured
180
+ at 389 passed, 0 failed. The claim is corrected and two new tests close the gap
181
+ (see below).
182
+ - The README and `CONTRIBUTING.md` both described `examples/fib` as shipping a
183
+ "deliberately broken variant". It does not; the directory holds four files, none
184
+ of them broken. `docs/benchmark.md` is where you break it yourself, and says so.
185
+
186
+ - **`tests/test_readme_quickstart.py` can now fail on the two ways it used to
187
+ pass.** Proven by mutation against this commit.
188
+ - `test_readme_quickstart_hashes_are_not_normalised_away` compares the documented
189
+ digests against the *unmasked* real output, so a fabricated hash is rejected.
190
+ Replacing `request_sha256` with `dead0000...`: **389 passed / 0 failed before,
191
+ 1 failed after**.
192
+ - `test_readme_quickstart_json_keys_match_the_real_output` compares the JSON key
193
+ sequence at each indentation level and only tolerates a shorter sequence where
194
+ the document actually used a `...` marker. Dropping `deterministic_core` from
195
+ the `audit` block, which had no elision, is now a failure. This check caught a
196
+ real omission introduced while compressing this very README.
197
+ - A third mutation, inserting a fabricated `plan_hash`, fails both the original
198
+ subset test and the new hash test.
199
+
200
+ - **The README now explains the repository instead of only the happy path.**
201
+ Measured against a 60-surface checklist drawn from the code, coverage goes from
202
+ 14/60 to 60/60. Added: the L0-L14 layer table with the two layers that can decide
203
+ a verdict; all 11 command groups and their 17 nested actions; the other three
204
+ console scripts including `plan-auditor-formal`'s `verify`/`export-pddl`/
205
+ `make-check`; the core's `status`/`snapshot`/`rollback` modes; the `regex` check
206
+ type and the rule that `regex` and `file_exists` are non-behavioural; profiles,
207
+ run modes and the four LLM tiers; every file written under `.plan-auditor/`;
208
+ `hooks/gate_hook.py` as the single authoritative gate with no per-host adapter
209
+ files; exit codes including `3` for `UNKNOWN`; and
210
+ `references/plan-format.md`.
211
+ - Two checklist items from the audit were wrong and are documented as the code
212
+ actually is: the tiers are `NO_LLM`/`SMALL_LOCAL`/`STRONG_LOCAL`/`REMOTE`
213
+ (four, not "T1/T2/T3"), and there are no six hook adapters — `hooks/` contains
214
+ `gate_hook.py` and its README, and the per-host wiring patterns are documented
215
+ in `docs/integrations.md`.
216
+
217
+ - **The 53-line release-status block moved to `docs/release-status.md`** and is in
218
+ the mkdocs navigation. Almost all of it describes one version number and would be
219
+ wrong at the next release. The README keeps two lines, and keeps them honest
220
+ rather than dropping the substance: `2.4.2` is current on both registries, npm
221
+ has no provenance attestation and returns `404` for one, and PyPI publishes with a
222
+ PEP 740 attestation. `test_readme_states_the_npm_attestation_gap` still passes
223
+ against the shortened text, so the move did not cost the supply-chain disclosure.
224
+
225
+ - **Sections that GitHub or the docs already render are gone from the README:**
226
+ the inline `Troubleshooting` block (a 158-line per-error guide lives in
227
+ `docs/quickstart.md`), the standalone `npm` section, `Project links`, and
228
+ `License`. README length falls from 499 to 356 lines.
229
+
230
+ - **Two doc tests were updated because they pinned text that moved, not because
231
+ they were inconvenient.** `test_readme_adoption_region_covers_the_essentials`
232
+ used `## Troubleshooting` as its region sentinel; the sentinel is now
233
+ `## Documentation`, and the ordering assertions it exists to protect are
234
+ unchanged. `test_doc_transcripts.py` no longer requires the README to carry a
235
+ failing run, but now also requires the README to link the page that does, and
236
+ that page to still document the most common failure.
237
+
238
+ - **A new test keeps the deleted troubleshooting reachable.**
239
+ `test_readme_points_at_the_full_troubleshooting_page` fails if the README stops
240
+ linking `docs/quickstart.md`, or if that page stops documenting
241
+ `"request contract is not activated"`.
242
+
243
+ - **A successful npm publish is no longer reported as a failed one.** Run
244
+ 37136117550 published `plan-auditor@2.4.2` and then failed its own
245
+ verification step one second later with `ERROR: npm reports 'nothing',
246
+ expected 2.4.2`. `npm publish` returns when the registry's *write* path accepts
247
+ the upload, while clients read from a CDN that converges asynchronously; the
248
+ run's own timestamps show the window, with the probe at 16:15:10Z against a
249
+ registry `time["2.4.2"]` of 16:16:46Z. The verification step now polls with a
250
+ growing backoff over a bounded budget — 12 attempts, ~200s of waiting, first
251
+ match wins — and a version that never appears still fails closed with a
252
+ `::warning::` explaining what to check. Both directions are covered by
253
+ `tests/test_npm_registry_visibility.py`.
254
+ - **The poll queries the registry over HTTP instead of `npm view`.** `npm view`'s
255
+ stdout is not a stable contract, its on-disk HTTP cache can answer from state
256
+ staler than the registry, and it inherits `npm_config_*` and `NODE_AUTH_TOKEN`
257
+ from the environment. `GET /<package>/<version>` is exactly what an
258
+ independent reader requests, with no cache in between.
259
+ - **Documentation now matches the registries.** `README.md`, `SECURITY.md` and
260
+ `docs/index.md`, `docs/quickstart.md`, `docs/integrations.md` no longer say npm
261
+ is unpublished or that the published builds are behind `main`. `2.4.2` is on
262
+ both registries; `2.4.0` and `2.4.1` carried the defects and `2.4.2` is the
263
+ fixed release.
264
+ - **The attestation story is stated per registry, from the registries themselves.**
265
+ PyPI `2.4.2` carries a PEP 740 provenance attestation. npm `2.4.2` does **not**:
266
+ the attestations endpoint returns `404` and the packument has no `provenance`
267
+ field, because it was published in token mode, which cannot mint one. The npm
268
+ `dist.signatures` block is npm's own signature over the packument and is not
269
+ described as provenance.
270
+ - **The npm badge is retained** only after confirming the registry's `latest`
271
+ (`2.4.2`) matches PyPI's version (`2.4.2`).
272
+
5
273
  ## v2.4.2 - 2026-10-03
6
274
 
7
275
  - **npm publishing is restored, and `2.4.2` exists because the published `2.4.1`
@@ -11,7 +279,7 @@ All notable changes to plan-auditor. Versions are published to PyPI and npm.
11
279
  workspace directory resolves `.` against the *installed package directory* and
12
280
  reports `plan yok: .../node_modules/plan-auditor/.plan-auditor/plan.json`. The
13
281
  launcher starts and an absolute workspace path works, so the failure is silent
14
- and looks authoritative — it audits the wrong tree. `2.4.1` cannot be
282
+ and looks authoritative — it audits the wrong tree. `2.4.1` cannot be
15
283
  republished because npm versions are immutable, hence the patch bump.
16
284
  - **The launcher now runs the CLI in the caller's working directory.** `index.js`
17
285
  keeps `process.cwd()` and prepends the package directory to `PYTHONPATH`
@@ -20,9 +288,13 @@ All notable changes to plan-auditor. Versions are published to PyPI and npm.
20
288
  - **`npm publish` runs again.** The previous commit replaced the publish step
21
289
  with `echo "npm publishing is disabled" && exit 0`, so the workflow reported
22
290
  success while publishing nothing. Publishing is back, gated on the version not
23
- already existing on the registry, using OIDC trusted publishing with
24
- `npm publish --provenance`. `NPM_TOKEN` remains available as an explicitly
25
- documented fallback only.
291
+ already existing on the registry, and selectable between OIDC trusted
292
+ publishing and an `NPM_TOKEN` fallback that must be requested explicitly.
293
+ Correction: `2.4.2` itself was published in **token mode** — the run log
294
+ records `selected publish mode: token` — so it carries **no** provenance
295
+ attestation. The attestation endpoint for `plan-auditor@2.4.2` returns `404`
296
+ and the packument has no `provenance` field. Only PyPI publishes with
297
+ attestation, via trusted publishing.
26
298
  - **The publish path proves the artifact works before uploading it.** The gate
27
299
  packs the tarball, installs it into a throwaway directory, and runs the
28
300
  *installed* `bin/plan-auditor.js` from an unrelated working directory against a
@@ -32,12 +304,11 @@ All notable changes to plan-auditor. Versions are published to PyPI and npm.
32
304
  `.github/pypi-release-trigger` on `main` publishes the same version to both
33
305
  registries, so the two cannot drift apart.
34
306
 
35
- ## Unreleased — OSS visibility and onboarding
307
+ ### OSS visibility and onboarding (shipped in `2.4.2`)
36
308
 
37
309
  Documentation and project-metadata work only. No behaviour in the supervisor, the
38
- deterministic core or the npm launcher changed, and the version numbers in
39
- `pyproject.toml`, `package.json`, `SKILL.md` and `CITATION.cff` are untouched at
40
- `2.4.1` — a release owner must bump them for any of this to reach a registry.
310
+ deterministic core or the npm launcher changed. This work was merged before the
311
+ `2.4.2` release commit, so it is part of `2.4.2` rather than still pending.
41
312
 
42
313
  - **The README now states the real release status instead of implying parity.** The
43
314
  published PyPI `2.4.1` was built 2026-09-29 and npm `2.4.1` 2026-10-01, from
@@ -92,7 +363,7 @@ deterministic core or the npm launcher changed, and the version numbers in
92
363
  there is no PGP key. `CODE_OF_CONDUCT.md` moved enforcement off the public
93
364
  issue tracker, which would have exposed reporters, onto a private address, and
94
365
  its Contact section now matches what Contributor Covenant 2.1 requires.
95
- - **`CONTRIBUTING.md` documents the workflow the code actually implements** — the
366
+ - **`CONTRIBUTING.md` documents the workflow the code actually implements** — the
96
367
  real test and coverage commands, the seal and trust chain, exit codes, the
97
368
  `CHECK_TYPES` extension path, and the release procedure including the reason the
98
369
  two registries diverged.
@@ -103,15 +374,15 @@ deterministic core or the npm launcher changed, and the version numbers in
103
374
  GitHub" link, and social links for the repository, PyPI, npm and the citation
104
375
  file. Navigation is unchanged and still covers every page.
105
376
 
106
- ### Re-verified against `main` after #24
377
+ #### Re-verified against `main` after #24
107
378
 
108
379
  - **The README's release-status text was corrected against the merged code rather
109
380
  than the previous `main`.** The wheel now force-includes the Agent Skill assets
110
381
  under `plan_auditor_skill/`, so the earlier claim that a `pip` install cannot
111
382
  supply `SKILL.md`, `references/` or `hooks/` was true of the published `2.4.1`
112
383
  wheel and false of anything built from `main`. The README and
113
- `docs/integrations.md` now document both routes — a checkout, or the installed
114
- `plan_auditor_skill/` directory — with a command that prints its location, and
384
+ `docs/integrations.md` now document both routes — a checkout, or the installed
385
+ `plan_auditor_skill/` directory — with a command that prints its location, and
115
386
  the claim is scoped to the already-published build. `docs/` and `examples/` are
116
387
  still not in the wheel, which is stated as such.
117
388
  - **The npm surface was re-checked against the merged launcher, not the old one.**
@@ -158,7 +429,7 @@ that already exists on PyPI, so the metadata on `main` cannot be published witho
158
429
  a version bump. That part is unchanged by this entry.
159
430
 
160
431
  The other half has been fixed since, by #24: the npm workflow now runs a `verify`
161
- job — the launcher tests and the packed-tarball check — before publishing, and
432
+ job — the launcher tests and the packed-tarball check — before publishing, and
162
433
  refuses a version already on the registry, so the absence of any gate that let
163
434
  `2.4.0` ship a syntax error is no longer the state of the tree. `main` is also
164
435
  now protected by a ruleset with no bypass actors, so none of the required checks
@@ -167,7 +438,7 @@ can be skipped by pushing to `main`.
167
438
  **Still outstanding:** the version bump itself. Until `2.4.2` is published to both
168
439
  registries, a `pip` user keeps seeing the pre-rewrite README on the project page.
169
440
 
170
- ## v2.4.1 — PyPI 2026-09-29, npm 2026-10-01
441
+ ## v2.4.1 — PyPI 2026-09-29, npm 2026-10-01
171
442
 
172
443
  ### Published to both registries
173
444
 
@@ -199,7 +470,7 @@ registries, a `pip` user keeps seeing the pre-rewrite README on the project page
199
470
 
200
471
  - **Both npm entry points now propagate the verifier's exit code.** The fix was
201
472
  initially placed only in `index.js`, but `package.json` maps the `plan-auditor`
202
- bin to `bin/plan-auditor.js` — the file `npx plan-auditor` actually executes —
473
+ bin to `bin/plan-auditor.js` — the file `npx plan-auditor` actually executes —
203
474
  and that file discarded the child's result entirely. Verified: `node
204
475
  bin/plan-auditor.js run <failing plan>` returned `0` while `index.js` returned
205
476
  `1`. `index.js` now exposes `runPythonAndPropagate()`, which attaches the
@@ -215,9 +486,9 @@ registries, a `pip` user keeps seeing the pre-rewrite README on the project page
215
486
  - `test_docs_metadata.py` and `test_doc_transcripts.py` now check that the `bin`
216
487
  field resolves to a launcher that propagates rather than a bare spawn, and that
217
488
  documented launcher commands reference a file that exists.
218
- - **Verbatim transcripts.** The README and `docs/quickstart.md`/`docs/cli.md` failure transcripts previously showed a single collapsed `çıktı:` line while the tool actually prints a `|`-joined multi-line traceback. Both blocks now reproduce the real output line for line and state that nothing is elided.
489
+ - **Verbatim transcripts.** The README and `docs/quickstart.md`/`docs/cli.md` failure transcripts previously showed a single collapsed `çıktı:` line while the tool actually prints a `|`-joined multi-line traceback. Both blocks now reproduce the real output line for line and state that nothing is elided.
219
490
  - **Removed a fabricated transcript line from `docs/benchmark.md`:** it showed
220
- `çıktı: AssertionError` where the tool emits a full traceback. Replaced with
491
+ `çıktı: AssertionError` where the tool emits a full traceback. Replaced with
221
492
  verbatim output, plus the equivalent launcher invocation and its exit code.
222
493
  - **Transcripts are now stable across the CI matrix.** Two platform differences
223
494
  had made the documented failure output wrong somewhere: the core joins a
@@ -233,7 +504,7 @@ registries, a `pip` user keeps seeing the pre-rewrite README on the project page
233
504
  traceback that pins a version-specific frame.
234
505
  - **`.npmignore` added and `package.json` tightened:** `__pycache__` directories were still being packed despite the `files` allowlist, because the allowlist re-includes whole directories. Added `!**/__pycache__` and `!**/*.py[cod]` negation patterns and a minimal `.npmignore`. `npm pack --dry-run` now reports 59 entries / ~134 KB with zero `__pycache__`, `.venv`, or `site-packages` paths, down from 18502 entries / 29.1 MB.
235
506
 
236
- ## v2.4.0 — 2026-09-06
507
+ ## v2.4.0 — 2026-09-06
237
508
 
238
509
  - **Deterministic automatic formalization:** `plan-auditor-formalize compile` converts structured Plan Auditor requirements, coverage, dependencies, named outputs, `requires_outputs`, and deterministic checks into a conservative grounded STRIPS contract without asking an LLM to invent authoritative symbolic semantics.
239
510
  - **Independent formalization proof:** generated contracts carry a `formalization-source:<SHA256>` marker and are independently recompiled from the current plan; stale, weakened, omitted, or manually edited generated contracts are rejected even if their embedded contract SHA is recomputed.
@@ -242,7 +513,7 @@ registries, a `pip` user keeps seeing the pre-rewrite README on the project page
242
513
  - **New installed CLI:** adds `plan-auditor-formalize compile|verify`; package and skill identity advance to stable `2.4.0`.
243
514
  - **Regression coverage:** tests exercise exact recompilation, source-staleness detection, goal weakening, dropped output preconditions, fake initial requirement goals, idempotence, sealed-plan mutation refusal, and manual-contract preservation.
244
515
 
245
- ## v2.3.0 — 2026-09-06
516
+ ## v2.3.0 — 2026-09-06
246
517
 
247
518
  - **Sealed classical planning:** non-trivial multi-step plans can embed one sealed `formal_planning` contract with explicit initial facts, final goals, one grounded STRIPS-style action per Plan Auditor step, symbolic preconditions, add effects and delete effects.
248
519
  - **Native LLM-free reachability:** monotonic contracts use deterministic forward reasoning while delete-effect contracts use bounded state-space search. Exhausting the configured state budget returns UNKNOWN instead of manufacturing PASS.
@@ -253,12 +524,12 @@ registries, a `pip` user keeps seeing the pre-rewrite README on the project page
253
524
  - **Regression coverage:** dedicated formal-planning and semantic-binding tests cover reachable/unreachable contracts, delete-effect dead ends, alternate valid orderings, bounded search, PDDL sanitization, duplicate anchors, requirement omissions and formal-contract mutation.
254
525
  - **Version identity:** source/package/skill version advances to `2.3.0`, so the post-v2.2.0 formal-planning and semantic-binding code is no longer distributed under the already-published `2.2.0` identity.
255
526
 
256
- ## v2.2.0 — 2026-09-05
527
+ ## v2.2.0 — 2026-09-05
257
528
 
258
529
  - **Physical control-plane confinement:** existing `.plan-auditor`, plan, seal, request/activation and policy path components are inspected with `lstat`; symlinked parents/leaves cannot redefine the workspace trust root.
259
530
  - **Policy read confinement:** `load_config` authorizes only symlink-free workspace policy directories before policy loading; a resolved external symlink target is rejected before its files are read.
260
531
  - **Sealed scope freeze:** automatic monotonic strengthening remains available for extra deterministic checks/prerequisites, but new steps, requirements, tools, coverage assignments or declared outputs now require a new host-approved request generation.
261
- - **Safe v3→v4 migration:** `plan-auditor-migrate-seal` provides a representation-only migration path for exact full-contract v3 seals. It requires authoritative request alignment and refuses any plan-scope change.
532
+ - **Safe v3→v4 migration:** `plan-auditor-migrate-seal` provides a representation-only migration path for exact full-contract v3 seals. It requires authoritative request alignment and refuses any plan-scope change.
262
533
  - **Seal self-consistency:** v3/v4 seals validate their contract hash and criteria count on load/save before being trusted or authenticated.
263
534
  - **Streaming evidence verification:** JSONL verification, hashing and HMAC migration retain one record/chunk at a time instead of reading complete evidence/archive files into RAM.
264
535
  - **PID-aware registry locking:** registry transaction locks carry PID + random token; live owners are never evicted because of age alone, and stale cleanup requires a provably dead PID plus unchanged lock identity.
@@ -268,7 +539,7 @@ registries, a `pip` user keeps seeing the pre-rewrite README on the project page
268
539
  - **Trust-boundary documentation:** deliberate same-OS-user interference is explicitly treated as an OS isolation problem; separate account/container/VM deployment is required when that attacker is in scope.
269
540
  - **Regression coverage:** new tests cover plan/policy symlink escapes, scope expansion, config-only activation, PID-aware registry locks, streaming evidence verification and exact legacy-seal migration.
270
541
 
271
- ## v2.1.0 — 2026-09-05
542
+ ## v2.1.0 — 2026-09-05
272
543
 
273
544
  - **Aggregate multi-plan completion:** the integrated supervisor now enumerates the default plan and every safe `.plan-auditor/plans/<name>.json` plan. Global PASS requires every active plan to PASS; a passing default plan cannot hide an unfinished named plan, and a named-only workspace is no longer misclassified as `NO_PLAN`.
274
545
  - **Explicit requirement coverage:** Supervisor Mode requires explicit requirements and deterministic `covers` links from steps. Every `must`/`should` requirement must be covered; omitted user requirements, unknown coverage IDs and duplicate requirement contracts block plan approval/PASS.
@@ -290,7 +561,7 @@ registries, a `pip` user keeps seeing the pre-rewrite README on the project page
290
561
  - **Regression hardening:** dedicated failure-injection tests cover named-plan bypasses, seal-contract weakening, environment downgrade, HMAC seal tampering, invalid config/policies, path traversal, evidence races/rotation/retry history, active-log tampering, rollback cleanup, executable-bit fingerprint changes, canonical agent conflicts, missing tools and bounded verifier output.
291
562
  - **Observational final audit:** a full audit fails if a verifier mutates product workspace content, type, or mode. Verification must prove pre-existing implementation state rather than creating the claimed result during the audit itself.
292
563
 
293
- ## v2.0.2 — 2026-09-05
564
+ ## v2.0.2 — 2026-09-05
294
565
 
295
566
  - **Integrated supervisor pipeline:** new `supervisor/orchestrator.py` wires plan validation, requirements, workspace state, policies, sealing, deterministic evidence, adversarial review, completion gating, lifecycle state, and multi-agent state into one fail-closed assessment.
296
567
  - **Real hook enforcement:** `hooks/gate_hook.py` no longer trusts `status=verified` or fabricated integrity flags; PASS requires a valid seal and matching fresh full-audit evidence.
@@ -302,7 +573,7 @@ registries, a `pip` user keeps seeing the pre-rewrite README on the project page
302
573
  - **Workspace safety:** file checks and rollback are path-confined; workspace observation is read-only and uses `shutil.which()` instead of shell redirections that could create files.
303
574
  - **Daemon integration:** the background supervisor persists an integrated assessment and final gate outcome on every observation cycle.
304
575
 
305
- ## v1.1.0 — 2026-09-03
576
+ ## v1.1.0 — 2026-09-03
306
577
 
307
578
  - **Portable skill paths:** `SKILL.md` resolves auditor scripts relative to the skill directory.
308
579
  - **Hard attempt cap:** `run` refuses a step after the configured failed-attempt cap unless explicitly forced.
@@ -310,7 +581,7 @@ registries, a `pip` user keeps seeing the pre-rewrite README on the project page
310
581
  - **Snapshot / rollback:** snapshot and rollback support were introduced and recorded in evidence.
311
582
  - **Evidence rotation:** large evidence logs rotate into `.plan-auditor/archive/`.
312
583
 
313
- ## v1.0.0 — 2026-09-03
584
+ ## v1.0.0 — 2026-09-03
314
585
 
315
586
  - Initial strict plan + independent auditor Agent Skill.
316
587
  - Machine-checkable `verify` checks (`run`, `exec`, `file_exists`, `regex`, `pytest`).
@@ -21,8 +21,8 @@ authors:
21
21
  repository-code: "https://github.com/Furox-Art/plan-auditor"
22
22
  url: "https://github.com/Furox-Art/plan-auditor"
23
23
  license: MIT
24
- version: 2.4.2
25
- date-released: "2026-10-03"
24
+ version: 2.4.4
25
+ date-released: "2026-10-10"
26
26
  keywords:
27
27
  - AI coding agents
28
28
  - deterministic verification
@@ -221,7 +221,7 @@ with a non-zero code if Python cannot be started at all.
221
221
  - Every command you document must exist. `tests/test_docs_metadata.py` parses
222
222
  fenced code blocks and checks the subcommand against the real argument parser.
223
223
  - Every transcript must be copied from a real run, and any elision must say what
224
- is elided. A `çıktı:` line whose interior depends on your Python version must be
224
+ is elided. An `output:` line whose interior depends on your Python version must be
225
225
  scoped, not quoted.
226
226
  - Never add a download count, a star count, a user count or a trust badge. Link to
227
227
  the package page instead; the tests reject a copied number.
@@ -299,7 +299,7 @@ the point: nothing in the release path depends on a maintainer remembering a ste
299
299
  | `plan-auditor doctor .` | Machine-readable capability and health report. Run this first when anything misbehaves. |
300
300
  | `SKILL.md` | The Agent Skill definition loaded by skill hosts. |
301
301
  | `hooks/gate_hook.py` | The authoritative hook gate for hosts that support blocking hooks. |
302
- | `examples/fib/` | A complete, runnable two-step plan, including a deliberately broken variant. |
302
+ | `examples/fib/` | A complete, runnable two-step plan whose second step is a pytest run. |
303
303
  | `docs/` | The documentation set. Navigation is defined in `mkdocs.yml`. |
304
304
 
305
305
  ## Conduct and security