# Tasks — enterprise-rules-migration > Every checkbox MUST reflect work actually done in this change. Retroactive ticking is the failure mode this template guards against. ## 1. Spec authoring - [x] 1.1 Read `../suaveplan/enterprise/rules.md` end-to-end - [x] 1.2 No prior `openspec/specs/rules/spec.md` exists — new capability - [x] 1.3 Read `openspec/AGENTS.md` Sections 13 and 14 - [x] 1.4 Draft `proposal.md` from templates/proposal.md - [x] 1.5 Source mapping table cites enterprise/rules.md lines for every requirement - [x] 1.6 Draft `specs/rules/spec.md` and `specs/rules-hono/spec.md` - [x] 1.7 Every requirement carries a `**Verified by:**` line ## 2. Implementation — @suaveplan/rules ### 2.1 Package scaffold — ✅ landed 2026-05-11 - [x] 2.1.1 `packages/workflow/rules/package.json` (catalog deps + workspace `@suaveplan/error`, `events`, `types`) - [x] 2.1.2 `tsconfig.json` + `tsconfig.lib.json` extend `tsconfig.base.json` - [x] 2.1.3 `vite.config.ts` (preserveModules, dts) - [x] 2.1.4 `vitest.config.ts` (istanbul, 100/100/100/100 thresholds) - [x] 2.1.5 Subpath exports declared for every feature module (engine, builder, context, actions, events, operators, validators/{schema,field,custom}, serializer, optimizer, types, errors) ### 2.2 Types + errors + constants — ✅ landed 2026-05-11 - [x] 2.2.1 `src/types/` — rule.types, context.types, operator.types, action.types, event.types, validator.types, result.types, guards.ts, index.ts - [x] 2.2.2 `src/errors/rules-error.ts` — `defineCodes("RULES", [24 codes])` + `RulesError extends SuaveplanError` + `isRulesError` guard + sibling `.test.ts` + sibling `.md` - [x] 2.2.3 `src/constants.ts` — PACKAGE_NAME, VERSION, DEFAULT_MAX_DEPTH, DEFAULT_EVENT_HISTORY, DEFAULT_ACTION_TIMEOUT_MS, DEFAULT_ACTION_PARALLELISM + sibling `.md` ### 2.3 Engine + builder + context — ✅ landed 2026-05-11 - [x] 2.3.1 `src/engine/engine.ts` — `RuleEngine` with evaluate/evaluateAll/evaluateRuleset/check, depth limit (`RULES.ENGINE_DEPTH_EXCEEDED`), plugin registration (idempotent), AbortSignal (`RULES.ENGINE_ABORTED`), OTel histogram + counters + span; internal `compareValues` dispatcher over 33 operators + sibling .md + sibling test - [x] 2.3.2 `src/builder/builder.ts` — `RuleBuilder` (fluent + pending-operator combine), `FieldBuilder` (30 operator methods), `rule`/`condition`/`and`/`or`/`not`/`group` factories + sibling .md + sibling test - [x] 2.3.3 `src/context/context.ts` — `ContextBuilder` (immutable per call), `DefaultContextProvider` (injectable `Clock`, enhancer pipeline), `DefaultFieldResolver` (dot-path + `prop[N]`, strict mode → `RULES.FIELD_RESOLUTION_FAILED`), `createRequestContext`/`createScopedContext`, `getField`/`hasField`, Zod-validated options + sibling .md + sibling test - [x] 2.3.4 `src/otel/otel.ts` — lazy OTel instruments (`getInstruments` / `resetInstruments`) + sibling .md ### 2.4 Actions + events - [ ] 2.4.1 `src/actions/actions.ts` — `Action`, `ActionRegistry`, `ActionExecutor`, `createAction`/`createActionRegistry`/`createActionExecutor`, `validateActionConfig`, `builtInHandlers` (log/set/delay/noop with `LoggerLike`) - [ ] 2.4.2 `src/events/event-bus.ts` — `EventBus`, `HookManager`, bounded history, priority hooks, `waitFor` with timeout + AbortSignal ### 2.5 Operators - [ ] 2.5.1 `src/operators/registry.ts` — `OperatorRegistry` - [ ] 2.5.2 `src/operators/defaults.ts` — 30 built-in operators + `defaultOperatorRegistry` registration ### 2.6 Validators - [ ] 2.6.1 `src/validators/schema/schema.ts` — `SchemaValidator` with formats, transforms, recursion, AbortSignal - [ ] 2.6.2 `src/validators/field/field.ts` — `FieldValidator`, `field()`, 12 preset chains - [ ] 2.6.3 `src/validators/custom/custom.ts` — `CustomValidator`, `ValidatorRegistry`, 17 built-ins + `composeValidators` + `defaultValidatorRegistry` ### 2.7 Serializer + optimizer - [ ] 2.7.1 `src/serializer/serializer.ts` — full serialize/deserialize surface with function-placeholder strategy + Zod boundary - [ ] 2.7.2 `src/optimizer/optimizer.ts` — `optimizeRule`/`analyzeRule`/`estimateCost`/`findFields`/`hasAsyncComponents`/`countRules` ### 2.8 Barrel + benchmarks - [ ] 2.8.1 `src/index.ts` — explicit named re-exports for every public symbol (no `export *`) - [ ] 2.8.2 `src/__benchmarks__/` — mitata benchmarks for engine.evaluate + serializer round-trip + optimizer ## 3. Implementation — @suaveplan/rules-hono - [ ] 3.1 `packages/workflow/rules-hono/package.json` (peer `hono`, dep `@suaveplan/rules`) - [ ] 3.2 tsconfig + vite + vitest configs - [ ] 3.3 `src/middleware/rule.ts`, `validation.ts`, `access-control.ts`, `response-validation.ts`, `rate-limit-rule.ts`, `combine.ts` - [ ] 3.4 `src/engine/default.ts` — lazy `getDefaultEngine` + `resetDefaultEngine` under `./testing` subpath - [ ] 3.5 OTel surface for every middleware - [ ] 3.6 Barrel + subpath exports ## 4. Tests - [ ] 4.1 Unit tests per feature module covering every scenario (every `it()` has `{ timeout: 5000 }`) - [ ] 4.2 Spec-conformance tests (`*.spec-conformance.test.ts`) pinning type-level / OTel / RulesError-code-thrown / strict-mode scenarios - [ ] 4.3 Property-based tests on operators (commutative/associative) + optimizer + serializer round-trips (`fast-check`) - [ ] 4.4 Hono middleware tests via in-process `app.request(...)` (no mocks) ## 5. Documentation - [ ] 5.1 Sibling `.md` ≥200 words for every implementation `.ts` (Purpose / Features / Basic / Advanced / API Reference / Implementation Notes) - [ ] 5.2 Root `README.md` per package with Modules section linking every co-located `.md` - [ ] 5.3 Update root `CLAUDE.md` package listing - [ ] 5.4 Update `STATUS.md` (rules row + new rules-hono row) - [ ] 5.5 Update `SUMMARY.md` workflow section ## 6. 5-gate verification - [ ] 6.1 `bun run check` — 0/0/0 - [ ] 6.2 `bunx turbo lint typecheck test --filter=@suaveplan/rules` — green - [ ] 6.3 `bunx turbo lint typecheck test --filter=@suaveplan/rules-hono` — green - [ ] 6.4 `bunx turbo test:coverage --filter=@suaveplan/rules` — 100/100/100/100 - [ ] 6.5 `bunx turbo test:coverage --filter=@suaveplan/rules-hono` — 100/100/100/100 - [ ] 6.6 `bun scripts/openspec-conformance.ts @suaveplan/rules` — exit 0 - [ ] 6.7 `bun scripts/openspec-conformance.ts @suaveplan/rules-hono` — exit 0 - [ ] 6.8 `bunx turbo build --filter=@suaveplan/{rules,rules-hono}` — green ## 7. Pre-archive 9-row checklist - [ ] 7.1 Generics threaded; `expectTypeOf` assertions on every literal-type claim (type guards) - [ ] 7.2 Zod schemas wired at every declared boundary (RuleSchema, RulesetSchema, SerializedRuleSchema, SchemaSchema, ContextSchema, MiddlewareOptionsSchemas) - [ ] 7.3 Every code in `defineCodes("RULES", [...])` thrown by ≥1 production path - [ ] 7.4 Strict-mode behaviors tested both on and off (FieldResolver strict, abortEarly) - [ ] 7.5 OTel instruments emitted from production paths, asserted with in-memory `MeterProvider` - [ ] 7.6 Lifecycle dedup tested (`engine.use(plugin)` idempotent, `getDefaultEngine` returns identical reference) - [ ] 7.7 No retroactive tick — every box reflects work done in this change - [ ] 7.8 No `export *` in feature-module barrels (§6a) — `grep` clean - [ ] 7.9 No direct `vitest` / `bun:test` imports — `grep` clean ## Continuation pickup point (next session) **State as of 2026-05-11 ~15:55:** Sections 1, 2.1, 2.2 are complete. Section 2.3 (engine + builder + context) is the next atomic unit — start there. **Recommended order:** 1. **2.3 engine + builder + context** — the engine consumes context + operators; builder produces rules. Implement context first (`FieldResolver` with dot-path/array-index, `ContextBuilder`, `DefaultContextProvider`, `createRequestContext` with injectable `Clock`), then builder, then engine (depth limit, AbortSignal, OTel histograms, plugin registration). 2. **2.5 operators** — 30 built-ins are independent of engine internals beyond the `OperatorDefinition` shape (already in types). Can be implemented in parallel with 2.3 via subagent. 3. **2.4 actions + events** — depend on context + operators. EventBus consumes injectable `Clock`. 4. **2.6 validators** — three modules (schema/field/custom), each independent. 5. **2.7 serializer + optimizer** — depend on the full `Rule` surface being stable. 6. **2.8 barrel + benchmarks** — finalise `src/index.ts` to re-export every public symbol (no `export *`). 7. **3.x rules-hono** — only after the rules core is green at 100% coverage. 8. **5.x docs + 6.x gates + 7.x checklist + 8.x archive** — final sequence. **Verification stub to land mid-stream once 2.3 is in:** ```bash cd /home/paul/web/genesis && bun install bunx turbo lint typecheck test --filter=@suaveplan/rules bunx turbo test:coverage --filter=@suaveplan/rules ``` Coverage must already be 100/100/100/100 on the foundation (types + errors + constants) before adding 2.3 on top. ## 8. Archive - [ ] 8.1 Fold `specs/rules/spec.md` into `openspec/specs/rules/spec.md` - [ ] 8.2 Fold `specs/rules-hono/spec.md` into `openspec/specs/rules-hono/spec.md` - [ ] 8.3 Move `openspec/changes/enterprise-rules-migration/` → `openspec/archive/-enterprise-rules-migration/` - [ ] 8.4 `bun scripts/folder-reorg/generate-manifest.ts` - [ ] 8.5 `bun scripts/generate-missing.ts` - [ ] 8.6 `bunx markdownlint-cli2 --fix`