@codyswann/lisa 1.47.1 → 1.48.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/all/copy-overwrite/.claude/rules/lisa.md +23 -10
- package/all/copy-overwrite/.claude/settings.json +10 -252
- package/all/deletions.json +67 -1
- package/cdk/copy-overwrite/.claude/settings.json +80 -0
- package/cdk/create-only/.github/workflows/ci.yml +1 -1
- package/cdk/create-only/.github/workflows/deploy.yml +1 -1
- package/dist/core/lisa.d.ts +14 -0
- package/dist/core/lisa.d.ts.map +1 -1
- package/dist/core/lisa.js +47 -0
- package/dist/core/lisa.js.map +1 -1
- package/expo/copy-overwrite/.claude/settings.json +80 -0
- package/expo/copy-overwrite/eslint.expo.ts +2 -2
- package/expo/create-only/.github/workflows/ci.yml +1 -1
- package/expo/create-only/.github/workflows/deploy.yml +1 -1
- package/expo/deletions.json +33 -0
- package/expo/package-lisa/package.lisa.json +2 -2
- package/nestjs/copy-overwrite/.claude/settings.json +80 -0
- package/nestjs/create-only/.github/workflows/ci.yml +1 -1
- package/nestjs/create-only/.github/workflows/deploy.yml +1 -1
- package/nestjs/deletions.json +8 -0
- package/package.json +8 -4
- package/rails/copy-overwrite/.claude/settings.json +80 -0
- package/rails/create-only/.github/workflows/ci.yml +1 -1
- package/rails/deletions.json +11 -1
- package/typescript/copy-overwrite/.claude/settings.json +13 -253
- package/typescript/copy-overwrite/eslint.typescript.ts +1 -1
- package/typescript/create-only/.github/workflows/ci.yml +1 -1
- package/typescript/deletions.json +12 -1
- package/typescript/package-lisa/package.lisa.json +1 -1
- package/all/copy-overwrite/.claude/agents/agent-architect.md +0 -310
- package/all/copy-overwrite/.claude/agents/architecture-specialist.md +0 -53
- package/all/copy-overwrite/.claude/agents/debug-specialist.md +0 -204
- package/all/copy-overwrite/.claude/agents/git-history-analyzer.md +0 -183
- package/all/copy-overwrite/.claude/agents/hooks-expert.md +0 -74
- package/all/copy-overwrite/.claude/agents/implementer.md +0 -54
- package/all/copy-overwrite/.claude/agents/learner.md +0 -44
- package/all/copy-overwrite/.claude/agents/performance-specialist.md +0 -95
- package/all/copy-overwrite/.claude/agents/product-specialist.md +0 -72
- package/all/copy-overwrite/.claude/agents/quality-specialist.md +0 -55
- package/all/copy-overwrite/.claude/agents/security-specialist.md +0 -58
- package/all/copy-overwrite/.claude/agents/skill-evaluator.md +0 -246
- package/all/copy-overwrite/.claude/agents/slash-command-architect.md +0 -87
- package/all/copy-overwrite/.claude/agents/test-specialist.md +0 -64
- package/all/copy-overwrite/.claude/agents/verification-specialist.md +0 -189
- package/all/copy-overwrite/.claude/agents/web-search-researcher.md +0 -112
- package/all/copy-overwrite/.claude/commands/git/commit-and-submit-pr.md +0 -7
- package/all/copy-overwrite/.claude/commands/git/commit-submit-pr-and-verify.md +0 -7
- package/all/copy-overwrite/.claude/commands/git/commit-submit-pr-deploy-and-verify.md +0 -7
- package/all/copy-overwrite/.claude/commands/git/commit.md +0 -7
- package/all/copy-overwrite/.claude/commands/git/prune.md +0 -6
- package/all/copy-overwrite/.claude/commands/git/submit-pr.md +0 -7
- package/all/copy-overwrite/.claude/commands/jira/create.md +0 -7
- package/all/copy-overwrite/.claude/commands/jira/sync.md +0 -7
- package/all/copy-overwrite/.claude/commands/jira/verify.md +0 -7
- package/all/copy-overwrite/.claude/commands/lisa/review-implementation.md +0 -7
- package/all/copy-overwrite/.claude/commands/plan/add-test-coverage.md +0 -7
- package/all/copy-overwrite/.claude/commands/plan/create.md +0 -6
- package/all/copy-overwrite/.claude/commands/plan/execute.md +0 -7
- package/all/copy-overwrite/.claude/commands/plan/fix-linter-error.md +0 -7
- package/all/copy-overwrite/.claude/commands/plan/local-code-review.md +0 -6
- package/all/copy-overwrite/.claude/commands/plan/lower-code-complexity.md +0 -6
- package/all/copy-overwrite/.claude/commands/plan/reduce-max-lines-per-function.md +0 -7
- package/all/copy-overwrite/.claude/commands/plan/reduce-max-lines.md +0 -7
- package/all/copy-overwrite/.claude/commands/pull-request/review.md +0 -7
- package/all/copy-overwrite/.claude/commands/security/zap-scan.md +0 -6
- package/all/copy-overwrite/.claude/commands/sonarqube/check.md +0 -6
- package/all/copy-overwrite/.claude/commands/sonarqube/fix.md +0 -6
- package/all/copy-overwrite/.claude/commands/tasks/load.md +0 -7
- package/all/copy-overwrite/.claude/commands/tasks/sync.md +0 -7
- package/all/copy-overwrite/.claude/hooks/check-tired-boss.sh +0 -61
- package/all/copy-overwrite/.claude/hooks/debug-hook.sh +0 -47
- package/all/copy-overwrite/.claude/hooks/enforce-plan-rules.sh +0 -15
- package/all/copy-overwrite/.claude/hooks/notify-ntfy.sh +0 -183
- package/all/copy-overwrite/.claude/hooks/setup-jira-cli.sh +0 -52
- package/all/copy-overwrite/.claude/hooks/sync-tasks.sh +0 -107
- package/all/copy-overwrite/.claude/hooks/ticket-sync-reminder.sh +0 -23
- package/all/copy-overwrite/.claude/hooks/track-plan-sessions.sh +0 -164
- package/all/copy-overwrite/.claude/hooks/verify-completion.sh +0 -77
- package/all/copy-overwrite/.claude/rules/coding-philosophy.md +0 -428
- package/all/copy-overwrite/.claude/rules/verfication.md +0 -596
- package/all/copy-overwrite/.claude/skills/agent-design-best-practices/SKILL.md +0 -219
- package/all/copy-overwrite/.claude/skills/git-commit/SKILL.md +0 -48
- package/all/copy-overwrite/.claude/skills/git-commit-and-submit-pr/SKILL.md +0 -8
- package/all/copy-overwrite/.claude/skills/git-commit-submit-pr-and-verify/SKILL.md +0 -7
- package/all/copy-overwrite/.claude/skills/git-commit-submit-pr-deploy-and-verify/SKILL.md +0 -7
- package/all/copy-overwrite/.claude/skills/git-prune/SKILL.md +0 -35
- package/all/copy-overwrite/.claude/skills/git-submit-pr/SKILL.md +0 -44
- package/all/copy-overwrite/.claude/skills/jira-create/SKILL.md +0 -41
- package/all/copy-overwrite/.claude/skills/jira-sync/SKILL.md +0 -63
- package/all/copy-overwrite/.claude/skills/jira-verify/SKILL.md +0 -29
- package/all/copy-overwrite/.claude/skills/lisa-review-implementation/SKILL.md +0 -209
- package/all/copy-overwrite/.claude/skills/plan-add-test-coverage/SKILL.md +0 -44
- package/all/copy-overwrite/.claude/skills/plan-execute/SKILL.md +0 -89
- package/all/copy-overwrite/.claude/skills/plan-fix-linter-error/SKILL.md +0 -45
- package/all/copy-overwrite/.claude/skills/plan-local-code-review/SKILL.md +0 -88
- package/all/copy-overwrite/.claude/skills/plan-lower-code-complexity/SKILL.md +0 -44
- package/all/copy-overwrite/.claude/skills/plan-reduce-max-lines/SKILL.md +0 -45
- package/all/copy-overwrite/.claude/skills/plan-reduce-max-lines-per-function/SKILL.md +0 -46
- package/all/copy-overwrite/.claude/skills/pull-request-review/SKILL.md +0 -68
- package/all/copy-overwrite/.claude/skills/security-zap-scan/SKILL.md +0 -33
- package/all/copy-overwrite/.claude/skills/skill-creator/LICENSE.txt +0 -202
- package/all/copy-overwrite/.claude/skills/skill-creator/SKILL.md +0 -210
- package/all/copy-overwrite/.claude/skills/skill-creator/scripts/__pycache__/quick_validate.cpython-312.pyc +0 -0
- package/all/copy-overwrite/.claude/skills/skill-creator/scripts/init_skill.py +0 -305
- package/all/copy-overwrite/.claude/skills/skill-creator/scripts/package_skill.py +0 -112
- package/all/copy-overwrite/.claude/skills/skill-creator/scripts/quick_validate.py +0 -67
- package/all/copy-overwrite/.claude/skills/sonarqube-check/SKILL.md +0 -11
- package/all/copy-overwrite/.claude/skills/sonarqube-fix/SKILL.md +0 -8
- package/all/copy-overwrite/.claude/skills/tasks-load/SKILL.md +0 -88
- package/all/copy-overwrite/.claude/skills/tasks-sync/SKILL.md +0 -108
- package/eslint-plugin-code-organization/README.md +0 -149
- package/eslint-plugin-code-organization/__tests__/enforce-statement-order.test.js +0 -473
- package/eslint-plugin-code-organization/index.js +0 -28
- package/eslint-plugin-code-organization/package.json +0 -10
- package/eslint-plugin-code-organization/rules/enforce-statement-order.js +0 -162
- package/expo/copy-overwrite/.claude/agents/ops-specialist.md +0 -124
- package/expo/copy-overwrite/.claude/rules/expo-verification.md +0 -261
- package/expo/copy-overwrite/.claude/skills/apollo-client/SKILL.md +0 -238
- package/expo/copy-overwrite/.claude/skills/apollo-client/references/mutation-patterns.md +0 -360
- package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/SKILL.md +0 -360
- package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/atomic-levels.md +0 -417
- package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/folder-structure.md +0 -257
- package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/references/gluestack-mapping.md +0 -233
- package/expo/copy-overwrite/.claude/skills/atomic-design-gluestack/scripts/validate_atomic_structure.py +0 -329
- package/expo/copy-overwrite/.claude/skills/container-view-pattern/SKILL.md +0 -299
- package/expo/copy-overwrite/.claude/skills/container-view-pattern/references/examples.md +0 -749
- package/expo/copy-overwrite/.claude/skills/container-view-pattern/references/patterns.md +0 -318
- package/expo/copy-overwrite/.claude/skills/container-view-pattern/scripts/create_component.py +0 -200
- package/expo/copy-overwrite/.claude/skills/container-view-pattern/scripts/validate_component.py +0 -209
- package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/SKILL.md +0 -268
- package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/common-issues.md +0 -619
- package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/file-extensions.md +0 -340
- package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/references/platform-api.md +0 -276
- package/expo/copy-overwrite/.claude/skills/cross-platform-compatibility/scripts/validate_cross_platform.py +0 -416
- package/expo/copy-overwrite/.claude/skills/directory-structure/SKILL.md +0 -202
- package/expo/copy-overwrite/.claude/skills/directory-structure/scripts/validate_structure.py +0 -445
- package/expo/copy-overwrite/.claude/skills/expo-env-config/SKILL.md +0 -309
- package/expo/copy-overwrite/.claude/skills/expo-env-config/references/validation-patterns.md +0 -417
- package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/SKILL.md +0 -431
- package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/references/official-docs.md +0 -290
- package/expo/copy-overwrite/.claude/skills/expo-router-best-practices/scripts/generate-route.py +0 -171
- package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/SKILL.md +0 -411
- package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/color-tokens.md +0 -343
- package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/component-mapping.md +0 -307
- package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/references/spacing-scale.md +0 -300
- package/expo/copy-overwrite/.claude/skills/gluestack-nativewind/scripts/validate_styling.py +0 -315
- package/expo/copy-overwrite/.claude/skills/local-state/SKILL.md +0 -362
- package/expo/copy-overwrite/.claude/skills/local-state/references/async-storage.md +0 -505
- package/expo/copy-overwrite/.claude/skills/local-state/references/persistence-patterns.md +0 -711
- package/expo/copy-overwrite/.claude/skills/local-state/references/reactive-variables.md +0 -446
- package/expo/copy-overwrite/.claude/skills/ops-browser-uat/SKILL.md +0 -124
- package/expo/copy-overwrite/.claude/skills/ops-check-logs/SKILL.md +0 -211
- package/expo/copy-overwrite/.claude/skills/ops-db-ops/SKILL.md +0 -119
- package/expo/copy-overwrite/.claude/skills/ops-deploy/SKILL.md +0 -119
- package/expo/copy-overwrite/.claude/skills/ops-monitor-errors/SKILL.md +0 -99
- package/expo/copy-overwrite/.claude/skills/ops-performance/SKILL.md +0 -165
- package/expo/copy-overwrite/.claude/skills/ops-run-local/SKILL.md +0 -166
- package/expo/copy-overwrite/.claude/skills/ops-verify-health/SKILL.md +0 -101
- package/expo/copy-overwrite/.claude/skills/owasp-zap/SKILL.md +0 -56
- package/expo/copy-overwrite/.claude/skills/playwright-selectors/SKILL.md +0 -223
- package/expo/copy-overwrite/.claude/skills/testing-library/SKILL.md +0 -314
- package/expo/copy-overwrite/.claude/skills/testing-library/references/async-patterns.md +0 -420
- package/expo/copy-overwrite/.claude/skills/testing-library/references/expo-router-testing.md +0 -556
- package/expo/copy-overwrite/.claude/skills/testing-library/references/mocking-patterns.md +0 -590
- package/expo/copy-overwrite/.claude/skills/testing-library/references/query-priority.md +0 -291
- package/expo/copy-overwrite/eslint-plugin-component-structure/README.md +0 -234
- package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/plugin-index.test.js +0 -89
- package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/require-memo-in-view.test.js +0 -201
- package/expo/copy-overwrite/eslint-plugin-component-structure/__tests__/single-component-per-file.test.js +0 -294
- package/expo/copy-overwrite/eslint-plugin-component-structure/index.js +0 -37
- package/expo/copy-overwrite/eslint-plugin-component-structure/package.json +0 -10
- package/expo/copy-overwrite/eslint-plugin-component-structure/rules/enforce-component-structure.js +0 -235
- package/expo/copy-overwrite/eslint-plugin-component-structure/rules/no-return-in-view.js +0 -96
- package/expo/copy-overwrite/eslint-plugin-component-structure/rules/require-memo-in-view.js +0 -183
- package/expo/copy-overwrite/eslint-plugin-component-structure/rules/single-component-per-file.js +0 -243
- package/expo/copy-overwrite/eslint-plugin-ui-standards/README.md +0 -192
- package/expo/copy-overwrite/eslint-plugin-ui-standards/index.js +0 -31
- package/expo/copy-overwrite/eslint-plugin-ui-standards/package.json +0 -10
- package/expo/copy-overwrite/eslint-plugin-ui-standards/rules/no-classname-outside-ui.js +0 -56
- package/expo/copy-overwrite/eslint-plugin-ui-standards/rules/no-direct-rn-imports.js +0 -60
- package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/SKILL.md +0 -176
- package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/advanced-features.md +0 -527
- package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/project-patterns.md +0 -483
- package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/quick-start.md +0 -257
- package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/resolvers-mutations.md +0 -413
- package/nestjs/copy-overwrite/.claude/skills/nestjs-graphql/references/types-scalars.md +0 -513
- package/nestjs/copy-overwrite/.claude/skills/nestjs-rules/SKILL.md +0 -536
- package/nestjs/copy-overwrite/.claude/skills/security-zap-scan/SKILL.md +0 -33
- package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/SKILL.md +0 -275
- package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/configuration-patterns.md +0 -487
- package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/entity-patterns.md +0 -450
- package/nestjs/copy-overwrite/.claude/skills/typeorm-patterns/references/observability-patterns.md +0 -536
- package/rails/copy-overwrite/.claude/skills/action-controller-best-practices/SKILL.md +0 -374
- package/rails/copy-overwrite/.claude/skills/action-view-best-practices/SKILL.md +0 -335
- package/rails/copy-overwrite/.claude/skills/active-record-model-best-practices/SKILL.md +0 -166
- package/rails/copy-overwrite/.claude/skills/plan-add-test-coverage/SKILL.md +0 -45
- package/rails/copy-overwrite/.claude/skills/plan-fix-linter-error/SKILL.md +0 -45
- package/rails/copy-overwrite/.claude/skills/plan-lower-code-complexity/SKILL.md +0 -48
- package/rails/copy-overwrite/.claude/skills/plan-reduce-max-lines/SKILL.md +0 -46
- package/rails/copy-overwrite/.claude/skills/plan-reduce-max-lines-per-function/SKILL.md +0 -46
- package/typescript/copy-overwrite/.claude/hooks/format-on-edit.sh +0 -76
- package/typescript/copy-overwrite/.claude/hooks/install-pkgs.sh +0 -64
- package/typescript/copy-overwrite/.claude/hooks/lint-on-edit.sh +0 -81
- package/typescript/copy-overwrite/.claude/hooks/sg-scan-on-edit.sh +0 -68
- package/typescript/copy-overwrite/.claude/skills/jsdoc-best-practices/SKILL.md +0 -432
- package/typescript/copy-overwrite/eslint-plugin-code-organization/README.md +0 -149
- package/typescript/copy-overwrite/eslint-plugin-code-organization/__tests__/enforce-statement-order.test.js +0 -473
- package/typescript/copy-overwrite/eslint-plugin-code-organization/index.js +0 -28
- package/typescript/copy-overwrite/eslint-plugin-code-organization/package.json +0 -10
- package/typescript/copy-overwrite/eslint-plugin-code-organization/rules/enforce-statement-order.js +0 -162
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: active-record-model-best-practices
|
|
3
|
-
description: Best practices for Ruby on Rails models, splitting code into well-organized, maintainable code. Use when a model exceeds ~100 lines, has mixed responsibilities, or when the user asks to refactor, extract, clean up, or organize a Rails model. Applies patterns: concerns, service objects, query objects, form objects, and value objects.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Rails Model Refactoring
|
|
7
|
-
|
|
8
|
-
When refactoring a Rails model, analyze the file and extract code into the appropriate pattern based on what the code does. The model itself should only contain associations, enums, basic validations, and concern includes.
|
|
9
|
-
|
|
10
|
-
## Decision Framework
|
|
11
|
-
|
|
12
|
-
Read the model file and classify each block of code:
|
|
13
|
-
|
|
14
|
-
| Code type | Extract to | Location |
|
|
15
|
-
|---|---|---|
|
|
16
|
-
| Related scopes + simple methods sharing a theme | Concern | `app/models/concerns/` |
|
|
17
|
-
| Business logic, multi-step operations, callbacks with side effects | Service object | `app/services/` |
|
|
18
|
-
| Complex queries, multi-join scopes, reporting queries | Query object | `app/queries/` |
|
|
19
|
-
| Context-specific validations (e.g. registration vs admin update) | Form object | `app/forms/` |
|
|
20
|
-
| Domain concepts beyond a primitive (money, coordinates, scores) | Value object | `app/models/` |
|
|
21
|
-
| Associations, enums, core validations, simple scopes | Keep on model | — |
|
|
22
|
-
|
|
23
|
-
## Patterns
|
|
24
|
-
|
|
25
|
-
### Concerns
|
|
26
|
-
|
|
27
|
-
Use for grouping related scopes, validations, callbacks, and simple instance methods that share a single theme. Name the concern after the capability it provides.
|
|
28
|
-
|
|
29
|
-
```ruby
|
|
30
|
-
# app/models/concerns/searchable.rb
|
|
31
|
-
module Searchable
|
|
32
|
-
extend ActiveSupport::Concern
|
|
33
|
-
|
|
34
|
-
included do
|
|
35
|
-
scope :search, ->(query) { where("name ILIKE ?", "%#{query}%") }
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def matching_terms(query)
|
|
39
|
-
name.scan(/#{Regexp.escape(query)}/i)
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### Service Objects
|
|
45
|
-
|
|
46
|
-
Use for business logic, orchestration of multiple models, and anything triggered by a user action that involves more than a simple CRUD operation. Follow the single-responsibility principle — one service, one operation.
|
|
47
|
-
|
|
48
|
-
```ruby
|
|
49
|
-
# app/services/players/calculate_stats.rb
|
|
50
|
-
module Players
|
|
51
|
-
class CalculateStats
|
|
52
|
-
def initialize(player)
|
|
53
|
-
@player = player
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def call
|
|
57
|
-
# complex logic here
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Conventions:
|
|
64
|
-
- Namespace under the model name: `Players::CalculateStats`
|
|
65
|
-
- Single public method: `call`
|
|
66
|
-
- Accept dependencies via `initialize`
|
|
67
|
-
- Return a result or raise a domain-specific error
|
|
68
|
-
|
|
69
|
-
### Query Objects
|
|
70
|
-
|
|
71
|
-
Use for complex database queries that involve joins, subqueries, CTEs, or multi-condition filtering that would clutter a model with scopes.
|
|
72
|
-
|
|
73
|
-
```ruby
|
|
74
|
-
# app/queries/players/free_agent_query.rb
|
|
75
|
-
module Players
|
|
76
|
-
class FreeAgentQuery
|
|
77
|
-
def initialize(relation = Player.all)
|
|
78
|
-
@relation = relation
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def call(filters = {})
|
|
82
|
-
@relation
|
|
83
|
-
.where(contract_status: :expired)
|
|
84
|
-
.where("age < ?", filters[:max_age])
|
|
85
|
-
.joins(:stats)
|
|
86
|
-
.order(war: :desc)
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
Conventions:
|
|
93
|
-
- Accept a base relation in `initialize` (default to `Model.all`)
|
|
94
|
-
- Return an ActiveRecord relation so it remains chainable
|
|
95
|
-
- Single public method: `call`
|
|
96
|
-
|
|
97
|
-
### Form Objects
|
|
98
|
-
|
|
99
|
-
Use when validations only apply in specific contexts, or when a form spans multiple models.
|
|
100
|
-
|
|
101
|
-
```ruby
|
|
102
|
-
# app/forms/player_registration_form.rb
|
|
103
|
-
class PlayerRegistrationForm
|
|
104
|
-
include ActiveModel::Model
|
|
105
|
-
include ActiveModel::Attributes
|
|
106
|
-
|
|
107
|
-
attribute :name, :string
|
|
108
|
-
attribute :email, :string
|
|
109
|
-
attribute :team_id, :integer
|
|
110
|
-
attribute :position, :string
|
|
111
|
-
|
|
112
|
-
validates :name, :email, :position, presence: true
|
|
113
|
-
validates :email, format: { with: URI::MailTo::EMAIL_REGEXP }
|
|
114
|
-
|
|
115
|
-
def save
|
|
116
|
-
return false unless valid?
|
|
117
|
-
Player.create!(attributes)
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
### Value Objects
|
|
123
|
-
|
|
124
|
-
Use for domain concepts that deserve their own identity beyond a raw primitive.
|
|
125
|
-
|
|
126
|
-
```ruby
|
|
127
|
-
# app/models/batting_average.rb
|
|
128
|
-
class BattingAverage
|
|
129
|
-
include Comparable
|
|
130
|
-
|
|
131
|
-
def initialize(hits, at_bats)
|
|
132
|
-
@hits = hits
|
|
133
|
-
@at_bats = at_bats
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
def value
|
|
137
|
-
return 0.0 if @at_bats.zero?
|
|
138
|
-
(@hits.to_f / @at_bats).round(3)
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
def elite?
|
|
142
|
-
value >= 0.300
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
def <=>(other)
|
|
146
|
-
value <=> other.value
|
|
147
|
-
end
|
|
148
|
-
end
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
## Refactoring Process
|
|
152
|
-
|
|
153
|
-
1. **Read the entire model** and identify every method, scope, callback, and validation.
|
|
154
|
-
2. **Classify each block** using the decision framework table above.
|
|
155
|
-
3. **Extract in order**: value objects first, then query objects, then service objects, then concerns. Do concerns last because some may become unnecessary after other extractions.
|
|
156
|
-
4. **Update the model** to include concerns and delegate to new objects.
|
|
157
|
-
5. **Verify** that the slimmed-down model only contains: associations, enums, core validations, and concern includes.
|
|
158
|
-
6. **Create or update tests** for each extracted class. Each new class gets its own spec file mirroring the source path.
|
|
159
|
-
|
|
160
|
-
## What NOT to Do
|
|
161
|
-
|
|
162
|
-
- Don't extract everything — simple one-line scopes and basic validations belong on the model.
|
|
163
|
-
- Don't create a class for trivial logic just to hit a line count target.
|
|
164
|
-
- Don't use concerns as junk drawers — each concern should have a clear, single theme.
|
|
165
|
-
- Don't break ActiveRecord conventions (e.g. don't move associations into concerns).
|
|
166
|
-
- Don't introduce callback-heavy service objects — prefer explicit invocation over implicit hooks.
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: plan-add-test-coverage
|
|
3
|
-
description: This skill should be used when increasing test coverage to a specified threshold percentage. It runs the test suite with SimpleCov, identifies files with the lowest coverage, generates a brief with coverage gaps, and creates a plan with tasks to add the missing tests.
|
|
4
|
-
allowed-tools: ["Read", "Bash", "Glob", "Grep"]
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Increase Test Coverage
|
|
9
|
-
|
|
10
|
-
Target threshold: $ARGUMENTS%
|
|
11
|
-
|
|
12
|
-
If no argument provided, prompt the user for a target.
|
|
13
|
-
|
|
14
|
-
## Step 1: Gather Requirements
|
|
15
|
-
|
|
16
|
-
1. **Find coverage config** (`.simplecov` or `spec/spec_helper.rb`)
|
|
17
|
-
2. **Run test suite with coverage** to get current state:
|
|
18
|
-
```bash
|
|
19
|
-
bundle exec rspec 2>&1 | tail -50
|
|
20
|
-
```
|
|
21
|
-
3. **Check SimpleCov output** in `coverage/index.html` or console output
|
|
22
|
-
4. **Identify the 20 files with lowest coverage**, noting:
|
|
23
|
-
- File path
|
|
24
|
-
- Current coverage % (lines, branches)
|
|
25
|
-
- Which lines/branches are uncovered
|
|
26
|
-
|
|
27
|
-
## Step 2: Compile Brief and Delegate
|
|
28
|
-
|
|
29
|
-
Compile the gathered information into a structured brief:
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
Increase test coverage from [current]% to $ARGUMENTS%.
|
|
33
|
-
|
|
34
|
-
Files needing coverage (ordered by coverage gap):
|
|
35
|
-
1. [file] - [current]% coverage (target: $ARGUMENTS%)
|
|
36
|
-
- Uncovered: [lines]
|
|
37
|
-
- Missing branch coverage: [lines]
|
|
38
|
-
2. ...
|
|
39
|
-
|
|
40
|
-
Configuration: .simplecov, update minimum_coverage to $ARGUMENTS%
|
|
41
|
-
|
|
42
|
-
Verification: `bundle exec rspec` -> Expected: SimpleCov reports >= $ARGUMENTS% coverage
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
Invoke `/plan-execute` with this brief to create the implementation plan.
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: plan-fix-linter-error
|
|
3
|
-
description: This skill should be used when fixing all violations of one or more RuboCop cops across the codebase. It runs RuboCop, groups violations by cop and file, generates a brief with fix strategies, and creates a plan with tasks to implement the fixes.
|
|
4
|
-
allowed-tools: ["Read", "Bash", "Glob", "Grep"]
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Fix Linter Errors
|
|
9
|
-
|
|
10
|
-
Target cops: $ARGUMENTS
|
|
11
|
-
|
|
12
|
-
If no arguments provided, prompt the user for at least one RuboCop cop name.
|
|
13
|
-
|
|
14
|
-
## Step 1: Gather Requirements
|
|
15
|
-
|
|
16
|
-
1. **Parse cops** from $ARGUMENTS (space-separated)
|
|
17
|
-
2. **Run RuboCop** to collect all violations:
|
|
18
|
-
```bash
|
|
19
|
-
bundle exec rubocop --format json 2>&1
|
|
20
|
-
```
|
|
21
|
-
3. **Group violations** by cop, then by file, noting:
|
|
22
|
-
- File path and line numbers
|
|
23
|
-
- Violation count per file
|
|
24
|
-
- Sample offense messages
|
|
25
|
-
|
|
26
|
-
## Step 2: Compile Brief and Delegate
|
|
27
|
-
|
|
28
|
-
Compile the gathered information into a structured brief:
|
|
29
|
-
|
|
30
|
-
```
|
|
31
|
-
Fix RuboCop violations for cops: $ARGUMENTS
|
|
32
|
-
|
|
33
|
-
Violations by cop:
|
|
34
|
-
- [CopName1]: X total violations across Y files
|
|
35
|
-
- [file]: N violations (lines: ...)
|
|
36
|
-
- ...
|
|
37
|
-
- [CopName2]: X total violations across Y files
|
|
38
|
-
- ...
|
|
39
|
-
|
|
40
|
-
Fix strategies: extract methods, reduce complexity, apply auto-correct where safe
|
|
41
|
-
|
|
42
|
-
Verification: `bundle exec rubocop --format simple 2>&1 | grep -E "($ARGUMENTS)" | wc -l` -> Expected: 0
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
Invoke `/plan-execute` with this brief to create the implementation plan.
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: plan-lower-code-complexity
|
|
3
|
-
description: This skill should be used when reducing the code complexity threshold of the codebase. It lowers the CyclomaticComplexity threshold by 2, identifies methods that exceed the new limit, generates a brief with refactoring strategies, and creates a plan with tasks to fix all violations.
|
|
4
|
-
allowed-tools: ["Read", "Bash", "Glob", "Grep"]
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Lower Code Complexity
|
|
8
|
-
|
|
9
|
-
Reduces the CyclomaticComplexity threshold by 2 and fixes all violations.
|
|
10
|
-
|
|
11
|
-
## Step 1: Gather Requirements
|
|
12
|
-
|
|
13
|
-
1. **Read current threshold** from `.rubocop.yml` (`Metrics/CyclomaticComplexity` Max)
|
|
14
|
-
2. **Calculate new threshold**: current - 2 (e.g., 10 -> 8)
|
|
15
|
-
3. **Run RuboCop and flog** to find violations:
|
|
16
|
-
```bash
|
|
17
|
-
bundle exec rubocop --only Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity --format json 2>&1
|
|
18
|
-
```
|
|
19
|
-
```bash
|
|
20
|
-
bundle exec flog --all --group app/ 2>&1 | head -50
|
|
21
|
-
```
|
|
22
|
-
4. **Note for each violation**:
|
|
23
|
-
- File path and line number
|
|
24
|
-
- Method name
|
|
25
|
-
- Current complexity score (RuboCop and/or flog)
|
|
26
|
-
|
|
27
|
-
If no violations at new threshold, report success and exit.
|
|
28
|
-
|
|
29
|
-
## Step 2: Compile Brief and Delegate
|
|
30
|
-
|
|
31
|
-
Compile the gathered information into a structured brief:
|
|
32
|
-
|
|
33
|
-
```
|
|
34
|
-
Reduce CyclomaticComplexity threshold from [current] to [new].
|
|
35
|
-
|
|
36
|
-
Methods exceeding threshold (ordered by complexity):
|
|
37
|
-
1. [file:method_name] (complexity: X, target: [new]) - Line Y
|
|
38
|
-
- flog score: Z
|
|
39
|
-
2. ...
|
|
40
|
-
|
|
41
|
-
Configuration change: .rubocop.local.yml, Metrics/CyclomaticComplexity Max from [current] to [new]
|
|
42
|
-
|
|
43
|
-
Refactoring strategies: extract methods, early returns, extract conditions, use lookup hashes, replace conditionals with polymorphism
|
|
44
|
-
|
|
45
|
-
Verification: `bundle exec rubocop --only Metrics/CyclomaticComplexity --format simple 2>&1 | grep "offense" | wc -l` -> Expected: 0
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
Invoke `/plan-execute` with this brief to create the implementation plan.
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: plan-reduce-max-lines
|
|
3
|
-
description: This skill should be used when reducing the maximum class/module lines threshold and fixing all violations. It updates the RuboCop configuration, identifies classes and modules exceeding the new limit, generates a brief with refactoring strategies, and creates a plan with tasks to split oversized files.
|
|
4
|
-
allowed-tools: ["Read", "Bash", "Glob", "Grep"]
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Reduce Max Lines
|
|
9
|
-
|
|
10
|
-
Target threshold: $ARGUMENTS lines per class/module
|
|
11
|
-
|
|
12
|
-
If no argument provided, prompt the user for a target.
|
|
13
|
-
|
|
14
|
-
## Step 1: Gather Requirements
|
|
15
|
-
|
|
16
|
-
1. **Read current config** from `.rubocop.yml` or `.rubocop.local.yml` (`Metrics/ClassLength` and `Metrics/ModuleLength`)
|
|
17
|
-
2. **Run RuboCop** with the target threshold to find violations:
|
|
18
|
-
```bash
|
|
19
|
-
bundle exec rubocop --only Metrics/ClassLength,Metrics/ModuleLength --format json 2>&1
|
|
20
|
-
```
|
|
21
|
-
3. **Note for each violation**:
|
|
22
|
-
- File path
|
|
23
|
-
- Class/module name
|
|
24
|
-
- Current line count
|
|
25
|
-
|
|
26
|
-
If no violations at $ARGUMENTS, report success and exit.
|
|
27
|
-
|
|
28
|
-
## Step 2: Compile Brief and Delegate
|
|
29
|
-
|
|
30
|
-
Compile the gathered information into a structured brief:
|
|
31
|
-
|
|
32
|
-
```
|
|
33
|
-
Reduce max class/module lines threshold to $ARGUMENTS.
|
|
34
|
-
|
|
35
|
-
Classes/modules exceeding threshold (ordered by line count):
|
|
36
|
-
1. [file:ClassName] - [current] lines (target: $ARGUMENTS)
|
|
37
|
-
2. ...
|
|
38
|
-
|
|
39
|
-
Configuration change: .rubocop.local.yml, Metrics/ClassLength Max to $ARGUMENTS, Metrics/ModuleLength Max to $ARGUMENTS
|
|
40
|
-
|
|
41
|
-
Refactoring strategies: extract concerns, extract service objects, remove duplication, delete dead code, simplify logic
|
|
42
|
-
|
|
43
|
-
Verification: `bundle exec rubocop --only Metrics/ClassLength,Metrics/ModuleLength --format simple 2>&1 | grep "offense" | wc -l` -> Expected: 0
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Invoke `/plan-execute` with this brief to create the implementation plan.
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: plan-reduce-max-lines-per-function
|
|
3
|
-
description: This skill should be used when reducing the maximum lines per method threshold and fixing all violations. It updates the RuboCop configuration, identifies methods exceeding the new limit, generates a brief with refactoring strategies, and creates a plan with tasks to split oversized methods.
|
|
4
|
-
allowed-tools: ["Read", "Bash", "Glob", "Grep"]
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Reduce Max Lines Per Method
|
|
9
|
-
|
|
10
|
-
Target threshold: $ARGUMENTS lines per method
|
|
11
|
-
|
|
12
|
-
If no argument provided, prompt the user for a target.
|
|
13
|
-
|
|
14
|
-
## Step 1: Gather Requirements
|
|
15
|
-
|
|
16
|
-
1. **Read current config** from `.rubocop.yml` or `.rubocop.local.yml` (`Metrics/MethodLength`)
|
|
17
|
-
2. **Run RuboCop** with the target threshold to find violations:
|
|
18
|
-
```bash
|
|
19
|
-
bundle exec rubocop --only Metrics/MethodLength --format json 2>&1
|
|
20
|
-
```
|
|
21
|
-
3. **Note for each violation**:
|
|
22
|
-
- File path and line number
|
|
23
|
-
- Method name
|
|
24
|
-
- Current line count
|
|
25
|
-
|
|
26
|
-
If no violations at $ARGUMENTS, report success and exit.
|
|
27
|
-
|
|
28
|
-
## Step 2: Compile Brief and Delegate
|
|
29
|
-
|
|
30
|
-
Compile the gathered information into a structured brief:
|
|
31
|
-
|
|
32
|
-
```
|
|
33
|
-
Reduce max lines per method threshold to $ARGUMENTS.
|
|
34
|
-
|
|
35
|
-
Methods exceeding threshold (ordered by line count):
|
|
36
|
-
1. [file:method_name] (lines: X, target: $ARGUMENTS) - Line Y
|
|
37
|
-
2. ...
|
|
38
|
-
|
|
39
|
-
Configuration change: .rubocop.local.yml, Metrics/MethodLength Max to $ARGUMENTS
|
|
40
|
-
|
|
41
|
-
Refactoring strategies: extract methods, early returns, extract conditions, use lookup hashes, consolidate logic
|
|
42
|
-
|
|
43
|
-
Verification: `bundle exec rubocop --only Metrics/MethodLength --format simple 2>&1 | grep "offense" | wc -l` -> Expected: 0
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Invoke `/plan-execute` with this brief to create the implementation plan.
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# This file is managed by Lisa.
|
|
3
|
-
# Do not edit directly — changes will be overwritten on the next `lisa` run.
|
|
4
|
-
|
|
5
|
-
# Hook script to format files with Prettier after Claude edits them
|
|
6
|
-
# This script receives JSON input via stdin with tool information
|
|
7
|
-
# Reference: https://docs.claude.com/en/docs/claude-code/hooks
|
|
8
|
-
|
|
9
|
-
# Read the JSON input from stdin
|
|
10
|
-
JSON_INPUT=$(cat)
|
|
11
|
-
|
|
12
|
-
# Extract the file path from the tool_input
|
|
13
|
-
# The Edit tool input contains a "file_path" field in the tool_input object
|
|
14
|
-
FILE_PATH=$(echo "$JSON_INPUT" | grep -o '"tool_input":{[^}]*"file_path":"[^"]*"' | grep -o '"file_path":"[^"]*"' | cut -d'"' -f4)
|
|
15
|
-
|
|
16
|
-
# Check if we successfully extracted a file path
|
|
17
|
-
if [ -z "$FILE_PATH" ]; then
|
|
18
|
-
echo "⚠ Skipping Prettier: Could not extract file path from Edit tool input" >&2
|
|
19
|
-
exit 0 # Exit gracefully to not interrupt Claude's workflow
|
|
20
|
-
fi
|
|
21
|
-
|
|
22
|
-
# Check if the file exists
|
|
23
|
-
if [ ! -f "$FILE_PATH" ]; then
|
|
24
|
-
echo "⚠ Skipping Prettier: File does not exist: $FILE_PATH" >&2
|
|
25
|
-
exit 0 # Exit gracefully
|
|
26
|
-
fi
|
|
27
|
-
|
|
28
|
-
# Get the file extension
|
|
29
|
-
FILE_EXT="${FILE_PATH##*.}"
|
|
30
|
-
|
|
31
|
-
# Check if this is a TypeScript or JavaScript file that should be formatted
|
|
32
|
-
# Based on package.json format command: "prettier --write \"src/**/*.ts\" \"test/**/*.ts\""
|
|
33
|
-
case "$FILE_EXT" in
|
|
34
|
-
ts|tsx|js|jsx|json)
|
|
35
|
-
# File type is supported for formatting
|
|
36
|
-
;;
|
|
37
|
-
*)
|
|
38
|
-
echo "ℹ Skipping Prettier: File type .$FILE_EXT is not configured for auto-formatting"
|
|
39
|
-
exit 0
|
|
40
|
-
;;
|
|
41
|
-
esac
|
|
42
|
-
|
|
43
|
-
# Change to the project directory to ensure package manager commands work
|
|
44
|
-
cd "$CLAUDE_PROJECT_DIR" || exit 0
|
|
45
|
-
|
|
46
|
-
# Detect package manager based on lock file presence
|
|
47
|
-
detect_package_manager() {
|
|
48
|
-
if [ -f "bun.lockb" ] || [ -f "bun.lock" ]; then
|
|
49
|
-
echo "bun"
|
|
50
|
-
elif [ -f "pnpm-lock.yaml" ]; then
|
|
51
|
-
echo "pnpm"
|
|
52
|
-
elif [ -f "yarn.lock" ]; then
|
|
53
|
-
echo "yarn"
|
|
54
|
-
elif [ -f "package-lock.json" ]; then
|
|
55
|
-
echo "npm"
|
|
56
|
-
else
|
|
57
|
-
echo "npm" # Default fallback
|
|
58
|
-
fi
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
PKG_MANAGER=$(detect_package_manager)
|
|
62
|
-
|
|
63
|
-
# Run Prettier on the specific file
|
|
64
|
-
echo "🎨 Running Prettier on: $FILE_PATH"
|
|
65
|
-
$PKG_MANAGER prettier --write "$FILE_PATH" 2>&1 | grep -v "run v" | grep -v "Done in"
|
|
66
|
-
|
|
67
|
-
# Check the exit status
|
|
68
|
-
if [ ${PIPESTATUS[0]} -eq 0 ]; then
|
|
69
|
-
echo "✓ Successfully formatted: $(basename "$FILE_PATH")"
|
|
70
|
-
else
|
|
71
|
-
echo "⚠ Prettier formatting failed for: $FILE_PATH" >&2
|
|
72
|
-
echo " You may need to run '$PKG_MANAGER run format' manually to fix formatting issues." >&2
|
|
73
|
-
fi
|
|
74
|
-
|
|
75
|
-
# Always exit successfully to not interrupt Claude's workflow
|
|
76
|
-
exit 0
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# This file is managed by Lisa.
|
|
3
|
-
# Do not edit directly — changes will be overwritten on the next `lisa` run.
|
|
4
|
-
|
|
5
|
-
# Only run package installation in remote (Claude Code web) environment
|
|
6
|
-
# node_modules are gitignored, so they need to be installed remotely
|
|
7
|
-
if [ "$CLAUDE_CODE_REMOTE" != "true" ]; then
|
|
8
|
-
exit 0
|
|
9
|
-
fi
|
|
10
|
-
|
|
11
|
-
# Detect package manager based on lock file presence
|
|
12
|
-
if [ -f "bun.lockb" ] || [ -f "bun.lock" ]; then
|
|
13
|
-
bun install
|
|
14
|
-
elif [ -f "pnpm-lock.yaml" ]; then
|
|
15
|
-
pnpm install
|
|
16
|
-
elif [ -f "yarn.lock" ]; then
|
|
17
|
-
yarn install
|
|
18
|
-
elif [ -f "package-lock.json" ]; then
|
|
19
|
-
npm install
|
|
20
|
-
else
|
|
21
|
-
npm install
|
|
22
|
-
fi
|
|
23
|
-
|
|
24
|
-
# Install Gitleaks for secret detection (pre-commit hook)
|
|
25
|
-
echo "Installing Gitleaks for secret detection..."
|
|
26
|
-
GITLEAKS_VERSION="8.18.4"
|
|
27
|
-
curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" | tar -xz -C /usr/local/bin gitleaks
|
|
28
|
-
echo "Gitleaks installed: $(gitleaks version)"
|
|
29
|
-
|
|
30
|
-
# Install jira-cli for JIRA integration
|
|
31
|
-
# The tarball nests the binary at jira_VERSION_linux_x86_64/bin/jira,
|
|
32
|
-
# so we extract to a temp dir and copy the binary out.
|
|
33
|
-
echo "Installing jira-cli for JIRA integration..."
|
|
34
|
-
JIRA_CLI_VERSION="1.7.0"
|
|
35
|
-
JIRA_TMPDIR=$(mktemp -d)
|
|
36
|
-
curl -sSfL "https://github.com/ankitpokhrel/jira-cli/releases/download/v${JIRA_CLI_VERSION}/jira_${JIRA_CLI_VERSION}_linux_x86_64.tar.gz" \
|
|
37
|
-
| tar -xz -C "${JIRA_TMPDIR}"
|
|
38
|
-
cp "${JIRA_TMPDIR}/jira_${JIRA_CLI_VERSION}_linux_x86_64/bin/jira" /usr/local/bin/jira
|
|
39
|
-
chmod +x /usr/local/bin/jira
|
|
40
|
-
rm -rf "${JIRA_TMPDIR}"
|
|
41
|
-
echo "jira-cli installed: $(jira version)"
|
|
42
|
-
|
|
43
|
-
# Install Chromium for Lighthouse CI (pre-push hook)
|
|
44
|
-
# Playwright's bundled Chromium works with @lhci/cli
|
|
45
|
-
echo "Installing Chromium for Lighthouse CI..."
|
|
46
|
-
npx playwright install chromium
|
|
47
|
-
|
|
48
|
-
# Find and export CHROME_PATH for Lighthouse CI
|
|
49
|
-
# Use sort to ensure deterministic selection of the latest version
|
|
50
|
-
CHROME_PATH=$(find ~/.cache/ms-playwright -name "chrome" -type f 2>/dev/null | grep "chrome-linux" | sort | tail -n 1)
|
|
51
|
-
if [ -n "$CHROME_PATH" ]; then
|
|
52
|
-
# Append to ~/.bashrc for shell sessions (idempotent)
|
|
53
|
-
if ! grep -q "export CHROME_PATH=" ~/.bashrc 2>/dev/null; then
|
|
54
|
-
echo "export CHROME_PATH=\"$CHROME_PATH\"" >> ~/.bashrc
|
|
55
|
-
else
|
|
56
|
-
# Update existing CHROME_PATH in bashrc
|
|
57
|
-
sed -i "s|^export CHROME_PATH=.*|export CHROME_PATH=\"$CHROME_PATH\"|" ~/.bashrc
|
|
58
|
-
fi
|
|
59
|
-
|
|
60
|
-
export CHROME_PATH="$CHROME_PATH"
|
|
61
|
-
echo "Chromium installed at: $CHROME_PATH"
|
|
62
|
-
fi
|
|
63
|
-
|
|
64
|
-
exit 0
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# This file is managed by Lisa.
|
|
3
|
-
# Do not edit directly — changes will be overwritten on the next `lisa` run.
|
|
4
|
-
# =============================================================================
|
|
5
|
-
# ESLint Lint-on-Edit Hook (PostToolUse - Write|Edit)
|
|
6
|
-
# =============================================================================
|
|
7
|
-
# Runs ESLint --fix with --quiet --cache on each edited TypeScript file.
|
|
8
|
-
# Part of the inline self-correction pipeline: prettier → ast-grep → eslint.
|
|
9
|
-
#
|
|
10
|
-
# Behavior:
|
|
11
|
-
# - Exit 0: lint passes or auto-fix resolved all errors
|
|
12
|
-
# - Exit 2: unfixable errors remain — blocks Claude so it fixes them immediately
|
|
13
|
-
#
|
|
14
|
-
# @see .claude/rules/verfication.md "Self-Correction Loop" section
|
|
15
|
-
# =============================================================================
|
|
16
|
-
|
|
17
|
-
# Extract file path from JSON input
|
|
18
|
-
FILE_PATH=$(cat | grep -o '"file_path":"[^"]*"' | head -1 | cut -d'"' -f4)
|
|
19
|
-
|
|
20
|
-
if [ -z "$FILE_PATH" ] || [ ! -f "$FILE_PATH" ]; then
|
|
21
|
-
exit 0
|
|
22
|
-
fi
|
|
23
|
-
|
|
24
|
-
# Check if file type is supported (TypeScript only)
|
|
25
|
-
case "${FILE_PATH##*.}" in
|
|
26
|
-
ts|tsx) ;;
|
|
27
|
-
*) exit 0 ;;
|
|
28
|
-
esac
|
|
29
|
-
|
|
30
|
-
# Validate project directory
|
|
31
|
-
if [ -z "${CLAUDE_PROJECT_DIR:-}" ]; then
|
|
32
|
-
exit 0
|
|
33
|
-
fi
|
|
34
|
-
|
|
35
|
-
# Check if file is in a source directory
|
|
36
|
-
RELATIVE_PATH="${FILE_PATH#$CLAUDE_PROJECT_DIR/}"
|
|
37
|
-
case "$RELATIVE_PATH" in
|
|
38
|
-
src/*|apps/*|libs/*|test/*|tests/*|features/*|components/*|hooks/*|screens/*|app/*|constants/*|utils/*|providers/*|stores/*) ;;
|
|
39
|
-
*) exit 0 ;;
|
|
40
|
-
esac
|
|
41
|
-
|
|
42
|
-
cd "$CLAUDE_PROJECT_DIR" || exit 0
|
|
43
|
-
|
|
44
|
-
# Detect package manager
|
|
45
|
-
if [ -f "bun.lockb" ] || [ -f "bun.lock" ]; then
|
|
46
|
-
PKG_MANAGER="bun"
|
|
47
|
-
elif [ -f "pnpm-lock.yaml" ]; then
|
|
48
|
-
PKG_MANAGER="pnpm"
|
|
49
|
-
elif [ -f "yarn.lock" ]; then
|
|
50
|
-
PKG_MANAGER="yarn"
|
|
51
|
-
else
|
|
52
|
-
PKG_MANAGER="npm"
|
|
53
|
-
fi
|
|
54
|
-
|
|
55
|
-
# Run ESLint with --fix --quiet --cache on the specific file
|
|
56
|
-
# --quiet: suppress warnings, only show errors
|
|
57
|
-
# --cache: use ESLint cache for performance
|
|
58
|
-
echo "Running ESLint --fix on: $FILE_PATH"
|
|
59
|
-
|
|
60
|
-
# First pass: attempt auto-fix
|
|
61
|
-
OUTPUT=$($PKG_MANAGER eslint --fix --quiet --cache "$FILE_PATH" 2>&1)
|
|
62
|
-
FIX_EXIT=$?
|
|
63
|
-
|
|
64
|
-
if [ $FIX_EXIT -eq 0 ]; then
|
|
65
|
-
echo "ESLint: No errors in $(basename "$FILE_PATH")"
|
|
66
|
-
exit 0
|
|
67
|
-
fi
|
|
68
|
-
|
|
69
|
-
# Auto-fix resolved some issues but errors remain — re-run to get remaining errors
|
|
70
|
-
OUTPUT=$($PKG_MANAGER eslint --quiet --cache "$FILE_PATH" 2>&1)
|
|
71
|
-
LINT_EXIT=$?
|
|
72
|
-
|
|
73
|
-
if [ $LINT_EXIT -eq 0 ]; then
|
|
74
|
-
echo "ESLint: Auto-fixed all errors in $(basename "$FILE_PATH")"
|
|
75
|
-
exit 0
|
|
76
|
-
fi
|
|
77
|
-
|
|
78
|
-
# Unfixable errors remain — block with feedback
|
|
79
|
-
echo "ESLint found unfixable errors in: $FILE_PATH" >&2
|
|
80
|
-
echo "$OUTPUT" >&2
|
|
81
|
-
exit 2
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# This file is managed by Lisa.
|
|
3
|
-
# Do not edit directly — changes will be overwritten on the next `lisa` run.
|
|
4
|
-
|
|
5
|
-
# Hook script to run ast-grep scan after Claude edits files
|
|
6
|
-
# This script receives JSON input via stdin with tool information
|
|
7
|
-
# Reference: https://docs.claude.com/en/docs/claude-code/hooks
|
|
8
|
-
# Note: This hook is BLOCKING - it returns non-zero exit codes so Claude must fix issues
|
|
9
|
-
|
|
10
|
-
# Extract file path from JSON input
|
|
11
|
-
FILE_PATH=$(cat | grep -o '"file_path":"[^"]*"' | head -1 | cut -d'"' -f4)
|
|
12
|
-
|
|
13
|
-
if [ -z "$FILE_PATH" ] || [ ! -f "$FILE_PATH" ]; then
|
|
14
|
-
exit 0
|
|
15
|
-
fi
|
|
16
|
-
|
|
17
|
-
# Check if file type is supported (TypeScript, JavaScript)
|
|
18
|
-
case "${FILE_PATH##*.}" in
|
|
19
|
-
ts|tsx|js|jsx|mjs|cjs) ;;
|
|
20
|
-
*) exit 0 ;;
|
|
21
|
-
esac
|
|
22
|
-
|
|
23
|
-
# Validate project directory
|
|
24
|
-
if [ -z "${CLAUDE_PROJECT_DIR:-}" ]; then
|
|
25
|
-
exit 0
|
|
26
|
-
fi
|
|
27
|
-
|
|
28
|
-
# Check if file is in a source directory
|
|
29
|
-
RELATIVE_PATH="${FILE_PATH#$CLAUDE_PROJECT_DIR/}"
|
|
30
|
-
case "$RELATIVE_PATH" in
|
|
31
|
-
src/*|apps/*|libs/*|test/*|tests/*|features/*|components/*|hooks/*|screens/*|app/*|constants/*|utils/*|providers/*|stores/*) ;;
|
|
32
|
-
*) exit 0 ;;
|
|
33
|
-
esac
|
|
34
|
-
|
|
35
|
-
cd "$CLAUDE_PROJECT_DIR" || exit 0
|
|
36
|
-
|
|
37
|
-
# Verify ast-grep configuration exists
|
|
38
|
-
if [ ! -f "sgconfig.yml" ]; then
|
|
39
|
-
exit 0
|
|
40
|
-
fi
|
|
41
|
-
|
|
42
|
-
# Verify rules are defined
|
|
43
|
-
RULE_COUNT=$(find ast-grep/rules -name "*.yml" -o -name "*.yaml" 2>/dev/null | grep -v ".gitkeep" | wc -l | tr -d ' ')
|
|
44
|
-
if [ "$RULE_COUNT" -eq 0 ]; then
|
|
45
|
-
exit 0
|
|
46
|
-
fi
|
|
47
|
-
|
|
48
|
-
# Detect package manager
|
|
49
|
-
if [ -f "bun.lockb" ] || [ -f "bun.lock" ]; then
|
|
50
|
-
PKG_MANAGER="bun"
|
|
51
|
-
elif [ -f "pnpm-lock.yaml" ]; then
|
|
52
|
-
PKG_MANAGER="pnpm"
|
|
53
|
-
elif [ -f "yarn.lock" ]; then
|
|
54
|
-
PKG_MANAGER="yarn"
|
|
55
|
-
else
|
|
56
|
-
PKG_MANAGER="npm"
|
|
57
|
-
fi
|
|
58
|
-
|
|
59
|
-
# Run ast-grep scan
|
|
60
|
-
echo "Running ast-grep scan on: $FILE_PATH"
|
|
61
|
-
if OUTPUT=$($PKG_MANAGER run sg:scan "$FILE_PATH" 2>&1); then
|
|
62
|
-
echo "ast-grep: No issues found in $(basename "$FILE_PATH")"
|
|
63
|
-
exit 0
|
|
64
|
-
else
|
|
65
|
-
echo "ast-grep found issues in: $FILE_PATH" >&2
|
|
66
|
-
echo "$OUTPUT" >&2
|
|
67
|
-
exit 1
|
|
68
|
-
fi
|