plumbbob 0.9.3 → 0.9.5
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/.claude-plugin/plugin.json +1 -1
- package/README.md +15 -13
- package/dist/cli-core.js +19 -2
- package/dist/lib/check.js +46 -13
- package/dist/lib/intent.js +1 -1
- package/dist/lib/latch.js +3 -3
- package/dist/lib/reentry.js +70 -0
- package/dist/verbs/agent.js +2 -2
- package/dist/verbs/doctor.js +4 -4
- package/dist/verbs/finish.js +1 -1
- package/dist/verbs/recover.js +297 -0
- package/dist/verbs/revert.js +2 -2
- package/dist/verbs/spike.js +8 -2
- package/hooks/post-edit.sh +4 -4
- package/hooks/pre-bash-commit.sh +3 -3
- package/node_modules/checkride/.claude-plugin/plugin.json +11 -0
- package/node_modules/checkride/CHANGELOG.md +1003 -0
- package/node_modules/checkride/LICENSE +201 -21
- package/node_modules/checkride/README.md +171 -30
- package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.d.ts +15 -0
- package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.d.ts.map +1 -0
- package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.js +17 -0
- package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.js.map +1 -0
- package/node_modules/checkride/dist/adapters.d.ts +18 -6
- package/node_modules/checkride/dist/adapters.d.ts.map +1 -1
- package/node_modules/checkride/dist/adapters.js +42 -23
- package/node_modules/checkride/dist/adapters.js.map +1 -1
- package/node_modules/checkride/dist/agent-setup/claude.d.ts +88 -0
- package/node_modules/checkride/dist/agent-setup/claude.d.ts.map +1 -0
- package/node_modules/checkride/dist/agent-setup/claude.js +305 -0
- package/node_modules/checkride/dist/agent-setup/claude.js.map +1 -0
- package/node_modules/checkride/dist/agent-setup/command.d.ts +43 -0
- package/node_modules/checkride/dist/agent-setup/command.d.ts.map +1 -0
- package/node_modules/checkride/dist/agent-setup/command.js +77 -0
- package/node_modules/checkride/dist/agent-setup/command.js.map +1 -0
- package/node_modules/checkride/dist/agent-setup/cursor.d.ts +61 -0
- package/node_modules/checkride/dist/agent-setup/cursor.d.ts.map +1 -0
- package/node_modules/checkride/dist/agent-setup/cursor.js +189 -0
- package/node_modules/checkride/dist/agent-setup/cursor.js.map +1 -0
- package/node_modules/checkride/dist/agent-setup/files.d.ts +50 -0
- package/node_modules/checkride/dist/agent-setup/files.d.ts.map +1 -0
- package/node_modules/checkride/dist/agent-setup/files.js +80 -0
- package/node_modules/checkride/dist/agent-setup/files.js.map +1 -0
- package/node_modules/checkride/dist/agent-setup/harness.d.ts +101 -0
- package/node_modules/checkride/dist/agent-setup/harness.d.ts.map +1 -0
- package/node_modules/checkride/dist/agent-setup/harness.js +84 -0
- package/node_modules/checkride/dist/agent-setup/harness.js.map +1 -0
- package/node_modules/checkride/dist/agent-setup/hook.d.ts +45 -52
- package/node_modules/checkride/dist/agent-setup/hook.d.ts.map +1 -1
- package/node_modules/checkride/dist/agent-setup/hook.js +64 -95
- package/node_modules/checkride/dist/agent-setup/hook.js.map +1 -1
- package/node_modules/checkride/dist/agent-setup/index.d.ts +10 -4
- package/node_modules/checkride/dist/agent-setup/index.d.ts.map +1 -1
- package/node_modules/checkride/dist/agent-setup/index.js +9 -4
- package/node_modules/checkride/dist/agent-setup/index.js.map +1 -1
- package/node_modules/checkride/dist/agent-setup/scripts.d.ts +58 -0
- package/node_modules/checkride/dist/agent-setup/scripts.d.ts.map +1 -0
- package/node_modules/checkride/dist/agent-setup/scripts.js +299 -0
- package/node_modules/checkride/dist/agent-setup/scripts.js.map +1 -0
- package/node_modules/checkride/dist/agent-setup/skills.d.ts +31 -0
- package/node_modules/checkride/dist/agent-setup/skills.d.ts.map +1 -0
- package/node_modules/checkride/dist/agent-setup/skills.js +56 -0
- package/node_modules/checkride/dist/agent-setup/skills.js.map +1 -0
- package/node_modules/checkride/dist/artifacts/configured.d.ts +30 -0
- package/node_modules/checkride/dist/artifacts/configured.d.ts.map +1 -0
- package/node_modules/checkride/dist/artifacts/configured.js +45 -0
- package/node_modules/checkride/dist/artifacts/configured.js.map +1 -0
- package/node_modules/checkride/dist/artifacts/format.d.ts +33 -0
- package/node_modules/checkride/dist/artifacts/format.d.ts.map +1 -0
- package/node_modules/checkride/dist/artifacts/format.js +56 -0
- package/node_modules/checkride/dist/artifacts/format.js.map +1 -0
- package/node_modules/checkride/dist/artifacts/freshness.d.ts +32 -0
- package/node_modules/checkride/dist/artifacts/freshness.d.ts.map +1 -0
- package/node_modules/checkride/dist/artifacts/freshness.js +37 -0
- package/node_modules/checkride/dist/artifacts/freshness.js.map +1 -0
- package/node_modules/checkride/dist/artifacts/index.d.ts +22 -0
- package/node_modules/checkride/dist/artifacts/index.d.ts.map +1 -0
- package/node_modules/checkride/dist/artifacts/index.js +19 -0
- package/node_modules/checkride/dist/artifacts/index.js.map +1 -0
- package/node_modules/checkride/dist/artifacts/json.d.ts +31 -0
- package/node_modules/checkride/dist/artifacts/json.d.ts.map +1 -0
- package/node_modules/checkride/dist/artifacts/json.js +47 -0
- package/node_modules/checkride/dist/artifacts/json.js.map +1 -0
- package/node_modules/checkride/dist/artifacts/raw.d.ts +60 -0
- package/node_modules/checkride/dist/artifacts/raw.d.ts.map +1 -0
- package/node_modules/checkride/dist/artifacts/raw.js +91 -0
- package/node_modules/checkride/dist/artifacts/raw.js.map +1 -0
- package/node_modules/checkride/dist/artifacts/summary.d.ts +69 -0
- package/node_modules/checkride/dist/artifacts/summary.d.ts.map +1 -0
- package/node_modules/checkride/dist/artifacts/summary.js +108 -0
- package/node_modules/checkride/dist/artifacts/summary.js.map +1 -0
- package/node_modules/checkride/dist/atomic.d.ts +16 -1
- package/node_modules/checkride/dist/atomic.d.ts.map +1 -1
- package/node_modules/checkride/dist/atomic.js +25 -3
- package/node_modules/checkride/dist/atomic.js.map +1 -1
- package/node_modules/checkride/dist/baseline/fallow.d.ts +9 -5
- package/node_modules/checkride/dist/baseline/fallow.d.ts.map +1 -1
- package/node_modules/checkride/dist/baseline/fallow.js +161 -58
- package/node_modules/checkride/dist/baseline/fallow.js.map +1 -1
- package/node_modules/checkride/dist/baseline/fingerprint.d.ts +7 -7
- package/node_modules/checkride/dist/baseline/fingerprint.d.ts.map +1 -1
- package/node_modules/checkride/dist/baseline/fingerprint.js +16 -19
- package/node_modules/checkride/dist/baseline/fingerprint.js.map +1 -1
- package/node_modules/checkride/dist/baseline/index.d.ts +4 -4
- package/node_modules/checkride/dist/baseline/index.d.ts.map +1 -1
- package/node_modules/checkride/dist/baseline/index.js +4 -4
- package/node_modules/checkride/dist/baseline/index.js.map +1 -1
- package/node_modules/checkride/dist/baseline/store.d.ts +12 -4
- package/node_modules/checkride/dist/baseline/store.d.ts.map +1 -1
- package/node_modules/checkride/dist/baseline/store.js +16 -9
- package/node_modules/checkride/dist/baseline/store.js.map +1 -1
- package/node_modules/checkride/dist/baseline-command.d.ts +5 -5
- package/node_modules/checkride/dist/baseline-command.js +7 -7
- package/node_modules/checkride/dist/baseline-command.js.map +1 -1
- package/node_modules/checkride/dist/cli.d.ts +17 -4
- package/node_modules/checkride/dist/cli.d.ts.map +1 -1
- package/node_modules/checkride/dist/cli.js +259 -18
- package/node_modules/checkride/dist/cli.js.map +1 -1
- package/node_modules/checkride/dist/config.d.ts +84 -8
- package/node_modules/checkride/dist/config.d.ts.map +1 -1
- package/node_modules/checkride/dist/config.js +122 -18
- package/node_modules/checkride/dist/config.js.map +1 -1
- package/node_modules/checkride/dist/digest/digest.d.ts +5 -5
- package/node_modules/checkride/dist/digest/digest.js +5 -5
- package/node_modules/checkride/dist/digest/index.d.ts +2 -2
- package/node_modules/checkride/dist/digest/index.js +2 -2
- package/node_modules/checkride/dist/doctor.d.ts +25 -6
- package/node_modules/checkride/dist/doctor.d.ts.map +1 -1
- package/node_modules/checkride/dist/doctor.js +193 -27
- package/node_modules/checkride/dist/doctor.js.map +1 -1
- package/node_modules/checkride/dist/gate.d.ts +135 -0
- package/node_modules/checkride/dist/gate.d.ts.map +1 -0
- package/node_modules/checkride/dist/gate.js +490 -0
- package/node_modules/checkride/dist/gate.js.map +1 -0
- package/node_modules/checkride/dist/init.d.ts +72 -12
- package/node_modules/checkride/dist/init.d.ts.map +1 -1
- package/node_modules/checkride/dist/init.js +324 -81
- package/node_modules/checkride/dist/init.js.map +1 -1
- package/node_modules/checkride/dist/json.d.ts +21 -0
- package/node_modules/checkride/dist/json.d.ts.map +1 -0
- package/node_modules/checkride/dist/json.js +21 -0
- package/node_modules/checkride/dist/json.js.map +1 -0
- package/node_modules/checkride/dist/links.d.ts +31 -5
- package/node_modules/checkride/dist/links.d.ts.map +1 -1
- package/node_modules/checkride/dist/links.js +141 -32
- package/node_modules/checkride/dist/links.js.map +1 -1
- package/node_modules/checkride/dist/node-pin.d.ts +129 -0
- package/node_modules/checkride/dist/node-pin.d.ts.map +1 -0
- package/node_modules/checkride/dist/node-pin.js +211 -0
- package/node_modules/checkride/dist/node-pin.js.map +1 -0
- package/node_modules/checkride/dist/orchestrator.d.ts +40 -10
- package/node_modules/checkride/dist/orchestrator.d.ts.map +1 -1
- package/node_modules/checkride/dist/orchestrator.js +196 -102
- package/node_modules/checkride/dist/orchestrator.js.map +1 -1
- package/node_modules/checkride/dist/pack.d.ts +8 -9
- package/node_modules/checkride/dist/pack.d.ts.map +1 -1
- package/node_modules/checkride/dist/pack.js +53 -17
- package/node_modules/checkride/dist/pack.js.map +1 -1
- package/node_modules/checkride/dist/pm/detect.d.ts +6 -1
- package/node_modules/checkride/dist/pm/detect.d.ts.map +1 -1
- package/node_modules/checkride/dist/pm/detect.js +6 -1
- package/node_modules/checkride/dist/pm/detect.js.map +1 -1
- package/node_modules/checkride/dist/pm/index.d.ts +6 -2
- package/node_modules/checkride/dist/pm/index.d.ts.map +1 -1
- package/node_modules/checkride/dist/pm/index.js +6 -2
- package/node_modules/checkride/dist/pm/index.js.map +1 -1
- package/node_modules/checkride/dist/pm/launch.d.ts +51 -0
- package/node_modules/checkride/dist/pm/launch.d.ts.map +1 -0
- package/node_modules/checkride/dist/pm/launch.js +92 -0
- package/node_modules/checkride/dist/pm/launch.js.map +1 -0
- package/node_modules/checkride/dist/pm/tools.d.ts +73 -0
- package/node_modules/checkride/dist/pm/tools.d.ts.map +1 -0
- package/node_modules/checkride/dist/pm/tools.js +124 -0
- package/node_modules/checkride/dist/pm/tools.js.map +1 -0
- package/node_modules/checkride/dist/pm/translate.d.ts +35 -9
- package/node_modules/checkride/dist/pm/translate.d.ts.map +1 -1
- package/node_modules/checkride/dist/pm/translate.js +78 -18
- package/node_modules/checkride/dist/pm/translate.js.map +1 -1
- package/node_modules/checkride/dist/proc.d.ts +30 -0
- package/node_modules/checkride/dist/proc.d.ts.map +1 -0
- package/node_modules/checkride/dist/proc.js +42 -0
- package/node_modules/checkride/dist/proc.js.map +1 -0
- package/node_modules/checkride/dist/qa/cli.d.ts +20 -0
- package/node_modules/checkride/dist/qa/cli.d.ts.map +1 -0
- package/node_modules/checkride/dist/qa/cli.js +24 -0
- package/node_modules/checkride/dist/qa/cli.js.map +1 -0
- package/node_modules/checkride/dist/qa/dead.d.ts +39 -0
- package/node_modules/checkride/dist/qa/dead.d.ts.map +1 -0
- package/node_modules/checkride/dist/qa/dead.js +88 -0
- package/node_modules/checkride/dist/qa/dead.js.map +1 -0
- package/node_modules/checkride/dist/qa/dupes.d.ts +45 -0
- package/node_modules/checkride/dist/qa/dupes.d.ts.map +1 -0
- package/node_modules/checkride/dist/qa/dupes.js +62 -0
- package/node_modules/checkride/dist/qa/dupes.js.map +1 -0
- package/node_modules/checkride/dist/qa/health.d.ts +85 -0
- package/node_modules/checkride/dist/qa/health.d.ts.map +1 -0
- package/node_modules/checkride/dist/qa/health.js +109 -0
- package/node_modules/checkride/dist/qa/health.js.map +1 -0
- package/node_modules/checkride/dist/qa/index.d.ts +23 -0
- package/node_modules/checkride/dist/qa/index.d.ts.map +1 -0
- package/node_modules/checkride/dist/qa/index.js +22 -0
- package/node_modules/checkride/dist/qa/index.js.map +1 -0
- package/node_modules/checkride/dist/qa/mutation.d.ts +80 -0
- package/node_modules/checkride/dist/qa/mutation.d.ts.map +1 -0
- package/node_modules/checkride/dist/qa/mutation.js +195 -0
- package/node_modules/checkride/dist/qa/mutation.js.map +1 -0
- package/node_modules/checkride/dist/qa/qa.d.ts +71 -0
- package/node_modules/checkride/dist/qa/qa.d.ts.map +1 -0
- package/node_modules/checkride/dist/qa/qa.js +158 -0
- package/node_modules/checkride/dist/qa/qa.js.map +1 -0
- package/node_modules/checkride/dist/qa/read.d.ts +40 -0
- package/node_modules/checkride/dist/qa/read.d.ts.map +1 -0
- package/node_modules/checkride/dist/qa/read.js +47 -0
- package/node_modules/checkride/dist/qa/read.js.map +1 -0
- package/node_modules/checkride/dist/qa/render.d.ts +26 -0
- package/node_modules/checkride/dist/qa/render.d.ts.map +1 -0
- package/node_modules/checkride/dist/qa/render.js +310 -0
- package/node_modules/checkride/dist/qa/render.js.map +1 -0
- package/node_modules/checkride/dist/security.d.ts +45 -0
- package/node_modules/checkride/dist/security.d.ts.map +1 -0
- package/node_modules/checkride/dist/security.js +86 -0
- package/node_modules/checkride/dist/security.js.map +1 -0
- package/node_modules/checkride/dist/smoke.d.ts +5 -5
- package/node_modules/checkride/dist/smoke.js +5 -5
- package/node_modules/checkride/dist/snippets.d.ts +26 -29
- package/node_modules/checkride/dist/snippets.d.ts.map +1 -1
- package/node_modules/checkride/dist/snippets.js +26 -30
- package/node_modules/checkride/dist/snippets.js.map +1 -1
- package/node_modules/checkride/dist/tool-json.d.ts +33 -0
- package/node_modules/checkride/dist/tool-json.d.ts.map +1 -0
- package/node_modules/checkride/dist/tool-json.js +58 -0
- package/node_modules/checkride/dist/tool-json.js.map +1 -0
- package/node_modules/checkride/dist/triage/cli.d.ts +21 -0
- package/node_modules/checkride/dist/triage/cli.d.ts.map +1 -0
- package/node_modules/checkride/dist/triage/cli.js +26 -0
- package/node_modules/checkride/dist/triage/cli.js.map +1 -0
- package/node_modules/checkride/dist/triage/doctor-fold.d.ts +51 -0
- package/node_modules/checkride/dist/triage/doctor-fold.d.ts.map +1 -0
- package/node_modules/checkride/dist/triage/doctor-fold.js +88 -0
- package/node_modules/checkride/dist/triage/doctor-fold.js.map +1 -0
- package/node_modules/checkride/dist/triage/env.d.ts +54 -0
- package/node_modules/checkride/dist/triage/env.d.ts.map +1 -0
- package/node_modules/checkride/dist/triage/env.js +81 -0
- package/node_modules/checkride/dist/triage/env.js.map +1 -0
- package/node_modules/checkride/dist/triage/gate.d.ts +61 -0
- package/node_modules/checkride/dist/triage/gate.d.ts.map +1 -0
- package/node_modules/checkride/dist/triage/gate.js +121 -0
- package/node_modules/checkride/dist/triage/gate.js.map +1 -0
- package/node_modules/checkride/dist/triage/index.d.ts +22 -0
- package/node_modules/checkride/dist/triage/index.d.ts.map +1 -0
- package/node_modules/checkride/dist/triage/index.js +20 -0
- package/node_modules/checkride/dist/triage/index.js.map +1 -0
- package/node_modules/checkride/dist/triage/render.d.ts +19 -0
- package/node_modules/checkride/dist/triage/render.d.ts.map +1 -0
- package/node_modules/checkride/dist/triage/render.js +419 -0
- package/node_modules/checkride/dist/triage/render.js.map +1 -0
- package/node_modules/checkride/dist/triage/triage.d.ts +83 -0
- package/node_modules/checkride/dist/triage/triage.d.ts.map +1 -0
- package/node_modules/checkride/dist/triage/triage.js +131 -0
- package/node_modules/checkride/dist/triage/triage.js.map +1 -0
- package/node_modules/checkride/package.json +17 -15
- package/node_modules/checkride/schema/checkride.config.schema.json +62 -5
- package/node_modules/checkride/schema/checkride.summary.schema.json +1 -1
- package/node_modules/checkride/skills/check/SKILL.md +257 -0
- package/node_modules/checkride/skills/qa/SKILL.md +231 -0
- package/node_modules/checkride/templates/shared/cspell.json +1 -0
- package/node_modules/checkride/templates/shared/oxlintrc.json +1 -1
- package/package.json +2 -2
- package/skills/build/SKILL.md +23 -19
- package/skills/finish/SKILL.md +3 -1
- package/skills/harvest/SKILL.md +2 -1
- package/skills/plan/SKILL.md +8 -7
- package/skills/recover/SKILL.md +28 -0
- package/skills/refine/SKILL.md +5 -4
- package/skills/spike/SKILL.md +1 -1
- package/skills/step/SKILL.md +4 -4
- package/skills/verify/SKILL.md +19 -14
- package/templates/intent.md +8 -7
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `dupes.json` — fallow's duplication report. The smallest of the four
|
|
3
|
+
* artifacts (483 B when clean here) and the one most able to explode: every
|
|
4
|
+
* clone instance carries a `fragment` holding the duplicated *source text*, so
|
|
5
|
+
* a report with real findings is mostly code.
|
|
6
|
+
*
|
|
7
|
+
* None of that text is extracted. What a reader needs is where the duplication
|
|
8
|
+
* is and how much of it there is — so a family reduces to its file membership
|
|
9
|
+
* and its line and token totals, and the fragments stay on disk.
|
|
10
|
+
*
|
|
11
|
+
* Families, not groups, are the unit: fallow groups clones by content and then
|
|
12
|
+
* collects the groups that span the same files into a family, which is the
|
|
13
|
+
* level a refactor actually happens at. The group count still reports, because
|
|
14
|
+
* that is what checkride gates the slot on.
|
|
15
|
+
*
|
|
16
|
+
* The `../qa` barrel is this module's only public surface.
|
|
17
|
+
*/
|
|
18
|
+
/** A set of files sharing duplicated code. */
|
|
19
|
+
export type CloneFamily = {
|
|
20
|
+
files: string[];
|
|
21
|
+
/** Files past {@link FILES_PER_FAMILY}, so the list never implies completeness. */
|
|
22
|
+
omittedFiles: number;
|
|
23
|
+
groups: number;
|
|
24
|
+
lines: number | null;
|
|
25
|
+
tokens: number | null;
|
|
26
|
+
};
|
|
27
|
+
export type DupesExtract = {
|
|
28
|
+
duplicationPercentage: number | null;
|
|
29
|
+
duplicatedLines: number | null;
|
|
30
|
+
totalLines: number | null;
|
|
31
|
+
totalFiles: number | null;
|
|
32
|
+
filesWithClones: number | null;
|
|
33
|
+
/** Clone groups — the count checkride gates the `dupes` slot on. */
|
|
34
|
+
cloneGroups: number;
|
|
35
|
+
totalFamilies: number;
|
|
36
|
+
families: CloneFamily[];
|
|
37
|
+
omittedFamilies: number;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Fold a parsed `dupes.json` into the report model, or `null` when it has no
|
|
41
|
+
* `clone_groups` array — the field checkride's own verdict reads, so a report
|
|
42
|
+
* without it is not a dupes report and must not be summarized as clean.
|
|
43
|
+
*/
|
|
44
|
+
export declare function extractDupes(value: Record<string, unknown>): DupesExtract | null;
|
|
45
|
+
//# sourceMappingURL=dupes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dupes.d.ts","sourceRoot":"","sources":["../../src/qa/dupes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AASH,8CAA8C;AAC9C,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,mFAAmF;IACnF,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAwBF;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY,GAAG,IAAI,CAiBhF"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `dupes.json` — fallow's duplication report. The smallest of the four
|
|
3
|
+
* artifacts (483 B when clean here) and the one most able to explode: every
|
|
4
|
+
* clone instance carries a `fragment` holding the duplicated *source text*, so
|
|
5
|
+
* a report with real findings is mostly code.
|
|
6
|
+
*
|
|
7
|
+
* None of that text is extracted. What a reader needs is where the duplication
|
|
8
|
+
* is and how much of it there is — so a family reduces to its file membership
|
|
9
|
+
* and its line and token totals, and the fragments stay on disk.
|
|
10
|
+
*
|
|
11
|
+
* Families, not groups, are the unit: fallow groups clones by content and then
|
|
12
|
+
* collects the groups that span the same files into a family, which is the
|
|
13
|
+
* level a refactor actually happens at. The group count still reports, because
|
|
14
|
+
* that is what checkride gates the slot on.
|
|
15
|
+
*
|
|
16
|
+
* The `../qa` barrel is this module's only public surface.
|
|
17
|
+
*/
|
|
18
|
+
import { asNumberOrNull, asRecord, asRecordArray } from '../artifacts/index.js';
|
|
19
|
+
/** Families listed; the rest are counted. */
|
|
20
|
+
const TOP_FAMILIES = 6;
|
|
21
|
+
/** Files named per family before the rest collapse to a count. */
|
|
22
|
+
const FILES_PER_FAMILY = 4;
|
|
23
|
+
function readFamily(family) {
|
|
24
|
+
const files = (Array.isArray(family['files']) ? family['files'] : []).filter((file) => typeof file === 'string');
|
|
25
|
+
return {
|
|
26
|
+
files: files.slice(0, FILES_PER_FAMILY),
|
|
27
|
+
omittedFiles: Math.max(0, files.length - FILES_PER_FAMILY),
|
|
28
|
+
groups: asRecordArray(family['groups']).length,
|
|
29
|
+
lines: asNumberOrNull(family['total_duplicated_lines']),
|
|
30
|
+
tokens: asNumberOrNull(family['total_duplicated_tokens']),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** Worst first: most duplicated lines, then most files, then by name. */
|
|
34
|
+
function byWeight(a, b) {
|
|
35
|
+
return ((b.lines ?? 0) - (a.lines ?? 0) ||
|
|
36
|
+
b.files.length - a.files.length ||
|
|
37
|
+
(a.files[0] ?? '').localeCompare(b.files[0] ?? ''));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Fold a parsed `dupes.json` into the report model, or `null` when it has no
|
|
41
|
+
* `clone_groups` array — the field checkride's own verdict reads, so a report
|
|
42
|
+
* without it is not a dupes report and must not be summarized as clean.
|
|
43
|
+
*/
|
|
44
|
+
export function extractDupes(value) {
|
|
45
|
+
const groups = value['clone_groups'];
|
|
46
|
+
if (!Array.isArray(groups))
|
|
47
|
+
return null;
|
|
48
|
+
const stats = asRecord(value['stats']);
|
|
49
|
+
const families = asRecordArray(value['clone_families']).map(readFamily).toSorted(byWeight);
|
|
50
|
+
return {
|
|
51
|
+
duplicationPercentage: asNumberOrNull(stats['duplication_percentage']),
|
|
52
|
+
duplicatedLines: asNumberOrNull(stats['duplicated_lines']),
|
|
53
|
+
totalLines: asNumberOrNull(stats['total_lines']),
|
|
54
|
+
totalFiles: asNumberOrNull(stats['total_files']),
|
|
55
|
+
filesWithClones: asNumberOrNull(stats['files_with_clones']),
|
|
56
|
+
cloneGroups: groups.length,
|
|
57
|
+
totalFamilies: families.length,
|
|
58
|
+
families: families.slice(0, TOP_FAMILIES),
|
|
59
|
+
omittedFamilies: Math.max(0, families.length - TOP_FAMILIES),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=dupes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dupes.js","sourceRoot":"","sources":["../../src/qa/dupes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEhF,6CAA6C;AAC7C,MAAM,YAAY,GAAG,CAAC,CAAC;AACvB,kEAAkE;AAClE,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAyB3B,SAAS,UAAU,CAAC,MAA+B;IACjD,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAC1E,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CACnD,CAAC;IACF,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC;QACvC,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,gBAAgB,CAAC;QAC1D,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM;QAC9C,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC;QACvD,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,yBAAyB,CAAC,CAAC;KAC1D,CAAC;AACJ,CAAC;AAED,yEAAyE;AACzE,SAAS,QAAQ,CAAC,CAAc,EAAE,CAAc;IAC9C,OAAO,CACL,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;QAC/B,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM;QAC/B,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CACnD,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,KAA8B;IACzD,MAAM,MAAM,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;IACrC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAExC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC3F,OAAO;QACL,qBAAqB,EAAE,cAAc,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;QACtE,eAAe,EAAE,cAAc,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAC1D,UAAU,EAAE,cAAc,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAChD,UAAU,EAAE,cAAc,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAChD,eAAe,EAAE,cAAc,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAC3D,WAAW,EAAE,MAAM,CAAC,MAAM;QAC1B,aAAa,EAAE,QAAQ,CAAC,MAAM;QAC9B,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC;QACzC,eAAe,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,GAAG,YAAY,CAAC;KAC7D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `health.json` — fallow's complexity and maintainability report, ~50 KB of
|
|
3
|
+
* which perhaps twenty numbers are worth an agent's attention.
|
|
4
|
+
*
|
|
5
|
+
* The score is the headline, but a bare `80.7/B` is not actionable: fallow
|
|
6
|
+
* computes it by subtracting named penalties from 100, and the *non-zero*
|
|
7
|
+
* penalties are the whole explanation of the grade. Reporting them ranked, with
|
|
8
|
+
* the zeroes counted rather than listed, turns "the score is B" into "hotspots
|
|
9
|
+
* cost 10 points and unit size cost 8.5" — which names what to fix.
|
|
10
|
+
*
|
|
11
|
+
* Per-function findings are the other half. fallow gates on four independent
|
|
12
|
+
* thresholds (cyclomatic, cognitive, CRAP, unit size) and each finding says in
|
|
13
|
+
* `exceeded` which one it breached, so the findings group by that rather than
|
|
14
|
+
* collapsing into an undifferentiated count: a function over the size threshold
|
|
15
|
+
* and one over CRAP want different fixes.
|
|
16
|
+
*
|
|
17
|
+
* Hotspots (complex *and* frequently changed) are ranked by fallow's own score
|
|
18
|
+
* and capped — they are the input to the fragility judgment the skill makes,
|
|
19
|
+
* not a judgment this reader should be making.
|
|
20
|
+
*
|
|
21
|
+
* The `../qa` barrel is this module's only public surface.
|
|
22
|
+
*/
|
|
23
|
+
/** One named penalty subtracted from a perfect 100. */
|
|
24
|
+
export type Penalty = {
|
|
25
|
+
name: string;
|
|
26
|
+
points: number;
|
|
27
|
+
};
|
|
28
|
+
/** One function over one of fallow's four thresholds. */
|
|
29
|
+
export type HealthFinding = {
|
|
30
|
+
path: string;
|
|
31
|
+
name: string;
|
|
32
|
+
line: number | null;
|
|
33
|
+
/** Which threshold it breached: `cyclomatic`, `cognitive`, `crap`, `unit_size`. */
|
|
34
|
+
exceeded: string;
|
|
35
|
+
severity: string;
|
|
36
|
+
cyclomatic: number | null;
|
|
37
|
+
cognitive: number | null;
|
|
38
|
+
lineCount: number | null;
|
|
39
|
+
};
|
|
40
|
+
/** A file that is both complex and frequently changed. */
|
|
41
|
+
export type Hotspot = {
|
|
42
|
+
path: string;
|
|
43
|
+
score: number | null;
|
|
44
|
+
commits: number | null;
|
|
45
|
+
complexityDensity: number | null;
|
|
46
|
+
trend: string;
|
|
47
|
+
};
|
|
48
|
+
/** The four thresholds a `health` finding can breach, as configured. */
|
|
49
|
+
export type Thresholds = {
|
|
50
|
+
cyclomatic: number | null;
|
|
51
|
+
cognitive: number | null;
|
|
52
|
+
crap: number | null;
|
|
53
|
+
unitSize: number | null;
|
|
54
|
+
};
|
|
55
|
+
export type HealthExtract = {
|
|
56
|
+
score: number | null;
|
|
57
|
+
grade: string;
|
|
58
|
+
formulaVersion: number | null;
|
|
59
|
+
/** Non-zero penalties, worst first — the score's actual causes. */
|
|
60
|
+
penalties: Penalty[];
|
|
61
|
+
/** Penalties that scored zero, counted rather than listed. */
|
|
62
|
+
zeroPenalties: number;
|
|
63
|
+
filesAnalyzed: number | null;
|
|
64
|
+
functionsAnalyzed: number | null;
|
|
65
|
+
averageMaintainability: number | null;
|
|
66
|
+
thresholds: Thresholds;
|
|
67
|
+
totalFindings: number;
|
|
68
|
+
findings: HealthFinding[];
|
|
69
|
+
omittedFindings: number;
|
|
70
|
+
/** Findings per breached threshold, worst first — covers the omitted ones too. */
|
|
71
|
+
byThreshold: {
|
|
72
|
+
exceeded: string;
|
|
73
|
+
count: number;
|
|
74
|
+
}[];
|
|
75
|
+
totalHotspots: number;
|
|
76
|
+
hotspots: Hotspot[];
|
|
77
|
+
omittedHotspots: number;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Fold a parsed `health.json` into the report model, or `null` when it carries
|
|
81
|
+
* no `health_score` block — that is not a fallow health report, and saying so
|
|
82
|
+
* beats reporting a zero score that reads like a finding.
|
|
83
|
+
*/
|
|
84
|
+
export declare function extractHealth(value: Record<string, unknown>): HealthExtract | null;
|
|
85
|
+
//# sourceMappingURL=health.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/qa/health.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AASH,uDAAuD;AACvD,MAAM,MAAM,OAAO,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD,yDAAyD;AACzD,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,mFAAmF;IACnF,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AAEF,0DAA0D;AAC1D,MAAM,MAAM,OAAO,GAAG;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wEAAwE;AACxE,MAAM,MAAM,UAAU,GAAG;IACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,mEAAmE;IACnE,SAAS,EAAE,OAAO,EAAE,CAAC;IACrB,8DAA8D;IAC9D,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,UAAU,EAAE,UAAU,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,kFAAkF;IAClF,WAAW,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACnD,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAuDF;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,GAAG,IAAI,CA2BlF"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `health.json` — fallow's complexity and maintainability report, ~50 KB of
|
|
3
|
+
* which perhaps twenty numbers are worth an agent's attention.
|
|
4
|
+
*
|
|
5
|
+
* The score is the headline, but a bare `80.7/B` is not actionable: fallow
|
|
6
|
+
* computes it by subtracting named penalties from 100, and the *non-zero*
|
|
7
|
+
* penalties are the whole explanation of the grade. Reporting them ranked, with
|
|
8
|
+
* the zeroes counted rather than listed, turns "the score is B" into "hotspots
|
|
9
|
+
* cost 10 points and unit size cost 8.5" — which names what to fix.
|
|
10
|
+
*
|
|
11
|
+
* Per-function findings are the other half. fallow gates on four independent
|
|
12
|
+
* thresholds (cyclomatic, cognitive, CRAP, unit size) and each finding says in
|
|
13
|
+
* `exceeded` which one it breached, so the findings group by that rather than
|
|
14
|
+
* collapsing into an undifferentiated count: a function over the size threshold
|
|
15
|
+
* and one over CRAP want different fixes.
|
|
16
|
+
*
|
|
17
|
+
* Hotspots (complex *and* frequently changed) are ranked by fallow's own score
|
|
18
|
+
* and capped — they are the input to the fragility judgment the skill makes,
|
|
19
|
+
* not a judgment this reader should be making.
|
|
20
|
+
*
|
|
21
|
+
* The `../qa` barrel is this module's only public surface.
|
|
22
|
+
*/
|
|
23
|
+
import { asNumberOrNull as num, asRecord, asRecordArray, asStringOrNull, isRecord } from '../artifacts/index.js';
|
|
24
|
+
/** Findings listed individually before they collapse to counts by threshold. */
|
|
25
|
+
const TOP_FINDINGS = 8;
|
|
26
|
+
/** Hotspots listed; the rest are counted. */
|
|
27
|
+
const TOP_HOTSPOTS = 6;
|
|
28
|
+
/** Non-zero penalties, worst first, plus how many scored zero. */
|
|
29
|
+
function readPenalties(scoreBlock) {
|
|
30
|
+
const entries = Object.entries(asRecord(scoreBlock['penalties']))
|
|
31
|
+
.map(([name, value]) => ({ name, points: num(value) ?? 0 }));
|
|
32
|
+
return {
|
|
33
|
+
penalties: entries
|
|
34
|
+
.filter((p) => p.points > 0)
|
|
35
|
+
.toSorted((a, b) => b.points - a.points || a.name.localeCompare(b.name)),
|
|
36
|
+
zeroPenalties: entries.filter((p) => p.points <= 0).length,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function readThresholds(summary) {
|
|
40
|
+
return {
|
|
41
|
+
cyclomatic: num(summary['max_cyclomatic_threshold']),
|
|
42
|
+
cognitive: num(summary['max_cognitive_threshold']),
|
|
43
|
+
crap: num(summary['max_crap_threshold']),
|
|
44
|
+
unitSize: num(summary['max_unit_size_threshold']),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function readFinding(finding) {
|
|
48
|
+
return {
|
|
49
|
+
path: asStringOrNull(finding['path']) ?? '?',
|
|
50
|
+
name: asStringOrNull(finding['name']) ?? '?',
|
|
51
|
+
line: num(finding['line']),
|
|
52
|
+
exceeded: asStringOrNull(finding['exceeded']) ?? 'unknown',
|
|
53
|
+
severity: asStringOrNull(finding['severity']) ?? 'unknown',
|
|
54
|
+
cyclomatic: num(finding['cyclomatic']),
|
|
55
|
+
cognitive: num(finding['cognitive']),
|
|
56
|
+
lineCount: num(finding['line_count']),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/** Every finding grouped by the threshold it breached, worst-populated first. */
|
|
60
|
+
function groupByThreshold(findings) {
|
|
61
|
+
const counts = new Map();
|
|
62
|
+
for (const finding of findings)
|
|
63
|
+
counts.set(finding.exceeded, (counts.get(finding.exceeded) ?? 0) + 1);
|
|
64
|
+
return [...counts]
|
|
65
|
+
.map(([exceeded, count]) => ({ exceeded, count }))
|
|
66
|
+
.toSorted((a, b) => b.count - a.count || a.exceeded.localeCompare(b.exceeded));
|
|
67
|
+
}
|
|
68
|
+
function readHotspot(hotspot) {
|
|
69
|
+
return {
|
|
70
|
+
path: asStringOrNull(hotspot['path']) ?? '?',
|
|
71
|
+
score: num(hotspot['score']),
|
|
72
|
+
commits: num(hotspot['commits']),
|
|
73
|
+
complexityDensity: num(hotspot['complexity_density']),
|
|
74
|
+
trend: asStringOrNull(hotspot['trend']) ?? 'unknown',
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Fold a parsed `health.json` into the report model, or `null` when it carries
|
|
79
|
+
* no `health_score` block — that is not a fallow health report, and saying so
|
|
80
|
+
* beats reporting a zero score that reads like a finding.
|
|
81
|
+
*/
|
|
82
|
+
export function extractHealth(value) {
|
|
83
|
+
const scoreBlock = value['health_score'];
|
|
84
|
+
if (!isRecord(scoreBlock))
|
|
85
|
+
return null;
|
|
86
|
+
const summary = asRecord(value['summary']);
|
|
87
|
+
const { penalties, zeroPenalties } = readPenalties(scoreBlock);
|
|
88
|
+
const findings = asRecordArray(value['findings']).map(readFinding);
|
|
89
|
+
const hotspots = asRecordArray(value['hotspots']).map(readHotspot);
|
|
90
|
+
return {
|
|
91
|
+
score: num(scoreBlock['score']),
|
|
92
|
+
grade: asStringOrNull(scoreBlock['grade']) ?? '?',
|
|
93
|
+
formulaVersion: num(scoreBlock['formula_version']),
|
|
94
|
+
penalties,
|
|
95
|
+
zeroPenalties,
|
|
96
|
+
filesAnalyzed: num(summary['files_analyzed']),
|
|
97
|
+
functionsAnalyzed: num(summary['functions_analyzed']),
|
|
98
|
+
averageMaintainability: num(summary['average_maintainability']),
|
|
99
|
+
thresholds: readThresholds(summary),
|
|
100
|
+
totalFindings: findings.length,
|
|
101
|
+
findings: findings.slice(0, TOP_FINDINGS),
|
|
102
|
+
omittedFindings: Math.max(0, findings.length - TOP_FINDINGS),
|
|
103
|
+
byThreshold: groupByThreshold(findings),
|
|
104
|
+
totalHotspots: hotspots.length,
|
|
105
|
+
hotspots: hotspots.slice(0, TOP_HOTSPOTS),
|
|
106
|
+
omittedHotspots: Math.max(0, hotspots.length - TOP_HOTSPOTS),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/qa/health.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,cAAc,IAAI,GAAG,EAAE,QAAQ,EAAE,aAAa,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjH,gFAAgF;AAChF,MAAM,YAAY,GAAG,CAAC,CAAC;AACvB,6CAA6C;AAC7C,MAAM,YAAY,GAAG,CAAC,CAAC;AAyDvB,kEAAkE;AAClE,SAAS,aAAa,CAAC,UAAmC;IACxD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;SAC9D,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/D,OAAO;QACL,SAAS,EAAE,OAAO;aACf,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;aAC3B,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC1E,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,MAAM;KAC3D,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,OAAgC;IACtD,OAAO;QACL,UAAU,EAAE,GAAG,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;QACpD,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;QAClD,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QACxC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;KAClD,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,OAAgC;IACnD,OAAO;QACL,IAAI,EAAE,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,GAAG;QAC5C,IAAI,EAAE,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,GAAG;QAC5C,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC1B,QAAQ,EAAE,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,IAAI,SAAS;QAC1D,QAAQ,EAAE,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,IAAI,SAAS;QAC1D,UAAU,EAAE,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACtC,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QACpC,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;KACtC,CAAC;AACJ,CAAC;AAED,iFAAiF;AACjF,SAAS,gBAAgB,CAAC,QAAkC;IAC1D,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,OAAO,IAAI,QAAQ;QAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACtG,OAAO,CAAC,GAAG,MAAM,CAAC;SACf,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;SACjD,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;AACnF,CAAC;AAED,SAAS,WAAW,CAAC,OAAgC;IACnD,OAAO;QACL,IAAI,EAAE,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,GAAG;QAC5C,KAAK,EAAE,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC5B,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAChC,iBAAiB,EAAE,GAAG,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QACrD,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,SAAS;KACrD,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAA8B;IAC1D,MAAM,UAAU,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;IACzC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IAEvC,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAC3C,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;IAC/D,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACnE,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAEnE,OAAO;QACL,KAAK,EAAE,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAC/B,KAAK,EAAE,cAAc,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,GAAG;QACjD,cAAc,EAAE,GAAG,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;QAClD,SAAS;QACT,aAAa;QACb,aAAa,EAAE,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAC7C,iBAAiB,EAAE,GAAG,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QACrD,sBAAsB,EAAE,GAAG,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;QAC/D,UAAU,EAAE,cAAc,CAAC,OAAO,CAAC;QACnC,aAAa,EAAE,QAAQ,CAAC,MAAM;QAC9B,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC;QACzC,eAAe,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,GAAG,YAAY,CAAC;QAC5D,WAAW,EAAE,gBAAgB,CAAC,QAAQ,CAAC;QACvC,aAAa,EAAE,QAAQ,CAAC,MAAM;QAC9B,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC;QACzC,eAAe,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,GAAG,YAAY,CAAC;KAC7D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quality module — the bundled plugin's reader for the four artifacts
|
|
3
|
+
* checkride already writes about code quality: `mutation`, `dead`, `dupes` and
|
|
4
|
+
* `health`. Named for the skill it serves, as `../triage` is.
|
|
5
|
+
*
|
|
6
|
+
* It runs nothing (D2). It opens what a previous run left in `.check/`, folds
|
|
7
|
+
* each artifact to a short, ranked list, and says plainly which of the four is
|
|
8
|
+
* evidence and which is stale, absent, or from a slot the repo never opted into
|
|
9
|
+
* — the normal case, not the edge case, since three of the four are opt-in.
|
|
10
|
+
*
|
|
11
|
+
* `./cli.ts` is the executable form (`node dist/qa/cli.js`); this
|
|
12
|
+
* barrel is the module's programmatic surface, and files inside the module
|
|
13
|
+
* import each other directly rather than through it.
|
|
14
|
+
*/
|
|
15
|
+
export { extractDead } from './dead.js';
|
|
16
|
+
export { extractDupes } from './dupes.js';
|
|
17
|
+
export { extractHealth } from './health.js';
|
|
18
|
+
export { extractMutation } from './mutation.js';
|
|
19
|
+
export { qaExtract } from './qa.js';
|
|
20
|
+
export type { QaReport } from './qa.js';
|
|
21
|
+
export { readJsonArtifact } from './read.js';
|
|
22
|
+
export { QA_MAX_BYTES, renderQa } from './render.js';
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/qa/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quality module — the bundled plugin's reader for the four artifacts
|
|
3
|
+
* checkride already writes about code quality: `mutation`, `dead`, `dupes` and
|
|
4
|
+
* `health`. Named for the skill it serves, as `../triage` is.
|
|
5
|
+
*
|
|
6
|
+
* It runs nothing (D2). It opens what a previous run left in `.check/`, folds
|
|
7
|
+
* each artifact to a short, ranked list, and says plainly which of the four is
|
|
8
|
+
* evidence and which is stale, absent, or from a slot the repo never opted into
|
|
9
|
+
* — the normal case, not the edge case, since three of the four are opt-in.
|
|
10
|
+
*
|
|
11
|
+
* `./cli.ts` is the executable form (`node dist/qa/cli.js`); this
|
|
12
|
+
* barrel is the module's programmatic surface, and files inside the module
|
|
13
|
+
* import each other directly rather than through it.
|
|
14
|
+
*/
|
|
15
|
+
export { extractDead } from './dead.js';
|
|
16
|
+
export { extractDupes } from './dupes.js';
|
|
17
|
+
export { extractHealth } from './health.js';
|
|
18
|
+
export { extractMutation } from './mutation.js';
|
|
19
|
+
export { qaExtract } from './qa.js';
|
|
20
|
+
export { readJsonArtifact } from './read.js';
|
|
21
|
+
export { QA_MAX_BYTES, renderQa } from './render.js';
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/qa/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAGpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `mutation.json` — 2.3 MB and 4453 mutants in this repo — folded into a short
|
|
3
|
+
* list an agent can act on.
|
|
4
|
+
*
|
|
5
|
+
* The scores are stryker's own, computed the way stryker computes them, so the
|
|
6
|
+
* numbers here match the ones its reporter printed: `Ignored` (and any error
|
|
7
|
+
* status) leaves the denominator entirely, `Killed` and `Timeout` are detected,
|
|
8
|
+
* `Survived` and `NoCoverage` are not. Inventing a differently-defined score
|
|
9
|
+
* than the tool prints is the confidently-wrong answer this reader exists to
|
|
10
|
+
* prevent, so the arithmetic is pinned to the tool's.
|
|
11
|
+
*
|
|
12
|
+
* **The ranking is the judgment here.** 777 survivors is not a list anyone
|
|
13
|
+
* reads, so files rank by *undetected* count (`Survived` + `NoCoverage`)
|
|
14
|
+
* descending — that is what "where would tests buy the most" means — with the
|
|
15
|
+
* per-file score shown beside it so a small badly-tested file is still legible
|
|
16
|
+
* next to a large mostly-tested one. Ranking by score alone would put a
|
|
17
|
+
* two-mutant file at the top of a 4453-mutant report; ranking by count alone
|
|
18
|
+
* would say nothing but "the big files are big". Ties break on the worse score,
|
|
19
|
+
* then the path, so the same report always renders the same bytes.
|
|
20
|
+
*
|
|
21
|
+
* Two further cuts carry most of the signal at almost no byte cost. Splitting
|
|
22
|
+
* `NoCoverage` out from `Survived` separates "no test reaches this line" (add
|
|
23
|
+
* any test) from "a test reaches it and asserts nothing about it" (strengthen
|
|
24
|
+
* an assertion). And tallying undetected mutants *by mutator kind* separates
|
|
25
|
+
* real logic gaps (`ConditionalExpression`, `EqualityOperator`) from the
|
|
26
|
+
* `StringLiteral` churn in error messages that no one intends to assert on.
|
|
27
|
+
*
|
|
28
|
+
* The `../qa` barrel is this module's only public surface.
|
|
29
|
+
*/
|
|
30
|
+
/** One mutator kind and how many undetected mutants it accounts for. */
|
|
31
|
+
export type MutatorCount = {
|
|
32
|
+
mutator: string;
|
|
33
|
+
count: number;
|
|
34
|
+
};
|
|
35
|
+
/** An undetected mutant, located — enough to open the file at the right line. */
|
|
36
|
+
export type MutantSample = {
|
|
37
|
+
path: string;
|
|
38
|
+
line: number | null;
|
|
39
|
+
mutator: string;
|
|
40
|
+
status: string;
|
|
41
|
+
/** First line of the replacement, clipped; `…` marks anything left off. */
|
|
42
|
+
replacement: string;
|
|
43
|
+
};
|
|
44
|
+
/** One source file's mutation standing. */
|
|
45
|
+
export type MutationFile = {
|
|
46
|
+
path: string;
|
|
47
|
+
survived: number;
|
|
48
|
+
noCoverage: number;
|
|
49
|
+
/** Mutants that counted toward the score — detected plus undetected. */
|
|
50
|
+
tested: number;
|
|
51
|
+
/** Percentage, or `null` when no mutant in this file was testable. */
|
|
52
|
+
score: number | null;
|
|
53
|
+
mutators: MutatorCount[];
|
|
54
|
+
};
|
|
55
|
+
export type MutationExtract = {
|
|
56
|
+
killed: number;
|
|
57
|
+
timeout: number;
|
|
58
|
+
survived: number;
|
|
59
|
+
noCoverage: number;
|
|
60
|
+
ignored: number;
|
|
61
|
+
/** Compile/runtime errors and any status a future stryker adds. */
|
|
62
|
+
other: number;
|
|
63
|
+
total: number;
|
|
64
|
+
/** Stryker's headline: detected ÷ tested. `null` when nothing was testable. */
|
|
65
|
+
score: number | null;
|
|
66
|
+
/** Stryker's "score covered": the same, ignoring mutants no test reaches. */
|
|
67
|
+
scoreCovered: number | null;
|
|
68
|
+
totalFiles: number;
|
|
69
|
+
files: MutationFile[];
|
|
70
|
+
omittedFiles: number;
|
|
71
|
+
mutators: MutatorCount[];
|
|
72
|
+
samples: MutantSample[];
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Fold a parsed `mutation.json` into the report model, or `null` when it is not
|
|
76
|
+
* a stryker report (no `files` object) — the ledger reports that rather than
|
|
77
|
+
* this returning an empty extract that would read as "nothing survived".
|
|
78
|
+
*/
|
|
79
|
+
export declare function extractMutation(value: Record<string, unknown>): MutationExtract | null;
|
|
80
|
+
//# sourceMappingURL=mutation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutation.d.ts","sourceRoot":"","sources":["../../src/qa/mutation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAkBH,wEAAwE;AACxE,MAAM,MAAM,YAAY,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9D,iFAAiF;AACjF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,2CAA2C;AAC3C,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;IACf,sEAAsE;IACtE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,6EAA6E;IAC7E,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB,CAAC;AAuJF;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,GAAG,IAAI,CAsBtF"}
|