timsquad 2.1.0 → 3.4.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.
- package/README.ko.md +288 -0
- package/README.md +170 -763
- package/dist/commands/compile.d.ts +3 -0
- package/dist/commands/compile.d.ts.map +1 -0
- package/dist/commands/compile.js +170 -0
- package/dist/commands/compile.js.map +1 -0
- package/dist/commands/daemon.d.ts +7 -0
- package/dist/commands/daemon.d.ts.map +1 -0
- package/dist/commands/daemon.js +229 -0
- package/dist/commands/daemon.js.map +1 -0
- package/dist/commands/feedback.d.ts +9 -0
- package/dist/commands/feedback.d.ts.map +1 -1
- package/dist/commands/feedback.js +235 -14
- package/dist/commands/feedback.js.map +1 -1
- package/dist/commands/full.js +2 -2
- package/dist/commands/full.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +118 -22
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/knowledge.d.ts +3 -0
- package/dist/commands/knowledge.d.ts.map +1 -0
- package/dist/commands/knowledge.js +316 -0
- package/dist/commands/knowledge.js.map +1 -0
- package/dist/commands/log.d.ts +27 -0
- package/dist/commands/log.d.ts.map +1 -1
- package/dist/commands/log.js +965 -0
- package/dist/commands/log.js.map +1 -1
- package/dist/commands/meta-index.d.ts +3 -0
- package/dist/commands/meta-index.d.ts.map +1 -0
- package/dist/commands/meta-index.js +401 -0
- package/dist/commands/meta-index.js.map +1 -0
- package/dist/commands/metrics.d.ts.map +1 -1
- package/dist/commands/metrics.js +239 -4
- package/dist/commands/metrics.js.map +1 -1
- package/dist/commands/retro.js +154 -6
- package/dist/commands/retro.js.map +1 -1
- package/dist/commands/skills.d.ts +12 -0
- package/dist/commands/skills.d.ts.map +1 -0
- package/dist/commands/skills.js +231 -0
- package/dist/commands/skills.js.map +1 -0
- package/dist/commands/upgrade.d.ts +8 -0
- package/dist/commands/upgrade.d.ts.map +1 -0
- package/dist/commands/upgrade.js +292 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/commands/workflow.d.ts +3 -0
- package/dist/commands/workflow.d.ts.map +1 -0
- package/dist/commands/workflow.js +607 -0
- package/dist/commands/workflow.js.map +1 -0
- package/dist/daemon/context-writer.d.ts +16 -0
- package/dist/daemon/context-writer.d.ts.map +1 -0
- package/dist/daemon/context-writer.js +35 -0
- package/dist/daemon/context-writer.js.map +1 -0
- package/dist/daemon/entry.d.ts +7 -0
- package/dist/daemon/entry.d.ts.map +1 -0
- package/dist/daemon/entry.js +17 -0
- package/dist/daemon/entry.js.map +1 -0
- package/dist/daemon/event-queue.d.ts +52 -0
- package/dist/daemon/event-queue.d.ts.map +1 -0
- package/dist/daemon/event-queue.js +255 -0
- package/dist/daemon/event-queue.js.map +1 -0
- package/dist/daemon/file-watcher.d.ts +19 -0
- package/dist/daemon/file-watcher.d.ts.map +1 -0
- package/dist/daemon/file-watcher.js +87 -0
- package/dist/daemon/file-watcher.js.map +1 -0
- package/dist/daemon/index.d.ts +29 -0
- package/dist/daemon/index.d.ts.map +1 -0
- package/dist/daemon/index.js +296 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/daemon/jsonl-watcher.d.ts +49 -0
- package/dist/daemon/jsonl-watcher.d.ts.map +1 -0
- package/dist/daemon/jsonl-watcher.js +258 -0
- package/dist/daemon/jsonl-watcher.js.map +1 -0
- package/dist/daemon/meta-cache.d.ts +63 -0
- package/dist/daemon/meta-cache.d.ts.map +1 -0
- package/dist/daemon/meta-cache.js +249 -0
- package/dist/daemon/meta-cache.js.map +1 -0
- package/dist/daemon/session-state.d.ts +19 -0
- package/dist/daemon/session-state.d.ts.map +1 -0
- package/dist/daemon/session-state.js +132 -0
- package/dist/daemon/session-state.js.map +1 -0
- package/dist/daemon/shutdown.d.ts +21 -0
- package/dist/daemon/shutdown.d.ts.map +1 -0
- package/dist/daemon/shutdown.js +164 -0
- package/dist/daemon/shutdown.js.map +1 -0
- package/dist/index.js +24 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-composer.d.ts +38 -0
- package/dist/lib/agent-composer.d.ts.map +1 -0
- package/dist/lib/agent-composer.js +128 -0
- package/dist/lib/agent-composer.js.map +1 -0
- package/dist/lib/agent-generator.d.ts +22 -0
- package/dist/lib/agent-generator.d.ts.map +1 -0
- package/dist/lib/agent-generator.js +150 -0
- package/dist/lib/agent-generator.js.map +1 -0
- package/dist/lib/ast-parser.d.ts +11 -0
- package/dist/lib/ast-parser.d.ts.map +1 -0
- package/dist/lib/ast-parser.js +282 -0
- package/dist/lib/ast-parser.js.map +1 -0
- package/dist/lib/compile-rules.d.ts +66 -0
- package/dist/lib/compile-rules.d.ts.map +1 -0
- package/dist/lib/compile-rules.js +114 -0
- package/dist/lib/compile-rules.js.map +1 -0
- package/dist/lib/compiler.d.ts +105 -0
- package/dist/lib/compiler.d.ts.map +1 -0
- package/dist/lib/compiler.js +368 -0
- package/dist/lib/compiler.js.map +1 -0
- package/dist/lib/config.d.ts +7 -2
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +34 -3
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/meta-index.d.ts +19 -0
- package/dist/lib/meta-index.d.ts.map +1 -0
- package/dist/lib/meta-index.js +573 -0
- package/dist/lib/meta-index.js.map +1 -0
- package/dist/lib/project.js +1 -1
- package/dist/lib/project.js.map +1 -1
- package/dist/lib/skill-generator.d.ts +32 -0
- package/dist/lib/skill-generator.d.ts.map +1 -0
- package/dist/lib/skill-generator.js +187 -0
- package/dist/lib/skill-generator.js.map +1 -0
- package/dist/lib/template.d.ts +16 -2
- package/dist/lib/template.d.ts.map +1 -1
- package/dist/lib/template.js +115 -20
- package/dist/lib/template.js.map +1 -1
- package/dist/lib/ui-index.d.ts +12 -0
- package/dist/lib/ui-index.d.ts.map +1 -0
- package/dist/lib/ui-index.js +239 -0
- package/dist/lib/ui-index.js.map +1 -0
- package/dist/lib/ui-parser.d.ts +12 -0
- package/dist/lib/ui-parser.d.ts.map +1 -0
- package/dist/lib/ui-parser.js +472 -0
- package/dist/lib/ui-parser.js.map +1 -0
- package/dist/lib/update-check.d.ts +6 -0
- package/dist/lib/update-check.d.ts.map +1 -0
- package/dist/lib/update-check.js +121 -0
- package/dist/lib/update-check.js.map +1 -0
- package/dist/lib/upgrade-backup.d.ts +33 -0
- package/dist/lib/upgrade-backup.d.ts.map +1 -0
- package/dist/lib/upgrade-backup.js +101 -0
- package/dist/lib/upgrade-backup.js.map +1 -0
- package/dist/lib/version.d.ts +19 -0
- package/dist/lib/version.d.ts.map +1 -0
- package/dist/lib/version.js +35 -0
- package/dist/lib/version.js.map +1 -0
- package/dist/lib/workflow-state.d.ts +48 -0
- package/dist/lib/workflow-state.d.ts.map +1 -0
- package/dist/lib/workflow-state.js +67 -0
- package/dist/lib/workflow-state.js.map +1 -0
- package/dist/types/config.d.ts +103 -2
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +184 -9
- package/dist/types/config.js.map +1 -1
- package/dist/types/feedback.d.ts +7 -0
- package/dist/types/feedback.d.ts.map +1 -1
- package/dist/types/feedback.js +1 -1
- package/dist/types/feedback.js.map +1 -1
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/meta-index.d.ts +146 -0
- package/dist/types/meta-index.d.ts.map +1 -0
- package/dist/types/meta-index.js +7 -0
- package/dist/types/meta-index.js.map +1 -0
- package/dist/types/project.d.ts +19 -3
- package/dist/types/project.d.ts.map +1 -1
- package/dist/types/project.js +23 -0
- package/dist/types/project.js.map +1 -1
- package/dist/types/task-log.d.ts +208 -0
- package/dist/types/task-log.d.ts.map +1 -0
- package/dist/types/task-log.js +6 -0
- package/dist/types/task-log.js.map +1 -0
- package/dist/types/ui-meta.d.ts +118 -0
- package/dist/types/ui-meta.d.ts.map +1 -0
- package/dist/types/ui-meta.js +7 -0
- package/dist/types/ui-meta.js.map +1 -0
- package/package.json +12 -4
- package/templates/base/agents/base/tsq-architect.md +68 -0
- package/templates/base/agents/base/tsq-dba.md +56 -0
- package/templates/base/agents/base/tsq-designer.md +72 -0
- package/templates/base/agents/base/tsq-developer.md +67 -0
- package/templates/base/agents/base/tsq-qa.md +55 -0
- package/templates/base/agents/base/tsq-security.md +65 -0
- package/templates/base/agents/overlays/domain/general-web/_common.md +11 -0
- package/templates/base/agents/overlays/domain/mobile/_common.md +13 -0
- package/templates/base/agents/overlays/platform/claude-code.md +12 -0
- package/templates/base/config.template.yaml +213 -0
- package/templates/base/knowledge/checklists/accessibility.md +37 -0
- package/templates/base/knowledge/checklists/architecture-review.md +28 -0
- package/templates/base/knowledge/checklists/database-standards.md +84 -0
- package/templates/base/knowledge/checklists/design-reference.md +97 -0
- package/templates/base/knowledge/checklists/security.md +50 -0
- package/templates/base/knowledge/checklists/ssot-validation.md +19 -0
- package/templates/base/knowledge/domains/_template.md +16 -0
- package/templates/base/knowledge/platforms/_template.md +16 -0
- package/templates/base/knowledge/templates/sequence-report.md +44 -0
- package/templates/base/knowledge/templates/task-result.md +105 -0
- package/templates/base/skills/_template/SKILL.md +59 -0
- package/templates/base/skills/_template/references/_template.md +35 -0
- package/templates/base/skills/_template/rules/_sections.md +34 -0
- package/templates/base/skills/_template/rules/_template.md +32 -0
- package/templates/base/skills/_template/scripts/_template.sh +31 -0
- package/templates/base/skills/architecture/SKILL.md +54 -0
- package/templates/base/skills/architecture/references/adr-template.md +50 -0
- package/templates/base/skills/architecture/references/api-design.md +64 -0
- package/templates/base/skills/backend/node/SKILL.md +81 -0
- package/templates/base/skills/backend/node/rules/async-patterns.md +81 -0
- package/templates/base/skills/backend/node/rules/deployment.md +33 -0
- package/templates/base/skills/backend/node/rules/env-config.md +41 -0
- package/templates/base/skills/backend/node/rules/error-handling.md +83 -0
- package/templates/base/skills/backend/node/rules/hono-app-setup.md +98 -0
- package/templates/base/skills/backend/node/rules/jwt-auth.md +76 -0
- package/templates/base/skills/backend/node/rules/middleware.md +56 -0
- package/templates/base/skills/backend/node/rules/testing.md +82 -0
- package/templates/base/skills/coding/SKILL.md +47 -0
- package/templates/base/skills/coding/rules/patterns.md +81 -0
- package/templates/base/skills/controller/SKILL.md +111 -0
- package/templates/base/skills/controller/references/README.md +35 -0
- package/templates/base/skills/controller/rules/README.md +18 -0
- package/templates/base/skills/database/SKILL.md +98 -0
- package/templates/base/skills/database/prisma/SKILL.md +57 -0
- package/templates/base/skills/database/prisma/rules/queries.md +133 -0
- package/templates/base/skills/database/prisma/rules/schema-design.md +80 -0
- package/templates/base/skills/frontend/nextjs/SKILL.md +59 -0
- package/templates/base/skills/frontend/nextjs/rules/app-router.md +138 -0
- package/templates/base/skills/frontend/react/SKILL.md +86 -0
- package/templates/base/skills/frontend/react/rules/_sections.md +88 -0
- package/templates/base/skills/frontend/react/rules/anti-patterns.md +67 -0
- package/templates/base/skills/frontend/react/rules/async-api-routes.md +38 -0
- package/templates/base/skills/frontend/react/rules/async-defer-await.md +80 -0
- package/templates/base/skills/frontend/react/rules/async-dependencies.md +36 -0
- package/templates/base/skills/frontend/react/rules/async-parallel.md +28 -0
- package/templates/base/skills/frontend/react/rules/async-suspense-boundaries.md +99 -0
- package/templates/base/skills/frontend/react/rules/bundle-barrel-imports.md +59 -0
- package/templates/base/skills/frontend/react/rules/bundle-defer-third-party.md +49 -0
- package/templates/base/skills/frontend/react/rules/bundle-dynamic-imports.md +35 -0
- package/templates/base/skills/frontend/react/rules/component-conventions.md +74 -0
- package/templates/base/skills/frontend/react/rules/js-combine-iterations.md +32 -0
- package/templates/base/skills/frontend/react/rules/js-early-exit.md +50 -0
- package/templates/base/skills/frontend/react/rules/js-index-maps.md +37 -0
- package/templates/base/skills/frontend/react/rules/js-set-map-lookups.md +24 -0
- package/templates/base/skills/frontend/react/rules/rendering-conditional-render.md +40 -0
- package/templates/base/skills/frontend/react/rules/rendering-content-visibility.md +38 -0
- package/templates/base/skills/frontend/react/rules/rendering-hoist-jsx.md +46 -0
- package/templates/base/skills/frontend/react/rules/rerender-defer-reads.md +39 -0
- package/templates/base/skills/frontend/react/rules/rerender-derived-state.md +29 -0
- package/templates/base/skills/frontend/react/rules/rerender-memo.md +44 -0
- package/templates/base/skills/frontend/react/rules/rerender-transitions.md +40 -0
- package/templates/base/skills/frontend/react/rules/server-after-nonblocking.md +73 -0
- package/templates/base/skills/frontend/react/rules/server-cache-react.md +26 -0
- package/templates/base/skills/frontend/react/rules/server-parallel-fetching.md +79 -0
- package/templates/base/skills/frontend/react/rules/state-location.md +55 -0
- package/templates/base/skills/methodology/bdd/SKILL.md +69 -0
- package/templates/base/skills/methodology/bdd/rules/gherkin-patterns.md +113 -0
- package/templates/base/skills/methodology/ddd/SKILL.md +74 -0
- package/templates/base/skills/methodology/ddd/rules/strategic-patterns.md +98 -0
- package/templates/base/skills/methodology/debugging/SKILL.md +60 -0
- package/templates/base/skills/methodology/debugging/references/root-cause-tracing.md +84 -0
- package/templates/base/skills/methodology/tdd/SKILL.md +66 -0
- package/templates/base/skills/methodology/tdd/rules/real-world-example.md +88 -0
- package/templates/base/skills/methodology/tdd/rules/techniques.md +185 -0
- package/templates/base/skills/mobile/dart/SKILL.md +69 -0
- package/templates/base/skills/mobile/dart/rules/async-patterns.md +112 -0
- package/templates/base/skills/mobile/dart/rules/code-style.md +96 -0
- package/templates/base/skills/mobile/dart/rules/null-safety.md +84 -0
- package/templates/base/skills/mobile/dart/rules/type-system.md +111 -0
- package/templates/base/skills/mobile/flutter/SKILL.md +89 -0
- package/templates/base/skills/mobile/flutter/ci-cd/SKILL.md +82 -0
- package/templates/base/skills/mobile/flutter/ci-cd/references/ci-cd-pipeline.md +314 -0
- package/templates/base/skills/mobile/flutter/ci-cd/rules/code-signing.md +106 -0
- package/templates/base/skills/mobile/flutter/ci-cd/rules/codemagic-setup.md +116 -0
- package/templates/base/skills/mobile/flutter/ci-cd/rules/fastlane-setup.md +105 -0
- package/templates/base/skills/mobile/flutter/ci-cd/rules/github-actions.md +112 -0
- package/templates/base/skills/mobile/flutter/ci-cd/rules/store-deployment.md +106 -0
- package/templates/base/skills/mobile/flutter/ci-cd/rules/versioning.md +107 -0
- package/templates/base/skills/mobile/flutter/i18n/SKILL.md +78 -0
- package/templates/base/skills/mobile/flutter/i18n/references/i18n-architecture.md +225 -0
- package/templates/base/skills/mobile/flutter/i18n/rules/arb-files.md +182 -0
- package/templates/base/skills/mobile/flutter/i18n/rules/locale-switching.md +226 -0
- package/templates/base/skills/mobile/flutter/i18n/rules/localization-setup.md +137 -0
- package/templates/base/skills/mobile/flutter/i18n/rules/plural-gender.md +159 -0
- package/templates/base/skills/mobile/flutter/i18n/rules/text-direction.md +199 -0
- package/templates/base/skills/mobile/flutter/monitoring/SKILL.md +81 -0
- package/templates/base/skills/mobile/flutter/monitoring/references/monitoring-architecture.md +269 -0
- package/templates/base/skills/mobile/flutter/monitoring/rules/analytics.md +227 -0
- package/templates/base/skills/mobile/flutter/monitoring/rules/crashlytics-setup.md +195 -0
- package/templates/base/skills/mobile/flutter/monitoring/rules/logging.md +258 -0
- package/templates/base/skills/mobile/flutter/monitoring/rules/performance-monitoring.md +248 -0
- package/templates/base/skills/mobile/flutter/monitoring/rules/sentry-integration.md +249 -0
- package/templates/base/skills/mobile/flutter/networking/SKILL.md +88 -0
- package/templates/base/skills/mobile/flutter/networking/references/api-client-architecture.md +305 -0
- package/templates/base/skills/mobile/flutter/networking/rules/caching.md +212 -0
- package/templates/base/skills/mobile/flutter/networking/rules/connectivity.md +213 -0
- package/templates/base/skills/mobile/flutter/networking/rules/dio-setup.md +159 -0
- package/templates/base/skills/mobile/flutter/networking/rules/error-handling.md +209 -0
- package/templates/base/skills/mobile/flutter/networking/rules/interceptors.md +205 -0
- package/templates/base/skills/mobile/flutter/networking/rules/retrofit-patterns.md +194 -0
- package/templates/base/skills/mobile/flutter/push-notifications/SKILL.md +87 -0
- package/templates/base/skills/mobile/flutter/push-notifications/references/notification-architecture.md +340 -0
- package/templates/base/skills/mobile/flutter/push-notifications/references/platform-setup.md +286 -0
- package/templates/base/skills/mobile/flutter/push-notifications/rules/background-processing.md +308 -0
- package/templates/base/skills/mobile/flutter/push-notifications/rules/deep-linking.md +217 -0
- package/templates/base/skills/mobile/flutter/push-notifications/rules/fcm-setup.md +164 -0
- package/templates/base/skills/mobile/flutter/push-notifications/rules/local-notifications.md +262 -0
- package/templates/base/skills/mobile/flutter/push-notifications/rules/notification-handling.md +210 -0
- package/templates/base/skills/mobile/flutter/push-notifications/rules/notification-permissions.md +246 -0
- package/templates/base/skills/mobile/flutter/push-notifications/rules/rich-notifications.md +320 -0
- package/templates/base/skills/mobile/flutter/references/freezed-patterns.md +162 -0
- package/templates/base/skills/mobile/flutter/references/project-structure.md +170 -0
- package/templates/base/skills/mobile/flutter/rules/animations.md +112 -0
- package/templates/base/skills/mobile/flutter/rules/architecture.md +121 -0
- package/templates/base/skills/mobile/flutter/rules/navigation-routing.md +117 -0
- package/templates/base/skills/mobile/flutter/rules/performance.md +112 -0
- package/templates/base/skills/mobile/flutter/rules/platform-adaptive.md +126 -0
- package/templates/base/skills/mobile/flutter/rules/state-management.md +110 -0
- package/templates/base/skills/mobile/flutter/rules/testing.md +131 -0
- package/templates/base/skills/mobile/flutter/rules/widget-conventions.md +122 -0
- package/templates/base/skills/mobile/flutter/security/SKILL.md +86 -0
- package/templates/base/skills/mobile/flutter/security/references/mobile-security-checklist.md +168 -0
- package/templates/base/skills/mobile/flutter/security/rules/api-key-protection.md +206 -0
- package/templates/base/skills/mobile/flutter/security/rules/authentication.md +248 -0
- package/templates/base/skills/mobile/flutter/security/rules/data-protection.md +271 -0
- package/templates/base/skills/mobile/flutter/security/rules/obfuscation.md +213 -0
- package/templates/base/skills/mobile/flutter/security/rules/secure-storage.md +171 -0
- package/templates/base/skills/mobile/flutter/security/rules/ssl-pinning.md +197 -0
- package/templates/base/skills/planning/SKILL.md +58 -0
- package/templates/base/skills/planning/references/prd-guide.md +47 -0
- package/templates/base/skills/planning/references/requirements-guide.md +46 -0
- package/templates/base/skills/prompt-engineering/SKILL.md +103 -0
- package/templates/base/skills/retrospective/SKILL.md +102 -0
- package/templates/base/skills/security/SKILL.md +55 -0
- package/templates/base/skills/security/rules/owasp-examples.md +119 -0
- package/templates/base/skills/security/scripts/check-secrets.sh +55 -0
- package/templates/base/skills/testing/SKILL.md +63 -0
- package/templates/base/skills/testing/references/testing-patterns.md +103 -0
- package/templates/base/skills/tsq-protocol/SKILL.md +51 -0
- package/templates/base/skills/typescript/SKILL.md +67 -0
- package/templates/base/skills/typescript/rules/type-patterns.md +135 -0
- package/templates/base/skills/typescript/rules/utility-types.md +76 -0
- package/templates/base/skills/ui-design/SKILL.md +70 -0
- package/templates/{common → base}/timsquad/feedback/routing-rules.yaml +1 -1
- package/templates/{common → base}/timsquad/retrospective/metrics/metrics-schema.json +46 -1
- package/templates/platforms/claude-code/CLAUDE.md.template +89 -0
- package/templates/platforms/claude-code/rules/adr-rules.md +32 -0
- package/templates/platforms/claude-code/rules/feedback-routing.md +18 -0
- package/templates/platforms/claude-code/rules/phase-management.md +23 -0
- package/templates/platforms/claude-code/rules/reporting-format.md +26 -0
- package/templates/platforms/claude-code/rules/sequence-management.md +72 -0
- package/templates/platforms/claude-code/rules/workspace-sync.md +33 -0
- package/templates/platforms/claude-code/scripts/completion-guard.sh +57 -0
- package/templates/platforms/claude-code/scripts/phase-guard.sh +79 -0
- package/templates/platforms/claude-code/settings.json +98 -0
- package/templates/project-types/api-backend/config.yaml +227 -0
- package/templates/project-types/api-backend/process/workflow.xml +214 -0
- package/templates/project-types/fintech/config.yaml +151 -0
- package/templates/project-types/fintech/process/workflow.xml +316 -0
- package/templates/project-types/infra/config.yaml +327 -0
- package/templates/project-types/infra/process/workflow.xml +296 -0
- package/templates/project-types/mobile-app/config.yaml +123 -0
- package/templates/project-types/mobile-app/process/workflow.xml +191 -0
- package/templates/project-types/platform/config.yaml +254 -0
- package/templates/project-types/platform/process/workflow.xml +254 -0
- package/templates/project-types/web-app/config.yaml +198 -0
- package/templates/project-types/web-app/process/workflow.xml +210 -0
- package/templates/project-types/web-service/config.yaml +136 -0
- package/templates/project-types/web-service/process/workflow.xml +184 -0
- package/templates/common/CLAUDE.md.template +0 -254
- package/templates/common/claude/agents/tsq-dba.md +0 -311
- package/templates/common/claude/agents/tsq-designer.md +0 -323
- package/templates/common/claude/agents/tsq-developer.md +0 -177
- package/templates/common/claude/agents/tsq-planner.md +0 -190
- package/templates/common/claude/agents/tsq-prompter.md +0 -356
- package/templates/common/claude/agents/tsq-qa.md +0 -168
- package/templates/common/claude/agents/tsq-retro.md +0 -193
- package/templates/common/claude/agents/tsq-security.md +0 -221
- package/templates/common/claude/hooks/auto-metrics.sh +0 -165
- package/templates/common/claude/hooks/auto-worklog.sh +0 -245
- package/templates/common/claude/hooks/event-logger.sh +0 -208
- package/templates/common/claude/settings.json +0 -86
- package/templates/common/claude/skills/architecture/SKILL.md +0 -123
- package/templates/common/claude/skills/backend/node/SKILL.md +0 -1015
- package/templates/common/claude/skills/coding/SKILL.md +0 -171
- package/templates/common/claude/skills/database/prisma/SKILL.md +0 -357
- package/templates/common/claude/skills/frontend/nextjs/SKILL.md +0 -279
- package/templates/common/claude/skills/frontend/react/SKILL.md +0 -1729
- package/templates/common/claude/skills/methodology/bdd/SKILL.md +0 -234
- package/templates/common/claude/skills/methodology/ddd/SKILL.md +0 -311
- package/templates/common/claude/skills/methodology/tdd/SKILL.md +0 -512
- package/templates/common/claude/skills/planning/SKILL.md +0 -90
- package/templates/common/claude/skills/security/SKILL.md +0 -234
- package/templates/common/claude/skills/testing/SKILL.md +0 -146
- package/templates/common/claude/skills/typescript/SKILL.md +0 -435
- package/templates/common/config.template.yaml +0 -132
- /package/templates/{common → base}/timsquad/architectures/clean/ARCHITECTURE.md +0 -0
- /package/templates/{common → base}/timsquad/architectures/clean/backend.xml +0 -0
- /package/templates/{common → base}/timsquad/architectures/clean/frontend.xml +0 -0
- /package/templates/{common → base}/timsquad/architectures/fsd/ARCHITECTURE.md +0 -0
- /package/templates/{common → base}/timsquad/architectures/fsd/frontend.xml +0 -0
- /package/templates/{common → base}/timsquad/architectures/hexagonal/ARCHITECTURE.md +0 -0
- /package/templates/{common → base}/timsquad/architectures/hexagonal/backend.xml +0 -0
- /package/templates/{common → base}/timsquad/constraints/competency-framework.xml +0 -0
- /package/templates/{common → base}/timsquad/constraints/ssot-schema.xml +0 -0
- /package/templates/{common → base}/timsquad/feedback/feedback-router.sh +0 -0
- /package/templates/{common → base}/timsquad/generators/data-design.xml +0 -0
- /package/templates/{common → base}/timsquad/generators/prd.xml +0 -0
- /package/templates/{common → base}/timsquad/generators/requirements.xml +0 -0
- /package/templates/{common → base}/timsquad/generators/service-spec.xml +0 -0
- /package/templates/{common → base}/timsquad/logs/_example.md +0 -0
- /package/templates/{common → base}/timsquad/logs/_template.md +0 -0
- /package/templates/{common → base}/timsquad/patterns/cqrs.xml +0 -0
- /package/templates/{common → base}/timsquad/patterns/event-sourcing.xml +0 -0
- /package/templates/{common → base}/timsquad/patterns/repository.xml +0 -0
- /package/templates/{common → base}/timsquad/process/phase-checklist.yaml +0 -0
- /package/templates/{common → base}/timsquad/process/state-machine.xml +0 -0
- /package/templates/{common → base}/timsquad/process/validation-rules.xml +0 -0
- /package/templates/{common → base}/timsquad/process/workflow-base.xml +0 -0
- /package/templates/{common → base}/timsquad/retrospective/cycle-report.template.md +0 -0
- /package/templates/{common → base}/timsquad/retrospective/patterns/failure-patterns.md +0 -0
- /package/templates/{common → base}/timsquad/retrospective/patterns/success-patterns.md +0 -0
- /package/templates/{common → base}/timsquad/retrospective/retrospective-config.xml +0 -0
- /package/templates/{common → base}/timsquad/retrospective/retrospective-state.xml +0 -0
- /package/templates/{common → base}/timsquad/ssot/adr/ADR-000-template.md +0 -0
- /package/templates/{common → base}/timsquad/ssot/adr/ADR-001-example.md +0 -0
- /package/templates/{common → base}/timsquad/ssot/data-design.template.md +0 -0
- /package/templates/{common → base}/timsquad/ssot/deployment-spec.template.md +0 -0
- /package/templates/{common → base}/timsquad/ssot/env-config.template.md +0 -0
- /package/templates/{common → base}/timsquad/ssot/error-codes.template.md +0 -0
- /package/templates/{common → base}/timsquad/ssot/functional-spec.template.md +0 -0
- /package/templates/{common → base}/timsquad/ssot/glossary.template.md +0 -0
- /package/templates/{common → base}/timsquad/ssot/integration-spec.template.md +0 -0
- /package/templates/{common → base}/timsquad/ssot/planning.template.md +0 -0
- /package/templates/{common → base}/timsquad/ssot/prd.template.md +0 -0
- /package/templates/{common → base}/timsquad/ssot/requirements.template.md +0 -0
- /package/templates/{common → base}/timsquad/ssot/security-spec.template.md +0 -0
- /package/templates/{common → base}/timsquad/ssot/service-spec.template.md +0 -0
- /package/templates/{common → base}/timsquad/ssot/test-spec.template.md +0 -0
- /package/templates/{common → base}/timsquad/ssot/ui-ux-spec.template.md +0 -0
- /package/templates/{common → base}/timsquad/state/workspace.xml +0 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Early Return from Functions
|
|
3
|
+
impact: LOW-MEDIUM
|
|
4
|
+
impactDescription: avoids unnecessary computation
|
|
5
|
+
tags: javascript, functions, optimization, early-return
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Early Return from Functions
|
|
9
|
+
|
|
10
|
+
Return early when result is determined to skip unnecessary processing.
|
|
11
|
+
|
|
12
|
+
**Incorrect (processes all items even after finding answer):**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
function validateUsers(users: User[]) {
|
|
16
|
+
let hasError = false
|
|
17
|
+
let errorMessage = ''
|
|
18
|
+
|
|
19
|
+
for (const user of users) {
|
|
20
|
+
if (!user.email) {
|
|
21
|
+
hasError = true
|
|
22
|
+
errorMessage = 'Email required'
|
|
23
|
+
}
|
|
24
|
+
if (!user.name) {
|
|
25
|
+
hasError = true
|
|
26
|
+
errorMessage = 'Name required'
|
|
27
|
+
}
|
|
28
|
+
// Continues checking all users even after error found
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return hasError ? { valid: false, error: errorMessage } : { valid: true }
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Correct (returns immediately on first error):**
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
function validateUsers(users: User[]) {
|
|
39
|
+
for (const user of users) {
|
|
40
|
+
if (!user.email) {
|
|
41
|
+
return { valid: false, error: 'Email required' }
|
|
42
|
+
}
|
|
43
|
+
if (!user.name) {
|
|
44
|
+
return { valid: false, error: 'Name required' }
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return { valid: true }
|
|
49
|
+
}
|
|
50
|
+
```
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Build Index Maps for Repeated Lookups
|
|
3
|
+
impact: LOW-MEDIUM
|
|
4
|
+
impactDescription: 1M ops to 2K ops
|
|
5
|
+
tags: javascript, map, indexing, optimization, performance
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Build Index Maps for Repeated Lookups
|
|
9
|
+
|
|
10
|
+
Multiple `.find()` calls by the same key should use a Map.
|
|
11
|
+
|
|
12
|
+
**Incorrect (O(n) per lookup):**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
function processOrders(orders: Order[], users: User[]) {
|
|
16
|
+
return orders.map(order => ({
|
|
17
|
+
...order,
|
|
18
|
+
user: users.find(u => u.id === order.userId)
|
|
19
|
+
}))
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Correct (O(1) per lookup):**
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
function processOrders(orders: Order[], users: User[]) {
|
|
27
|
+
const userById = new Map(users.map(u => [u.id, u]))
|
|
28
|
+
|
|
29
|
+
return orders.map(order => ({
|
|
30
|
+
...order,
|
|
31
|
+
user: userById.get(order.userId)
|
|
32
|
+
}))
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Build map once (O(n)), then all lookups are O(1).
|
|
37
|
+
For 1000 orders × 1000 users: 1M ops → 2K ops.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use Set/Map for O(1) Lookups
|
|
3
|
+
impact: LOW-MEDIUM
|
|
4
|
+
impactDescription: O(n) to O(1)
|
|
5
|
+
tags: javascript, set, map, data-structures, performance
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Use Set/Map for O(1) Lookups
|
|
9
|
+
|
|
10
|
+
Convert arrays to Set/Map for repeated membership checks.
|
|
11
|
+
|
|
12
|
+
**Incorrect (O(n) per check):**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
const allowedIds = ['a', 'b', 'c', ...]
|
|
16
|
+
items.filter(item => allowedIds.includes(item.id))
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Correct (O(1) per check):**
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
const allowedIds = new Set(['a', 'b', 'c', ...])
|
|
23
|
+
items.filter(item => allowedIds.has(item.id))
|
|
24
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use Explicit Conditional Rendering
|
|
3
|
+
impact: LOW
|
|
4
|
+
impactDescription: prevents rendering 0 or NaN
|
|
5
|
+
tags: rendering, conditional, jsx, falsy-values
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Use Explicit Conditional Rendering
|
|
9
|
+
|
|
10
|
+
Use explicit ternary operators (`? :`) instead of `&&` for conditional rendering when the condition can be `0`, `NaN`, or other falsy values that render.
|
|
11
|
+
|
|
12
|
+
**Incorrect (renders "0" when count is 0):**
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
function Badge({ count }: { count: number }) {
|
|
16
|
+
return (
|
|
17
|
+
<div>
|
|
18
|
+
{count && <span className="badge">{count}</span>}
|
|
19
|
+
</div>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// When count = 0, renders: <div>0</div>
|
|
24
|
+
// When count = 5, renders: <div><span class="badge">5</span></div>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Correct (renders nothing when count is 0):**
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
function Badge({ count }: { count: number }) {
|
|
31
|
+
return (
|
|
32
|
+
<div>
|
|
33
|
+
{count > 0 ? <span className="badge">{count}</span> : null}
|
|
34
|
+
</div>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// When count = 0, renders: <div></div>
|
|
39
|
+
// When count = 5, renders: <div><span class="badge">5</span></div>
|
|
40
|
+
```
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: CSS content-visibility for Long Lists
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: faster initial render
|
|
5
|
+
tags: rendering, css, content-visibility, long-lists
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## CSS content-visibility for Long Lists
|
|
9
|
+
|
|
10
|
+
Apply `content-visibility: auto` to defer off-screen rendering.
|
|
11
|
+
|
|
12
|
+
**CSS:**
|
|
13
|
+
|
|
14
|
+
```css
|
|
15
|
+
.message-item {
|
|
16
|
+
content-visibility: auto;
|
|
17
|
+
contain-intrinsic-size: 0 80px;
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
**Example:**
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
function MessageList({ messages }: { messages: Message[] }) {
|
|
25
|
+
return (
|
|
26
|
+
<div className="overflow-y-auto h-screen">
|
|
27
|
+
{messages.map(msg => (
|
|
28
|
+
<div key={msg.id} className="message-item">
|
|
29
|
+
<Avatar user={msg.author} />
|
|
30
|
+
<div>{msg.content}</div>
|
|
31
|
+
</div>
|
|
32
|
+
))}
|
|
33
|
+
</div>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
For 1000 messages, browser skips layout/paint for ~990 off-screen items (10× faster initial render).
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Hoist Static JSX Elements
|
|
3
|
+
impact: LOW
|
|
4
|
+
impactDescription: avoids re-creation
|
|
5
|
+
tags: rendering, jsx, static, optimization
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Hoist Static JSX Elements
|
|
9
|
+
|
|
10
|
+
Extract static JSX outside components to avoid re-creation.
|
|
11
|
+
|
|
12
|
+
**Incorrect (recreates element every render):**
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
function LoadingSkeleton() {
|
|
16
|
+
return <div className="animate-pulse h-20 bg-gray-200" />
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function Container() {
|
|
20
|
+
return (
|
|
21
|
+
<div>
|
|
22
|
+
{loading && <LoadingSkeleton />}
|
|
23
|
+
</div>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Correct (reuses same element):**
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
const loadingSkeleton = (
|
|
32
|
+
<div className="animate-pulse h-20 bg-gray-200" />
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
function Container() {
|
|
36
|
+
return (
|
|
37
|
+
<div>
|
|
38
|
+
{loading && loadingSkeleton}
|
|
39
|
+
</div>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
This is especially helpful for large and static SVG nodes, which can be expensive to recreate on every render.
|
|
45
|
+
|
|
46
|
+
**Note:** If your project has [React Compiler](https://react.dev/learn/react-compiler) enabled, the compiler automatically hoists static JSX elements and optimizes component re-renders, making manual hoisting unnecessary.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Defer State Reads to Usage Point
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: avoids unnecessary subscriptions
|
|
5
|
+
tags: rerender, searchParams, localStorage, optimization
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Defer State Reads to Usage Point
|
|
9
|
+
|
|
10
|
+
Don't subscribe to dynamic state (searchParams, localStorage) if you only read it inside callbacks.
|
|
11
|
+
|
|
12
|
+
**Incorrect (subscribes to all searchParams changes):**
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
function ShareButton({ chatId }: { chatId: string }) {
|
|
16
|
+
const searchParams = useSearchParams()
|
|
17
|
+
|
|
18
|
+
const handleShare = () => {
|
|
19
|
+
const ref = searchParams.get('ref')
|
|
20
|
+
shareChat(chatId, { ref })
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return <button onClick={handleShare}>Share</button>
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Correct (reads on demand, no subscription):**
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
function ShareButton({ chatId }: { chatId: string }) {
|
|
31
|
+
const handleShare = () => {
|
|
32
|
+
const params = new URLSearchParams(window.location.search)
|
|
33
|
+
const ref = params.get('ref')
|
|
34
|
+
shareChat(chatId, { ref })
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return <button onClick={handleShare}>Share</button>
|
|
38
|
+
}
|
|
39
|
+
```
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Subscribe to Derived State
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: reduces re-render frequency
|
|
5
|
+
tags: rerender, derived-state, media-query, optimization
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Subscribe to Derived State
|
|
9
|
+
|
|
10
|
+
Subscribe to derived boolean state instead of continuous values to reduce re-render frequency.
|
|
11
|
+
|
|
12
|
+
**Incorrect (re-renders on every pixel change):**
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
function Sidebar() {
|
|
16
|
+
const width = useWindowWidth() // updates continuously
|
|
17
|
+
const isMobile = width < 768
|
|
18
|
+
return <nav className={isMobile ? 'mobile' : 'desktop'}>
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Correct (re-renders only when boolean changes):**
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
function Sidebar() {
|
|
26
|
+
const isMobile = useMediaQuery('(max-width: 767px)')
|
|
27
|
+
return <nav className={isMobile ? 'mobile' : 'desktop'}>
|
|
28
|
+
}
|
|
29
|
+
```
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Extract to Memoized Components
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: enables early returns
|
|
5
|
+
tags: rerender, memo, useMemo, optimization
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Extract to Memoized Components
|
|
9
|
+
|
|
10
|
+
Extract expensive work into memoized components to enable early returns before computation.
|
|
11
|
+
|
|
12
|
+
**Incorrect (computes avatar even when loading):**
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
function Profile({ user, loading }: Props) {
|
|
16
|
+
const avatar = useMemo(() => {
|
|
17
|
+
const id = computeAvatarId(user)
|
|
18
|
+
return <Avatar id={id} />
|
|
19
|
+
}, [user])
|
|
20
|
+
|
|
21
|
+
if (loading) return <Skeleton />
|
|
22
|
+
return <div>{avatar}</div>
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Correct (skips computation when loading):**
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
const UserAvatar = memo(function UserAvatar({ user }: { user: User }) {
|
|
30
|
+
const id = useMemo(() => computeAvatarId(user), [user])
|
|
31
|
+
return <Avatar id={id} />
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
function Profile({ user, loading }: Props) {
|
|
35
|
+
if (loading) return <Skeleton />
|
|
36
|
+
return (
|
|
37
|
+
<div>
|
|
38
|
+
<UserAvatar user={user} />
|
|
39
|
+
</div>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Note:** If your project has [React Compiler](https://react.dev/learn/react-compiler) enabled, manual memoization with `memo()` and `useMemo()` is not necessary. The compiler automatically optimizes re-renders.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use Transitions for Non-Urgent Updates
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: maintains UI responsiveness
|
|
5
|
+
tags: rerender, transitions, startTransition, performance
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Use Transitions for Non-Urgent Updates
|
|
9
|
+
|
|
10
|
+
Mark frequent, non-urgent state updates as transitions to maintain UI responsiveness.
|
|
11
|
+
|
|
12
|
+
**Incorrect (blocks UI on every scroll):**
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
function ScrollTracker() {
|
|
16
|
+
const [scrollY, setScrollY] = useState(0)
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const handler = () => setScrollY(window.scrollY)
|
|
19
|
+
window.addEventListener('scroll', handler, { passive: true })
|
|
20
|
+
return () => window.removeEventListener('scroll', handler)
|
|
21
|
+
}, [])
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Correct (non-blocking updates):**
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { startTransition } from 'react'
|
|
29
|
+
|
|
30
|
+
function ScrollTracker() {
|
|
31
|
+
const [scrollY, setScrollY] = useState(0)
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
const handler = () => {
|
|
34
|
+
startTransition(() => setScrollY(window.scrollY))
|
|
35
|
+
}
|
|
36
|
+
window.addEventListener('scroll', handler, { passive: true })
|
|
37
|
+
return () => window.removeEventListener('scroll', handler)
|
|
38
|
+
}, [])
|
|
39
|
+
}
|
|
40
|
+
```
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use after() for Non-Blocking Operations
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: faster response times
|
|
5
|
+
tags: server, async, logging, analytics, side-effects
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Use after() for Non-Blocking Operations
|
|
9
|
+
|
|
10
|
+
Use Next.js's `after()` to schedule work that should execute after a response is sent. This prevents logging, analytics, and other side effects from blocking the response.
|
|
11
|
+
|
|
12
|
+
**Incorrect (blocks response):**
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import { logUserAction } from '@/app/utils'
|
|
16
|
+
|
|
17
|
+
export async function POST(request: Request) {
|
|
18
|
+
// Perform mutation
|
|
19
|
+
await updateDatabase(request)
|
|
20
|
+
|
|
21
|
+
// Logging blocks the response
|
|
22
|
+
const userAgent = request.headers.get('user-agent') || 'unknown'
|
|
23
|
+
await logUserAction({ userAgent })
|
|
24
|
+
|
|
25
|
+
return new Response(JSON.stringify({ status: 'success' }), {
|
|
26
|
+
status: 200,
|
|
27
|
+
headers: { 'Content-Type': 'application/json' }
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Correct (non-blocking):**
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
import { after } from 'next/server'
|
|
36
|
+
import { headers, cookies } from 'next/headers'
|
|
37
|
+
import { logUserAction } from '@/app/utils'
|
|
38
|
+
|
|
39
|
+
export async function POST(request: Request) {
|
|
40
|
+
// Perform mutation
|
|
41
|
+
await updateDatabase(request)
|
|
42
|
+
|
|
43
|
+
// Log after response is sent
|
|
44
|
+
after(async () => {
|
|
45
|
+
const userAgent = (await headers()).get('user-agent') || 'unknown'
|
|
46
|
+
const sessionCookie = (await cookies()).get('session-id')?.value || 'anonymous'
|
|
47
|
+
|
|
48
|
+
logUserAction({ sessionCookie, userAgent })
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
return new Response(JSON.stringify({ status: 'success' }), {
|
|
52
|
+
status: 200,
|
|
53
|
+
headers: { 'Content-Type': 'application/json' }
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The response is sent immediately while logging happens in the background.
|
|
59
|
+
|
|
60
|
+
**Common use cases:**
|
|
61
|
+
|
|
62
|
+
- Analytics tracking
|
|
63
|
+
- Audit logging
|
|
64
|
+
- Sending notifications
|
|
65
|
+
- Cache invalidation
|
|
66
|
+
- Cleanup tasks
|
|
67
|
+
|
|
68
|
+
**Important notes:**
|
|
69
|
+
|
|
70
|
+
- `after()` runs even if the response fails or redirects
|
|
71
|
+
- Works in Server Actions, Route Handlers, and Server Components
|
|
72
|
+
|
|
73
|
+
Reference: [https://nextjs.org/docs/app/api-reference/functions/after](https://nextjs.org/docs/app/api-reference/functions/after)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Per-Request Deduplication with React.cache()
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: deduplicates within request
|
|
5
|
+
tags: server, cache, react-cache, deduplication
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Per-Request Deduplication with React.cache()
|
|
9
|
+
|
|
10
|
+
Use `React.cache()` for server-side request deduplication. Authentication and database queries benefit most.
|
|
11
|
+
|
|
12
|
+
**Usage:**
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
import { cache } from 'react'
|
|
16
|
+
|
|
17
|
+
export const getCurrentUser = cache(async () => {
|
|
18
|
+
const session = await auth()
|
|
19
|
+
if (!session?.user?.id) return null
|
|
20
|
+
return await db.user.findUnique({
|
|
21
|
+
where: { id: session.user.id }
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Within a single request, multiple calls to `getCurrentUser()` execute the query only once.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Parallel Data Fetching with Component Composition
|
|
3
|
+
impact: CRITICAL
|
|
4
|
+
impactDescription: eliminates server-side waterfalls
|
|
5
|
+
tags: server, rsc, parallel-fetching, composition
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Parallel Data Fetching with Component Composition
|
|
9
|
+
|
|
10
|
+
React Server Components execute sequentially within a tree. Restructure with composition to parallelize data fetching.
|
|
11
|
+
|
|
12
|
+
**Incorrect (Sidebar waits for Page's fetch to complete):**
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
export default async function Page() {
|
|
16
|
+
const header = await fetchHeader()
|
|
17
|
+
return (
|
|
18
|
+
<div>
|
|
19
|
+
<div>{header}</div>
|
|
20
|
+
<Sidebar />
|
|
21
|
+
</div>
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function Sidebar() {
|
|
26
|
+
const items = await fetchSidebarItems()
|
|
27
|
+
return <nav>{items.map(renderItem)}</nav>
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Correct (both fetch simultaneously):**
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
async function Header() {
|
|
35
|
+
const data = await fetchHeader()
|
|
36
|
+
return <div>{data}</div>
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function Sidebar() {
|
|
40
|
+
const items = await fetchSidebarItems()
|
|
41
|
+
return <nav>{items.map(renderItem)}</nav>
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default function Page() {
|
|
45
|
+
return (
|
|
46
|
+
<div>
|
|
47
|
+
<Header />
|
|
48
|
+
<Sidebar />
|
|
49
|
+
</div>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Alternative with children prop:**
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
async function Layout({ children }: { children: ReactNode }) {
|
|
58
|
+
const header = await fetchHeader()
|
|
59
|
+
return (
|
|
60
|
+
<div>
|
|
61
|
+
<div>{header}</div>
|
|
62
|
+
{children}
|
|
63
|
+
</div>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async function Sidebar() {
|
|
68
|
+
const items = await fetchSidebarItems()
|
|
69
|
+
return <nav>{items.map(renderItem)}</nav>
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export default function Page() {
|
|
73
|
+
return (
|
|
74
|
+
<Layout>
|
|
75
|
+
<Sidebar />
|
|
76
|
+
</Layout>
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
```
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: State Location
|
|
3
|
+
impact: HIGH
|
|
4
|
+
tags: state, zustand, react-query
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## State Location
|
|
8
|
+
|
|
9
|
+
상태의 종류에 따라 적절한 위치를 선택한다.
|
|
10
|
+
|
|
11
|
+
| 상태 종류 | 위치 | 예시 |
|
|
12
|
+
|-----------|------|------|
|
|
13
|
+
| 단일 컴포넌트 | `useState` | 토글, 입력값 |
|
|
14
|
+
| 부모-자식 공유 | Props 전달 | 선택된 아이템 |
|
|
15
|
+
| 깊은 트리 공유 | Context | 테마, 인증, i18n |
|
|
16
|
+
| 여러 페이지 공유 | Zustand | UI 상태, 사이드바, 선택 항목 |
|
|
17
|
+
| API 데이터 | React Query | 서버 데이터 (캐싱, 동기화) |
|
|
18
|
+
| 복잡한 로직 | `useReducer` | 장바구니, 폼 위저드 |
|
|
19
|
+
|
|
20
|
+
### Key: 서버 상태 vs 클라이언트 상태 분리
|
|
21
|
+
|
|
22
|
+
**Incorrect:**
|
|
23
|
+
```tsx
|
|
24
|
+
// 서버 데이터를 전역 store에 저장
|
|
25
|
+
const useStore = create((set) => ({
|
|
26
|
+
users: [],
|
|
27
|
+
fetchUsers: async () => {
|
|
28
|
+
const users = await api.getUsers();
|
|
29
|
+
set({ users });
|
|
30
|
+
},
|
|
31
|
+
}));
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Correct:**
|
|
35
|
+
```tsx
|
|
36
|
+
// 서버 데이터는 React Query, UI 상태는 Zustand
|
|
37
|
+
function ItemList() {
|
|
38
|
+
const { data: items } = useQuery({ queryKey: ['items'], queryFn: fetchItems });
|
|
39
|
+
const { selectedItems, selectItem } = useUIStore();
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<ul>
|
|
43
|
+
{items?.map(item => (
|
|
44
|
+
<li
|
|
45
|
+
key={item.id}
|
|
46
|
+
className={selectedItems.includes(item.id) ? 'selected' : ''}
|
|
47
|
+
onClick={() => selectItem(item.id)}
|
|
48
|
+
>
|
|
49
|
+
{item.name}
|
|
50
|
+
</li>
|
|
51
|
+
))}
|
|
52
|
+
</ul>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
```
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bdd
|
|
3
|
+
description: Behavior-Driven Development 가이드라인
|
|
4
|
+
version: "1.0.0"
|
|
5
|
+
tags: [bdd, methodology, testing]
|
|
6
|
+
user-invocable: false
|
|
7
|
+
compatible-with: [tdd, ddd]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# BDD (Behavior-Driven Development)
|
|
11
|
+
|
|
12
|
+
## 철학
|
|
13
|
+
- 비즈니스 언어로 요구사항 표현
|
|
14
|
+
- Given-When-Then으로 시나리오 명세
|
|
15
|
+
- 살아있는 문서 (Living Documentation)
|
|
16
|
+
- 개발자, QA, 기획자 간 공통 언어
|
|
17
|
+
|
|
18
|
+
## 핵심 개념
|
|
19
|
+
|
|
20
|
+
### User Story
|
|
21
|
+
```
|
|
22
|
+
As a [역할]
|
|
23
|
+
I want [기능]
|
|
24
|
+
So that [가치/이유]
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Scenario (Given-When-Then)
|
|
28
|
+
```
|
|
29
|
+
Given [사전 조건]
|
|
30
|
+
When [행위]
|
|
31
|
+
Then [기대 결과]
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Acceptance Criteria
|
|
35
|
+
인수 조건 — 기능 완료 기준
|
|
36
|
+
|
|
37
|
+
## BDD vs TDD
|
|
38
|
+
|
|
39
|
+
| 관점 | TDD | BDD |
|
|
40
|
+
|------|-----|-----|
|
|
41
|
+
| 시점 | 개발자 (코드 단위) | 사용자/비즈니스 (행위) |
|
|
42
|
+
| 언어 | 기술 용어 | 비즈니스 용어 |
|
|
43
|
+
| 대상 | 단위 테스트 | 인수/E2E 테스트 |
|
|
44
|
+
| 문서 | 코드가 문서 | 시나리오가 살아있는 문서 |
|
|
45
|
+
|
|
46
|
+
**권장**: TDD + BDD 함께 사용 (보완 관계)
|
|
47
|
+
|
|
48
|
+
## Rules
|
|
49
|
+
|
|
50
|
+
### 필수
|
|
51
|
+
- 시나리오는 비즈니스 언어로 작성
|
|
52
|
+
- Given-When-Then 형식 준수
|
|
53
|
+
- 하나의 시나리오는 하나의 행위만 테스트
|
|
54
|
+
- 시나리오는 독립적으로 실행 가능
|
|
55
|
+
|
|
56
|
+
### 금지
|
|
57
|
+
- 기술 용어를 시나리오에 노출 (CSS selector, API endpoint 등)
|
|
58
|
+
- 테스트 간 상태 공유
|
|
59
|
+
- UI 구현 세부사항 시나리오에 포함
|
|
60
|
+
|
|
61
|
+
## Checklist
|
|
62
|
+
- [ ] Feature 파일이 비즈니스 언어로 작성됨
|
|
63
|
+
- [ ] Given-When-Then 형식 준수
|
|
64
|
+
- [ ] 시나리오가 독립적으로 실행 가능
|
|
65
|
+
- [ ] Step Definition 재사용성 확보
|
|
66
|
+
- [ ] Background로 공통 전제조건 추출
|
|
67
|
+
|
|
68
|
+
## 참조
|
|
69
|
+
- `rules/gherkin-patterns.md` — Feature 파일, Step Definition, API BDD 예시, 디렉토리 구조
|