smart-spec-kit-mcp 2.2.9 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +3 -0
  2. package/dist/schemas/workflowSchema.d.ts +10 -2
  3. package/dist/schemas/workflowSchema.d.ts.map +1 -1
  4. package/dist/schemas/workflowSchema.js +23 -1
  5. package/dist/schemas/workflowSchema.js.map +1 -1
  6. package/dist/tools/orchestrationTools.d.ts.map +1 -1
  7. package/dist/tools/orchestrationTools.js +182 -16
  8. package/dist/tools/orchestrationTools.js.map +1 -1
  9. package/dist/utils/constitutionUpdater.d.ts +25 -0
  10. package/dist/utils/constitutionUpdater.d.ts.map +1 -0
  11. package/dist/utils/constitutionUpdater.js +143 -0
  12. package/dist/utils/constitutionUpdater.js.map +1 -0
  13. package/dist/utils/initGuidedFlow.d.ts +21 -0
  14. package/dist/utils/initGuidedFlow.d.ts.map +1 -0
  15. package/dist/utils/initGuidedFlow.js +81 -0
  16. package/dist/utils/initGuidedFlow.js.map +1 -0
  17. package/dist/utils/initGuidedFlow.test.d.ts +5 -0
  18. package/dist/utils/initGuidedFlow.test.d.ts.map +1 -0
  19. package/dist/utils/initGuidedFlow.test.js +34 -0
  20. package/dist/utils/initGuidedFlow.test.js.map +1 -0
  21. package/dist/utils/initGuidedSessionStore.d.ts +34 -0
  22. package/dist/utils/initGuidedSessionStore.d.ts.map +1 -0
  23. package/dist/utils/initGuidedSessionStore.js +90 -0
  24. package/dist/utils/initGuidedSessionStore.js.map +1 -0
  25. package/dist/utils/stackDetector.d.ts +17 -0
  26. package/dist/utils/stackDetector.d.ts.map +1 -0
  27. package/dist/utils/stackDetector.js +256 -0
  28. package/dist/utils/stackDetector.js.map +1 -0
  29. package/dist/utils/stackDetector.test.d.ts +5 -0
  30. package/dist/utils/stackDetector.test.d.ts.map +1 -0
  31. package/dist/utils/stackDetector.test.js +93 -0
  32. package/dist/utils/stackDetector.test.js.map +1 -0
  33. package/dist/utils/workflowLoader.d.ts +15 -3
  34. package/dist/utils/workflowLoader.d.ts.map +1 -1
  35. package/docs/DOCUMENTATION.md +35 -0
  36. package/package.json +2 -2
  37. package/starter-kit/workflows/bugfix.yaml +41 -50
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Guided Init Flow Utilities
3
+ *
4
+ * Provides question definitions and answer normalization for guided init.
5
+ */
6
+ import * as path from "node:path";
7
+ export function getTodayDate() {
8
+ return new Date().toISOString().slice(0, 10);
9
+ }
10
+ export function buildInitQuestions(projectPath, detection, today = getTodayDate()) {
11
+ return [
12
+ {
13
+ key: "projectName",
14
+ label: "Nom du projet",
15
+ suggestion: detection.projectName ?? path.basename(projectPath),
16
+ },
17
+ {
18
+ key: "ratificationDate",
19
+ label: "Date de ratification (YYYY-MM-DD)",
20
+ suggestion: today,
21
+ },
22
+ {
23
+ key: "lastAmended",
24
+ label: "Dernière mise à jour (YYYY-MM-DD)",
25
+ suggestion: today,
26
+ },
27
+ {
28
+ key: "language",
29
+ label: "Langage principal",
30
+ suggestion: detection.language,
31
+ },
32
+ {
33
+ key: "framework",
34
+ label: "Framework principal",
35
+ suggestion: detection.framework,
36
+ },
37
+ {
38
+ key: "database",
39
+ label: "Base de données",
40
+ suggestion: detection.database,
41
+ },
42
+ {
43
+ key: "testing",
44
+ label: "Outils de test",
45
+ suggestion: detection.testing,
46
+ },
47
+ {
48
+ key: "codeStyle",
49
+ label: "Conventions de style de code",
50
+ suggestion: detection.codeStyle,
51
+ },
52
+ {
53
+ key: "approvers",
54
+ label: "Qui approuve les changements de constitution",
55
+ },
56
+ ];
57
+ }
58
+ export function normalizeGuidedAnswer(answer, suggestion, today = getTodayDate()) {
59
+ if (!answer) {
60
+ return { skipped: false };
61
+ }
62
+ const trimmed = answer.trim();
63
+ if (!trimmed) {
64
+ return { skipped: false };
65
+ }
66
+ const lower = trimmed.toLowerCase();
67
+ if (lower === "skip" || lower === "pass") {
68
+ return { skipped: true };
69
+ }
70
+ if (lower === "auto" || lower === "default") {
71
+ return { skipped: false, value: suggestion };
72
+ }
73
+ if (lower === "today" || lower === "aujourdhui" || lower === "aujourd'hui") {
74
+ return { skipped: false, value: today };
75
+ }
76
+ return { skipped: false, value: trimmed };
77
+ }
78
+ export function isAnswerFilled(answers, question, skippedKeys) {
79
+ return Boolean(answers[question.key]) || skippedKeys.has(question.key);
80
+ }
81
+ //# sourceMappingURL=initGuidedFlow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initGuidedFlow.js","sourceRoot":"","sources":["../../src/utils/initGuidedFlow.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAelC,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,WAAmB,EACnB,SAAyB,EACzB,QAAgB,YAAY,EAAE;IAE9B,OAAO;QACL;YACE,GAAG,EAAE,aAAa;YAClB,KAAK,EAAE,eAAe;YACtB,UAAU,EAAE,SAAS,CAAC,WAAW,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;SAChE;QACD;YACE,GAAG,EAAE,kBAAkB;YACvB,KAAK,EAAE,mCAAmC;YAC1C,UAAU,EAAE,KAAK;SAClB;QACD;YACE,GAAG,EAAE,aAAa;YAClB,KAAK,EAAE,mCAAmC;YAC1C,UAAU,EAAE,KAAK;SAClB;QACD;YACE,GAAG,EAAE,UAAU;YACf,KAAK,EAAE,mBAAmB;YAC1B,UAAU,EAAE,SAAS,CAAC,QAAQ;SAC/B;QACD;YACE,GAAG,EAAE,WAAW;YAChB,KAAK,EAAE,qBAAqB;YAC5B,UAAU,EAAE,SAAS,CAAC,SAAS;SAChC;QACD;YACE,GAAG,EAAE,UAAU;YACf,KAAK,EAAE,iBAAiB;YACxB,UAAU,EAAE,SAAS,CAAC,QAAQ;SAC/B;QACD;YACE,GAAG,EAAE,SAAS;YACd,KAAK,EAAE,gBAAgB;YACvB,UAAU,EAAE,SAAS,CAAC,OAAO;SAC9B;QACD;YACE,GAAG,EAAE,WAAW;YAChB,KAAK,EAAE,8BAA8B;YACrC,UAAU,EAAE,SAAS,CAAC,SAAS;SAChC;QACD;YACE,GAAG,EAAE,WAAW;YAChB,KAAK,EAAE,8CAA8C;SACtD;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,MAA0B,EAC1B,UAA8B,EAC9B,QAAgB,YAAY,EAAE;IAE9B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5B,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5B,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAEpC,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QACzC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC5C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IAC/C,CAAC;IAED,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,YAAY,IAAI,KAAK,KAAK,aAAa,EAAE,CAAC;QAC3E,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC1C,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,OAA4B,EAC5B,QAAsB,EACtB,WAA2C;IAE3C,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACzE,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Tests for guided init flow utilities.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=initGuidedFlow.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initGuidedFlow.test.d.ts","sourceRoot":"","sources":["../../src/utils/initGuidedFlow.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Tests for guided init flow utilities.
3
+ */
4
+ import { test } from "node:test";
5
+ import assert from "node:assert/strict";
6
+ import { buildInitQuestions, normalizeGuidedAnswer } from "./initGuidedFlow.js";
7
+ const detection = {
8
+ projectName: "demo-app",
9
+ language: "TypeScript",
10
+ framework: "React",
11
+ database: "PostgreSQL",
12
+ testing: "Vitest",
13
+ codeStyle: "ESLint + Prettier",
14
+ evidence: [],
15
+ };
16
+ test("buildInitQuestions uses detection values", () => {
17
+ const questions = buildInitQuestions("/tmp/demo", detection, "2026-01-31");
18
+ const projectNameQuestion = questions[0];
19
+ assert.ok(projectNameQuestion);
20
+ assert.equal(projectNameQuestion.suggestion, "demo-app");
21
+ const languageQuestion = questions.find(q => q.key === "language");
22
+ assert.equal(languageQuestion?.suggestion, "TypeScript");
23
+ });
24
+ test("normalizeGuidedAnswer respects auto/skip/today", () => {
25
+ const auto = normalizeGuidedAnswer("auto", "React", "2026-01-31");
26
+ assert.equal(auto.value, "React");
27
+ assert.equal(auto.skipped, false);
28
+ const skip = normalizeGuidedAnswer("skip", "React", "2026-01-31");
29
+ assert.equal(skip.value, undefined);
30
+ assert.equal(skip.skipped, true);
31
+ const today = normalizeGuidedAnswer("today", "", "2026-01-31");
32
+ assert.equal(today.value, "2026-01-31");
33
+ });
34
+ //# sourceMappingURL=initGuidedFlow.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initGuidedFlow.test.js","sourceRoot":"","sources":["../../src/utils/initGuidedFlow.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEhF,MAAM,SAAS,GAAG;IAChB,WAAW,EAAE,UAAU;IACvB,QAAQ,EAAE,YAAY;IACtB,SAAS,EAAE,OAAO;IAClB,QAAQ,EAAE,YAAY;IACtB,OAAO,EAAE,QAAQ;IACjB,SAAS,EAAE,mBAAmB;IAC9B,QAAQ,EAAE,EAAE;CACb,CAAC;AAEF,IAAI,CAAC,0CAA0C,EAAE,GAAG,EAAE;IACpD,MAAM,SAAS,GAAG,kBAAkB,CAAC,WAAW,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;IAC3E,MAAM,mBAAmB,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IACzC,MAAM,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC;IAC/B,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IACzD,MAAM,gBAAgB,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,UAAU,CAAC,CAAC;IACnE,MAAM,CAAC,KAAK,CAAC,gBAAgB,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;AAC3D,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,gDAAgD,EAAE,GAAG,EAAE;IAC1D,MAAM,IAAI,GAAG,qBAAqB,CAAC,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;IAClE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAClC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAElC,MAAM,IAAI,GAAG,qBAAqB,CAAC,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;IAClE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACpC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAEjC,MAAM,KAAK,GAAG,qBAAqB,CAAC,OAAO,EAAE,EAAE,EAAE,YAAY,CAAC,CAAC;IAC/D,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;AAC1C,CAAC,CAAC,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Guided Init Session Store
3
+ *
4
+ * Tracks multi-step guided init state across tool calls.
5
+ */
6
+ import type { StackDetection } from "./stackDetector.js";
7
+ import type { ConstitutionAnswers } from "./constitutionUpdater.js";
8
+ export interface InitGuidedSession {
9
+ sessionId: string;
10
+ projectPath: string;
11
+ status: "active" | "completed" | "cancelled";
12
+ stepIndex: number;
13
+ answers: ConstitutionAnswers;
14
+ skippedKeys: Array<keyof ConstitutionAnswers>;
15
+ detection: StackDetection;
16
+ createdAt: string;
17
+ updatedAt: string;
18
+ }
19
+ declare class InitGuidedSessionStore {
20
+ private readonly sessions;
21
+ private readonly persistDir;
22
+ constructor();
23
+ init(): Promise<void>;
24
+ generateSessionId(): string;
25
+ create(projectPath: string, detection: StackDetection): Promise<InitGuidedSession>;
26
+ get(sessionId: string): InitGuidedSession | undefined;
27
+ getActiveSession(projectPath: string): InitGuidedSession | undefined;
28
+ update(session: InitGuidedSession): Promise<void>;
29
+ delete(sessionId: string): Promise<void>;
30
+ private persist;
31
+ }
32
+ export declare const initGuidedSessionStore: InitGuidedSessionStore;
33
+ export {};
34
+ //# sourceMappingURL=initGuidedSessionStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initGuidedSessionStore.d.ts","sourceRoot":"","sources":["../../src/utils/initGuidedSessionStore.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,mBAAmB,CAAC;IAC7B,WAAW,EAAE,KAAK,CAAC,MAAM,mBAAmB,CAAC,CAAC;IAC9C,SAAS,EAAE,cAAc,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,cAAM,sBAAsB;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA6C;IACtE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;;IAM9B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB3B,iBAAiB,IAAI,MAAM;IAMrB,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAsBxF,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAIrD,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAY9D,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAMjD,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAUhC,OAAO;CAItB;AAED,eAAO,MAAM,sBAAsB,wBAA+B,CAAC"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Guided Init Session Store
3
+ *
4
+ * Tracks multi-step guided init state across tool calls.
5
+ */
6
+ import * as fs from "node:fs/promises";
7
+ import * as path from "node:path";
8
+ import * as os from "node:os";
9
+ class InitGuidedSessionStore {
10
+ sessions = new Map();
11
+ persistDir;
12
+ constructor() {
13
+ this.persistDir = path.join(os.tmpdir(), "spec-kit-init-sessions");
14
+ }
15
+ async init() {
16
+ try {
17
+ await fs.mkdir(this.persistDir, { recursive: true });
18
+ const files = await fs.readdir(this.persistDir);
19
+ for (const file of files) {
20
+ if (file.endsWith(".json")) {
21
+ const content = await fs.readFile(path.join(this.persistDir, file), "utf-8");
22
+ const session = JSON.parse(content);
23
+ this.sessions.set(session.sessionId, session);
24
+ }
25
+ }
26
+ }
27
+ catch {
28
+ // No persisted sessions
29
+ }
30
+ }
31
+ generateSessionId() {
32
+ const timestamp = Date.now().toString(36);
33
+ const random = Math.random().toString(36).substring(2, 8);
34
+ return `init-${timestamp}-${random}`;
35
+ }
36
+ async create(projectPath, detection) {
37
+ const sessionId = this.generateSessionId();
38
+ const now = new Date().toISOString();
39
+ const session = {
40
+ sessionId,
41
+ projectPath,
42
+ status: "active",
43
+ stepIndex: 0,
44
+ answers: {},
45
+ skippedKeys: [],
46
+ detection,
47
+ createdAt: now,
48
+ updatedAt: now,
49
+ };
50
+ this.sessions.set(sessionId, session);
51
+ await this.persist(session);
52
+ return session;
53
+ }
54
+ get(sessionId) {
55
+ return this.sessions.get(sessionId);
56
+ }
57
+ getActiveSession(projectPath) {
58
+ let latest;
59
+ for (const session of this.sessions.values()) {
60
+ if (session.status === "active" && session.projectPath === projectPath) {
61
+ if (!latest || session.updatedAt > latest.updatedAt) {
62
+ latest = session;
63
+ }
64
+ }
65
+ }
66
+ return latest;
67
+ }
68
+ async update(session) {
69
+ session.updatedAt = new Date().toISOString();
70
+ this.sessions.set(session.sessionId, session);
71
+ await this.persist(session);
72
+ }
73
+ async delete(sessionId) {
74
+ this.sessions.delete(sessionId);
75
+ const filePath = path.join(this.persistDir, `${sessionId}.json`);
76
+ try {
77
+ await fs.unlink(filePath);
78
+ }
79
+ catch {
80
+ // Ignore
81
+ }
82
+ }
83
+ async persist(session) {
84
+ const filePath = path.join(this.persistDir, `${session.sessionId}.json`);
85
+ await fs.writeFile(filePath, JSON.stringify(session, null, 2), "utf-8");
86
+ }
87
+ }
88
+ export const initGuidedSessionStore = new InitGuidedSessionStore();
89
+ await initGuidedSessionStore.init();
90
+ //# sourceMappingURL=initGuidedSessionStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initGuidedSessionStore.js","sourceRoot":"","sources":["../../src/utils/initGuidedSessionStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Stack Detector
3
+ *
4
+ * Detects project language, framework, database, and testing stack
5
+ * based on common project files and dependencies.
6
+ */
7
+ export interface StackDetection {
8
+ projectName?: string;
9
+ language?: string;
10
+ framework?: string;
11
+ database?: string;
12
+ testing?: string;
13
+ codeStyle?: string;
14
+ evidence: string[];
15
+ }
16
+ export declare function detectStack(projectPath: string): Promise<StackDetection>;
17
+ //# sourceMappingURL=stackDetector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stackDetector.d.ts","sourceRoot":"","sources":["../../src/utils/stackDetector.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAgQD,wBAAsB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAyB9E"}
@@ -0,0 +1,256 @@
1
+ /**
2
+ * Stack Detector
3
+ *
4
+ * Detects project language, framework, database, and testing stack
5
+ * based on common project files and dependencies.
6
+ */
7
+ import * as fs from "node:fs/promises";
8
+ import * as path from "node:path";
9
+ const EXCLUDED_DIRS = new Set(["node_modules", ".git", "dist", "build", "out", ".next", ".turbo", ".cache"]);
10
+ async function exists(filePath) {
11
+ try {
12
+ await fs.access(filePath);
13
+ return true;
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ }
19
+ async function readJsonFile(filePath) {
20
+ try {
21
+ const raw = await fs.readFile(filePath, "utf-8");
22
+ return JSON.parse(raw);
23
+ }
24
+ catch {
25
+ return null;
26
+ }
27
+ }
28
+ async function readTextFile(filePath) {
29
+ try {
30
+ return await fs.readFile(filePath, "utf-8");
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ }
36
+ async function listFilesRecursive(root, depth, results = []) {
37
+ if (depth < 0)
38
+ return results;
39
+ let entries = [];
40
+ try {
41
+ entries = await fs.readdir(root, { withFileTypes: true });
42
+ }
43
+ catch {
44
+ return results;
45
+ }
46
+ for (const entry of entries) {
47
+ if (entry.isDirectory()) {
48
+ if (EXCLUDED_DIRS.has(entry.name))
49
+ continue;
50
+ await listFilesRecursive(path.join(root, entry.name), depth - 1, results);
51
+ }
52
+ else {
53
+ results.push(path.join(root, entry.name));
54
+ }
55
+ }
56
+ return results;
57
+ }
58
+ function addUnique(list, value) {
59
+ if (!value)
60
+ return;
61
+ if (!list.includes(value))
62
+ list.push(value);
63
+ }
64
+ function joinValues(values) {
65
+ if (values.length === 0)
66
+ return undefined;
67
+ return values.join(" + ");
68
+ }
69
+ function detectFromDependencies(deps) {
70
+ const frameworks = [];
71
+ const testing = [];
72
+ const frameworkMap = [
73
+ ["next", "Next.js"],
74
+ ["react", "React"],
75
+ ["vue", "Vue"],
76
+ ["nuxt", "Nuxt"],
77
+ ["svelte", "Svelte"],
78
+ ["@angular/core", "Angular"],
79
+ ["express", "Express"],
80
+ ["@nestjs/core", "NestJS"],
81
+ ["fastify", "Fastify"],
82
+ ["koa", "Koa"],
83
+ ];
84
+ const testMap = [
85
+ ["vitest", "Vitest"],
86
+ ["jest", "Jest"],
87
+ ["mocha", "Mocha"],
88
+ ["ava", "AVA"],
89
+ ["@playwright/test", "Playwright"],
90
+ ["cypress", "Cypress"],
91
+ ];
92
+ for (const [dep, label] of frameworkMap) {
93
+ if (deps.has(dep))
94
+ addUnique(frameworks, label);
95
+ }
96
+ for (const [dep, label] of testMap) {
97
+ if (deps.has(dep))
98
+ addUnique(testing, label);
99
+ }
100
+ const databaseMap = [
101
+ [["mongoose"], "MongoDB"],
102
+ [["pg", "pg-promise"], "PostgreSQL"],
103
+ [["mysql2", "mysql"], "MySQL"],
104
+ [["sqlite3", "better-sqlite3"], "SQLite"],
105
+ [["prisma"], "Prisma (DB non détectée)"],
106
+ [["typeorm"], "TypeORM (DB non détectée)"],
107
+ [["sequelize"], "Sequelize (DB non détectée)"],
108
+ ];
109
+ let database;
110
+ for (const [depsList, label] of databaseMap) {
111
+ if (depsList.some(dep => deps.has(dep))) {
112
+ database = label;
113
+ break;
114
+ }
115
+ }
116
+ return { frameworks, testing, database };
117
+ }
118
+ function detectCodeStyleFiles(fileList, projectPath) {
119
+ const normalized = fileList.map(file => path.relative(projectPath, file).toLowerCase());
120
+ const hasEslint = normalized.some(file => file.startsWith(".eslintrc") || file === "eslint.config.js" || file === "eslint.config.mjs");
121
+ const hasPrettier = normalized.some(file => file.startsWith(".prettierrc") || file === "prettier.config.js" || file === "prettier.config.cjs");
122
+ const parts = [];
123
+ if (hasEslint)
124
+ parts.push("ESLint");
125
+ if (hasPrettier)
126
+ parts.push("Prettier");
127
+ return joinValues(parts);
128
+ }
129
+ function extractPythonDeps(text) {
130
+ const deps = new Set();
131
+ const lines = text.split("\n").map(line => line.trim());
132
+ for (const line of lines) {
133
+ if (!line || line.startsWith("#"))
134
+ continue;
135
+ const name = line.split(/[<=>\s]/)[0];
136
+ if (name)
137
+ deps.add(name.toLowerCase());
138
+ }
139
+ return deps;
140
+ }
141
+ async function detectNodeStack(projectPath, detection) {
142
+ const packageJsonPath = path.join(projectPath, "package.json");
143
+ const tsconfigPath = path.join(projectPath, "tsconfig.json");
144
+ if (!(await exists(packageJsonPath)))
145
+ return;
146
+ const pkg = await readJsonFile(packageJsonPath);
147
+ if (!pkg)
148
+ return;
149
+ detection.evidence.push("package.json");
150
+ if (pkg.name)
151
+ detection.projectName = pkg.name;
152
+ const depNames = new Set([
153
+ ...Object.keys(pkg.dependencies ?? {}),
154
+ ...Object.keys(pkg.devDependencies ?? {}),
155
+ ]);
156
+ if (depNames.has("typescript") || (await exists(tsconfigPath))) {
157
+ addUnique(detection.languages, "TypeScript");
158
+ }
159
+ else {
160
+ addUnique(detection.languages, "JavaScript");
161
+ }
162
+ const depDetection = detectFromDependencies(depNames);
163
+ for (const fw of depDetection.frameworks)
164
+ addUnique(detection.frameworks, fw);
165
+ for (const test of depDetection.testing)
166
+ addUnique(detection.testing, test);
167
+ if (depDetection.database)
168
+ detection.database = depDetection.database;
169
+ }
170
+ async function detectPythonStack(projectPath, detection) {
171
+ const pyprojectPath = path.join(projectPath, "pyproject.toml");
172
+ const requirementsPath = path.join(projectPath, "requirements.txt");
173
+ const poetryLockPath = path.join(projectPath, "poetry.lock");
174
+ if (!(await exists(pyprojectPath)) && !(await exists(requirementsPath)) && !(await exists(poetryLockPath)))
175
+ return;
176
+ addUnique(detection.languages, "Python");
177
+ detection.evidence.push("python files");
178
+ const pyText = (await readTextFile(pyprojectPath)) ?? (await readTextFile(requirementsPath)) ?? "";
179
+ const pyDeps = extractPythonDeps(pyText);
180
+ if (pyDeps.has("django"))
181
+ addUnique(detection.frameworks, "Django");
182
+ if (pyDeps.has("flask"))
183
+ addUnique(detection.frameworks, "Flask");
184
+ if (pyDeps.has("fastapi"))
185
+ addUnique(detection.frameworks, "FastAPI");
186
+ if (pyDeps.has("pytest"))
187
+ addUnique(detection.testing, "Pytest");
188
+ if (pyDeps.has("sqlalchemy") && !detection.database)
189
+ detection.database = "SQLAlchemy";
190
+ }
191
+ async function detectOtherStacks(projectPath, detection) {
192
+ const goModPath = path.join(projectPath, "go.mod");
193
+ const cargoPath = path.join(projectPath, "Cargo.toml");
194
+ const pomPath = path.join(projectPath, "pom.xml");
195
+ const gradlePath = path.join(projectPath, "build.gradle");
196
+ const gradleKtsPath = path.join(projectPath, "build.gradle.kts");
197
+ const composerPath = path.join(projectPath, "composer.json");
198
+ const gemfilePath = path.join(projectPath, "Gemfile");
199
+ const pubspecPath = path.join(projectPath, "pubspec.yaml");
200
+ if (await exists(goModPath)) {
201
+ addUnique(detection.languages, "Go");
202
+ detection.evidence.push("go.mod");
203
+ }
204
+ if (await exists(cargoPath)) {
205
+ addUnique(detection.languages, "Rust");
206
+ detection.evidence.push("Cargo.toml");
207
+ }
208
+ if (await exists(pomPath) || await exists(gradlePath) || await exists(gradleKtsPath)) {
209
+ addUnique(detection.languages, "Java");
210
+ detection.evidence.push("Java build files");
211
+ }
212
+ if (await exists(composerPath)) {
213
+ addUnique(detection.languages, "PHP");
214
+ detection.evidence.push("composer.json");
215
+ }
216
+ if (await exists(gemfilePath)) {
217
+ addUnique(detection.languages, "Ruby");
218
+ detection.evidence.push("Gemfile");
219
+ }
220
+ if (await exists(pubspecPath)) {
221
+ addUnique(detection.languages, "Dart");
222
+ detection.evidence.push("pubspec.yaml");
223
+ }
224
+ }
225
+ async function detectDotNet(projectPath, detection) {
226
+ const files = await listFilesRecursive(projectPath, 2);
227
+ const csprojFound = files.some(file => file.toLowerCase().endsWith(".csproj"));
228
+ if (csprojFound) {
229
+ addUnique(detection.languages, ".NET");
230
+ detection.evidence.push(".csproj");
231
+ }
232
+ }
233
+ export async function detectStack(projectPath) {
234
+ const detection = {
235
+ languages: [],
236
+ frameworks: [],
237
+ testing: [],
238
+ evidence: [],
239
+ };
240
+ await detectNodeStack(projectPath, detection);
241
+ await detectPythonStack(projectPath, detection);
242
+ await detectOtherStacks(projectPath, detection);
243
+ await detectDotNet(projectPath, detection);
244
+ const files = await listFilesRecursive(projectPath, 2);
245
+ const codeStyle = detectCodeStyleFiles(files, projectPath);
246
+ return {
247
+ projectName: detection.projectName,
248
+ language: joinValues(detection.languages),
249
+ framework: joinValues(detection.frameworks),
250
+ database: detection.database,
251
+ testing: joinValues(detection.testing),
252
+ codeStyle,
253
+ evidence: detection.evidence,
254
+ };
255
+ }
256
+ //# sourceMappingURL=stackDetector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stackDetector.js","sourceRoot":"","sources":["../../src/utils/stackDetector.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAYlC,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;AAE7G,KAAK,UAAU,MAAM,CAAC,QAAgB;IACpC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,KAAK,UAAU,YAAY,CAAc,QAAgB;IACvD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAM,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,QAAgB;IAC1C,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,IAAY,EAAE,KAAa,EAAE,UAAoB,EAAE;IACnF,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC;IAE9B,IAAI,OAAO,GAAa,EAAE,CAAC;IAC3B,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,IAAI,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC5C,MAAM,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;QAC5E,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,SAAS,CAAC,IAAc,EAAE,KAAc;IAC/C,IAAI,CAAC,KAAK;QAAE,OAAO;IACnB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,UAAU,CAAC,MAAgB;IAClC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC1C,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,sBAAsB,CAAC,IAAiB;IAK/C,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,MAAM,YAAY,GAA4B;QAC5C,CAAC,MAAM,EAAE,SAAS,CAAC;QACnB,CAAC,OAAO,EAAE,OAAO,CAAC;QAClB,CAAC,KAAK,EAAE,KAAK,CAAC;QACd,CAAC,MAAM,EAAE,MAAM,CAAC;QAChB,CAAC,QAAQ,EAAE,QAAQ,CAAC;QACpB,CAAC,eAAe,EAAE,SAAS,CAAC;QAC5B,CAAC,SAAS,EAAE,SAAS,CAAC;QACtB,CAAC,cAAc,EAAE,QAAQ,CAAC;QAC1B,CAAC,SAAS,EAAE,SAAS,CAAC;QACtB,CAAC,KAAK,EAAE,KAAK,CAAC;KACf,CAAC;IAEF,MAAM,OAAO,GAA4B;QACvC,CAAC,QAAQ,EAAE,QAAQ,CAAC;QACpB,CAAC,MAAM,EAAE,MAAM,CAAC;QAChB,CAAC,OAAO,EAAE,OAAO,CAAC;QAClB,CAAC,KAAK,EAAE,KAAK,CAAC;QACd,CAAC,kBAAkB,EAAE,YAAY,CAAC;QAClC,CAAC,SAAS,EAAE,SAAS,CAAC;KACvB,CAAC;IAEF,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,YAAY,EAAE,CAAC;QACxC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;QACnC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,WAAW,GAA8B;QAC7C,CAAC,CAAC,UAAU,CAAC,EAAE,SAAS,CAAC;QACzB,CAAC,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE,YAAY,CAAC;QACpC,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC;QAC9B,CAAC,CAAC,SAAS,EAAE,gBAAgB,CAAC,EAAE,QAAQ,CAAC;QACzC,CAAC,CAAC,QAAQ,CAAC,EAAE,0BAA0B,CAAC;QACxC,CAAC,CAAC,SAAS,CAAC,EAAE,2BAA2B,CAAC;QAC1C,CAAC,CAAC,WAAW,CAAC,EAAE,6BAA6B,CAAC;KAC/C,CAAC;IAEF,IAAI,QAA4B,CAAC;IACjC,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5C,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACxC,QAAQ,GAAG,KAAK,CAAC;YACjB,MAAM;QACR,CAAC;IACH,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAC3C,CAAC;AAED,SAAS,oBAAoB,CAAC,QAAkB,EAAE,WAAmB;IACnE,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IACxF,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACvC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,IAAI,KAAK,kBAAkB,IAAI,IAAI,KAAK,mBAAmB,CAC5F,CAAC;IACF,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACzC,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,IAAI,KAAK,oBAAoB,IAAI,IAAI,KAAK,qBAAqB,CAClG,CAAC;IAEF,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpC,IAAI,WAAW;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAExC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY;IACrC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACxD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;QACtC,IAAI,IAAI;YAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAWD,KAAK,UAAU,eAAe,CAAC,WAAmB,EAAE,SAA2B;IAC7E,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAC/D,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;IAE7D,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;QAAE,OAAO;IAE7C,MAAM,GAAG,GAAG,MAAM,YAAY,CAAqG,eAAe,CAAC,CAAC;IACpJ,IAAI,CAAC,GAAG;QAAE,OAAO;IAEjB,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACxC,IAAI,GAAG,CAAC,IAAI;QAAE,SAAS,CAAC,WAAW,GAAG,GAAG,CAAC,IAAI,CAAC;IAE/C,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAS;QAC/B,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC;QACtC,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC;KAC1C,CAAC,CAAC;IAEH,IAAI,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC;QAC/D,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAC/C,CAAC;SAAM,CAAC;QACN,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,YAAY,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IACtD,KAAK,MAAM,EAAE,IAAI,YAAY,CAAC,UAAU;QAAE,SAAS,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC9E,KAAK,MAAM,IAAI,IAAI,YAAY,CAAC,OAAO;QAAE,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC5E,IAAI,YAAY,CAAC,QAAQ;QAAE,SAAS,CAAC,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC;AACxE,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,WAAmB,EAAE,SAA2B;IAC/E,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;IAC/D,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;IACpE,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;IAE7D,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;QAAE,OAAO;IAEnH,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACzC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAExC,MAAM,MAAM,GAAG,CAAC,MAAM,YAAY,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,MAAM,YAAY,CAAC,gBAAgB,CAAC,CAAC,IAAI,EAAE,CAAC;IACnG,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAEzC,IAAI,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,SAAS,CAAC,SAAS,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACpE,IAAI,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;QAAE,SAAS,CAAC,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAClE,IAAI,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC;QAAE,SAAS,CAAC,SAAS,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IACtE,IAAI,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACjE,IAAI,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ;QAAE,SAAS,CAAC,QAAQ,GAAG,YAAY,CAAC;AACzF,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,WAAmB,EAAE,SAA2B;IAC/E,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IACnD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAClD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAC1D,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;IACjE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;IAC7D,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACtD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAE3D,IAAI,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5B,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACrC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5B,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACvC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,MAAM,MAAM,CAAC,UAAU,CAAC,IAAI,MAAM,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;QACrF,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACvC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI,MAAM,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;QAC/B,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACtC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,MAAM,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QAC9B,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACvC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,MAAM,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QAC9B,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACvC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1C,CAAC;AACH,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,WAAmB,EAAE,SAA2B;IAC1E,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACvD,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;IAC/E,IAAI,WAAW,EAAE,CAAC;QAChB,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACvC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,WAAmB;IACnD,MAAM,SAAS,GAAqB;QAClC,SAAS,EAAE,EAAE;QACb,UAAU,EAAE,EAAE;QACd,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,EAAE;KACb,CAAC;IAEF,MAAM,eAAe,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAC9C,MAAM,iBAAiB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAChD,MAAM,iBAAiB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAChD,MAAM,YAAY,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAE3C,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,oBAAoB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IAE3D,OAAO;QACL,WAAW,EAAE,SAAS,CAAC,WAAW;QAClC,QAAQ,EAAE,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC;QACzC,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC;QAC3C,QAAQ,EAAE,SAAS,CAAC,QAAQ;QAC5B,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC;QACtC,SAAS;QACT,QAAQ,EAAE,SAAS,CAAC,QAAQ;KAC7B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Tests for stack detection and constitution update.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=stackDetector.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stackDetector.test.d.ts","sourceRoot":"","sources":["../../src/utils/stackDetector.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}