@ryuenn3123/agentic-senior-core 4.4.0 → 5.2.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/.agents/plugins/agentic-senior-core/plugin.json +3 -0
- package/.agents/plugins/agentic-senior-core/rules/agentic-senior-core.md +131 -0
- package/.agents/plugins/agentic-senior-core/skills/asc/SKILL.md +16 -0
- package/.agents/plugins/agentic-senior-core/skills/asc-audit/SKILL.md +28 -0
- package/.agents/plugins/agentic-senior-core/skills/asc-refactor/SKILL.md +35 -0
- package/.agents/plugins/agentic-senior-core/skills/asc-review/SKILL.md +54 -0
- package/.agents/rules/agentic-senior-core.md +131 -0
- package/.claude-plugin/marketplace.json +17 -0
- package/.claude-plugin/plugin.json +17 -0
- package/.clinerules/agentic-senior-core.md +94 -0
- package/.codex-plugin/plugin.json +24 -0
- package/.cursor/rules/agentic-senior-core.mdc +99 -0
- package/.devin-plugin/plugin.json +13 -0
- package/.github/copilot-instructions.md +94 -0
- package/.github/plugin/marketplace.json +20 -0
- package/.github/plugin/plugin.json +16 -0
- package/.kiro/steering/agentic-senior-core.md +94 -0
- package/.openclaw/skills/asc/SKILL.md +23 -0
- package/.openclaw/skills/asc-audit/SKILL.md +28 -0
- package/.openclaw/skills/asc-review/SKILL.md +54 -0
- package/.opencode/plugins/agentic-senior-core.mjs +31 -0
- package/.windsurf/rules/agentic-senior-core.md +94 -0
- package/AGENTS.md +126 -127
- package/CONTRIBUTING.md +93 -63
- package/README.md +190 -110
- package/__init__.py +61 -0
- package/bin/agentic-senior-core.js +42 -41
- package/commands/asc-audit.md +1 -0
- package/commands/asc-audit.toml +2 -0
- package/commands/asc-help.md +9 -0
- package/commands/asc-help.toml +2 -0
- package/commands/asc-refactor.md +1 -0
- package/commands/asc-refactor.toml +2 -0
- package/commands/asc-review.md +1 -0
- package/commands/asc-review.toml +2 -0
- package/gemini-extension.json +10 -0
- package/hooks/copilot-hooks.json +21 -0
- package/hooks/hooks.json +31 -0
- package/hooks/session-start.js +36 -0
- package/hooks/subagent-start.js +38 -0
- package/lib/cli/commands/adapter.mjs +109 -0
- package/lib/cli/commands/clean.mjs +63 -0
- package/lib/cli/commands/status.mjs +94 -0
- package/package.json +43 -60
- package/plugin.yaml +16 -0
- package/scripts/uninstall.js +38 -0
- package/skills/asc/SKILL.md +16 -0
- package/skills/asc-audit/SKILL.md +28 -0
- package/skills/asc-refactor/SKILL.md +35 -0
- package/skills/asc-review/SKILL.md +54 -0
- package/.agent-context/policies/llm-judge-threshold.json +0 -29
- package/.agent-context/prompts/bootstrap-design.md +0 -63
- package/.agent-context/prompts/compact-natural-mode.md +0 -100
- package/.agent-context/prompts/init-project.md +0 -60
- package/.agent-context/prompts/refactor.md +0 -38
- package/.agent-context/prompts/review-code.md +0 -31
- package/.agent-context/review-checklists/architecture-review.md +0 -57
- package/.agent-context/review-checklists/pr-checklist.md +0 -134
- package/.agent-context/rules/api-docs.md +0 -24
- package/.agent-context/rules/api-versioning.md +0 -16
- package/.agent-context/rules/architecture.md +0 -38
- package/.agent-context/rules/background-jobs.md +0 -17
- package/.agent-context/rules/config-and-flags.md +0 -16
- package/.agent-context/rules/database-design.md +0 -18
- package/.agent-context/rules/docker-runtime.md +0 -17
- package/.agent-context/rules/error-handling.md +0 -16
- package/.agent-context/rules/event-driven.md +0 -16
- package/.agent-context/rules/frontend-architecture.md +0 -54
- package/.agent-context/rules/microservices.md +0 -16
- package/.agent-context/rules/migrations.md +0 -16
- package/.agent-context/rules/observability.md +0 -16
- package/.agent-context/rules/performance.md +0 -16
- package/.agent-context/rules/realtime.md +0 -16
- package/.agent-context/rules/resilience.md +0 -18
- package/.agent-context/rules/security.md +0 -18
- package/.agent-context/rules/testing.md +0 -16
- package/.agent-context/state/README.md +0 -25
- package/.agent-context/state/architecture-map.md +0 -40
- package/.agent-context/state/benchmark-comparison-schema.json +0 -181
- package/.agent-context/state/benchmark-reproducibility.json +0 -87
- package/.agent-context/state/benchmark-thresholds.json +0 -10
- package/.agent-context/state/benchmark-writer-judge-config.json +0 -58
- package/.agent-context/state/dependency-map.md +0 -41
- package/.agent-context/state/memory-adapter-contract.json +0 -52
- package/.agent-context/state/memory-schema-v1.json +0 -88
- package/GEMINI.md +0 -1
- package/benchmarks/README.md +0 -60
- package/benchmarks/compact-natural-mode/fixtures.mjs +0 -359
- package/benchmarks/compact-natural-mode/scorer.mjs +0 -331
- package/benchmarks/runtime-token-saver/fixtures.mjs +0 -836
- package/lib/cli/adaptive-context/catalog.mjs +0 -394
- package/lib/cli/adaptive-context/file-signals.mjs +0 -100
- package/lib/cli/adaptive-context/implications.mjs +0 -44
- package/lib/cli/adaptive-context.mjs +0 -151
- package/lib/cli/audits/typography-palette-anti-repeat/color-utils.mjs +0 -156
- package/lib/cli/audits/typography-palette-anti-repeat/file-scanner.mjs +0 -103
- package/lib/cli/audits/typography-palette-anti-repeat/typography-utils.mjs +0 -70
- package/lib/cli/backup.mjs +0 -210
- package/lib/cli/commands/context.mjs +0 -140
- package/lib/cli/commands/init/project-context.mjs +0 -60
- package/lib/cli/commands/init/runtime-environment.mjs +0 -59
- package/lib/cli/commands/init/setup-decisions.mjs +0 -83
- package/lib/cli/commands/init.mjs +0 -654
- package/lib/cli/commands/launch.mjs +0 -76
- package/lib/cli/commands/optimize.mjs +0 -284
- package/lib/cli/commands/rollback.mjs +0 -64
- package/lib/cli/commands/upgrade/token-optimization-state.mjs +0 -51
- package/lib/cli/commands/upgrade.mjs +0 -451
- package/lib/cli/compiler.mjs +0 -187
- package/lib/cli/constants.mjs +0 -136
- package/lib/cli/detector/constants.mjs +0 -135
- package/lib/cli/detector/design-evidence/collector.mjs +0 -256
- package/lib/cli/detector/design-evidence/constants.mjs +0 -39
- package/lib/cli/detector/design-evidence/file-traversal.mjs +0 -83
- package/lib/cli/detector/design-evidence/structured-attribute-evidence.mjs +0 -117
- package/lib/cli/detector/design-evidence/summary.mjs +0 -109
- package/lib/cli/detector/design-evidence/utility-helpers.mjs +0 -122
- package/lib/cli/detector/design-evidence.mjs +0 -25
- package/lib/cli/detector/stack-detection.mjs +0 -243
- package/lib/cli/detector/ui-signals.mjs +0 -150
- package/lib/cli/detector/workspace-scan.mjs +0 -177
- package/lib/cli/detector.mjs +0 -23
- package/lib/cli/init-detection-flow.mjs +0 -48
- package/lib/cli/init-options.mjs +0 -237
- package/lib/cli/init-selection.mjs +0 -29
- package/lib/cli/memory-continuity.mjs +0 -537
- package/lib/cli/preflight.mjs +0 -76
- package/lib/cli/project-scaffolder/constants.mjs +0 -69
- package/lib/cli/project-scaffolder/discovery.mjs +0 -272
- package/lib/cli/project-scaffolder/prompt-builders.mjs +0 -171
- package/lib/cli/project-scaffolder/storage.mjs +0 -144
- package/lib/cli/project-scaffolder/ui-scope-detection.mjs +0 -36
- package/lib/cli/project-scaffolder.mjs +0 -29
- package/lib/cli/rollback.mjs +0 -66
- package/lib/cli/token-optimization.mjs +0 -401
- package/lib/cli/utils/filesystem.mjs +0 -81
- package/lib/cli/utils/managed-surface.mjs +0 -280
- package/lib/cli/utils/prompting.mjs +0 -44
- package/lib/cli/utils.mjs +0 -479
- package/mcp.json +0 -134
- package/scripts/adaptive-context/fixtures.mjs +0 -183
- package/scripts/adaptive-context-benchmark.mjs +0 -9
- package/scripts/ascx-runtime-token-saver-benchmark.mjs +0 -9
- package/scripts/benchmark-evidence-bundle.mjs +0 -645
- package/scripts/benchmark-gate.mjs +0 -121
- package/scripts/benchmark-intelligence.mjs +0 -33
- package/scripts/benchmark-writer-judge-matrix.mjs +0 -379
- package/scripts/build-release-benchmark-bundle.mjs +0 -202
- package/scripts/bump-version.mjs +0 -103
- package/scripts/clean-local-artifacts.mjs +0 -78
- package/scripts/compact-natural-mode-benchmark.mjs +0 -9
- package/scripts/context-triggered-audit.mjs +0 -391
- package/scripts/detection-benchmark.mjs +0 -127
- package/scripts/docs-quality-drift-report.mjs +0 -358
- package/scripts/documentation-boundary-audit.mjs +0 -305
- package/scripts/explain-on-demand-audit.mjs +0 -427
- package/scripts/forbidden-content-check.mjs +0 -123
- package/scripts/frontend-usability-audit.mjs +0 -243
- package/scripts/generate-sbom.mjs +0 -61
- package/scripts/governance-weekly-report.mjs +0 -466
- package/scripts/llm-judge/checklist-loader.mjs +0 -45
- package/scripts/llm-judge/constants.mjs +0 -66
- package/scripts/llm-judge/diff-collection.mjs +0 -74
- package/scripts/llm-judge/prompting.mjs +0 -78
- package/scripts/llm-judge/providers.mjs +0 -111
- package/scripts/llm-judge/verdict.mjs +0 -134
- package/scripts/llm-judge.mjs +0 -200
- package/scripts/memory-continuity-benchmark.mjs +0 -322
- package/scripts/quality-trend-report.mjs +0 -289
- package/scripts/release-gate/audit-checks.mjs +0 -441
- package/scripts/release-gate/constants.mjs +0 -53
- package/scripts/release-gate/runtime.mjs +0 -63
- package/scripts/release-gate/static-checks.mjs +0 -182
- package/scripts/release-gate.mjs +0 -42
- package/scripts/rules-guardian-audit.mjs +0 -580
- package/scripts/single-source-lazy-loading-audit.mjs +0 -449
- package/scripts/sync-thin-adapters.mjs +0 -72
- package/scripts/token-optimization-benchmark.mjs +0 -252
- package/scripts/ui-design-judge/constants.mjs +0 -13
- package/scripts/ui-design-judge/design-execution-summary.mjs +0 -81
- package/scripts/ui-design-judge/git-input.mjs +0 -134
- package/scripts/ui-design-judge/prompting.mjs +0 -52
- package/scripts/ui-design-judge/providers.mjs +0 -102
- package/scripts/ui-design-judge/reporting.mjs +0 -183
- package/scripts/ui-design-judge/rubric-calibration.mjs +0 -214
- package/scripts/ui-design-judge/rubric-goldset.json +0 -188
- package/scripts/ui-design-judge.mjs +0 -319
- package/scripts/ui-rubric-calibration.mjs +0 -35
- package/scripts/validate/audits/cache-layer-contract.mjs +0 -230
- package/scripts/validate/audits/caching-scope-hygiene.mjs +0 -235
- package/scripts/validate/audits/file-size.mjs +0 -158
- package/scripts/validate/audits/reflection-citations.mjs +0 -130
- package/scripts/validate/audits/release-bundle.mjs +0 -135
- package/scripts/validate/audits/rule-id-uniqueness.mjs +0 -278
- package/scripts/validate/config.mjs +0 -501
- package/scripts/validate/coverage-checks.mjs +0 -446
- package/scripts/validate/file-structure.mjs +0 -158
- package/scripts/validate/markdown-content.mjs +0 -109
- package/scripts/validate/project-metadata.mjs +0 -166
- package/scripts/validate/utils.mjs +0 -52
- package/scripts/validate.mjs +0 -267
package/lib/cli/constants.mjs
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CLI Constants — All configuration values extracted from the monolith.
|
|
3
|
-
* Zero dependencies on other lib modules.
|
|
4
|
-
*/
|
|
5
|
-
import { readFileSync } from 'node:fs';
|
|
6
|
-
import { resolve, join, dirname } from 'node:path';
|
|
7
|
-
import { fileURLToPath } from 'node:url';
|
|
8
|
-
|
|
9
|
-
const currentFilePath = fileURLToPath(import.meta.url);
|
|
10
|
-
const currentDirectoryPath = dirname(currentFilePath);
|
|
11
|
-
|
|
12
|
-
export const REPOSITORY_ROOT = resolve(currentDirectoryPath, '..', '..');
|
|
13
|
-
export const PACKAGE_JSON_PATH = join(REPOSITORY_ROOT, 'package.json');
|
|
14
|
-
export const CLI_VERSION = JSON.parse(readFileSync(PACKAGE_JSON_PATH, 'utf8')).version;
|
|
15
|
-
export const AGENT_CONTEXT_DIR = join(REPOSITORY_ROOT, '.agent-context');
|
|
16
|
-
export const POLICY_FILE_NAME = 'llm-judge-threshold.json';
|
|
17
|
-
|
|
18
|
-
export const ALLOWED_SEVERITY_LEVELS = new Set(['critical', 'high', 'medium', 'low']);
|
|
19
|
-
|
|
20
|
-
export const AGENT_DECISION_STACK_FILE_NAME = 'agent-decision-runtime.md';
|
|
21
|
-
export const AGENT_DECISION_BLUEPRINT_FILE_NAME = 'agent-decision-architecture.md';
|
|
22
|
-
|
|
23
|
-
export const INIT_PRESETS = {
|
|
24
|
-
'frontend-ui': {
|
|
25
|
-
stack: null,
|
|
26
|
-
blueprint: null,
|
|
27
|
-
ci: true,
|
|
28
|
-
description: 'Frontend/UI scope hint; agent recommends runtime and architecture before coding',
|
|
29
|
-
},
|
|
30
|
-
'backend-service': {
|
|
31
|
-
stack: null,
|
|
32
|
-
blueprint: null,
|
|
33
|
-
ci: true,
|
|
34
|
-
description: 'Backend/API scope hint; agent recommends runtime and architecture before coding',
|
|
35
|
-
},
|
|
36
|
-
'fullstack-product': {
|
|
37
|
-
stack: null,
|
|
38
|
-
blueprint: null,
|
|
39
|
-
ci: true,
|
|
40
|
-
description: 'Fullstack product scope hint; agent recommends runtime and architecture before coding',
|
|
41
|
-
},
|
|
42
|
-
'mobile-app': {
|
|
43
|
-
stack: null,
|
|
44
|
-
blueprint: null,
|
|
45
|
-
ci: true,
|
|
46
|
-
description: 'Mobile app scope hint; agent recommends native strategy before coding',
|
|
47
|
-
},
|
|
48
|
-
'platform-ops': {
|
|
49
|
-
stack: null,
|
|
50
|
-
blueprint: null,
|
|
51
|
-
ci: true,
|
|
52
|
-
description: 'Platform operations scope hint; agent recommends runtime and architecture before coding',
|
|
53
|
-
},
|
|
54
|
-
observability: {
|
|
55
|
-
stack: null,
|
|
56
|
-
blueprint: null,
|
|
57
|
-
ci: true,
|
|
58
|
-
description: 'Observability scope hint; agent recommends runtime and architecture before coding',
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
export const PROFILE_PRESETS = {
|
|
63
|
-
beginner: {
|
|
64
|
-
displayName: 'Beginner',
|
|
65
|
-
description: 'Safest path. Minimal decisions, agent-led stack decision, and CI enabled.',
|
|
66
|
-
defaultStackFileName: null,
|
|
67
|
-
defaultBlueprintFileName: null,
|
|
68
|
-
defaultCi: true,
|
|
69
|
-
lockCi: true,
|
|
70
|
-
blockingSeverities: ['critical'],
|
|
71
|
-
},
|
|
72
|
-
balanced: {
|
|
73
|
-
displayName: 'Balanced',
|
|
74
|
-
description: 'Recommended for most teams. Guided choices with strong default guardrails.',
|
|
75
|
-
defaultStackFileName: null,
|
|
76
|
-
defaultBlueprintFileName: null,
|
|
77
|
-
defaultCi: true,
|
|
78
|
-
lockCi: false,
|
|
79
|
-
blockingSeverities: ['critical', 'high'],
|
|
80
|
-
},
|
|
81
|
-
strict: {
|
|
82
|
-
displayName: 'Strict',
|
|
83
|
-
description: 'Tighter governance. CI stays on and medium-risk findings can block merges.',
|
|
84
|
-
defaultStackFileName: null,
|
|
85
|
-
defaultBlueprintFileName: null,
|
|
86
|
-
defaultCi: true,
|
|
87
|
-
lockCi: true,
|
|
88
|
-
blockingSeverities: ['critical', 'high', 'medium'],
|
|
89
|
-
},
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
export const GOLDEN_STANDARD_PROFILE_NAME = 'balanced';
|
|
93
|
-
|
|
94
|
-
export const PROJECT_SCOPE_CHOICES = [
|
|
95
|
-
{
|
|
96
|
-
key: 'frontend-only',
|
|
97
|
-
label: 'Frontend only',
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
key: 'backend-only',
|
|
101
|
-
label: 'Backend only',
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
key: 'both',
|
|
105
|
-
label: 'Both (frontend + backend)',
|
|
106
|
-
},
|
|
107
|
-
];
|
|
108
|
-
|
|
109
|
-
export const RUNTIME_ENVIRONMENT_CHOICES = [
|
|
110
|
-
{
|
|
111
|
-
key: 'linux-wsl',
|
|
112
|
-
label: 'Linux / WSL',
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
key: 'windows',
|
|
116
|
-
label: 'Windows',
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
key: 'linux',
|
|
120
|
-
label: 'Linux',
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
key: 'macos',
|
|
124
|
-
label: 'macOS',
|
|
125
|
-
},
|
|
126
|
-
];
|
|
127
|
-
|
|
128
|
-
export const entryPointFiles = [
|
|
129
|
-
'AGENTS.md',
|
|
130
|
-
'CLAUDE.md',
|
|
131
|
-
'GEMINI.md',
|
|
132
|
-
];
|
|
133
|
-
|
|
134
|
-
export const directoryCopies = ['.agent-context'];
|
|
135
|
-
|
|
136
|
-
export const BACKUP_DIR_NAME = '.agentic-backup';
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Static configuration sets and known-marker tables for the project context
|
|
3
|
-
* detector. Centralized so workspace traversal, UI signal analysis, and stack
|
|
4
|
-
* detection share one source of truth.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { FRONTEND_SCAN_IGNORE_DIRECTORY_NAMES } from './design-evidence.mjs';
|
|
8
|
-
|
|
9
|
-
export const WORKSPACE_SCAN_MAX_DEPTH = 3;
|
|
10
|
-
export const WORKSPACE_SCAN_MAX_DIRECTORIES = 120;
|
|
11
|
-
|
|
12
|
-
export const WORKSPACE_SCAN_IGNORE_DIRECTORY_NAMES = new Set([
|
|
13
|
-
...FRONTEND_SCAN_IGNORE_DIRECTORY_NAMES,
|
|
14
|
-
'.agent-context',
|
|
15
|
-
'.agents',
|
|
16
|
-
'.cursor',
|
|
17
|
-
'.gemini',
|
|
18
|
-
'.github',
|
|
19
|
-
'.idea',
|
|
20
|
-
'.vscode',
|
|
21
|
-
'.windsurf',
|
|
22
|
-
'.zed',
|
|
23
|
-
]);
|
|
24
|
-
|
|
25
|
-
export const WORKSPACE_CONTAINER_DIRECTORY_NAMES = new Set([
|
|
26
|
-
'admin', 'admins',
|
|
27
|
-
'api', 'apis',
|
|
28
|
-
'app', 'apps',
|
|
29
|
-
'backend', 'backends',
|
|
30
|
-
'client', 'clients',
|
|
31
|
-
'dashboard', 'dashboards',
|
|
32
|
-
'frontend', 'frontends',
|
|
33
|
-
'mobile', 'mobiles',
|
|
34
|
-
'package', 'packages', 'pkg',
|
|
35
|
-
'server', 'servers',
|
|
36
|
-
'service', 'services',
|
|
37
|
-
'site', 'sites',
|
|
38
|
-
'ui', 'web',
|
|
39
|
-
'worker', 'workers',
|
|
40
|
-
]);
|
|
41
|
-
|
|
42
|
-
export const WORKSPACE_ROOT_MARKER_FILE_NAMES = new Set([
|
|
43
|
-
'lerna.json',
|
|
44
|
-
'nx.json',
|
|
45
|
-
'pnpm-workspace.yaml',
|
|
46
|
-
'turbo.json',
|
|
47
|
-
]);
|
|
48
|
-
|
|
49
|
-
export const DIRECT_UI_MARKER_NAMES = [
|
|
50
|
-
'src',
|
|
51
|
-
'next.config.js',
|
|
52
|
-
'next.config.mjs',
|
|
53
|
-
'next.config.ts',
|
|
54
|
-
'tailwind.config.js',
|
|
55
|
-
'tailwind.config.mjs',
|
|
56
|
-
'tailwind.config.ts',
|
|
57
|
-
'vite.config.js',
|
|
58
|
-
'vite.config.mjs',
|
|
59
|
-
'vite.config.ts',
|
|
60
|
-
'react-native.config.js',
|
|
61
|
-
'app',
|
|
62
|
-
'pages',
|
|
63
|
-
'components',
|
|
64
|
-
'public',
|
|
65
|
-
'styles',
|
|
66
|
-
'android',
|
|
67
|
-
'ios',
|
|
68
|
-
'index.html',
|
|
69
|
-
];
|
|
70
|
-
|
|
71
|
-
export const PROJECT_MARKER_FILE_NAMES = new Set([
|
|
72
|
-
'Cargo.toml',
|
|
73
|
-
'Gemfile',
|
|
74
|
-
'build.gradle',
|
|
75
|
-
'build.gradle.kts',
|
|
76
|
-
'composer.json',
|
|
77
|
-
'go.mod',
|
|
78
|
-
'package.json',
|
|
79
|
-
'pom.xml',
|
|
80
|
-
'pubspec.yaml',
|
|
81
|
-
'pyproject.toml',
|
|
82
|
-
'react-native.config.js',
|
|
83
|
-
'requirements.txt',
|
|
84
|
-
'tsconfig.json',
|
|
85
|
-
...DIRECT_UI_MARKER_NAMES,
|
|
86
|
-
]);
|
|
87
|
-
|
|
88
|
-
export const INTERNAL_GOVERNANCE_SURFACE_NAMES = new Set([
|
|
89
|
-
'.agent-context',
|
|
90
|
-
'.agent-instructions.md',
|
|
91
|
-
'.agentic-backup',
|
|
92
|
-
'.agents',
|
|
93
|
-
'.clauderc',
|
|
94
|
-
'.cursorrules',
|
|
95
|
-
'.cursor',
|
|
96
|
-
'.gemini',
|
|
97
|
-
'.github',
|
|
98
|
-
'.instructions.md',
|
|
99
|
-
'.vscode',
|
|
100
|
-
'.windsurf',
|
|
101
|
-
'.windsurfrules',
|
|
102
|
-
'.zed',
|
|
103
|
-
'AGENTS.md',
|
|
104
|
-
'CLAUDE.md',
|
|
105
|
-
'GEMINI.md',
|
|
106
|
-
'mcp.json',
|
|
107
|
-
]);
|
|
108
|
-
|
|
109
|
-
const WORKSPACE_KEYWORD_FRAGMENTS = [
|
|
110
|
-
'admin', 'api', 'app', 'backend', 'client', 'dashboard',
|
|
111
|
-
'frontend', 'mobile', 'package', 'server', 'service',
|
|
112
|
-
'site', 'ui', 'web', 'worker',
|
|
113
|
-
];
|
|
114
|
-
|
|
115
|
-
export function looksLikeWorkspaceSearchCandidate(directoryName) {
|
|
116
|
-
const normalizedDirectoryName = String(directoryName || '').trim().toLowerCase();
|
|
117
|
-
|
|
118
|
-
if (!normalizedDirectoryName) {
|
|
119
|
-
return false;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (WORKSPACE_CONTAINER_DIRECTORY_NAMES.has(normalizedDirectoryName)) {
|
|
123
|
-
return true;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return WORKSPACE_KEYWORD_FRAGMENTS.some((keyword) => normalizedDirectoryName.includes(keyword));
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export function hasProjectMarkers(markerNames) {
|
|
130
|
-
return Array.from(markerNames).some((markerName) => (
|
|
131
|
-
PROJECT_MARKER_FILE_NAMES.has(markerName)
|
|
132
|
-
|| markerName.endsWith('.csproj')
|
|
133
|
-
|| markerName.endsWith('.sln')
|
|
134
|
-
));
|
|
135
|
-
}
|
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Top-level orchestrator for the design evidence scan. Resolves which roots to
|
|
3
|
-
* scan, walks the filesystem, and aggregates results from the inspection
|
|
4
|
-
* passes into a single summary plus a flat metrics object that downstream
|
|
5
|
-
* consumers (detector + UI rubric calibration) read.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import fs from 'node:fs/promises';
|
|
9
|
-
import path from 'node:path';
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
ANIMATION_PATTERN,
|
|
13
|
-
ARBITRARY_BREAKPOINT_PATTERN,
|
|
14
|
-
COLOR_PATTERN,
|
|
15
|
-
CSS_VARIABLE_DEFINITION_PATTERN,
|
|
16
|
-
CSS_VARIABLE_REFERENCE_PATTERN,
|
|
17
|
-
DURATION_PATTERN,
|
|
18
|
-
FONT_FAMILY_PATTERN,
|
|
19
|
-
FONT_SIZE_PATTERN,
|
|
20
|
-
FRONTEND_FILE_SCAN_LIMIT,
|
|
21
|
-
FRONTEND_FILE_SIZE_LIMIT_BYTES,
|
|
22
|
-
FRONTEND_SCAN_DIRECTORY_NAMES,
|
|
23
|
-
LETTER_SPACING_PATTERN,
|
|
24
|
-
LINE_HEIGHT_PATTERN,
|
|
25
|
-
MEDIA_QUERY_PATTERN,
|
|
26
|
-
MEDIA_WIDTH_PATTERN,
|
|
27
|
-
PROP_DRILLING_PATTERN,
|
|
28
|
-
RAW_RADIUS_PATTERN,
|
|
29
|
-
RAW_SHADOW_PATTERN,
|
|
30
|
-
RAW_SPACING_PATTERN,
|
|
31
|
-
TAILWIND_BREAKPOINT_PATTERN,
|
|
32
|
-
TRANSITION_PATTERN,
|
|
33
|
-
} from './constants.mjs';
|
|
34
|
-
import { collectFrontendSourceFilePaths, registerSurfaceFile } from './file-traversal.mjs';
|
|
35
|
-
import { collectStructuredAttributeEvidence } from './structured-attribute-evidence.mjs';
|
|
36
|
-
import { createDesignEvidenceSummary } from './summary.mjs';
|
|
37
|
-
import {
|
|
38
|
-
categorizeCssVariable,
|
|
39
|
-
countPatternMatches,
|
|
40
|
-
incrementCountMap,
|
|
41
|
-
inferColorKind,
|
|
42
|
-
pushSampleValue,
|
|
43
|
-
} from './utility-helpers.mjs';
|
|
44
|
-
|
|
45
|
-
function resolveCandidateDirectoryPaths(targetDirectoryPath, markerNames, scanRootDirectoryPaths) {
|
|
46
|
-
const candidateDirectoryPaths = FRONTEND_SCAN_DIRECTORY_NAMES
|
|
47
|
-
.filter((directoryName) => markerNames.has(directoryName))
|
|
48
|
-
.map((directoryName) => path.join(targetDirectoryPath, directoryName));
|
|
49
|
-
const explicitScanRootDirectoryPaths = Array.isArray(scanRootDirectoryPaths)
|
|
50
|
-
? scanRootDirectoryPaths.filter(
|
|
51
|
-
(scanRootDirectoryPath) => typeof scanRootDirectoryPath === 'string' && scanRootDirectoryPath.trim().length > 0,
|
|
52
|
-
)
|
|
53
|
-
: [];
|
|
54
|
-
if (explicitScanRootDirectoryPaths.length > 0) {
|
|
55
|
-
return Array.from(new Set(explicitScanRootDirectoryPaths));
|
|
56
|
-
}
|
|
57
|
-
if (candidateDirectoryPaths.length > 0) {
|
|
58
|
-
return candidateDirectoryPaths;
|
|
59
|
-
}
|
|
60
|
-
return [targetDirectoryPath];
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export async function collectFrontendDesignEvidence({
|
|
64
|
-
targetDirectoryPath,
|
|
65
|
-
markerNames,
|
|
66
|
-
scanRootDirectoryPaths = [],
|
|
67
|
-
}) {
|
|
68
|
-
const resolvedCandidateDirectoryPaths = resolveCandidateDirectoryPaths(
|
|
69
|
-
targetDirectoryPath,
|
|
70
|
-
markerNames,
|
|
71
|
-
scanRootDirectoryPaths,
|
|
72
|
-
);
|
|
73
|
-
const scannedFilePaths = [];
|
|
74
|
-
const scanRootRelativePaths = resolvedCandidateDirectoryPaths
|
|
75
|
-
.map((candidateDirectoryPath) => (
|
|
76
|
-
path.relative(targetDirectoryPath, candidateDirectoryPath).replace(/\\/g, '/') || '.'
|
|
77
|
-
));
|
|
78
|
-
const designEvidenceSummary = createDesignEvidenceSummary(scanRootRelativePaths);
|
|
79
|
-
const cssVariableSamples = new Set();
|
|
80
|
-
const colorSamples = new Set();
|
|
81
|
-
const spacingSamples = new Set();
|
|
82
|
-
const radiusSamples = new Set();
|
|
83
|
-
const shadowSamples = new Set();
|
|
84
|
-
const fontFamilySamples = new Set();
|
|
85
|
-
const fontSizeSamples = new Set();
|
|
86
|
-
const lineHeightSamples = new Set();
|
|
87
|
-
const letterSpacingSamples = new Set();
|
|
88
|
-
const durationSamples = new Set();
|
|
89
|
-
const structuredClassAttributeSamples = new Set();
|
|
90
|
-
const structuredInlineStyleSamples = new Set();
|
|
91
|
-
const structuredUtilityFamilySamples = new Set();
|
|
92
|
-
const seenSurfaceFiles = new Set();
|
|
93
|
-
let hardcodedColorCount = 0;
|
|
94
|
-
let propDrillingCandidateCount = 0;
|
|
95
|
-
let mediaQueryCount = 0;
|
|
96
|
-
let tailwindBreakpointUsageCount = 0;
|
|
97
|
-
let arbitraryBreakpointCount = 0;
|
|
98
|
-
const uniqueMediaWidths = new Set();
|
|
99
|
-
|
|
100
|
-
for (const candidateDirectoryPath of resolvedCandidateDirectoryPaths) {
|
|
101
|
-
await collectFrontendSourceFilePaths(candidateDirectoryPath, scannedFilePaths);
|
|
102
|
-
if (scannedFilePaths.length >= FRONTEND_FILE_SCAN_LIMIT) {
|
|
103
|
-
break;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
designEvidenceSummary.scannedFileCount = scannedFilePaths.length;
|
|
108
|
-
|
|
109
|
-
for (const scannedFilePath of scannedFilePaths) {
|
|
110
|
-
let sourceText;
|
|
111
|
-
|
|
112
|
-
try {
|
|
113
|
-
const fileStat = await fs.stat(scannedFilePath);
|
|
114
|
-
if (fileStat.size > FRONTEND_FILE_SIZE_LIMIT_BYTES) {
|
|
115
|
-
continue;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
sourceText = await fs.readFile(scannedFilePath, 'utf8');
|
|
119
|
-
} catch {
|
|
120
|
-
continue;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
registerSurfaceFile(designEvidenceSummary, targetDirectoryPath, scannedFilePath, seenSurfaceFiles);
|
|
124
|
-
collectStructuredAttributeEvidence(
|
|
125
|
-
sourceText,
|
|
126
|
-
designEvidenceSummary,
|
|
127
|
-
structuredClassAttributeSamples,
|
|
128
|
-
structuredInlineStyleSamples,
|
|
129
|
-
structuredUtilityFamilySamples,
|
|
130
|
-
);
|
|
131
|
-
|
|
132
|
-
for (const cssVariableMatch of sourceText.matchAll(CSS_VARIABLE_DEFINITION_PATTERN)) {
|
|
133
|
-
designEvidenceSummary.cssVariables.definitionCount += 1;
|
|
134
|
-
const variableName = cssVariableMatch[1];
|
|
135
|
-
const categoryKey = categorizeCssVariable(variableName);
|
|
136
|
-
incrementCountMap(designEvidenceSummary.cssVariables.categoryCounts, categoryKey);
|
|
137
|
-
pushSampleValue(designEvidenceSummary.cssVariables.sampleNames, variableName, cssVariableSamples);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
for (const cssVariableReferenceMatch of sourceText.matchAll(CSS_VARIABLE_REFERENCE_PATTERN)) {
|
|
141
|
-
designEvidenceSummary.cssVariables.referenceCount += 1;
|
|
142
|
-
pushSampleValue(
|
|
143
|
-
designEvidenceSummary.cssVariables.sampleNames,
|
|
144
|
-
cssVariableReferenceMatch[1],
|
|
145
|
-
cssVariableSamples,
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
for (const colorMatch of sourceText.matchAll(COLOR_PATTERN)) {
|
|
150
|
-
const colorValue = colorMatch[0];
|
|
151
|
-
hardcodedColorCount += 1;
|
|
152
|
-
designEvidenceSummary.colors.hardcodedCount += 1;
|
|
153
|
-
incrementCountMap(designEvidenceSummary.colors.kindCounts, inferColorKind(colorValue));
|
|
154
|
-
pushSampleValue(designEvidenceSummary.colors.sampleValues, colorValue, colorSamples);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
propDrillingCandidateCount += countPatternMatches(sourceText, PROP_DRILLING_PATTERN);
|
|
158
|
-
mediaQueryCount += countPatternMatches(sourceText, MEDIA_QUERY_PATTERN);
|
|
159
|
-
tailwindBreakpointUsageCount += countPatternMatches(sourceText, TAILWIND_BREAKPOINT_PATTERN);
|
|
160
|
-
arbitraryBreakpointCount += countPatternMatches(sourceText, ARBITRARY_BREAKPOINT_PATTERN);
|
|
161
|
-
designEvidenceSummary.tailwind.breakpointUsageCount += countPatternMatches(sourceText, TAILWIND_BREAKPOINT_PATTERN);
|
|
162
|
-
designEvidenceSummary.tailwind.arbitraryBreakpointCount += countPatternMatches(sourceText, ARBITRARY_BREAKPOINT_PATTERN);
|
|
163
|
-
|
|
164
|
-
for (const rawSpacingMatch of sourceText.matchAll(RAW_SPACING_PATTERN)) {
|
|
165
|
-
designEvidenceSummary.spacing.rawValueCount += 1;
|
|
166
|
-
pushSampleValue(designEvidenceSummary.spacing.sampleValues, rawSpacingMatch[1], spacingSamples);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
for (const rawRadiusMatch of sourceText.matchAll(RAW_RADIUS_PATTERN)) {
|
|
170
|
-
designEvidenceSummary.radius.rawValueCount += 1;
|
|
171
|
-
pushSampleValue(designEvidenceSummary.radius.sampleValues, rawRadiusMatch[1], radiusSamples);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
for (const rawShadowMatch of sourceText.matchAll(RAW_SHADOW_PATTERN)) {
|
|
175
|
-
designEvidenceSummary.shadow.rawValueCount += 1;
|
|
176
|
-
pushSampleValue(designEvidenceSummary.shadow.sampleValues, rawShadowMatch[1], shadowSamples);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
for (const fontFamilyMatch of sourceText.matchAll(FONT_FAMILY_PATTERN)) {
|
|
180
|
-
designEvidenceSummary.typography.fontFamilyCount += 1;
|
|
181
|
-
pushSampleValue(designEvidenceSummary.typography.fontFamilySamples, fontFamilyMatch[1], fontFamilySamples);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
for (const fontSizeMatch of sourceText.matchAll(FONT_SIZE_PATTERN)) {
|
|
185
|
-
designEvidenceSummary.typography.fontSizeCount += 1;
|
|
186
|
-
pushSampleValue(designEvidenceSummary.typography.fontSizeSamples, fontSizeMatch[1], fontSizeSamples);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
for (const lineHeightMatch of sourceText.matchAll(LINE_HEIGHT_PATTERN)) {
|
|
190
|
-
designEvidenceSummary.typography.lineHeightCount += 1;
|
|
191
|
-
pushSampleValue(designEvidenceSummary.typography.lineHeightSamples, lineHeightMatch[1], lineHeightSamples);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
for (const letterSpacingMatch of sourceText.matchAll(LETTER_SPACING_PATTERN)) {
|
|
195
|
-
designEvidenceSummary.typography.letterSpacingCount += 1;
|
|
196
|
-
pushSampleValue(
|
|
197
|
-
designEvidenceSummary.typography.letterSpacingSamples,
|
|
198
|
-
letterSpacingMatch[1],
|
|
199
|
-
letterSpacingSamples,
|
|
200
|
-
);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
designEvidenceSummary.motion.transitionCount += countPatternMatches(sourceText, TRANSITION_PATTERN);
|
|
204
|
-
designEvidenceSummary.motion.animationCount += countPatternMatches(sourceText, ANIMATION_PATTERN);
|
|
205
|
-
|
|
206
|
-
for (const durationMatch of sourceText.matchAll(DURATION_PATTERN)) {
|
|
207
|
-
designEvidenceSummary.motion.durationCount += 1;
|
|
208
|
-
pushSampleValue(designEvidenceSummary.motion.durationSamples, durationMatch[0], durationSamples);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
for (const mediaWidthMatch of sourceText.matchAll(MEDIA_WIDTH_PATTERN)) {
|
|
212
|
-
uniqueMediaWidths.add(mediaWidthMatch[1]);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
designEvidenceSummary.tailwind.utilityFamilyCounts = {
|
|
217
|
-
...designEvidenceSummary.structuredInspection.utilityFamilyCounts,
|
|
218
|
-
};
|
|
219
|
-
designEvidenceSummary.tailwind.utilityFamilySamples = [
|
|
220
|
-
...designEvidenceSummary.structuredInspection.utilityFamilySamples,
|
|
221
|
-
];
|
|
222
|
-
|
|
223
|
-
designEvidenceSummary.tokenBypassSignals = {
|
|
224
|
-
hardcodedColorCount: designEvidenceSummary.colors.hardcodedCount,
|
|
225
|
-
rawSpacingCount: designEvidenceSummary.spacing.rawValueCount,
|
|
226
|
-
rawRadiusCount: designEvidenceSummary.radius.rawValueCount,
|
|
227
|
-
rawShadowCount: designEvidenceSummary.shadow.rawValueCount,
|
|
228
|
-
inlineHardcodedColorCount: designEvidenceSummary.structuredInspection.inlineTokenBypassSignals.hardcodedColorCount,
|
|
229
|
-
inlineRawSpacingCount: designEvidenceSummary.structuredInspection.inlineTokenBypassSignals.rawSpacingCount,
|
|
230
|
-
inlineRawRadiusCount: designEvidenceSummary.structuredInspection.inlineTokenBypassSignals.rawRadiusCount,
|
|
231
|
-
inlineRawShadowCount: designEvidenceSummary.structuredInspection.inlineTokenBypassSignals.rawShadowCount,
|
|
232
|
-
inlineCssVariableReferenceCount: designEvidenceSummary.structuredInspection.inlineTokenBypassSignals.cssVariableReferenceCount,
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
return {
|
|
236
|
-
frontendEvidenceMetrics: {
|
|
237
|
-
scannedFileCount: scannedFilePaths.length,
|
|
238
|
-
hardcodedColorCount,
|
|
239
|
-
propDrillingCandidateCount,
|
|
240
|
-
mediaQueryCount,
|
|
241
|
-
tailwindBreakpointUsageCount,
|
|
242
|
-
arbitraryBreakpointCount,
|
|
243
|
-
uniqueMediaWidthCount: uniqueMediaWidths.size,
|
|
244
|
-
structuredClassAttributeCount: designEvidenceSummary.structuredInspection.classAttributeCount,
|
|
245
|
-
boundClassExpressionCount: designEvidenceSummary.structuredInspection.boundClassExpressionCount,
|
|
246
|
-
inlineStyleObjectCount: designEvidenceSummary.structuredInspection.inlineStyleObjectCount,
|
|
247
|
-
inlineStyleBindingCount: designEvidenceSummary.structuredInspection.inlineStyleBindingCount,
|
|
248
|
-
inlineStyleTokenBypassCount:
|
|
249
|
-
designEvidenceSummary.structuredInspection.inlineTokenBypassSignals.hardcodedColorCount
|
|
250
|
-
+ designEvidenceSummary.structuredInspection.inlineTokenBypassSignals.rawSpacingCount
|
|
251
|
-
+ designEvidenceSummary.structuredInspection.inlineTokenBypassSignals.rawRadiusCount
|
|
252
|
-
+ designEvidenceSummary.structuredInspection.inlineTokenBypassSignals.rawShadowCount,
|
|
253
|
-
},
|
|
254
|
-
designEvidenceSummary,
|
|
255
|
-
};
|
|
256
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Static configuration and regex patterns for the lightweight static design
|
|
3
|
-
* evidence scan. Kept in one place so the scanner internals stay pattern-driven
|
|
4
|
-
* and reviewable.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export const FRONTEND_SCAN_DIRECTORY_NAMES = ['src', 'app', 'pages', 'components', 'styles'];
|
|
8
|
-
export const FRONTEND_SCAN_FILE_EXTENSIONS = new Set([
|
|
9
|
-
'.js', '.jsx', '.ts', '.tsx', '.vue', '.css', '.scss', '.sass',
|
|
10
|
-
]);
|
|
11
|
-
export const FRONTEND_SCAN_IGNORE_DIRECTORY_NAMES = new Set([
|
|
12
|
-
'.git', 'node_modules', '.next', 'dist', 'build', 'coverage',
|
|
13
|
-
]);
|
|
14
|
-
export const FRONTEND_FILE_SCAN_LIMIT = 200;
|
|
15
|
-
export const FRONTEND_FILE_SIZE_LIMIT_BYTES = 200_000;
|
|
16
|
-
export const DESIGN_EVIDENCE_SAMPLE_LIMIT = 12;
|
|
17
|
-
|
|
18
|
-
export const COLOR_PATTERN = /#[0-9a-fA-F]{3,8}\b|rgba?\([^)]+\)|hsla?\([^)]+\)|oklch\([^)]+\)/g;
|
|
19
|
-
export const PROP_DRILLING_PATTERN = /<[A-Z][A-Za-z0-9_.:-]*(?:\s+[A-Za-z0-9_:-]+=\{[^}]+\}){5,}/g;
|
|
20
|
-
export const MEDIA_QUERY_PATTERN = /@media\b/g;
|
|
21
|
-
export const TAILWIND_BREAKPOINT_PATTERN = /\b(?:sm|md|lg|xl|2xl):/g;
|
|
22
|
-
export const ARBITRARY_BREAKPOINT_PATTERN = /\b(?:min|max)-\[[^\]]+\]:/g;
|
|
23
|
-
export const CSS_VARIABLE_DEFINITION_PATTERN = /--([a-zA-Z0-9-_]+)\s*:/g;
|
|
24
|
-
export const CSS_VARIABLE_REFERENCE_PATTERN = /var\(--([a-zA-Z0-9-_]+)\)/g;
|
|
25
|
-
export const RAW_SPACING_PATTERN = /\b(?:margin|padding|gap|column-gap|row-gap|min-width|max-width|min-height|max-height|width|height|top|right|bottom|left|inset|spaceBetween|paddingInline|paddingBlock|marginInline|marginBlock|gapX|gapY|spaceX|spaceY)\b[^;\n:]*[:=]\s*['"`{(]*(-?[0-9.]+(?:px|rem|em|vh|vw))/gi;
|
|
26
|
-
export const RAW_RADIUS_PATTERN = /\b(?:border-radius|borderRadius)\b[^;\n:]*[:=]\s*['"`{(]*([0-9.]+(?:px|rem|em)|9999px)/gi;
|
|
27
|
-
export const RAW_SHADOW_PATTERN = /\b(?:box-shadow|boxShadow)\b[^;\n:]*[:=]\s*['"`{(]*([^;\n}]+)/gi;
|
|
28
|
-
export const FONT_FAMILY_PATTERN = /\b(?:font-family|fontFamily)\b[^;\n:]*[:=]\s*['"`{(]*([^;\n}]+)/gi;
|
|
29
|
-
export const FONT_SIZE_PATTERN = /\b(?:font-size|fontSize)\b[^;\n:]*[:=]\s*['"`{(]*([0-9.]+(?:px|rem|em))/gi;
|
|
30
|
-
export const LINE_HEIGHT_PATTERN = /\b(?:line-height|lineHeight)\b[^;\n:]*[:=]\s*['"`{(]*([0-9.]+(?:px|rem|em)?)/gi;
|
|
31
|
-
export const LETTER_SPACING_PATTERN = /\b(?:letter-spacing|letterSpacing)\b[^;\n:]*[:=]\s*['"`{(]*([0-9.-]+(?:px|rem|em))/gi;
|
|
32
|
-
export const TRANSITION_PATTERN = /\btransition(?:-[a-z]+)?\b/g;
|
|
33
|
-
export const ANIMATION_PATTERN = /\banimation(?:-[a-z]+)?\b/g;
|
|
34
|
-
export const DURATION_PATTERN = /\b\d+(?:\.\d+)?m?s\b/g;
|
|
35
|
-
export const MEDIA_WIDTH_PATTERN = /\((?:min|max)-width:\s*([0-9.]+(?:px|rem|em))\)/g;
|
|
36
|
-
export const STRING_CLASS_ATTRIBUTE_PATTERN = /\b(?:className|class)\s*=\s*(?:"([^"]*)"|'([^']*)'|\{`([^`]*)`\}|\{"([^"]*)"\}|\{'([^']*)'\})/g;
|
|
37
|
-
export const EXPRESSION_CLASS_ATTRIBUTE_PATTERN = /\b(?:className|class|:class)\s*=\s*\{([^}\n]+)\}/g;
|
|
38
|
-
export const JSX_INLINE_STYLE_PATTERN = /\bstyle\s*=\s*\{\{([\s\S]*?)\}\}/g;
|
|
39
|
-
export const VUE_INLINE_STYLE_PATTERN = /\b:style\s*=\s*["']\{([^"']*)\}["']/g;
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Filesystem traversal and surface-file classification for the design evidence
|
|
3
|
-
* scan. Bounded by FRONTEND_FILE_SCAN_LIMIT so the scan never blows up on huge
|
|
4
|
-
* monorepos.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import fs from 'node:fs/promises';
|
|
8
|
-
import path from 'node:path';
|
|
9
|
-
|
|
10
|
-
import {
|
|
11
|
-
DESIGN_EVIDENCE_SAMPLE_LIMIT,
|
|
12
|
-
FRONTEND_FILE_SCAN_LIMIT,
|
|
13
|
-
FRONTEND_SCAN_FILE_EXTENSIONS,
|
|
14
|
-
FRONTEND_SCAN_IGNORE_DIRECTORY_NAMES,
|
|
15
|
-
} from './constants.mjs';
|
|
16
|
-
|
|
17
|
-
export async function collectFrontendSourceFilePaths(directoryPath, collectedFilePaths = []) {
|
|
18
|
-
if (collectedFilePaths.length >= FRONTEND_FILE_SCAN_LIMIT) {
|
|
19
|
-
return collectedFilePaths;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
let directoryEntries;
|
|
23
|
-
try {
|
|
24
|
-
directoryEntries = await fs.readdir(directoryPath, { withFileTypes: true });
|
|
25
|
-
} catch {
|
|
26
|
-
return collectedFilePaths;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
for (const directoryEntry of directoryEntries) {
|
|
30
|
-
if (collectedFilePaths.length >= FRONTEND_FILE_SCAN_LIMIT) {
|
|
31
|
-
break;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (directoryEntry.isDirectory()) {
|
|
35
|
-
if (FRONTEND_SCAN_IGNORE_DIRECTORY_NAMES.has(directoryEntry.name)) {
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
await collectFrontendSourceFilePaths(path.join(directoryPath, directoryEntry.name), collectedFilePaths);
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const fileExtension = path.extname(directoryEntry.name).toLowerCase();
|
|
44
|
-
if (FRONTEND_SCAN_FILE_EXTENSIONS.has(fileExtension)) {
|
|
45
|
-
collectedFilePaths.push(path.join(directoryPath, directoryEntry.name));
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return collectedFilePaths;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function registerSurfaceFile(summary, targetDirectoryPath, scannedFilePath, seenSurfaceFiles) {
|
|
53
|
-
const relativeFilePath = path.relative(targetDirectoryPath, scannedFilePath).replace(/\\/g, '/');
|
|
54
|
-
const normalizedBaseName = path.basename(scannedFilePath, path.extname(scannedFilePath)).toLowerCase();
|
|
55
|
-
const looksLikeComponent = /[A-Z]/.test(path.basename(scannedFilePath, path.extname(scannedFilePath)))
|
|
56
|
-
|| relativeFilePath.includes('/components/')
|
|
57
|
-
|| relativeFilePath.startsWith('components/');
|
|
58
|
-
const looksLikePage = normalizedBaseName === 'page'
|
|
59
|
-
|| normalizedBaseName === 'index'
|
|
60
|
-
|| relativeFilePath.includes('/pages/')
|
|
61
|
-
|| relativeFilePath.startsWith('pages/')
|
|
62
|
-
|| relativeFilePath.includes('/app/');
|
|
63
|
-
const looksLikeLayout = normalizedBaseName === 'layout' || relativeFilePath.includes('/layouts/');
|
|
64
|
-
|
|
65
|
-
if (looksLikeComponent) {
|
|
66
|
-
summary.componentInventory.componentFileCount += 1;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (looksLikePage) {
|
|
70
|
-
summary.componentInventory.pageFileCount += 1;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (looksLikeLayout) {
|
|
74
|
-
summary.componentInventory.layoutFileCount += 1;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if ((looksLikeComponent || looksLikePage || looksLikeLayout) && !seenSurfaceFiles.has(relativeFilePath)) {
|
|
78
|
-
seenSurfaceFiles.add(relativeFilePath);
|
|
79
|
-
if (summary.componentInventory.surfaceFileSamples.length < DESIGN_EVIDENCE_SAMPLE_LIMIT) {
|
|
80
|
-
summary.componentInventory.surfaceFileSamples.push(relativeFilePath);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|