monocart-coverage-reports 3.2.0 → 3.2.1

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/README.md CHANGED
@@ -14,6 +14,7 @@
14
14
 
15
15
  * [Usage](#usage)
16
16
  * [Best Practices](#best-practices)
17
+ * [AI Agent Skill](#ai-agent-skill)
17
18
  * [Options](#options)
18
19
  * [Available Reports](#available-reports)
19
20
  * [Compare Reports](#compare-reports)
@@ -118,20 +119,21 @@ For detailed setup instructions and examples, see the [best-practices guide](ski
118
119
 
119
120
  ## AI Agent Skill
120
121
 
121
- For AI-assisted development in a source checkout, start with [AGENTS.md](https://github.com/cenfun/monocart-coverage-reports/blob/main/AGENTS.md). It describes the source layout, development commands, validation, and safety boundaries. `.github/copilot-instructions.md` provides a self-contained summary of the core rules for GitHub Copilot. These checkout-only guides are not included in the npm package and are separate from the reusable integration skill below.
122
+ **Reliable AI-assisted development starts with automated testing.** Test results validate behavior; coverage highlights testing gaps. With **`mcr test`**, AI coding agents can run Node.js tests, collect native V8 coverage, and generate reports without instrumentation. This feedback supports iterative development and CI/CD quality gates, whether an agent assists a developer or works autonomously.
122
123
 
123
- The reusable [Monocart Coverage Reports skill](skills/monocart-coverage-reports/SKILL.md) helps AI coding agents collect coverage, configure the CLI, debug sourcemaps and filters, merge raw reports, and enforce CI thresholds. It uses a main `SKILL.md` with task-specific references loaded on demand, targeting MCR 3.x only and checking its runtime requirements.
124
+ The [Monocart Coverage Reports skill](skills/monocart-coverage-reports/SKILL.md) guides agents through coverage collection, CLI configuration, sourcemap troubleshooting, report merging, and CI thresholds. It targets MCR 3.x and loads task-specific references on demand.
124
125
 
125
- The npm package includes `skills/monocart-coverage-reports/`. Copy this **entire directory**, including `references/`, into your agent's supported skills location, or ask the agent to read `SKILL.md` directly. Installing MCR does not automatically register the skill or modify agent settings. The instructions are in English; requests and responses can use any language.
126
+ The skill ships in the npm package. Copy the **entire `skills/monocart-coverage-reports/` directory**, including `references/`, into your agent's skills directory, or have the agent read `SKILL.md` directly. Installation does not automatically register the skill. The instructions are in English; you can use any language with your agent.
126
127
 
127
- From the host project root, locate the installed skill and package manifest (older releases may not include the skill):
128
+ Locate the installed skill from your project root:
128
129
 
129
130
  ```sh
130
131
  node -p "require.resolve('monocart-coverage-reports/skills/monocart-coverage-reports/SKILL.md')"
131
- node -p "require.resolve('monocart-coverage-reports/package.json')"
132
132
  ```
133
133
 
134
- Read the resolved skill, then follow its relative reference links. Use the installed package's runtime, API, and version requirements rather than assuming all examples apply to older releases. These commands resolve files; they do not import Markdown as JavaScript.
134
+ Follow the skill's reference links and the installed package's version and runtime requirements. Older releases may not include the skill.
135
+
136
+ For development of MCR itself, see [AGENTS.md](https://github.com/cenfun/monocart-coverage-reports/blob/main/AGENTS.md).
135
137
 
136
138
  ## Options
137
139
  - Default options: [lib/default/options.js](./lib/default/options.js)
package/README.zh-Hans.md CHANGED
@@ -14,6 +14,7 @@
14
14
 
15
15
  * [用法](#usage)
16
16
  * [最佳实践](#best-practices)
17
+ * [AI Agent Skill](#ai-agent-skill)
17
18
  * [选项配置](#options)
18
19
  * [所有支持的报告类型](#available-reports)
19
20
  * [比较两种报告](#compare-reports)
@@ -118,20 +119,21 @@ mcr node my-app.js -r v8,console-details
118
119
 
119
120
  ## AI Agent Skill
120
121
 
121
- 使用 AI 辅助开发本仓库源码时,请先阅读 [AGENTS.md](https://github.com/cenfun/monocart-coverage-reports/blob/main/AGENTS.md),了解源码结构、开发命令、验证流程和安全边界。`.github/copilot-instructions.md` 为 GitHub Copilot 提供可独立使用的核心规则摘要。这些指南仅用于源码仓库,不随 npm 包发布,与下面可复用的集成技能相互独立。
122
+ **可靠的 AI 辅助开发离不开自动化测试。** 测试结果验证代码行为,覆盖率帮助识别测试缺口。通过 **`mcr test`**,AI 编程助手可直接运行 Node.js 测试、采集原生 V8 覆盖率并生成报告,无需插桩。测试与覆盖率反馈支持持续迭代,并可结合 CI/CD 质量门禁,用于 AI 辅助或自主开发。
122
123
 
123
- 项目提供可复用的 [Monocart Coverage Reports 技能](skills/monocart-coverage-reports/SKILL.md),帮助 AI coding agent 采集覆盖率、配置 CLI、排查 sourcemap 和过滤问题、合并 raw 报告及设置 CI 阈值。结构为主 `SKILL.md` 加按需加载的专题参考文档,仅面向 MCR 3.x,并检查其运行环境要求。
124
+ [Monocart Coverage Reports 技能](skills/monocart-coverage-reports/SKILL.md) 指导 AI 配置覆盖率采集和 CLI、排查 sourcemap 问题、合并报告及设置 CI 阈值,适用于 MCR 3.x,专题参考文档按需加载。
124
125
 
125
- npm 包包含 `skills/monocart-coverage-reports/`。请将**整个目录**(包括 `references/`)复制到 agent 支持的 skills 目录,或直接让 agent 读取 `SKILL.md`。安装 MCR 不会自动注册技能或修改 agent 配置。技能说明使用英文,但提问和回复可以使用中文或其他语言。
126
+ 技能随 npm 包发布。将**整个 `skills/monocart-coverage-reports/` 目录**(含 `references/`)复制到 AI 工具的技能目录,或让 AI 直接读取 `SKILL.md`。安装 MCR 不会自动注册技能。技能说明使用英文,与 AI 交流可使用任意语言。
126
127
 
127
- 在使用 MCR 的项目根目录中定位已安装的技能和包配置(旧版本可能尚未包含技能):
128
+ 在项目根目录定位已安装的技能:
128
129
 
129
130
  ```sh
130
131
  node -p "require.resolve('monocart-coverage-reports/skills/monocart-coverage-reports/SKILL.md')"
131
- node -p "require.resolve('monocart-coverage-reports/package.json')"
132
132
  ```
133
133
 
134
- 读取定位到的技能文件,再按相对链接读取专题文档。请以已安装包的运行时、API 和版本要求为准,不要假设所有示例都适用于旧版本。以上命令用于定位文件,不是将 Markdown 作为 JavaScript 导入。
134
+ 按技能中的链接查阅参考文档,并以已安装包的版本和运行环境要求为准。旧版本可能不包含该技能。
135
+
136
+ 开发 MCR 本身时,请参阅 [AGENTS.md](https://github.com/cenfun/monocart-coverage-reports/blob/main/AGENTS.md)。
135
137
 
136
138
  ## Options
137
139
  - 默认选项: [lib/default/options.js](./lib/default/options.js)
@@ -489,6 +489,7 @@ const viteImportDefaultHandler = (node, group) => {
489
489
 
490
490
  const collectNodes = (ast) => {
491
491
  const functionNodes = [];
492
+ const initializerNodes = [];
492
493
  const statementNodes = [];
493
494
  const blockNodes = [];
494
495
  const branchMap = new Map();
@@ -514,6 +515,12 @@ const collectNodes = (ast) => {
514
515
  });
515
516
  },
516
517
 
518
+ PropertyDefinition: (node) => {
519
+ if (node.value) {
520
+ initializerNodes.push(node);
521
+ }
522
+ },
523
+
517
524
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static
518
525
  // as a function "functionName": "<static_initializer>",
519
526
  StaticBlock: (node, parents) => {
@@ -646,6 +653,7 @@ const collectNodes = (ast) => {
646
653
 
647
654
  return {
648
655
  functionNodes,
656
+ initializerNodes,
649
657
  statementNodes,
650
658
  blockNodes,
651
659
  branchMap
@@ -735,12 +743,30 @@ const findFunctionRange = (item, coverageInfo) => {
735
743
  const collectAstInfo = (ast, coverageInfo) => {
736
744
 
737
745
  const {
738
- functionNodes, statementNodes, blockNodes, branchMap
746
+ functionNodes, initializerNodes, statementNodes, blockNodes, branchMap
739
747
  } = collectNodes(ast);
740
748
 
741
749
  // root function state
742
750
  const rootState = getRootFunctionState(ast, coverageInfo);
743
751
 
752
+ // V8 groups field values into implicit functions. Use their counts and
753
+ // block ranges without adding synthetic functions to the report. Keys
754
+ // execute at class definition time, so only the value gets this state.
755
+ initializerNodes.forEach((node) => {
756
+ const ranges = node.static ? coverageInfo.functionStaticRanges : coverageInfo.functionInstanceRanges;
757
+ const { value } = node;
758
+ const range = Util.findInRanges(value.start, value.end, ranges, 'startOffset', 'endOffset');
759
+ if (range) {
760
+ value._state = {
761
+ isFunction: true,
762
+ count: range.count,
763
+ range
764
+ };
765
+ }
766
+ });
767
+
768
+ // Explicit functions (including arrow-valued fields) keep their own
769
+ // execution state, overriding any initializer state on the value node.
744
770
  const functions = [];
745
771
  functionNodes.forEach((item) => {
746
772
  const { node } = item;
@@ -9,6 +9,7 @@ const getCoverageInfo = (coverageList) => {
9
9
  const functionMap = new Map();
10
10
  const functionNameMap = new Map();
11
11
  const functionStaticRanges = [];
12
+ const functionInstanceRanges = [];
12
13
  const functionUncoveredRanges = [];
13
14
 
14
15
  let rootRange;
@@ -66,6 +67,9 @@ const getCoverageInfo = (coverageList) => {
66
67
  if (functionName === '<static_initializer>') {
67
68
  functionStaticRanges.push(functionRange);
68
69
  }
70
+ if (functionName === '<instance_members_initializer>') {
71
+ functionInstanceRanges.push(functionRange);
72
+ }
69
73
 
70
74
  // cache uncovered
71
75
  if (functionRange.count === 0) {
@@ -76,11 +80,14 @@ const getCoverageInfo = (coverageList) => {
76
80
 
77
81
  // sort ranges
78
82
  Util.sortOffsetRanges(functionUncoveredRanges);
83
+ Util.sortOffsetRanges(functionStaticRanges);
84
+ Util.sortOffsetRanges(functionInstanceRanges);
79
85
 
80
86
  return {
81
87
  functionMap,
82
88
  functionNameMap,
83
89
  functionStaticRanges,
90
+ functionInstanceRanges,
84
91
  functionUncoveredRanges,
85
92
  rootRange
86
93
  };
@@ -220,7 +227,19 @@ const addRule = (item, coverageList, coveredRanges, count = 0) => {
220
227
  const endOffset = end.offset;
221
228
 
222
229
  if (!count) {
223
- const coveredRange = Util.findInRanges(startOffset, endOffset, coveredRanges, 'startOffset', 'endOffset');
230
+ let matchEnd = endOffset;
231
+ if (item.type === 'rule') {
232
+ const child = item.nodes?.find((node) => node.type === 'rule' || node.type === 'atrule');
233
+ if (child) {
234
+ // Chromium 158 may stop the used parent range before a nested
235
+ // rule. Keep legacy whole-rule accounting, matching only the
236
+ // parent's prefix rather than requiring its entire subtree.
237
+ // TODO: Track native nested rules and trailing declarations
238
+ // separately, including their sparse sourcemap boundaries.
239
+ matchEnd = startOffset + source.input.css.slice(startOffset, child.source.start.offset).trimEnd().length;
240
+ }
241
+ }
242
+ const coveredRange = Util.findInRanges(startOffset, matchEnd, coveredRanges, 'startOffset', 'endOffset');
224
243
  if (coveredRange) {
225
244
  count = 1;
226
245
  }