@archpilotlabs/archpilot 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -8
- package/dist/archpilot-cli.js +341 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="https://archpilot.org/logo.svg" width="100" />
|
|
2
|
+
<img src="https://archpilot.org/media/branding/logo.svg" width="100" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<h1 align="center">ArchPilot</h1>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
-
|
|
8
|
+
Architecture guardrails for AI-native software development
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
|
+
ArchPilot validates your repository against architecture rules and helps engineering teams move faster with AI-assisted development-without sacrificing architectural integrity.
|
|
12
|
+
|
|
13
|
+
**Your AI writes code. ArchPilot protects architecture.**
|
|
14
|
+
|
|
11
15
|
<p align="center">
|
|
12
16
|
Validate • Enforce • Measure architecture continuously
|
|
13
17
|
</p>
|
|
14
18
|
|
|
15
|
-
ArchPilot
|
|
19
|
+
ArchPilot makes architecture **visible, enforceable, and measurable** as your system evolves.
|
|
16
20
|
|
|
17
21
|
---
|
|
18
22
|
|
|
@@ -24,6 +28,10 @@ Over time, boundaries blur, dependencies leak, and architectural decisions drift
|
|
|
24
28
|
|
|
25
29
|
ArchPilot turns architecture into something you can **actually validate, enforce, and track continuously**.
|
|
26
30
|
|
|
31
|
+
AI accelerates code delivery-but architectural drift accelerates too.
|
|
32
|
+
|
|
33
|
+
ArchPilot gives teams deterministic architecture guardrails in local development, CI, and governance workflows.
|
|
34
|
+
|
|
27
35
|
---
|
|
28
36
|
|
|
29
37
|
## 🚀 What it does
|
|
@@ -65,12 +73,9 @@ archpilot cloud connect
|
|
|
65
73
|
archpilot cloud disconnect
|
|
66
74
|
```
|
|
67
75
|
|
|
68
|
-
Cloud setup only asks for your API token.
|
|
69
|
-
|
|
70
|
-
`https://api.archpilot.org`
|
|
71
|
-
|
|
72
|
-
For local development, set `ARCHPILOT_CLOUD_URL=http://localhost:4000` before running Cloud commands. CLI `--server` remains available for one-off debugging and automated tests.
|
|
76
|
+
Cloud setup only asks for your API token.
|
|
73
77
|
|
|
78
|
+
ArchPilot uses the canonical production API automatically-no server URL setup required for normal use.
|
|
74
79
|
Learn more:
|
|
75
80
|
|
|
76
81
|
https://archpilot.org/docs
|
package/dist/archpilot-cli.js
CHANGED
|
@@ -210936,6 +210936,8 @@ var validCanonicalStackIds = /* @__PURE__ */ new Set([
|
|
|
210936
210936
|
"java",
|
|
210937
210937
|
"spring",
|
|
210938
210938
|
"fastapi",
|
|
210939
|
+
"django",
|
|
210940
|
+
"flask",
|
|
210939
210941
|
"python",
|
|
210940
210942
|
"php",
|
|
210941
210943
|
"go",
|
|
@@ -210958,6 +210960,8 @@ var canonicalStackLabels = {
|
|
|
210958
210960
|
java: "Java",
|
|
210959
210961
|
spring: "Spring",
|
|
210960
210962
|
fastapi: "FastAPI",
|
|
210963
|
+
django: "Django",
|
|
210964
|
+
flask: "Flask",
|
|
210961
210965
|
python: "Python",
|
|
210962
210966
|
php: "PHP",
|
|
210963
210967
|
go: "Go",
|
|
@@ -211805,6 +211809,326 @@ var stackAdaptersById = {
|
|
|
211805
211809
|
resolveProjectKinds: () => ["backend"],
|
|
211806
211810
|
getImportExtractionMode: () => "python-imports"
|
|
211807
211811
|
}),
|
|
211812
|
+
django: buildAdapter({
|
|
211813
|
+
id: "django",
|
|
211814
|
+
displayName: canonicalStackLabels.django,
|
|
211815
|
+
ecosystem: "python",
|
|
211816
|
+
category: "framework",
|
|
211817
|
+
priority: 68,
|
|
211818
|
+
manifestDetectionHints: [
|
|
211819
|
+
"requirements.txt",
|
|
211820
|
+
"pyproject.toml",
|
|
211821
|
+
"Pipfile",
|
|
211822
|
+
"Pipfile.lock",
|
|
211823
|
+
"poetry.lock",
|
|
211824
|
+
"manage.py",
|
|
211825
|
+
"settings.py",
|
|
211826
|
+
"urls.py",
|
|
211827
|
+
"wsgi.py",
|
|
211828
|
+
"asgi.py"
|
|
211829
|
+
],
|
|
211830
|
+
buildToolHints: ["pip", "poetry", "django-admin"],
|
|
211831
|
+
defaults: {
|
|
211832
|
+
sourceRoots: [".", "src", "app"],
|
|
211833
|
+
moduleRootCandidates: [".", "src", "app"],
|
|
211834
|
+
apiRoots: [".", "src", "app"],
|
|
211835
|
+
databaseRoots: ["migrations", "db", "database"],
|
|
211836
|
+
configFiles: ["requirements.txt", "pyproject.toml", "Pipfile", "Pipfile.lock", "poetry.lock", "manage.py"],
|
|
211837
|
+
fileExtensions: [".py", ".toml", ".txt", ".sql", ".yaml", ".yml"],
|
|
211838
|
+
dependencyFileExtensions: [".py"],
|
|
211839
|
+
ignoreDirectories: [
|
|
211840
|
+
"__pycache__",
|
|
211841
|
+
".pytest_cache",
|
|
211842
|
+
".venv",
|
|
211843
|
+
"venv",
|
|
211844
|
+
"dist",
|
|
211845
|
+
"build",
|
|
211846
|
+
".idea",
|
|
211847
|
+
...commonIgnoreDirectories
|
|
211848
|
+
],
|
|
211849
|
+
entrypointHints: ["manage.py", "wsgi.py", "asgi.py", "settings.py", "urls.py"],
|
|
211850
|
+
publicEntrypointDirectories: [],
|
|
211851
|
+
moduleIndexFileName: "__init__.py"
|
|
211852
|
+
},
|
|
211853
|
+
detect: (context) => {
|
|
211854
|
+
const evidence = [];
|
|
211855
|
+
let strongSignals = 0;
|
|
211856
|
+
let mediumSignals = 0;
|
|
211857
|
+
let weakSignals = 0;
|
|
211858
|
+
let score = 0;
|
|
211859
|
+
const hasRequirementsDjango = context.hasFileMatchingPattern(
|
|
211860
|
+
"requirements.txt",
|
|
211861
|
+
/(^|\s)django([=<>~!]|$)/imu
|
|
211862
|
+
);
|
|
211863
|
+
const hasPyprojectDjango = context.hasFileMatchingPattern("pyproject.toml", /\bdjango\b/iu);
|
|
211864
|
+
const hasPoetryLockDjango = context.hasFileMatchingPattern(
|
|
211865
|
+
"poetry.lock",
|
|
211866
|
+
/\bname\s*=\s*["']django["']/iu
|
|
211867
|
+
);
|
|
211868
|
+
const hasPipfileDjango = context.hasFileMatchingPattern("Pipfile", /\bdjango\b/iu);
|
|
211869
|
+
const hasPipfileLockDjango = context.hasFileMatchingPattern("Pipfile.lock", /"django"\s*:/iu);
|
|
211870
|
+
const hasDjangoDependencyEvidence = hasRequirementsDjango || hasPyprojectDjango || hasPoetryLockDjango || hasPipfileDjango || hasPipfileLockDjango;
|
|
211871
|
+
const hasManagePy = context.hasFile("manage.py");
|
|
211872
|
+
const hasDjangoSettingsModule = context.hasFileMatchingPattern(
|
|
211873
|
+
"manage.py",
|
|
211874
|
+
/\bDJANGO_SETTINGS_MODULE\b/u
|
|
211875
|
+
);
|
|
211876
|
+
const hasSettingsPy = context.hasFile("settings.py");
|
|
211877
|
+
const hasUrlsPy = context.hasFile("urls.py");
|
|
211878
|
+
const hasWsgiOrAsgi = context.hasFile("wsgi.py") || context.hasFile("asgi.py");
|
|
211879
|
+
const hasInstalledApps = context.hasFileMatchingPattern("settings.py", /\bINSTALLED_APPS\s*=/u);
|
|
211880
|
+
const hasDjangoAdmin = context.hasAnyFileMatchingPattern(/(^|\/)(manage|settings|urls|wsgi|asgi)\.py$/iu, /\bdjango-admin\b/iu);
|
|
211881
|
+
const hasDjangoImport = context.hasAnyFileMatchingPattern(/\.py$/iu, /\b(from|import)\s+django\b/u);
|
|
211882
|
+
const hasDjangoUrlsImport = context.hasAnyFileMatchingPattern(
|
|
211883
|
+
/\.py$/iu,
|
|
211884
|
+
/\bfrom\s+django\.urls\s+import\s+(?:path|include|re_path)\b/u
|
|
211885
|
+
);
|
|
211886
|
+
if (hasRequirementsDjango) {
|
|
211887
|
+
strongSignals += 1;
|
|
211888
|
+
score += 52;
|
|
211889
|
+
evidence.push("Found requirements.txt with django dependency");
|
|
211890
|
+
}
|
|
211891
|
+
if (hasPyprojectDjango) {
|
|
211892
|
+
strongSignals += 1;
|
|
211893
|
+
score += 52;
|
|
211894
|
+
evidence.push("Found pyproject.toml with django dependency");
|
|
211895
|
+
}
|
|
211896
|
+
if (hasPoetryLockDjango || hasPipfileDjango || hasPipfileLockDjango) {
|
|
211897
|
+
strongSignals += 1;
|
|
211898
|
+
score += 50;
|
|
211899
|
+
evidence.push("Found Pipfile/lock metadata with django dependency");
|
|
211900
|
+
}
|
|
211901
|
+
if (hasManagePy) {
|
|
211902
|
+
strongSignals += 1;
|
|
211903
|
+
score += 34;
|
|
211904
|
+
evidence.push("Found manage.py");
|
|
211905
|
+
}
|
|
211906
|
+
if (hasDjangoSettingsModule) {
|
|
211907
|
+
strongSignals += 1;
|
|
211908
|
+
score += 24;
|
|
211909
|
+
evidence.push("Found DJANGO_SETTINGS_MODULE in manage.py");
|
|
211910
|
+
}
|
|
211911
|
+
if (hasInstalledApps) {
|
|
211912
|
+
strongSignals += 1;
|
|
211913
|
+
score += 24;
|
|
211914
|
+
evidence.push("Found INSTALLED_APPS in settings.py");
|
|
211915
|
+
}
|
|
211916
|
+
if (hasDjangoImport) {
|
|
211917
|
+
strongSignals += 1;
|
|
211918
|
+
score += 22;
|
|
211919
|
+
evidence.push("Found django import in source");
|
|
211920
|
+
}
|
|
211921
|
+
if (hasSettingsPy) {
|
|
211922
|
+
mediumSignals += 1;
|
|
211923
|
+
score += 12;
|
|
211924
|
+
evidence.push("Found settings.py");
|
|
211925
|
+
}
|
|
211926
|
+
if (hasUrlsPy) {
|
|
211927
|
+
mediumSignals += 1;
|
|
211928
|
+
score += 10;
|
|
211929
|
+
evidence.push("Found urls.py");
|
|
211930
|
+
}
|
|
211931
|
+
if (hasWsgiOrAsgi) {
|
|
211932
|
+
mediumSignals += 1;
|
|
211933
|
+
score += 10;
|
|
211934
|
+
evidence.push("Found wsgi.py or asgi.py");
|
|
211935
|
+
}
|
|
211936
|
+
if (hasDjangoUrlsImport) {
|
|
211937
|
+
mediumSignals += 1;
|
|
211938
|
+
score += 10;
|
|
211939
|
+
evidence.push("Found Django URL routing import");
|
|
211940
|
+
}
|
|
211941
|
+
if (hasDjangoAdmin) {
|
|
211942
|
+
weakSignals += 1;
|
|
211943
|
+
score += 3;
|
|
211944
|
+
evidence.push("Found django-admin reference");
|
|
211945
|
+
}
|
|
211946
|
+
if (context.hasDirectory("migrations")) {
|
|
211947
|
+
weakSignals += 1;
|
|
211948
|
+
score += 2;
|
|
211949
|
+
evidence.push("Found migrations directory");
|
|
211950
|
+
}
|
|
211951
|
+
const hasSafeDjangoCoreEvidence = hasDjangoDependencyEvidence || hasManagePy && (hasDjangoSettingsModule || hasSettingsPy || hasUrlsPy || hasWsgiOrAsgi) || hasInstalledApps && (hasSettingsPy || hasDjangoImport) || hasDjangoImport && (hasDjangoUrlsImport || hasUrlsPy);
|
|
211952
|
+
if (!hasSafeDjangoCoreEvidence || strongSignals === 0) {
|
|
211953
|
+
return null;
|
|
211954
|
+
}
|
|
211955
|
+
const hasRestEvidence = hasUrlsPy || hasDjangoUrlsImport;
|
|
211956
|
+
const confidence = strongSignals >= 2 ? "high" : strongSignals >= 1 || mediumSignals >= 3 || mediumSignals >= 2 && weakSignals >= 1 ? "medium" : "low";
|
|
211957
|
+
return toResult({
|
|
211958
|
+
adapterId: "django",
|
|
211959
|
+
confidence,
|
|
211960
|
+
score,
|
|
211961
|
+
evidence,
|
|
211962
|
+
projectKindHints: ["backend"],
|
|
211963
|
+
apiStyleHint: hasRestEvidence ? "rest" : "unknown"
|
|
211964
|
+
});
|
|
211965
|
+
},
|
|
211966
|
+
resolveProjectKinds: () => ["backend"],
|
|
211967
|
+
getImportExtractionMode: () => "python-imports"
|
|
211968
|
+
}),
|
|
211969
|
+
flask: buildAdapter({
|
|
211970
|
+
id: "flask",
|
|
211971
|
+
displayName: canonicalStackLabels.flask,
|
|
211972
|
+
ecosystem: "python",
|
|
211973
|
+
category: "framework",
|
|
211974
|
+
priority: 66,
|
|
211975
|
+
manifestDetectionHints: [
|
|
211976
|
+
"requirements.txt",
|
|
211977
|
+
"pyproject.toml",
|
|
211978
|
+
"Pipfile",
|
|
211979
|
+
"Pipfile.lock",
|
|
211980
|
+
"poetry.lock",
|
|
211981
|
+
"app.py",
|
|
211982
|
+
"wsgi.py",
|
|
211983
|
+
"main.py"
|
|
211984
|
+
],
|
|
211985
|
+
buildToolHints: ["pip", "poetry", "flask"],
|
|
211986
|
+
defaults: {
|
|
211987
|
+
sourceRoots: ["app", "src", "."],
|
|
211988
|
+
moduleRootCandidates: ["app", "src/app", "src", "blueprints", "api"],
|
|
211989
|
+
apiRoots: ["app", "src", "blueprints", "api"],
|
|
211990
|
+
databaseRoots: ["migrations", "app/db", "app/database", "src/db", "src/database"],
|
|
211991
|
+
configFiles: ["requirements.txt", "pyproject.toml", "Pipfile", "Pipfile.lock", "poetry.lock"],
|
|
211992
|
+
fileExtensions: [".py", ".toml", ".txt", ".sql", ".yaml", ".yml"],
|
|
211993
|
+
dependencyFileExtensions: [".py"],
|
|
211994
|
+
ignoreDirectories: [
|
|
211995
|
+
"__pycache__",
|
|
211996
|
+
".pytest_cache",
|
|
211997
|
+
".venv",
|
|
211998
|
+
"venv",
|
|
211999
|
+
"dist",
|
|
212000
|
+
"build",
|
|
212001
|
+
".idea",
|
|
212002
|
+
...commonIgnoreDirectories
|
|
212003
|
+
],
|
|
212004
|
+
entrypointHints: ["app.py", "main.py", "wsgi.py", "app/__init__.py"],
|
|
212005
|
+
publicEntrypointDirectories: [],
|
|
212006
|
+
moduleIndexFileName: "__init__.py"
|
|
212007
|
+
},
|
|
212008
|
+
detect: (context) => {
|
|
212009
|
+
const evidence = [];
|
|
212010
|
+
let strongSignals = 0;
|
|
212011
|
+
let mediumSignals = 0;
|
|
212012
|
+
let weakSignals = 0;
|
|
212013
|
+
let score = 0;
|
|
212014
|
+
const hasRequirementsFlask = context.hasFileMatchingPattern(
|
|
212015
|
+
"requirements.txt",
|
|
212016
|
+
/(^|\s)flask([=<>~!]|$)/imu
|
|
212017
|
+
);
|
|
212018
|
+
const hasPyprojectFlask = context.hasFileMatchingPattern("pyproject.toml", /\bflask\b/iu);
|
|
212019
|
+
const hasPoetryLockFlask = context.hasFileMatchingPattern(
|
|
212020
|
+
"poetry.lock",
|
|
212021
|
+
/\bname\s*=\s*["']flask["']/iu
|
|
212022
|
+
);
|
|
212023
|
+
const hasPipfileFlask = context.hasFileMatchingPattern("Pipfile", /\bflask\b/iu);
|
|
212024
|
+
const hasPipfileLockFlask = context.hasFileMatchingPattern("Pipfile.lock", /"flask"\s*:/iu);
|
|
212025
|
+
const hasFlaskDependencyEvidence = hasRequirementsFlask || hasPyprojectFlask || hasPoetryLockFlask || hasPipfileFlask || hasPipfileLockFlask;
|
|
212026
|
+
const hasFlaskImport = context.hasAnyFileMatchingPattern(
|
|
212027
|
+
/\.py$/iu,
|
|
212028
|
+
/\bfrom\s+flask\s+import\s+.*\bFlask\b/u
|
|
212029
|
+
);
|
|
212030
|
+
const hasFlaskConstruction = context.hasAnyFileMatchingPattern(
|
|
212031
|
+
/\.py$/iu,
|
|
212032
|
+
/\b\w+\s*=\s*Flask\s*\(\s*__name__/u
|
|
212033
|
+
);
|
|
212034
|
+
const hasRouteDecorator = context.hasAnyFileMatchingPattern(
|
|
212035
|
+
/\.py$/iu,
|
|
212036
|
+
/@\w+\.route\s*\(/u
|
|
212037
|
+
);
|
|
212038
|
+
const hasMethodRouteDecorator = context.hasAnyFileMatchingPattern(
|
|
212039
|
+
/\.py$/iu,
|
|
212040
|
+
/@\w+\.(?:get|post|put|delete)\s*\(/u
|
|
212041
|
+
);
|
|
212042
|
+
const hasBlueprintImport = context.hasAnyFileMatchingPattern(
|
|
212043
|
+
/\.py$/iu,
|
|
212044
|
+
/\bfrom\s+flask\s+import\s+.*\bBlueprint\b/u
|
|
212045
|
+
);
|
|
212046
|
+
const hasBlueprintConstruction = context.hasAnyFileMatchingPattern(
|
|
212047
|
+
/\.py$/iu,
|
|
212048
|
+
/\b\w+\s*=\s*Blueprint\s*\(/u
|
|
212049
|
+
);
|
|
212050
|
+
const hasFlaskEntrypointConstruction = context.hasAnyFileMatchingPattern(
|
|
212051
|
+
/(^|\/)(app|main|wsgi)\.py$/iu,
|
|
212052
|
+
/\b\w+\s*=\s*Flask\s*\(/u
|
|
212053
|
+
);
|
|
212054
|
+
if (hasRequirementsFlask) {
|
|
212055
|
+
strongSignals += 1;
|
|
212056
|
+
score += 52;
|
|
212057
|
+
evidence.push("Found requirements.txt with flask dependency");
|
|
212058
|
+
}
|
|
212059
|
+
if (hasPyprojectFlask) {
|
|
212060
|
+
strongSignals += 1;
|
|
212061
|
+
score += 52;
|
|
212062
|
+
evidence.push("Found pyproject.toml with flask dependency");
|
|
212063
|
+
}
|
|
212064
|
+
if (hasPoetryLockFlask || hasPipfileFlask || hasPipfileLockFlask) {
|
|
212065
|
+
strongSignals += 1;
|
|
212066
|
+
score += 50;
|
|
212067
|
+
evidence.push("Found Pipfile/lock metadata with flask dependency");
|
|
212068
|
+
}
|
|
212069
|
+
if (hasFlaskImport) {
|
|
212070
|
+
strongSignals += 1;
|
|
212071
|
+
score += 34;
|
|
212072
|
+
evidence.push("Found Flask import in source");
|
|
212073
|
+
}
|
|
212074
|
+
if (hasFlaskConstruction) {
|
|
212075
|
+
strongSignals += 1;
|
|
212076
|
+
score += 34;
|
|
212077
|
+
evidence.push("Found Flask application construction in source");
|
|
212078
|
+
}
|
|
212079
|
+
if (hasRouteDecorator) {
|
|
212080
|
+
strongSignals += 1;
|
|
212081
|
+
score += 22;
|
|
212082
|
+
evidence.push("Found Flask route decorator in source");
|
|
212083
|
+
}
|
|
212084
|
+
if (hasMethodRouteDecorator) {
|
|
212085
|
+
mediumSignals += 1;
|
|
212086
|
+
score += 10;
|
|
212087
|
+
evidence.push("Found Flask method route decorator in source");
|
|
212088
|
+
}
|
|
212089
|
+
if (hasBlueprintImport) {
|
|
212090
|
+
mediumSignals += 1;
|
|
212091
|
+
score += 10;
|
|
212092
|
+
evidence.push("Found Blueprint import in source");
|
|
212093
|
+
}
|
|
212094
|
+
if (hasBlueprintConstruction) {
|
|
212095
|
+
mediumSignals += 1;
|
|
212096
|
+
score += 8;
|
|
212097
|
+
evidence.push("Found Blueprint construction in source");
|
|
212098
|
+
}
|
|
212099
|
+
if (hasFlaskEntrypointConstruction) {
|
|
212100
|
+
mediumSignals += 1;
|
|
212101
|
+
score += 8;
|
|
212102
|
+
evidence.push("Found Flask construction in app.py/main.py/wsgi.py");
|
|
212103
|
+
}
|
|
212104
|
+
if (context.hasDirectory("blueprints")) {
|
|
212105
|
+
weakSignals += 1;
|
|
212106
|
+
score += 2;
|
|
212107
|
+
evidence.push("Found blueprints directory");
|
|
212108
|
+
}
|
|
212109
|
+
if (context.hasDirectory("app") || context.hasDirectory("src")) {
|
|
212110
|
+
weakSignals += 1;
|
|
212111
|
+
score += 2;
|
|
212112
|
+
evidence.push("Found typical Python backend layout directory");
|
|
212113
|
+
}
|
|
212114
|
+
const hasSafeFlaskCoreEvidence = hasFlaskDependencyEvidence || hasFlaskImport && hasFlaskConstruction || hasFlaskImport && (hasRouteDecorator || hasMethodRouteDecorator || hasBlueprintImport) || hasBlueprintImport && hasBlueprintConstruction;
|
|
212115
|
+
if (!hasSafeFlaskCoreEvidence || strongSignals === 0) {
|
|
212116
|
+
return null;
|
|
212117
|
+
}
|
|
212118
|
+
const hasRestEvidence = hasRouteDecorator || hasMethodRouteDecorator || hasBlueprintImport;
|
|
212119
|
+
const confidence = strongSignals >= 2 ? "high" : strongSignals >= 1 || mediumSignals >= 3 || mediumSignals >= 2 && weakSignals >= 1 ? "medium" : "low";
|
|
212120
|
+
return toResult({
|
|
212121
|
+
adapterId: "flask",
|
|
212122
|
+
confidence,
|
|
212123
|
+
score,
|
|
212124
|
+
evidence,
|
|
212125
|
+
projectKindHints: ["backend"],
|
|
212126
|
+
apiStyleHint: hasRestEvidence ? "rest" : "unknown"
|
|
212127
|
+
});
|
|
212128
|
+
},
|
|
212129
|
+
resolveProjectKinds: () => ["backend"],
|
|
212130
|
+
getImportExtractionMode: () => "python-imports"
|
|
212131
|
+
}),
|
|
211808
212132
|
python: buildAdapter({
|
|
211809
212133
|
id: "python",
|
|
211810
212134
|
displayName: canonicalStackLabels.python,
|
|
@@ -231312,6 +231636,8 @@ var ignoredDirectoryNames2 = /* @__PURE__ */ new Set([
|
|
|
231312
231636
|
var backendStackIds = /* @__PURE__ */ new Set([
|
|
231313
231637
|
"spring",
|
|
231314
231638
|
"fastapi",
|
|
231639
|
+
"django",
|
|
231640
|
+
"flask",
|
|
231315
231641
|
"dotnet",
|
|
231316
231642
|
"nestjs",
|
|
231317
231643
|
"java",
|
|
@@ -231539,6 +231865,8 @@ function toDetectedStack(adapterId) {
|
|
|
231539
231865
|
case "java":
|
|
231540
231866
|
case "spring":
|
|
231541
231867
|
case "fastapi":
|
|
231868
|
+
case "django":
|
|
231869
|
+
case "flask":
|
|
231542
231870
|
case "dotnet":
|
|
231543
231871
|
case "python":
|
|
231544
231872
|
case "php":
|
|
@@ -231572,6 +231900,12 @@ function resolveLanguages(stacks) {
|
|
|
231572
231900
|
if (stacks.includes("fastapi")) {
|
|
231573
231901
|
languages.add("python");
|
|
231574
231902
|
}
|
|
231903
|
+
if (stacks.includes("django")) {
|
|
231904
|
+
languages.add("python");
|
|
231905
|
+
}
|
|
231906
|
+
if (stacks.includes("flask")) {
|
|
231907
|
+
languages.add("python");
|
|
231908
|
+
}
|
|
231575
231909
|
if (stacks.includes("php")) {
|
|
231576
231910
|
languages.add("php");
|
|
231577
231911
|
}
|
|
@@ -233402,6 +233736,10 @@ function resolveImplementationProfile(input2) {
|
|
|
233402
233736
|
return input2.apiStyleHint === "rest" ? "backend-spring-rest" : "backend-spring";
|
|
233403
233737
|
case "fastapi":
|
|
233404
233738
|
return input2.apiStyleHint === "rest" ? "backend-fastapi-rest" : "backend-fastapi";
|
|
233739
|
+
case "django":
|
|
233740
|
+
return input2.apiStyleHint === "rest" ? "backend-django-rest" : "backend-django";
|
|
233741
|
+
case "flask":
|
|
233742
|
+
return input2.apiStyleHint === "rest" ? "backend-flask-rest" : "backend-flask";
|
|
233405
233743
|
case "dotnet":
|
|
233406
233744
|
return input2.apiStyleHint === "rest" ? "backend-dotnet-webapi" : "backend-dotnet";
|
|
233407
233745
|
case "java":
|
|
@@ -233457,6 +233795,9 @@ function resolveNormalizedProjectKinds(detection, evidence) {
|
|
|
233457
233795
|
addEvidence6(evidence, `Normalized project kinds from selected adapter '${selectedAdapter.id}' hints`);
|
|
233458
233796
|
} else if (detection.topology.topology === "monorepo" && selectedHints.length > 0) {
|
|
233459
233797
|
normalizedKinds = uniqueSortedKinds([...heuristicKinds, ...selectedHints]);
|
|
233798
|
+
if (normalizedKinds.includes("library") && !selectedHints.includes("library") && (detection.architectureStyleSignals?.sharedPackageCount ?? 0) === 0) {
|
|
233799
|
+
normalizedKinds = normalizedKinds.filter((kind) => kind !== "library");
|
|
233800
|
+
}
|
|
233460
233801
|
addEvidence6(evidence, "Normalized monorepo project kinds from adapter hints plus heuristic evidence");
|
|
233461
233802
|
} else if (heuristicKinds.length > 0) {
|
|
233462
233803
|
normalizedKinds = uniqueSortedKinds(heuristicKinds);
|