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
301 changes: 300 additions & 1 deletion .github/workflows/docs.yml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ endfunction()

if (BOOST_CAPY_MRDOCS_BUILD)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/mrdocs.cpp"
"#include <boost/capy.hpp>\n")
"#include <boost/capy.hpp>\n#include <boost/capy/test.hpp>\n")
add_library(boost_capy_mrdocs "${CMAKE_CURRENT_BINARY_DIR}/mrdocs.cpp")
boost_capy_setup_properties(boost_capy_mrdocs)
target_compile_definitions(boost_capy_mrdocs PUBLIC BOOST_CAPY_MRDOCS)
Expand Down
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`); Capy/ is ours and is tracked.
.vale/styles/Google/
.vale/styles/Vale/
20 changes: 20 additions & 0 deletions doc/.pa11yci.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"_comment": "Style Guide E4 — contrast check (light + dark), Part F.0 'a11y contrast' gate. As of Phase-2 exit the contrast subset is BLOCKING (see docs.yml Phase-2 gate). Serve doc/build/site (e.g. `npx http-server doc/build/site -p 8088`) before running pa11y-ci against these paths, or point urls at file:// paths directly. chromeLaunchConfig.executablePath below is the LOCAL default (/usr/bin/chromium); run-a11y.mjs overrides it from the PA11Y_CHROME_PATH env var when set — CI sets that to the runner's browser (ubuntu-latest ships google-chrome at /usr/bin/google-chrome, not chromium).",
"defaults": {
"timeout": 30000,
"wait": 250,
"runners": ["axe"],
"standard": "WCAG2AA",
"chromeLaunchConfig": {
"executablePath": "/usr/bin/chromium",
"args": ["--no-sandbox"]
}
},
"urls": [
"http://localhost:8088/capy/index.html",
"http://localhost:8088/capy/why-capy.html",
"http://localhost:8088/capy/quick-start.html",
"http://localhost:8088/capy/4.coroutines/4a.tasks.html",
"http://localhost:8088/capy/reference/boost/capy.html"
]
}
102 changes: 102 additions & 0 deletions doc/.vale.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
StylesPath = .vale/styles
MinAlertLevel = warning
Packages = Google
; Capy domain vocabulary: .vale/styles/config/vocabularies/Capy/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 = Capy
[*.adoc]
BasedOnStyles = Vale, Google, Capy
; 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
; used to sit here; it 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. Measured on the real corpus
; (Phase-4 blockignores task): removing that line dropped `.adoc` warning-level alerts
; 503 -> 376 (Vale.Spelling 189 -> 73, Capy.SentenceLength 140 -> 135, Capy.Terminology
; 17 -> 12, Google.Units 2 -> 1). A fingerprint-level audit attributed all but one of the
; retired findings to code.
;
; The one exception, and a second, pre-existing instance a position-independent control
; run also turned up (both confirmed in the fix-round-1 report, not "an isolated loss" as
; an earlier draft of this comment claimed): a correctly-excluded code block can suppress
; an UNRELATED, later Vale.Spelling/Google.Colons alert if the block's own text shares a
; SUBSTRING with the flagged word, and only if the block comes BEFORE the flagged prose in
; the file (a block after it has no effect; distance within the file does not matter).
; Reduced fixture: `// token` before a paragraph containing `foo_token` suppresses the
; alert; `// hello` before it does not; either half of `// zzqq_wwrr` suppresses a later
; bare `zzqq_wwrr`. This is a Vale/asciidoctor position-resolution artifact, not something
; any `BlockIgnores`/`TokenIgnores` value here controls — do not try to "fix" it with a
; config change without a fresh bite-tested fixture proving the change does something.
; Two known-affected spots as of the fix-round-1 report, neither currently flagged live by
; Vale, both still real defects to fix from the worklist rather than from a fresh Vale run:
; `stop_token` bare in prose at 9l.RunApi.adoc:171, and `Intentionally` after a colon at
; 9o.WhyNotTMC.adoc:68. If you are tempted to re-add a BlockIgnores line for source blocks:
; don't. Confirm first, with an isolated fixture, that Vale is actually failing to skip
; something.
; Ignore inline code spans (backticks) AND `cpp:target[...]` reference macros
; (the B1 conversion replaced backtick symbol spans with cpp: macros; 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 Capy does not get to
; rewrite it; 16 of the 30 Colons hits at 4bea4edf were this one idiom, all in
; header docstrings (`grep -rn 'objects:' --include='*.hpp' include` → 18; no .adoc
; page uses it). 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 one instance continues into a longer clause
; ("Shared objects: Safe for copy, comparison, and `context()`.") that the
; phrase-exact form left exposed while suppressing its 16 siblings.
; This is NOT a Google.Colons demotion, on purpose: demoting the rule would also
; hide the genuine non-idiom Colons hits. Measured after: 11 survive (8 .adoc, all
; in 9o.WhyNotTMC/9b.Separation/3b.synchronization; 3 docstring "Pass ..." hits in
; io/any_*_stream.hpp). 30 - 16 does not equal 11 because the Vocab above also
; removed 3 .adoc Colons hits — Vale treats vocabulary terms as capitalisation
; exceptions, and "Capy"/"Corosio"/"Coroutine" after a colon were never defects.
TokenIgnores = (\x60[^\x60]+\x60), (cpp:[^\s\[]*\[[^\]]*\]), ((?:Distinct|Shared) objects:)

; --- Google house-style pack: deliberately demoted, not abandoned ----------------
; Maintainer ruling (Phase 4): these eight rules encode GOOGLE's house style, not
; Capy defects, and are scoped out of Phase 4's "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 measured at 4bea4edf with `vale --output=JSON --minAlertLevel=suggestion`
; over `modules` (.adoc) and `lint/.docstrings` (header docstrings), i.e. BEFORE the
; Vocab above existed. Re-running now shows slightly lower numbers for two of them
; (Headings 597 -> 569, WordListCase 44 -> 43) because Vale treats vocabulary terms
; as exceptions to its capitalisation rules; that is a side effect of Step 1, not a
; fix, and it does not change the ruling.
;
; Google.Headings 597 .adoc / 0 docstrings — Capy writes Title Case section
; headings; Google style mandates sentence case. Retitling 597 headings is a
; user-visible house-style change, not a defect fix.
; Google.WordListCase 44 .adoc / 49 docstrings — Google's capitalisation list for
; words like "Internet"/"email"; disagrees with Boost usage, not with Part C.
; Google.EmDash 56 .adoc / 18 docstrings — bans spaced em dashes. Capy uses
; ` -- ` (AsciiDoc's em-dash form) as a deliberate typographic convention.
; Google.We 10 .adoc / 0 docstrings — bans first-person plural. The
; design essays under 9.design argue in the first person by design (D3).
; Google.FirstPerson 6 .adoc / 0 docstrings — same ruling as Google.We.
; Google.Latin 10 .adoc / 17 docstrings — bans "e.g."/"i.e."; both are
; standard in Boost reference documentation.
; Google.Quotes 12 .adoc / 2 docstrings — demands commas and periods inside
; quotation marks (US convention). Capy quotes code-like strings, where moving
; punctuation inside the quotes would misstate the string's contents.
; Google.Spacing 11 .adoc / 3 docstrings — flags spacing around punctuation
; in prose that is mostly quoted code.
;
; NOT demoted, on purpose: Google.Will (a genuine C4 signal, and the plan promotes
; C4), Google.Colons, Google.OxfordComma, Google.LyHyphens, Google.Units,
; Google.Ordinal.
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/Capy/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/Capy/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/Capy/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:Capy\.SentenceLength$'` — the
# obvious spec, by analogy with the working `vale_adoc:Capy\.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 `Capy.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 `Capy.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
40 changes: 40 additions & 0 deletions doc/.vale/styles/Capy/SimpleTense.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# 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-capy)
# 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
tokens:
- 'will\s'
- 'has been'
36 changes: 36 additions & 0 deletions doc/.vale/styles/Capy/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