miaoda-game-devkit 0.2.2 → 0.2.4

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
@@ -17,10 +17,14 @@ Scene 命令、restart、业务 checkpoint 和销毁。玩法测试可以调用
17
17
  `host.assertGameplayEvidence()` 把这些客观事实设为门禁;它不推断业务语义,
18
18
  authoritative state 仍必须由测试显式断言。
19
19
 
20
- 玩法测试应优先使用 `gameplayTest`。它在 Vitest 收集阶段写入静态 contract metadata,
21
- 在执行阶段绑定 HEADLESS host,并在 `onTestFinished` 校验 Ledger。`gameplayAudit` reporter
22
- 会在测试执行前报告未声明或重复的 contract,在测试结束后汇总缺失、失败、证据不足、
23
- Scene 未访问和 registry 不一致。`registerGameplayContract` 保留为不参加执行前预检的低层接口。
20
+ 玩法测试应优先使用 `gameplayTest`。它在 Vitest 收集阶段写入测试声明,
21
+ 在执行阶段绑定 HEADLESS host,并在 `onTestFinished` 校验 Ledger。配置加载阶段会先校验
22
+ 交互项目的最低基线:至少一个 `kind: "playthrough"` contract 必须要求真实输入、完整帧和
23
+ 语义 checkpoint,每个非入口 Scene 必须有生产转场覆盖;检测到 `scene.restart()` 时还必须
24
+ 声明 `flows.restart: true` 和 `kind: "recovery"` contract。配置预检失败时测试和 coverage
25
+ 都不会运行。配置通过后,`gameplayAudit` reporter 才会检查测试声明,并在结束时汇总
26
+ 缺失、失败、证据不足、Scene 未访问和 registry 不一致。`registerGameplayContract` 保留为
27
+ 不参加执行前预检的低层接口。
24
28
 
25
29
  模板直接调用开发工具包提供的命令行程序:
26
30
 
@@ -83,7 +87,12 @@ DOM 到 Phaser 的输入、命中测试和游戏状态变化,不验证 Canvas/
83
87
  断言 authoritative state 后调用 `host.checkpoint("progress")`、
84
88
  `host.checkpoint("recovery")` 等稳定检查点,并在清单中通过 `requireCheckpoint` 声明。
85
89
  运行结束会输出稳定的 `GAMEPLAY_AUDIT: ALL CONTRACTS PASSED` 或
86
- `GAMEPLAY_AUDIT: ... FAILED` 标识。
90
+ `GAMEPLAY_AUDIT: ... FAILED` 标识。该标识只表示玩法证据审计;`pnpm test` 的整体结果
91
+ 必须以最后的 `TEST_RESULT: PASS` 或 `TEST_RESULT: FAIL` 为准。失败报告会合并重复的问题,
92
+ 并给出按类别去重的修复建议,先处理列出的原始测试错误,再重新运行 `pnpm test`。
93
+
94
+ 共享 Vitest 配置使用 `minimal` reporter 和 `text-summary` coverage reporter,保留失败
95
+ 定位、Scene 覆盖摘要和最终机器标识,同时避免输出完整测试列表和逐文件噪声。
87
96
 
88
97
  ## 发布顺序
89
98
 
@@ -162,6 +162,8 @@ declare function createHeadlessGame<TScene extends Phaser.Scene>(scene: TScene,
162
162
 
163
163
  /** 一个必须由指定测试文件证明的玩法契约。 */
164
164
  interface GameplayAuditContract extends HeadlessGameplayEvidenceRequirements {
165
+ /** 契约用途;boot 不得替代交互游戏的 playthrough。 */
166
+ kind: "boot" | "playthrough" | "transition" | "recovery";
165
167
  /** 在整个游戏项目中唯一且稳定的契约标识。 */
166
168
  id: string;
167
169
  /** 相对于游戏项目根目录的 Vitest 测试文件。 */
@@ -171,6 +173,15 @@ interface GameplayAuditContract extends HeadlessGameplayEvidenceRequirements {
171
173
  }
172
174
  /** 游戏项目在一次 Vitest 运行中必须完成的玩法审计清单。 */
173
175
  interface GameplayAuditOptions {
176
+ /** 默认按交互游戏审计;纯演示项目必须显式豁免并说明原因。 */
177
+ mode?: "interactive" | "non-interactive";
178
+ /** non-interactive 模式的可审计豁免理由。 */
179
+ nonInteractiveJustification?: string;
180
+ /** 应用声明的可恢复流程;restart 会触发 recovery contract 基线。 */
181
+ flows?: {
182
+ restart?: boolean;
183
+ reset?: boolean;
184
+ };
174
185
  /** 生产 Scene registry 中预期出现的全部 Scene key。 */
175
186
  scenes: string[];
176
187
  /** 必须定义、执行并满足证据要求的玩法契约。 */
@@ -178,6 +189,8 @@ interface GameplayAuditOptions {
178
189
  }
179
190
  /** 通过 Vitest task metadata 在 worker 与 reporter 之间传递的契约数据。 */
180
191
  interface GameplayContractMetadata {
192
+ /** 契约用途。 */
193
+ kind: GameplayAuditContract["kind"];
181
194
  /** 契约唯一标识。 */
182
195
  id: string;
183
196
  /** 契约负责证明的生产 Scene key。 */
@@ -162,6 +162,8 @@ declare function createHeadlessGame<TScene extends Phaser.Scene>(scene: TScene,
162
162
 
163
163
  /** 一个必须由指定测试文件证明的玩法契约。 */
164
164
  interface GameplayAuditContract extends HeadlessGameplayEvidenceRequirements {
165
+ /** 契约用途;boot 不得替代交互游戏的 playthrough。 */
166
+ kind: "boot" | "playthrough" | "transition" | "recovery";
165
167
  /** 在整个游戏项目中唯一且稳定的契约标识。 */
166
168
  id: string;
167
169
  /** 相对于游戏项目根目录的 Vitest 测试文件。 */
@@ -171,6 +173,15 @@ interface GameplayAuditContract extends HeadlessGameplayEvidenceRequirements {
171
173
  }
172
174
  /** 游戏项目在一次 Vitest 运行中必须完成的玩法审计清单。 */
173
175
  interface GameplayAuditOptions {
176
+ /** 默认按交互游戏审计;纯演示项目必须显式豁免并说明原因。 */
177
+ mode?: "interactive" | "non-interactive";
178
+ /** non-interactive 模式的可审计豁免理由。 */
179
+ nonInteractiveJustification?: string;
180
+ /** 应用声明的可恢复流程;restart 会触发 recovery contract 基线。 */
181
+ flows?: {
182
+ restart?: boolean;
183
+ reset?: boolean;
184
+ };
174
185
  /** 生产 Scene registry 中预期出现的全部 Scene key。 */
175
186
  scenes: string[];
176
187
  /** 必须定义、执行并满足证据要求的玩法契约。 */
@@ -178,6 +189,8 @@ interface GameplayAuditOptions {
178
189
  }
179
190
  /** 通过 Vitest task metadata 在 worker 与 reporter 之间传递的契约数据。 */
180
191
  interface GameplayContractMetadata {
192
+ /** 契约用途。 */
193
+ kind: GameplayAuditContract["kind"];
181
194
  /** 契约唯一标识。 */
182
195
  id: string;
183
196
  /** 契约负责证明的生产 Scene key。 */
package/dist/index.d.mts CHANGED
@@ -1,10 +1,12 @@
1
- import { G as GameplayContractMetadata, H as HeadlessGameHost, a as HeadlessGameplayEvidenceRequirements } from './gameplay-audit-CYqLL8gY.mjs';
2
- export { b as GameplayAuditContract, c as GameplayAuditOptions, d as HeadlessCanvasBounds, e as HeadlessGameOptions, f as HeadlessGameplayEvidence, g as HeadlessInputDriver, h as HeadlessInputPoint, i as HeadlessKeyboardEventOptions, j as HeadlessKeyboardInput, k as HeadlessMouseInput, l as HeadlessTouchInput, m as createHeadlessGame } from './gameplay-audit-CYqLL8gY.mjs';
1
+ import { G as GameplayContractMetadata, H as HeadlessGameHost, a as HeadlessGameplayEvidenceRequirements } from './gameplay-audit-XBGq_jIV.mjs';
2
+ export { b as GameplayAuditContract, c as GameplayAuditOptions, d as HeadlessCanvasBounds, e as HeadlessGameOptions, f as HeadlessGameplayEvidence, g as HeadlessInputDriver, h as HeadlessInputPoint, i as HeadlessKeyboardEventOptions, j as HeadlessKeyboardInput, k as HeadlessMouseInput, l as HeadlessTouchInput, m as createHeadlessGame } from './gameplay-audit-XBGq_jIV.mjs';
3
3
  import * as Phaser from 'phaser';
4
4
  import { TestContext, TestOptions } from 'vitest';
5
5
 
6
6
  /** 将单个 Vitest 测试绑定到玩法 Ledger 的契约选项。 */
7
7
  interface GameplayContractOptions extends HeadlessGameplayEvidenceRequirements {
8
+ /** 契约用途;交互项目不能只使用 boot。 */
9
+ kind: "boot" | "playthrough" | "transition" | "recovery";
8
10
  /** 生产玩法清单中稳定且唯一的 contract 标识。 */
9
11
  id: string;
10
12
  /** 当前契约负责证明的生产 Scene key。 */
package/dist/index.d.ts CHANGED
@@ -1,10 +1,12 @@
1
- import { G as GameplayContractMetadata, H as HeadlessGameHost, a as HeadlessGameplayEvidenceRequirements } from './gameplay-audit-CYqLL8gY.js';
2
- export { b as GameplayAuditContract, c as GameplayAuditOptions, d as HeadlessCanvasBounds, e as HeadlessGameOptions, f as HeadlessGameplayEvidence, g as HeadlessInputDriver, h as HeadlessInputPoint, i as HeadlessKeyboardEventOptions, j as HeadlessKeyboardInput, k as HeadlessMouseInput, l as HeadlessTouchInput, m as createHeadlessGame } from './gameplay-audit-CYqLL8gY.js';
1
+ import { G as GameplayContractMetadata, H as HeadlessGameHost, a as HeadlessGameplayEvidenceRequirements } from './gameplay-audit-XBGq_jIV.js';
2
+ export { b as GameplayAuditContract, c as GameplayAuditOptions, d as HeadlessCanvasBounds, e as HeadlessGameOptions, f as HeadlessGameplayEvidence, g as HeadlessInputDriver, h as HeadlessInputPoint, i as HeadlessKeyboardEventOptions, j as HeadlessKeyboardInput, k as HeadlessMouseInput, l as HeadlessTouchInput, m as createHeadlessGame } from './gameplay-audit-XBGq_jIV.js';
3
3
  import * as Phaser from 'phaser';
4
4
  import { TestContext, TestOptions } from 'vitest';
5
5
 
6
6
  /** 将单个 Vitest 测试绑定到玩法 Ledger 的契约选项。 */
7
7
  interface GameplayContractOptions extends HeadlessGameplayEvidenceRequirements {
8
+ /** 契约用途;交互项目不能只使用 boot。 */
9
+ kind: "boot" | "playthrough" | "transition" | "recovery";
8
10
  /** 生产玩法清单中稳定且唯一的 contract 标识。 */
9
11
  id: string;
10
12
  /** 当前契约负责证明的生产 Scene key。 */
package/dist/index.js CHANGED
@@ -1089,6 +1089,8 @@ async function createHeadlessGame(scene, options = {}) {
1089
1089
  var import_vitest = require("vitest");
1090
1090
 
1091
1091
  // src/gameplay-audit.ts
1092
+ var import_node_fs = require("fs");
1093
+ var import_node_path = require("path");
1092
1094
  function normalizeList(value) {
1093
1095
  if (value === void 0) return [];
1094
1096
  const values = typeof value === "string" ? [value] : value;
@@ -1119,6 +1121,7 @@ function createGameplayContractMetadata(contract) {
1119
1121
  const scenes = normalizeSet(contract.scenes);
1120
1122
  return {
1121
1123
  id: contract.id.trim(),
1124
+ kind: contract.kind,
1122
1125
  scenes,
1123
1126
  requirements: normalizeGameplayRequirements(contract, scenes),
1124
1127
  verified: false
package/dist/index.mjs CHANGED
@@ -1047,6 +1047,8 @@ async function createHeadlessGame(scene, options = {}) {
1047
1047
  import { test } from "vitest";
1048
1048
 
1049
1049
  // src/gameplay-audit.ts
1050
+ import { readdirSync, readFileSync, statSync } from "fs";
1051
+ import { join } from "path";
1050
1052
  function normalizeList(value) {
1051
1053
  if (value === void 0) return [];
1052
1054
  const values = typeof value === "string" ? [value] : value;
@@ -1077,6 +1079,7 @@ function createGameplayContractMetadata(contract) {
1077
1079
  const scenes = normalizeSet(contract.scenes);
1078
1080
  return {
1079
1081
  id: contract.id.trim(),
1082
+ kind: contract.kind,
1080
1083
  scenes,
1081
1084
  requirements: normalizeGameplayRequirements(contract, scenes),
1082
1085
  verified: false