@pavp/wavefront 0.1.0

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.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +226 -0
  3. package/agents/i18n-tokens.md +58 -0
  4. package/agents/mapper.md +64 -0
  5. package/agents/module-builder.md +90 -0
  6. package/agents/reviewer.md +65 -0
  7. package/agents/tester.md +84 -0
  8. package/bin/wavefront.js +91 -0
  9. package/commands/wavefront-change.md +26 -0
  10. package/commands/wavefront-execute.md +28 -0
  11. package/commands/wavefront-feature.md +25 -0
  12. package/commands/wavefront-fix.md +28 -0
  13. package/commands/wavefront-init.md +27 -0
  14. package/commands/wavefront-plan.md +30 -0
  15. package/commands/wavefront-ship.md +26 -0
  16. package/commands/wavefront-state.md +23 -0
  17. package/commands/wavefront-verify.md +24 -0
  18. package/hooks/lint-after-edit.sh +43 -0
  19. package/hooks/typecheck-on-stop.sh +27 -0
  20. package/install.sh +83 -0
  21. package/package.json +67 -0
  22. package/planning-templates/PHASE_PLAN.md +37 -0
  23. package/planning-templates/PROJECT.md +18 -0
  24. package/planning-templates/REQUIREMENTS.md +27 -0
  25. package/planning-templates/ROADMAP.md +12 -0
  26. package/planning-templates/STATE.md +21 -0
  27. package/settings.template.json +29 -0
  28. package/skills/clean-architecture/SKILL.md +46 -0
  29. package/skills/component-composition/SKILL.md +67 -0
  30. package/skills/component-composition/examples/compound-component.md +62 -0
  31. package/skills/data-fetching-react-query/SKILL.md +68 -0
  32. package/skills/design-intake/SKILL.md +69 -0
  33. package/skills/design-system-inventory/SKILL.md +38 -0
  34. package/skills/forms-rhf-zod/SKILL.md +75 -0
  35. package/skills/gateway-pattern/SKILL.md +79 -0
  36. package/skills/hook-patterns/SKILL.md +74 -0
  37. package/skills/i18n-next-intl/SKILL.md +59 -0
  38. package/skills/module-structure/SKILL.md +98 -0
  39. package/skills/mui-design-tokens/SKILL.md +60 -0
  40. package/skills/naming-conventions/SKILL.md +65 -0
  41. package/skills/repository-pattern/SKILL.md +128 -0
  42. package/skills/requirement-intake/SKILL.md +65 -0
  43. package/skills/responsive-layouts/SKILL.md +64 -0
  44. package/skills/selector-pattern/SKILL.md +59 -0
  45. package/skills/store-zustand/SKILL.md +63 -0
  46. package/skills/sync-audit/SKILL.md +52 -0
  47. package/skills/testing-jest-rtl/SKILL.md +83 -0
  48. package/uninstall.sh +36 -0
@@ -0,0 +1,52 @@
1
+ ---
2
+ name: sync-audit
3
+ description: Detect drift between wavefront's self-contained skills and the scaffold they were distilled from, by comparing each skill's source_version pin against the current scaffold. Read when running an audit or before trusting skills on a newer scaffold.
4
+ source: wavefront framework meta — audits the other skills
5
+ source_version: 8edaa0b
6
+ ---
7
+
8
+ # Sync audit (drift detection)
9
+
10
+ wavefront skills are **self-contained** (copied knowledge, not links to scaffold `docs/`). The tradeoff: they can drift as the scaffold evolves. This skill is the promised mitigation — it detects drift so skills get re-pinned deliberately.
11
+
12
+ ## What each skill carries
13
+
14
+ Every `*/SKILL.md` frontmatter has:
15
+ - `source:` — the scaffold file(s)/doc(s) it was distilled from.
16
+ - `source_version:` — the scaffold git commit it was pinned at (currently `8edaa0b`).
17
+
18
+ Drift = the scaffold's `source` files changed since `source_version`.
19
+
20
+ ## Audit procedure
21
+
22
+ Inputs: path to a scaffold checkout (or the generated app, which mirrors it). Without it, degrade to a frontmatter-only report (list pins, can't diff).
23
+
24
+ 1. **Collect pins:** read `source_version` + `source` from all `.claude/skills/*/SKILL.md`. Confirm they agree on one version (they should).
25
+ 2. **Get scaffold HEAD:** in the scaffold repo, `git rev-parse --short HEAD`. If it equals the pin → CLEAN, stop.
26
+ 3. **Diff source files:** `git diff --name-only <pin> <HEAD> -- <union of all skills' source paths>`.
27
+ - Map each changed file back to the skill(s) whose `source:` references it.
28
+ 4. **Classify:**
29
+ - **STALE (action needed):** a skill's `source` file changed → its content may be wrong.
30
+ - **PIN-ONLY (cheap):** no source file changed but `source_version` < HEAD → just bump the pin (content still valid). This was the case for `8148abf → 8edaa0b`.
31
+ 5. **Report:** per-skill verdict + the diff summary for STALE ones + a suggested re-pin/re-distill list. Read-only — never auto-rewrite skills.
32
+
33
+ ## Output shape
34
+
35
+ ```
36
+ wavefront sync-audit — pin 8edaa0b vs scaffold <HEAD>
37
+ CLEAN: <n> skills (no source change)
38
+ PIN-ONLY: <skills> → bump source_version to <HEAD>
39
+ STALE: <skill> ← <changed file> (re-distill: <what to recheck>)
40
+ Verdict: <CLEAN | PIN-ONLY bump | RE-DISTILL needed>
41
+ ```
42
+
43
+ ## Re-pin vs re-distill
44
+ - **PIN-ONLY:** bulk-bump `source_version` across skills (mechanical).
45
+ - **STALE:** read the changed source file, update that skill's content, then bump its pin. One skill at a time.
46
+
47
+ ## Notes
48
+ - Scaffold source moves independently of wavefront; expect periodic PIN-ONLY drift.
49
+ - Generated apps == scaffold at their generation commit, so a generated app is a valid diff target when the scaffold repo isn't handy.
50
+
51
+ ## Related
52
+ Audits all pattern/core skills: [[clean-architecture]] [[module-structure]] [[naming-conventions]] [[repository-pattern]] [[gateway-pattern]] [[data-fetching-react-query]] [[store-zustand]] [[selector-pattern]] [[hook-patterns]] [[forms-rhf-zod]] [[mui-design-tokens]] [[testing-jest-rtl]] [[i18n-next-intl]]
@@ -0,0 +1,83 @@
1
+ ---
2
+ name: testing-jest-rtl
3
+ description: Jest + React Testing Library conventions in scaffold-nextjs-app — renderWithProviders, faker mock factories, colocated tests. Read before writing tests.
4
+ source: scaffold-nextjs-app/docs/testing.md + test/utils, test/entities, src/modules/todo/**/*.test.*
5
+ source_version: 8edaa0b
6
+ ---
7
+
8
+ # Testing: Jest + RTL
9
+
10
+ Tests colocate next to source as `*.test.ts` / `*.test.tsx`. Everything is imported from `@test/utils` (lint forbids importing RTL / `react-dom` directly in feature tests).
11
+
12
+ ## Coverage is per-layer (mirror todo)
13
+ The scaffold tests EVERY layer — `src/modules/todo` ships a colocated test for api, gateway, repository (queries + mutations), store, each selector, business + controller hooks, each helper, each component, and the view. Match that: one colocated test per piece with logic, not just the happy-path hook.
14
+ - **Unit:** pure pieces alone — helpers, store, a presentational component with mock props.
15
+ - **Integration:** pieces wired through providers — `renderHookWithProviders` for a business hook (hook→repository→gateway→api), a view with real hooks.
16
+ Cover both. A module with one test is undertested.
17
+
18
+ ## Import surface
19
+
20
+ ```ts
21
+ import { renderWithProviders, renderHookWithProviders, screen, fireEvent, waitFor } from '@test/utils';
22
+ import { createMockTodo, createMockTodos } from '@test/entities/todo.mock'; // faker factories
23
+ ```
24
+ - `renderWithProviders(ui, opts)` — wraps in `AllProviders` (QueryClient + Theme + intl). Returns `{ queryClient, ...result }`.
25
+ - `renderHookWithProviders(hook, opts)` — same providers for hooks.
26
+ - Options: `{ queryClient?, queryClientOptions?, initialStoreStates? }` — seed Zustand via `initialStoreStates`.
27
+
28
+ ## Component test
29
+
30
+ ```tsx
31
+ import { fireEvent, renderWithProviders, screen, waitFor } from '@test/utils';
32
+ import { TodoForm } from './todo-form.component';
33
+
34
+ describe('TodoForm', () => {
35
+ const mockOnSubmit = jest.fn();
36
+ beforeEach(() => mockOnSubmit.mockClear());
37
+
38
+ it('calls onSubmit with form data', async () => {
39
+ renderWithProviders(<TodoForm isCreating={false} onSubmit={mockOnSubmit} />);
40
+ fireEvent.change(screen.getByRole('textbox', { name: /title/i }), { target: { value: 'Test' } });
41
+ await waitFor(() => expect(screen.getByRole('button', { name: /add/i })).not.toBeDisabled());
42
+ fireEvent.click(screen.getByRole('button', { name: /add/i }));
43
+ expect(mockOnSubmit).toHaveBeenCalledWith({ title: 'Test', description: '', priority: 'medium' });
44
+ });
45
+ });
46
+ ```
47
+
48
+ ## Hook test
49
+
50
+ ```ts
51
+ import { renderHookWithProviders, waitFor } from '@test/utils';
52
+ const { result } = renderHookWithProviders(() => useTodoStatsSelector(), {
53
+ initialStoreStates: { 'todo-store': { filters: {} } },
54
+ });
55
+ await waitFor(() => expect(result.current.isLoading).toBe(false));
56
+ ```
57
+
58
+ ## Mock factories (per entity)
59
+
60
+ ```ts
61
+ // test/entities/[entity].mock.ts
62
+ import { faker } from '@faker-js/faker';
63
+ export const createMockTodo = (overrides: Partial<Todo> = {}): Todo => ({
64
+ id: faker.number.int(), title: faker.lorem.sentence(), completed: false, ...overrides,
65
+ });
66
+ export const createMockTodos = (count: number, base = {}): Todo[] =>
67
+ Array.from({ length: count }, (_, i) => createMockTodo({ id: i + 1, ...base }));
68
+ // + specialized (createCompletedTodo) + deterministic (createDeterministicTodo with faker.seed)
69
+ ```
70
+
71
+ ## Conventions
72
+ - Query priority: `getByRole` > `getByLabelText` > `getByText`; avoid testid unless necessary (`data-testid` exists for some views).
73
+ - Async UI: wrap assertions in `waitFor`. Use `jest.fn()` for callbacks, clear in `beforeEach`.
74
+ - Test behavior, not implementation. Seed data with factories, not inline literals.
75
+ - `__mocks__` (next-intl, next/navigation, zustand, mixpanel, screeb, fonts/styles) are pre-wired in `test/__mocks__` + `test/jest.setup.tsx` — rely on them.
76
+ - Run: `yarn test` / `yarn test:watch` / `yarn test:changed`. Filter by path with `yarn test --testPathPatterns=<name>` (Jest 30 — note the plural; old `--testPathPattern` errors).
77
+ - Coverage threshold is **85% global**: running a single new file fails the coverage gate (exit 1) even when tests pass. That exit is the threshold, not a test failure — judge by `Tests: N passed`. Add enough tests for the module, or run the full suite, before treating exit 1 as red.
78
+
79
+ ## TDD note (confirm mode with user)
80
+ RED→GREEN supported but the scaffold's existing tests are post-hoc. Default to writing tests against the built component unless the user asks for strict RED-first.
81
+
82
+ ## Related skills
83
+ [[mui-design-tokens]] · [[hook-patterns]] · [[i18n-next-intl]] · [[naming-conventions]]
package/uninstall.sh ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env bash
2
+ # wavefront uninstaller — removes the surface (symlinks or copies) from a target app.
3
+ # Usage: ./uninstall.sh <target-app> [--purge-home]
4
+ # --purge-home also remove ~/.wavefront (the global install)
5
+ set -euo pipefail
6
+
7
+ HOME_DIR="${WAVEFRONT_HOME:-$HOME/.wavefront}"
8
+ SURFACE=(agents skills commands planning-templates)
9
+
10
+ die() { echo "error: $*" >&2; exit 1; }
11
+
12
+ [ $# -ge 1 ] || die "usage: ./uninstall.sh <target-app> [--purge-home]"
13
+ TARGET="$1"; PURGE="${2:-}"
14
+ CLAUDE_DIR="$TARGET/.claude"
15
+
16
+ [ -d "$CLAUDE_DIR" ] || die ".claude not found in $TARGET"
17
+
18
+ for d in "${SURFACE[@]}"; do
19
+ link="$CLAUDE_DIR/$d"
20
+ if [ -L "$link" ]; then
21
+ rm -f "$link"; echo "removed symlink $link"
22
+ elif [ -d "$link" ]; then
23
+ rm -rf "$link"; echo "removed copy $link"
24
+ fi
25
+ done
26
+
27
+ # hooks (copied) + the settings template we wrote
28
+ [ -d "$CLAUDE_DIR/hooks" ] && { rm -rf "$CLAUDE_DIR/hooks"; echo "removed $CLAUDE_DIR/hooks"; }
29
+ [ -f "$CLAUDE_DIR/settings.wavefront.json" ] && { rm -f "$CLAUDE_DIR/settings.wavefront.json"; echo "removed settings.wavefront.json"; }
30
+ echo "note: if you merged the hooks block into settings.json, remove it manually."
31
+
32
+ if [ "$PURGE" = "--purge-home" ]; then
33
+ rm -rf "$HOME_DIR"; echo "purged $HOME_DIR"
34
+ fi
35
+
36
+ echo "✓ uninstall done."