25d895d 🐛 fix(gitea_workflow): clean up temp repos after job steps 2bc3b11 🐛 fix(gitea_workflow): clean up temporary repo dirs in workflows 98c3f30 📝 docs(agent_rules): allow plan execution on current branch 16c7230 📝 docs(prompts): define custom verify layering 8efc4dd 🐛 fix(skills): quote commit-message description bc8498f 🐛 fix(ci): install tomli for gitea tests 55cda3b 🐛 fix(tests): report missing toml parser clearly c0729c7 🐛 fix(playbook): import Optional for cli compatibility 63e24bf 📦 deps(skills): sync thirdparty skills d2f9356 🐛 fix(ci): isolate gitea workflow repos 588b81d 🐛 fix(ci): inline gitea workflow bootstrap e0b1c3a ♻️ refactor(skills): standardize first-party skill contracts 2c5050d ♻️ refactor(skills): rename repo skills source dir f049dfb 📦 deps(skills): drop duplicate first-party superpowers skills 234b335 ✨ feat(workflow): add superpowers planning and execution state tracking c1702a6 📝 docs(markdown): format tracked markdown and drop stale templates 2325409 📝 docs(markdown): clarify optional markdownlint usage 214c44e 🔧 chore(markdown): add markdownlint baseline and lint fixes a22b324 📝 docs(templates): add execution and memory-bank prompt templates 223a797 📝 docs(templates): update README for Claude Code and current features 4ac8672 📝 docs: simplify README + platform-agnostic tools + auto-create local rules 2431c9d 📝 docs: add claude_md config and use cross-platform paths d64b248 📝 docs: fix README.md inaccuracies and add Claude Code info c8d6bf2 🐛 fix(playbook): use relative paths in CLAUDE.md when not at project root 6518f0f ✨ feat(playbook): auto-create CLAUDE.md with path discovery 6ec9a45 ✨ feat(skills): add skill_link symlink support + platform-agnostic prompt 9f8b6b5 📝 docs: update README and config example for Claude Code support 79cff6c 📝 docs(skills): add Claude Code platform support 452c6f5 ✨ feat(playbook): auto-inject AGENTS.md into CLAUDE.md e1dbf3c 🐛 fix(skills): remove dual-path from commit-message skill f3a7259 🔧 chore(ci): use prepare_repo.sh in both workflows da08212 🔧 chore(ci): extract prepare_repo.sh and clean up workflows 7ade85e 🗑️ remove(tsl): drop syntax_book/, data/ source and build script f94dba0 ♻️ refactor(skills): update playbook.py and tests for thirdparty/ layout b3df412 ♻️ refactor(skills): separate thirdparty skills into thirdparty/ subdirectory 64950e7 📦 deps(skills): sync thirdparty skills a2e3cb0 ✨ feat(playbook): add no_backup deploy controls 8609d59 🐛 fix(docs): repair reference catalog source links 956da11 🐛 fix(playbook): publish hidden ci test fixes 3f67754 📦 deps(skills): sync thirdparty skills 08ca87b 📦 deps(skills): add karpathy thirdparty sync 96b705b 📝 docs(tsl): rebuild canonical syntax and routing manual 3ed5052 📦 deps(skills): sync thirdparty skills 60108dd 📦 deps(skills): sync thirdparty skills da85d4e 🐛 fix(thirdparty): prune nested project snapshots a2a697e 📦 deps(skills): sync thirdparty skills 9df610a 🐛 fix(thirdparty): exclude duplicated superpowers skills 33dd5bb 🐛 fix(thirdparty): preserve optional manifest fields 91b0ea7 🐛 fix(thirdparty): preserve manifest during snapshot update 2e26f98 🔧 chore(thirdparty): generalize skills sync pipeline 5b9c1e3 📦 deps(skills): sync superpowers 2f2d34a 📝 docs(readme): normalize subtree command spacing 62db7db 🐛 fix(ci): serialize superpowers update and sync 3463223 🐛 fix(ci): use literal superpowers sync paths 48f6de8 📦 deps(skills): sync superpowers 4b23529 🔧 chore(ci): merge superpowers update and sync workflow a56d75b 📦 deps(skills): sync superpowers 84bcefa 🔧 chore(ci): use ci[bot] commit author name 00a07e5 📦 deps(skills): sync superpowers 7b84daf 🐛 fix(templates): enforce main loop progress tracking 51373d7 🔧 chore(ci): automate superpowers sync workflow eaaa39c 🐛 fix(ci): prevent stale superpowers sync from restoring skills block 79755c6 📦 deps(skills): sync superpowers 836d878 📦 deps(skills): sync superpowers 8216c9f 📦 deps(skills): sync superpowers 9439505 🐛 fix(playbook): address reported repo issues git-subtree-dir: docs/standards/playbook git-subtree-split: 25d895d8b3f56624ccfe99ad7289e9eb49e0f316
11 KiB
11 KiB
| 1 | No | Category | Guideline | Description | Do | Don't | Code Good | Code Bad | Severity | Docs URL |
|---|---|---|---|---|---|---|---|---|---|---|
| 2 | 1 | Reactivity | Use $: for reactive statements | Automatic dependency tracking | $: for derived values | Manual recalculation | $: doubled = count * 2 | let doubled; count && (doubled = count * 2) | Medium | https://svelte.dev/docs/svelte-components#script-3-$-marks-a-statement-as-reactive |
| 3 | 2 | Reactivity | Trigger reactivity with assignment | Svelte tracks assignments not mutations | Reassign arrays/objects to trigger update | Mutate without reassignment | items = [...items, newItem] | items.push(newItem) | High | https://svelte.dev/docs/svelte-components#script-2-assignments-are-reactive |
| 4 | 3 | Reactivity | Use $state in Svelte 5 | Runes for explicit reactivity | let count = $state(0) | Implicit reactivity in Svelte 5 | let count = $state(0) | let count = 0 (Svelte 5) | Medium | https://svelte.dev/blog/runes |
| 5 | 4 | Reactivity | Use $derived for computed values | $derived replaces $: in Svelte 5 | let doubled = $derived(count * 2) | $: in Svelte 5 | let doubled = $derived(count * 2) | $: doubled = count * 2 (Svelte 5) | Medium | |
| 6 | 5 | Reactivity | Use $effect for side effects | $effect replaces $: side effects | Use $effect for subscriptions | $: for side effects in Svelte 5 | $effect(() => console.log(count)) | $: console.log(count) (Svelte 5) | Medium | |
| 7 | 6 | Props | Export let for props | Declare props with export let | export let propName | Props without export | export let count = 0 | let count = 0 | High | https://svelte.dev/docs/svelte-components#script-1-export-creates-a-component-prop |
| 8 | 7 | Props | Use $props in Svelte 5 | $props rune for prop access | let { name } = $props() | export let in Svelte 5 | let { name, age = 0 } = $props() | export let name; export let age = 0 | Medium | |
| 9 | 8 | Props | Provide default values | Default props with assignment | export let count = 0 | Required props without defaults | export let count = 0 | export let count | Low | |
| 10 | 9 | Props | Use spread props | Pass through unknown props | {...$$restProps} on elements | Manual prop forwarding | <button {...$$restProps}> | <button class={$$props.class}> | Low | https://svelte.dev/docs/basic-markup#attributes-and-props |
| 11 | 10 | Bindings | Use bind: for two-way binding | Simplified input handling | bind:value for inputs | on:input with manual update | <input bind:value={name}> | <input value={name} on:input={e => name = e.target.value}> | Low | https://svelte.dev/docs/element-directives#bind-property |
| 12 | 11 | Bindings | Bind to DOM elements | Reference DOM nodes | bind:this for element reference | querySelector in onMount | <div bind:this={el}> | onMount(() => el = document.querySelector()) | Medium | |
| 13 | 12 | Bindings | Use bind:group for radios/checkboxes | Simplified group handling | bind:group for radio/checkbox groups | Manual checked handling | <input type="radio" bind:group={selected}> | <input type="radio" checked={selected === value}> | Low | |
| 14 | 13 | Events | Use on: for event handlers | Event directive syntax | on:click={handler} | addEventListener in onMount | <button on:click={handleClick}> | onMount(() => btn.addEventListener()) | Medium | https://svelte.dev/docs/element-directives#on-eventname |
| 15 | 14 | Events | Forward events with on:event | Pass events to parent | on:click without handler | createEventDispatcher for DOM events | <button on:click> | dispatch('click', event) | Low | |
| 16 | 15 | Events | Use createEventDispatcher | Custom component events | dispatch for custom events | on:event for custom events | dispatch('save', { data }) | on:save without dispatch | Medium | https://svelte.dev/docs/svelte#createeventdispatcher |
| 17 | 16 | Lifecycle | Use onMount for initialization | Run code after component mounts | onMount for setup and data fetching | Code in script body for side effects | onMount(() => fetchData()) | fetchData() in script body | High | https://svelte.dev/docs/svelte#onmount |
| 18 | 17 | Lifecycle | Return cleanup from onMount | Automatic cleanup on destroy | Return function from onMount | Separate onDestroy for paired cleanup | onMount(() => { sub(); return unsub }) | onMount(sub); onDestroy(unsub) | Medium | |
| 19 | 18 | Lifecycle | Use onDestroy sparingly | Only when onMount cleanup not possible | onDestroy for non-mount cleanup | onDestroy for mount-related cleanup | onDestroy for store unsubscribe | onDestroy(() => clearInterval(id)) | Low | |
| 20 | 19 | Lifecycle | Avoid beforeUpdate/afterUpdate | Usually not needed | Reactive statements instead | beforeUpdate for derived state | $: if (x) doSomething() | beforeUpdate(() => doSomething()) | Low | |
| 21 | 20 | Stores | Use writable for mutable state | Basic reactive store | writable for shared mutable state | Local variables for shared state | const count = writable(0) | let count = 0 in module | Medium | https://svelte.dev/docs/svelte-store#writable |
| 22 | 21 | Stores | Use readable for read-only state | External data sources | readable for derived/external data | writable for read-only data | readable(0, set => interval(set)) | writable(0) for timer | Low | https://svelte.dev/docs/svelte-store#readable |
| 23 | 22 | Stores | Use derived for computed stores | Combine or transform stores | derived for computed values | Manual subscription for derived | derived(count, $c => $c * 2) | count.subscribe(c => doubled = c * 2) | Medium | https://svelte.dev/docs/svelte-store#derived |
| 24 | 23 | Stores | Use $ prefix for auto-subscription | Automatic subscribe/unsubscribe | $storeName in components | Manual subscription | {$count} | count.subscribe(c => value = c) | High | |
| 25 | 24 | Stores | Clean up custom subscriptions | Unsubscribe when component destroys | Return unsubscribe from onMount | Leave subscriptions open | onMount(() => store.subscribe(fn)) | store.subscribe(fn) in script | High | |
| 26 | 25 | Slots | Use slots for composition | Content projection | <slot> for flexible content | Props for all content | <slot>Default</slot> | <Component content="text"/> | Medium | https://svelte.dev/docs/special-elements#slot |
| 27 | 26 | Slots | Name slots for multiple areas | Multiple content areas | <slot name="header"> | Single slot for complex layouts | <slot name="header"><slot name="footer"> | <slot> with complex conditionals | Low | |
| 28 | 27 | Slots | Check slot content with $$slots | Conditional slot rendering | $$slots.name for conditional rendering | Always render slot wrapper | {#if $$slots.footer}<slot name="footer"/>{/if} | <div><slot name="footer"/></div> | Low | |
| 29 | 28 | Styling | Use scoped styles by default | Styles scoped to component | <style> for component styles | Global styles for component | :global() only when needed | <style> all global | Medium | https://svelte.dev/docs/svelte-components#style |
| 30 | 29 | Styling | Use :global() sparingly | Escape scoping when needed | :global for third-party styling | Global for all styles | :global(.external-lib) | <style> without scoping | Medium | |
| 31 | 30 | Styling | Use CSS variables for theming | Dynamic styling | CSS custom properties | Inline styles for themes | style="--color: {color}" | style="color: {color}" | Low | |
| 32 | 31 | Transitions | Use built-in transitions | Svelte transition directives | transition:fade for simple effects | Manual CSS transitions | <div transition:fade> | <div class:fade={visible}> | Low | https://svelte.dev/docs/element-directives#transition-fn |
| 33 | 32 | Transitions | Use in: and out: separately | Different enter/exit animations | in:fly out:fade for asymmetric | Same transition for both | <div in:fly out:fade> | <div transition:fly> | Low | |
| 34 | 33 | Transitions | Add local modifier | Prevent ancestor trigger | transition:fade|local | Global transitions for lists | <div transition:slide|local> | <div transition:slide> | Medium | |
| 35 | 34 | Actions | Use actions for DOM behavior | Reusable DOM logic | use:action for DOM enhancements | onMount for each usage | <div use:clickOutside> | onMount(() => setupClickOutside(el)) | Medium | https://svelte.dev/docs/element-directives#use-action |
| 36 | 35 | Actions | Return update and destroy | Lifecycle methods for actions | Return { update, destroy } | Only initial setup | return { update(params) {}, destroy() {} } | return destroy only | Medium | |
| 37 | 36 | Actions | Pass parameters to actions | Configure action behavior | use:action={params} | Hardcoded action behavior | <div use:tooltip={options}> | <div use:tooltip> | Low | |
| 38 | 37 | Logic | Use {#if} for conditionals | Template conditionals | {#if} {:else if} {:else} | Ternary in expressions | {#if cond}...{:else}...{/if} | {cond ? a : b} for complex | Low | https://svelte.dev/docs/logic-blocks#if |
| 39 | 38 | Logic | Use {#each} for lists | List rendering | {#each} with key | Map in expression | {#each items as item (item.id)} | {items.map(i => `<div>${i}</div>`)} | Medium | |
| 40 | 39 | Logic | Always use keys in {#each} | Proper list reconciliation | (item.id) for unique key | Index as key or no key | {#each items as item (item.id)} | {#each items as item, i (i)} | High | |
| 41 | 40 | Logic | Use {#await} for promises | Handle async states | {#await} for loading/error states | Manual promise handling | {#await promise}...{:then}...{:catch} | {#if loading}...{#if error} | Medium | https://svelte.dev/docs/logic-blocks#await |
| 42 | 41 | SvelteKit | Use +page.svelte for routes | File-based routing | +page.svelte for route components | Custom routing setup | routes/about/+page.svelte | routes/About.svelte | Medium | https://kit.svelte.dev/docs/routing |
| 43 | 42 | SvelteKit | Use +page.js for data loading | Load data before render | load function in +page.js | onMount for data fetching | export function load() {} | onMount(() => fetchData()) | High | https://kit.svelte.dev/docs/load |
| 44 | 43 | SvelteKit | Use +page.server.js for server-only | Server-side data loading | +page.server.js for sensitive data | +page.js for API keys | +page.server.js with DB access | +page.js with DB access | High | |
| 45 | 44 | SvelteKit | Use form actions | Server-side form handling | +page.server.js actions | API routes for forms | export const actions = { default } | fetch('/api/submit') | Medium | https://kit.svelte.dev/docs/form-actions |
| 46 | 45 | SvelteKit | Use $app/stores for app state | $page $navigating $updated | $page for current page data | Manual URL parsing | import { page } from '$app/stores' | window.location.pathname | Medium | https://kit.svelte.dev/docs/modules#$app-stores |
| 47 | 46 | Performance | Use {#key} for forced re-render | Reset component state | {#key id} for fresh instance | Manual destroy/create | {#key item.id}<Component/>{/key} | on:change={() => component = null} | Low | https://svelte.dev/docs/logic-blocks#key |
| 48 | 47 | Performance | Avoid unnecessary reactivity | Not everything needs $: | $: only for side effects | $: for simple assignments | $: if (x) console.log(x) | $: y = x (when y = x works) | Low | |
| 49 | 48 | Performance | Use immutable compiler option | Skip equality checks | immutable: true for large lists | Default for all components | <svelte:options immutable/> | Default without immutable | Low | |
| 50 | 49 | TypeScript | Use lang="ts" in script | TypeScript support | <script lang="ts"> | JavaScript for typed projects | <script lang="ts"> | <script> with JSDoc | Medium | https://svelte.dev/docs/typescript |
| 51 | 50 | TypeScript | Type props with interface | Explicit prop types | interface $$Props for types | Untyped props | interface $$Props { name: string } | export let name | Medium | |
| 52 | 51 | TypeScript | Type events with createEventDispatcher | Type-safe events | createEventDispatcher<Events>() | Untyped dispatch | createEventDispatcher<{ save: Data }>() | createEventDispatcher() | Medium | |
| 53 | 52 | Accessibility | Use semantic elements | Proper HTML in templates | button nav main appropriately | div for everything | <button on:click> | <div on:click> | High | |
| 54 | 53 | Accessibility | Add aria to dynamic content | Accessible state changes | aria-live for updates | Silent dynamic updates | <div aria-live="polite">{message}</div> | <div>{message}</div> | Medium |