From aaf696671561df9d8593ee8272df76be2bd88154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Bokisch?= Date: Wed, 25 Mar 2026 11:11:16 +0100 Subject: [PATCH 1/5] Upgrade workflows, rules, and settings to match fundamentals quality - Add workflow.md: role definition, mindset, API design philosophy, validation checklist, debugging, context management (inspired by tRPC, Zod, Drizzle, Svelte, Solid, Hono, Next.js, Nuxt) - Update anti-patterns.md: add stale closures, architecture mistakes, testing mistakes, file organization, conditional spreads - Add development.md: signal reactivity, package boundaries, context pattern, component customization, middleware pattern, version alignment, bun quirks - Update .claude/settings.json: comprehensive permissions with deny list - Update CI: add timeout-minutes, coverage upload, format check, proper concurrency group, permissions block Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/rules/anti-patterns.md | 36 +++++++++--- .claude/rules/development.md | 89 ++++++++++++++++++++++++++++ .claude/rules/workflow.md | 104 +++++++++++++++++++++++++++++++++ .claude/settings.json | 62 +++++++++++++------- .github/workflows/ci.yml | 40 ++++++------- 5 files changed, 282 insertions(+), 49 deletions(-) create mode 100644 .claude/rules/development.md create mode 100644 .claude/rules/workflow.md diff --git a/.claude/rules/anti-patterns.md b/.claude/rules/anti-patterns.md index 14177c9..74c2c8b 100644 --- a/.claude/rules/anti-patterns.md +++ b/.claude/rules/anti-patterns.md @@ -1,9 +1,10 @@ -# Anti-patterns — Common Mistakes in Pyreon Zero Apps +# Anti-patterns — Common Mistakes in Pyreon Zero ## React patterns that don't apply here - **Never** use `useState`, `useEffect`, `useCallback`, `useMemo` — these are React hooks - **Never** import `h` manually in `.tsx` files — JSX transform handles it - **Never** return cleanup functions from `onMount` — use `onUnmount` separately +- **Never** use `className` or `htmlFor` — use `class` and `for` ## Signal mistakes - **Never** create signals inside the render return function — they must be in the component body @@ -11,31 +12,34 @@ - **Never** set 3+ signals individually without `batch()` — causes unnecessary re-renders - **Never** call `signal(value)` to set — use `signal.set(value)` or `signal.update(fn)` - **Never** forget to call signal as function to read: use `count()` not `count` +- **Stale closures**: Don't capture `signal.peek()` in a closure that outlives the current tick. Use `signal()` (subscribing read) inside effects/computeds +- **Signal in hot path**: Don't create signals inside render functions or loops — create them once in setup ## JSX attribute casing -- **Always** use camelCase for JSX attributes: `onClick`, `onMouseEnter`, `onTouchStart`, `onLoad` +- **Always** use camelCase for events: `onClick`, `onMouseEnter`, `onTouchStart`, `onLoad` - **Never** use lowercase DOM event names: `onclick`, `onmouseenter`, `ontouchstart`, `onload` - **Always** use `srcSet` not `srcset`, `fetchPriority` not `fetchpriority` -- **Always** use `className` → `class`, `htmlFor` → `for` (Pyreon uses HTML names, not React names) ## JSX reactive expressions - **Never** use bare signal reads in JSX text — wrap in arrow: `{() => count()}` not `{count()}` -- **Never** return `undefined` from reactive JSX attributes — return empty string `''` instead -- **Never** use reactive functions for `aria-current` — compute it as a static value +- **Never** return `undefined` from reactive JSX attributes — return empty string `''` or use conditional spread `{...(value ? { attr: value } : {})}` +- Use conditional spreads for optional attributes with `exactOptionalPropertyTypes` ## Effect cleanup - `effect()` returns an `Effect` object with `.dispose()` — not a raw function - Use `onUnmount(() => dispose.dispose())` for cleanup, not `onUnmount(dispose)` -- Prefer `onCleanup()` inside effects for inline cleanup (available since @pyreon/reactivity 0.7.0) +- Prefer `onCleanup()` inside effects for inline cleanup -## Context mistakes +## Context pattern - **Never** use `` JSX — Pyreon contexts don't have a `.Provider` component -- Use `provide(context, value)` from `@pyreon/core` (available since 0.6.0) — it calls `pushContext` + `onUnmount(popContext)` automatically +- Use `provide(context, value)` from `@pyreon/core` — it calls `pushContext` + `onUnmount(popContext)` automatically - For manual control: `pushContext(new Map([[ctx.id, value]]))` + `onUnmount(() => popContext())` +- Always throw if context is missing: `if (!instance) throw new Error("[zero] useX() must be used within ")` ## Store mistakes - **Never** import `signal`/`computed`/`effect` from `@pyreon/reactivity` in app code — use `@pyreon/store` re-exports - **Never** call `defineStore` inside a component — it's a module-level declaration +- `useStore()` returns `{ store, patch, subscribe }` — destructure `store` to access state - Store setup function runs once (singleton) — don't rely on it re-running ## Form mistakes @@ -51,6 +55,22 @@ - Return `void` / `undefined` to pass through (don't short-circuit) - Use `withHeaders()` from `utils/with-headers.ts` to modify Response headers +## Architecture mistakes +- **Never** bundle `@pyreon/core` or `@pyreon/reactivity` — they must be peer dependencies +- **Never** import from another package's `src/` directly — use the package name +- Duck-type external library interfaces instead of importing their types — avoids hard version coupling +- Error messages prefixed with `[zero]` and include actionable guidance + +## Testing mistakes +- Test the public API as consumers use it, not internal implementation details +- Always run tests from the package directory +- Test error cases (throws, invalid inputs, edge cases) not just happy paths + +## File organization +- If a source file exceeds ~300 lines, consider splitting +- Tests go in `src/tests/`, not `__tests__/` or root +- Every new public function/type must be exported from `src/index.ts` + ## Hydration - `hydrateRoot(container, vnode)` — container first, then vnode (not reversed) - The `startClient()` function handles this automatically — prefer it over manual hydration diff --git a/.claude/rules/development.md b/.claude/rules/development.md new file mode 100644 index 0000000..23a177d --- /dev/null +++ b/.claude/rules/development.md @@ -0,0 +1,89 @@ +# Development Rules + +## Signal Reactivity + +- Every public reactive value MUST be a `Signal` or `Computed` — never a raw value that could go stale. +- Use `batch()` when setting multiple signals in a single operation to coalesce notifications. +- Use `signal.peek()` when reading without subscribing (e.g., inside event handlers, snapshot code). +- Never read signals inside constructors or module-level code — only inside effects, computeds, or component render functions. + +## Package Boundaries + +- Each package is independent. Never import from another `@pyreon/*` package's `src/` directly — use the package name. +- Peer dependencies (`@pyreon/core`, `@pyreon/reactivity`) are resolved at the consumer's level — never bundle them. +- `@pyreon/meta` is the barrel for fundamentals + UI system — `@pyreon/zero` is the framework. Never re-export fundamentals from zero directly. +- Shared utilities go in `packages/zero/src/utils/` — only extract when used by 2+ files. + +## Context Pattern + +All context-based APIs follow the same structure: + +```typescript +const XContext = createContext(null) + +function XProvider(props) { + pushContext(new Map([[XContext.id, props.instance]])) + onUnmount(() => popContext()) + return props.children +} + +function useX(): T { + const instance = useContext(XContext) + if (!instance) throw new Error("[zero] useX() must be used within ") + return instance +} +``` + +Or using `provide()` helper: + +```typescript +function XProvider(props) { + provide(XContext, props.instance) + return props.children +} +``` + +## Component Customization Pattern + +Components that need customization expose 3 levels: + +1. `useX(props)` — composable returning handlers, state, ref callback +2. `createX(Component)` — HOC wrapping any component with behavior +3. `X` — default component built on `createX` + +Example: `useLink()` → `createLink(Component)` → `Link` + +## Error Messages + +Prefix all thrown errors with `[zero]` and include actionable guidance: +```typescript +throw new Error("[zero] Missing #app container element. Add
to your index.html.") +``` + +## Middleware Pattern + +All middleware follows `(ctx: MiddlewareContext) => Response | void | Promise`: +- Return `Response` to short-circuit +- Return `void` / `undefined` to pass through +- Use `withHeaders()` from `utils/with-headers.ts` for header modification + +## Vite Plugin Pattern + +Vite plugins follow: `export function pluginName(config = {}): Plugin` + +## Route Module Exports + +Route files can export: `default`, `loader`, `guard`, `meta`, `error`, `loading`, `middleware`, `renderMode` + +## Version Alignment + +- All 4 packages (`zero`, `meta`, `zero-cli`, `create-zero`) share the same version (fixed versioning via changesets). +- `workspace:^` for inter-package peer deps (resolved at publish time). +- When bumping Pyreon deps, update: zero package.json, cli package.json, meta package.json, create-zero pyreonVersion(), template package.json, and CLAUDE.md. +- Always run `rm -f bun.lock && bun install` after version changes. + +## Bun Quirks + +- Bun doesn't resolve `extends` chains into `node_modules` for `jsxImportSource` — always duplicate it in root tsconfig. +- `customConditions: ["bun"]` needed for workspace deps to resolve in CI (lib/ not built). +- `bun run --filter='*' test` runs all workspace package tests — individual failures may cascade. diff --git a/.claude/rules/workflow.md b/.claude/rules/workflow.md new file mode 100644 index 0000000..ba22a01 --- /dev/null +++ b/.claude/rules/workflow.md @@ -0,0 +1,104 @@ +# Workflow Rules + +## Role + +You are a senior framework engineer building Pyreon Zero — a next-generation full-stack meta-framework designed for AI agents to build with successfully. Every decision should optimize for: correctness first, developer experience second, AI-friendliness third. + +## Mindset + +_Inspired by: Next.js (convention over configuration), Nuxt (file-based everything), Svelte (focused batched progress), Solid (alignment before implementation), Hono (lean core, modular extensions)_ + +- **Do it properly, not quickly.** No shortcuts. No workarounds when root causes can be found. No `as any`. No disabling strict flags. +- **Understand before changing.** Read existing code. Understand the problem fully. Form a hypothesis. Verify it. Then fix. +- **Be honest about quality.** A truthful 6/10 is infinitely more valuable than an inflated 9/10. List what's broken before claiming something works. +- **Think before acting.** For any non-trivial task, think through the approach first. Use plan mode for complex multi-step work. +- **Find root causes.** When something fails, investigate why — don't patch symptoms. Check versions, module resolution, types, and runtime behavior before writing code. +- **When uncertain, say so.** Don't guess. Don't fabricate confidence. Ask or investigate. +- **Verify before reporting.** Never blame upstream packages without reproducing in isolation. Read the actual type definition. Test the actual behavior. +- **One effort at a time.** Focus on completing the current task properly before starting the next. Batched, focused progress over scattered work. + +## API Design Philosophy + +_Inspired by: tRPC (types flow end-to-end), Zod (one clean chainable API), Drizzle ("if you know SQL, you know Drizzle")_ + +Zero's competitive advantage is simplicity. Every API must pass the "AI agent test" — can an AI agent use it correctly on the first try? + +- **Signals are the primitive.** `signal()`, `computed()`, `effect()`, `provide()` — four primitives that compose into everything. No dependency arrays, no re-renders. +- **File-based everything.** Routes, layouts, middleware, API routes, error boundaries — all from the file system. Convention over configuration. +- **Types flow end-to-end.** If users need `as any`, the types are wrong. +- **Zero-config defaults, full-control escape hatches.** Common case needs zero configuration. Advanced cases get explicit options. +- **Composability over configuration.** Three lines of explicit code beats a magic config object. + +## Before Writing Code + +- Read the existing source files before modifying. +- Check CLAUDE.md for the package's API surface. +- For new features, check if the pattern exists in another package. +- For complex tasks, outline the approach and get alignment before coding. + +## Code Changes + +- Keep changes minimal. One feature per file change. +- Follow existing naming: `useX` for hooks, `XProvider` for context, `createX` for factories. +- Export types separately: `export type { Foo }` not mixed with value exports. +- New public APIs need JSDoc with `@example` blocks. +- No unused imports, no dead code, no `// TODO` in committed code. +- Error messages prefixed with `[zero]` and include actionable guidance. + +## Testing + +- Every new public API needs tests. +- Test error cases, not just happy paths. +- Test files live at `packages/[name]/src/tests/`. +- Always run tests from the package directory. +- Run full test suite before pushing. + +## Git Practices — MANDATORY + +- **NEVER push directly to main.** Always create a branch and PR. +- **NEVER commit without running validation.** +- Don't commit unless explicitly asked. +- Never force push, never amend published commits. +- Use descriptive commit messages focused on "why" not "what". +- Stage specific files, not `git add .`. +- Always `git checkout main && git pull` before starting a new task. + +## Validation Checklist — Before EVERY Push + +Run ALL of these in order: + +1. `bun run lint` — no lint errors +2. `bun run typecheck` — zero type errors +3. `bun run test` — all tests pass + +If any step fails, fix it before pushing. Do not push broken code. + +## Before Considering Work Complete + +1. All validation checklist steps pass +2. Exports updated: new APIs in `src/index.ts` with type exports +3. CLAUDE.md updated if API surface changed +4. READMEs updated if user-facing features changed +5. Template updated if new patterns introduced +6. Anti-patterns rules updated if new gotchas discovered +7. No breaking changes without discussion +8. Honest quality assessment + +## Debugging + +- Check dependency versions and module resolution FIRST. +- Don't assume — verify. Read the actual error, check the actual types. +- If a workaround is needed temporarily, document WHY and create a follow-up. +- Never blame upstream without reproducing in isolation first. + +## Releases + +- Use changesets for versioning: `bunx changeset` to create, `bunx changeset version` to bump. +- Fixed versioning: all packages share the same version. +- New packages need manual first publish before CI can handle OIDC. + +## Context Management + +- Use `/compact` at ~50% context usage for long sessions. +- Start complex multi-package tasks in plan mode. +- Break work into steps that can complete within a single context window. diff --git a/.claude/settings.json b/.claude/settings.json index 9d20f61..cfc8e61 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -1,29 +1,49 @@ { "permissions": { "allow": [ - "Bash(bun run build)", - "Bash(bun run test)", - "Bash(bun run typecheck)", - "Bash(bun run dev)", - "Bash(bunx biome check .)", - "Bash(bunx biome check --write .)", - "Bash(bunx changeset)", - "Bash(bunx changeset version)", - "Bash(git status*)", - "Bash(git diff*)", - "Bash(git log*)", - "Bash(git branch*)", - "Bash(git stash*)", - "Bash(wc *)", - "Bash(ls *)", - "Bash(mkdir *)", - "Bash(cat *)" + "Read", + "Glob", + "Grep", + "Bash(bunx vitest:*)", + "Bash(bunx tsc:*)", + "Bash(bunx biome:*)", + "Bash(bunx changeset:*)", + "Bash(bun run:*)", + "Bash(bun install:*)", + "Bash(bun test:*)", + "Bash(bun x:*)", + "Bash(bun add:*)", + "Bash(git status:*)", + "Bash(git diff:*)", + "Bash(git log:*)", + "Bash(git branch:*)", + "Bash(git checkout:*)", + "Bash(git fetch:*)", + "Bash(git pull:*)", + "Bash(git add:*)", + "Bash(git commit:*)", + "Bash(git push:*)", + "Bash(git stash:*)", + "Bash(gh pr:*)", + "Bash(gh run:*)", + "Bash(gh api:*)", + "Bash(ls:*)", + "Bash(mkdir:*)", + "Bash(npm view:*)", + "Bash(npm pack:*)", + "Bash(sed:*)", + "Bash(grep:*)", + "Bash(wc:*)", + "Bash(head:*)", + "Bash(tail:*)", + "Bash(cp:*)" ], "deny": [ - "Bash(git push --force*)", - "Bash(git reset --hard*)", - "Bash(rm -rf *)", - "Bash(bun publish*)" + "Bash(rm -rf:*)", + "Bash(git push --force:*)", + "Bash(git reset --hard:*)", + "Bash(git checkout .)", + "Bash(bun publish:*)" ] } } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a7990ef..46b2a0a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,87 +8,87 @@ on: workflow_call: concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ci-${{ github.head_ref || github.ref }} cancel-in-progress: true +permissions: + contents: read + env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true jobs: lint: - name: Lint + name: Lint & Format runs-on: ubuntu-latest + timeout-minutes: 5 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 with: bun-version: latest - - run: bun install --frozen-lockfile - - - name: Biome lint & format check - run: bunx biome check . + - run: bun run lint + - run: bunx biome format ./packages/ typecheck: name: Typecheck runs-on: ubuntu-latest + timeout-minutes: 5 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 with: bun-version: latest - - run: bun install --frozen-lockfile - - name: Typecheck all packages run: bun run typecheck test: - name: Test + name: Test & Coverage runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 with: bun-version: latest - - run: bun install --frozen-lockfile - - name: Run tests run: bun run test + - name: Upload coverage + if: always() + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 + with: + name: coverage-reports + path: packages/*/coverage/ + retention-days: 7 template: name: Template Validation runs-on: ubuntu-latest + timeout-minutes: 5 steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 with: bun-version: latest - - name: Test template scaffold run: bash scripts/test-template.sh build: name: Build runs-on: ubuntu-latest + timeout-minutes: 10 needs: [lint, typecheck, test, template] steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 with: bun-version: latest - - run: bun install --frozen-lockfile - - name: Build all packages run: bun run build - - name: Check for uncommitted changes after build run: | if [ -n "$(git status --porcelain)" ]; then From e52dc0f2bf2bed8cc8783bb8c781e7a174cce0a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Bokisch?= Date: Wed, 25 Mar 2026 11:14:02 +0100 Subject: [PATCH 2/5] Add lint and format scripts to root package.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI calls bun run lint — needs the script to exist. Co-Authored-By: Claude Opus 4.6 (1M context) --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index dd3db8d..c60e908 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,8 @@ "dev": "bun run --filter='*' dev", "test": "bun run --filter='*' test", "typecheck": "bun run --filter='*' typecheck", + "lint": "bunx biome check .", + "format": "bunx biome format ./packages/", "test:template": "bash scripts/test-template.sh", "version-packages": "changeset version", "release": "bun run build && bun run scripts/publish.ts" From ac395236945fa414935ac31bb537408c0c6e8bf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Bokisch?= Date: Wed, 25 Mar 2026 11:16:11 +0100 Subject: [PATCH 3/5] Add Continuous Learning section to workflow rules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After every PR, update anti-patterns, development rules, CLAUDE.md, and building docs with learnings. The rules files are institutional memory — write it down now, not later. Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/rules/workflow.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.claude/rules/workflow.md b/.claude/rules/workflow.md index ba22a01..9e36240 100644 --- a/.claude/rules/workflow.md +++ b/.claude/rules/workflow.md @@ -97,6 +97,18 @@ If any step fails, fix it before pushing. Do not push broken code. - Fixed versioning: all packages share the same version. - New packages need manual first publish before CI can handle OIDC. +## Continuous Learning — MANDATORY + +After every PR, review what happened and update the rules: + +- **New anti-pattern discovered?** Add it to `anti-patterns.md` with the "why" so future sessions avoid it. +- **New development pattern established?** Add it to `development.md` so future sessions follow it consistently. +- **API changed upstream?** Update `CLAUDE.md`, template `CLAUDE.md`, and `building.md` with the new API. +- **Bun/TypeScript quirk found?** Document it in `development.md` under "Bun Quirks" so it's not rediscovered. +- **Workaround added?** Document WHY in a code comment AND add to anti-patterns so it gets removed when the upstream fix lands. + +The rules files are your institutional memory. If you learn something in this session that would help a future session, write it down NOW — not later. Every PR is an opportunity to make the next PR better. + ## Context Management - Use `/compact` at ~50% context usage for long sessions. From 1f0ac96dc882dc624ddc9dec0fff946bc920d9ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Bokisch?= Date: Wed, 25 Mar 2026 11:17:38 +0100 Subject: [PATCH 4/5] Update learning rules: docs go in the same PR, not after Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/rules/workflow.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.claude/rules/workflow.md b/.claude/rules/workflow.md index 9e36240..ccb6c32 100644 --- a/.claude/rules/workflow.md +++ b/.claude/rules/workflow.md @@ -99,15 +99,15 @@ If any step fails, fix it before pushing. Do not push broken code. ## Continuous Learning — MANDATORY -After every PR, review what happened and update the rules: +Every PR must include updates to rules and docs alongside the code changes. Don't submit code-only PRs when something was learned — update the rules in the SAME PR: -- **New anti-pattern discovered?** Add it to `anti-patterns.md` with the "why" so future sessions avoid it. -- **New development pattern established?** Add it to `development.md` so future sessions follow it consistently. -- **API changed upstream?** Update `CLAUDE.md`, template `CLAUDE.md`, and `building.md` with the new API. -- **Bun/TypeScript quirk found?** Document it in `development.md` under "Bun Quirks" so it's not rediscovered. -- **Workaround added?** Document WHY in a code comment AND add to anti-patterns so it gets removed when the upstream fix lands. +- **New anti-pattern discovered?** Add it to `anti-patterns.md` in the same commit. +- **New development pattern established?** Add it to `development.md` in the same PR. +- **API changed upstream?** Update `CLAUDE.md`, template `CLAUDE.md`, and `building.md` as part of the dep bump PR. +- **Bun/TypeScript quirk found?** Document it in `development.md` under "Bun Quirks" immediately. +- **Workaround added?** Document WHY in a code comment AND add to anti-patterns in the same commit. -The rules files are your institutional memory. If you learn something in this session that would help a future session, write it down NOW — not later. Every PR is an opportunity to make the next PR better. +The rules files are your institutional memory. Update them as you work, not as a separate follow-up. A PR that changes behavior without updating docs is incomplete. ## Context Management From 716ac073fb4ba38905e23b4e8e5a27941e44aa0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Bokisch?= Date: Wed, 25 Mar 2026 11:21:17 +0100 Subject: [PATCH 5/5] Expand completeness checklist: MCP, READMEs, rules, template, versions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every PR must be self-contained — code + all docs in one. Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/rules/workflow.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/.claude/rules/workflow.md b/.claude/rules/workflow.md index ccb6c32..561989e 100644 --- a/.claude/rules/workflow.md +++ b/.claude/rules/workflow.md @@ -75,14 +75,19 @@ If any step fails, fix it before pushing. Do not push broken code. ## Before Considering Work Complete +Every PR must be self-contained — code + docs + rules all in one: + 1. All validation checklist steps pass 2. Exports updated: new APIs in `src/index.ts` with type exports -3. CLAUDE.md updated if API surface changed -4. READMEs updated if user-facing features changed -5. Template updated if new patterns introduced -6. Anti-patterns rules updated if new gotchas discovered -7. No breaking changes without discussion -8. Honest quality assessment +3. **CLAUDE.md** updated if API surface or ecosystem changed +4. **READMEs** updated (root, package, meta) if user-facing features changed +5. **Template** updated (package.json, CLAUDE.md, source) if new patterns introduced +6. **Anti-patterns/development rules** updated if new gotchas or patterns discovered +7. **Building rules** updated if new "how to use" patterns for AI agents +8. **.mcp.json** verified still correct +9. **create-zero `pyreonVersion()`** updated if versions changed +10. No breaking changes without discussion +11. Honest quality assessment ## Debugging