@shrkcrft/boundaries 0.1.0-alpha.30 → 0.1.0-alpha.31
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/dist/baseline/compute-baseline.d.ts +8 -0
- package/dist/baseline/compute-baseline.d.ts.map +1 -1
- package/dist/baseline/compute-baseline.js +8 -7
- package/dist/baseline/diff-baseline.d.ts +28 -0
- package/dist/baseline/diff-baseline.d.ts.map +1 -1
- package/dist/baseline/diff-baseline.js +29 -0
- package/dist/evaluate/boundary-unit-finding.d.ts +10 -0
- package/dist/evaluate/boundary-unit-finding.d.ts.map +1 -0
- package/dist/evaluate/boundary-unit-finding.js +21 -0
- package/dist/evaluate/boundary-unit-kind.d.ts +7 -0
- package/dist/evaluate/boundary-unit-kind.d.ts.map +1 -0
- package/dist/evaluate/boundary-unit-kind.js +14 -0
- package/dist/evaluate/evaluate-boundaries.d.ts +230 -3
- package/dist/evaluate/evaluate-boundaries.d.ts.map +1 -1
- package/dist/evaluate/evaluate-boundaries.js +481 -53
- package/dist/evaluate/i-boundary-rule-settle-input.d.ts +27 -0
- package/dist/evaluate/i-boundary-rule-settle-input.d.ts.map +1 -0
- package/dist/evaluate/i-boundary-rule-settle-input.js +1 -0
- package/dist/evaluate/i-boundary-rule-settlement.d.ts +23 -0
- package/dist/evaluate/i-boundary-rule-settlement.d.ts.map +1 -0
- package/dist/evaluate/i-boundary-rule-settlement.js +1 -0
- package/dist/evaluate/i-boundary-unit-finding.d.ts +22 -0
- package/dist/evaluate/i-boundary-unit-finding.d.ts.map +1 -0
- package/dist/evaluate/i-boundary-unit-finding.js +1 -0
- package/dist/evaluate/settle-boundary-rule.d.ts +23 -0
- package/dist/evaluate/settle-boundary-rule.d.ts.map +1 -0
- package/dist/evaluate/settle-boundary-rule.js +73 -0
- package/dist/evaluate/with-boundary-rule-settlement.d.ts +11 -0
- package/dist/evaluate/with-boundary-rule-settlement.d.ts.map +1 -0
- package/dist/evaluate/with-boundary-rule-settlement.js +44 -0
- package/dist/extract/code-zones.d.ts +95 -3
- package/dist/extract/code-zones.d.ts.map +1 -1
- package/dist/extract/code-zones.js +313 -4
- package/dist/extract/extract-tokens.d.ts +30 -0
- package/dist/extract/extract-tokens.d.ts.map +1 -1
- package/dist/extract/extract-tokens.js +233 -27
- package/dist/extract/i-labeled-source.d.ts +12 -0
- package/dist/extract/i-labeled-source.d.ts.map +1 -0
- package/dist/extract/i-labeled-source.js +1 -0
- package/dist/extract/import-edges.d.ts +1 -0
- package/dist/extract/import-edges.d.ts.map +1 -1
- package/dist/extract/import-edges.js +20 -7
- package/dist/extract/inspect-source.d.ts +32 -3
- package/dist/extract/inspect-source.d.ts.map +1 -1
- package/dist/extract/inspect-source.js +50 -7
- package/dist/extract/parse-imports.d.ts +34 -12
- package/dist/extract/parse-imports.d.ts.map +1 -1
- package/dist/extract/parse-imports.js +119 -20
- package/dist/extract/scan-literals.d.ts +12 -1
- package/dist/extract/scan-literals.d.ts.map +1 -1
- package/dist/extract/scan-literals.js +15 -1
- package/dist/extract/source-liveness-request.d.ts +24 -0
- package/dist/extract/source-liveness-request.d.ts.map +1 -0
- package/dist/extract/source-liveness-request.js +45 -0
- package/dist/generated/check-provenance.d.ts.map +1 -1
- package/dist/generated/check-provenance.js +3 -1
- package/dist/generated/read-regen-tree.d.ts +16 -0
- package/dist/generated/read-regen-tree.d.ts.map +1 -0
- package/dist/generated/read-regen-tree.js +61 -0
- package/dist/generated/scan-generated.d.ts +8 -0
- package/dist/generated/scan-generated.d.ts.map +1 -1
- package/dist/generated/scan-generated.js +25 -10
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +51 -0
- package/dist/model/boundary-intended-empty-line.d.ts +10 -0
- package/dist/model/boundary-intended-empty-line.d.ts.map +1 -0
- package/dist/model/boundary-intended-empty-line.js +11 -0
- package/dist/model/boundary-markable-list.d.ts +15 -0
- package/dist/model/boundary-markable-list.d.ts.map +1 -0
- package/dist/model/boundary-markable-list.js +15 -0
- package/dist/model/boundary-rule-input-keys.d.ts +11 -0
- package/dist/model/boundary-rule-input-keys.d.ts.map +1 -0
- package/dist/model/boundary-rule-input-keys.js +29 -0
- package/dist/model/boundary-rule-input.d.ts +23 -0
- package/dist/model/boundary-rule-input.d.ts.map +1 -0
- package/dist/model/boundary-rule-input.js +1 -0
- package/dist/model/boundary-rule-key-problems.d.ts +11 -0
- package/dist/model/boundary-rule-key-problems.d.ts.map +1 -0
- package/dist/model/boundary-rule-key-problems.js +36 -0
- package/dist/model/boundary-rule-marker-problems.d.ts +26 -0
- package/dist/model/boundary-rule-marker-problems.d.ts.map +1 -0
- package/dist/model/boundary-rule-marker-problems.js +94 -0
- package/dist/model/boundary-rule-scope.d.ts +88 -0
- package/dist/model/boundary-rule-scope.d.ts.map +1 -0
- package/dist/model/boundary-rule-scope.js +175 -0
- package/dist/model/boundary-rule.d.ts +120 -5
- package/dist/model/boundary-rule.d.ts.map +1 -1
- package/dist/model/boundary-rule.js +148 -1
- package/dist/model/boundary-unit-problem-issue.d.ts +9 -0
- package/dist/model/boundary-unit-problem-issue.d.ts.map +1 -0
- package/dist/model/boundary-unit-problem-issue.js +16 -0
- package/dist/model/normalize-boundary-rule.d.ts +21 -0
- package/dist/model/normalize-boundary-rule.d.ts.map +1 -0
- package/dist/model/normalize-boundary-rule.js +62 -0
- package/dist/policy/evaluate-policy.d.ts +80 -3
- package/dist/policy/evaluate-policy.d.ts.map +1 -1
- package/dist/policy/evaluate-policy.js +152 -19
- package/dist/policy/i-policy-rule-liveness.d.ts +15 -0
- package/dist/policy/i-policy-rule-liveness.d.ts.map +1 -0
- package/dist/policy/i-policy-rule-liveness.js +1 -0
- package/dist/policy/run-policy.d.ts +1 -1
- package/dist/policy/run-policy.d.ts.map +1 -1
- package/dist/policy/run-policy.js +171 -21
- package/dist/registry/load-boundary-rules.d.ts +29 -1
- package/dist/registry/load-boundary-rules.d.ts.map +1 -1
- package/dist/registry/load-boundary-rules.js +38 -8
- package/dist/scan/glob.d.ts +90 -0
- package/dist/scan/glob.d.ts.map +1 -1
- package/dist/scan/glob.js +205 -0
- package/dist/scan/i-glob-unit-measure.d.ts +22 -0
- package/dist/scan/i-glob-unit-measure.d.ts.map +1 -0
- package/dist/scan/i-glob-unit-measure.js +1 -0
- package/dist/scan/import-pattern.d.ts +109 -0
- package/dist/scan/import-pattern.d.ts.map +1 -0
- package/dist/scan/import-pattern.js +191 -0
- package/dist/scan/node-builtin-package-names.d.ts +13 -0
- package/dist/scan/node-builtin-package-names.d.ts.map +1 -0
- package/dist/scan/node-builtin-package-names.js +25 -0
- package/dist/scan/scan-imports.d.ts +36 -3
- package/dist/scan/scan-imports.d.ts.map +1 -1
- package/dist/scan/scan-imports.js +114 -45
- package/dist/util/blank-run-hazard-finding.d.ts +34 -0
- package/dist/util/blank-run-hazard-finding.d.ts.map +1 -0
- package/dist/util/blank-run-hazard-finding.js +1 -0
- package/dist/util/blank-run-hazard.d.ts +29 -0
- package/dist/util/blank-run-hazard.d.ts.map +1 -0
- package/dist/util/blank-run-hazard.js +450 -0
- package/dist/util/dead-glob-units.d.ts +46 -0
- package/dist/util/dead-glob-units.d.ts.map +1 -0
- package/dist/util/dead-glob-units.js +116 -0
- package/dist/util/glob-list-liveness-input.d.ts +31 -0
- package/dist/util/glob-list-liveness-input.d.ts.map +1 -0
- package/dist/util/glob-list-liveness-input.js +65 -0
- package/dist/util/i-dead-glob-unit.d.ts +24 -0
- package/dist/util/i-dead-glob-unit.d.ts.map +1 -0
- package/dist/util/i-dead-glob-unit.js +1 -0
- package/dist/util/i-glob-list-units.d.ts +25 -0
- package/dist/util/i-glob-list-units.d.ts.map +1 -0
- package/dist/util/i-glob-list-units.js +1 -0
- package/dist/util/i-glob-liveness-list.d.ts +23 -0
- package/dist/util/i-glob-liveness-list.d.ts.map +1 -0
- package/dist/util/i-glob-liveness-list.js +1 -0
- package/dist/util/i-glob-liveness-request.d.ts +11 -0
- package/dist/util/i-glob-liveness-request.d.ts.map +1 -0
- package/dist/util/i-glob-liveness-request.js +1 -0
- package/dist/util/i-glob-negation.d.ts +13 -0
- package/dist/util/i-glob-negation.d.ts.map +1 -0
- package/dist/util/i-glob-negation.js +1 -0
- package/dist/util/matched-files.d.ts +22 -0
- package/dist/util/matched-files.d.ts.map +1 -0
- package/dist/util/matched-files.js +1 -0
- package/dist/util/negation-cause.d.ts +15 -0
- package/dist/util/negation-cause.d.ts.map +1 -0
- package/dist/util/negation-cause.js +21 -0
- package/dist/util/plane-scan-exclude-dirs.d.ts +17 -0
- package/dist/util/plane-scan-exclude-dirs.d.ts.map +1 -0
- package/dist/util/plane-scan-exclude-dirs.js +22 -0
- package/dist/util/read-glob-list-liveness.d.ts +20 -0
- package/dist/util/read-glob-list-liveness.d.ts.map +1 -0
- package/dist/util/read-glob-list-liveness.js +20 -0
- package/dist/util/read-scope-coverage.d.ts +90 -0
- package/dist/util/read-scope-coverage.d.ts.map +1 -0
- package/dist/util/read-scope-coverage.js +173 -0
- package/dist/util/read-scope.d.ts +14 -0
- package/dist/util/read-scope.d.ts.map +1 -0
- package/dist/util/read-scope.js +1 -0
- package/dist/util/read-selected-files.d.ts +16 -0
- package/dist/util/read-selected-files.d.ts.map +1 -0
- package/dist/util/read-selected-files.js +25 -0
- package/dist/util/settle-glob-lists.d.ts +12 -0
- package/dist/util/settle-glob-lists.d.ts.map +1 -0
- package/dist/util/settle-glob-lists.js +13 -0
- package/dist/util/unread-file-reason.d.ts +26 -0
- package/dist/util/unread-file-reason.d.ts.map +1 -0
- package/dist/util/unread-file-reason.js +26 -0
- package/dist/util/unread-file.d.ts +10 -0
- package/dist/util/unread-file.d.ts.map +1 -0
- package/dist/util/unread-file.js +1 -0
- package/dist/util/walk-files.d.ts +74 -10
- package/dist/util/walk-files.d.ts.map +1 -1
- package/dist/util/walk-files.js +137 -31
- package/dist/wiring/evaluate-wiring.d.ts +79 -5
- package/dist/wiring/evaluate-wiring.d.ts.map +1 -1
- package/dist/wiring/evaluate-wiring.js +267 -12
- package/dist/wiring/explain-wiring.d.ts +49 -5
- package/dist/wiring/explain-wiring.d.ts.map +1 -1
- package/dist/wiring/explain-wiring.js +118 -10
- package/dist/wiring/i-idiom-role-coverage.d.ts +24 -0
- package/dist/wiring/i-idiom-role-coverage.d.ts.map +1 -0
- package/dist/wiring/i-idiom-role-coverage.js +1 -0
- package/dist/wiring/i-registration-query-verdict.d.ts +38 -0
- package/dist/wiring/i-registration-query-verdict.d.ts.map +1 -0
- package/dist/wiring/i-registration-query-verdict.js +1 -0
- package/dist/wiring/i-registration-roles.d.ts +71 -0
- package/dist/wiring/i-registration-roles.d.ts.map +1 -0
- package/dist/wiring/i-registration-roles.js +1 -0
- package/dist/wiring/measure-idiom-role-coverage.d.ts +12 -0
- package/dist/wiring/measure-idiom-role-coverage.d.ts.map +1 -0
- package/dist/wiring/measure-idiom-role-coverage.js +20 -0
- package/dist/wiring/measure-registration-roles.d.ts +25 -0
- package/dist/wiring/measure-registration-roles.d.ts.map +1 -0
- package/dist/wiring/measure-registration-roles.js +124 -0
- package/dist/wiring/plan-wiring-fix.js +2 -2
- package/dist/wiring/registration-graph.d.ts +12 -0
- package/dist/wiring/registration-graph.d.ts.map +1 -1
- package/dist/wiring/registration-graph.js +16 -5
- package/dist/wiring/registration-query-verdict.d.ts +23 -0
- package/dist/wiring/registration-query-verdict.d.ts.map +1 -0
- package/dist/wiring/registration-query-verdict.js +118 -0
- package/dist/wiring/registry-query.d.ts +8 -0
- package/dist/wiring/registry-query.d.ts.map +1 -1
- package/dist/wiring/registry-query.js +12 -5
- package/dist/wiring/scan-wiring-files.d.ts +4 -2
- package/dist/wiring/scan-wiring-files.d.ts.map +1 -1
- package/dist/wiring/scan-wiring-files.js +52 -15
- package/dist/wiring/sink-imports.d.ts +11 -0
- package/dist/wiring/sink-imports.d.ts.map +1 -1
- package/dist/wiring/sink-imports.js +11 -2
- package/dist/wiring/trace-literal.d.ts +6 -0
- package/dist/wiring/trace-literal.d.ts.map +1 -1
- package/dist/wiring/trace-literal.js +5 -2
- package/dist/wiring/wiring-labeled-sources.d.ts +12 -0
- package/dist/wiring/wiring-labeled-sources.d.ts.map +1 -0
- package/dist/wiring/wiring-labeled-sources.js +20 -0
- package/package.json +2 -2
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { isNegatedGlob, UnitDeadWeight } from '@shrkcrft/core';
|
|
2
|
+
/**
|
|
3
|
+
* THE observation predicate for a gate-plane glob unit (round 13). Every
|
|
4
|
+
* gate-plane reporter — `gates coverage` / `gates try` / `quality`
|
|
5
|
+
* (`buildGateCoverage`), `policy-lint` (`runPolicyLint`), and each plane
|
|
6
|
+
* engine's rule-emptiness check (`settleGlobLists`) — builds its core
|
|
7
|
+
* `settleUnitLiveness` input here, so a glob and its marker are read one way
|
|
8
|
+
* everywhere:
|
|
9
|
+
*
|
|
10
|
+
* unit | exists | live
|
|
11
|
+
* --------------------------------------+--------+------
|
|
12
|
+
* inclusion glob, not dead | yes | yes (`it now matches N file(s)`)
|
|
13
|
+
* inclusion glob, dead, matched > 0 | yes | no (every match excluded by the list's own negations)
|
|
14
|
+
* inclusion glob, dead, matched 0 | no | no (its target does not exist)
|
|
15
|
+
* negation that excludes a file | yes | yes
|
|
16
|
+
* negation that excludes nothing | no | no
|
|
17
|
+
*
|
|
18
|
+
* `exists` is RAW target existence — it decides a MARKED unit (intended-empty,
|
|
19
|
+
* or went-live), so an acceptance never says "does not exist yet" about a glob
|
|
20
|
+
* whose files exist but are all excluded. `live` is the one dead-unit decision
|
|
21
|
+
* (`globListUnits`) negated — it decides an unmarked unit, and whether a
|
|
22
|
+
* went-live unit is effective. A glob in front of an unread file is not dead
|
|
23
|
+
* (`globListUnits`), so it reads live, never intended-empty.
|
|
24
|
+
*
|
|
25
|
+
* Advisory weight: a dead gate glob is listed and withholds the ✓, it moves
|
|
26
|
+
* the exit only under `--fail-on-dead-units`; record B (the acceptance) is
|
|
27
|
+
* emitted for any intended-empty unit.
|
|
28
|
+
*/
|
|
29
|
+
export function globListLivenessInput(request) {
|
|
30
|
+
const observations = [];
|
|
31
|
+
for (const l of request.lists) {
|
|
32
|
+
const deadBy = new Map(l.units.dead.map((d) => [d.glob, d]));
|
|
33
|
+
const excludes = new Map(l.units.negations.map((n) => [n.glob, n.excludes]));
|
|
34
|
+
const effective = new Map((l.units.measures ?? []).map((m) => [m.glob, m.effective]));
|
|
35
|
+
for (const glob of new Set(l.globs)) {
|
|
36
|
+
const dead = deadBy.get(glob);
|
|
37
|
+
const negation = isNegatedGlob(glob);
|
|
38
|
+
const exists = dead === undefined || (!dead.negation && dead.matched > 0);
|
|
39
|
+
const live = dead === undefined;
|
|
40
|
+
const count = negation ? excludes.get(glob) : live ? effective.get(glob) : dead?.matched;
|
|
41
|
+
const liveBecause = !exists
|
|
42
|
+
? undefined
|
|
43
|
+
: negation
|
|
44
|
+
? `it now excludes ${count ?? 'a'} file${count === 1 || count === undefined ? '' : 's'}`
|
|
45
|
+
: `it now matches ${count ?? 'a'} file${count === 1 || count === undefined ? '' : 's'}`;
|
|
46
|
+
observations.push({
|
|
47
|
+
list: l.list,
|
|
48
|
+
unit: glob,
|
|
49
|
+
label: l.label !== undefined ? `${l.label}: ${glob}` : glob,
|
|
50
|
+
exists,
|
|
51
|
+
live,
|
|
52
|
+
...(dead !== undefined ? { matched: dead.matched, deadReason: dead.reason } : {}),
|
|
53
|
+
...(liveBecause !== undefined ? { liveBecause } : {}),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
...(request.subject !== undefined ? { subject: request.subject } : {}),
|
|
59
|
+
unitLabel: 'globs',
|
|
60
|
+
weight: UnitDeadWeight.Advisory,
|
|
61
|
+
observations,
|
|
62
|
+
marks: request.marks,
|
|
63
|
+
deadSummary: 'select or exclude nothing',
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One glob of a gate-plane list that does nothing (`globListUnits`).
|
|
3
|
+
*
|
|
4
|
+
* An inclusion glob is dead when it selects nothing that survives the list's
|
|
5
|
+
* negations; a negation is dead when it EXCLUDES nothing from its own list's
|
|
6
|
+
* positive set. The `reason` says which, in the words every surface prints.
|
|
7
|
+
*/
|
|
8
|
+
export interface IDeadGlobUnit {
|
|
9
|
+
/** The glob as written (a negation keeps its `!`). */
|
|
10
|
+
readonly glob: string;
|
|
11
|
+
readonly negation: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Inclusion glob: the files it matched before the list's negations (0, or
|
|
14
|
+
* all of them excluded). Negation: the size of the positive set it failed to
|
|
15
|
+
* touch.
|
|
16
|
+
*/
|
|
17
|
+
readonly matched: number;
|
|
18
|
+
/**
|
|
19
|
+
* `matched 0 files`, `matches only files the list's negations exclude (N)`,
|
|
20
|
+
* or `excludes nothing — none of the N file(s) the other globs select match it`.
|
|
21
|
+
*/
|
|
22
|
+
readonly reason: string;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=i-dead-glob-unit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i-dead-glob-unit.d.ts","sourceRoot":"","sources":["../../src/util/i-dead-glob-unit.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,sDAAsD;IACtD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { IGlobUnitMeasure } from '../scan/i-glob-unit-measure.js';
|
|
2
|
+
import type { IDeadGlobUnit } from './i-dead-glob-unit.js';
|
|
3
|
+
import type { IGlobNegation } from './i-glob-negation.js';
|
|
4
|
+
/** One glob list's units, judged by `globListUnits`: the dead ones, the live negations, and how many were checked. */
|
|
5
|
+
export interface IGlobListUnits {
|
|
6
|
+
readonly dead: readonly IDeadGlobUnit[];
|
|
7
|
+
/** Negations that exclude at least one file, with the count. */
|
|
8
|
+
readonly negations: readonly IGlobNegation[];
|
|
9
|
+
/** Distinct globs (negations included) examined. */
|
|
10
|
+
readonly checked: number;
|
|
11
|
+
/**
|
|
12
|
+
* True when the list's OWN negations emptied it: its inclusion globs matched
|
|
13
|
+
* at least one file, every one of them is excluded, and no unread entry the
|
|
14
|
+
* list keeps in scope could hold a survivor. A rule over such a list that
|
|
15
|
+
* matched nothing is the author's `!` at work — not a stale selector.
|
|
16
|
+
*/
|
|
17
|
+
readonly allExcluded: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Every distinct glob's measure (`measureGlobList`: an inclusion glob's raw
|
|
20
|
+
* and effective matches, a negation's exclusions) — what a went-live unit's
|
|
21
|
+
* sentence quotes (`it now matches 3 file(s)`). Set by `globListUnits`.
|
|
22
|
+
*/
|
|
23
|
+
readonly measures?: readonly IGlobUnitMeasure[];
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=i-glob-list-units.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i-glob-list-units.d.ts","sourceRoot":"","sources":["../../src/util/i-glob-list-units.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,sHAAsH;AACtH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,CAAC;IACxC,gEAAgE;IAChE,QAAQ,CAAC,SAAS,EAAE,SAAS,aAAa,EAAE,CAAC;IAC7C,oDAAoD;IACpD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAC;CACjD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { IGlobListUnits } from './i-glob-list-units.js';
|
|
2
|
+
/**
|
|
3
|
+
* One gate-plane glob list as the liveness settle observes it (round 13).
|
|
4
|
+
*
|
|
5
|
+
* `list` is the marker ledger's `list` for these globs — `files`, `to.files`,
|
|
6
|
+
* `watchFiles`, `generatedGlob`, or a side-qualified `declared.files` when a
|
|
7
|
+
* rule reads several sources (`qualifyListPath`); the marks handed to the
|
|
8
|
+
* settle must be qualified the same way. `units` is the list judged by the one
|
|
9
|
+
* dead-unit decision (`globListUnits`).
|
|
10
|
+
*/
|
|
11
|
+
export interface IGlobLivenessList {
|
|
12
|
+
readonly list: string;
|
|
13
|
+
/**
|
|
14
|
+
* Display prefix for each unit of this list. Set when the rule reads more
|
|
15
|
+
* than one list: a unit then prints `<label>: <glob>` — today's dead-glob
|
|
16
|
+
* selector (`declared: src/moved/*.ts`). Absent: the bare glob.
|
|
17
|
+
*/
|
|
18
|
+
readonly label?: string;
|
|
19
|
+
/** The globs as the loader normalised them (a negation keeps its `!`). */
|
|
20
|
+
readonly globs: readonly string[];
|
|
21
|
+
readonly units: IGlobListUnits;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=i-glob-liveness-list.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i-glob-liveness-list.d.ts","sourceRoot":"","sources":["../../src/util/i-glob-liveness-list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;CAChC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IUnitMark } from '@shrkcrft/core';
|
|
2
|
+
import type { IGlobLivenessList } from './i-glob-liveness-list.js';
|
|
3
|
+
/** Every glob list one gate rule reads, and its markers — the input of the one gate-plane glob settle (round 13). */
|
|
4
|
+
export interface IGlobLivenessRequest {
|
|
5
|
+
/** The rule id; it becomes the coverage records' `subject`. */
|
|
6
|
+
readonly subject?: string;
|
|
7
|
+
readonly lists: readonly IGlobLivenessList[];
|
|
8
|
+
/** The rule's / sources' `expectEmptyUnits`, qualified exactly like the lists' `list`. */
|
|
9
|
+
readonly marks: readonly IUnitMark[];
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=i-glob-liveness-request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i-glob-liveness-request.d.ts","sourceRoot":"","sources":["../../src/util/i-glob-liveness-request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,qHAAqH;AACrH,MAAM,WAAW,oBAAoB;IACnC,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC7C,0FAA0F;IAC1F,QAAQ,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,CAAC;CACtC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A LIVE negation of a gate-plane glob list and what it removes: the files its
|
|
3
|
+
* list's inclusion globs select that it takes out of scope (read, or matched
|
|
4
|
+
* but unread). `gates coverage` prints each one, so the scope a `!` narrowed is
|
|
5
|
+
* visible on the surface the author already reads.
|
|
6
|
+
*/
|
|
7
|
+
export interface IGlobNegation {
|
|
8
|
+
/** The negation as written (`!src/**\/*.spec.ts`). */
|
|
9
|
+
readonly glob: string;
|
|
10
|
+
/** Files it excludes from the list's positive set (at least 1). */
|
|
11
|
+
readonly excludes: number;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=i-glob-negation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i-glob-negation.d.ts","sourceRoot":"","sources":["../../src/util/i-glob-negation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,sDAAsD;IACtD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { IUnreadFile } from './unread-file.js';
|
|
2
|
+
/**
|
|
3
|
+
* What the one reader returns: every glob-matched file it READ, and every
|
|
4
|
+
* glob-matched file it did NOT read, with the reason.
|
|
5
|
+
*
|
|
6
|
+
* The second half is the point. A reader that drops an over-cap file without
|
|
7
|
+
* saying so turns "a forbidden token in a 1.7MB file" into "examined 1 of 1 ✓":
|
|
8
|
+
* every plane counted its expected scope from what was read, so the dropped
|
|
9
|
+
* file was invisible to every coverage record built on top of it. Returning
|
|
10
|
+
* the unread files next to the read ones means no caller can build coverage
|
|
11
|
+
* without choosing, explicitly, what to do with them.
|
|
12
|
+
*/
|
|
13
|
+
export interface IMatchedFiles {
|
|
14
|
+
/**
|
|
15
|
+
* Project-relative POSIX path → content, for every matched file that was
|
|
16
|
+
* read. A fresh map per call, because callers filter and partition it.
|
|
17
|
+
*/
|
|
18
|
+
readonly files: Map<string, string>;
|
|
19
|
+
/** Matched files the reader did not read, sorted by path. */
|
|
20
|
+
readonly unread: readonly IUnreadFile[];
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=matched-files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matched-files.d.ts","sourceRoot":"","sources":["../../src/util/matched-files.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;CACzC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { IGlobNegation } from './i-glob-negation.js';
|
|
2
|
+
/**
|
|
3
|
+
* THE cause of a list its OWN negations emptied — its inclusion globs matched
|
|
4
|
+
* files and every one was excluded as written — for the policy plane's skip
|
|
5
|
+
* and coverage reasons. Not a stale selector, and never worded as one.
|
|
6
|
+
*/
|
|
7
|
+
export declare function allExcludedCause(negations: readonly IGlobNegation[]): string;
|
|
8
|
+
/**
|
|
9
|
+
* THE skip reason of an extraction SOURCE its own negations emptied (round 12
|
|
10
|
+
* review, R12-DOC-2) — the words `gates coverage` prints for the same rule, so
|
|
11
|
+
* `check wiring`, `gates check` and the NOT VERIFIED line no longer say "0
|
|
12
|
+
* files matched the source globs" (a file DID match, then was excluded).
|
|
13
|
+
*/
|
|
14
|
+
export declare function emptiedByNegationsReason(negations: readonly IGlobNegation[]): string;
|
|
15
|
+
//# sourceMappingURL=negation-cause.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"negation-cause.d.ts","sourceRoot":"","sources":["../../src/util/negation-cause.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAO1D;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,CAE5E;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,CAEpF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** `!src/**\/*.spec.ts (1 file), !docs/drafts/** (3 files)` — each negation with what it excluded. */
|
|
2
|
+
function describeNegations(negations) {
|
|
3
|
+
return negations.map((n) => `${n.glob} (${n.excludes} file${n.excludes === 1 ? '' : 's'})`).join(', ');
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* THE cause of a list its OWN negations emptied — its inclusion globs matched
|
|
7
|
+
* files and every one was excluded as written — for the policy plane's skip
|
|
8
|
+
* and coverage reasons. Not a stale selector, and never worded as one.
|
|
9
|
+
*/
|
|
10
|
+
export function allExcludedCause(negations) {
|
|
11
|
+
return `every file its inclusion globs select is excluded by its own negations (${describeNegations(negations)})`;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* THE skip reason of an extraction SOURCE its own negations emptied (round 12
|
|
15
|
+
* review, R12-DOC-2) — the words `gates coverage` prints for the same rule, so
|
|
16
|
+
* `check wiring`, `gates check` and the NOT VERIFIED line no longer say "0
|
|
17
|
+
* files matched the source globs" (a file DID match, then was excluded).
|
|
18
|
+
*/
|
|
19
|
+
export function emptiedByNegationsReason(negations) {
|
|
20
|
+
return `matched nothing after its own negations: every file its inclusion globs select is excluded (${describeNegations(negations)})`;
|
|
21
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE scan scope of every data-defined plane walk: the project-relative
|
|
3
|
+
* directories the walk prunes. Today that is the SharkCraft asset/config dir,
|
|
4
|
+
* when it sits inside the project. Its `.ts` files hold the rule definitions
|
|
5
|
+
* themselves, so a rule would otherwise match (and self-report) its own
|
|
6
|
+
* definition.
|
|
7
|
+
*
|
|
8
|
+
* Every verb and every aggregate that walks a plane reads it here: `policy-lint`,
|
|
9
|
+
* `check wiring`, `wiring explain | unprovided | orphans`, `registry …`,
|
|
10
|
+
* `baseline`, `generated`, `docs references`, `gates check | coverage | try`,
|
|
11
|
+
* `quality`, `finish`, `shrk gate` and MCP. Before round 11 each derived it
|
|
12
|
+
* inline, and several did not derive it at all. So `check wiring` and `gates
|
|
13
|
+
* check` (or `policy-lint` and `shrk gate`) walked different trees for the SAME
|
|
14
|
+
* rule, and one read 1 where the other read 0 ✓.
|
|
15
|
+
*/
|
|
16
|
+
export declare function planeScanExcludeDirs(projectRoot: string, sharkcraftDir: string | null | undefined): string[];
|
|
17
|
+
//# sourceMappingURL=plane-scan-exclude-dirs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plane-scan-exclude-dirs.d.ts","sourceRoot":"","sources":["../../src/util/plane-scan-exclude-dirs.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,EAAE,CAI5G"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as nodePath from 'node:path';
|
|
2
|
+
/**
|
|
3
|
+
* THE scan scope of every data-defined plane walk: the project-relative
|
|
4
|
+
* directories the walk prunes. Today that is the SharkCraft asset/config dir,
|
|
5
|
+
* when it sits inside the project. Its `.ts` files hold the rule definitions
|
|
6
|
+
* themselves, so a rule would otherwise match (and self-report) its own
|
|
7
|
+
* definition.
|
|
8
|
+
*
|
|
9
|
+
* Every verb and every aggregate that walks a plane reads it here: `policy-lint`,
|
|
10
|
+
* `check wiring`, `wiring explain | unprovided | orphans`, `registry …`,
|
|
11
|
+
* `baseline`, `generated`, `docs references`, `gates check | coverage | try`,
|
|
12
|
+
* `quality`, `finish`, `shrk gate` and MCP. Before round 11 each derived it
|
|
13
|
+
* inline, and several did not derive it at all. So `check wiring` and `gates
|
|
14
|
+
* check` (or `policy-lint` and `shrk gate`) walked different trees for the SAME
|
|
15
|
+
* rule, and one read 1 where the other read 0 ✓.
|
|
16
|
+
*/
|
|
17
|
+
export function planeScanExcludeDirs(projectRoot, sharkcraftDir) {
|
|
18
|
+
if (!sharkcraftDir)
|
|
19
|
+
return [];
|
|
20
|
+
const rel = nodePath.relative(projectRoot, sharkcraftDir).split(nodePath.sep).join('/');
|
|
21
|
+
return rel && !rel.startsWith('..') ? [rel] : [];
|
|
22
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ISettledUnitLiveness, IUnitMark } from '@shrkcrft/core';
|
|
2
|
+
import type { IGlobListUnits } from './i-glob-list-units.js';
|
|
3
|
+
/**
|
|
4
|
+
* ONE glob list, judged off the one reader's positive walk
|
|
5
|
+
* (`readGlobListUnits`, memoised under `withFileReadCache`) and settled with
|
|
6
|
+
* its markers (`settleGlobLists`) — for an engine that selects files by a bare
|
|
7
|
+
* list and must decide its rule's emptiness: a registry's / idiom role's /
|
|
8
|
+
* extractor baseline's source `files`, a generated rule's `generatedGlob`, a
|
|
9
|
+
* doc-reference rule's `files` (pass its `dotDirsNamedBy`, so the walk is the
|
|
10
|
+
* one the rule reads). `marks` are the list's own (`list` equal to `list`).
|
|
11
|
+
*/
|
|
12
|
+
export declare function readGlobListLiveness(projectRoot: string, list: string, globs: readonly string[], marks: readonly IUnitMark[], options?: {
|
|
13
|
+
readonly subject?: string;
|
|
14
|
+
readonly excludeDirs?: ReadonlySet<string>;
|
|
15
|
+
readonly allowDotDirs?: ReadonlySet<string>;
|
|
16
|
+
}): {
|
|
17
|
+
readonly units: IGlobListUnits;
|
|
18
|
+
readonly liveness: ISettledUnitLiveness;
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=read-glob-list-liveness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-glob-list-liveness.d.ts","sourceRoot":"","sources":["../../src/util/read-glob-list-liveness.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAG7D;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,OAAO,GAAE;IACP,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3C,QAAQ,CAAC,YAAY,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACxC,GACL;IAAE,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAA;CAAE,CAQ7E"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { readGlobListUnits } from "./dead-glob-units.js";
|
|
2
|
+
import { settleGlobLists } from "./settle-glob-lists.js";
|
|
3
|
+
/**
|
|
4
|
+
* ONE glob list, judged off the one reader's positive walk
|
|
5
|
+
* (`readGlobListUnits`, memoised under `withFileReadCache`) and settled with
|
|
6
|
+
* its markers (`settleGlobLists`) — for an engine that selects files by a bare
|
|
7
|
+
* list and must decide its rule's emptiness: a registry's / idiom role's /
|
|
8
|
+
* extractor baseline's source `files`, a generated rule's `generatedGlob`, a
|
|
9
|
+
* doc-reference rule's `files` (pass its `dotDirsNamedBy`, so the walk is the
|
|
10
|
+
* one the rule reads). `marks` are the list's own (`list` equal to `list`).
|
|
11
|
+
*/
|
|
12
|
+
export function readGlobListLiveness(projectRoot, list, globs, marks, options = {}) {
|
|
13
|
+
const units = readGlobListUnits(projectRoot, globs, options.excludeDirs, options.allowDotDirs);
|
|
14
|
+
const liveness = settleGlobLists({
|
|
15
|
+
...(options.subject !== undefined ? { subject: options.subject } : {}),
|
|
16
|
+
lists: [{ list, globs, units }],
|
|
17
|
+
marks: marks.filter((m) => m.list === list),
|
|
18
|
+
});
|
|
19
|
+
return { units, liveness };
|
|
20
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { IVerdictCoverage } from '@shrkcrft/core';
|
|
2
|
+
import type { IMatchedFiles } from './matched-files.js';
|
|
3
|
+
import type { IReadScope } from './read-scope.js';
|
|
4
|
+
import type { IUnreadFile } from './unread-file.js';
|
|
5
|
+
/** How a coverage gap names a file the reader skipped for its size. */
|
|
6
|
+
export declare const READ_CAP_REASON = "over the 1MB read cap";
|
|
7
|
+
/** How a coverage gap names a regenerated file skipped for its size. */
|
|
8
|
+
export declare const REGEN_CAP_REASON = "over the 2MB regen read cap";
|
|
9
|
+
/** How a coverage gap names a directory the walk could not list. */
|
|
10
|
+
export declare const UNLISTABLE_DIR_REASON = "unlistable (a directory whose files were never enumerated)";
|
|
11
|
+
/** The one sentence naming why a set of files went unread. */
|
|
12
|
+
export declare function unreadReason(unread: readonly IUnreadFile[]): string;
|
|
13
|
+
/** True for the entry of a directory the walk could not list (its path ends in `/`). */
|
|
14
|
+
export declare function isUnreadDirectory(u: IUnreadFile): boolean;
|
|
15
|
+
/** Is project-relative `path` beneath the unlistable-directory entry `u`? */
|
|
16
|
+
export declare function unreadDirectoryContains(u: IUnreadFile, path: string): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* THE "is this unread entry in front of these globs?" test, for every plane.
|
|
19
|
+
* A file: the list SELECTS its path (`globListSelects` — an inclusion glob
|
|
20
|
+
* matches, no negation does). A directory the walk could not list: an
|
|
21
|
+
* inclusion glob could match something beneath it (`globMayMatchUnder`) and no
|
|
22
|
+
* negation covers ALL of it (`globCoversAllUnder`) — its files were never
|
|
23
|
+
* enumerated, so no rule over that tree may claim it examined them, unless the
|
|
24
|
+
* list itself excludes every one of them.
|
|
25
|
+
*/
|
|
26
|
+
export declare function unreadEntryMatches(u: IUnreadFile, globs: readonly string[]): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* The exemption side of {@link unreadEntryMatches}: do `globs` take the WHOLE
|
|
29
|
+
* entry out of scope? A file: the list selects it. A directory: one inclusion
|
|
30
|
+
* glob covers everything beneath it (`globCoversAllUnder`) and no negation
|
|
31
|
+
* could carve part of it back out (`globMayMatchUnder`) — an exemption
|
|
32
|
+
* covering part of an unlistable directory leaves the rest a gap.
|
|
33
|
+
*/
|
|
34
|
+
export declare function unreadEntryWhollyMatches(u: IUnreadFile, globs: readonly string[]): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* The unread entries a selector's globs are in front of, optionally only those
|
|
37
|
+
* in a changeset. Sorted by path.
|
|
38
|
+
*
|
|
39
|
+
* Under a changeset, an unlistable directory contributes the CHANGED files
|
|
40
|
+
* beneath it that the globs match (each unreadable: its directory could not be
|
|
41
|
+
* listed) — the changeset is the scope, so the gap is named by file.
|
|
42
|
+
*/
|
|
43
|
+
export declare function unreadMatching(unread: readonly IUnreadFile[], globs: readonly string[], changed?: ReadonlySet<string>): IUnreadFile[];
|
|
44
|
+
/**
|
|
45
|
+
* One rule's read scope over a read the caller already did: the read files
|
|
46
|
+
* its globs match, and the unread ones. `changed` narrows both to a changeset,
|
|
47
|
+
* which is deliberate narrowing and not a gap.
|
|
48
|
+
*/
|
|
49
|
+
export declare function readScopeOf(matched: IMatchedFiles, globs: readonly string[], changed?: ReadonlySet<string>): IReadScope;
|
|
50
|
+
/** Merge several read scopes (a rule's sides), counting each unread path once. */
|
|
51
|
+
export declare function mergeReadScopes(read: number, scopes: readonly (readonly IUnreadFile[])[]): IReadScope;
|
|
52
|
+
/**
|
|
53
|
+
* The read scope of SEVERAL lists over one read (a registration idiom's three
|
|
54
|
+
* roles, every idiom of a graph): a file counts once when ANY list selects it,
|
|
55
|
+
* and each list's unread entries are taken from that list alone.
|
|
56
|
+
*
|
|
57
|
+
* Never flatten the lists into one and call {@link readScopeOf}: a negation
|
|
58
|
+
* subtracts from its own list only, and a flattened union would let one role's
|
|
59
|
+
* `!x` hide another role's file.
|
|
60
|
+
*/
|
|
61
|
+
export declare function readScopeOfLists(matched: IMatchedFiles, lists: readonly (readonly string[])[], changed?: ReadonlySet<string>): IReadScope;
|
|
62
|
+
/**
|
|
63
|
+
* True when a rule's scope holds a file the reader did not read. Such a rule's
|
|
64
|
+
* zero is never "matched nothing": it matched a file it could not examine. So
|
|
65
|
+
* it is PARTIAL (2), never a `failOnEmpty` failure (1), and never a pass.
|
|
66
|
+
*/
|
|
67
|
+
export declare function readScopeHasUnread(scope: IReadScope | undefined): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* THE rule for folding the one reader's unread files into a rule's coverage.
|
|
70
|
+
*
|
|
71
|
+
* With no unread file in scope, the plane's own record is returned unchanged.
|
|
72
|
+
* Otherwise the rule examined `read` of the `read + unread` files its globs
|
|
73
|
+
* MATCHED: unit `files`, and each unread path named with its reason
|
|
74
|
+
* (`examined 1 of 2 files, 1 over the 1MB read cap: src/big.ts`).
|
|
75
|
+
*
|
|
76
|
+
* The file record REPLACES the plane's record rather than sitting next to it.
|
|
77
|
+
* Every count the plane derived (tokens, content units, entries, references)
|
|
78
|
+
* came from an incomplete read, so it misses whatever the unread file holds.
|
|
79
|
+
* CLAUDE.md's loud-skip rule applies: a number derived from an incomplete input
|
|
80
|
+
* is reported NOT VERIFIED, never as a number. Any acceptance on the plane
|
|
81
|
+
* record (`registeredExtras`, `expectEmpty`, `--allow-empty`) is dropped with
|
|
82
|
+
* it, because none of them accepted an unread file.
|
|
83
|
+
*/
|
|
84
|
+
export declare function readScopeCoverage(plane: IVerdictCoverage, scope: IReadScope | undefined): IVerdictCoverage;
|
|
85
|
+
/**
|
|
86
|
+
* A short human clause for a rule's unread files, for skip reasons and hints:
|
|
87
|
+
* `1 matched file over the 1MB read cap (src/big.ts)`.
|
|
88
|
+
*/
|
|
89
|
+
export declare function describeUnread(unread: readonly IUnreadFile[], shown?: number): string;
|
|
90
|
+
//# sourceMappingURL=read-scope-coverage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-scope-coverage.d.ts","sourceRoot":"","sources":["../../src/util/read-scope-coverage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAOpD,uEAAuE;AACvE,eAAO,MAAM,eAAe,0BAA2D,CAAC;AAExF,wEAAwE;AACxE,eAAO,MAAM,gBAAgB,gCAAkE,CAAC;AAEhG,oEAAoE;AACpE,eAAO,MAAM,qBAAqB,+DAA+D,CAAC;AAElG,8DAA8D;AAC9D,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,GAAG,MAAM,CASnE;AAED,wFAAwF;AACxF,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,WAAW,GAAG,OAAO,CAEzD;AAED,6EAA6E;AAC7E,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAE7E;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAIpF;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAI1F;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,OAAO,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAC5B,WAAW,EAAE,CAef;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,OAAO,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAC5B,UAAU,CAMZ;AAED,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,SAAS,WAAW,EAAE,CAAC,EAAE,GAAG,UAAU,CAIrG;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,EACrC,OAAO,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAC5B,UAAU,CAOZ;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,CAEzE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,gBAAgB,CAa1G;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,EAAE,KAAK,SAAI,GAAG,MAAM,CAIhF"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { globCoversAllUnder, globListParts, globListSelects, globMayMatchUnder } from "../scan/glob.js";
|
|
2
|
+
import { UnreadFileReason } from "./unread-file-reason.js";
|
|
3
|
+
import { MAX_REGEN_FILE_BYTES, MAX_SCAN_FILE_BYTES } from "./walk-files.js";
|
|
4
|
+
/** At most this many unread paths ride on one coverage record. */
|
|
5
|
+
const UNREAD_LABEL_CAP = 20;
|
|
6
|
+
/** How a coverage gap names a file the reader skipped for its size. */
|
|
7
|
+
export const READ_CAP_REASON = `over the ${MAX_SCAN_FILE_BYTES / 1_000_000}MB read cap`;
|
|
8
|
+
/** How a coverage gap names a regenerated file skipped for its size. */
|
|
9
|
+
export const REGEN_CAP_REASON = `over the ${MAX_REGEN_FILE_BYTES / 1_000_000}MB regen read cap`;
|
|
10
|
+
/** How a coverage gap names a directory the walk could not list. */
|
|
11
|
+
export const UNLISTABLE_DIR_REASON = 'unlistable (a directory whose files were never enumerated)';
|
|
12
|
+
/** The one sentence naming why a set of files went unread. */
|
|
13
|
+
export function unreadReason(unread) {
|
|
14
|
+
const kinds = new Set(unread.map((u) => u.reason));
|
|
15
|
+
const parts = [
|
|
16
|
+
...(kinds.has(UnreadFileReason.OverReadCap) ? [READ_CAP_REASON] : []),
|
|
17
|
+
...(kinds.has(UnreadFileReason.OverRegenCap) ? [REGEN_CAP_REASON] : []),
|
|
18
|
+
...(kinds.has(UnreadFileReason.Unreadable) ? ['unreadable'] : []),
|
|
19
|
+
...(kinds.has(UnreadFileReason.UnreadableDirectory) ? [UNLISTABLE_DIR_REASON] : []),
|
|
20
|
+
];
|
|
21
|
+
return parts.length > 0 ? parts.join(' or ') : READ_CAP_REASON;
|
|
22
|
+
}
|
|
23
|
+
/** True for the entry of a directory the walk could not list (its path ends in `/`). */
|
|
24
|
+
export function isUnreadDirectory(u) {
|
|
25
|
+
return u.reason === UnreadFileReason.UnreadableDirectory;
|
|
26
|
+
}
|
|
27
|
+
/** Is project-relative `path` beneath the unlistable-directory entry `u`? */
|
|
28
|
+
export function unreadDirectoryContains(u, path) {
|
|
29
|
+
return isUnreadDirectory(u) && (u.path === './' || path.startsWith(u.path));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* THE "is this unread entry in front of these globs?" test, for every plane.
|
|
33
|
+
* A file: the list SELECTS its path (`globListSelects` — an inclusion glob
|
|
34
|
+
* matches, no negation does). A directory the walk could not list: an
|
|
35
|
+
* inclusion glob could match something beneath it (`globMayMatchUnder`) and no
|
|
36
|
+
* negation covers ALL of it (`globCoversAllUnder`) — its files were never
|
|
37
|
+
* enumerated, so no rule over that tree may claim it examined them, unless the
|
|
38
|
+
* list itself excludes every one of them.
|
|
39
|
+
*/
|
|
40
|
+
export function unreadEntryMatches(u, globs) {
|
|
41
|
+
if (!isUnreadDirectory(u))
|
|
42
|
+
return globListSelects(u.path, globs);
|
|
43
|
+
const { include, exclude } = globListParts(globs);
|
|
44
|
+
return include.some((g) => globMayMatchUnder(g, u.path)) && !exclude.some((n) => globCoversAllUnder(n, u.path));
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The exemption side of {@link unreadEntryMatches}: do `globs` take the WHOLE
|
|
48
|
+
* entry out of scope? A file: the list selects it. A directory: one inclusion
|
|
49
|
+
* glob covers everything beneath it (`globCoversAllUnder`) and no negation
|
|
50
|
+
* could carve part of it back out (`globMayMatchUnder`) — an exemption
|
|
51
|
+
* covering part of an unlistable directory leaves the rest a gap.
|
|
52
|
+
*/
|
|
53
|
+
export function unreadEntryWhollyMatches(u, globs) {
|
|
54
|
+
if (!isUnreadDirectory(u))
|
|
55
|
+
return globListSelects(u.path, globs);
|
|
56
|
+
const { include, exclude } = globListParts(globs);
|
|
57
|
+
return include.some((g) => globCoversAllUnder(g, u.path)) && !exclude.some((n) => globMayMatchUnder(n, u.path));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The unread entries a selector's globs are in front of, optionally only those
|
|
61
|
+
* in a changeset. Sorted by path.
|
|
62
|
+
*
|
|
63
|
+
* Under a changeset, an unlistable directory contributes the CHANGED files
|
|
64
|
+
* beneath it that the globs match (each unreadable: its directory could not be
|
|
65
|
+
* listed) — the changeset is the scope, so the gap is named by file.
|
|
66
|
+
*/
|
|
67
|
+
export function unreadMatching(unread, globs, changed) {
|
|
68
|
+
if (changed === undefined)
|
|
69
|
+
return unread.filter((u) => unreadEntryMatches(u, globs));
|
|
70
|
+
const out = new Map();
|
|
71
|
+
for (const u of unread) {
|
|
72
|
+
if (!isUnreadDirectory(u)) {
|
|
73
|
+
if (changed.has(u.path) && globListSelects(u.path, globs))
|
|
74
|
+
out.set(u.path, u);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
for (const path of changed) {
|
|
78
|
+
if (!out.has(path) && unreadDirectoryContains(u, path) && globListSelects(path, globs)) {
|
|
79
|
+
out.set(path, { path, reason: UnreadFileReason.Unreadable });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return [...out.values()].sort((a, b) => a.path.localeCompare(b.path));
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* One rule's read scope over a read the caller already did: the read files
|
|
87
|
+
* its globs match, and the unread ones. `changed` narrows both to a changeset,
|
|
88
|
+
* which is deliberate narrowing and not a gap.
|
|
89
|
+
*/
|
|
90
|
+
export function readScopeOf(matched, globs, changed) {
|
|
91
|
+
let read = 0;
|
|
92
|
+
for (const path of matched.files.keys()) {
|
|
93
|
+
if ((changed === undefined || changed.has(path)) && globListSelects(path, globs))
|
|
94
|
+
read += 1;
|
|
95
|
+
}
|
|
96
|
+
return { read, unread: unreadMatching(matched.unread, globs, changed) };
|
|
97
|
+
}
|
|
98
|
+
/** Merge several read scopes (a rule's sides), counting each unread path once. */
|
|
99
|
+
export function mergeReadScopes(read, scopes) {
|
|
100
|
+
const seen = new Map();
|
|
101
|
+
for (const list of scopes)
|
|
102
|
+
for (const u of list)
|
|
103
|
+
if (!seen.has(u.path))
|
|
104
|
+
seen.set(u.path, u);
|
|
105
|
+
return { read, unread: [...seen.values()].sort((a, b) => a.path.localeCompare(b.path)) };
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* The read scope of SEVERAL lists over one read (a registration idiom's three
|
|
109
|
+
* roles, every idiom of a graph): a file counts once when ANY list selects it,
|
|
110
|
+
* and each list's unread entries are taken from that list alone.
|
|
111
|
+
*
|
|
112
|
+
* Never flatten the lists into one and call {@link readScopeOf}: a negation
|
|
113
|
+
* subtracts from its own list only, and a flattened union would let one role's
|
|
114
|
+
* `!x` hide another role's file.
|
|
115
|
+
*/
|
|
116
|
+
export function readScopeOfLists(matched, lists, changed) {
|
|
117
|
+
let read = 0;
|
|
118
|
+
for (const path of matched.files.keys()) {
|
|
119
|
+
if (changed !== undefined && !changed.has(path))
|
|
120
|
+
continue;
|
|
121
|
+
if (lists.some((l) => globListSelects(path, l)))
|
|
122
|
+
read += 1;
|
|
123
|
+
}
|
|
124
|
+
return mergeReadScopes(read, lists.map((l) => unreadMatching(matched.unread, l, changed)));
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* True when a rule's scope holds a file the reader did not read. Such a rule's
|
|
128
|
+
* zero is never "matched nothing": it matched a file it could not examine. So
|
|
129
|
+
* it is PARTIAL (2), never a `failOnEmpty` failure (1), and never a pass.
|
|
130
|
+
*/
|
|
131
|
+
export function readScopeHasUnread(scope) {
|
|
132
|
+
return scope !== undefined && scope.unread.length > 0;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* THE rule for folding the one reader's unread files into a rule's coverage.
|
|
136
|
+
*
|
|
137
|
+
* With no unread file in scope, the plane's own record is returned unchanged.
|
|
138
|
+
* Otherwise the rule examined `read` of the `read + unread` files its globs
|
|
139
|
+
* MATCHED: unit `files`, and each unread path named with its reason
|
|
140
|
+
* (`examined 1 of 2 files, 1 over the 1MB read cap: src/big.ts`).
|
|
141
|
+
*
|
|
142
|
+
* The file record REPLACES the plane's record rather than sitting next to it.
|
|
143
|
+
* Every count the plane derived (tokens, content units, entries, references)
|
|
144
|
+
* came from an incomplete read, so it misses whatever the unread file holds.
|
|
145
|
+
* CLAUDE.md's loud-skip rule applies: a number derived from an incomplete input
|
|
146
|
+
* is reported NOT VERIFIED, never as a number. Any acceptance on the plane
|
|
147
|
+
* record (`registeredExtras`, `expectEmpty`, `--allow-empty`) is dropped with
|
|
148
|
+
* it, because none of them accepted an unread file.
|
|
149
|
+
*/
|
|
150
|
+
export function readScopeCoverage(plane, scope) {
|
|
151
|
+
if (scope === undefined || scope.unread.length === 0)
|
|
152
|
+
return plane;
|
|
153
|
+
const unread = scope.unread;
|
|
154
|
+
return {
|
|
155
|
+
unit: 'files',
|
|
156
|
+
expected: scope.read + unread.length,
|
|
157
|
+
examined: scope.read,
|
|
158
|
+
unexamined: unread.slice(0, UNREAD_LABEL_CAP).map((u) => u.path),
|
|
159
|
+
unexaminedTotal: unread.length,
|
|
160
|
+
reason: unreadReason(unread),
|
|
161
|
+
...(plane.root !== undefined ? { root: plane.root } : {}),
|
|
162
|
+
...(plane.subject !== undefined ? { subject: plane.subject } : {}),
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* A short human clause for a rule's unread files, for skip reasons and hints:
|
|
167
|
+
* `1 matched file over the 1MB read cap (src/big.ts)`.
|
|
168
|
+
*/
|
|
169
|
+
export function describeUnread(unread, shown = 3) {
|
|
170
|
+
const names = unread.slice(0, shown).map((u) => u.path);
|
|
171
|
+
const more = unread.length > shown ? `, +${unread.length - shown} more` : '';
|
|
172
|
+
return `${unread.length} matched file(s) ${unreadReason(unread)} (${names.join(', ')}${more})`;
|
|
173
|
+
}
|