@ibotor/smart-trellis 0.5.22 → 0.5.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/README.md +176 -153
  2. package/dist/cli/smart.js +3 -1
  3. package/dist/cli/smart.js.map +1 -1
  4. package/dist/commands/smart-init.d.ts +4 -1
  5. package/dist/commands/smart-init.d.ts.map +1 -1
  6. package/dist/commands/smart-init.js +96 -1
  7. package/dist/commands/smart-init.js.map +1 -1
  8. package/dist/configurators/shared.d.ts.map +1 -1
  9. package/dist/configurators/shared.js +2 -0
  10. package/dist/configurators/shared.js.map +1 -1
  11. package/dist/migrations/manifests/0.5.23.json +9 -0
  12. package/dist/templates/common/bundled-skills/trellis-dev-preflight/SKILL.md +162 -0
  13. package/dist/templates/common/bundled-skills/trellis-quality-review/SKILL.md +82 -0
  14. package/dist/templates/common/bundled-skills/trellis-quality-review/docs/overview.md +331 -0
  15. package/dist/templates/common/bundled-skills/trellis-quality-review/evals/evals.json +50 -0
  16. package/dist/templates/common/bundled-skills/trellis-quality-review/references/copy-fidelity.md +56 -0
  17. package/dist/templates/common/bundled-skills/trellis-quality-review/references/decision-tree.md +102 -0
  18. package/dist/templates/common/bundled-skills/trellis-quality-review/references/formatting-fidelity.md +37 -0
  19. package/dist/templates/common/bundled-skills/trellis-quality-review/references/framework-rules.md +59 -0
  20. package/dist/templates/common/bundled-skills/trellis-quality-review/references/report-format.md +23 -0
  21. package/dist/templates/common/bundled-skills/trellis-quality-review/references/safe-refactor-boundaries.md +158 -0
  22. package/dist/templates/common/bundled-skills/trellis-quality-review/references/scope-control.md +49 -0
  23. package/dist/templates/common/bundled-skills/trellis-quality-review/references/severity.md +105 -0
  24. package/dist/templates/common/bundled-skills/trellis-quality-review/references/small-change-fast-path.md +51 -0
  25. package/dist/templates/common/bundled-skills/trellis-quality-review/references/verification-selection.md +81 -0
  26. package/dist/templates/common/bundled-skills/trellis-quality-review/scripts/diff_scans.sh +145 -0
  27. package/dist/templates/common/bundled-skills/verification-before-completion/SKILL.md +139 -0
  28. package/dist/templates/common/commands/micro-task.md +33 -0
  29. package/dist/templates/trellis/workflow.md +1 -1
  30. package/package.json +1 -1
@@ -0,0 +1,158 @@
1
+ # Safe Refactor Boundaries
2
+
3
+ Use this reference before splitting components, extracting composables/hooks, moving helpers, or changing ownership. The goal is to reduce responsibility pile-up without creating abstraction churn or expanding beyond the current diff.
4
+
5
+ ## Core Rule
6
+
7
+ Refactor only when it improves the current requirement's clarity, correctness, or maintainability inside the review boundary. File size alone is not enough.
8
+
9
+ A safe refactor has all of these properties:
10
+
11
+ - The problematic responsibility is touched by the current diff.
12
+ - The target boundary is obvious and nameable.
13
+ - The extracted interface is smaller than the code it hides.
14
+ - The move does not require unrelated callers, routes, stores, styles, or tests to change.
15
+ - Behavior, copy, layout, and public contracts remain unchanged unless required.
16
+ - Verification can cover the moved logic or affected render path.
17
+
18
+ ## Strong Signals to Split or Extract
19
+
20
+ Consider a targeted split when at least one is true:
21
+
22
+ - A page/container now owns orchestration plus multiple changed UI sections.
23
+ - A component now mixes rendering with request orchestration, validation, mapping, and modal/table/form state touched by this requirement.
24
+ - The current diff duplicates non-trivial logic in two or more places.
25
+ - Newly added side effects make the render component hard to follow.
26
+ - Newly added pure mapping/formatting/validation logic obscures the UI path.
27
+ - A modal/drawer/wizard section has its own state, validation, and actions that can be named independently.
28
+ - A hook/composable would isolate stateful behavior used by the current feature without becoming a generic utility.
29
+
30
+ ## Strong Signals Not to Refactor
31
+
32
+ Avoid structural refactor when any is true:
33
+
34
+ - The file is merely large, but the current change touches a small localized area.
35
+ - The split would require moving unrelated markup, styles, tests, or callers.
36
+ - The extracted function/component would have many props or return values just to keep behavior working.
37
+ - The new abstraction would be used once and does not hide meaningful complexity.
38
+ - Naming the boundary requires vague words like `Common`, `Base`, `Manager`, `Handler`, or `Utils`.
39
+ - The refactor would change user-visible copy, layout, option order, focus behavior, or event timing.
40
+ - The user requested a micro-change or explicitly asked to avoid broad cleanup.
41
+
42
+ ## Boundary Heuristics
43
+
44
+ ### Page / Route / Container
45
+
46
+ Should own:
47
+
48
+ - route params and navigation glue
49
+ - top-level data loading orchestration
50
+ - composition of feature sections
51
+ - passing typed props and event handlers to children
52
+
53
+ Should not accumulate:
54
+
55
+ - multiple independent UI sections with detailed markup
56
+ - modal internals
57
+ - table cell formatting details
58
+ - form field validation internals
59
+ - low-level API payload mapping when it obscures orchestration
60
+
61
+ ### Component
62
+
63
+ Should own:
64
+
65
+ - one nameable UI section
66
+ - local UI state for that section
67
+ - typed props/events or callbacks
68
+ - minimal formatting needed for display
69
+
70
+ Extract when the component contains multiple independently nameable regions touched by this requirement, such as search form + table + edit modal + upload drawer.
71
+
72
+ Do not extract when the child would only wrap a few lines and add prop plumbing without hiding complexity.
73
+
74
+ ### Composable / Hook
75
+
76
+ Should own:
77
+
78
+ - stateful logic and side effects
79
+ - async request lifecycle
80
+ - derived state tied to the feature
81
+ - event handlers whose behavior is not just presentational
82
+
83
+ Good candidates:
84
+
85
+ - `useUserTableData`
86
+ - `useDomainForm`
87
+ - `useUploadDialog`
88
+
89
+ Weak candidates:
90
+
91
+ - `useHelpers`
92
+ - `useCommon`
93
+ - `usePageLogic`
94
+ - a hook returning 15 unrelated values
95
+
96
+ ### Helper
97
+
98
+ Should own pure logic:
99
+
100
+ - formatters
101
+ - mappers
102
+ - validators
103
+ - sort/filter predicates
104
+ - small calculations
105
+
106
+ Keep helpers local when used only by one component/composable. Move to a separate file only when the helper is non-trivial, reused by current-work code, or makes the owning file materially clearer.
107
+
108
+ ### Types
109
+
110
+ Keep feature-local types near the owning component/composable when they are not reused.
111
+
112
+ Move types to shared files only when:
113
+
114
+ - multiple current-work files consume them
115
+ - they represent API or route/store boundaries
116
+ - colocating them would create import cycles or unclear ownership
117
+
118
+ ## Vue-Specific Guidance
119
+
120
+ - Prefer `<script setup>` and typed props/emits when the project uses that style.
121
+ - Keep section-local refs in the section component unless parent orchestration needs them.
122
+ - Extract a composable when state transitions, async effects, watchers, or derived state dominate the component.
123
+ - Avoid Pinia for one-off UI state; use Pinia when state is shared across routes/features or must outlive the component.
124
+ - Avoid composables that return large bags of unrelated refs; split by feature behavior instead.
125
+
126
+ ## React / Next-Specific Guidance
127
+
128
+ - Keep route/page components focused on orchestration and server/client boundary correctness.
129
+ - Do not add `use client` broadly just to support a small interactive child; prefer isolating the client component when feasible and in scope.
130
+ - Extract a hook when stateful behavior or side effects obscure the component body.
131
+ - Extract a component when a nameable UI section has its own props and events.
132
+ - Do not add `useMemo`/`useCallback` as a refactor unless identity stability or render cost is a real current-diff concern.
133
+
134
+ ## Safe Refactor Procedure
135
+
136
+ 1. Name the responsibility that is piled up.
137
+ 2. Confirm it is touched by the current requirement.
138
+ 3. Choose the smallest boundary that hides complexity without leaking many props/returns.
139
+ 4. Preserve public behavior, copy, layout, and event timing.
140
+ 5. Move only the directly related code.
141
+ 6. Re-run the smallest relevant verification from `verification-selection.md`.
142
+ 7. If any step requires broad unrelated edits, stop and record the idea as Note Only.
143
+
144
+ ## Reporting
145
+
146
+ When you refactor, report why the boundary was safe:
147
+
148
+ ```text
149
+ Changed:
150
+ - Extracted EditDomainModal because the current diff added independent modal state, validation, and submit handling; parent now only orchestrates open/close and refresh.
151
+ ```
152
+
153
+ When you do not refactor, report why not when relevant:
154
+
155
+ ```text
156
+ Severity:
157
+ - Should Fix: did not split SettingsPage because the large table section was pre-existing and untouched by this request.
158
+ ```
@@ -0,0 +1,49 @@
1
+ # Scope Control
2
+
3
+ Use this gate before any cleanup or refactor. The purpose is to protect the user's requested change from scope creep.
4
+
5
+ ## Default Rule
6
+
7
+ Change only what the requirement asks for, plus the smallest necessary adjacent code to keep it correct, typed, lint-clean, or buildable.
8
+
9
+ Do not opportunistically optimize, polish, reorder, refactor, rename, reformat, or clean up code the requirement does not touch.
10
+
11
+ Preserve existing user-visible text, helper descriptions, option order, placeholders, tooltips, validation messages, comments, and layout unless the requirement explicitly asks to change them or the feature cannot work without the change.
12
+
13
+ If the user says “do not change anything not mentioned”, treat all non-required UI/text changes as high-risk and list them explicitly in the review.
14
+
15
+ ## Gate Steps
16
+
17
+ 1. Restate the current requirement in one sentence.
18
+ 2. Inspect `git status` and `git diff HEAD` before editing.
19
+ 3. Classify each changed block:
20
+ - **In requirement:** directly implements or verifies the requested change.
21
+ - **Necessary adjacent:** required to keep the requested change correct, typed, lint-clean, or buildable.
22
+ - **Out of scope:** opportunistic old-code optimization, unrelated formatting, broad refactor, unrelated dead-code cleanup, renamed abstractions, style changes, user-visible copy changes, helper-description changes, or option-order changes not needed by the requirement.
23
+ 4. Only edit **In requirement** and **Necessary adjacent** blocks.
24
+ 5. For **Out of scope** blocks, do not extend the change.
25
+ 6. Revert your own out-of-scope edits when safe.
26
+ 7. If an out-of-scope edit predates the session or ownership is unclear, leave it untouched and mention it in Notes.
27
+ 8. If classification is unclear and would change more code, ask the user instead of deciding silently.
28
+
29
+ ## Responsibility Map
30
+
31
+ Use this map to decide whether structure changes are justified:
32
+
33
+ - **route/page/container:** orchestration, data loading, high-level composition
34
+ - **component:** one UI section with typed props/emits or typed component props/callbacks
35
+ - **composable/hook:** stateful logic, side effects, derived state, lifecycle coordination
36
+ - **helper:** pure feature-local logic
37
+ - **api/types:** external boundary and shared contracts
38
+
39
+ Split only when the current requirement created unclear ownership or repeated logic. Keep feature-local types/helpers near the owning unit unless reused broadly.
40
+
41
+ ## Common Scope Mistakes
42
+
43
+ | Mistake | Correction |
44
+ | --- | --- |
45
+ | Optimizing old code during requirement review | Record it in Notes unless it blocks the current requirement |
46
+ | Splitting every type/helper into standalone files | Keep local helpers local unless reused |
47
+ | Moving UI state into parent unnecessarily | Keep section-local state near the section |
48
+ | Letting old violations expand scope | Fix only newly introduced violations unless adjacent legacy code blocks correctness |
49
+ | Trusting visual refactor | Preserve behavior and verify with commands |
@@ -0,0 +1,105 @@
1
+ # Severity
2
+
3
+ Classify findings before fixing them. Severity applies to the current review boundary: default to `git diff HEAD` unless the user requested staged-only or a specific base ref. Historical or untouched issues are usually Note Only unless they block the current requirement.
4
+
5
+ ## Levels
6
+
7
+ ### Blocker
8
+
9
+ Must be fixed before handoff. The current diff introduces or exposes a problem that can break build, typecheck, runtime behavior, critical user flow, permissions, data integrity, or security.
10
+
11
+ Frontend examples:
12
+
13
+ - current diff causes build, typecheck, or required test failure
14
+ - key page crashes or fails to render
15
+ - form cannot submit, primary action cannot be clicked, or required user flow is broken
16
+ - API payload or response mapping is wrong for the changed feature
17
+ - permission/auth guard is loosened or bypassed
18
+ - Next.js server/client boundary error prevents render or build
19
+ - changed props/types break touched consumers
20
+ - unsanitized user-controlled `dangerouslySetInnerHTML` or equivalent XSS risk
21
+ - production-executed `debugger`
22
+
23
+ Action: fix in the current review if possible, rerun relevant verification, and report as blocking if not resolved.
24
+
25
+ ### Must Fix Before Handoff
26
+
27
+ Should be fixed before delivery when introduced by the current diff, even if it does not immediately fail build.
28
+
29
+ Frontend examples:
30
+
31
+ - added `console.log`, `debugger`, unexplained `@ts-ignore`, `@ts-expect-error`, or broad `eslint-disable`
32
+ - current-work dead code: unused props, emits, refs, state, imports, branches, mock fields
33
+ - out-of-scope user-visible copy, helper text, placeholder, validation message, or option-order changes
34
+ - out-of-scope formatting churn mixed into the diff
35
+ - current diff introduces obvious duplicated logic that can be removed locally
36
+ - local UI state was lifted or globalized without requirement support
37
+ - newly added loading/error state is never rendered or consumed
38
+ - temporary mock/demo data is scattered in production components
39
+
40
+ Action: fix when ownership is clear and the fix stays inside the requirement boundary. If ownership is unclear, record in Notes instead of expanding scope.
41
+
42
+ ### Should Fix If In Scope
43
+
44
+ Real issue, but fix only when it is clearly within the current requirement and the change is small.
45
+
46
+ Frontend examples:
47
+
48
+ - unclear name in newly added function, prop, event, or variable
49
+ - newly added condition is hard to read but safe
50
+ - new component is somewhat large but not yet clearly multi-responsibility
51
+ - duplicated new snippet appears twice and a local helper would clarify it
52
+ - type could be narrower, but current type is safe
53
+ - composable/hook return shape is slightly broad but still understandable
54
+ - helper extraction would improve clarity but requires moving files or touching callers
55
+ - tests are not ideal, but selected verification covers the main changed path
56
+
57
+ Action: fix only if the edit is small and does not expand scope. Otherwise mention as a follow-up Note.
58
+
59
+ ### Note Only
60
+
61
+ Do not fix during this review. The issue is historical, untouched, unclear ownership, or not needed for the current requirement.
62
+
63
+ Frontend examples:
64
+
65
+ - old component is large but this task touched only a tiny unrelated line
66
+ - historical lint/typecheck/test failures
67
+ - old copy inconsistency
68
+ - legacy form validation pattern
69
+ - old API layer or directory structure concerns
70
+ - untouched hook/composable design issue
71
+ - existing `any`, formatter churn, or test gap not introduced by the current diff
72
+
73
+ Action: record briefly in Notes when useful. Do not mark the current task failed unless it blocks the current requirement.
74
+
75
+ ## Classification Flow
76
+
77
+ 1. **Was it introduced or exposed by the current review diff?**
78
+ - No: Note Only, unless it blocks the current requirement.
79
+ - Yes: continue.
80
+
81
+ 2. **Can it break build, typecheck, runtime behavior, critical flow, permissions, data integrity, or security?**
82
+ - Yes: Blocker.
83
+ - No: continue.
84
+
85
+ 3. **Is it current-work debug code, unexplained suppression, dead code, out-of-scope copy, or out-of-scope formatting?**
86
+ - Yes: Must Fix Before Handoff.
87
+ - No: continue.
88
+
89
+ 4. **Is the fix small, local, and inside the current requirement boundary?**
90
+ - Yes: Should Fix If In Scope.
91
+ - No: Note Only.
92
+
93
+ ## Reporting
94
+
95
+ Keep severity concise. Prefer counts and high-signal examples over long lists.
96
+
97
+ Example:
98
+
99
+ ```text
100
+ Severity:
101
+ - Blocker: none
102
+ - Must Fix: removed added console.log; restored out-of-scope placeholder change
103
+ - Should Fix: did not split SettingsPanel because it would touch unrelated sections
104
+ - Note Only: pre-existing vue-tsc errors in src/legacy/* are unrelated to touched files
105
+ ```
@@ -0,0 +1,51 @@
1
+ # Small-Change Fast Path
2
+
3
+ Use this path for tiny, low-risk frontend changes where full quality review would create more churn than value.
4
+
5
+ ## Qualifying Changes
6
+
7
+ A change qualifies only when all are true:
8
+
9
+ - The user's request is narrow and explicit.
10
+ - The diff is limited to one file or a very small localized area.
11
+ - The change does not affect API shape, routing, permissions, state flow, data transformation, validation behavior, dependency configuration, or shared types.
12
+ - The change is easy to verify by reading the diff.
13
+ - No suspicious added lines appear, such as `console.log`, `debugger`, `@ts-ignore`, `eslint-disable`, `TODO`, or `FIXME`.
14
+
15
+ Common qualifying examples:
16
+
17
+ - UI spacing, width, color, or alignment constants
18
+ - single label/copy change explicitly requested by the user
19
+ - table column width/order requested by the user
20
+ - small style/class adjustment
21
+ - single local config flag with no behavior cascade
22
+
23
+ ## Disqualifiers
24
+
25
+ Do not use the fast path if any are true:
26
+
27
+ - The change affects component boundaries, composables/hooks, stores, route logic, API calls, form validation, permissions, upload/download behavior, or data mapping.
28
+ - The diff spans multiple modules or shared abstractions.
29
+ - The change introduces or edits TypeScript types used outside the local file.
30
+ - The diff includes unrelated formatting or copy churn.
31
+ - The user asks for a full review, cleanup, refactor, verification, or confidence before handoff.
32
+ - The project currently has failing diagnostics that may be related to the touched code.
33
+
34
+ ## Fast Path Procedure
35
+
36
+ 1. Restate the small requirement in one sentence.
37
+ 2. Inspect the relevant diff only.
38
+ 3. Confirm the diff contains only the requested localized change.
39
+ 4. Do not run broad lint, typecheck, unit tests, or build by default.
40
+ 5. If a minimal targeted command is obvious and cheap, run it only when it directly validates the change.
41
+ 6. Report that the fast path was used and whether verification was limited to diff inspection.
42
+
43
+ ## Required Final Note
44
+
45
+ When using this path, include a short note like:
46
+
47
+ ```text
48
+ Used small-change fast path: skipped lint/typecheck/test/build because the diff is a localized UI/copy/config change and diff inspection confirmed scope.
49
+ ```
50
+
51
+ If the diff inspection finds scope expansion, leave the fast path and return to the normal decision tree.
@@ -0,0 +1,81 @@
1
+ # Verification Selection
2
+
3
+ Use this reference before reporting completion or correctness. The goal is to choose the smallest verification set that gives confidence for the current frontend diff without expanding into unrelated legacy cleanup.
4
+
5
+ ## Core Rule
6
+
7
+ Verification should match the risk introduced by the current diff:
8
+
9
+ - Tiny localized UI/copy/style/config changes can use the small-change fast path and diff inspection only.
10
+ - Type, data, state, validation, routing, API, component-boundary, or framework-boundary changes need targeted commands.
11
+ - Full build is reserved for changes that affect bundling, routes/pages, framework config, server/client boundaries, or when lighter checks cannot cover the risk.
12
+
13
+ Always inspect project scripts and nearby docs/config before inventing commands.
14
+
15
+ ## Command Discovery Order
16
+
17
+ Prefer project-defined scripts over raw tool invocations:
18
+
19
+ 1. Read `package.json` scripts.
20
+ 2. Check project docs or local agent instructions if already relevant to the task.
21
+ 3. Check framework config only when needed: `vite.config.*`, `next.config.*`, `tsconfig*.json`, `eslint.config.*`, `.eslintrc*`, `vitest.config.*`, `jest.config.*`, `playwright.config.*`.
22
+ 4. Prefer the package manager already used by the project: lockfiles and scripts reveal `pnpm`, `npm`, `yarn`, or `bun`.
23
+
24
+ Do not add dependencies or modify configs just to run verification.
25
+
26
+ ## Selection Matrix
27
+
28
+ | Diff signal | Verification default |
29
+ | --- | --- |
30
+ | Small-change fast path | Diff inspection only; no broad lint/typecheck/test/build by default |
31
+ | `.vue` template/script/style changes | Project lint plus Vue/typecheck script when available, such as `vue-tsc` or `typecheck` |
32
+ | Vue props/emits/composable/store changes | Typecheck plus targeted tests if present |
33
+ | React/TSX component changes | Project lint plus TypeScript check when available |
34
+ | Next.js route/page/server-client boundary changes | Lint/typecheck plus build when boundary or route behavior risk is meaningful |
35
+ | Type definitions or shared contracts changed | Typecheck; targeted tests for consumers when present |
36
+ | Form validation, data mapping, formatter, parser, permission logic | Targeted unit tests; typecheck if TypeScript is involved |
37
+ | API call shape or request/response mapping changed | Typecheck plus targeted integration/unit tests if available |
38
+ | Styling-only but not fast-path | Scoped lint/style check if project has one; otherwise diff inspection plus optional visual/manual note |
39
+ | Suspicious added debug/type-suppression lines fixed | Re-run the scan or scoped lint that would catch the issue |
40
+ | Formatter conflict | Prefer scoped lint with formatting rules disabled when preserving scope; report the conflict |
41
+
42
+ ## Running Strategy
43
+
44
+ 1. Start with the narrowest command that covers the changed files or feature.
45
+ 2. Prefer targeted tests over full test suites when a clear target exists.
46
+ 3. Run full lint/typecheck/build only when the diff risk justifies it or project scripts are fast and standard.
47
+ 4. If a command is unavailable, do not invent a replacement blindly; report that no matching script was found.
48
+ 5. If the user explicitly asked to skip verification, skip it and report that instruction.
49
+
50
+ ## Failure Handling
51
+
52
+ When a command fails:
53
+
54
+ 1. Read the output and identify the failing file or test.
55
+ 2. Decide whether the failure is related to the current diff.
56
+ 3. If related, fix within scope and rerun the relevant command.
57
+ 4. If unrelated or historical, do not expand scope; report it under Notes with evidence.
58
+ 5. Do not claim verification passed if any required command failed.
59
+ 6. If partial verification passed, say exactly which commands passed and which failed.
60
+
61
+ ## Final Report Evidence
62
+
63
+ In the `Verified` section, include:
64
+
65
+ - exact command
66
+ - exit status
67
+ - short result summary
68
+ - if skipped, the explicit reason
69
+
70
+ Examples:
71
+
72
+ ```text
73
+ Verified:
74
+ - `pnpm lint -- src/pages/Settings.vue` exited 0.
75
+ - `pnpm vue-tsc --noEmit` exited 1 due to pre-existing errors in src/legacy/*; no errors referenced the touched files.
76
+ ```
77
+
78
+ ```text
79
+ Verified:
80
+ - Used small-change fast path: skipped lint/typecheck/test/build because only one table column width changed and diff inspection confirmed scope.
81
+ ```
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ mode="base"
5
+ base_ref="HEAD"
6
+ json=0
7
+ files_only=0
8
+
9
+ usage() {
10
+ cat <<'EOF'
11
+ Usage: diff_scans.sh [--base REF] [--cached] [--files] [--json]
12
+
13
+ Modes:
14
+ --base REF Scan git diff against REF. Defaults to HEAD.
15
+ --cached Scan staged changes.
16
+ --files Only print changed frontend files.
17
+ --json Print a JSON summary instead of sectioned text.
18
+ -h, --help Show this help.
19
+ EOF
20
+ }
21
+
22
+ while [[ $# -gt 0 ]]; do
23
+ case "$1" in
24
+ --base)
25
+ mode="base"
26
+ base_ref="${2:?--base requires a ref}"
27
+ shift 2
28
+ ;;
29
+ --cached|--staged)
30
+ mode="cached"
31
+ shift
32
+ ;;
33
+ --files)
34
+ files_only=1
35
+ shift
36
+ ;;
37
+ --json)
38
+ json=1
39
+ shift
40
+ ;;
41
+ -h|--help)
42
+ usage
43
+ exit 0
44
+ ;;
45
+ *)
46
+ mode="base"
47
+ base_ref="$1"
48
+ shift
49
+ ;;
50
+ esac
51
+ done
52
+
53
+ frontend_globs=(-- '*.vue' '*.ts' '*.tsx' '*.jsx' '*.js' '*.css' '*.scss')
54
+ code_globs=(-- '*.vue' '*.ts' '*.tsx' '*.jsx' '*.js')
55
+
56
+ git_diff() {
57
+ if [[ "$mode" == "cached" ]]; then
58
+ git diff --cached "$@"
59
+ else
60
+ git diff "$base_ref" "$@"
61
+ fi
62
+ }
63
+
64
+ diff_label() {
65
+ if [[ "$mode" == "cached" ]]; then
66
+ echo "--cached"
67
+ else
68
+ echo "$base_ref"
69
+ fi
70
+ }
71
+
72
+ json_array() {
73
+ python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().splitlines()))'
74
+ }
75
+
76
+ json_string() {
77
+ python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))'
78
+ }
79
+
80
+ changed_files() {
81
+ git_diff --name-only --diff-filter=ACMRTUXB "${frontend_globs[@]}" || true
82
+ }
83
+
84
+ scan() {
85
+ local title="$1"
86
+ local pattern="$2"
87
+ shift 2
88
+ echo
89
+ echo "== $title =="
90
+ git_diff -U0 "$@" | rg "$pattern" || true
91
+ }
92
+
93
+ if [[ "$files_only" -eq 1 && "$json" -eq 0 ]]; then
94
+ changed_files
95
+ exit 0
96
+ fi
97
+
98
+ if [[ "$json" -eq 1 ]]; then
99
+ files="$(changed_files)"
100
+ suspicious="$(git_diff -U0 "${code_globs[@]}" | rg '^\+[^+].*(eslint-disable|@ts-ignore|@ts-expect-error|console\.log|debugger|TODO|FIXME)' || true)"
101
+ ts_risks="$(git_diff -U0 "${code_globs[@]}" | rg '^\+[^+].*(:\s*any\b|as\s+any\b|as\s+unknown\s+as|!\.|\w!\b)' || true)"
102
+ vue_risks="$(git_diff -U0 -- '*.vue' | rg '^\+[^+].*(v-model:|watch\s*\([^\n]*deep\s*:\s*true|defineProps\([^\n]*\)\.[A-Za-z_$][\w$]*\s*=)' || true)"
103
+ react_next_risks="$(git_diff -U0 "${code_globs[@]}" | rg '^\+[^+].*(use client|dangerouslySetInnerHTML|window\.|document\.|localStorage\.|sessionStorage\.)' || true)"
104
+ copy_changes="$(git_diff -U0 "${code_globs[@]}" | rg '^[+-][^+-].*(label|title|placeholder|help|message|Radio|Checkbox|Button|Tooltip|content|confirmText|cancelText|text-|aria-label|alt=|请选择|请输入|验证|账户|服务商|域名|说明|提示)' || true)"
105
+
106
+ printf '{\n'
107
+ printf ' "mode": %s,\n' "$(printf '%s' "$(diff_label)" | json_string)"
108
+ printf ' "changed_files": %s,\n' "$(printf '%s' "$files" | json_array)"
109
+ printf ' "suspicious_patterns": %s,\n' "$(printf '%s' "$suspicious" | json_array)"
110
+ printf ' "typescript_risks": %s,\n' "$(printf '%s' "$ts_risks" | json_array)"
111
+ printf ' "vue_risks": %s,\n' "$(printf '%s' "$vue_risks" | json_array)"
112
+ printf ' "react_next_risks": %s,\n' "$(printf '%s' "$react_next_risks" | json_array)"
113
+ printf ' "potential_copy_changes": %s\n' "$(printf '%s' "$copy_changes" | json_array)"
114
+ printf '}\n'
115
+ exit 0
116
+ fi
117
+
118
+ label="$(diff_label)"
119
+
120
+ echo "== Diff scan mode =="
121
+ echo "$label"
122
+
123
+ echo
124
+ echo "== Changed frontend files =="
125
+ changed_files
126
+
127
+ scan "Added-line suspicious patterns" '^\+[^+].*(eslint-disable|@ts-ignore|@ts-expect-error|console\.log|debugger|TODO|FIXME)' "${code_globs[@]}"
128
+
129
+ scan "TypeScript risk patterns on added lines" '^\+[^+].*(:\s*any\b|as\s+any\b|as\s+unknown\s+as|!\.|\w!\b)' "${code_globs[@]}"
130
+
131
+ scan "Vue risk patterns on added lines" '^\+[^+].*(v-model:|watch\s*\([^\n]*deep\s*:\s*true|defineProps\([^\n]*\)\.[A-Za-z_$][\w$]*\s*=)' -- '*.vue'
132
+
133
+ scan "React/Next/browser-boundary risk patterns on added lines" '^\+[^+].*(use client|dangerouslySetInnerHTML|window\.|document\.|localStorage\.|sessionStorage\.)' "${code_globs[@]}"
134
+
135
+ scan "Potential copy/accessibility text changes" '^[+-][^+-].*(label|title|placeholder|help|message|Radio|Checkbox|Button|Tooltip|content|confirmText|cancelText|text-|aria-label|alt=|请选择|请输入|验证|账户|服务商|域名|说明|提示)' "${code_globs[@]}"
136
+
137
+ echo
138
+ echo "== Formatting check hint =="
139
+ echo "For each modified existing file, compare:"
140
+ echo " git diff $label -- path/to/file"
141
+ if [[ "$mode" == "cached" ]]; then
142
+ echo " git diff --cached -w -- path/to/file"
143
+ else
144
+ echo " git diff -w $base_ref -- path/to/file"
145
+ fi