@cosyte/script-utils 0.1.0 → 0.1.2
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.
- package/CHANGELOG.md +27 -0
- package/README.md +14 -12
- package/check-no-emdash.sh +46 -23
- package/package.json +1 -1
- package/phi-scan.d.ts +10 -5
- package/phi-scan.js +15 -7
package/CHANGELOG.md
CHANGED
|
@@ -12,6 +12,33 @@ pre-alpha rule. See
|
|
|
12
12
|
|
|
13
13
|
## [Unreleased]
|
|
14
14
|
|
|
15
|
+
## [0.1.2] - Unreleased
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- **`check-no-emdash.sh` refuses the en dash (U+2013) as well as the em dash** (operator decision,
|
|
20
|
+
2026-11-07). It matches the en dash in the same six forms it already matched for the em dash: the
|
|
21
|
+
literal character, its URL encoding, its JS escape and three HTML entity spellings. Its self-test
|
|
22
|
+
now also proves it matches a known en dash and passes a clean line (hyphens, a range written with
|
|
23
|
+
"to", the minus sign U+2212). Exit codes, modes and the exclusion declaration are unchanged; the
|
|
24
|
+
messages name both dashes. **A tracked file or a PR text carrying an en dash in any of those forms
|
|
25
|
+
now refuses where 0.1.1 printed OK**: write a range with "to", and rewrite a pause with a period,
|
|
26
|
+
a colon, a comma or parentheses.
|
|
27
|
+
|
|
28
|
+
## [0.1.1] - Unreleased
|
|
29
|
+
|
|
30
|
+
### Fixed
|
|
31
|
+
|
|
32
|
+
- **`phi-scan`: the per-root observation rule is answered from the WALK's reads only.** It was
|
|
33
|
+
answered from every read the run took, including the index-union reads of the bytes git carries,
|
|
34
|
+
so a scan root that was missing or empty on disk was credited whenever git tracked a file under
|
|
35
|
+
it. In a real repository every root holds tracked files, so the rule never fired for the state it
|
|
36
|
+
exists to catch. Measured before the change: two repositories with `src` emptied on disk, differing
|
|
37
|
+
only in whether `src/index.ts` was tracked, exited at the refuse code and at the clean code with
|
|
38
|
+
`OK: no hits`. **Such a root now refuses at the `refuse` code, naming it.** Those tracked files are
|
|
39
|
+
still read from the bytes git carries and a hit in them is printed before the refusal; the
|
|
40
|
+
completeness rule still counts every read, and a root the walk reads is not refused.
|
|
41
|
+
|
|
15
42
|
## [0.1.0] - Unreleased
|
|
16
43
|
|
|
17
44
|
### Changed
|
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ Zero-dependency helpers for the repo-local gate scripts in @cosyte/\* repos.
|
|
|
20
20
|
|
|
21
21
|
A gate script that exits 0 without having checked anything is worse than no gate, because the run
|
|
22
22
|
conclusion is the only thing anyone reads. Two ways of producing one turned out to be universal
|
|
23
|
-
across the
|
|
23
|
+
across the Cosyte repositories: an entrypoint guard written by hand that answers `false` for ordinary
|
|
24
24
|
invocations, and thirteen byte-distinct copies of one PHI scanner, each of which had to be fixed
|
|
25
25
|
separately when an escape was found.
|
|
26
26
|
|
|
@@ -30,7 +30,7 @@ request and a version bump.
|
|
|
30
30
|
|
|
31
31
|
## Status
|
|
32
32
|
|
|
33
|
-
`@cosyte/script-utils` is on the
|
|
33
|
+
`@cosyte/script-utils` is on the Cosyte 0.1.x line: the public API is settled and bump types follow ordinary semver.
|
|
34
34
|
|
|
35
35
|
Still moving: the `runPhiScan` option surface, which is where the per-repo axes below are still being
|
|
36
36
|
argued about, and the cross-cutting detection floor, which gains patterns as escapes are found. A new
|
|
@@ -183,8 +183,9 @@ A repository narrows WHAT IS SCANNED, and only that, through a tracked file at i
|
|
|
183
183
|
`scripts/check-no-emdash.exclude`: one entry per line, `#` comments and blank lines ignored, an entry
|
|
184
184
|
ending in `/` covering every tracked path beneath it, and every entry anchored at the repository
|
|
185
185
|
root. An entry that matches no tracked path is refused rather than ignored, because an exclusion that
|
|
186
|
-
has outlived its subject is a hole nobody is looking at. Nothing narrows WHAT IS MATCHED: the
|
|
187
|
-
banned forms are fixed in the gate.
|
|
186
|
+
has outlived its subject is a hole nobody is looking at. Nothing narrows WHAT IS MATCHED: the twelve
|
|
187
|
+
banned forms are fixed in the gate. They are the em dash (U+2014) and the en dash (U+2013), each as
|
|
188
|
+
the literal character, its URL encoding, its JS escape and three HTML entity spellings.
|
|
188
189
|
|
|
189
190
|
## Overrides
|
|
190
191
|
|
|
@@ -246,7 +247,7 @@ Is this module the file Node was pointed at, rather than one imported by somethi
|
|
|
246
247
|
|
|
247
248
|
#### Why not compare the strings
|
|
248
249
|
|
|
249
|
-
The obvious spelling is a one-liner, and several
|
|
250
|
+
The obvious spelling is a one-liner, and several Cosyte repos wrote it by hand:
|
|
250
251
|
|
|
251
252
|
```js
|
|
252
253
|
// Do not do this.
|
|
@@ -314,7 +315,7 @@ paths, and the `all`-mode sweep); reading the allow-list and the override log; t
|
|
|
314
315
|
the union of the working-tree walk with the bytes git carries at every index path, deduplicated **by
|
|
315
316
|
content** under git's own `blob <len>\0` framing; the completeness rule (a target the run enumerated
|
|
316
317
|
and never read refuses, naming the paths); the per-root observation rule (`all` mode refuses unless
|
|
317
|
-
every `scanRoots` entry yielded a file
|
|
318
|
+
every `scanRoots` entry yielded a file the WALK read, naming the starved roots); every refusal; and a
|
|
318
319
|
cross-cutting detection floor that finds a dashed SSN shape and an email at an undeclared domain over
|
|
319
320
|
every file, always.
|
|
320
321
|
|
|
@@ -359,12 +360,13 @@ because without it the sweep is the working-tree walk's word alone. A freshly sc
|
|
|
359
360
|
`git init` and commit before an `all`-mode run means anything.
|
|
360
361
|
|
|
361
362
|
**Every scan root has to produce something.** `all` mode refuses when a `scanRoots` entry yielded no
|
|
362
|
-
file
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
363
|
+
file the walk read, and names it, even when git tracks files under it: those are still read from the
|
|
364
|
+
index, but what git carries cannot vouch for a directory on disk. A root that is missing, unreadable,
|
|
365
|
+
or whose every file your read filter drops used to leave the sweep quietly narrower than its own
|
|
366
|
+
configuration said, and one productive root made the whole run look productive. If you narrow
|
|
367
|
+
`scanRoots`, this is the tier that tells you what the narrowing stopped reading. A root naming a
|
|
368
|
+
regular file is scanned as one target; one naming a symbolic link is refused rather than followed;
|
|
369
|
+
one naming a directory that cannot be listed is refused, naming the path.
|
|
368
370
|
|
|
369
371
|
**`scanRoots` bounds the WALK, not the index.** `all` mode reads the bytes git carries at every
|
|
370
372
|
tracked path, whatever your roots say, because a root list answers what is on disk under it and the
|
package/check-no-emdash.sh
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# scripts/check-no-emdash.sh
|
|
3
|
-
# Brand rule (founder directive, 2026-07-24):
|
|
3
|
+
# Brand rule (founder directive, 2026-07-24): we never use the em dash.
|
|
4
4
|
# The em dash (U+2014) reads as an AI tell, so it is banned outright across every
|
|
5
|
-
#
|
|
6
|
-
#
|
|
5
|
+
# Cosyte surface. The en dash (U+2013) is banned with it (operator decision,
|
|
6
|
+
# 2026-11-07), and this gate refuses both. Source of truth:
|
|
7
|
+
# `knowledgebase/06-brand/voice-and-tone.md`, which names COMMIT MESSAGES explicitly.
|
|
7
8
|
#
|
|
8
9
|
# THIS FILE IS THE ONE IMPLEMENTATION OF THE EM-DASH GATE FOR THIS ESTATE, and config
|
|
9
10
|
# owns it. Every other repo EXECUTES THESE EXACT BYTES and tracks no implementation of
|
|
@@ -57,8 +58,8 @@
|
|
|
57
58
|
# over a tree that was cleared rather than green over a tree nobody looked at. A gate
|
|
58
59
|
# without the sweep reds CI on arrival; a sweep without the gate lets it grow back.
|
|
59
60
|
#
|
|
60
|
-
# The fix is never to re-encode the character:
|
|
61
|
-
# colon, a comma, or parentheses.
|
|
61
|
+
# The fix is never to re-encode the character: write a range with "to", and rewrite a
|
|
62
|
+
# pause with a period, a colon, a comma, or parentheses.
|
|
62
63
|
#
|
|
63
64
|
# ---------------------------------------------------------------------------
|
|
64
65
|
# THE SURFACE. Four modes, and the exit vocabulary is CLOSED AT TWO CODES.
|
|
@@ -146,7 +147,7 @@
|
|
|
146
147
|
# hardcoded name would have excluded a consuming repo's `scripts/check-no-emdash.sh`
|
|
147
148
|
# whether or not one existed, which is an exclusion granted to a file nobody reviewed.
|
|
148
149
|
#
|
|
149
|
-
# Nothing checks the checker, so keep this file free of
|
|
150
|
+
# Nothing checks the checker, so keep this file free of either literal character: it
|
|
150
151
|
# matches by codepoint and by encoding and never spells one out.
|
|
151
152
|
# ---------------------------------------------------------------------------
|
|
152
153
|
# BINARY POSTURE. This repo scans EVERY tracked file with NO binary partition and
|
|
@@ -230,12 +231,16 @@ export LC_ALL=C.UTF-8
|
|
|
230
231
|
# Matches U+2014 as the literal character and as its encodings: %E2%80%94 (URL), the
|
|
231
232
|
# JS backslash-u escape, and the — / — / — HTML entities. The
|
|
232
233
|
# escape is not theoretical in this repo: it is what the parser-template manifest
|
|
233
|
-
# carried, and a literal-only sweep passed straight over it.
|
|
234
|
-
#
|
|
235
|
-
#
|
|
236
|
-
#
|
|
237
|
-
#
|
|
234
|
+
# carried, and a literal-only sweep passed straight over it. Matches U+2013 the same
|
|
235
|
+
# way: %E2%80%93, the backslash-u escape, and the – / – / – HTML
|
|
236
|
+
# entities.
|
|
237
|
+
#
|
|
238
|
+
# THE MATCH VOCABULARY IS FROZEN at these twelve forms, six for each dash. A consumer
|
|
239
|
+
# may narrow WHAT IS SCANNED through the declaration above; nothing may narrow WHAT IS
|
|
240
|
+
# MATCHED, and widening it is a change every consuming repo inherits at once and is
|
|
241
|
+
# specced as one. The en dash's six were that change (operator decision, 2026-11-07).
|
|
238
242
|
PATTERN='\x{2014}|%E2%80%94|\\u2014|—|—|—'
|
|
243
|
+
PATTERN+='|\x{2013}|%E2%80%93|\\u2013|–|–|–'
|
|
239
244
|
|
|
240
245
|
# The declaration's path, relative to the top level of the repo under scan. Deliberately
|
|
241
246
|
# NOT relative to this file: in a consuming repo this file lives under `node_modules/`
|
|
@@ -671,10 +676,11 @@ fi
|
|
|
671
676
|
|
|
672
677
|
if [ "$MODE" = files ] || [ "$MODE" = stdin ]; then
|
|
673
678
|
# SELF-TEST: prove the scanner can still MATCH what it is meant to catch before any
|
|
674
|
-
# clean result is believed
|
|
675
|
-
#
|
|
676
|
-
#
|
|
677
|
-
#
|
|
679
|
+
# clean result is believed, and that it leaves alone what the rule allows. `printf`
|
|
680
|
+
# emits U+2014, U+2013 and U+2212 as their UTF-8 bytes, so this file still never
|
|
681
|
+
# contains any of those characters. Scope the claim honestly: this proves the PATTERN
|
|
682
|
+
# compiles and matches, not that the scan reached every tracked file. The probe below
|
|
683
|
+
# and the refusals further down cover the second half.
|
|
678
684
|
if ! printf 'a\xe2\x80\x94b\n' | grep -qP "$PATTERN"; then
|
|
679
685
|
echo "ERROR: check-no-emdash - the scanner cannot match a known em dash." >&2
|
|
680
686
|
echo " grep -P is unavailable, not in UTF-8 mode (LC_ALL=${LC_ALL}), or has" >&2
|
|
@@ -683,6 +689,22 @@ if [ "$MODE" = files ] || [ "$MODE" = stdin ]; then
|
|
|
683
689
|
echo " Refusing to report a clean tree on a scanner that cannot see." >&2
|
|
684
690
|
exit 1
|
|
685
691
|
fi
|
|
692
|
+
if ! printf 'a\xe2\x80\x93b\n' | grep -qP "$PATTERN"; then
|
|
693
|
+
echo "ERROR: check-no-emdash - the scanner cannot match a known en dash." >&2
|
|
694
|
+
echo " grep -P is unavailable, not in UTF-8 mode (LC_ALL=${LC_ALL}), or has" >&2
|
|
695
|
+
echo " been forced to basic regular expressions, under which the alternations" >&2
|
|
696
|
+
echo " in PATTERN are literals and match nothing." >&2
|
|
697
|
+
echo " Refusing to report a clean tree on a scanner that cannot see." >&2
|
|
698
|
+
exit 1
|
|
699
|
+
fi
|
|
700
|
+
# The clean fixture: hyphens, a range written with "to", and the minus sign (U+2212),
|
|
701
|
+
# none of which the rule bans. A scanner that matched it would fail every tree, so its
|
|
702
|
+
# findings could not be told from noise.
|
|
703
|
+
if printf 'a-b, 2 to 3 tiers, \xe2\x88\x921\n' | grep -qP "$PATTERN"; then
|
|
704
|
+
echo "ERROR: check-no-emdash - the scanner matched clean text (hyphens and a minus sign)." >&2
|
|
705
|
+
echo " Refusing to report findings from a scanner that flags what the rule allows." >&2
|
|
706
|
+
exit 1
|
|
707
|
+
fi
|
|
686
708
|
|
|
687
709
|
# SCANNER VISIBILITY PROBE: prove the scanner can still READ a file before believing a
|
|
688
710
|
# word it says about one. The self-test above asserts what the tool MATCHES; this
|
|
@@ -708,7 +730,7 @@ if [ "$MODE" = files ] || [ "$MODE" = stdin ]; then
|
|
|
708
730
|
echo " NUL byte and a seeded em dash: no hit on stdout, no diagnostic on stderr," >&2
|
|
709
731
|
echo " exit 0. That is a scanner that cannot see its subject, and it is" >&2
|
|
710
732
|
echo " indistinguishable from a clean tree." >&2
|
|
711
|
-
echo " The known cause is a \`grep\` interposed with -I forced (the
|
|
733
|
+
echo " The known cause is a \`grep\` interposed with -I forced (the Cosyte dev" >&2
|
|
712
734
|
echo " container ships one as a shell function; \`export -f grep\` reaches a child" >&2
|
|
713
735
|
echo " script). Run this gate with a real GNU grep." >&2
|
|
714
736
|
exit 1
|
|
@@ -719,9 +741,10 @@ fail_with_hits() {
|
|
|
719
741
|
local what="$1" hits="$2"
|
|
720
742
|
echo "$hits" >&2
|
|
721
743
|
echo "" >&2
|
|
722
|
-
echo "ERROR: check-no-emdash - em dash (U+2014, or an encoded form) found in ${what}." >&2
|
|
723
|
-
echo "
|
|
724
|
-
echo "
|
|
744
|
+
echo "ERROR: check-no-emdash - em or en dash (U+2014 or U+2013, or an encoded form) found in ${what}." >&2
|
|
745
|
+
echo " We never use em or en dashes (founder directive; 06-brand/voice-and-tone.md)." >&2
|
|
746
|
+
echo " Write a range with \"to\"; rewrite a pause with a period, colon, comma, or" >&2
|
|
747
|
+
echo " parentheses. Never re-encode it." >&2
|
|
725
748
|
exit 1
|
|
726
749
|
}
|
|
727
750
|
|
|
@@ -738,7 +761,7 @@ refuse_if_incomplete() {
|
|
|
738
761
|
if grep -qi 'binary file' "$ERRLOG"; then
|
|
739
762
|
echo "ERROR: check-no-emdash - the input named above MATCHED the banned pattern, but" >&2
|
|
740
763
|
echo " grep classifies it as binary, so the hit is reported without a line" >&2
|
|
741
|
-
echo " number. Treat it as a real em dash." >&2
|
|
764
|
+
echo " number. Treat it as a real em or en dash." >&2
|
|
742
765
|
if [ "$SCAN_MODE" = stdin ]; then
|
|
743
766
|
echo " The text piped in is not valid UTF-8. Fix the encoding of whatever" >&2
|
|
744
767
|
echo " produced it, then rewrite the sentence." >&2
|
|
@@ -749,7 +772,7 @@ refuse_if_incomplete() {
|
|
|
749
772
|
echo " has ever tracked. If it is the latter, read the BINARY POSTURE note in" >&2
|
|
750
773
|
echo " this script's header before changing anything." >&2
|
|
751
774
|
fi
|
|
752
|
-
echo "
|
|
775
|
+
echo " We never use em or en dashes (founder directive; 06-brand/voice-and-tone.md)." >&2
|
|
753
776
|
fi
|
|
754
777
|
if grep -qiv 'binary file' "$ERRLOG"; then
|
|
755
778
|
echo "ERROR: check-no-emdash - the scan reported errors, so it did not read all of" >&2
|
|
@@ -776,7 +799,7 @@ if [ "$MODE" = stdin ]; then
|
|
|
776
799
|
HITS=$(grep -nP -e "$PATTERN" -- "$STDINBUF" 2>> "$ERRLOG" || true)
|
|
777
800
|
refuse_if_incomplete
|
|
778
801
|
[ -n "$HITS" ] && fail_with_hits "$LABEL" "$HITS"
|
|
779
|
-
echo "check-no-emdash: OK (no em dashes in ${LABEL})"
|
|
802
|
+
echo "check-no-emdash: OK (no em or en dashes in ${LABEL})"
|
|
780
803
|
exit 0
|
|
781
804
|
fi
|
|
782
805
|
|
|
@@ -869,6 +892,6 @@ refuse_if_incomplete
|
|
|
869
892
|
|
|
870
893
|
[ -n "$HITS" ] && fail_with_hits "the tracked files listed above" "$HITS"
|
|
871
894
|
|
|
872
|
-
echo "check-no-emdash: OK (no em dashes in ${scanned} of ${#TRACKED[@]} tracked file(s);" \
|
|
895
|
+
echo "check-no-emdash: OK (no em or en dashes in ${scanned} of ${#TRACKED[@]} tracked file(s);" \
|
|
873
896
|
"${gitlinks} gitlink(s) skipped, ${self_excluded} excluded as the implementation under" \
|
|
874
897
|
"scan, ${declared_excluded} excluded by ${DECLARATION})"
|
package/package.json
CHANGED
package/phi-scan.d.ts
CHANGED
|
@@ -159,13 +159,18 @@ export interface PhiScanConfig {
|
|
|
159
159
|
* this contract reserves for HITS FOUND. A MISSING root is skipped by the WALK, which is unchanged
|
|
160
160
|
* from the copied scanners, and is then caught by the rule below.
|
|
161
161
|
*
|
|
162
|
-
* 🛑 EVERY ROOT MUST YIELD AT LEAST ONE FILE
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
162
|
+
* 🛑 EVERY ROOT MUST YIELD AT LEAST ONE FILE THE WALK READ, OR `all` MODE REFUSES AND NAMES THE
|
|
163
|
+
* STARVED ROOTS. That is what closes the class the paragraph above used to end with: a root that
|
|
164
|
+
* contributes nothing WITHOUT SAYING SO. All three of the known members are in it - a missing
|
|
165
|
+
* root, an UNREADABLE root (reported the same way a missing one is), and a root whose every file
|
|
166
|
+
* the read filter drops, which is what a `.md` file root does under the default
|
|
167
167
|
* `isWalkReadable`. A root is a scope decision, and a scope decision that silently selected
|
|
168
168
|
* nothing is the sweep reporting on a corpus it never had.
|
|
169
|
+
*
|
|
170
|
+
* THE INDEX HALF NEVER CREDITS A ROOT. A root that is missing or empty on disk is starved even
|
|
171
|
+
* when git tracks files under it: those files are still read from the bytes git carries, and any
|
|
172
|
+
* hit in them is reported before the refusal, but what git carries cannot vouch for a directory
|
|
173
|
+
* on disk.
|
|
169
174
|
*/
|
|
170
175
|
scanRoots: readonly string[];
|
|
171
176
|
|
package/phi-scan.js
CHANGED
|
@@ -1287,14 +1287,16 @@ class PhiScan {
|
|
|
1287
1287
|
}
|
|
1288
1288
|
|
|
1289
1289
|
/**
|
|
1290
|
-
* Did this root yield at least one file
|
|
1290
|
+
* Did this root yield at least one file the WALK actually read?
|
|
1291
1291
|
*
|
|
1292
|
-
* IT IS ASKED OF
|
|
1293
|
-
*
|
|
1294
|
-
*
|
|
1292
|
+
* IT IS ASKED OF THE WALK'S READS, WHICH ARE EVIDENCE OF OBSERVATION RATHER THAN A PLAN TO
|
|
1293
|
+
* OBSERVE, and never of the index union's: the union reads the bytes git carries at a tracked
|
|
1294
|
+
* path, and that cannot vouch for a directory on disk. It is asked per root rather than of the
|
|
1295
|
+
* whole sweep, because the whole sweep is exactly what hides a starved root: one productive root
|
|
1296
|
+
* makes the whole sweep look productive.
|
|
1295
1297
|
*
|
|
1296
1298
|
* @param {string} root A normalised scan root.
|
|
1297
|
-
* @param {Set<string>} read The repo-relative paths
|
|
1299
|
+
* @param {Set<string>} read The repo-relative paths the walk opened.
|
|
1298
1300
|
* @returns {boolean}
|
|
1299
1301
|
*/
|
|
1300
1302
|
anyReadUnder(root, read) {
|
|
@@ -1751,6 +1753,11 @@ class PhiScan {
|
|
|
1751
1753
|
|
|
1752
1754
|
const walkFailure = sweep(targets);
|
|
1753
1755
|
if (walkFailure !== null) return walkFailure;
|
|
1756
|
+
// WHAT THE WALK READ, FROZEN BEFORE THE UNION ADDS TO `read`. The per-root observation rule is
|
|
1757
|
+
// answered from this and nothing else: the union reads what git carries at a tracked path, which
|
|
1758
|
+
// is not evidence that anything under a root exists on disk. `read` itself keeps both halves,
|
|
1759
|
+
// because the completeness rule needs every read the run took.
|
|
1760
|
+
const walkRead = new Set(read);
|
|
1754
1761
|
|
|
1755
1762
|
// THE INDEX ROUTE'S OWN REFUSALS, RAISED HERE RATHER THAN WHERE THEY ARE COMPUTED (AC-15). An
|
|
1756
1763
|
// unmerged entry or a tracked link anywhere in the index refuses the whole sweep, and the walk
|
|
@@ -1799,9 +1806,10 @@ class PhiScan {
|
|
|
1799
1806
|
// target was read; it cannot ask whether a root produced a target in the first place, and a
|
|
1800
1807
|
// root that produces none is the silently-narrowed sweep: a typo, a directory that moved, a
|
|
1801
1808
|
// root whose every file the read filter drops. One productive root makes the whole run look
|
|
1802
|
-
// productive, so the question is asked per root and answered from `
|
|
1809
|
+
// productive, so the question is asked per root and answered from `walkRead`: a root git
|
|
1810
|
+
// tracks files under and that holds nothing on disk is starved, whatever the union read there.
|
|
1803
1811
|
const starved =
|
|
1804
|
-
index === null ? [] : this.cfg.scanRoots.filter((root) => !this.anyReadUnder(root,
|
|
1812
|
+
index === null ? [] : this.cfg.scanRoots.filter((root) => !this.anyReadUnder(root, walkRead));
|
|
1805
1813
|
|
|
1806
1814
|
// Hits FIRST, so nothing below can swallow one.
|
|
1807
1815
|
this.reportHits(hits);
|