@levironexe/architect 0.1.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/CHANGELOG.md +32 -0
- package/CONTRIBUTING.md +55 -0
- package/README.md +341 -0
- package/dist/analyzers/ast-parser.d.ts +3 -0
- package/dist/analyzers/ast-parser.js +305 -0
- package/dist/analyzers/ast-parser.js.map +1 -0
- package/dist/analyzers/dependency-graph.d.ts +2 -0
- package/dist/analyzers/dependency-graph.js +67 -0
- package/dist/analyzers/dependency-graph.js.map +1 -0
- package/dist/analyzers/duplication.d.ts +2 -0
- package/dist/analyzers/duplication.js +56 -0
- package/dist/analyzers/duplication.js.map +1 -0
- package/dist/analyzers/file-walker.d.ts +3 -0
- package/dist/analyzers/file-walker.js +80 -0
- package/dist/analyzers/file-walker.js.map +1 -0
- package/dist/cli/context-runner.d.ts +1 -0
- package/dist/cli/context-runner.js +16 -0
- package/dist/cli/context-runner.js.map +1 -0
- package/dist/cli/index.d.ts +24 -0
- package/dist/cli/index.js +217 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init-runner.d.ts +25 -0
- package/dist/cli/init-runner.js +152 -0
- package/dist/cli/init-runner.js.map +1 -0
- package/dist/cli/scan-runner.d.ts +8 -0
- package/dist/cli/scan-runner.js +133 -0
- package/dist/cli/scan-runner.js.map +1 -0
- package/dist/formatters/plan-json.d.ts +2 -0
- package/dist/formatters/plan-json.js +4 -0
- package/dist/formatters/plan-json.js.map +1 -0
- package/dist/formatters/plan-markdown.d.ts +2 -0
- package/dist/formatters/plan-markdown.js +42 -0
- package/dist/formatters/plan-markdown.js.map +1 -0
- package/dist/formatters/plan-prompt.d.ts +4 -0
- package/dist/formatters/plan-prompt.js +5 -0
- package/dist/formatters/plan-prompt.js.map +1 -0
- package/dist/formatters/plan-terminal.d.ts +5 -0
- package/dist/formatters/plan-terminal.js +62 -0
- package/dist/formatters/plan-terminal.js.map +1 -0
- package/dist/generators/blueprint-renderer.d.ts +3 -0
- package/dist/generators/blueprint-renderer.js +27 -0
- package/dist/generators/blueprint-renderer.js.map +1 -0
- package/dist/generators/claudeWriter.d.ts +3 -0
- package/dist/generators/claudeWriter.js +9 -0
- package/dist/generators/claudeWriter.js.map +1 -0
- package/dist/generators/copilotWriter.d.ts +3 -0
- package/dist/generators/copilotWriter.js +11 -0
- package/dist/generators/copilotWriter.js.map +1 -0
- package/dist/generators/cursorWriter.d.ts +3 -0
- package/dist/generators/cursorWriter.js +14 -0
- package/dist/generators/cursorWriter.js.map +1 -0
- package/dist/generators/genericWriter.d.ts +3 -0
- package/dist/generators/genericWriter.js +9 -0
- package/dist/generators/genericWriter.js.map +1 -0
- package/dist/generators/template-context.d.ts +18 -0
- package/dist/generators/template-context.js +126 -0
- package/dist/generators/template-context.js.map +1 -0
- package/dist/generators/templateRenderer.d.ts +2 -0
- package/dist/generators/templateRenderer.js +19 -0
- package/dist/generators/templateRenderer.js.map +1 -0
- package/dist/generators/windsurfWriter.d.ts +3 -0
- package/dist/generators/windsurfWriter.js +14 -0
- package/dist/generators/windsurfWriter.js.map +1 -0
- package/dist/generators/writer-types.d.ts +11 -0
- package/dist/generators/writer-types.js +40 -0
- package/dist/generators/writer-types.js.map +1 -0
- package/dist/llm/claude-provider.d.ts +8 -0
- package/dist/llm/claude-provider.js +22 -0
- package/dist/llm/claude-provider.js.map +1 -0
- package/dist/llm/concern-classifier.d.ts +15 -0
- package/dist/llm/concern-classifier.js +61 -0
- package/dist/llm/concern-classifier.js.map +1 -0
- package/dist/llm/config.d.ts +11 -0
- package/dist/llm/config.js +120 -0
- package/dist/llm/config.js.map +1 -0
- package/dist/llm/ollama-provider.d.ts +8 -0
- package/dist/llm/ollama-provider.js +27 -0
- package/dist/llm/ollama-provider.js.map +1 -0
- package/dist/llm/openai-provider.d.ts +8 -0
- package/dist/llm/openai-provider.js +19 -0
- package/dist/llm/openai-provider.js.map +1 -0
- package/dist/llm/prompt-builder.d.ts +12 -0
- package/dist/llm/prompt-builder.js +132 -0
- package/dist/llm/prompt-builder.js.map +1 -0
- package/dist/llm/provider.d.ts +17 -0
- package/dist/llm/provider.js +2 -0
- package/dist/llm/provider.js.map +1 -0
- package/dist/llm/response-parser.d.ts +6 -0
- package/dist/llm/response-parser.js +128 -0
- package/dist/llm/response-parser.js.map +1 -0
- package/dist/planner/plan-generator.d.ts +7 -0
- package/dist/planner/plan-generator.js +275 -0
- package/dist/planner/plan-generator.js.map +1 -0
- package/dist/planner/plan-prompt-builder.d.ts +9 -0
- package/dist/planner/plan-prompt-builder.js +92 -0
- package/dist/planner/plan-prompt-builder.js.map +1 -0
- package/dist/planner/plan-response-parser.d.ts +7 -0
- package/dist/planner/plan-response-parser.js +21 -0
- package/dist/planner/plan-response-parser.js.map +1 -0
- package/dist/planner/plan-validator.d.ts +3 -0
- package/dist/planner/plan-validator.js +49 -0
- package/dist/planner/plan-validator.js.map +1 -0
- package/dist/reporters/scan-json.d.ts +13 -0
- package/dist/reporters/scan-json.js +26 -0
- package/dist/reporters/scan-json.js.map +1 -0
- package/dist/reporters/terminal.d.ts +6 -0
- package/dist/reporters/terminal.js +224 -0
- package/dist/reporters/terminal.js.map +1 -0
- package/dist/scoring/consistency-score.d.ts +3 -0
- package/dist/scoring/consistency-score.js +23 -0
- package/dist/scoring/consistency-score.js.map +1 -0
- package/dist/scoring/duplication-score.d.ts +3 -0
- package/dist/scoring/duplication-score.js +16 -0
- package/dist/scoring/duplication-score.js.map +1 -0
- package/dist/scoring/health-score.d.ts +4 -0
- package/dist/scoring/health-score.js +20 -0
- package/dist/scoring/health-score.js.map +1 -0
- package/dist/scoring/issue-builder.d.ts +4 -0
- package/dist/scoring/issue-builder.js +62 -0
- package/dist/scoring/issue-builder.js.map +1 -0
- package/dist/scoring/modularity-score.d.ts +3 -0
- package/dist/scoring/modularity-score.js +56 -0
- package/dist/scoring/modularity-score.js.map +1 -0
- package/dist/scoring/pattern-analysis.d.ts +3 -0
- package/dist/scoring/pattern-analysis.js +74 -0
- package/dist/scoring/pattern-analysis.js.map +1 -0
- package/dist/scoring/separation-score.d.ts +3 -0
- package/dist/scoring/separation-score.js +35 -0
- package/dist/scoring/separation-score.js.map +1 -0
- package/dist/skills/detector.d.ts +4 -0
- package/dist/skills/detector.js +104 -0
- package/dist/skills/detector.js.map +1 -0
- package/dist/skills/lister.d.ts +9 -0
- package/dist/skills/lister.js +35 -0
- package/dist/skills/lister.js.map +1 -0
- package/dist/skills/loader.d.ts +6 -0
- package/dist/skills/loader.js +76 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/structure-check.d.ts +2 -0
- package/dist/skills/structure-check.js +37 -0
- package/dist/skills/structure-check.js.map +1 -0
- package/dist/skills/validator.d.ts +6 -0
- package/dist/skills/validator.js +229 -0
- package/dist/skills/validator.js.map +1 -0
- package/dist/types/analysis.d.ts +130 -0
- package/dist/types/analysis.js +41 -0
- package/dist/types/analysis.js.map +1 -0
- package/dist/types/concern.d.ts +48 -0
- package/dist/types/concern.js +16 -0
- package/dist/types/concern.js.map +1 -0
- package/dist/types/generation.d.ts +32 -0
- package/dist/types/generation.js +2 -0
- package/dist/types/generation.js.map +1 -0
- package/dist/types/issue.d.ts +12 -0
- package/dist/types/issue.js +2 -0
- package/dist/types/issue.js.map +1 -0
- package/dist/types/pattern.d.ts +15 -0
- package/dist/types/pattern.js +2 -0
- package/dist/types/pattern.js.map +1 -0
- package/dist/types/plan.d.ts +56 -0
- package/dist/types/plan.js +2 -0
- package/dist/types/plan.js.map +1 -0
- package/dist/types/scan-output.d.ts +84 -0
- package/dist/types/scan-output.js +2 -0
- package/dist/types/scan-output.js.map +1 -0
- package/dist/types/scoring.d.ts +15 -0
- package/dist/types/scoring.js +2 -0
- package/dist/types/scoring.js.map +1 -0
- package/dist/types/skill.d.ts +97 -0
- package/dist/types/skill.js +2 -0
- package/dist/types/skill.js.map +1 -0
- package/dist/utils/agent-detector.d.ts +2 -0
- package/dist/utils/agent-detector.js +22 -0
- package/dist/utils/agent-detector.js.map +1 -0
- package/dist/utils/interactive.d.ts +6 -0
- package/dist/utils/interactive.js +15 -0
- package/dist/utils/interactive.js.map +1 -0
- package/dist/utils/path.d.ts +5 -0
- package/dist/utils/path.js +31 -0
- package/dist/utils/path.js.map +1 -0
- package/dist/utils/progress.d.ts +17 -0
- package/dist/utils/progress.js +48 -0
- package/dist/utils/progress.js.map +1 -0
- package/dist/utils/thresholds.d.ts +6 -0
- package/dist/utils/thresholds.js +48 -0
- package/dist/utils/thresholds.js.map +1 -0
- package/package.json +63 -0
- package/skills/meta/general-js.skill.yaml +131 -0
- package/skills/patterns/clerk-auth.skill.yaml +349 -0
- package/skills/patterns/docker-deploy.skill.yaml +214 -0
- package/skills/patterns/drizzle.skill.yaml +277 -0
- package/skills/patterns/mongoose.skill.yaml +290 -0
- package/skills/patterns/nextauth.skill.yaml +308 -0
- package/skills/patterns/playwright-e2e.skill.yaml +265 -0
- package/skills/patterns/prisma.skill.yaml +255 -0
- package/skills/patterns/s3-storage.skill.yaml +235 -0
- package/skills/patterns/selenium-e2e.skill.yaml +276 -0
- package/skills/patterns/supabase-auth.skill.yaml +298 -0
- package/skills/patterns/supabase.skill.yaml +304 -0
- package/skills/patterns/vercel-deploy.skill.yaml +219 -0
- package/skills/patterns/vitest-testing.skill.yaml +262 -0
- package/skills/stacks/express-api.skill.yaml +155 -0
- package/skills/stacks/fastify-api.skill.yaml +119 -0
- package/skills/stacks/hono-api.skill.yaml +130 -0
- package/skills/stacks/nestjs.skill.yaml +135 -0
- package/skills/stacks/nextjs-app-router.skill.yaml +176 -0
- package/skills/stacks/react-spa.skill.yaml +153 -0
- package/skills/stacks/vue-nuxt.skill.yaml +115 -0
- package/templates/architect-plan.md +139 -0
- package/templates/architect-refactor.md +119 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactive.js","sourceRoot":"","sources":["../../src/utils/interactive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAO1C,MAAM,UAAU,qBAAqB,CAAC,UAA8B,EAAE;IACpE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC;IAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAEhD,OAAO,KAAK,CAAC,KAAK,KAAK,IAAI,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC;AACvD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAAO,GAAG,oBAAoB;IACrE,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC;QACzB,OAAO;QACP,OAAO,EAAE,GAAG;QACZ,QAAQ,EAAE,IAAI;KACf,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function normalizeToAbsolutePath(targetPath: string, cwd?: string): string;
|
|
2
|
+
export declare function ensureDirectoryPath(targetPath: string): string;
|
|
3
|
+
export declare function isPathContained(rootPath: string, candidatePath: string): boolean;
|
|
4
|
+
export declare function resolveContainedRealPath(rootPath: string, candidatePath: string): string | null;
|
|
5
|
+
export declare function toRelativePath(rootPath: string, candidatePath: string): string;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { realpathSync, statSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export function normalizeToAbsolutePath(targetPath, cwd = process.cwd()) {
|
|
4
|
+
return path.resolve(cwd, targetPath);
|
|
5
|
+
}
|
|
6
|
+
export function ensureDirectoryPath(targetPath) {
|
|
7
|
+
const absolutePath = normalizeToAbsolutePath(targetPath);
|
|
8
|
+
const stats = statSync(absolutePath);
|
|
9
|
+
if (!stats.isDirectory()) {
|
|
10
|
+
throw new Error(`Target path is not a directory: ${absolutePath}`);
|
|
11
|
+
}
|
|
12
|
+
return absolutePath;
|
|
13
|
+
}
|
|
14
|
+
export function isPathContained(rootPath, candidatePath) {
|
|
15
|
+
const normalizedRoot = stripTrailingSeparator(path.resolve(rootPath));
|
|
16
|
+
const normalizedCandidate = stripTrailingSeparator(path.resolve(candidatePath));
|
|
17
|
+
const relativePath = path.relative(normalizedRoot, normalizedCandidate);
|
|
18
|
+
return relativePath === '' || (!relativePath.startsWith('..') && !path.isAbsolute(relativePath));
|
|
19
|
+
}
|
|
20
|
+
export function resolveContainedRealPath(rootPath, candidatePath) {
|
|
21
|
+
const realRootPath = stripTrailingSeparator(realpathSync(rootPath));
|
|
22
|
+
const realCandidatePath = stripTrailingSeparator(realpathSync(candidatePath));
|
|
23
|
+
return isPathContained(realRootPath, realCandidatePath) ? realCandidatePath : null;
|
|
24
|
+
}
|
|
25
|
+
export function toRelativePath(rootPath, candidatePath) {
|
|
26
|
+
return path.relative(stripTrailingSeparator(rootPath), stripTrailingSeparator(candidatePath)) || '.';
|
|
27
|
+
}
|
|
28
|
+
function stripTrailingSeparator(targetPath) {
|
|
29
|
+
return targetPath.endsWith(path.sep) ? targetPath.slice(0, -1) : targetPath;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.js","sourceRoot":"","sources":["../../src/utils/path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,UAAU,uBAAuB,CAAC,UAAkB,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC7E,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IACpD,MAAM,YAAY,GAAG,uBAAuB,CAAC,UAAU,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;IAErC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,mCAAmC,YAAY,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,aAAqB;IACrE,MAAM,cAAc,GAAG,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IACtE,MAAM,mBAAmB,GAAG,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC;IAChF,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC;IAExE,OAAO,YAAY,KAAK,EAAE,IAAI,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;AACnG,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,QAAgB,EAAE,aAAqB;IAC9E,MAAM,YAAY,GAAG,sBAAsB,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC;IACpE,MAAM,iBAAiB,GAAG,sBAAsB,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC;IAE9E,OAAO,eAAe,CAAC,YAAY,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC;AACrF,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,aAAqB;IACpE,OAAO,IAAI,CAAC,QAAQ,CAAC,sBAAsB,CAAC,QAAQ,CAAC,EAAE,sBAAsB,CAAC,aAAa,CAAC,CAAC,IAAI,GAAG,CAAC;AACvG,CAAC;AAED,SAAS,sBAAsB,CAAC,UAAkB;IAChD,OAAO,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;AAC9E,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ScanDiagnostic } from '../types/scan-output.js';
|
|
2
|
+
export declare const LARGE_SCAN_FILE_THRESHOLD = 1000;
|
|
3
|
+
export declare const SCAN_PHASES: readonly ["discovery", "parsing", "dependency-analysis", "duplication-analysis", "classification", "scoring", "reporting"];
|
|
4
|
+
export declare function shouldReportProgress(fileCount: number, verbose: boolean, threshold?: number): boolean;
|
|
5
|
+
export interface ProgressRenderOptions {
|
|
6
|
+
json?: boolean;
|
|
7
|
+
verbose?: boolean;
|
|
8
|
+
isInteractive?: boolean;
|
|
9
|
+
stdoutIsTTY?: boolean;
|
|
10
|
+
stderrIsTTY?: boolean;
|
|
11
|
+
fileCount?: number;
|
|
12
|
+
threshold?: number;
|
|
13
|
+
force?: boolean;
|
|
14
|
+
}
|
|
15
|
+
export declare function shouldRenderHumanProgress(options: ProgressRenderOptions): boolean;
|
|
16
|
+
export declare function createProgressDiagnostics(fileCount: number, verbose: boolean, threshold?: number): ScanDiagnostic[];
|
|
17
|
+
export declare function createThresholdDiagnostics(locThreshold: number, complexityThreshold: number): ScanDiagnostic[];
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export const LARGE_SCAN_FILE_THRESHOLD = 1000;
|
|
2
|
+
export const SCAN_PHASES = [
|
|
3
|
+
'discovery',
|
|
4
|
+
'parsing',
|
|
5
|
+
'dependency-analysis',
|
|
6
|
+
'duplication-analysis',
|
|
7
|
+
'classification',
|
|
8
|
+
'scoring',
|
|
9
|
+
'reporting'
|
|
10
|
+
];
|
|
11
|
+
export function shouldReportProgress(fileCount, verbose, threshold = LARGE_SCAN_FILE_THRESHOLD) {
|
|
12
|
+
return verbose && fileCount >= threshold;
|
|
13
|
+
}
|
|
14
|
+
export function shouldRenderHumanProgress(options) {
|
|
15
|
+
if (options.force === true) {
|
|
16
|
+
return options.json !== true;
|
|
17
|
+
}
|
|
18
|
+
if (options.json === true || options.isInteractive !== true || options.stderrIsTTY !== true) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
return options.verbose === true || shouldReportProgress(options.fileCount ?? 0, true, options.threshold);
|
|
22
|
+
}
|
|
23
|
+
export function createProgressDiagnostics(fileCount, verbose, threshold = LARGE_SCAN_FILE_THRESHOLD) {
|
|
24
|
+
if (!shouldReportProgress(fileCount, verbose, threshold)) {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
return SCAN_PHASES.map((phase) => ({
|
|
28
|
+
phase,
|
|
29
|
+
message: `Large scan progress milestone: ${phase}`,
|
|
30
|
+
details: {
|
|
31
|
+
fileCount,
|
|
32
|
+
threshold
|
|
33
|
+
}
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
export function createThresholdDiagnostics(locThreshold, complexityThreshold) {
|
|
37
|
+
return [
|
|
38
|
+
{
|
|
39
|
+
phase: 'configuration',
|
|
40
|
+
message: 'Scan thresholds applied',
|
|
41
|
+
details: {
|
|
42
|
+
locThreshold,
|
|
43
|
+
complexityThreshold
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress.js","sourceRoot":"","sources":["../../src/utils/progress.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,yBAAyB,GAAG,IAAI,CAAC;AAE9C,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,WAAW;IACX,SAAS;IACT,qBAAqB;IACrB,sBAAsB;IACtB,gBAAgB;IAChB,SAAS;IACT,WAAW;CACH,CAAC;AAEX,MAAM,UAAU,oBAAoB,CAAC,SAAiB,EAAE,OAAgB,EAAE,SAAS,GAAG,yBAAyB;IAC7G,OAAO,OAAO,IAAI,SAAS,IAAI,SAAS,CAAC;AAC3C,CAAC;AAaD,MAAM,UAAU,yBAAyB,CAAC,OAA8B;IACtE,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;QAC3B,OAAO,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC;IAC/B,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI,IAAI,OAAO,CAAC,aAAa,KAAK,IAAI,IAAI,OAAO,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;QAC5F,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,OAAO,CAAC,OAAO,KAAK,IAAI,IAAI,oBAAoB,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;AAC3G,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,SAAiB,EAAE,OAAgB,EAAE,SAAS,GAAG,yBAAyB;IAClH,IAAI,CAAC,oBAAoB,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC;QACzD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACjC,KAAK;QACL,OAAO,EAAE,kCAAkC,KAAK,EAAE;QAClD,OAAO,EAAE;YACP,SAAS;YACT,SAAS;SACV;KACF,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,YAAoB,EAAE,mBAA2B;IAC1F,OAAO;QACL;YACE,KAAK,EAAE,eAAe;YACtB,OAAO,EAAE,yBAAyB;YAClC,OAAO,EAAE;gBACP,YAAY;gBACZ,mBAAmB;aACpB;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ThresholdConfiguration } from '../types/scan-output.js';
|
|
2
|
+
export declare const DEFAULT_SCAN_THRESHOLDS: ThresholdConfiguration;
|
|
3
|
+
export declare class ThresholdParseError extends Error {
|
|
4
|
+
constructor(message: string);
|
|
5
|
+
}
|
|
6
|
+
export declare function parseThresholdOption(value: string | undefined): ThresholdConfiguration;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { DEFAULT_COMPLEXITY_THRESHOLD, DEFAULT_LOC_THRESHOLD } from '../types/analysis.js';
|
|
2
|
+
const THRESHOLD_KEYS = new Set(['loc', 'complexity']);
|
|
3
|
+
export const DEFAULT_SCAN_THRESHOLDS = {
|
|
4
|
+
locThreshold: DEFAULT_LOC_THRESHOLD,
|
|
5
|
+
complexityThreshold: DEFAULT_COMPLEXITY_THRESHOLD,
|
|
6
|
+
source: 'default'
|
|
7
|
+
};
|
|
8
|
+
export class ThresholdParseError extends Error {
|
|
9
|
+
constructor(message) {
|
|
10
|
+
super(`${message} Example: --threshold loc=300,complexity=15`);
|
|
11
|
+
this.name = 'ThresholdParseError';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function parseThresholdOption(value) {
|
|
15
|
+
if (!value || value.trim().length === 0) {
|
|
16
|
+
return DEFAULT_SCAN_THRESHOLDS;
|
|
17
|
+
}
|
|
18
|
+
const entries = value.split(',').map((entry) => entry.trim()).filter(Boolean);
|
|
19
|
+
if (entries.length === 0) {
|
|
20
|
+
throw new ThresholdParseError('Threshold value is empty.');
|
|
21
|
+
}
|
|
22
|
+
const thresholds = {
|
|
23
|
+
...DEFAULT_SCAN_THRESHOLDS,
|
|
24
|
+
source: 'cli'
|
|
25
|
+
};
|
|
26
|
+
for (const entry of entries) {
|
|
27
|
+
const [rawKey, rawValue, extra] = entry.split('=');
|
|
28
|
+
if (!rawKey || rawValue === undefined || extra !== undefined) {
|
|
29
|
+
throw new ThresholdParseError(`Invalid threshold segment "${entry}".`);
|
|
30
|
+
}
|
|
31
|
+
const key = rawKey.trim().toLowerCase();
|
|
32
|
+
if (!THRESHOLD_KEYS.has(key)) {
|
|
33
|
+
throw new ThresholdParseError(`Unknown threshold key "${rawKey}". Supported keys: loc, complexity.`);
|
|
34
|
+
}
|
|
35
|
+
const parsed = Number(rawValue.trim());
|
|
36
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
37
|
+
throw new ThresholdParseError(`Threshold "${rawKey}" must be a positive integer.`);
|
|
38
|
+
}
|
|
39
|
+
if (key === 'loc') {
|
|
40
|
+
thresholds.locThreshold = parsed;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
thresholds.complexityThreshold = parsed;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return thresholds;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=thresholds.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thresholds.js","sourceRoot":"","sources":["../../src/utils/thresholds.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAG3F,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC;AAEtD,MAAM,CAAC,MAAM,uBAAuB,GAA2B;IAC7D,YAAY,EAAE,qBAAqB;IACnC,mBAAmB,EAAE,4BAA4B;IACjD,MAAM,EAAE,SAAS;CAClB,CAAC;AAEF,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,OAAe;QACzB,KAAK,CAAC,GAAG,OAAO,6CAA6C,CAAC,CAAC;QAC/D,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAyB;IAC5D,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxC,OAAO,uBAAuB,CAAC;IACjC,CAAC;IAED,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9E,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,mBAAmB,CAAC,2BAA2B,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,UAAU,GAA2B;QACzC,GAAG,uBAAuB;QAC1B,MAAM,EAAE,KAAK;KACd,CAAC;IAEF,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM,IAAI,QAAQ,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAC7D,MAAM,IAAI,mBAAmB,CAAC,8BAA8B,KAAK,IAAI,CAAC,CAAC;QACzE,CAAC;QAED,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACxC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,mBAAmB,CAAC,0BAA0B,MAAM,qCAAqC,CAAC,CAAC;QACvG,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAI,mBAAmB,CAAC,cAAc,MAAM,+BAA+B,CAAC,CAAC;QACrF,CAAC;QAED,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;YAClB,UAAU,CAAC,YAAY,GAAG,MAAM,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,mBAAmB,GAAG,MAAM,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@levironexe/architect",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Structural health scanner for vibe-coded JavaScript and TypeScript projects.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"architect": "dist/cli/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"skills",
|
|
12
|
+
"templates",
|
|
13
|
+
"README.md",
|
|
14
|
+
"CHANGELOG.md",
|
|
15
|
+
"CONTRIBUTING.md"
|
|
16
|
+
],
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=20.0.0"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc -p tsconfig.json",
|
|
22
|
+
"dev": "tsx src/cli/index.ts",
|
|
23
|
+
"lint": "eslint .",
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"test:watch": "vitest"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"architecture",
|
|
29
|
+
"code-quality",
|
|
30
|
+
"refactoring",
|
|
31
|
+
"cli",
|
|
32
|
+
"vibe-coding",
|
|
33
|
+
"vibe-coded",
|
|
34
|
+
"typescript",
|
|
35
|
+
"static-analysis"
|
|
36
|
+
],
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@babel/parser": "^7.28.5",
|
|
40
|
+
"@babel/traverse": "^7.28.5",
|
|
41
|
+
"@inquirer/prompts": "^8.4.2",
|
|
42
|
+
"chalk": "^5.6.2",
|
|
43
|
+
"cli-table3": "^0.6.5",
|
|
44
|
+
"commander": "^14.0.0",
|
|
45
|
+
"glob": "^11.0.3",
|
|
46
|
+
"ignore": "^7.0.5",
|
|
47
|
+
"js-yaml": "^4.1.1",
|
|
48
|
+
"jscpd": "^4.0.9",
|
|
49
|
+
"madge": "^8.0.0",
|
|
50
|
+
"ora": "^9.4.0"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@eslint/js": "^9.39.1",
|
|
54
|
+
"@types/js-yaml": "^4.0.9",
|
|
55
|
+
"@types/node": "^24.9.1",
|
|
56
|
+
"eslint": "^9.39.1",
|
|
57
|
+
"globals": "^16.4.0",
|
|
58
|
+
"tsx": "^4.20.6",
|
|
59
|
+
"typescript": "^5.9.3",
|
|
60
|
+
"typescript-eslint": "^8.46.2",
|
|
61
|
+
"vitest": "^4.0.7"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
schema_version: "2.0.0"
|
|
2
|
+
id: general-js
|
|
3
|
+
name: "General JavaScript/TypeScript"
|
|
4
|
+
version: "1.1.0"
|
|
5
|
+
description: "Language-level JavaScript and TypeScript hygiene for naming, imports, errors, and environment handling."
|
|
6
|
+
category: meta
|
|
7
|
+
language: javascript
|
|
8
|
+
frameworks: []
|
|
9
|
+
detection:
|
|
10
|
+
source_indicators:
|
|
11
|
+
- "import "
|
|
12
|
+
- "export "
|
|
13
|
+
structure:
|
|
14
|
+
required_dirs: []
|
|
15
|
+
recommended_dirs:
|
|
16
|
+
- path: src
|
|
17
|
+
purpose: "All application source code. Every module the app ships is rooted here. Consumers import from src/ paths, not from the project root."
|
|
18
|
+
- path: tests
|
|
19
|
+
purpose: "All automated test files. Mirrors src/ directory structure with *.test.ts or *.spec.ts suffixes."
|
|
20
|
+
separation:
|
|
21
|
+
rules:
|
|
22
|
+
- concern: configuration
|
|
23
|
+
belongs_in: src/config
|
|
24
|
+
rule_text: "Environment and runtime configuration must be centralized in src/config so the rest of the codebase consumes validated config values instead of raw process.env reads scattered across modules. Fail fast at startup when required variables are missing."
|
|
25
|
+
example: |
|
|
26
|
+
// src/config/index.ts
|
|
27
|
+
import { z } from 'zod';
|
|
28
|
+
const envSchema = z.object({
|
|
29
|
+
API_BASE_URL: z.string().url(),
|
|
30
|
+
PORT: z.coerce.number().default(3000),
|
|
31
|
+
DATABASE_URL: z.string().min(1),
|
|
32
|
+
});
|
|
33
|
+
export const config = envSchema.parse(process.env);
|
|
34
|
+
indicators:
|
|
35
|
+
- "process.env"
|
|
36
|
+
- concern: utility
|
|
37
|
+
belongs_in: src/utils
|
|
38
|
+
rule_text: "Generic helper functions with no domain or framework coupling belong in src/utils so they can be reused across all feature modules without creating circular dependencies. A utility must not import from domain or service modules."
|
|
39
|
+
example: |
|
|
40
|
+
// src/utils/array.ts
|
|
41
|
+
export function chunk<T>(items: T[], size: number): T[][] {
|
|
42
|
+
return items.reduce<T[][]>((groups, item, index) => {
|
|
43
|
+
const groupIndex = Math.floor(index / size);
|
|
44
|
+
groups[groupIndex] ??= [];
|
|
45
|
+
groups[groupIndex].push(item);
|
|
46
|
+
return groups;
|
|
47
|
+
}, []);
|
|
48
|
+
}
|
|
49
|
+
anti_indicators:
|
|
50
|
+
- "import.*services"
|
|
51
|
+
- "import.*controllers"
|
|
52
|
+
- "import.*repositories"
|
|
53
|
+
- concern: error_handler
|
|
54
|
+
belongs_in: src/errors
|
|
55
|
+
rule_text: "Custom error classes that extend the built-in Error must live in src/errors so all modules throw typed, structured errors instead of raw strings or plain objects. Typed errors enable central error middleware to map errors to correct HTTP status codes."
|
|
56
|
+
example: |
|
|
57
|
+
// src/errors/app-error.ts
|
|
58
|
+
export class AppError extends Error {
|
|
59
|
+
constructor(
|
|
60
|
+
message: string,
|
|
61
|
+
public readonly code: string,
|
|
62
|
+
public readonly statusCode = 500,
|
|
63
|
+
public readonly isOperational = true,
|
|
64
|
+
) {
|
|
65
|
+
super(message);
|
|
66
|
+
this.name = 'AppError';
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
indicators:
|
|
70
|
+
- "extends Error"
|
|
71
|
+
- "new Error("
|
|
72
|
+
patterns:
|
|
73
|
+
naming:
|
|
74
|
+
files: "Use kebab-case for all filenames (user-service.ts, auth-middleware.ts). Use *.test.ts or *.spec.ts suffixes for test files. Never use spaces or underscores in filenames."
|
|
75
|
+
variables: "Use lowerCamelCase for local variables and functions (userId, fetchUser). Use UpperCamelCase for classes and type aliases (UserService, ApiResponse). Use UPPER_SNAKE_CASE for true module-level constants (MAX_RETRIES, DEFAULT_TIMEOUT)."
|
|
76
|
+
functions: "Name all functions, including callbacks and inline arrow functions. Anonymous functions appear as '<anonymous>' in stack traces and profiling tools, making debugging significantly harder."
|
|
77
|
+
error_handling:
|
|
78
|
+
recommended: "Always 'return await' when returning promises to preserve full stack traces. Register process.on('unhandledRejection', handler) as a global safety net. Subscribe to EventEmitter 'error' events when working with streams or event-driven code."
|
|
79
|
+
data_flow:
|
|
80
|
+
direction: "node: built-ins -> external packages -> src/config -> src/errors -> src/utils -> domain modules -> route handlers"
|
|
81
|
+
rules:
|
|
82
|
+
- "Group imports: node: built-ins first, then external packages, then internal src/ path aliases, then relative paths. Use a consistent blank line between groups."
|
|
83
|
+
- "Keep all process.env access inside src/config. No module outside src/config reads process.env directly."
|
|
84
|
+
- "Avoid barrel re-export index.ts files that re-export across feature boundaries — they create circular import graphs that cause runtime errors and slow bundlers."
|
|
85
|
+
anti_patterns:
|
|
86
|
+
- id: empty_catch
|
|
87
|
+
severity: warning
|
|
88
|
+
description: "Errors are swallowed without handling or logging, making failures invisible to monitoring, on-call engineers, and automated alerting. Silent failures in production are the hardest class of bug to diagnose."
|
|
89
|
+
bad_example: |
|
|
90
|
+
try {
|
|
91
|
+
await saveUser(user);
|
|
92
|
+
} catch (error) {}
|
|
93
|
+
good_example: |
|
|
94
|
+
try {
|
|
95
|
+
await saveUser(user);
|
|
96
|
+
} catch (error) {
|
|
97
|
+
logger.error('Failed to save user', { userId: user.id, error });
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
- id: hardcoded_env_values
|
|
101
|
+
severity: critical
|
|
102
|
+
description: "Environment-specific values (hostnames, secrets, feature flags, API keys) are hardcoded in source files. This prevents running the app in multiple environments, leaks production config into version control, and requires code changes for every environment switch."
|
|
103
|
+
bad_example: |
|
|
104
|
+
// Hardcoded deep inside a feature file
|
|
105
|
+
const db = new Client({
|
|
106
|
+
host: 'prod-db.us-east-1.internal',
|
|
107
|
+
password: 'super_secret_prod_password',
|
|
108
|
+
});
|
|
109
|
+
good_example: |
|
|
110
|
+
// Read once at startup in src/config/index.ts; consumed everywhere else
|
|
111
|
+
import { config } from '@/config';
|
|
112
|
+
const db = new Client({
|
|
113
|
+
host: config.DB_HOST,
|
|
114
|
+
password: config.DB_PASSWORD,
|
|
115
|
+
});
|
|
116
|
+
- id: unsafe_any
|
|
117
|
+
severity: warning
|
|
118
|
+
description: "Using the 'any' type disables TypeScript's type checker for that value and everything downstream that touches it. Values typed as 'any' propagate unsafely through the call chain, turning TypeScript into JavaScript with extra syntax overhead."
|
|
119
|
+
bad_example: |
|
|
120
|
+
async function getUser(id: string): Promise<any> {
|
|
121
|
+
const data: any = await fetchJson(`/users/${id}`);
|
|
122
|
+
return data.profile.email; // crashes at runtime if shape is wrong; no IDE help
|
|
123
|
+
}
|
|
124
|
+
good_example: |
|
|
125
|
+
interface UserResponse {
|
|
126
|
+
profile: { email: string; name: string };
|
|
127
|
+
}
|
|
128
|
+
async function getUser(id: string): Promise<UserResponse> {
|
|
129
|
+
const data = await fetchJson<UserResponse>(`/users/${id}`);
|
|
130
|
+
return data; // fully type-checked; IDE autocomplete and refactoring work
|
|
131
|
+
}
|