Workflow domain entity
Skill marzun9620/agent_skills/workflow/skills/workflow-domain-entity
Domain Entity implementation guide. Define entities with Schema.Class + Brand, plus Value Objects, Domain Errors (Schema.TaggedError), and barrel exports. Triggers: domain entity creation, Schema.Class, Brand types, domain model, Value Object, domain error, domain layer implementation.From its SKILL.md
npx -y skills add marzun9620/agent_skills --skill workflow-domain-entityAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
4.7 KB, ~1.3k tokens by cl100k_base, as published. Nobody here has run it
Domain Entity 実装手順
ADR-0001 / ADR-0004 準拠。domain 層は純粋なデータ定義のみ。I/O 禁止。
ファイル構成(必ずこの構造に従う)
apps/datahub/src/domain/{module}/
├── {entity}Id.ts # Brand 型 ID
├── {entity}Status.ts # Enum(必要な場合)
├── {entity}.ts # Entity 本体(Schema.Class)
├── errors.ts # Domain Error(Schema.TaggedError)
└── index.ts # Barrel export(全 public 型)
ファイル名は camelCase。1ファイル1責務。
Import ルール(重要)
- 同一ディレクトリ内:
./で直接 import OK - cross-directory(他の domain module 等): barrel(
index.js)経由のみ
// ✅ 同一ディレクトリ内
import { EntityId } from "./entityId.js";
// ✅ 他の domain module
import { UserId } from "~/domain/user/index.js";
// ❌ 禁止
import { UserId } from "~/domain/user/userId.js";
1. Entity 定義
ファイル: apps/datahub/src/domain/{module}/{entity}.ts
import { Schema } from "effect";
import { EntityId } from "./entityId.js";
export class Entity extends Schema.Class<Entity>("Entity")({
id: EntityId,
name: Schema.String,
status: EntityStatus,
// nested value objects OK
}) {}
Schema.Class<T>(name)({fields})で定義- メソッドなし、純粋なデータコンテナ
- ネストされた Value Object / Enum を参照可能
2. Value Object(ID)
ファイル: apps/datahub/src/domain/{module}/{entity}Id.ts
import { Schema } from "effect";
export const EntityId = Schema.String.pipe(Schema.brand("EntityId"));
export type EntityId = typeof EntityId.Type;
3. Enum(Status / Role / Kind)
ファイル: apps/datahub/src/domain/{module}/{entity}Status.ts
import { Schema } from "effect";
export const EntityStatus = Schema.Literal("ACTIVE", "ARCHIVED");
export type EntityStatus = typeof EntityStatus.Type;
命名: *Status, *Role, *Kind を使う。*Type は避ける。
4. Domain Error
ファイル: apps/datahub/src/domain/{module}/errors.ts
import { Schema } from "effect";
import { EntityId } from "./entityId.js";
export class EntityNotFoundError extends Schema.TaggedError<EntityNotFoundError>()(
"EntityNotFoundError",
{ entityId: EntityId },
) {}
Schema.TaggedErrorを使う(Data.TaggedErrorは domain 層で禁止)- Brand にしない
5. Domain Service(必要な場合のみ)
ファイル: apps/datahub/src/domain/services/{serviceName}.ts
import { Match, Option } from "effect";
// 純粋関数のみ。Effect を返す場合も I/O なし
export const checkPermission = (role: SystemRole) =>
Match.value(role).pipe(
Match.when("SYSTEM_ADMIN", () => Effect.void),
Match.when("USER", () => Effect.fail(new InsufficientPermissionError({}))),
Match.exhaustive,
);
- nullable は
Option.fromNullable+Option.matchで処理 Match.value()+Match.exhaustiveでパターンマッチ
6. Barrel Export
ファイル: apps/datahub/src/domain/{module}/index.ts
export { Entity } from "./entity.js";
export { EntityId } from "./entityId.js";
export type { EntityId as EntityIdType } from "./entityId.js";
export { EntityStatus } from "./entityStatus.js";
export { EntityNotFoundError } from "./errors.js";
cross-directory import はこの barrel 経由のみ。同一ディレクトリ内は ./ OK。
テスト踏襲ルール
実装前に、plan の Ref test に指定された既存テストファイルを読むこと:
- 同モジュールのテストがあればそれを踏襲
- なければ
tests/domain/内の別モジュールのテストを参考にする - 構造を合わせる: type 定義(
XxxCase)、table-driven(.each())、AAA パターン expect(result).toEqual(expected)を使う(toBeではなくtoEqual)
チェックリスト
-
typeを使っている(interface禁止 — ADR-0001) -
Schema.TaggedErrorを使っている(Data.TaggedError禁止) - I/O なし(postgres, drizzle, hono, node:fs, node:net の import なし)
-
_tagへの直接アクセスなし(Schema.is()/Match.tag()を使用) - barrel export が存在する
-
anyを使っていない - named export のみ(default export 禁止)
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.
Gives 0 of the 12 instructions most automation workflows skills give in ~1.3k tokens
Counted across 745 of the 1,008 authors here whose files we hold, read 2026-08-07
- Write conventional commit messagesin 36 of 745, across 35 files
- Delete branches after mergein 30 of 745, across 21 files
- Make atomic commitsin 25 of 745, across 15 files
- Write minimal code to pass testsin 22 of 745, across 10 files
- Re-snapshot after navigation or DOM changesin 21 of 745, across 13 files
- Use try-catch for error handlingin 20 of 745, across 8 files
- Run tests before committingin 20 of 745, across 12 files
- Write tests before implementationin 20 of 745, across 8 files
- Configure branch protection rulesin 19 of 745, across 5 files
- Explain the why in commit messagesin 19 of 745, across 9 files
- Refactor code while tests remain greenin 19 of 745, across 6 files
- Interact with elements using refsin 19 of 745, across 11 files
Said here and by no other author read
- define entities using schema class
- use brand types for identifiers
- use schema tagged error for errors
- create a barrel export file
- use direct imports within same directory
- import cross-directory modules via barrel exports
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.