Repository navigation
S23.22: final documentation and comment quality gate before 0.1.0 #708
Description
Parent epic: #246
A final quality gate over the written material — every .md file and every source
comment — before the first public release.
The audience is embedded engineers evaluating the library during procurement, so at
0.1.0 the documentation is part of the product rather than a support artifact. A
statement that is stale, contradicted elsewhere, or repeated in three places with
three different emphases costs the same as a defect, and is harder to find later
because nothing fails when it is wrong.
Axes
- Accuracy — does it describe what the code does now? Anything written ahead of
the implementation, or left behind by it. - Duplication — one authoritative home per piece of knowledge. Where the same
rule is stated twice, one copy becomes a link. - Repetition — the same point restated within a page, or a paragraph that adds
emphasis rather than information. - Readability — plain declarative prose. Structure that lets a reader find the
answer without reading the whole page.
Scope
docs/**and the root.mdfiles, including the community-health set.- Source comments in
Core/andPlatform/, and the@filebriefs that generate
the API reference. CLAUDE.mdandSKILL.md— internal, but they are the contract this work is
judged against, and they are public in a public repo.
Source comments are deliberately in scope here rather than under E24, so the
audit is one ticket to iterate rather than two. E24 should not pick up a parallel
comment-quality story.
Method
Findings are collected as comments on this issue. Because the audit is about
consistency across the documentation set, a fix scoped to one page cannot be judged
against that standard — so work proceeds as commits on a single branch behind a draft
PR, which runs the docs gates continuously without spending a review on a partial
state. The PR is marked ready when the set is coherent, and that is when it is read.
The issue closes when the findings list is empty, not when the first PR merges.
Out of scope
CHANGELOG.md(generated by release-please) andLICENSE.md.docs/generated/**— regenerated, not authored.- New content. This is an audit of what exists, not an authoring story.
- The pre-cut documentation edits already listed in Cut 0.1.0 release #650 — those state the release
has not happened yet and are tracked there as part of cutting 0.1.0. - API reference rendering and navigation — S23.05 (S23.05: stamp the version the documentation describes #251) and S23.07 (S23.07: Landing page and version switcher #253).
Acceptance
- Every finding on the list is resolved, or explicitly declined with a recorded
reason. markdownlint-cli2clean, and thedocs-buildandanalyze-markdownlanes green.- No statement in the audited set contradicts another, and each rule has one
authoritative home with links pointing at it.
Activity
DavidCozens commentedon Aug 5, 2026
First findings, from board maintenance after #707 merged.
CLAUDE.md— Project Board Membership. The board has six enabled project workflows: Auto-add sub-issues to project, Auto-close issue, Item added to project, Item closed, Pull request linked to issue, Pull request merged. Two documented rules look stale against them:addSubIssuemay already do it, making step 3 of the add-to-board recipe redundant.Done. Closing the issue does not update the Status field automatically." Item closed and Pull request merged are both enabled, and S32.02: OpenSSF Scorecard workflow + Best Practices badge #644 moved toDoneon closing without anyone setting it.Both need confirming by observation before the text is rewritten — an automation being enabled is not proof of which field it writes. Worth doing, because the current text prescribes manual steps that may be unnecessary.
Not a documentation finding, but adjacent.
issue.projectItemsin GraphQL returnstotalCount: 0for issues on this board, because the project is user-owned (DavidCozens) while the repository is org-owned (cososo-ltd). Enumerating the project's items directly works, and needs pagination — the board holds 277 items, past the 100-item page default. Anything in the docs that suggests checking board membership from the issue side would be unreliable.docs: S23.22 give each platform its own docs folder and nav tab
docs: S23.22 give each platform a Doxygen group, both ways
docs: S23.22 write the two TLS platform pages against the source
docs: S23.22 iterate the platform nav, traversal and page template
docs: S23.22 generate the platform doorways as chips
docs: S23.22 roll the platform template across the remaining eight
docs: S23.22 trim the two TLS setup pages to the wiring
docs: S23.22 name every platform the same way, in the reader's words
docs: S23.22 complete the setup pages, one shape for all ten
docs: S23.22 keep the generated back-link inside the build it is in
54 remaining items
DavidCozens commentedon Aug 12, 2026
Findings still open — the RFC compliance matrix is done
The matrix is finished and read end to end. #747, #749, #751 and #752 carry the work;
#748, #750 and #753 carry what came out of it and belong to 0.2.0. What remains on this
issue is the rest of the documentation set.
that state they carry no requirement of their own — §6.2.3.1, §6.3.5, §6.5, §7.1.4,
§7.2.5 — which exist so a reader can see those sections were considered rather than
skipped. Either the column becomes a row count, or those five are excluded and the
totals recomputed. Maintainer's decision.
applied to the matrix: the parent row carries what is true of the element, each child
row carries its own parameter, and headers carry the mechanics. §7.2 went from 177
words to 57, §7.3 from 95 to 49, RFC 5426 §3.2 from 136 to 75, RFC 5425 §4.2 from 34
to 13.
docs/iec62443.mdstructural review — everything after Control Implementation.Needs scope input: the per-substrate prose grows a block per TLS backend, and
Deployment Considerations and Architecture for Security now overlap
security/threat-model.mdandci.md. The old cipher-pinning overstatement is gone.describes a correctly wired instance, and that a component which could not be built is
reported through the error handler rather than being a compliance limit. The roles
pages and the porting guide have not been read for the same pattern.
porting.md,structured-data.md,NAMING.md,bdd.md, the integrating-* guides,CLAUDE.md,SKILL.md.build-integration.mdisparked deliberately.
misra-deviations.mdis done.a device already running FreeRTOS, lwIP, FatFs and Mbed TLS, and read as impossible
without that; em-dash density 27 in 986 words.
hardening-path.md.docs: S23.22 hold the structured-data guide to the value sink's contract
docs: S23.22 answer the review, and write the character rule down
docs: S23.22 hold the README, the working agreement and the porting g…
docs: S23.22 answer the review on the rewritten compliance pages
docs: S23.22 answer the second review round
docs: S23.22 rescope the compliance guides, and hold the BDD guide to…
DavidCozens commentedon Aug 12, 2026
Findings after the compliance-guide session
Four pull requests carry this round: #757, #759 and #760, alongside #758, which is
David's fix for a defect this audit turned up. What follows supersedes the
previous findings comment.
Closed
it and the review was satisfied, so the column stays as it is.
docs/porting.md,docs/roles/index.md,docs/structured-data.md,docs/core/index.md,docs/NAMING.md,docs/bdd.md. Audited against thecode.
core/index.mdneeded no change; its hand-maintained list of Core classesis complete today, though nothing asserts it stays so.
docs/iec62443.md. Rewritten, 2272 words to 1336. It had opened by arguingthe standard did not apply to us and then listed gaps in a column headed Gaps.
Four rows answered the wrong question: CR 6.1 described whether logging blocks
the caller where the control is about the log being readable, and CR 6.2
described transport reliability where the control is about monitoring for
intrusion, attack and fault.
docs/security/threat-model.md. Rescoped, 1752 words to 797. Inthreat-modelling terms a library is not a component, and the page asserted four
trust boundaries, two of which were admissions that no boundary existed. The
adversary catalogue and the Defended by construction list are gone; the second
had already drifted into claiming Send never blocks on a full kernel buffer,
which the Posix page contradicts.
porting.mdandroles/index.mdboth present Nulls as the porting mechanism rather than as acompliance limitation. No residue to remove.
rule added to
CLAUDE.mdin docs: S23.22 hold the README, the working agreement and the porting guide to the code #757.Declined, with reasons
packas vocabulary. Survives in six documents includingdocs/NAMING.md,where it heads a section. Removing it from
CLAUDE.mdalone would make thingsworse, and a repo-wide change is not this story's.
CLAUDE.md. It shaped decisions thissession but stays unwritten by the maintainer's decision.
SolidSyslogNullSdnaming exception. The StructuredData role's Nullbreaks the
SolidSyslogNull<Role>pattern that three documents state. Closed:no note, no rename. Do not raise it again.
Raised and resolved
FreeIfInUseheld thelock across the adapter's cleanup callback and the lwIP TCP stream blocks there,
so a FreeRTOS integrator wiring
taskENTER_CRITICALas the header thenrecommended would hang on teardown. Found by reading
docs/porting.mdagainstthe code it describes. Fixed in fix: give the config lock a context and require it to tolerate blocking #758: the lock now takes a context and is
specified as one that tolerates blocking.
Still open
builds.md,ci.md,containers.md,local-checks.md,release-process.md,error-severity.md,overview.md,docs/README.md, and thesecurity/siblings. Plus about 2,100words of community-health set,
CONTRIBUTING.md,CODE_OF_CONDUCT.md,SUPPORT.md,SECURITY.mdand the PR template, which this issue scopes in andno findings comment has mentioned before now.
Core/andPlatform/. 373 files, neverstarted. docs: write source comments in characters a UK keyboard types #760 changed characters, not content.
generally: they were justified for issues expected in 0.1.0 and that reason is
expiring. This contradicts the Link the record, not the source rule added to
CLAUDE.mdin docs: S23.22 hold the README, the working agreement and the porting guide to the code #757, so the rule is decided first and the sweep follows.build-integration.md, parked deliberately.Recorded nowhere else
Platform/PlusFat/has no compile-time sector-size check. S21.04: BlockDevice reports its own block size + single SOLIDSYSLOG_FILE_BLOCK_SIZE tunable #527's acceptanceasked for a
FF_MAX_SSfloor check on the FAT backends; onlySolidSyslogFatFsFile.chas one, and S21.04: BlockDevice reports its own block size + single SOLIDSYSLOG_FILE_BLOCK_SIZE tunable #527 is closed on 0.1.0. Not investigated, and may have been a
conscious scope change.
(
size_t* bytesRead) and anOutsuffix (uint8_t* keyOut). TheoutXrule inNAMING.mddescribed neither, had no uptake since May, and its only examplenamed a function that does not exist, so it has been deleted. Whether the two
conventions should converge is open.
docs: write source comments in characters a UK keyboard types (#760)
docs: take the CodeRabbit findings on #764, and drop the template legacy
docs: S23.22 audit the remaining pages, and resolve published root do…
DavidCozens commentedon Aug 13, 2026
Batch 5 closed, and Batch 6 deliberately scoped down
#764 carries this round. It supersedes the "Still open" section of the previous
comment on Batches 5 and the reference sweep.
Closed
builds.md,ci.md,containers.md,local-checks.md,release-process.md,error-severity.md,overview.md,docs/README.mdand thesecurity/siblings, held to the workflows, the presetsand the headers they describe.
builds.md,overview.mdandrelease-process.mdneeded no change.
had mentioned:
CONTRIBUTING.md,CODE_OF_CONDUCT.md,SUPPORT.md,SECURITY.mdand the pull-request template. All accurate; no change needed.
CLAUDE.md: an issue is linked while its work is outstanding, and when it closesthe prose is read against the code before either is deleted — a fixed divergence
takes prose and link out together, an issue closed as not planned takes only the
link. Source comments are held to this more strictly than documentation. Nine
closed-issue references removed; every reference left in
docs/points at an open0.2.0 issue. The MISRA deviation register keeps its provenance links by decision.
What was wrong
error-severity.mdnamed three error categories that are not symbols.SolidSyslog.hdocumentedSERVICE_HALTEDagainst aSolidSyslogDiscardPolicy_Haltthat does not exist; the enumerator is
SOLIDSYSLOG_DISCARD_POLICY_HALT.README.md, which is not published to thesite at all.
at-rest-cryptography.mdtied the two AES-GCM policies to host and embedded targetsrespectively; the choice is which crypto library the build links, and
integration-linux-mbedtlsruns Mbed TLS on Linux.containers.mddescribed the retired hello-world ELF and abehaveservice that isbehave-linux;sbom.mdsaid container digests live incontainers.md, which holdstags by design;
local-checks.mdcounted two IWYU lanes where there are three.and a line-of-C figure in
ci.md, and a CI wall-clock estimate inlocal-checks.md.Also settled
Links to published root documents. A page under
docs/names the root file by itsrepo-relative path, and
hooks/source_links.pyre-aims it at the published page atbuild time instead of rewriting it out to GitHub. The source form works on GitHub and
in a clone; the site resolves it internally. Ten hand-written site paths, five of them
predating this work, are now uniform.
The repository is no longer described as a template. One vestigial line in
CLAUDE.mdtold a reader cloning the template to reconfigure branch protection.Batch 6 is narrowed, by decision
Batch 6 was scoped as source comments across
Core/andPlatform/— 373 files. Itwill not be completed exhaustively before 0.1.0. The bar for this release is
documentation that is accurate, not comments that are word perfect, and docs improve
continuously after it ships.
Done already, mechanically, across all 373 files: every
SolidSyslogsymbol named in acomment resolves to a declared symbol (one defect, above), no comment names a file that
does not exist, and closed-issue references are gone.
What remains, and is the whole of the intended pass:
error is silent, unreported, or safely degraded — verified against the functions.
44 candidates identified; most are internal notes and will be left alone.
the duplication that actually rots, and stripping is the fix.
Explicitly out of scope for 0.1.0: adding the missing implementor halves of the
SolidSyslog<Role>Definition.hcontracts,@filebrief length variance, and any@param/@returnsweep. This is recorded so the narrowing reads as a decision.build-integration.mdremains parked.docs: S23.22 style the documentation tables, and stop Core naming a p…
DavidCozens commentedon Aug 17, 2026
Findings list is empty. #772 is the last one.
Supersedes the "Still open" and "Recorded nowhere else" sections of every previous
comment.
Closed
373 files were done before the previous comment; docs: S23.22 style the documentation tables, and stop Core naming a platform #765 carried the duplication
finding. The 43 failure-mode claims were re-derived and the integrator-facing ones
verified against the functions:
SolidSyslogBuffer.h's silent drop (theCircularBuffer write does drop and report nothing), the Mbed TLS HMAC mismatch
returning false unreported, the Posix message-queue buffer's EAGAIN silence with
every other errno surfaced, and the UDP sender swallowing an untransmittable record
as sent. All four accurate. The rest of the 43 are internal notes, left alone by the
narrowing decision. The cross-class half is machine-guarded:
scripts/check_platform_docs.pypasses.docs/build-integration.md. Read by the maintainer; no change needed. It wasparked from the start and comes off the list rather than moving to another one.
hardening-path.md. Both done since the last comment.Declined, with reasons
size_t* bytesReadalongside
uint8_t* keyOut. Dropped. Parameter names are not ABI and thedivergence costs a reader nothing.
Platform/PlusFat/. Investigated anddeclined.
FF_MAX_SSis a FatFs macro; FreeRTOS+FAT publishes no compile-timesector-size macro at all, taking the sector size as a runtime argument at disk
init, so S21.04: BlockDevice reports its own block size + single SOLIDSYSLOG_FILE_BLOCK_SIZE tunable #527's acceptance criterion was not expressible for that backend. Closing
the gap properly would mean a new
Filevtable operation so the adapter couldreport a runtime sector size to Core, existing only to second-guess a number the
integrator sets from their own media. Two things came out of the investigation and
came out of the investigation: the FatFs check covered only the tunable default,
since
SolidSyslogFileBlockDevice_CreatetakesblockSizeas a runtime parameterthat bypasses it, and the load-bearing floor - one worst-case record - is enforced
centrally in
SolidSyslogTunablesDefaults.hfor every backend. So the FatFs checkwas not earning its place either: docs: S23.22 drop the FatFs sector floor and its porting-guide example #772 removes it, along with the porting guide's
section that used it as the worked example for choosing an
#errorover a buildgate. The two FAT adapters end up the same shape, which settles the asymmetry
rather than explaining it.
Acceptance
Every finding resolved or explicitly declined.
markdownlint-cli2clean and thedocs-buildandanalyze-markdownlanes green on every PR in the series. Thedocumentation set has one authoritative home per fact, asserted by
check_platform_docs.py, by the strict anchor validation added in #747, and by thelink resolution settled in #764.
Batch 6's explicitly deferred items stand as recorded: the missing implementor halves
of the
SolidSyslog<Role>Definition.hcontracts,@filebrief length variance, andany
@param/@returnsweep. Documentation improves continuously after 0.1.0ships; none of those is a release gate.