소스 정보
- 저장소
- HoundTek/hound-whiteboard
- 최근 소스 활동
- 2026년 8월 2일 05:07
- 감지된 SKILL.md 언어
- 중국어
- 스타
- 6
- 포크
- 0
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
SOC 직업 분류 기준
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/HoundTek/hound-whiteboard --skill hound-whiteboard-test-patterns명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SKILL.md 표시 중
Write and unify JSDoc, inline comments, and file headers following the project's established style. Use when adding or editing code comments.
Hound Whiteboard 项目的 Git 提交信息规范。在准备提交时加载。
Write module documentation, technical overviews, and API docs following the project's established style. Use when creating or updating .md files in docs/ directories.
| name | hound-whiteboard-test-patterns |
| description | Hound Whiteboard 项目的测试模式、目录结构和编写规范。在需要添加、迁移或审查测试时加载。 |
测试文件(.test.js)不应写 @module。文件头只需要 @file、@description(可选)和 @author:
/**
* @file 区块加载器测试
* @author Zhou Chenyu
*/
原因:测试不被其他模块导入,@module 对文档/模块图无贡献;foo.test.js 和 foo.js 天然配对,路径关系自明。
测试文件与源码保持同级 tests/ 目录:
src/
├── tests/ ← 跨包冒烟 / 集成测试(board-input-flow 等,Mock 工具)
└── ui/devices-dag/tools/
├── creator/tests/
│ ├── stroke-creator.test.js ← StrokeCreatorTool 所有测试
│ └── polygon-creator.test.js
├── creator/circle/tests/
│ ├── data-creator.test.js ← CircleDataCreatorTool 生命周期
│ └── processors.test.js ← 三种圆手势 interpret + 端到端
├── creator/gesture/tests/
│ └── two-point-processor.test.js
├── modifier/tests/
│ └── common-object-modifier.test.js
├── chooser/tests/
│ ├── object-chooser.test.js
│ └── rectangle-object-chooser.test.js
└── wrapper/tests/
├── wrapper-tool.test.js ← WrapperTool 基座
├── handoff-wrapper.test.js ← handoff 机制 + 真实工具集成
└── switcher-wrapper.test.js ← tool-switcher 路由
规则:
board-input-flow.test.js 禁止放置具体工具的端到端测试 — 只放路由基础设施测试(使用 CollectingTool 等通用 Mock)tests/ 目录下,不得跨文件混放当测试创建 Viewport 且涉及位置→区块解析时(worldToChunk),必须在 board.viewports.set(...) 之后设置:
board.viewports.set("main", viewport);
board.width = 800; // ← 必须!否则 chunkWidth = 0
board.height = 600; // ← 必须!否则 chunkHeight = 0
Viewport.chunkWidth 的 getter 是 this.board?.width ?? 0。不设置则 worldToChunk 返回 null → resolveOwnerChunkId 返回 undefined → ensureObject 返回 false → 对象创建静默失败。如果测试不涉及位置→区块解析(如纯 DAG 路由测试、Mock 测试),可以省略。
当直接通过 DAG dispatch(绕过 board.signalsEventBus.emit("input", ...))时,必须传递 { board, viewport } 上下文:
const accumulatedContext = { board, viewport };
viewport.devicesDAG.dispatch(
{
to: "/main/workflow",
signals: [{ type: "position", context: { value: { x: 1, y: 1 } } }],
},
accumulatedContext,
); // ← 必须!
原因:通过 builder.node().tool(tool) 挂载的工具有 toolContext = {},board 和 viewport 只能从 dispatch 的 accumulated context 获取。而 board.signalsEventBus.emit("input", ...) 内部已自动添加该上下文,不需要手动传递。
GestureBasedObjectModifierTool(包括 CommonObjectModifierTool)同时接受 position(绝对坐标)和 displacement(相对位移)两种信号:
| 信号 | 行为 |
|---|---|
position | 驱动手势状态机(begin → update → end/cancel) |
displacement | 无状态增量,直接累加到对象位置,不参与手势状态机 |
| 同一帧两者并存 | position 先算 → displacement 再叠 → 锚点跟随位移同步 |
// ✅ position 信号(绝对世界坐标)
emit("input", {
signals: [{ type: "position", context: { value: { x: 10, y: 10 } } }],
});
// ✅ displacement 信号(相对位移增量)
emit("input", {
signals: [{ type: "displacement", context: { value: { x: 3, y: 0 } } }],
});
// ✅ 两者并存
emit("input", {
signals: [
{ type: "position", context: { value: { x: 10, y: 10 } } },
{ type: "displacement", context: { value: { x: 3, y: 0 } } },
],
});
手势生命周期(position 驱动):
| 信号 | 作用 |
|---|---|
首个 position | 记录锚点,启动手势(对象暂不动) |
后续 position | 以锚点为基准计算位移并更新对象位置 |
end | 结束手势,对象保留在 AOM 动态图中 |
success | 将修改提交到静态图 |
Displacement 特性:
canBeginGestureDragGestureProcessor.displace 在平移对象后同步平移各对象基准位置(锚点不动),使后续 position 不产生跳跃DragGestureProcessor.displace 会在首次 displacement 时记录初始位置,确保 cancel 能正确回退不要只检查"对象非空"或"AOM 大小不变"。直接验证对象状态:
// ✅ 强断言:验证位置确实变了
expect(creatorTool.obj.position.serialize()).toEqual({
x: createdPosition.x + 3,
y: createdPosition.y,
});
// ✅ 强断言:验证对象已落到正确的区块
expect(ownerChunk.objectManager.getObject(obj.id)).toBe(obj);
// ❌ 弱断言:无法发现 displacement 被静默忽略
expect(obj).not.toBeNull();
expect(AOM.size).toBe(1);
.not.toBeNull() 仅应在结构验证(如检查 DAG 节点是否存在)时使用。