hatch3r 1.7.0 → 1.7.5
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 +38 -12
- package/agents/hatch3r-a11y-auditor.md +4 -0
- package/agents/hatch3r-architect.md +5 -1
- package/agents/hatch3r-ci-watcher.md +4 -0
- package/agents/hatch3r-context-rules.md +4 -0
- package/agents/hatch3r-creator.md +4 -0
- package/agents/hatch3r-dependency-auditor.md +4 -0
- package/agents/hatch3r-devops.md +4 -0
- package/agents/hatch3r-docs-writer.md +4 -0
- package/agents/hatch3r-fixer.md +5 -1
- package/agents/hatch3r-handoff-loader.md +243 -0
- package/agents/hatch3r-handoff-preparer.md +134 -0
- package/agents/hatch3r-implementer.md +5 -1
- package/agents/hatch3r-learnings-loader.md +4 -0
- package/agents/hatch3r-lint-fixer.md +4 -0
- package/agents/hatch3r-perf-profiler.md +8 -0
- package/agents/hatch3r-researcher.md +5 -1
- package/agents/hatch3r-reviewer.md +92 -0
- package/agents/hatch3r-security-auditor.md +24 -0
- package/agents/hatch3r-test-writer.md +4 -0
- package/agents/modes/requirements-elicitation.md +5 -1
- package/agents/modes/similar-implementation.md +6 -0
- package/agents/modes/user-flows.md +76 -0
- package/agents/shared/quality-charter.md +129 -0
- package/agents/shared/user-question-protocol.md +95 -0
- package/commands/board/shared-azure-devops.md +2 -0
- package/commands/board/shared-github.md +17 -0
- package/commands/board/shared-gitlab.md +4 -0
- package/commands/hatch3r-board-fill.md +2 -1
- package/commands/hatch3r-board-pickup.md +1 -1
- package/commands/hatch3r-board-shared.md +21 -0
- package/commands/hatch3r-create.md +2 -0
- package/commands/hatch3r-handoff.md +126 -0
- package/commands/hatch3r-pr-resolve.md +672 -0
- package/commands/hatch3r-quick-change.md +5 -3
- package/commands/hatch3r-report.md +167 -0
- package/commands/hatch3r-revision.md +1 -1
- package/commands/hatch3r-workflow.md +3 -1
- package/dist/cli/index.js +3144 -979
- package/dist/cli/index.js.map +1 -1
- package/package.json +4 -2
- package/rules/hatch3r-accessibility-standards.md +21 -0
- package/rules/hatch3r-accessibility-standards.mdc +21 -0
- package/rules/hatch3r-agent-orchestration.md +32 -1
- package/rules/hatch3r-agent-orchestration.mdc +32 -1
- package/rules/hatch3r-ai-evals.md +158 -0
- package/rules/hatch3r-ai-evals.mdc +154 -0
- package/rules/hatch3r-ai-ux-patterns.md +131 -0
- package/rules/hatch3r-ai-ux-patterns.mdc +127 -0
- package/rules/hatch3r-api-design.md +67 -9
- package/rules/hatch3r-api-design.mdc +67 -9
- package/rules/hatch3r-api-versioning.md +119 -0
- package/rules/hatch3r-api-versioning.mdc +115 -0
- package/rules/hatch3r-auth-patterns.md +170 -0
- package/rules/hatch3r-auth-patterns.mdc +166 -0
- package/rules/hatch3r-component-conventions.md +30 -0
- package/rules/hatch3r-component-conventions.mdc +30 -0
- package/rules/hatch3r-container-hardening.md +131 -0
- package/rules/hatch3r-container-hardening.mdc +127 -0
- package/rules/hatch3r-contract-testing.md +117 -0
- package/rules/hatch3r-contract-testing.mdc +113 -0
- package/rules/hatch3r-deep-context.md +3 -1
- package/rules/hatch3r-deep-context.mdc +3 -1
- package/rules/hatch3r-dependency-management.md +73 -1
- package/rules/hatch3r-dependency-management.mdc +72 -0
- package/rules/hatch3r-design-system-detection.md +142 -0
- package/rules/hatch3r-design-system-detection.mdc +138 -0
- package/rules/hatch3r-event-schema-evolution.md +90 -0
- package/rules/hatch3r-event-schema-evolution.mdc +86 -0
- package/rules/hatch3r-handoff-readiness.md +45 -0
- package/rules/hatch3r-handoff-readiness.mdc +40 -0
- package/rules/hatch3r-i18n.md +13 -0
- package/rules/hatch3r-i18n.mdc +13 -0
- package/rules/hatch3r-iteration-summary.md +2 -0
- package/rules/hatch3r-iteration-summary.mdc +2 -0
- package/rules/hatch3r-migrations.md +61 -16
- package/rules/hatch3r-migrations.mdc +61 -16
- package/rules/hatch3r-observability-logging.md +1 -1
- package/rules/hatch3r-observability-logging.mdc +1 -1
- package/rules/hatch3r-observability-metrics.md +1 -1
- package/rules/hatch3r-observability-metrics.mdc +1 -1
- package/rules/hatch3r-observability-tracing-detail.md +1 -1
- package/rules/hatch3r-observability-tracing-detail.mdc +1 -1
- package/rules/hatch3r-observability-tracing.md +1 -1
- package/rules/hatch3r-observability-tracing.mdc +1 -1
- package/rules/hatch3r-observability.md +1 -0
- package/rules/hatch3r-observability.mdc +1 -0
- package/rules/hatch3r-operability.md +149 -0
- package/rules/hatch3r-operability.mdc +145 -0
- package/rules/hatch3r-passkey-server.md +181 -0
- package/rules/hatch3r-passkey-server.mdc +177 -0
- package/rules/hatch3r-progressive-delivery.md +120 -0
- package/rules/hatch3r-progressive-delivery.mdc +116 -0
- package/rules/hatch3r-resilience-patterns.md +154 -0
- package/rules/hatch3r-resilience-patterns.mdc +150 -0
- package/rules/hatch3r-secrets-management.md +29 -0
- package/rules/hatch3r-secrets-management.mdc +29 -0
- package/rules/hatch3r-testing.md +139 -43
- package/rules/hatch3r-testing.mdc +139 -43
- package/rules/hatch3r-ux-states-and-flows.md +149 -0
- package/rules/hatch3r-ux-states-and-flows.mdc +145 -0
- package/skills/hatch3r-a11y-audit/SKILL.md +14 -0
- package/skills/hatch3r-ai-feature/SKILL.md +134 -0
- package/skills/hatch3r-api-spec/SKILL.md +5 -0
- package/skills/hatch3r-architecture-review/SKILL.md +14 -0
- package/skills/hatch3r-bug-fix/SKILL.md +5 -0
- package/skills/hatch3r-ci-pipeline/SKILL.md +14 -0
- package/skills/hatch3r-cli-aichat/SKILL.md +84 -0
- package/skills/hatch3r-cli-ast-grep/SKILL.md +85 -0
- package/skills/hatch3r-cli-az-devops/SKILL.md +89 -0
- package/skills/hatch3r-cli-bat/SKILL.md +85 -0
- package/skills/hatch3r-cli-comby/SKILL.md +85 -0
- package/skills/hatch3r-cli-csvkit/SKILL.md +84 -0
- package/skills/hatch3r-cli-delta/SKILL.md +86 -0
- package/skills/hatch3r-cli-difftastic/SKILL.md +84 -0
- package/skills/hatch3r-cli-docker/SKILL.md +89 -0
- package/skills/hatch3r-cli-duckdb/SKILL.md +84 -0
- package/skills/hatch3r-cli-fd/SKILL.md +85 -0
- package/skills/hatch3r-cli-fzf/SKILL.md +84 -0
- package/skills/hatch3r-cli-gh/SKILL.md +90 -0
- package/skills/hatch3r-cli-glab/SKILL.md +89 -0
- package/skills/hatch3r-cli-jq/SKILL.md +85 -0
- package/skills/hatch3r-cli-lazygit/SKILL.md +78 -0
- package/skills/hatch3r-cli-llm/SKILL.md +84 -0
- package/skills/hatch3r-cli-miller/SKILL.md +84 -0
- package/skills/hatch3r-cli-mods/SKILL.md +84 -0
- package/skills/hatch3r-cli-overview/SKILL.md +60 -0
- package/skills/hatch3r-cli-playwright/SKILL.md +89 -0
- package/skills/hatch3r-cli-podman/SKILL.md +84 -0
- package/skills/hatch3r-cli-ripgrep/SKILL.md +85 -0
- package/skills/hatch3r-cli-rtk/SKILL.md +91 -0
- package/skills/hatch3r-cli-sd/SKILL.md +85 -0
- package/skills/hatch3r-cli-stagehand/SKILL.md +79 -0
- package/skills/hatch3r-cli-taplo/SKILL.md +84 -0
- package/skills/hatch3r-cli-xsv/SKILL.md +89 -0
- package/skills/hatch3r-cli-yq/SKILL.md +85 -0
- package/skills/hatch3r-cli-zstd/SKILL.md +85 -0
- package/skills/hatch3r-context-health/SKILL.md +14 -0
- package/skills/hatch3r-cost-tracking/SKILL.md +14 -0
- package/skills/hatch3r-customize/SKILL.md +14 -0
- package/skills/hatch3r-dep-audit/SKILL.md +14 -0
- package/skills/hatch3r-design-system-detect/SKILL.md +162 -0
- package/skills/hatch3r-feature/SKILL.md +2 -0
- package/skills/hatch3r-gh-agentic-workflows/SKILL.md +13 -0
- package/skills/hatch3r-handoff-prepare/SKILL.md +160 -0
- package/skills/hatch3r-handoff-resume/SKILL.md +171 -0
- package/skills/hatch3r-incident-response/SKILL.md +14 -0
- package/skills/hatch3r-issue-workflow/SKILL.md +5 -0
- package/skills/hatch3r-logical-refactor/SKILL.md +14 -0
- package/skills/hatch3r-migration/SKILL.md +14 -0
- package/skills/hatch3r-observability-verify/SKILL.md +133 -0
- package/skills/hatch3r-perf-audit/SKILL.md +14 -0
- package/skills/hatch3r-pr-creation/SKILL.md +14 -0
- package/skills/hatch3r-qa-validation/SKILL.md +18 -0
- package/skills/hatch3r-recipe/SKILL.md +14 -0
- package/skills/hatch3r-refactor/SKILL.md +14 -0
- package/skills/hatch3r-release/SKILL.md +14 -0
- package/skills/hatch3r-reliability-verify/SKILL.md +144 -0
- package/skills/hatch3r-ui-ux-verify/SKILL.md +136 -0
- package/skills/hatch3r-visual-refactor/SKILL.md +15 -1
|
@@ -26,3 +26,75 @@ alwaysApply: false
|
|
|
26
26
|
- Review changelogs and migration guides before upgrading major versions. Never blindly bump major versions and assume backward compatibility.
|
|
27
27
|
- Run the full test suite after any dependency upgrade, including integration tests. A passing unit test suite does not guarantee compatibility with upgraded peer dependencies.
|
|
28
28
|
- When upgrading a shared dependency used across multiple modules, upgrade all consumers in the same PR to avoid version skew within the monorepo or project.
|
|
29
|
+
|
|
30
|
+
## npm Trusted Publishing (OIDC)
|
|
31
|
+
|
|
32
|
+
For libraries published to npm, configure an npm Trusted Publisher with GitHub OIDC. The publishing workflow exchanges a per-run JWT for short-lived publish credentials — no long-lived `NPM_TOKEN` in secrets. Provenance attestations are auto-generated and signed by Sigstore Fulcio with the inclusion record in Rekor.
|
|
33
|
+
|
|
34
|
+
- Requirements: npm CLI >=11.5.1, Node >=22.14.0, `repository` field set in `package.json` (provenance validation fails without it).
|
|
35
|
+
- Workflow grants `id-token: write` permission at the job level.
|
|
36
|
+
- Remove `NPM_TOKEN` from repository and organization secrets after migrating to trusted publishing.
|
|
37
|
+
- PyPI, crates.io, and RubyGems offer equivalent OIDC trusted publishing — migrate at least one ecosystem per release pipeline.
|
|
38
|
+
|
|
39
|
+
## Provenance Flag for Non-Trusted Publishing
|
|
40
|
+
|
|
41
|
+
When trusted publishing is not yet enabled, publish with `npm publish --provenance`. The flag activates Sigstore-signed provenance even with token auth.
|
|
42
|
+
|
|
43
|
+
- Verify provenance: `npm view <pkg> --json | jq .dist.attestations` returns Sigstore attestation URLs; the npm package page renders a Provenance section.
|
|
44
|
+
- Consumers verify on install: `npm audit signatures` walks the attestation chain and confirms Rekor inclusion.
|
|
45
|
+
|
|
46
|
+
## SBOM Generation
|
|
47
|
+
|
|
48
|
+
Every release artifact ships a CycloneDX 1.6 or SPDX 3.0.1 SBOM, committed as a release asset and signed with the same Sigstore identity that signed the artifact. CycloneDX 1.6 is ECMA-424 ratified and broadly supported (Syft, Trivy, cdxgen, GitLab native). SPDX 3.0.1 is the BSI TR-03183-2 / EU CRA baseline.
|
|
49
|
+
|
|
50
|
+
- Tooling baseline: `npm sbom --sbom-format=cyclonedx` (npm 10+), `cdxgen` (broad ecosystem coverage including Python, Java, Rust, Go), `syft` (containers + source repos).
|
|
51
|
+
- CI step generates SBOM on every release tag and uploads as a release asset.
|
|
52
|
+
- PR-time SBOM diff (`cyclonedx-cli diff` or `syft diff`) blocks PRs that introduce unexpected new transitive dependencies; reviewer approves the diff alongside the source diff.
|
|
53
|
+
|
|
54
|
+
## SLSA v1.0 / v1.1 Build Provenance
|
|
55
|
+
|
|
56
|
+
Target SLSA Build L3 for production release artifacts: ephemeral hosted runner, isolated builder identity, signed in-toto provenance, transparency log inclusion. SLSA v1.1 (April 2025) is incremental on the Build track — v1.0 L3 artifacts also meet v1.1 L3.
|
|
57
|
+
|
|
58
|
+
- GitHub Actions implementation: `slsa-framework/slsa-github-generator` (language-agnostic generators for npm, container, generic artifact).
|
|
59
|
+
- Deploy-time verification: `slsa-verifier` CLI confirms provenance, builder identity allow-list, and source-repo match before the artifact is consumed.
|
|
60
|
+
- Pin the generator action to a 40-char commit SHA per the action-pinning policy below.
|
|
61
|
+
|
|
62
|
+
## Malicious-Package Detection Beyond `npm audit`
|
|
63
|
+
|
|
64
|
+
`npm audit` only flags published CVEs. The 2025-2026 incident class — Shai-Hulud (Sep-Nov 2025), Axios 1.14.1 maintainer hijack (Mar 2026), Mini-Shai-Hulud (May 2026), DevTap typosquat (Apr-May 2026) — never reaches a CVE filing. Layer install-time behavioral detection on top of `npm audit`:
|
|
65
|
+
|
|
66
|
+
- Pre-install behavioral scan: `socket.dev`, `snyk`, or `osv-scanner` against the lockfile in CI. `npq` adds a pre-install gate at the developer workstation.
|
|
67
|
+
- pnpm `minimumReleaseAge: 72` (3 days, raise to 7 for high-trust projects) blocks consumption of brand-new versions until the typosquat / maintainer-hijack window closes.
|
|
68
|
+
- Disable lifecycle scripts in CI: `.npmrc` sets `ignore-scripts=true`; pnpm uses `strictDepBuilds: true` plus `allowBuilds: [explicit-list]`.
|
|
69
|
+
- GitHub `dependency-review-action` on every PR blocks new dependencies with known advisories or disallowed licenses.
|
|
70
|
+
|
|
71
|
+
## Lockfile Policy
|
|
72
|
+
|
|
73
|
+
- Lockfile committed to the repository: `package-lock.json`, `yarn.lock`, or `pnpm-lock.yaml`. Multi-language repos commit the per-ecosystem lockfile (`Cargo.lock`, `poetry.lock`, `go.sum`, `Gemfile.lock`).
|
|
74
|
+
- CI installs from the lockfile only: `npm ci`, `yarn install --frozen-lockfile`, `pnpm install --frozen-lockfile`, `cargo build --locked`. Drift fails the build.
|
|
75
|
+
- `lockfile-lint` enforces registry allow-list and integrity-hash presence on every entry. Run in CI alongside install.
|
|
76
|
+
- Lockfile diffs receive the same review scrutiny as source diffs — reviewers inspect new transitive entries and version jumps.
|
|
77
|
+
- Renovate or Dependabot configured with grouped weekly updates: one PR per ecosystem per week for non-security updates; security updates open immediately.
|
|
78
|
+
|
|
79
|
+
## License Compliance
|
|
80
|
+
|
|
81
|
+
- Allow-list (default): MIT, Apache-2.0, ISC, BSD-2-Clause, BSD-3-Clause, MPL-2.0, CC0-1.0. Project policy may extend.
|
|
82
|
+
- Deny-list (default): GPL-2.0, GPL-3.0, AGPL-3.0, AGPL-3.0-or-later, SSPL-1.0, Commons Clause. AGPL triggers copyleft on network use — it is the SaaS landmine.
|
|
83
|
+
- Override requires documented business justification in the PR description plus security/legal sign-off.
|
|
84
|
+
- CI gate per ecosystem: `license-checker --onlyAllow "MIT;Apache-2.0;ISC;BSD-2-Clause;BSD-3-Clause;MPL-2.0;CC0-1.0"` (Node), `pip-licenses --allow-only` (Python), `cargo-license` (Rust). CI fails on detection of a denied license in direct or transitive deps.
|
|
85
|
+
|
|
86
|
+
## Pinned GitHub Action SHAs
|
|
87
|
+
|
|
88
|
+
Every action `uses:` line references a 40-character commit SHA, never a tag (`@v3`, `@main`, `@v44.5.1`). Tags are mutable; SHAs are not.
|
|
89
|
+
|
|
90
|
+
- CVE-2025-30066 (tj-actions/changed-files, March 2025) compromised 23,000+ repositories — the attacker mutated existing version tags to point to a malicious commit that dumped secrets to workflow logs. Root cause: compromised PAT on `reviewdog/action-setup` (CVE-2025-30154). Tag pinning would not have prevented this; SHA pinning would have.
|
|
91
|
+
- Annotate the SHA with the version: `uses: actions/checkout@<40-char-sha> # v4.2.2`.
|
|
92
|
+
- Dependabot configured with `package-ecosystem: github-actions` updates SHAs while preserving the version comment. Renovate equivalent: `pinDigests: true`.
|
|
93
|
+
- CI rejects PRs that introduce tag references via a linter step (e.g., `pinact` or a custom regex check).
|
|
94
|
+
|
|
95
|
+
## OSV.dev and GHSA Feeds
|
|
96
|
+
|
|
97
|
+
- `osv-scanner` runs on every PR and nightly against the lockfile. OSV.dev (Google) is the polyglot 2026 aggregator: npm, PyPI, crates.io, Maven, Go modules, RubyGems, Packagist, NuGet — single schema across all.
|
|
98
|
+
- GitHub Security Advisories (GHSA) remain the npm-ecosystem authoritative feed; `npm audit` and OSV both consume GHSA.
|
|
99
|
+
- NVD provides CPE-keyed CVE records for OS and language-stdlib vulnerabilities.
|
|
100
|
+
- Renovate `vulnerabilityAlerts: { enabled: true }` plus `osvVulnerabilityAlerts: true` produce auto-PRs that force-update to fixed versions and bypass the normal cooldown for security fixes. Pair with auto-merge for patch-level fixes when tests pass.
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: hatch3r-design-system-detection
|
|
3
|
+
type: rule
|
|
4
|
+
description: Mandatory detection of existing design tokens, theme primitives, and component library before AI agents author new UI components
|
|
5
|
+
scope: "**/*.vue,**/*.jsx,**/*.tsx,**/*.svelte,**/*.css,**/*.scss,**/components/**,**/tokens*,**/theme*,**/design-system/**,**/tailwind*"
|
|
6
|
+
tags: [ui, design-system, frontend]
|
|
7
|
+
quality_charter: agents/shared/quality-charter.md
|
|
8
|
+
cache_friendly: true
|
|
9
|
+
---
|
|
10
|
+
# Design System Detection
|
|
11
|
+
|
|
12
|
+
## Reuse-Before-Author Principle
|
|
13
|
+
|
|
14
|
+
Existing tokens beat extended tokens beat new tokens. Before authoring any UI primitive, an agent must detect whether tokens, themes, or component libraries already exist in the project and reuse them. Skipping detection is a regression: it produces duplicate primitives, drift in semantic naming, and visual inconsistency with shipped UI.
|
|
15
|
+
|
|
16
|
+
## Detection Routine (5 Steps, Ordered)
|
|
17
|
+
|
|
18
|
+
Run these five steps in order before authoring any UI artifact. Record each finding in the implementation plan or PR description.
|
|
19
|
+
|
|
20
|
+
### Step 1 — Scan `package.json` for design-system signals
|
|
21
|
+
|
|
22
|
+
Grep dependencies and `devDependencies` for: `@radix-ui/*`, `@shadcn/ui` references in `components.json`, `tailwindcss` (record the major version), `@chakra-ui/*`, `@mui/*` (Material), `bootstrap`, `headlessui`, `@ariakit/*`, `@reach/*`. Each signal pins the headless or styled library the project already commits to.
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
jq '.dependencies + .devDependencies | keys[]' package.json | grep -E '(radix|shadcn|tailwind|chakra|mui|bootstrap|headlessui|ariakit|reach)'
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Step 2 — Locate the token source
|
|
29
|
+
|
|
30
|
+
Search in this exact order — the first hit wins:
|
|
31
|
+
|
|
32
|
+
1. `tokens.json` at repo root or under `design-system/` — DTCG 2025.10 format
|
|
33
|
+
2. `src/styles/tokens.css` or `app/styles/tokens.css` — CSS custom properties
|
|
34
|
+
3. Tailwind v4 `@theme` block inside `app.css`, `globals.css`, or `src/styles/main.css`
|
|
35
|
+
4. `tailwind.config.{js,ts,mjs}` `theme.extend` — Tailwind v3 fallback
|
|
36
|
+
5. `figma.tokens.json` — Tokens Studio export, transformed downstream
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
fd -e json -e css 'tokens|theme' . && rg '^\s*@theme\b' --type css
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Step 3 — Map the component library
|
|
43
|
+
|
|
44
|
+
Look for these markers, in order:
|
|
45
|
+
|
|
46
|
+
- `components.json` — shadcn CLI registry config; records the components directory and registry URLs
|
|
47
|
+
- `src/components/ui/*` — shadcn convention
|
|
48
|
+
- `src/components/primitives/*` — generic primitives directory
|
|
49
|
+
- `app/components/*` — Nuxt/Vue convention
|
|
50
|
+
- `packages/ui/src/*` — monorepo shared package
|
|
51
|
+
|
|
52
|
+
Record the directory, the import pattern (`@/components/ui/button` etc.), and whether components wrap a headless library or hand-roll DOM.
|
|
53
|
+
|
|
54
|
+
### Step 4 — Identify the color space
|
|
55
|
+
|
|
56
|
+
Inspect token values:
|
|
57
|
+
|
|
58
|
+
- OKLCH (`oklch(0.7 0.15 250)`) — preferred 2026 default for shadcn v4 and Tailwind v4
|
|
59
|
+
- Display-P3 (`color(display-p3 1 0.5 0)`) — wide-gamut explicit
|
|
60
|
+
- sRGB hex (`#3b82f6`) — legacy; flag for migration when adding tokens
|
|
61
|
+
|
|
62
|
+
Document the convention. New tokens must match the existing color space — mixed-space palettes produce inconsistent blending in `color-mix()`.
|
|
63
|
+
|
|
64
|
+
### Step 5 — Record findings
|
|
65
|
+
|
|
66
|
+
Add a short section to the implementation plan or PR description listing: token source path, component library directory, headless library (Radix/Ariakit/Headless UI/none), color space, breakpoint strategy (container queries via `@container` or media queries via `@media`).
|
|
67
|
+
|
|
68
|
+
## DTCG Token Format (2025.10)
|
|
69
|
+
|
|
70
|
+
When emitting or proposing new tokens, conform to the W3C Design Tokens Community Group format. Required fields per token: `$value`, `$type` (one of `color`, `dimension`, `fontFamily`, `fontWeight`, `duration`, `cubicBezier`, `number`). Optional: `$description`. Alias another token via `{group.token}` reference syntax. Transform pipelines: Style Dictionary 4.x or Tokens Studio. Source: `design-tokens.github.io/community-group`.
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"color": {
|
|
75
|
+
"primary": { "$value": "oklch(0.7 0.15 250)", "$type": "color" },
|
|
76
|
+
"brand": { "$value": "{color.primary}", "$type": "color" }
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## shadcn Baseline (2026)
|
|
82
|
+
|
|
83
|
+
When scaffolding React UI in a project without a component library:
|
|
84
|
+
|
|
85
|
+
- `npx shadcn@latest init` — initialize `components.json`, base tokens, and `cn()` util
|
|
86
|
+
- `npx shadcn@latest add <component> --dry-run` — inspect the diff before writing
|
|
87
|
+
- Pull from namespaced registries (`@my-org/...`) for org-specific components
|
|
88
|
+
- Never fork primitives into local copies; extend via composition
|
|
89
|
+
|
|
90
|
+
## Tailwind v4 CSS-First
|
|
91
|
+
|
|
92
|
+
For new projects targeting Tailwind v4: configure entirely via the `@theme` block in CSS. Do not generate `tailwind.config.js` — that is the v3 model. v4 defaults to OKLCH color space; use `color-mix(in oklch, ...)` for tints, shades, and surface elevations.
|
|
93
|
+
|
|
94
|
+
```css
|
|
95
|
+
@import "tailwindcss";
|
|
96
|
+
@theme {
|
|
97
|
+
--color-primary: oklch(0.7 0.15 250);
|
|
98
|
+
--color-primary-hover: color-mix(in oklch, var(--color-primary) 90%, black);
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Radix Primitives + WAI-ARIA APG
|
|
103
|
+
|
|
104
|
+
Never hand-roll focus traps, ARIA roles, roving tabindex, or keyboard navigation for: menu, dialog, popover, tabs, select, combobox, listbox, dropdown, tooltip, accordion. Compose Radix Primitives, Ariakit, or React Aria, and verify behavior against the WAI-ARIA Authoring Practices Guide (`w3.org/WAI/ARIA/apg/`). Hand-rolled implementations of these patterns are rejected.
|
|
105
|
+
|
|
106
|
+
## Modern CSS Over JS (Interop 2026 Baseline)
|
|
107
|
+
|
|
108
|
+
Prefer the native CSS or HTML feature over a JS equivalent whenever the Interop 2026 baseline includes it:
|
|
109
|
+
|
|
110
|
+
- `:has()` selector — replaces JS-based parent-state classes
|
|
111
|
+
- Container queries (`@container`) — replaces `@media` for component-scoped breakpoints
|
|
112
|
+
- View Transitions API — replaces Framer Motion route transitions
|
|
113
|
+
- Native `<dialog>` + Popover API (`popover` attribute) — replaces Headless UI modals for non-trapping cases
|
|
114
|
+
- CSS anchor positioning — replaces Floating UI for menus and tooltips
|
|
115
|
+
- Cascade layers (`@layer`) — replaces specificity hacks
|
|
116
|
+
- `color-mix()` — replaces JS color manipulation libs
|
|
117
|
+
|
|
118
|
+
## Reuse > Extend > Create — Decision Tree
|
|
119
|
+
|
|
120
|
+
| Situation | Action |
|
|
121
|
+
|---|---|
|
|
122
|
+
| Token exists with matching semantic name | Use directly |
|
|
123
|
+
| Token exists with adjacent semantic | Alias new semantic to existing primitive |
|
|
124
|
+
| No token, primitive exists in scale | Add semantic alias pointing at the existing primitive |
|
|
125
|
+
| No primitive at all | Add primitive plus semantic alias; justify the new primitive in the PR |
|
|
126
|
+
|
|
127
|
+
## Verification Before "Done"
|
|
128
|
+
|
|
129
|
+
- Design-token adoption >= 95% in generated code — no hard-coded hex, rgb, or pixel values for colors and spacing
|
|
130
|
+
- `npx shadcn@latest add <component> --diff` shows no unintentional local drift from the registry
|
|
131
|
+
- Components imported from the primitives library; not duplicated inline
|
|
132
|
+
- Color values in OKLCH where the existing token source uses OKLCH
|
|
133
|
+
- New tokens conform to DTCG `$value`/`$type` shape and pass the project's Style Dictionary build
|
|
134
|
+
|
|
135
|
+
## References
|
|
136
|
+
|
|
137
|
+
- W3C Design Tokens Community Group spec: `design-tokens.github.io/community-group` (2025.10 working draft)
|
|
138
|
+
- shadcn docs: `ui.shadcn.com`
|
|
139
|
+
- Tailwind v4 docs: `tailwindcss.com/docs` (CSS-first `@theme` chapter)
|
|
140
|
+
- Radix Primitives: `radix-ui.com/primitives`
|
|
141
|
+
- WAI-ARIA Authoring Practices Guide: `w3.org/WAI/ARIA/apg/`
|
|
142
|
+
- Interop 2026 dashboard: `wpt.fyi/interop-2026`
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Mandatory detection of existing design tokens, theme primitives, and component library before AI agents author new UI components
|
|
3
|
+
globs: ["**/*.vue", "**/*.jsx", "**/*.tsx", "**/*.svelte", "**/*.css", "**/*.scss", "**/components/**", "**/tokens*", "**/theme*", "**/design-system/**", "**/tailwind*"]
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
# Design System Detection
|
|
7
|
+
|
|
8
|
+
## Reuse-Before-Author Principle
|
|
9
|
+
|
|
10
|
+
Existing tokens beat extended tokens beat new tokens. Before authoring any UI primitive, an agent must detect whether tokens, themes, or component libraries already exist in the project and reuse them. Skipping detection is a regression: it produces duplicate primitives, drift in semantic naming, and visual inconsistency with shipped UI.
|
|
11
|
+
|
|
12
|
+
## Detection Routine (5 Steps, Ordered)
|
|
13
|
+
|
|
14
|
+
Run these five steps in order before authoring any UI artifact. Record each finding in the implementation plan or PR description.
|
|
15
|
+
|
|
16
|
+
### Step 1 — Scan `package.json` for design-system signals
|
|
17
|
+
|
|
18
|
+
Grep dependencies and `devDependencies` for: `@radix-ui/*`, `@shadcn/ui` references in `components.json`, `tailwindcss` (record the major version), `@chakra-ui/*`, `@mui/*` (Material), `bootstrap`, `headlessui`, `@ariakit/*`, `@reach/*`. Each signal pins the headless or styled library the project already commits to.
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
jq '.dependencies + .devDependencies | keys[]' package.json | grep -E '(radix|shadcn|tailwind|chakra|mui|bootstrap|headlessui|ariakit|reach)'
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Step 2 — Locate the token source
|
|
25
|
+
|
|
26
|
+
Search in this exact order — the first hit wins:
|
|
27
|
+
|
|
28
|
+
1. `tokens.json` at repo root or under `design-system/` — DTCG 2025.10 format
|
|
29
|
+
2. `src/styles/tokens.css` or `app/styles/tokens.css` — CSS custom properties
|
|
30
|
+
3. Tailwind v4 `@theme` block inside `app.css`, `globals.css`, or `src/styles/main.css`
|
|
31
|
+
4. `tailwind.config.{js,ts,mjs}` `theme.extend` — Tailwind v3 fallback
|
|
32
|
+
5. `figma.tokens.json` — Tokens Studio export, transformed downstream
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
fd -e json -e css 'tokens|theme' . && rg '^\s*@theme\b' --type css
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Step 3 — Map the component library
|
|
39
|
+
|
|
40
|
+
Look for these markers, in order:
|
|
41
|
+
|
|
42
|
+
- `components.json` — shadcn CLI registry config; records the components directory and registry URLs
|
|
43
|
+
- `src/components/ui/*` — shadcn convention
|
|
44
|
+
- `src/components/primitives/*` — generic primitives directory
|
|
45
|
+
- `app/components/*` — Nuxt/Vue convention
|
|
46
|
+
- `packages/ui/src/*` — monorepo shared package
|
|
47
|
+
|
|
48
|
+
Record the directory, the import pattern (`@/components/ui/button` etc.), and whether components wrap a headless library or hand-roll DOM.
|
|
49
|
+
|
|
50
|
+
### Step 4 — Identify the color space
|
|
51
|
+
|
|
52
|
+
Inspect token values:
|
|
53
|
+
|
|
54
|
+
- OKLCH (`oklch(0.7 0.15 250)`) — preferred 2026 default for shadcn v4 and Tailwind v4
|
|
55
|
+
- Display-P3 (`color(display-p3 1 0.5 0)`) — wide-gamut explicit
|
|
56
|
+
- sRGB hex (`#3b82f6`) — legacy; flag for migration when adding tokens
|
|
57
|
+
|
|
58
|
+
Document the convention. New tokens must match the existing color space — mixed-space palettes produce inconsistent blending in `color-mix()`.
|
|
59
|
+
|
|
60
|
+
### Step 5 — Record findings
|
|
61
|
+
|
|
62
|
+
Add a short section to the implementation plan or PR description listing: token source path, component library directory, headless library (Radix/Ariakit/Headless UI/none), color space, breakpoint strategy (container queries via `@container` or media queries via `@media`).
|
|
63
|
+
|
|
64
|
+
## DTCG Token Format (2025.10)
|
|
65
|
+
|
|
66
|
+
When emitting or proposing new tokens, conform to the W3C Design Tokens Community Group format. Required fields per token: `$value`, `$type` (one of `color`, `dimension`, `fontFamily`, `fontWeight`, `duration`, `cubicBezier`, `number`). Optional: `$description`. Alias another token via `{group.token}` reference syntax. Transform pipelines: Style Dictionary 4.x or Tokens Studio. Source: `design-tokens.github.io/community-group`.
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"color": {
|
|
71
|
+
"primary": { "$value": "oklch(0.7 0.15 250)", "$type": "color" },
|
|
72
|
+
"brand": { "$value": "{color.primary}", "$type": "color" }
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## shadcn Baseline (2026)
|
|
78
|
+
|
|
79
|
+
When scaffolding React UI in a project without a component library:
|
|
80
|
+
|
|
81
|
+
- `npx shadcn@latest init` — initialize `components.json`, base tokens, and `cn()` util
|
|
82
|
+
- `npx shadcn@latest add <component> --dry-run` — inspect the diff before writing
|
|
83
|
+
- Pull from namespaced registries (`@my-org/...`) for org-specific components
|
|
84
|
+
- Never fork primitives into local copies; extend via composition
|
|
85
|
+
|
|
86
|
+
## Tailwind v4 CSS-First
|
|
87
|
+
|
|
88
|
+
For new projects targeting Tailwind v4: configure entirely via the `@theme` block in CSS. Do not generate `tailwind.config.js` — that is the v3 model. v4 defaults to OKLCH color space; use `color-mix(in oklch, ...)` for tints, shades, and surface elevations.
|
|
89
|
+
|
|
90
|
+
```css
|
|
91
|
+
@import "tailwindcss";
|
|
92
|
+
@theme {
|
|
93
|
+
--color-primary: oklch(0.7 0.15 250);
|
|
94
|
+
--color-primary-hover: color-mix(in oklch, var(--color-primary) 90%, black);
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Radix Primitives + WAI-ARIA APG
|
|
99
|
+
|
|
100
|
+
Never hand-roll focus traps, ARIA roles, roving tabindex, or keyboard navigation for: menu, dialog, popover, tabs, select, combobox, listbox, dropdown, tooltip, accordion. Compose Radix Primitives, Ariakit, or React Aria, and verify behavior against the WAI-ARIA Authoring Practices Guide (`w3.org/WAI/ARIA/apg/`). Hand-rolled implementations of these patterns are rejected.
|
|
101
|
+
|
|
102
|
+
## Modern CSS Over JS (Interop 2026 Baseline)
|
|
103
|
+
|
|
104
|
+
Prefer the native CSS or HTML feature over a JS equivalent whenever the Interop 2026 baseline includes it:
|
|
105
|
+
|
|
106
|
+
- `:has()` selector — replaces JS-based parent-state classes
|
|
107
|
+
- Container queries (`@container`) — replaces `@media` for component-scoped breakpoints
|
|
108
|
+
- View Transitions API — replaces Framer Motion route transitions
|
|
109
|
+
- Native `<dialog>` + Popover API (`popover` attribute) — replaces Headless UI modals for non-trapping cases
|
|
110
|
+
- CSS anchor positioning — replaces Floating UI for menus and tooltips
|
|
111
|
+
- Cascade layers (`@layer`) — replaces specificity hacks
|
|
112
|
+
- `color-mix()` — replaces JS color manipulation libs
|
|
113
|
+
|
|
114
|
+
## Reuse > Extend > Create — Decision Tree
|
|
115
|
+
|
|
116
|
+
| Situation | Action |
|
|
117
|
+
|---|---|
|
|
118
|
+
| Token exists with matching semantic name | Use directly |
|
|
119
|
+
| Token exists with adjacent semantic | Alias new semantic to existing primitive |
|
|
120
|
+
| No token, primitive exists in scale | Add semantic alias pointing at the existing primitive |
|
|
121
|
+
| No primitive at all | Add primitive plus semantic alias; justify the new primitive in the PR |
|
|
122
|
+
|
|
123
|
+
## Verification Before "Done"
|
|
124
|
+
|
|
125
|
+
- Design-token adoption >= 95% in generated code — no hard-coded hex, rgb, or pixel values for colors and spacing
|
|
126
|
+
- `npx shadcn@latest add <component> --diff` shows no unintentional local drift from the registry
|
|
127
|
+
- Components imported from the primitives library; not duplicated inline
|
|
128
|
+
- Color values in OKLCH where the existing token source uses OKLCH
|
|
129
|
+
- New tokens conform to DTCG `$value`/`$type` shape and pass the project's Style Dictionary build
|
|
130
|
+
|
|
131
|
+
## References
|
|
132
|
+
|
|
133
|
+
- W3C Design Tokens Community Group spec: `design-tokens.github.io/community-group` (2025.10 working draft)
|
|
134
|
+
- shadcn docs: `ui.shadcn.com`
|
|
135
|
+
- Tailwind v4 docs: `tailwindcss.com/docs` (CSS-first `@theme` chapter)
|
|
136
|
+
- Radix Primitives: `radix-ui.com/primitives`
|
|
137
|
+
- WAI-ARIA Authoring Practices Guide: `w3.org/WAI/ARIA/apg/`
|
|
138
|
+
- Interop 2026 dashboard: `wpt.fyi/interop-2026`
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: hatch3r-event-schema-evolution
|
|
3
|
+
type: rule
|
|
4
|
+
description: Event and message schema evolution patterns for Kafka / Kinesis / Pub-Sub / event store — backward + forward + full compatibility modes, schema registry, consumer-side defaults
|
|
5
|
+
scope: "**/events/**,**/schemas/**,**/*.avsc,**/*.proto,**/messaging/**,**/kafka/**,**/pubsub/**"
|
|
6
|
+
tags: [implementation, devops]
|
|
7
|
+
quality_charter: agents/shared/quality-charter.md
|
|
8
|
+
cache_friendly: true
|
|
9
|
+
---
|
|
10
|
+
# Event Schema Evolution
|
|
11
|
+
|
|
12
|
+
Schemas for events, messages, and stream records evolve independently of producer and consumer deploy order. Every change must declare an explicit compatibility mode and pass a registry compatibility check before merge.
|
|
13
|
+
|
|
14
|
+
## Compatibility Modes
|
|
15
|
+
|
|
16
|
+
A registry compatibility mode constrains the diff between adjacent schema versions. Pick the mode that matches the deploy-order guarantee available in the target system.
|
|
17
|
+
|
|
18
|
+
- **`BACKWARD`** — a consumer using the new schema reads data written with the old schema. Allowed diffs: delete a field, add a field that has a default value. Deploy consumers first. Default for evolving consumer code.
|
|
19
|
+
- **`FORWARD`** — a consumer using the old schema reads data written with the new schema. Allowed diffs: add a field, delete a field that had a default value. Deploy producers first. Default for evolving producer code.
|
|
20
|
+
- **`FULL`** — both directions. Required when producer and consumer deploy order cannot be controlled (e.g., split across teams or platforms).
|
|
21
|
+
- **`*_TRANSITIVE`** variants (BACKWARD_TRANSITIVE, FORWARD_TRANSITIVE, FULL_TRANSITIVE) — the constraint holds against every prior schema version, not just the immediately preceding one. Required when consumers may replay from offset zero or read a historical archive.
|
|
22
|
+
- **`NONE`** — disables compatibility checking; breaking changes accepted. Permitted only on a dedicated `*-v2` subject during a planned migration window with a dated deprecation plan in the migration ticket.
|
|
23
|
+
|
|
24
|
+
Default recommendation when in doubt: `BACKWARD_TRANSITIVE` — consumers can deploy first and replay from offset zero.
|
|
25
|
+
|
|
26
|
+
## Schema Registry Mandate
|
|
27
|
+
|
|
28
|
+
- Every event topic / stream / subscription has a registered schema in Confluent Schema Registry, Apicurio Registry, AWS Glue Schema Registry, or Karapace. No in-tree schema-only repos without a registry binding.
|
|
29
|
+
- Subject naming strategy is declared per topic: `TopicNameStrategy` (one schema per topic — default), `RecordNameStrategy` (one schema per record type across topics), or `TopicRecordNameStrategy` (multiple record types per topic). Mixing strategies inside the same topic is forbidden.
|
|
30
|
+
- Compatibility mode is set per subject in the registry and asserted in CI. Changing the mode requires a registry-admin role and a logged justification.
|
|
31
|
+
- Schemas are versioned by the registry; the producer pins the schema ID it serialized with, and the consumer fetches by ID — never by name + "latest".
|
|
32
|
+
|
|
33
|
+
## Avro Evolution Rules
|
|
34
|
+
|
|
35
|
+
- Adding a field requires a `default` value to remain backward-compatible — a consumer using the new schema reads old data by substituting the default for the absent field.
|
|
36
|
+
- Removing a field requires the field to have had a `default` value to remain forward-compatible — an old consumer reads new data and the missing field falls back to its declared default.
|
|
37
|
+
- Use a union with `null` (e.g., `["null", "string"]` with `default: null`) to express an optional field. Place `null` first in the union so the default is unambiguously the null branch.
|
|
38
|
+
- Never rename a field — add a new field and register an `aliases: ["old_name"]` entry on the new field so old data deserializes against the new schema.
|
|
39
|
+
- Never change a field's type. To replace a type, add a new field of the new type, dual-write during the migration window, and remove the old field only after consumer migration completes.
|
|
40
|
+
|
|
41
|
+
## Protobuf Evolution Rules
|
|
42
|
+
|
|
43
|
+
- Use `proto3` for new schemas. Field numbers are immutable identifiers — never reuse a tag number, never renumber, never reorder by tag.
|
|
44
|
+
- When removing a field, add a `reserved` clause for both the tag number and the field name so future authors cannot resurrect the removed field with a different type and produce silent data corruption.
|
|
45
|
+
- Field type widening is constrained: int32 / uint32 / int64 / uint64 / bool are mutually wire-compatible; sint32 ↔ sint64 are compatible; fixed32 ↔ sfixed32 are compatible; `string` ↔ `bytes` are compatible when bytes are valid UTF-8. Other type changes are breaking.
|
|
46
|
+
- Use `optional` (proto3 since 3.15) for clear presence semantics on scalar fields. Without `optional`, unset and default-valued fields are indistinguishable on the wire.
|
|
47
|
+
- Never remove an enum value — mark it `[deprecated = true]` and leave it in place. Removing an enum value breaks consumers that have it pinned.
|
|
48
|
+
- New message types are not forward-compatible — old producers/consumers do not know about them. Prefer `BACKWARD_TRANSITIVE` for protobuf subjects.
|
|
49
|
+
|
|
50
|
+
## JSON Schema Evolution
|
|
51
|
+
|
|
52
|
+
- Default policy: additive only. New optional properties may be added; required properties may not be added to an existing record type.
|
|
53
|
+
- `additionalProperties: false` blocks forward compatibility (a consumer using the old strict schema rejects new fields). Choose explicitly: set `false` only when the consumer must reject unknown fields for security reasons; set `true` (or omit) to allow forward-compatible evolution.
|
|
54
|
+
- Version the schema identifier with semver (e.g., `$id: "https://example.com/schemas/event/v1.3.0.json"`). Patch and minor bumps must be additive; major bumps signal an incompatible change and require a new subject.
|
|
55
|
+
- For shared envelope shapes (e.g., CloudEvents), pin the envelope spec version and version only the `data` payload schema.
|
|
56
|
+
|
|
57
|
+
## Consumer-Side Defaults and Tolerance
|
|
58
|
+
|
|
59
|
+
- Every optional field deserializes to an explicit default value in consumer code (zero-value, `None`, empty string, empty list — declared, not implicit).
|
|
60
|
+
- Consumers never panic, crash, or fail-stop on a missing field. Missing → default. Unknown field → log at `info`, increment `event.schema.unknown_field` counter, continue processing.
|
|
61
|
+
- Emit `event.schema.version` and `event.subject` as attributes on every consumer-side trace span and metric label, so observability dashboards surface version distribution and detect stuck consumers on the old schema.
|
|
62
|
+
- Consumers validate against the schema fetched by ID at deserialization time; never validate against a hard-coded in-process schema literal.
|
|
63
|
+
|
|
64
|
+
## Dual-Publish During Migration
|
|
65
|
+
|
|
66
|
+
- When the shape change exceeds what the registry compatibility mode permits, dual-publish: write the same logical event in both old and new shapes — either to two topics (`orders.v1`, `orders.v2`) or to one topic with a union schema discriminated by a `schema_version` field.
|
|
67
|
+
- Keep dual-publish active until every consumer has been confirmed migrated to the new shape (poll consumer-group offsets against both topics; alert on lag on the new shape; alert on consumption from the old shape from any non-allowlisted consumer group).
|
|
68
|
+
- Deprecate the old shape only after the consumer-migration confirmation report is logged in the migration ticket. Default deprecation window: 1 full release cycle plus 1 on-call rotation past zero consumption.
|
|
69
|
+
|
|
70
|
+
## Outbox and Idempotency
|
|
71
|
+
|
|
72
|
+
- Every event carries a unique `event_id`. Prefer UUIDv7 over UUIDv4 — UUIDv7 is time-sortable, which simplifies dedup and ordering checks.
|
|
73
|
+
- Consumers deduplicate by `event_id` over a sliding window sized to the maximum reprocessing horizon (typically 24–72 hours).
|
|
74
|
+
- Producers that write to a transactional database publish events via the transactional outbox pattern: append the event row to an `outbox` table in the same DB transaction as the business write; a separate relay process drains the outbox to the broker with at-least-once semantics. This avoids the dual-write inconsistency between DB and broker.
|
|
75
|
+
- Every consumer is idempotent at the business-logic layer — receiving the same `event_id` twice produces the same end-state.
|
|
76
|
+
|
|
77
|
+
## Verification
|
|
78
|
+
|
|
79
|
+
- CI runs a registry compatibility check on every PR that touches a schema file: `confluent-schema-registry-maven-plugin` test-compatibility goal, the REST `/compatibility/subjects/<subject>/versions/latest` endpoint, or `buf breaking` for protobuf. PR fails on incompatible diff.
|
|
80
|
+
- `buf breaking --against '.git#branch=main'` runs on every protobuf change to detect tag-reuse, type-narrowing, and enum-value removal.
|
|
81
|
+
- Generated client code from schemas is regenerated and committed in the same PR as the schema change; CI fails on drift between schema and generated code.
|
|
82
|
+
- A schema-evolution test fixture replays a representative set of historical messages against the new schema and asserts deserialization success.
|
|
83
|
+
|
|
84
|
+
## References
|
|
85
|
+
|
|
86
|
+
- Confluent Schema Registry — Schema Evolution and Compatibility: https://docs.confluent.io/platform/current/schema-registry/fundamentals/schema-evolution.html
|
|
87
|
+
- Apache Avro Specification — Schema Resolution: https://avro.apache.org/docs/current/specification/#schema-resolution
|
|
88
|
+
- Protocol Buffers Language Guide (proto3) — Updating a Message Type: https://protobuf.dev/programming-guides/proto3/#updating
|
|
89
|
+
- `buf breaking` — protobuf breaking-change detector: https://buf.build/docs/breaking/overview
|
|
90
|
+
- CloudEvents specification: https://github.com/cloudevents/spec
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Event and message schema evolution patterns for Kafka / Kinesis / Pub-Sub / event store — backward + forward + full compatibility modes, schema registry, consumer-side defaults
|
|
3
|
+
globs: ["**/events/**", "**/schemas/**", "**/*.avsc", "**/*.proto", "**/messaging/**", "**/kafka/**", "**/pubsub/**"]
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
# Event Schema Evolution
|
|
7
|
+
|
|
8
|
+
Schemas for events, messages, and stream records evolve independently of producer and consumer deploy order. Every change must declare an explicit compatibility mode and pass a registry compatibility check before merge.
|
|
9
|
+
|
|
10
|
+
## Compatibility Modes
|
|
11
|
+
|
|
12
|
+
A registry compatibility mode constrains the diff between adjacent schema versions. Pick the mode that matches the deploy-order guarantee available in the target system.
|
|
13
|
+
|
|
14
|
+
- **`BACKWARD`** — a consumer using the new schema reads data written with the old schema. Allowed diffs: delete a field, add a field that has a default value. Deploy consumers first. Default for evolving consumer code.
|
|
15
|
+
- **`FORWARD`** — a consumer using the old schema reads data written with the new schema. Allowed diffs: add a field, delete a field that had a default value. Deploy producers first. Default for evolving producer code.
|
|
16
|
+
- **`FULL`** — both directions. Required when producer and consumer deploy order cannot be controlled (e.g., split across teams or platforms).
|
|
17
|
+
- **`*_TRANSITIVE`** variants (BACKWARD_TRANSITIVE, FORWARD_TRANSITIVE, FULL_TRANSITIVE) — the constraint holds against every prior schema version, not just the immediately preceding one. Required when consumers may replay from offset zero or read a historical archive.
|
|
18
|
+
- **`NONE`** — disables compatibility checking; breaking changes accepted. Permitted only on a dedicated `*-v2` subject during a planned migration window with a dated deprecation plan in the migration ticket.
|
|
19
|
+
|
|
20
|
+
Default recommendation when in doubt: `BACKWARD_TRANSITIVE` — consumers can deploy first and replay from offset zero.
|
|
21
|
+
|
|
22
|
+
## Schema Registry Mandate
|
|
23
|
+
|
|
24
|
+
- Every event topic / stream / subscription has a registered schema in Confluent Schema Registry, Apicurio Registry, AWS Glue Schema Registry, or Karapace. No in-tree schema-only repos without a registry binding.
|
|
25
|
+
- Subject naming strategy is declared per topic: `TopicNameStrategy` (one schema per topic — default), `RecordNameStrategy` (one schema per record type across topics), or `TopicRecordNameStrategy` (multiple record types per topic). Mixing strategies inside the same topic is forbidden.
|
|
26
|
+
- Compatibility mode is set per subject in the registry and asserted in CI. Changing the mode requires a registry-admin role and a logged justification.
|
|
27
|
+
- Schemas are versioned by the registry; the producer pins the schema ID it serialized with, and the consumer fetches by ID — never by name + "latest".
|
|
28
|
+
|
|
29
|
+
## Avro Evolution Rules
|
|
30
|
+
|
|
31
|
+
- Adding a field requires a `default` value to remain backward-compatible — a consumer using the new schema reads old data by substituting the default for the absent field.
|
|
32
|
+
- Removing a field requires the field to have had a `default` value to remain forward-compatible — an old consumer reads new data and the missing field falls back to its declared default.
|
|
33
|
+
- Use a union with `null` (e.g., `["null", "string"]` with `default: null`) to express an optional field. Place `null` first in the union so the default is unambiguously the null branch.
|
|
34
|
+
- Never rename a field — add a new field and register an `aliases: ["old_name"]` entry on the new field so old data deserializes against the new schema.
|
|
35
|
+
- Never change a field's type. To replace a type, add a new field of the new type, dual-write during the migration window, and remove the old field only after consumer migration completes.
|
|
36
|
+
|
|
37
|
+
## Protobuf Evolution Rules
|
|
38
|
+
|
|
39
|
+
- Use `proto3` for new schemas. Field numbers are immutable identifiers — never reuse a tag number, never renumber, never reorder by tag.
|
|
40
|
+
- When removing a field, add a `reserved` clause for both the tag number and the field name so future authors cannot resurrect the removed field with a different type and produce silent data corruption.
|
|
41
|
+
- Field type widening is constrained: int32 / uint32 / int64 / uint64 / bool are mutually wire-compatible; sint32 ↔ sint64 are compatible; fixed32 ↔ sfixed32 are compatible; `string` ↔ `bytes` are compatible when bytes are valid UTF-8. Other type changes are breaking.
|
|
42
|
+
- Use `optional` (proto3 since 3.15) for clear presence semantics on scalar fields. Without `optional`, unset and default-valued fields are indistinguishable on the wire.
|
|
43
|
+
- Never remove an enum value — mark it `[deprecated = true]` and leave it in place. Removing an enum value breaks consumers that have it pinned.
|
|
44
|
+
- New message types are not forward-compatible — old producers/consumers do not know about them. Prefer `BACKWARD_TRANSITIVE` for protobuf subjects.
|
|
45
|
+
|
|
46
|
+
## JSON Schema Evolution
|
|
47
|
+
|
|
48
|
+
- Default policy: additive only. New optional properties may be added; required properties may not be added to an existing record type.
|
|
49
|
+
- `additionalProperties: false` blocks forward compatibility (a consumer using the old strict schema rejects new fields). Choose explicitly: set `false` only when the consumer must reject unknown fields for security reasons; set `true` (or omit) to allow forward-compatible evolution.
|
|
50
|
+
- Version the schema identifier with semver (e.g., `$id: "https://example.com/schemas/event/v1.3.0.json"`). Patch and minor bumps must be additive; major bumps signal an incompatible change and require a new subject.
|
|
51
|
+
- For shared envelope shapes (e.g., CloudEvents), pin the envelope spec version and version only the `data` payload schema.
|
|
52
|
+
|
|
53
|
+
## Consumer-Side Defaults and Tolerance
|
|
54
|
+
|
|
55
|
+
- Every optional field deserializes to an explicit default value in consumer code (zero-value, `None`, empty string, empty list — declared, not implicit).
|
|
56
|
+
- Consumers never panic, crash, or fail-stop on a missing field. Missing → default. Unknown field → log at `info`, increment `event.schema.unknown_field` counter, continue processing.
|
|
57
|
+
- Emit `event.schema.version` and `event.subject` as attributes on every consumer-side trace span and metric label, so observability dashboards surface version distribution and detect stuck consumers on the old schema.
|
|
58
|
+
- Consumers validate against the schema fetched by ID at deserialization time; never validate against a hard-coded in-process schema literal.
|
|
59
|
+
|
|
60
|
+
## Dual-Publish During Migration
|
|
61
|
+
|
|
62
|
+
- When the shape change exceeds what the registry compatibility mode permits, dual-publish: write the same logical event in both old and new shapes — either to two topics (`orders.v1`, `orders.v2`) or to one topic with a union schema discriminated by a `schema_version` field.
|
|
63
|
+
- Keep dual-publish active until every consumer has been confirmed migrated to the new shape (poll consumer-group offsets against both topics; alert on lag on the new shape; alert on consumption from the old shape from any non-allowlisted consumer group).
|
|
64
|
+
- Deprecate the old shape only after the consumer-migration confirmation report is logged in the migration ticket. Default deprecation window: 1 full release cycle plus 1 on-call rotation past zero consumption.
|
|
65
|
+
|
|
66
|
+
## Outbox and Idempotency
|
|
67
|
+
|
|
68
|
+
- Every event carries a unique `event_id`. Prefer UUIDv7 over UUIDv4 — UUIDv7 is time-sortable, which simplifies dedup and ordering checks.
|
|
69
|
+
- Consumers deduplicate by `event_id` over a sliding window sized to the maximum reprocessing horizon (typically 24–72 hours).
|
|
70
|
+
- Producers that write to a transactional database publish events via the transactional outbox pattern: append the event row to an `outbox` table in the same DB transaction as the business write; a separate relay process drains the outbox to the broker with at-least-once semantics. This avoids the dual-write inconsistency between DB and broker.
|
|
71
|
+
- Every consumer is idempotent at the business-logic layer — receiving the same `event_id` twice produces the same end-state.
|
|
72
|
+
|
|
73
|
+
## Verification
|
|
74
|
+
|
|
75
|
+
- CI runs a registry compatibility check on every PR that touches a schema file: `confluent-schema-registry-maven-plugin` test-compatibility goal, the REST `/compatibility/subjects/<subject>/versions/latest` endpoint, or `buf breaking` for protobuf. PR fails on incompatible diff.
|
|
76
|
+
- `buf breaking --against '.git#branch=main'` runs on every protobuf change to detect tag-reuse, type-narrowing, and enum-value removal.
|
|
77
|
+
- Generated client code from schemas is regenerated and committed in the same PR as the schema change; CI fails on drift between schema and generated code.
|
|
78
|
+
- A schema-evolution test fixture replays a representative set of historical messages against the new schema and asserts deserialization success.
|
|
79
|
+
|
|
80
|
+
## References
|
|
81
|
+
|
|
82
|
+
- Confluent Schema Registry — Schema Evolution and Compatibility: https://docs.confluent.io/platform/current/schema-registry/fundamentals/schema-evolution.html
|
|
83
|
+
- Apache Avro Specification — Schema Resolution: https://avro.apache.org/docs/current/specification/#schema-resolution
|
|
84
|
+
- Protocol Buffers Language Guide (proto3) — Updating a Message Type: https://protobuf.dev/programming-guides/proto3/#updating
|
|
85
|
+
- `buf breaking` — protobuf breaking-change detector: https://buf.build/docs/breaking/overview
|
|
86
|
+
- CloudEvents specification: https://github.com/cloudevents/spec
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: hatch3r-handoff-readiness
|
|
3
|
+
type: rule
|
|
4
|
+
description: Handoff readiness checklist — pre-write validation before persisting a canonical handoff document.
|
|
5
|
+
scope: conditional
|
|
6
|
+
globs: .agents/handoffs/active/**/*.md
|
|
7
|
+
precedence: high
|
|
8
|
+
tags: [core, maintenance]
|
|
9
|
+
quality_charter: agents/shared/quality-charter.md
|
|
10
|
+
cache_friendly: true
|
|
11
|
+
---
|
|
12
|
+
# Handoff Readiness Checklist
|
|
13
|
+
|
|
14
|
+
Before writing a handoff to `.agents/handoffs/active/`, verify each criterion. Refuse the write if any **Required** criterion fails; warn on **Recommended** failures.
|
|
15
|
+
|
|
16
|
+
## Required (fail = refuse write)
|
|
17
|
+
|
|
18
|
+
| # | Criterion | Rationale |
|
|
19
|
+
|---|-----------|-----------|
|
|
20
|
+
| 1 | Body ≤ 51,200 bytes (50 KB) | Token bloat — full transcripts and unbounded sessions degrade resume reliability |
|
|
21
|
+
| 2 | Body contains no full message transcript | Token bloat — structured fields only |
|
|
22
|
+
| 3 | All 8 required sections present (Problem, Decisions, Work Done, Work Remaining, Blockers, Next Steps, Build & Test Status, File Manifest) | Resume needs structured state |
|
|
23
|
+
| 4 | git_ref matches current HEAD (branch@sha7) | Staleness signal integrity |
|
|
24
|
+
| 5 | Frontmatter validates against schema | Loader interop |
|
|
25
|
+
| 6 | Injection-pattern scan clean (P-LEARN-01..05) | ASI06 memory poisoning prevention |
|
|
26
|
+
| 7 | Integrity hash computed (sha256:<hex>) | Tamper detection |
|
|
27
|
+
|
|
28
|
+
## Recommended (fail = warn)
|
|
29
|
+
|
|
30
|
+
| # | Criterion | Rationale |
|
|
31
|
+
|---|-----------|-----------|
|
|
32
|
+
| 8 | `summary` populated, ≤ 200 chars | Loader briefing budget |
|
|
33
|
+
| 9 | `target_agent` is explicit (not `any`) | Avoids handoff loops (industry anti-pattern) |
|
|
34
|
+
| 10 | `Build & Test Status` table populated with at least one row | Resume reliability — knowing whether tests passed at handoff time |
|
|
35
|
+
|
|
36
|
+
## Enforcement
|
|
37
|
+
|
|
38
|
+
The `hatch3r-handoff-preparer` agent applies this checklist before invoking `writeHandoff` in `src/content/handoffs/index.ts`. The `validateHandoffContent` function in `src/content/handoffs/validation.ts` runs criteria 1-7 as `errors[]` and 8-10 as `warnings[]`.
|
|
39
|
+
|
|
40
|
+
## Cross-references
|
|
41
|
+
|
|
42
|
+
- Body sections schema: `.agents/handoffs/README.md`
|
|
43
|
+
- Iteration Summary contract (populates Work Done / Work Remaining / Blockers): `rules/hatch3r-iteration-summary.md`
|
|
44
|
+
- Injection-pattern catalog: `agents/shared/injection-patterns.md` Section B
|
|
45
|
+
- Quality charter (confidence levels): `agents/shared/quality-charter.md`
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Handoff readiness checklist — pre-write validation before persisting a canonical handoff document.
|
|
3
|
+
globs: [".agents/handoffs/active/**/*.md"]
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
precedence: high
|
|
6
|
+
---
|
|
7
|
+
# Handoff Readiness Checklist
|
|
8
|
+
|
|
9
|
+
Before writing a handoff to `.agents/handoffs/active/`, verify each criterion. Refuse the write if any **Required** criterion fails; warn on **Recommended** failures.
|
|
10
|
+
|
|
11
|
+
## Required (fail = refuse write)
|
|
12
|
+
|
|
13
|
+
| # | Criterion | Rationale |
|
|
14
|
+
|---|-----------|-----------|
|
|
15
|
+
| 1 | Body ≤ 51,200 bytes (50 KB) | Token bloat — full transcripts and unbounded sessions degrade resume reliability |
|
|
16
|
+
| 2 | Body contains no full message transcript | Token bloat — structured fields only |
|
|
17
|
+
| 3 | All 8 required sections present (Problem, Decisions, Work Done, Work Remaining, Blockers, Next Steps, Build & Test Status, File Manifest) | Resume needs structured state |
|
|
18
|
+
| 4 | git_ref matches current HEAD (branch@sha7) | Staleness signal integrity |
|
|
19
|
+
| 5 | Frontmatter validates against schema | Loader interop |
|
|
20
|
+
| 6 | Injection-pattern scan clean (P-LEARN-01..05) | ASI06 memory poisoning prevention |
|
|
21
|
+
| 7 | Integrity hash computed (sha256:<hex>) | Tamper detection |
|
|
22
|
+
|
|
23
|
+
## Recommended (fail = warn)
|
|
24
|
+
|
|
25
|
+
| # | Criterion | Rationale |
|
|
26
|
+
|---|-----------|-----------|
|
|
27
|
+
| 8 | `summary` populated, ≤ 200 chars | Loader briefing budget |
|
|
28
|
+
| 9 | `target_agent` is explicit (not `any`) | Avoids handoff loops (industry anti-pattern) |
|
|
29
|
+
| 10 | `Build & Test Status` table populated with at least one row | Resume reliability — knowing whether tests passed at handoff time |
|
|
30
|
+
|
|
31
|
+
## Enforcement
|
|
32
|
+
|
|
33
|
+
The `hatch3r-handoff-preparer` agent applies this checklist before invoking `writeHandoff` in `src/content/handoffs/index.ts`. The `validateHandoffContent` function in `src/content/handoffs/validation.ts` runs criteria 1-7 as `errors[]` and 8-10 as `warnings[]`.
|
|
34
|
+
|
|
35
|
+
## Cross-references
|
|
36
|
+
|
|
37
|
+
- Body sections schema: `.agents/handoffs/README.md`
|
|
38
|
+
- Iteration Summary contract (populates Work Done / Work Remaining / Blockers): `rules/hatch3r-iteration-summary.md`
|
|
39
|
+
- Injection-pattern catalog: `agents/shared/injection-patterns.md` Section B
|
|
40
|
+
- Quality charter (confidence levels): `agents/shared/quality-charter.md`
|