:cmd-number: 0011 :cmd-title: Governed selection and lexical-v5 :cmd-state: committed :cmd-type: Standards Track :cmd-authors: ["Vikrant Rathore", "Ronak Rathore", "Kanak Rathore"] :cmd-created: 2026-10-24 :cmd-updated: 2026-10-24 :cmd-discussion: No external discussion URL assigned :cmd-labels: ["counting","selection","verification"] Governed selection and lexical-v5 ================================= Abstract -------- CMD 0010 left two questions open: whether its corrections need a new policy name, and whether directory names such as ``build`` should decide selection. We answer both. Directory names decide only where no Git repository or ignore file governs the tree. The policy becomes ``lexical-v5``, which also adds Roff, file-name conventions for Make, Meson, and Bazel, and closing rules for Shell, YAML, and Markdown found on FreeBSD. We state the properties that the counts guarantee and check them on Linux 6.12, FreeBSD 15.1, and Chromium 156, instead of grading CCM against another counter. Motivation and scope -------------------- CCM excluded every directory named ``target``, ``node_modules``, ``.venv``, ``vendor``, ``dist``, ``build``, ``_build``, or ``__pycache__``. In Chromium, ``build/`` is hand-written source that Git tracks, and the rule removed 35,063 such files with 7.4 million program lines. A project that keeps its output in ``build/`` already says so in its ``.gitignore``. The name rule therefore only helps in a tree that says nothing, such as an unpacked archive. Comparing with scc does not settle what a correct count is. When two counters disagree, at least one is wrong; when they agree, both may be wrong in the same way. A definition with a property we can check on the input settles it. Specification ------------- Governed selection. A directory is governed when it or a directory above it, within the root or the enclosing repository, holds a ``.git``, ``.gitignore``, ``.ignore``, or ``.ccmignore``. In a governed directory the ignore rules alone decide; the name exclusions apply only to directories that are not governed. ``.git`` and ``.jj`` stay excluded everywhere. ``--no-ignore`` sets ignore files aside, so nothing is governed and the names apply again; ``--no-default-ignore`` disables the names everywhere. .. code-block:: text archive/ not governed: build/ and vendor/ are excluded build/ repo/ governed by repo/.git: .gitignore decides .gitignore /out/ build/ counted out/ excluded by the rule plain/ sub/ governed by sub/.gitignore .gitignore build/ counted Roff. Roff documents are documentation with a native policy: ``.\"`` and ``'\"`` begin a comment line, and ``\"`` and ``\#`` begin a comment after text. ``.roff``, ``.man``, ``.mdoc``, ``.ms``, ``.me``, and ``.tmac`` are Roff. A manual page ``.1`` to ``.9`` is Roff only when its first line with content is a roff request such as ``.TH`` or ``.Dd``, because single-digit extensions also name rotated logs. ``.t`` files. A ``.t`` file is a Perl test by convention, but FreeBSD also uses the extension for troff papers and pjdfstest shell scripts. Its shebang decides first, then a roff opening, and Perl otherwise. Names before suffixes. A naming convention outranks the extension. ``Makefile.inc``, ``Makefile.am``, ``Makefile.in``, ``Makefile.asm``, and their kin are Make, because the suffix names what the makefile builds; only ``.PL``, ``.pl``, ``.py``, ``.m4``, the prose suffixes, and the data suffixes name the file's own language. ``meson.build``, ``meson_options.txt``, and ``meson.options`` are Meson. A Bazel overlay such as ``zlib.BUILD`` or ``jpeg.BUILD.bazel`` is Starlark. A ``.y`` file is a yacc grammar with C comments and character literals, not Happy, which has no comment rule in the catalog. Shell. A heredoc inside a command substitution may end on the line that closes the substitution: ``EOF)``, or ``EOF`` followed by the closing backtick. A script may carry data after a top-level ``exit``, as FreeBSD's stress tests carry a C program that they extract with ``sed '1,/^EOF/d' < $0``. The shell never reads that text. When a script does not lex as a whole, we look for the last line that is ``exit`` or ``exit WORD`` in the first column and before which the script lexes cleanly, and count the nonblank lines after it as code. A script that lexes as a whole keeps its own counts. YAML and Markdown. In YAML, a ``[`` or ``{`` opens a flow collection only where a value begins, and a quote after a ``,`` opens a string only inside a flow collection or on a line that continues one. Braces and commas in a plain scalar, such as ``sed -e 's,a/${A}/b,c,'``, are text. In Markdown, a code span is text, so `` `