Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
347 changes: 346 additions & 1 deletion .github/workflows/docs.yml

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions doc/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
node_modules/
build/
lint/.docstrings/
# Vale-managed style packages (regenerated by `vale sync`); Corosio/ is ours and is tracked.
.vale/styles/Google/
.vale/styles/Vale/
96 changes: 96 additions & 0 deletions doc/.vale.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
StylesPath = .vale/styles
MinAlertLevel = warning
; Pinned deliberately. A bare `Packages = Google` resolves to whatever release the
; feed serves at `vale sync` time, so the corpus moves underneath baseline.json and
; findings appear as NEW without a word of prose changing. Note the project also
; moved errata-ai -> vale-cli. Bump this URL on purpose, and reseed in the same change.
Packages = https://github.com/vale-cli/Google/releases/download/v0.7.1/Google.zip
; Corosio domain vocabulary: .vale/styles/config/vocabularies/Corosio/accept.txt.
; It holds genuine prose words and proper nouns ONLY. Bare C++ identifiers used as
; running text stay unlisted on purpose — they are style-guide B1 defects and must
; keep showing up as Vale.Spelling alerts until the prose is fixed.
Vocab = Corosio
[*.adoc]
BasedOnStyles = Vale, Google, Corosio
; NO BlockIgnores here, on purpose. Vale's native AsciiDoc handling (it shells out to
; asciidoctor and only lints extracted prose nodes) already excludes delimited listing
; blocks — `[source,cpp]`/`----`, bare `----`, `....` literal blocks, blocks nested in
; list items or admonitions, `role=pseudocode`/`role=external`, and callout markers are
; all skipped natively. A `BlockIgnores = (?s) *(\[source.*?----.*?----)` substitution
; does NOT additionally protect anything — it destroys the `----` delimiters before
; asciidoctor sees them, which corrupts the block structure and hands the code inside to
; the linter as if it were a paragraph. That was measured on Capy's corpus, where
; removing the line dropped `.adoc` warning-level alerts 503 -> 376; Corosio inherits the
; decision rather than re-deriving it. If you are tempted to add a BlockIgnores line for
; source blocks: don't. Confirm first, with an isolated fixture, that Vale is actually
; failing to skip something.
;
; One Vale/asciidoctor artifact to know about before chasing a missing alert: a
; correctly-excluded code block can suppress an UNRELATED, later Vale.Spelling or
; Google.Colons alert when the block's own text shares a SUBSTRING with the flagged word,
; and only when the block sits BEFORE the flagged prose in the file. Reduced fixture:
; `// token` before a paragraph containing `foo_token` suppresses the alert; `// hello`
; before it does not. This is a position-resolution artifact, not something any
; BlockIgnores/TokenIgnores value controls — do not try to "fix" it with a config change
; without a bite-tested fixture proving the change does something.
;
; Ignore inline code spans (backticks) AND `cpp:target[...]` reference macros: the B1
; conversion replaces backtick symbol spans with cpp: macros, and their symbol text must
; stay unlinted, exactly as the backtick spans were.
;
; The third clause is the fixed label of the boost-wide thread-safety idiom
; ("Distinct objects: Safe." / "Shared objects: Unsafe."). Each instance is a genuine
; Google.Colons hit, but the form is boost-wide and Corosio does not get to rewrite it;
; `grep -ro '\(Distinct\|Shared\) objects:' --include='*.hpp' include` reports 72, spread
; over io_context, resolver_results, endpoint, signal_set, tcp_acceptor, the TLS streams
; and others. Only the LABEL and its colon are blanked, so whatever follows stays fully
; linted by every other rule; the pattern deliberately does NOT spell out "Safe."/
; "Unsafe." because instances continue into longer clauses that a phrase-exact form would
; leave exposed while suppressing its siblings.
; This is NOT a Google.Colons demotion, on purpose: demoting the rule would also hide the
; genuine non-idiom Colons hits.
TokenIgnores = (\x60[^\x60]+\x60), (cpp:[^\s\[]*\[[^\]]*\]), ((?:Distinct|Shared) objects:)

; --- Google house-style pack: deliberately demoted, not abandoned ----------------
; These eight rules encode GOOGLE's house style, not Corosio defects, and are scoped out
; of the "vale clean" criterion. They are demoted to `suggestion` (below MinAlertLevel)
; rather than removed, so a curious reader can still run
; `vale --minAlertLevel=suggestion` and see them. Counts below are measured on Corosio's
; two corpora at the port commit — `.adoc` = doc/modules, docstrings =
; lint/.docstrings — and are the same ruling Capy made, re-measured here rather than
; inherited.
;
; Google.Headings — Corosio writes Title Case section headings; Google style mandates
; sentence case. Retitling every heading is a user-visible house-style change, not a
; defect fix.
; Google.WordListCase — Google's capitalisation list for words like "Internet"/"email";
; disagrees with Boost usage, not with Part C. Note Corosio's networking tutorial uses
; "Internet" heavily, so this rule is noisier here than in Capy.
; Google.EmDash — bans spaced em dashes. Corosio uses ` -- ` (AsciiDoc's em-dash form) as
; a deliberate typographic convention.
; Google.We / Google.FirstPerson — ban first-person. The tutorial and design prose
; address the reader directly by design (D1/D3).
; Google.Latin — bans "e.g."/"i.e."; both are standard in Boost reference documentation.
; Google.Quotes — demands commas and periods inside quotation marks (US convention).
; Corosio quotes code-like strings, where moving punctuation inside the quotes would
; misstate the string's contents.
; Google.Spacing — flags spacing around punctuation in prose that is mostly quoted code.
;
; NOT demoted, on purpose: Google.Will (a genuine C4 signal, and C4 is gated),
; Google.Colons, Google.OxfordComma, Google.LyHyphens, Google.Units, Google.Ordinal.
;
; Google.LyHyphens misfires on Corosio's `family-*` compounds -- `family-neutral`,
; `family-sensitive`, `family-generic`, `family-specific`. The rule targets adverb
; hyphenation (`newly-created`) and matches these only because "family" ends in "ly".
; The hyphens are correct: they are compound adjectives, not adverbs. The rule stays
; un-demoted because it catches the real thing elsewhere, so this bounded set of false
; positives is carried in baseline.json instead -- grandfathered on purpose, not by
; accident. Re-check it if the `family-*` vocabulary grows.
Google.Headings = suggestion
Google.WordListCase = suggestion
Google.EmDash = suggestion
Google.We = suggestion
Google.FirstPerson = suggestion
Google.Latin = suggestion
Google.Quotes = suggestion
Google.Spacing = suggestion
14 changes: 14 additions & 0 deletions doc/.vale/styles/Corosio/NoFluff.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
extends: existence
message: "Filler/fluff — delete or rewrite (style guide C5/C9): '%s'."
level: warning
ignorecase: true
tokens:
- simply
- basically
- essentially
- obviously
- of course
- note that
- in order to
- due to the fact that
- utilize
7 changes: 7 additions & 0 deletions doc/.vale/styles/Corosio/PartHeadings.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
extends: existence
message: "Heading uses 'Part N' ceremony instead of a descriptive title (style guide A7): '%s'."
level: warning
scope: heading
ignorecase: true
raw:
- '^Part\s+([0-9]+|[IVXLC]+)\b'
68 changes: 68 additions & 0 deletions doc/.vale/styles/Corosio/SentenceLength.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# RETIRED AS AN AUTHORITY — demoted rather than deleted, the same treatment
# .vale.ini gives the Google house-style pack. `doc/lint/sentence-length.mjs` is
# the authority for C2 on both surfaces; this rule is kept only so that
# `vale --minAlertLevel=suggestion` can still show what Vale made of a page.
# `suggestion` is below .vale.ini's `MinAlertLevel = warning`, so it no longer
# reaches baseline.json, the gate, or a default `vale modules` run.
#
# ============================================================================
# DO NOT GATE THIS RULE. `--gate 'vale_adoc:Corosio\.SentenceLength$'` — the
# obvious spec, by analogy with the working `vale_adoc:Corosio\.PartHeadings$` —
# is VACUOUS. At `suggestion` this rule never enters a Vale fingerprint set, so
# the spec matches nothing and the gate reports `gated: true, gatedNew: 0` and
# exits 0 while checking NOTHING. Measured, exactly that. That is the same
# fail-open shape as the vacuous `Corosio.PartHeadings` rule this branch already
# had to fix. Gate the script instead:
#
# --gate 'sentence_length:^C2:'
#
# which is live in docs.yml since the Phase-4 exit. Re-measured at the Phase-4
# final fix wave: EXIT=1 / gatedNew=2, both findings the grandfathered
# `when_any.hpp` refusals, so it still needs a baseline reseed before it can go
# green. (An earlier version of this comment said gatedNew=135, the figure from
# before the .adoc hard slice was worked to zero; `doc/lint/README.md` carried
# the identical staleness and was corrected, this copy was missed.)
# `^C2:` binds the HARD slice only; the design-essay
# findings are keyed `advisory-C2` and are deliberately unreachable from a
# `C2`-prefixed spec (doc/STYLE_GUIDE.md Part C2: hard in API docs, soft in
# essays).
# ============================================================================
#
# Three measured reasons this rule cannot be the authority, none fixable inside
# a Vale rule (all `cwd=doc`, vale 3.15.1, target `modules`):
#
# 1. UNDER-COUNTS. It runs after .vale.ini's `TokenIgnores` blanks inline code
# spans, so a span contributes ZERO words where a reader counts one. Three
# measurements of the size of that blind spot, all agreeing:
# * task P4-prereq, Vale with rewritten TokenIgnores, on the
# pre-BlockIgnores-fix config: 140 -> 170 (+30)
# * this task, Vale with the committed TokenIgnores, every backtick span
# (2115) and `cpp:` macro (557) outside code blocks replaced by one
# word, `--minAlertLevel=suggestion`: 135 -> 164 (+29)
# * sentence-length.mjs, spans blanked versus spans as one word, all
# slices of `.adoc`: 125 -> 152 (+27)
# An earlier version of this comment claimed "+35, measured twice" by
# substituting today's 135 for prereq's 140 and by counting words with
# Vale's tokenizer. Both were wrong; the real figure is +27 to +30.
# 2. MIS-ATTRIBUTES, which is worse: the missed block produces no alert to
# chase, so re-running to a fixpoint never finds it. The blanking corrupts
# Vale's position mapping for `scope: sentence` rules. Hand-verified case:
# `5.buffers/5b.types.adoc` holds two over-limit sentences in list items
# (27 and 34 words) and Vale reports NONE. The artifact is not confined to
# `scope: sentence` either — a `Corosio.Terminology` alert on
# `4.coroutines/4b.launching.adoc` is reported at line 25, an `include::`
# line inside a `[source,cpp]` block, when the text that matched is at
# line 68.
# 3. FALSE-POSITIVES on under-segmentation. `4.coroutines/4f.composition.adoc:93`
# is flagged as one sentence; its four real sentences are 23, 14, 11 and 6
# words. Reproduced with that paragraph alone in a file.
#
# Do NOT re-promote this to warning/error without first showing, on a fixture,
# that Vale's position mapping for `scope: sentence` is fixed. Two checkers
# reporting different C2 numbers is how a gate loses credibility.
extends: occurrence
message: "Sentence over 25 words — split it (style guide C1/C2)."
level: suggestion
scope: sentence
token: \b(\w+)\b
max: 25
48 changes: 48 additions & 0 deletions doc/.vale/styles/Corosio/SimpleTense.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Deliberately scoped to the two literal tokens doc/STYLE_GUIDE.md Part C4 names
# ("Avoid needless 'will' and 'has been'") — NOT extended to every perfect-tense
# form. What this rule does and does not see, re-measured at commit 620fdf2c with
# cwd=doc and PATH including node_modules/.bin (Vale shells out to asciidoctor for
# .adoc, and the extracted docstrings are .adoc too):
#
# `will\s` IS wrap-tolerant, and that is deliberate. Commit 30464086 changed the
# token from the space-literal `'will '` to `'will\s'`, so a `will` at the end of a
# wrapped source line now matches. Fixture proof: `The buffer will\nbe consumed.`
# is FLAGGED, Match `"will\n"`. Do not "simplify" this back to a literal space.
#
# `has been` is NOT wrap-tolerant — a known, open hole. Fixture proof: `The buffer
# has\nbeen consumed.` is NOT flagged, while the same text on one line is. It costs
# nothing today (0 occurrences of `has\s*\n\s*been` in either corpus at 620fdf2c),
# so it is recorded rather than fixed; the fix is the same one-character change
# (`has\sbeen`) if an instance ever appears.
#
# The perfect-tense family this rule deliberately excludes — 17 occurrences on the
# docstring corpus (`doc/lint/.docstrings/`), plus 4 on the `.adoc` pages:
# have been x12 (ex/this_coro.hpp x4, read_at_least.hpp x3,
# write_at_least.hpp x3, ex/thread_pool.hpp,
# write.hpp)
# has already been x3 (when_any.hpp x2, ex/async_mutex.hpp)
# has not been x1 (write_at_least.hpp)
# has now<newline>been x1 (ex/async_waker.hpp — invisible for BOTH reasons:
# an intervening adverb and a line wrap)
# (.adoc: have been x2 in 4h.lambda-captures, 9l.RunApi; has <adv> been x2 in
# 9b.Separation, why-corosio)
# Maintainer ruling: these stay excluded. Part C4 names only "will" and "has been",
# so the rule is FAITHFUL to the guide as written; extending `tokens` would be a
# style-guide change smuggled in as a lint fix, and would surface ~17 new prose
# findings at once. A future editor who wants broader coverage changes Part C4
# first, then this file.
extends: existence
message: "Avoid needless future/perfect tense — prefer present simple (style guide C4): '%s'."
level: warning
ignorecase: true
# `have been` and `had been` are the same present/past-perfect construct as
# `has been`, which C4 names explicitly. Matching only the singular left a blind
# spot a future author could write into freely: a raw grep found 8 live sites the
# rule could not see (6 in published docstrings, 2 on pages), including one CI
# surfaced only because a long single-line paragraph parses differently there.
# All 8 were fixed when these tokens were added, so the rule stays at zero.
tokens:
- 'will\s'
- 'has been'
- 'have been'
- 'had been'
36 changes: 36 additions & 0 deletions doc/.vale/styles/Corosio/Terminology.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# C10 / C.1 one-term-per-concept. Two things this rule has to get right at once,
# and it got both wrong before: it must catch the verb in every form a writer
# actually uses, and it must NOT touch API identifiers or the noun `launcher`.
#
# `ignorecase: false` plus bare stems meant only the exact lowercase stem was
# seen. Measured on a fixture: `Launch the task for execution.`, `launches it on
# the executor`, `launched`, `launching`, `Spawn`, `spawns`, `spawned`,
# `spawning`, `Fire off`, `fires off`, `Kick off`, `kicked off` and `Boxed` all
# passed; only `launch`, `cancellation token`, `cancel token` and `boxed` were
# caught. That left the majority of real C10 prose invisible to the C10 checker.
#
# `ignorecase: true` is safe here, MEASURED rather than assumed. Every
# `launch`/`spawn`-bearing identifier in the library and the pages is either
# snake_case (`launch_one`, `launch_all`, `spawn_work`, `co_spawn`,
# `launch_policies`, the snippet tag `4b_launching`) or a `launcher` compound
# (`when_any_io_launcher`, `launchable`, `relaunch`, `launchers`). `_` is a word
# character, so the `\b` after the stem already excludes the snake_case forms,
# and the inflection list below is deliberately limited to VERB endings so it
# cannot reach `launcher`. On top of that, `.vale.ini`'s `TokenIgnores` blanks
# backtick spans and `cpp:` macros, so an identifier written as code is invisible
# to this rule anyway.
#
# The noun `launcher` STAYS, and must not be flagged: it is the role name of the
# `run_async` wrapper object, and plan Task 11's approved brief for all 18
# overloads uses it — "Bind <options> to produce a launcher; invoke the launcher
# with a task to start it." The verb `launch` is the violation, the noun
# `launcher` is not. Verify both directions if you touch the pattern.
extends: substitution
message: "Use '%s' for one-term-per-concept consistency (style guide C.1)."
level: warning
ignorecase: true
swap:
'\b(launch(?:es|ed|ing)?|spawn(?:s|ed|ing)?|fire[sd]? off|firing off|kick(?:s|ed)? off|kicking off)\b': start
'\bcancellation token\b': stop token
'\bcancel token\b': stop token
'\bboxed\b': type-erased
Loading
Loading