dsh-codebase-chat 0.24.0 → 0.25.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.
- package/README.md +1 -0
- package/dist/cli.js +932 -7
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +44 -2
- package/dist/index.js +961 -6
- package/dist/index.js.map +1 -1
- package/lib/index.js +45 -275
- package/package.json +4 -1
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import { parseArgs } from "util";
|
|
5
5
|
import { watch } from "fs";
|
|
6
|
-
import { sep as sep5 } from "path";
|
|
6
|
+
import { sep as sep5, basename as basename3 } from "path";
|
|
7
7
|
|
|
8
8
|
// src/context.ts
|
|
9
9
|
import { join as join5 } from "path";
|
|
@@ -594,7 +594,11 @@ function globToRegExp(glob) {
|
|
|
594
594
|
function matchesAnyGlob(relPath, globs) {
|
|
595
595
|
if (!globs || globs.length === 0) return false;
|
|
596
596
|
const rel = relPath.replace(/\\/g, "/");
|
|
597
|
-
|
|
597
|
+
const base = rel.split("/").pop() ?? rel;
|
|
598
|
+
return globs.some((g) => {
|
|
599
|
+
const re = globToRegExp(g);
|
|
600
|
+
return re.test(rel) || !g.includes("/") && re.test(base);
|
|
601
|
+
});
|
|
598
602
|
}
|
|
599
603
|
|
|
600
604
|
// src/project.ts
|
|
@@ -640,6 +644,18 @@ var DEFAULT_SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
|
640
644
|
".cache",
|
|
641
645
|
".turbo",
|
|
642
646
|
".next",
|
|
647
|
+
"target",
|
|
648
|
+
"bin",
|
|
649
|
+
"obj",
|
|
650
|
+
"vendor",
|
|
651
|
+
".venv",
|
|
652
|
+
"venv",
|
|
653
|
+
"__pycache__",
|
|
654
|
+
".npm-cache",
|
|
655
|
+
".parcel-cache",
|
|
656
|
+
".gradle",
|
|
657
|
+
".mypy_cache",
|
|
658
|
+
".pytest_cache",
|
|
643
659
|
"android",
|
|
644
660
|
"ios",
|
|
645
661
|
"e2e-shots",
|
|
@@ -648,7 +664,6 @@ var DEFAULT_SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
|
648
664
|
".idea",
|
|
649
665
|
".memsearch",
|
|
650
666
|
".vscode",
|
|
651
|
-
"__pycache__",
|
|
652
667
|
".dsh-tmp",
|
|
653
668
|
".dsh-vision-router",
|
|
654
669
|
".agents",
|
|
@@ -708,7 +723,7 @@ async function* walkFiles(startDir, skipDirs = DEFAULT_SKIP_DIRS, skipFiles = DE
|
|
|
708
723
|
const fullPath = join3(dir, entry.name);
|
|
709
724
|
const rel = relative(startDir, fullPath).split(sep).join("/");
|
|
710
725
|
if (entry.isDirectory()) {
|
|
711
|
-
if (!skipDirs.has(entry.name) && !matchesAnyGlob(rel, ignoreGlobs)) queue.push(fullPath);
|
|
726
|
+
if (!skipDirs.has(entry.name) && !skipDirs.has(rel) && !matchesAnyGlob(rel, ignoreGlobs)) queue.push(fullPath);
|
|
712
727
|
continue;
|
|
713
728
|
}
|
|
714
729
|
if (!entry.isFile()) continue;
|
|
@@ -728,7 +743,7 @@ async function safeReadText(filePath) {
|
|
|
728
743
|
return void 0;
|
|
729
744
|
}
|
|
730
745
|
}
|
|
731
|
-
async function buildTree(startDir, maxLines = 500, skipDirs = DEFAULT_SKIP_DIRS) {
|
|
746
|
+
async function buildTree(startDir, maxLines = 500, skipDirs = DEFAULT_SKIP_DIRS, skipFiles = DEFAULT_SKIP_FILES, ignoreGlobs = []) {
|
|
732
747
|
const lines = [];
|
|
733
748
|
async function walk(dir, prefix = "") {
|
|
734
749
|
if (lines.length >= maxLines) return;
|
|
@@ -741,12 +756,14 @@ async function buildTree(startDir, maxLines = 500, skipDirs = DEFAULT_SKIP_DIRS)
|
|
|
741
756
|
entries.sort((a, b) => a.isDirectory() === b.isDirectory() ? a.name.localeCompare(b.name) : a.isDirectory() ? -1 : 1);
|
|
742
757
|
for (const entry of entries) {
|
|
743
758
|
if (lines.length >= maxLines) return;
|
|
744
|
-
if (skipDirs.has(entry.name)) continue;
|
|
745
759
|
const fullPath = join3(dir, entry.name);
|
|
760
|
+
const rel = relative(startDir, fullPath).split(sep).join("/");
|
|
746
761
|
if (entry.isDirectory()) {
|
|
762
|
+
if (skipDirs.has(entry.name) || skipDirs.has(rel) || matchesAnyGlob(rel, ignoreGlobs)) continue;
|
|
747
763
|
lines.push(`${prefix}${entry.name}/`);
|
|
748
764
|
await walk(fullPath, `${prefix} `);
|
|
749
765
|
} else {
|
|
766
|
+
if (skipFiles.has(entry.name) || matchesAnyGlob(rel, ignoreGlobs)) continue;
|
|
750
767
|
lines.push(`${prefix}${entry.name}`);
|
|
751
768
|
}
|
|
752
769
|
}
|
|
@@ -920,7 +937,7 @@ async function buildIndex(projectPath, progress) {
|
|
|
920
937
|
const projectName = absProject.split(sep2).pop() ?? "project";
|
|
921
938
|
progress?.(`Indexing ${projectName}...`);
|
|
922
939
|
const walk = await getWalkOptions(absProject);
|
|
923
|
-
const tree = await buildTree(absProject, void 0, walk.skipDirs);
|
|
940
|
+
const tree = await buildTree(absProject, void 0, walk.skipDirs, walk.skipFiles, walk.ignoreGlobs);
|
|
924
941
|
const startDir = absProject;
|
|
925
942
|
const previous = await loadIndex(absProject);
|
|
926
943
|
const previousFiles = previous?.projectPath === absProject ? previous.files : {};
|
|
@@ -1769,6 +1786,810 @@ function riskKey(r) {
|
|
|
1769
1786
|
return r;
|
|
1770
1787
|
}
|
|
1771
1788
|
|
|
1789
|
+
// src/prompts.ts
|
|
1790
|
+
import { readFileSync } from "fs";
|
|
1791
|
+
import figlet from "figlet";
|
|
1792
|
+
var cachedVersion;
|
|
1793
|
+
function promptVersion() {
|
|
1794
|
+
if (!cachedVersion) {
|
|
1795
|
+
try {
|
|
1796
|
+
const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
1797
|
+
cachedVersion = pkg.version ?? "0.0.0";
|
|
1798
|
+
} catch {
|
|
1799
|
+
cachedVersion = "0.0.0";
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
return cachedVersion;
|
|
1803
|
+
}
|
|
1804
|
+
function citationInstruction(lang = "fr") {
|
|
1805
|
+
const isEn = lang === "en";
|
|
1806
|
+
return `${isEn ? "## Evidence & Scoring (mandatory)" : "## Sources & Scoring (obligatoire)"}
|
|
1807
|
+
- ${isEn ? "Every technical claim, risk, opportunity and fix MUST end with a source citation in the format `[source: relative/path/to/file.ts:line]` (e.g. `[source: src/App.tsx:42]`)." : "Chaque affirmation technique, risque, opportunit\xE9 et correctif DOIT se terminer par une citation source au format `[source: chemin/relatif/vers/fichier.ts:ligne]` (ex. `[source: src/App.tsx:42]`)."}
|
|
1808
|
+
- ${isEn ? "Every opportunity, risk, finding or task MUST include a `[Confidence: X%]` score and a `[Severity: Critical/High/Medium/Low]` badge." : "Chaque opportunit\xE9, risque, constat ou t\xE2che DOIT inclure un score `[Confiance : X%]` et un badge `[S\xE9v\xE9rit\xE9 : Critique/\xC9lev\xE9e/Moyenne/Faible]`."}
|
|
1809
|
+
- ${isEn ? "Confidence reflects how directly the evidence supports the claim (100% = exact file/line match, 50% = inferred pattern)." : "La confiance refl\xE8te \xE0 quel point l'evidence supporte directement l'affirmation (100% = correspondance exacte fichier/ligne, 50% = pattern inf\xE9r\xE9)."}
|
|
1810
|
+
- ${isEn ? "Do not invent citations. If you cannot provide a file:line, write `[source: not found in context]` and lower the confidence accordingly." : "Ne pas inventer de citations. Si vous ne pouvez pas donner fichier:ligne, \xE9crivez `[source: non trouv\xE9 dans le contexte]` et baissez la confiance en cons\xE9quence."}
|
|
1811
|
+
`;
|
|
1812
|
+
}
|
|
1813
|
+
function withCitations(prompt, lang = "fr") {
|
|
1814
|
+
return `${prompt}
|
|
1815
|
+
|
|
1816
|
+
${citationInstruction(lang)}`;
|
|
1817
|
+
}
|
|
1818
|
+
function langInstruction(lang = "fr") {
|
|
1819
|
+
if (lang === "en") {
|
|
1820
|
+
return "IMPORTANT: This whole prompt is in French for context, but the user requested English. Your ENTIRE response MUST be written in English. Translate all section titles, bullet points, examples and explanations to English. Do not output any French words except quoted code or file paths.";
|
|
1821
|
+
}
|
|
1822
|
+
return "IMPORTANT: Reponds obligatoirement en francais. Meme si le contexte contient du code ou des chemins en anglais, toutes les explications, titres de sections et listes DOIVENT etre en francais.";
|
|
1823
|
+
}
|
|
1824
|
+
function normalizeLabels(prompt, lang) {
|
|
1825
|
+
if (lang !== "en") return prompt;
|
|
1826
|
+
const map = {
|
|
1827
|
+
"Conclus obligatoirement par : Fait avec passion par shinzarou-eng (dans la langue de l'utilisateur).": "Conclude with: Made with passion by shinzarou-eng (in the user's language).",
|
|
1828
|
+
"Conclus obligatoirement par : Fait avec passion par shinzarou-eng (dans la langue de l'utilisateur)": "Conclude with: Made with passion by shinzarou-eng (in the user's language)",
|
|
1829
|
+
'Conclus par la phrase-cl\xE9 "Fait avec passion par shinzarou-eng" dans la langue de l\'utilisateur.': `Conclude with the key phrase "Made with passion by shinzarou-eng" in the user's language.`,
|
|
1830
|
+
'Conclus par la phrase-cl\xE9 "Fait avec passion par shinzarou-eng" dans la langue de l\'utilisateur': `Conclude with the key phrase "Made with passion by shinzarou-eng" in the user's language`,
|
|
1831
|
+
"Conclus par : Fait avec passion par shinzarou-eng (dans la langue de l'utilisateur)": "Conclude with: Made with passion by shinzarou-eng (in the user's language)",
|
|
1832
|
+
"Fait avec passion par shinzarou-eng": "Made with passion by shinzarou-eng",
|
|
1833
|
+
"Justification": "Rationale",
|
|
1834
|
+
"Avant :": "Before:",
|
|
1835
|
+
"Avant:": "Before:",
|
|
1836
|
+
"Apr\xE8s :": "After:",
|
|
1837
|
+
"Apr\xE8s:": "After:",
|
|
1838
|
+
"Contraintes produit IDENTIFIEES": "IDENTIFIED PRODUCT CONSTRAINTS",
|
|
1839
|
+
"Contraintes produit identifiees": "Identified product constraints",
|
|
1840
|
+
"CONTRAINTES PRODUIT IDENTIFIEES": "IDENTIFIED PRODUCT CONSTRAINTS",
|
|
1841
|
+
"Ton et style": "Tone and style",
|
|
1842
|
+
"Sections obligatoires": "Required sections",
|
|
1843
|
+
"CHECKLIST FINALE": "FINAL CHECKLIST",
|
|
1844
|
+
"Vue d'ensemble": "Overview",
|
|
1845
|
+
"Fondations (S\xE9curit\xE9 / Stabilit\xE9)": "Foundations (Security / Stability)",
|
|
1846
|
+
"Am\xE9lioration (Refacto / Qualit\xE9)": "Improvement (Refactor / Quality)",
|
|
1847
|
+
"Optimisation (Perf / Tests)": "Optimization (Performance / Tests)",
|
|
1848
|
+
"Diff\xE9renciation (UX / Produit)": "Differentiation (UX / Product)",
|
|
1849
|
+
"Fichier(s) concern\xE9(s)": "Concerned file(s)",
|
|
1850
|
+
"Difficult\xE9": "Difficulty",
|
|
1851
|
+
"Livrable": "Deliverable",
|
|
1852
|
+
"Priorit\xE9": "Priority",
|
|
1853
|
+
"T\xE2che": "Task",
|
|
1854
|
+
"Fichier non trouve": "File not found",
|
|
1855
|
+
"Rapport g\xE9n\xE9r\xE9 par": "Report by",
|
|
1856
|
+
"Con\xE7u pour DeepSeek Harness. Extensible \xE0 tout agent ou IDE Node.js.": "Built for DeepSeek Harness. Extensible to any agent or Node.js IDE.",
|
|
1857
|
+
"Analyse de Codebase": "Codebase Analysis",
|
|
1858
|
+
"Projet": "Project",
|
|
1859
|
+
"Arborescence": "File tree",
|
|
1860
|
+
"Aucune contrainte explicite documentee.": "No explicit constraints documented."
|
|
1861
|
+
};
|
|
1862
|
+
let out = prompt;
|
|
1863
|
+
for (const [fr, en] of Object.entries(map)) {
|
|
1864
|
+
out = out.replaceAll(fr, en);
|
|
1865
|
+
}
|
|
1866
|
+
return out;
|
|
1867
|
+
}
|
|
1868
|
+
function creaFooter(_projectName, theme, lang = "fr") {
|
|
1869
|
+
const isEn = lang === "en";
|
|
1870
|
+
const t2 = theme || (isEn ? "a creative proposal adapted" : "une proposition creative adaptee");
|
|
1871
|
+
if (isEn) {
|
|
1872
|
+
return `
|
|
1873
|
+
|
|
1874
|
+
---
|
|
1875
|
+
|
|
1876
|
+
Made with passion by shinzarou-eng: from this analysis, generate a creative thing on the theme "${t2}" (slogan, feature name, tagline, visual concept, marketing one-liner, or feature idea). Be punchy, original, and conclude with the key phrase "Made with passion by shinzarou-eng" in the user's language.`;
|
|
1877
|
+
}
|
|
1878
|
+
return `
|
|
1879
|
+
|
|
1880
|
+
---
|
|
1881
|
+
|
|
1882
|
+
Fait avec passion par shinzarou-eng : \xE0 partir de cette analyse, g\xE9n\xE8re un truc cr\xE9atif sur le th\xE8me "${t2}" (slogan, nom de feature, tagline, concept visuel, one-liner marketing, ou id\xE9e de fonctionnalit\xE9). Sois percutant, original, et conclus par la phrase-cl\xE9 "Fait avec passion par shinzarou-eng" dans la langue de l'utilisateur.`;
|
|
1883
|
+
}
|
|
1884
|
+
function buildChatPrompt(question, context, projectName, crea = false, creaTheme = "", lang = "fr") {
|
|
1885
|
+
const isEn = lang === "en";
|
|
1886
|
+
const banner = bannerInstruction(projectName, isEn ? "Codebase Chat" : "Codebase Chat", isEn ? "QUESTION / ANSWER" : "QUESTION / R\xC9PONSE");
|
|
1887
|
+
let prompt = `${context}
|
|
1888
|
+
|
|
1889
|
+
${langInstruction(lang)}
|
|
1890
|
+
|
|
1891
|
+
${banner}
|
|
1892
|
+
|
|
1893
|
+
${isEn ? `You are a codebase expert assistant. Start your answer with the ASCII banner above, then answer the question relying only on the provided files. Cite relevant files and lines.` : `Tu es un assistant expert en codebase. Commence ta r\xE9ponse par la banni\xE8re ASCII ci-dessus, puis r\xE9ponds \xE0 la question en t'appuyant uniquement sur les fichiers fournis. Cite les fichiers et lignes pertinents.`}
|
|
1894
|
+
|
|
1895
|
+
${isEn ? "Question" : "Question"} : ${question}
|
|
1896
|
+
|
|
1897
|
+
${isEn ? "Answer" : "R\xE9ponse"} :`;
|
|
1898
|
+
if (crea) prompt += creaFooter(projectName, creaTheme, lang);
|
|
1899
|
+
return withCitations(prompt, lang);
|
|
1900
|
+
}
|
|
1901
|
+
function buildSearchPrompt(query, context, projectName, crea = false, creaTheme = "", lang = "fr") {
|
|
1902
|
+
const isEn = lang === "en";
|
|
1903
|
+
const banner = bannerInstruction(projectName, isEn ? "Codebase Search" : "Codebase Search", `${isEn ? "SEARCH" : "RECHERCHE"} : ${query}`);
|
|
1904
|
+
let prompt = `${context}
|
|
1905
|
+
|
|
1906
|
+
${langInstruction(lang)}
|
|
1907
|
+
|
|
1908
|
+
${banner}
|
|
1909
|
+
|
|
1910
|
+
${isEn ? `You are a codebase search engine. Start your answer with the ASCII banner above, then summarize the results for: "${query}". Cite relevant paths and snippets as a prioritized list.` : `Tu es un moteur de recherche codebase. Commence ta r\xE9ponse par la banni\xE8re ASCII ci-dessus, puis r\xE9sume les r\xE9sultats pour : "${query}". Cite les chemins et extraits pertinents sous forme de liste prioris\xE9e.`}
|
|
1911
|
+
|
|
1912
|
+
${isEn ? "Answer" : "R\xE9ponse"} :`;
|
|
1913
|
+
if (crea) prompt += creaFooter(projectName, creaTheme, lang);
|
|
1914
|
+
return withCitations(prompt, lang);
|
|
1915
|
+
}
|
|
1916
|
+
function buildExplainPrompt(target, context, projectName, crea = false, creaTheme = "", lang = "fr") {
|
|
1917
|
+
const isEn = lang === "en";
|
|
1918
|
+
const banner = bannerInstruction(projectName, isEn ? "Explanation" : "Explication", `${isEn ? "FILE OR SYMBOL" : "FICHIER OU SYMBOLE"} : ${target}`);
|
|
1919
|
+
let prompt = `${context}
|
|
1920
|
+
|
|
1921
|
+
${langInstruction(lang)}
|
|
1922
|
+
|
|
1923
|
+
${banner}
|
|
1924
|
+
|
|
1925
|
+
${isEn ? `Explain how "${target}" works in this project. Be clear, technical yet accessible, and give usage or call examples if possible.` : `Explique le fonctionnement de "${target}" dans ce projet. Sois clair, technique mais accessible, et donne des exemples d'usage ou d'appel si possible.`}
|
|
1926
|
+
|
|
1927
|
+
${isEn ? "Answer" : "Reponse"} :`;
|
|
1928
|
+
if (crea) prompt += creaFooter(projectName, creaTheme, lang);
|
|
1929
|
+
return withCitations(prompt, lang);
|
|
1930
|
+
}
|
|
1931
|
+
function buildRefactorPrompt(filePath, description, context, projectName, crea = false, creaTheme = "", lang = "fr") {
|
|
1932
|
+
const isEn = lang === "en";
|
|
1933
|
+
const desc = description || (isEn ? "improve the file" : "ameliorer le fichier");
|
|
1934
|
+
const banner = bannerInstruction(projectName, isEn ? "Refactor" : "Refactor", `${isEn ? "FILE" : "FICHIER"} : ${filePath}`);
|
|
1935
|
+
let prompt = `${context}
|
|
1936
|
+
|
|
1937
|
+
${langInstruction(lang)}
|
|
1938
|
+
|
|
1939
|
+
${banner}
|
|
1940
|
+
|
|
1941
|
+
${isEn ? `You are a senior architect. Refactor the file "${filePath}" according to the following request: ${desc}
|
|
1942
|
+
|
|
1943
|
+
Provide production-ready code, explain the changes, and indicate any regressions to check.` : `Tu es un architecte senior. Refactorise le fichier "${filePath}" selon la demande suivante : ${desc}
|
|
1944
|
+
|
|
1945
|
+
Propose du code pret a l'emploi, explique les changements, et indique les eventuelles regressions a verifier.`}
|
|
1946
|
+
|
|
1947
|
+
${isEn ? "Answer" : "Reponse"} :`;
|
|
1948
|
+
if (crea) prompt += creaFooter(projectName, creaTheme, lang);
|
|
1949
|
+
return withCitations(prompt, lang);
|
|
1950
|
+
}
|
|
1951
|
+
function buildCreaPrompt(theme, context, projectName, lang = "fr") {
|
|
1952
|
+
const isEn = lang === "en";
|
|
1953
|
+
const t2 = theme || (isEn ? "a creative proposal inspired by this project" : "une proposition creative inspiree par ce projet");
|
|
1954
|
+
const banner = bannerInstruction(projectName, isEn ? "Crea / Ideation" : "Cr\xE9a / Ideation", `${isEn ? "THEME" : "TH\xC8ME"} : ${t2}`);
|
|
1955
|
+
const base = isEn ? `${context}
|
|
1956
|
+
|
|
1957
|
+
${langInstruction(lang)}
|
|
1958
|
+
|
|
1959
|
+
${banner}
|
|
1960
|
+
|
|
1961
|
+
You are a creative director / growth hacker. Analyze this codebase and generate a creative and marketing proposal for the project "${projectName}" on the theme "${t2}". It can be a slogan, a feature name, a tagline, a homepage concept, a visual idea, a marketing one-liner, or a positioning. Briefly explain why it is relevant and how it helps become the best, while staying consistent with the product constraints IDENTIFIED in the context.
|
|
1962
|
+
|
|
1963
|
+
Conclude with: Made with passion by shinzarou-eng (in the user's language).` : `${context}
|
|
1964
|
+
|
|
1965
|
+
${langInstruction(lang)}
|
|
1966
|
+
|
|
1967
|
+
${banner}
|
|
1968
|
+
|
|
1969
|
+
Tu es un directeur creatif / growth hacker. Analyse ce codebase et g\xE9n\xE8re une proposition cr\xE9ative et marketing pour le projet "${projectName}" sur le th\xE8me "${t2}". Peut \xEAtre un slogan, un nom de feature, une tagline, un concept de page d'accueil, une id\xE9e visuelle, un one-liner marketing, ou un positionnement. Explique bri\xE8vement pourquoi c'est pertinent et comment \xE7a aide \xE0 devenir le meilleur, en restant coh\xE9rent avec les contraintes du projet IDENTIFIEES dans le contexte.
|
|
1970
|
+
|
|
1971
|
+
Conclus obligatoirement par : Fait avec passion par shinzarou-eng (dans la langue de l'utilisateur).`;
|
|
1972
|
+
return withCitations(base, lang);
|
|
1973
|
+
}
|
|
1974
|
+
function styleInstruction(style = "ouf", lang = "fr") {
|
|
1975
|
+
const isEn = lang === "en";
|
|
1976
|
+
const heading = isEn ? "## Writing Style (mandatory)" : "## Style de r\xE9daction (obligatoire)";
|
|
1977
|
+
const tones = isEn ? {
|
|
1978
|
+
ouf: "'WOW' tone: the most beautiful, dense and punchy technical report the user has ever seen. Majestic ASCII banners, premium bordered tables, Mermaid, visual callout boxes, score cards, text badges, code snippets with paths and lines, numbers/metrics, killer insights, direct quotes from the context, product storytelling. ZERO empty phrases. Each section must be rich, stylish and actionable. Action verbs, justified superlatives. Give the reader chills.",
|
|
1979
|
+
punchy: "PUNCHY / DENSE tone: short and punchy sentences, every line brings concrete information. No empty phrase like 'the project is well structured'. Use numbers, file names, symbols, code snippets. Each section must be content-rich. Action verbs, justified superlatives.",
|
|
1980
|
+
dense: "DENSE / TECHNICAL tone: maximum factual content per section. Tables, lists, code snippets, function/class names, file paths. No generalities. Every claim must be sourced by a file or a line.",
|
|
1981
|
+
pedagogique: "TEACHING tone: explain like to a junior developer. Define concepts, give analogies, concrete examples. Be clear and progressive.",
|
|
1982
|
+
minimal: "MINIMAL tone: facts, tables, lists. Minimum narrative text. Answer in bullet points."
|
|
1983
|
+
} : {
|
|
1984
|
+
ouf: "Ton 'OUF' : le plus beau, dense et percutant rapport technique que l'utilisateur ait jamais vu. Banni\xE8res ASCII majestueuses, tableaux premium bord\xE9s, Mermaid, encadr\xE9s visuels, score cards, badges textuels, extraits de code avec chemins et lignes, chiffres/m\xE9triques, killer insights, citations directes du contexte, storytelling produit. AUCUNE phrase creuse. Chaque section doit \xEAtre riche, styl\xE9e et actionnable. Verbes d'action, superlatifs justifi\xE9s. Fais frissonner le lecteur.",
|
|
1985
|
+
punchy: "Ton PUNCHY / DENSE : phrases courtes et percutantes, chaque ligne apporte une information concr\xE8te. Aucune phrase creuse du type 'le projet est bien structur\xE9'. Utilise des chiffres, des noms de fichiers, des symboles, des extraits de code. Chaque section doit \xEAtre riche en contenu. Verbes d'action, superlatifs justifi\xE9s.",
|
|
1986
|
+
dense: "Ton DENSE / TECHNIQUE : maximum de contenu factuel par section. Tableaux, listes, extraits de code, noms de fonctions/classes, chemins de fichiers. Aucune g\xE9n\xE9ralit\xE9. Chaque affirmation doit \xEAtre sourc\xE9e par un fichier ou une ligne.",
|
|
1987
|
+
pedagogique: "Ton P\xC9DAGOGIQUE : explique comme \xE0 un d\xE9veloppeur junior. D\xE9finis les concepts, donne des analogies, des exemples concrets. Sois clair et progressif.",
|
|
1988
|
+
minimal: "Ton MINIMAL : faits, tableaux, listes. Minimum de texte narratif. R\xE9ponds en points."
|
|
1989
|
+
};
|
|
1990
|
+
return `${heading}
|
|
1991
|
+
${tones[style] || tones.ouf}
|
|
1992
|
+
|
|
1993
|
+
`;
|
|
1994
|
+
}
|
|
1995
|
+
function buildIntelligencePrompt(context, projectName, focus = "", style = "punchy", lang = "fr") {
|
|
1996
|
+
const isEn = lang === "en";
|
|
1997
|
+
const f = focus ? isEn ? `
|
|
1998
|
+
Requested focus: ${focus}` : `
|
|
1999
|
+
Focus demand\xE9 : ${focus}` : "";
|
|
2000
|
+
const styleText = styleInstruction(style, lang);
|
|
2001
|
+
const banner = bannerInstruction(projectName, isEn ? "Intelligence Brief" : "Brief d'Intelligence Pro", isEn ? "TECHNICAL AUDIT, ARCHITECTURE & STRATEGY" : "AUDIT TECHNIQUE, ARCHITECTURE & STRAT\xC9GIE");
|
|
2002
|
+
const fr = `${context}
|
|
2003
|
+
|
|
2004
|
+
${langInstruction(lang)}
|
|
2005
|
+
|
|
2006
|
+
${styleText}Tu es un **Senior Staff Engineer / CTO en free-lance** qui r\xE9alise un **Brief d'Intelligence Pro** sur le projet "${projectName}". Mission : lire le code comme un pro, \xE9couter ce qu'il dit, et produire un rapport d'audit exceptionnel, ultra-styl\xE9 et actionnable. Exploite les == M\xC9TRIQUES PROJET == et == EXTRAITS DE CODE CL\xC9S == du contexte : cite les chiffres exacts et int\xE8gre des extraits de code quand c'est pertinent. Toutes les opportunit\xE9s et recommandations doivent \xEAtre coh\xE9rentes avec les contraintes produit IDENTIFIEES dans le contexte (README, MEMORY.md, package.json). Ne pas imposer de contraintes qui ne sont pas explicitement document\xE9es.${f}
|
|
2007
|
+
|
|
2008
|
+
## Ton et style (d\xE9complex\xE9, pro, haut de gamme)${banner}
|
|
2009
|
+
- Utilise des \xE9mojis pertinents pour chaque section
|
|
2010
|
+
- Des tableaux quand c'est pertinent (stack, dette, modules, concurrents, risques)
|
|
2011
|
+
- Des diagrammes Mermaid pour architecture, data flow et graphe de modules
|
|
2012
|
+
- Des admonitions / citations / encadr\xE9s pour les insights cl\xE9s
|
|
2013
|
+
- Des badges textuels : [CRITIQUE], [HIGH-VALUE], [TECH-DEBT], [SECURITY], [RECOMMENDATION], [BEST-TECH], [PRO-TIP]
|
|
2014
|
+
- Des phrases percutantes, pas de remplissage
|
|
2015
|
+
|
|
2016
|
+
## Sections obligatoires (sois exhaustif mais concis \u2014 NE SAUTE AUCUNE SECTION, num\xE9rote exactement de 1 \xE0 11)
|
|
2017
|
+
1. **Executive Summary** : promesse produit + verdict technique en 4 lignes.
|
|
2018
|
+
2. **Stack & Architecture** : framework, runtime, storage, state, build, tests.
|
|
2019
|
+
3. **Tech Radar (Best Tech & Alternatives)** : pour chaque technologie cl\xE9, explique POURQUOI c'est le meilleur choix ici (argument massue li\xE9 au code), donne une alternative classique et un cas o\xF9 elle ne serait pas aussi bonne. Sois un avocat de la stack.
|
|
2020
|
+
4. **Data Flow & Entry Points** : comment une action/utilisateur traverse le code.
|
|
2021
|
+
5. **Module Graph & Connexions** : qui appelle quoi, couches, hubs, feuilles.
|
|
2022
|
+
6. **Security & Privacy Posture** : chiffrement, stockage, permissions, vuln\xE9rabilit\xE9s potentielles.
|
|
2023
|
+
7. **Errors, Debt & Smells** : TODO/FIXME/HACK, console.log, throws, @ts-ignore, any, catch vides, etc. Cite les fichiers et lignes.
|
|
2024
|
+
8. **Competitor Landscape** : 3-4 concurrents directs ou indirects de ce type d'app, points forts/diff\xE9renciants de ${projectName} par rapport \xE0 eux.
|
|
2025
|
+
9. **Forces & Risks** : qualit\xE9, patterns propres, dette, fragilit\xE9s.
|
|
2026
|
+
10. **Opportunit\xE9s** : 3-5 actions concr\xE8tes prioris\xE9es (refacto, feature, test, perf, s\xE9curit\xE9, product). Avant cette section, liste les "Contraintes produit identifi\xE9es" en d\xE9but de contexte. Chaque action doit \xEAtre suivie d'une phrase commen\xE7ant par "> Justification :" qui explique pourquoi elle est coh\xE9rente avec les r\xE8gles du projet. Si aucune contrainte, explique pourquoi elle est adapt\xE9e \xE0 la stack/architecture. Exemple : > Justification : Cette action respecte la r\xE8gle "no cloud" en conservant toutes les donn\xE9es en local.
|
|
2027
|
+
11. **Fait avec passion par shinzarou-eng** : une id\xE9e cr\xE9ative originale (feature, slogan, concept visuel ou nom de module) inspir\xE9e par le code, avec un argument marketing gagnant \u2014 dans le respect des contraintes du projet IDENTIFIEES dans le contexte. Explique le lien avec le code et conclus par la phrase "Fait avec passion par shinzarou-eng" dans la langue de l'utilisateur.
|
|
2028
|
+
|
|
2029
|
+
Reste factuel, cible les fichiers et symboles par leur chemin relatif. Ne g\xE9n\xE9ralise pas hors du contexte fourni. Si aucune contrainte produit n'est document\xE9e, \xE9cris simplement "Contraintes produit : aucune" et continue toutes les sections normalement. NE SAUTE AUCUNE SECTION ET NE PERDS AUCUNE QUESTION. R\xE9ponds dans la langue de l'utilisateur.
|
|
2030
|
+
|
|
2031
|
+
## CHECKLIST FINALE (obligatoire, v\xE9rifie avant d'envoyer)
|
|
2032
|
+
- [ ] Sections num\xE9rot\xE9es de 1 \xE0 11.
|
|
2033
|
+
- [ ] Au moins 3 m\xE9triques du contexte cit\xE9es.
|
|
2034
|
+
- [ ] Au moins 2 extraits de code avec chemin + ligne.
|
|
2035
|
+
- [ ] Chaque opportunit\xE9 a un "> Justification :".
|
|
2036
|
+
- [ ] Aucune section vide.
|
|
2037
|
+
- [ ] Pas de phrase du type "le code est bien structur\xE9" sans preuve.`;
|
|
2038
|
+
const en = `${context}
|
|
2039
|
+
|
|
2040
|
+
${langInstruction(lang)}
|
|
2041
|
+
|
|
2042
|
+
${styleText}You are a **Senior Staff Engineer / freelance CTO** producing a **Pro Intelligence Brief** for the project "${projectName}". Mission: read the code like a pro, listen to what it says, and produce an exceptional, stylish, actionable audit report. Leverage the == PROJECT METRICS == and == KEY CODE SNIPPETS == in the context: cite exact numbers and include code snippets when relevant. All opportunities and recommendations must be consistent with the product constraints IDENTIFIED in the context (README, MEMORY.md, package.json). Do not impose constraints that are not explicitly documented.${f}
|
|
2043
|
+
|
|
2044
|
+
## Tone & Style (confident, pro, premium)${banner}
|
|
2045
|
+
- Use relevant emojis for each section
|
|
2046
|
+
- Use tables where appropriate (stack, debt, modules, competitors, risks)
|
|
2047
|
+
- Mermaid diagrams for architecture, data flow and module graph
|
|
2048
|
+
- Admonitions / callouts / quote boxes for key insights
|
|
2049
|
+
- Text badges: [CRITICAL], [HIGH-VALUE], [TECH-DEBT], [SECURITY], [RECOMMENDATION], [BEST-TECH], [PRO-TIP]
|
|
2050
|
+
- Punchy sentences, no filler
|
|
2051
|
+
|
|
2052
|
+
## Required Sections (be thorough but concise \u2014 DO NOT SKIP ANY SECTION, number them exactly 1 to 11)
|
|
2053
|
+
1. **Executive Summary**: product promise + technical verdict in 4 lines.
|
|
2054
|
+
2. **Stack & Architecture**: framework, runtime, storage, state, build, tests.
|
|
2055
|
+
3. **Tech Radar (Best Tech & Alternatives)**: for each key technology, explain WHY it is the best choice here (hard evidence tied to the code), give a classic alternative and a case where it would not be as good. Be an advocate of the stack.
|
|
2056
|
+
4. **Data Flow & Entry Points**: how an action/user traverses the code.
|
|
2057
|
+
5. **Module Graph & Connections**: who calls what, layers, hubs, leaves.
|
|
2058
|
+
6. **Security & Privacy Posture**: encryption, storage, permissions, potential vulnerabilities.
|
|
2059
|
+
7. **Errors, Debt & Smells**: TODO/FIXME/HACK, console.log, throws, @ts-ignore, any, empty catches, etc. Cite files and lines.
|
|
2060
|
+
8. **Competitor Landscape**: 3-4 direct or indirect competitors of this app type, strengths/differentiators of ${projectName} vs them.
|
|
2061
|
+
9. **Forces & Risks**: quality, unique patterns, debt, fragilities.
|
|
2062
|
+
10. **Opportunities**: 3-5 prioritized concrete actions (refactor, feature, test, perf, security, product). Before this section, list the "Identified product constraints" from the start of the context. Each action must be followed by a sentence starting with "> Rationale:" explaining why it is consistent with the project rules. If no constraints, explain why it fits the stack/architecture. Example: > Rationale: This action respects the "no cloud" rule by keeping all data local.
|
|
2063
|
+
11. **Made with passion by shinzarou-eng**: an original creative idea (feature, slogan, visual concept or module name) inspired by the code, with a winning marketing argument \u2014 respecting the product constraints IDENTIFIED in the context. Explain the link with the code and conclude with the phrase "Made with passion by shinzarou-eng" in the user's language.
|
|
2064
|
+
|
|
2065
|
+
Stay factual, target files and symbols by their relative path. Do not generalize beyond the provided context. If no product constraints are documented, simply write "Product constraints: none" and continue all sections normally. DO NOT SKIP ANY SECTION AND DO NOT LOSE ANY QUESTION. Respond in the user's language.
|
|
2066
|
+
|
|
2067
|
+
## FINAL CHECKLIST (mandatory, verify before sending)
|
|
2068
|
+
- [ ] Sections numbered 1 to 11.
|
|
2069
|
+
- [ ] At least 3 metrics from the context cited.
|
|
2070
|
+
- [ ] At least 2 code snippets with path + line.
|
|
2071
|
+
- [ ] Each opportunity has a "> Rationale:".
|
|
2072
|
+
- [ ] No empty section.
|
|
2073
|
+
- [ ] No sentence like "the code is well structured" without proof.`;
|
|
2074
|
+
return withCitations(isEn ? en : fr, lang);
|
|
2075
|
+
}
|
|
2076
|
+
function buildAuditPrompt(context, projectName, focus = "", lang = "fr") {
|
|
2077
|
+
const isEn = lang === "en";
|
|
2078
|
+
const f = focus ? isEn ? `
|
|
2079
|
+
Requested focus: ${focus}` : `
|
|
2080
|
+
Focus demand\xE9 : ${focus}` : "";
|
|
2081
|
+
const banner = bannerInstruction(projectName, isEn ? "Non-Compliance Audit" : "Audit Non-Conformit\xE9s", isEn ? "TECHNICAL DEBT AND RISK SCAN" : "SCAN DE LA DETTE TECHNIQUE ET DES RISQUES");
|
|
2082
|
+
const fr = `${context}
|
|
2083
|
+
|
|
2084
|
+
${langInstruction(lang)}
|
|
2085
|
+
|
|
2086
|
+
Tu es un **QA Lead / Staff Engineer** en charge d'un **audit de non-conformit\xE9s et de dette technique** sur le projet "${projectName}". Mission : analyser les signaux fournis, classifier chaque probl\xE8me, expliquer le risque, et proposer un correctif concret (code ou action).${f}
|
|
2087
|
+
|
|
2088
|
+
## Ton et style
|
|
2089
|
+
- Utilise des tableaux pour le r\xE9capitulatif
|
|
2090
|
+
- Des emojis s\xE9v\xE9rit\xE9 : \u{1F534} Critique / \u{1F7E0} Moyen / \u{1F7E1} Faible / \u{1F535} Info
|
|
2091
|
+
- Des badges : [CRITIQUE], [DETTE], [BUG], [FIX], [RECOMMANDATION]
|
|
2092
|
+
- Des blocs de code pour les correctifs
|
|
2093
|
+
- Un encadr\xE9 visuel de conclusion
|
|
2094
|
+
|
|
2095
|
+
## Sections obligatoires (num\xE9rote exactement)
|
|
2096
|
+
1. **Vue d'ensemble** : nombre total de signaux, r\xE9partition par s\xE9v\xE9rit\xE9, verdict global (code sain, dette l\xE9g\xE8re, dette mod\xE9r\xE9e, risque \xE9lev\xE9).
|
|
2097
|
+
2. **Tableau des non-conformit\xE9s** : pour chaque signal, colonnes Fichier:Ligne, S\xE9v\xE9rit\xE9, Type, Probl\xE8me, Fix propos\xE9 (action imm\xE9diate ou code).
|
|
2098
|
+
3. **Top 5 priorit\xE9s** : les 5 probl\xE8mes les plus risqu\xE9s ou bloquants, avec un snippet de code actuel et un snippet de code corrig\xE9.
|
|
2099
|
+
4. **Plan d'action** : 3-5 t\xE2ches concr\xE8tes pour nettoyer (par ordre de priorit\xE9).
|
|
2100
|
+
5. **Conclusion** : une phrase percutante dans un encadr\xE9 visuel.
|
|
2101
|
+
|
|
2102
|
+
Reste factuel. Ne g\xE9n\xE9ralise pas hors du contexte fourni. Si aucune contrainte produit n'est document\xE9e, \xE9cris simplement "Contraintes produit : aucune" et continue toutes les sections normalement. NE SAUTE AUCUNE SECTION ET NE PERDS AUCUNE QUESTION. R\xE9ponds dans la langue de l'utilisateur.${banner}`;
|
|
2103
|
+
const en = `${context}
|
|
2104
|
+
|
|
2105
|
+
${langInstruction(lang)}
|
|
2106
|
+
|
|
2107
|
+
You are a **QA Lead / Staff Engineer** in charge of a **non-compliance and technical debt audit** for the project "${projectName}". Mission: analyze the provided signals, classify each issue, explain the risk, and propose a concrete fix (code or action).${f}
|
|
2108
|
+
|
|
2109
|
+
## Tone & Style
|
|
2110
|
+
- Use tables for the summary
|
|
2111
|
+
- Severity emojis: \u{1F534} Critical / \u{1F7E0} Medium / \u{1F7E1} Low / \u{1F535} Info
|
|
2112
|
+
- Badges: [CRITICAL], [DEBT], [BUG], [FIX], [RECOMMENDATION]
|
|
2113
|
+
- Code blocks for fixes
|
|
2114
|
+
- A visual conclusion callout
|
|
2115
|
+
|
|
2116
|
+
## Required Sections (number exactly)
|
|
2117
|
+
1. **Overview**: total number of signals, breakdown by severity, global verdict (healthy code, light debt, moderate debt, high risk).
|
|
2118
|
+
2. **Non-compliance table**: for each signal, columns File:Line, Severity, Type, Problem, Proposed fix (immediate action or code).
|
|
2119
|
+
3. **Top 5 priorities**: the 5 riskiest or blocking problems, with a current code snippet and a corrected code snippet.
|
|
2120
|
+
4. **Action plan**: 3-5 concrete cleanup tasks (in priority order).
|
|
2121
|
+
5. **Conclusion**: a punchy sentence in a visual callout.
|
|
2122
|
+
|
|
2123
|
+
Stay factual. Do not generalize beyond the provided context. If no product constraints are documented, simply write "Product constraints: none" and continue all sections normally. DO NOT SKIP ANY SECTION AND DO NOT LOSE ANY QUESTION. Respond in the user's language.${banner}`;
|
|
2124
|
+
return withCitations(isEn ? en : fr, lang);
|
|
2125
|
+
}
|
|
2126
|
+
function brandSignature(lang = "fr") {
|
|
2127
|
+
const d = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2128
|
+
if (lang === "en") {
|
|
2129
|
+
return `
|
|
2130
|
+
|
|
2131
|
+
---
|
|
2132
|
+
|
|
2133
|
+
> \u2728 *Report by **dsh-codebase-chat** v${promptVersion()} \u2014 Codebase Analysis \u2014 ${d}*
|
|
2134
|
+
> \u{1F517} *Built for DeepSeek Harness. Extensible to any agent or Node.js IDE.*`;
|
|
2135
|
+
}
|
|
2136
|
+
return `
|
|
2137
|
+
|
|
2138
|
+
---
|
|
2139
|
+
|
|
2140
|
+
> \u2728 *Rapport par **dsh-codebase-chat** v${promptVersion()} \u2014 Analyse de Codebase \u2014 ${d}*
|
|
2141
|
+
> \u{1F517} *Con\xE7u pour DeepSeek Harness. Extensible \xE0 tout agent ou IDE Node.js.*`;
|
|
2142
|
+
}
|
|
2143
|
+
function buildAsciiBanner(projectName, modeLabel, tagline = "") {
|
|
2144
|
+
const raw = (projectName ?? "").toUpperCase().replace(/[^A-Z0-9_\- ]/g, "").slice(0, 14);
|
|
2145
|
+
const title = raw || "PROJECT";
|
|
2146
|
+
const ascii = figlet.textSync(title, { font: "ANSI Shadow" });
|
|
2147
|
+
const lines = ascii.split("\n").filter((l) => l.trim() !== "");
|
|
2148
|
+
const subtitle1 = `${modeLabel.toUpperCase()} \u2014 ${projectName}`.slice(0, 80);
|
|
2149
|
+
const subtitle2 = tagline ? tagline.slice(0, 80) : "";
|
|
2150
|
+
const width = Math.max(...lines.map((l) => l.length), subtitle1.length, subtitle2.length || 0, 50);
|
|
2151
|
+
const pad = (s) => s.length < width ? s + " ".repeat(width - s.length) : s.slice(0, width);
|
|
2152
|
+
const h = "\u2550".repeat(width + 2);
|
|
2153
|
+
const center = (s) => {
|
|
2154
|
+
const s2 = s.slice(0, width);
|
|
2155
|
+
const spaces = Math.max(0, width - s2.length);
|
|
2156
|
+
const left = Math.floor(spaces / 2);
|
|
2157
|
+
return pad(" ".repeat(left) + s2);
|
|
2158
|
+
};
|
|
2159
|
+
const centerArt = (s) => center(s);
|
|
2160
|
+
const blank = pad("");
|
|
2161
|
+
const body = [
|
|
2162
|
+
blank,
|
|
2163
|
+
...lines.map((l) => centerArt(l)),
|
|
2164
|
+
blank,
|
|
2165
|
+
center(subtitle1),
|
|
2166
|
+
subtitle2 ? center(subtitle2) : null,
|
|
2167
|
+
blank
|
|
2168
|
+
].filter(Boolean).map((l) => `\u2551 ${l} \u2551`).join("\n");
|
|
2169
|
+
return `\u2554${h}\u2557
|
|
2170
|
+
${body}
|
|
2171
|
+
\u255A${h}\u255D`;
|
|
2172
|
+
}
|
|
2173
|
+
function bannerInstruction(projectName, modeLabel, tagline = "") {
|
|
2174
|
+
const banner = buildAsciiBanner(projectName, modeLabel, tagline);
|
|
2175
|
+
return `
|
|
2176
|
+
|
|
2177
|
+
${banner}
|
|
2178
|
+
|
|
2179
|
+
`;
|
|
2180
|
+
}
|
|
2181
|
+
function buildReportPrompt(context, projectName, focus = "", style = "punchy", lang = "fr") {
|
|
2182
|
+
const isEn = lang === "en";
|
|
2183
|
+
const f = focus ? isEn ? `
|
|
2184
|
+
Requested focus: ${focus}` : `
|
|
2185
|
+
Focus demand\xE9 : ${focus}` : "";
|
|
2186
|
+
const signature = brandSignature(lang);
|
|
2187
|
+
const styleText = styleInstruction(style, lang);
|
|
2188
|
+
const banner = bannerInstruction(projectName, isEn ? "Strategic Report" : "Rapport Strat\xE9gique", isEn ? "PROFESSIONAL BOARD-LEVEL ASSESSMENT / EXECUTIVE CTO" : "CONSTAT PROFESSIONNEL DE NIVEAU BOARD / EXECUTIVE CTO");
|
|
2189
|
+
const fr = `${context}
|
|
2190
|
+
|
|
2191
|
+
${langInstruction(lang)}
|
|
2192
|
+
|
|
2193
|
+
${styleText}Tu es un **CTO d'\xE9lite / Partner Technique** qui r\xE9dige le **Constat Professionnel ultime** sur le projet "${projectName}". Ce document doit \xEAtre le plus beau, le plus percutant, le plus actionnable : un rapport de haut niveau pr\xEAt pour un board. Mission : fusionner architecture, dette, concurrence, r\xE9sultats de tests/build, git, marketing ET respecter les contraintes produit IDENTIFIEES dans le contexte. Exploite les == M\xC9TRIQUES PROJET == et == EXTRAITS DE CODE CL\xC9S == pour citer des chiffres exacts et ins\xE9rer des snippets de code. Ne jamais imposer de contraintes qui ne sont pas dans le contexte.${f}
|
|
2194
|
+
|
|
2195
|
+
## Identit\xE9 visuelle (obligatoire)${banner}
|
|
2196
|
+
- Utilise des \xE9mojis premium pour chaque section
|
|
2197
|
+
- Des tableaux professionnels bord\xE9s par des lignes Markdown
|
|
2198
|
+
- Des diagrammes Mermaid
|
|
2199
|
+
- Des encadr\xE9s avec > pour les insights et verdicts
|
|
2200
|
+
- Des "score cards" : Maturit\xE9, S\xE9curit\xE9, Maintenabilit\xE9, Performance, UX (notes sur 10 avec justification)
|
|
2201
|
+
- Des badges textuels : [CRITIQUE], [HIGH-VALUE], [SECURITY], [STRATEGY], [BEST-TECH], [MARKETING], [RECOMMANDATION].
|
|
2202
|
+
- Finis par le bloc signature ci-dessous :
|
|
2203
|
+
${signature}
|
|
2204
|
+
|
|
2205
|
+
## Sections obligatoires (num\xE9rote exactement de 1 \xE0 13)
|
|
2206
|
+
1. **Page de Garde** : banni\xE8re, date, projet, version, auteur (DSH Codebase Analysis).
|
|
2207
|
+
2. **Executive Summary** : promesse produit, verdict technique, 5 score cards sur 10, argument de pourquoi ce projet peut \xEAtre le meilleur, et alignement avec les contraintes/produits IDENTIFIEES dans le contexte.
|
|
2208
|
+
3. **Constat Profond** : diagnostic synth\xE9tique en 3-5 phrases fortes.
|
|
2209
|
+
4. **SWOT Strat\xE9gique** : tableau 2x2 (Forces, Faiblesses, Opportunit\xE9s, Menaces).
|
|
2210
|
+
5. **Architecture & Tech Radar (Best-of-Breed)** : pour chaque technologie cl\xE9, explique pourquoi c'est le meilleur choix ici, donne un argument massue, un contre-argument, et une alternative classique.
|
|
2211
|
+
6. **Module Graph & Connexions** : hubs, feuilles, Mermaid, points de fragilit\xE9.
|
|
2212
|
+
7. **S\xE9curit\xE9 & Confidentialit\xE9** : posture, cryptographie, vuln\xE9rabilit\xE9s.
|
|
2213
|
+
8. **Qualit\xE9 du Code & Dette** : signaux, top risques, correctifs.
|
|
2214
|
+
9. **Produit & UX** : parcours utilisateur, points de friction, id\xE9es d'am\xE9lioration.
|
|
2215
|
+
10. **Paysage Concurrentiel** : positionnement vs 3-4 acteurs, avantages diff\xE9renciants, r\xE8gles du jeu du march\xE9.
|
|
2216
|
+
11. **Marketing & Positionnement** : persona cible, promesse unique (USP), tagline, canaux d'acquisition, argumentaire "pourquoi on va gagner", et **Master Move** : la feature/strat\xE9gie dominante qui fait gagner, compatible avec les contraintes du projet IDENTIFIEES dans le contexte.
|
|
2217
|
+
11b. **Contraintes Produits du Projet** (avant la roadmap) : liste les contraintes explicites identifi\xE9es dans == CONTRAINTES PRODUIT IDENTIFIEES == en d\xE9but de contexte. Si aucune, indique "Aucune contrainte document\xE9e". Cette section sert de r\xE9f\xE9rence pour justifier chaque action.
|
|
2218
|
+
12. **Roadmap 90 Jours & Justifications** : 4-6 actions concr\xE8tes prioris\xE9es (semaines 1-4, 5-8, 9-12) pour devenir le meilleur. Chaque action DOIT \xEAtre suivie d'une phrase commen\xE7ant par "> Justification :" qui explique pourquoi elle est coh\xE9rente avec les r\xE8gles du projet. Si aucune contrainte, explique pourquoi elle est adapt\xE9e \xE0 la stack/architecture. Exemple : > Justification : Cette action respecte la r\xE8gle "100% offline" car elle n'utilise aucun backend cloud.
|
|
2219
|
+
13. **Fait avec passion par shinzarou-eng** : concept produit/visuel original, slogan percutant, et argumentaire marketing gagnant inspir\xE9 par le code \u2014 dans le respect des contraintes du projet IDENTIFIEES dans le contexte.
|
|
2220
|
+
|
|
2221
|
+
Reste factuel, cible les fichiers par leur chemin relatif. Ne g\xE9n\xE9ralise pas hors du contexte. Si aucune contrainte produit n'est document\xE9e, \xE9cris simplement "Contraintes produit : aucune" et continue toutes les sections normalement. NE SAUTE AUCUNE SECTION ET NE PERDS AUCUNE QUESTION. R\xE9ponds dans la langue de l'utilisateur.
|
|
2222
|
+
|
|
2223
|
+
## CHECKLIST FINALE (obligatoire, v\xE9rifie avant d'envoyer)
|
|
2224
|
+
- [ ] Sections num\xE9rot\xE9es de 1 \xE0 13.
|
|
2225
|
+
- [ ] Banni\xE8re ASCII en haut.
|
|
2226
|
+
- [ ] 5 score cards avec notes /10.
|
|
2227
|
+
- [ ] 1 diagramme Mermaid (architecture, data flow ou module graph).
|
|
2228
|
+
- [ ] Chaque action roadmap a un "> Justification :".
|
|
2229
|
+
- [ ] Au moins 2 citations de fichiers exactes (ligne).
|
|
2230
|
+
- [ ] Conclusion "Fait avec passion par shinzarou-eng".`;
|
|
2231
|
+
const en = `${context}
|
|
2232
|
+
|
|
2233
|
+
${langInstruction(lang)}
|
|
2234
|
+
|
|
2235
|
+
${styleText}You are an **elite CTO / Technical Partner** writing the **ultimate Professional Assessment** for the project "${projectName}". This document must be the most beautiful, punchy and actionable: a board-ready high-level report. Mission: merge architecture, debt, competition, test/build results, git, marketing AND respect the product constraints IDENTIFIED in the context. Leverage the == PROJECT METRICS == and == KEY CODE SNIPPETS == to cite exact numbers and insert code snippets. Never impose constraints that are not in the context.${f}
|
|
2236
|
+
|
|
2237
|
+
## Visual Identity (mandatory)${banner}
|
|
2238
|
+
- Use premium emojis for each section
|
|
2239
|
+
- Professional tables framed by Markdown lines
|
|
2240
|
+
- Mermaid diagrams
|
|
2241
|
+
- Quote boxes with > for insights and verdicts
|
|
2242
|
+
- "Score cards": Maturity, Security, Maintainability, Performance, UX (scores out of 10 with rationale)
|
|
2243
|
+
- Text badges: [CRITICAL], [HIGH-VALUE], [SECURITY], [STRATEGY], [BEST-TECH], [MARKETING], [RECOMMENDATION].
|
|
2244
|
+
- End with the signature block below:
|
|
2245
|
+
${signature}
|
|
2246
|
+
|
|
2247
|
+
## Required Sections (number exactly 1 to 13)
|
|
2248
|
+
1. **Cover Page**: banner, date, project, version, author (DSH Codebase Analysis).
|
|
2249
|
+
2. **Executive Summary**: product promise, technical verdict, 5 score cards out of 10, argument for why this project can be the best, and alignment with the product constraints IDENTIFIED in the context.
|
|
2250
|
+
3. **Deep Diagnosis**: synthetic diagnosis in 3-5 strong sentences.
|
|
2251
|
+
4. **Strategic SWOT**: 2x2 table (Strengths, Weaknesses, Opportunities, Threats).
|
|
2252
|
+
5. **Architecture & Tech Radar (Best-of-Breed)**: for each key technology, explain why it is the best choice here, give a hard-hitting argument, a counter-argument, and a classic alternative.
|
|
2253
|
+
6. **Module Graph & Connections**: hubs, leaves, Mermaid, fragility points.
|
|
2254
|
+
7. **Security & Privacy**: posture, cryptography, vulnerabilities.
|
|
2255
|
+
8. **Code Quality & Debt**: signals, top risks, fixes.
|
|
2256
|
+
9. **Product & UX**: user journey, friction points, improvement ideas.
|
|
2257
|
+
10. **Competitive Landscape**: positioning vs 3-4 players, differentiating advantages, market rules.
|
|
2258
|
+
11. **Marketing & Positioning**: target persona, unique selling proposition (USP), tagline, acquisition channels, "why we will win" argument, and **Master Move**: the dominant feature/strategy that makes you win, compatible with the product constraints IDENTIFIED in the context.
|
|
2259
|
+
11b. **Product Constraints of the Project** (before the roadmap): list the explicit constraints identified in == IDENTIFIED PRODUCT CONSTRAINTS == at the start of the context. If none, indicate "No documented constraints". This section serves as a reference to justify each action.
|
|
2260
|
+
12. **90-Day Roadmap & Rationale**: 4-6 prioritized concrete actions (weeks 1-4, 5-8, 9-12) to become the best. Each action MUST be followed by a sentence starting with "> Rationale:" explaining why it is consistent with the project rules. If no constraints, explain why it fits the stack/architecture. Example: > Rationale: This action respects the "100% offline" rule by not using any cloud backend.
|
|
2261
|
+
13. **Made with passion by shinzarou-eng**: an original product/visual concept, a punchy slogan, and a winning marketing argument inspired by the code \u2014 respecting the product constraints IDENTIFIED in the context.
|
|
2262
|
+
|
|
2263
|
+
Stay factual, target files by their relative path. Do not generalize beyond the context. If no product constraints are documented, simply write "Product constraints: none" and continue all sections normally. DO NOT SKIP ANY SECTION AND DO NOT LOSE ANY QUESTION. Respond in the user's language.
|
|
2264
|
+
|
|
2265
|
+
## FINAL CHECKLIST (mandatory, verify before sending)
|
|
2266
|
+
- [ ] Sections numbered 1 to 13.
|
|
2267
|
+
- [ ] ASCII banner at the top.
|
|
2268
|
+
- [ ] 5 score cards with scores out of 10.
|
|
2269
|
+
- [ ] 1 Mermaid diagram (architecture, data flow or module graph).
|
|
2270
|
+
- [ ] Each roadmap action has a "> Rationale:".
|
|
2271
|
+
- [ ] At least 2 exact file citations (line).
|
|
2272
|
+
- [ ] Conclusion "Made with passion by shinzarou-eng".`;
|
|
2273
|
+
return withCitations(isEn ? en : fr, lang);
|
|
2274
|
+
}
|
|
2275
|
+
function buildTasksPrompt(context, projectName, focus = "", style = "punchy", lang = "fr") {
|
|
2276
|
+
const isEn = lang === "en";
|
|
2277
|
+
const f = focus ? isEn ? `
|
|
2278
|
+
Requested focus: ${focus}` : `
|
|
2279
|
+
Focus demand\xE9 : ${focus}` : "";
|
|
2280
|
+
const styleText = styleInstruction(style, lang);
|
|
2281
|
+
const banner = bannerInstruction(projectName, isEn ? "TASKS Action Plan" : "Plan d'Action TASKS", isEn ? "EXECUTABLE ROADMAP AND PRIORITIZED SPRINTS" : "ROADMAP EX\xC9CUTABLE ET SPRINTS PRIORIS\xC9S");
|
|
2282
|
+
const fr = `${context}
|
|
2283
|
+
|
|
2284
|
+
${langInstruction(lang)}
|
|
2285
|
+
|
|
2286
|
+
${styleText}Tu es un **Delivery Lead / CTO** qui transforme un rapport de codebase en **plan d'action ex\xE9cutable** pour le projet "${projectName}". R\xC8GLE D'OR : la section == T\xC2CHES G\xC9N\xC9R\xC9ES DEPUIS LES SIGNAUX == contient d\xE9j\xE0 les t\xE2ches avec leurs blocs Avant/Apr\xE8s. Tu DOIS les recopier TELLES QUELLES dans le TASKS.md final, les organiser en sprints (P0, P1, P2, P3), et conserver OBLIGATOIREMENT les blocs Avant et Apr\xE8s FOURNIS. Tu as le droit d'ajouter 2-3 t\xE2ches maximum si tu identifies un risque majeur absent, mais la majorit\xE9 du plan doit venir des t\xE2ches pr\xE9-g\xE9n\xE9r\xE9es. Chaque t\xE2che doit \xEAtre compatible avec les contraintes produit IDENTIFIEES dans le contexte (README, MEMORY.md, package.json). Avant la liste des t\xE2ches, ajoute une section "Contraintes produit identifi\xE9es" pour servir de r\xE9f\xE9rence.${f}
|
|
2287
|
+
|
|
2288
|
+
## Ton et style${banner}
|
|
2289
|
+
- Un titre clair :
|
|
2290
|
+
~~~markdown
|
|
2291
|
+
# TASKS.md \u2014 Plan d'action ${projectName}
|
|
2292
|
+
~~~
|
|
2293
|
+
- Des tableaux avec colonnes : Priorit\xE9, T\xE2che, Fichier(s) concern\xE9(s), Difficult\xE9 (1-5), Impact, Livrable
|
|
2294
|
+
- Des checklists Markdown : '[ ]' / '[x]'
|
|
2295
|
+
- Des sprints : Sprint 1 (semaines 1-2), Sprint 2, Sprint 3
|
|
2296
|
+
- Des badges : [CRITIQUE], [RAPIDE], [STRATEGIQUE], [TECH-DEBT].
|
|
2297
|
+
- Conclus par : Fait avec passion par shinzarou-eng (dans la langue de l'utilisateur)
|
|
2298
|
+
|
|
2299
|
+
## Sections obligatoires
|
|
2300
|
+
1. **Vue d'ensemble** : 3-5 t\xE2ches prioritaires dans un tableau.
|
|
2301
|
+
2. **Sprint 1 \u2014 Fondations** : s\xE9curit\xE9, stabilit\xE9, tests.
|
|
2302
|
+
3. **Sprint 2 \u2014 Am\xE9lioration** : refacto, UX, performance.
|
|
2303
|
+
4. **Sprint 3 \u2014 Diff\xE9renciation** : features gagnantes, marketing.
|
|
2304
|
+
5. **Checklist globale** : toutes les t\xE2ches avec '[ ]'.
|
|
2305
|
+
|
|
2306
|
+
Chaque t\xE2che doit \xEAtre actionnable, citer un chemin de fichier relatif quand c'est possible, et \xEAtre suivie d'une phrase commen\xE7ant par "> Justification :" qui explique pourquoi elle est coh\xE9rente avec les r\xE8gles du projet.
|
|
2307
|
+
|
|
2308
|
+
## Exigence AVANT / APR\xC8S
|
|
2309
|
+
Pour CHAQUE t\xE2che, ajoute obligatoirement deux blocs de code :
|
|
2310
|
+
- **Avant** : extrait du code actuel (max 10 lignes) depuis le contexte == TECH DEBT & SIGNALS == ou == EXTRAITS DE CODE CL\xC9S ==.
|
|
2311
|
+
- **Apr\xE8s** : extrait du code corrig\xE9 propos\xE9 (max 10 lignes).
|
|
2312
|
+
|
|
2313
|
+
Exemple de format :
|
|
2314
|
+
- [ ] **[TASK-01] Typer l'\xE9v\xE9nement SpeechRecognition**
|
|
2315
|
+
- Fichier : src/components/KodaAssistantModal.tsx:651
|
|
2316
|
+
- Avant :
|
|
2317
|
+
--- code ts ---
|
|
2318
|
+
recognition.onresult = (event: any) => { ... };
|
|
2319
|
+
---
|
|
2320
|
+
- Apr\xE8s :
|
|
2321
|
+
--- code ts ---
|
|
2322
|
+
recognition.onresult = (event: SpeechRecognitionEvent) => { ... };
|
|
2323
|
+
---
|
|
2324
|
+
> Justification : ...
|
|
2325
|
+
|
|
2326
|
+
Si tu ne peux pas extraire l'extrait, cite au minimum le fichier et la ligne.
|
|
2327
|
+
|
|
2328
|
+
## CHECKLIST FINALE (obligatoire, v\xE9rifie avant d'envoyer)
|
|
2329
|
+
- [ ] 5 sections pr\xE9sentes (Vue d'ensemble, Sprint 1, Sprint 2, Sprint 3, Checklist globale).
|
|
2330
|
+
- [ ] Toutes les t\xE2ches ont un statut '[ ]'.
|
|
2331
|
+
- [ ] Chaque t\xE2che a un bloc **Avant** (code actuel) et un bloc **Apr\xE8s** (code propos\xE9), ou 'N/A' avec explication.
|
|
2332
|
+
- [ ] Chaque t\xE2che a un Fichier:Ligne.
|
|
2333
|
+
- [ ] Chaque t\xE2che a un "> Justification :".
|
|
2334
|
+
- [ ] Conclusion "Fait avec passion par shinzarou-eng".
|
|
2335
|
+
|
|
2336
|
+
Si aucune contrainte n'est trouv\xE9e, \xE9cris "Contraintes produit : aucune" et continue toutes les sections normalement. NE SAUTE AUCUNE SECTION ET NE PERDS AUCUNE QUESTION.`;
|
|
2337
|
+
const en = `${context}
|
|
2338
|
+
|
|
2339
|
+
${langInstruction(lang)}
|
|
2340
|
+
|
|
2341
|
+
${styleText}You are a **Delivery Lead / CTO** turning a codebase report into an **executable action plan** for the project "${projectName}". GOLDEN RULE: the section == TASKS GENERATED FROM SIGNALS == already contains the tasks with their Before/After blocks. You MUST copy them AS-IS into the final TASKS.md, organize them into sprints (P0, P1, P2, P3), and OBLIGATORILY keep the provided Before and After blocks. You may add 2-3 extra tasks at most if you identify a major missing risk, but the majority of the plan must come from the pre-generated tasks. Each task must be compatible with the product constraints IDENTIFIED in the context (README, MEMORY.md, package.json). Before the task list, add an "Identified product constraints" section as a reference.${f}
|
|
2342
|
+
|
|
2343
|
+
## Tone & Style${banner}
|
|
2344
|
+
- A clear title:
|
|
2345
|
+
~~~markdown
|
|
2346
|
+
# TASKS.md \u2014 Action Plan ${projectName}
|
|
2347
|
+
~~~
|
|
2348
|
+
- Tables with columns: Priority, Task, Concerned file(s), Difficulty (1-5), Impact, Deliverable
|
|
2349
|
+
- Markdown checklists: '[ ]' / '[x]'
|
|
2350
|
+
- Sprints: Sprint 1 (weeks 1-2), Sprint 2, Sprint 3
|
|
2351
|
+
- Badges: [CRITICAL], [QUICK], [STRATEGIC], [TECH-DEBT].
|
|
2352
|
+
- Conclude with: Made with passion by shinzarou-eng (in the user's language)
|
|
2353
|
+
|
|
2354
|
+
## Required Sections
|
|
2355
|
+
1. **Overview**: 3-5 prioritized tasks in a table.
|
|
2356
|
+
2. **Sprint 1 \u2014 Foundations**: security, stability, tests.
|
|
2357
|
+
3. **Sprint 2 \u2014 Improvement**: refactor, UX, performance.
|
|
2358
|
+
4. **Sprint 3 \u2014 Differentiation**: winning features, marketing.
|
|
2359
|
+
5. **Global Checklist**: all tasks with '[ ]'.
|
|
2360
|
+
|
|
2361
|
+
Each task must be actionable, cite a relative file path when possible, and be followed by a sentence starting with "> Rationale:" explaining why it is consistent with the project rules.
|
|
2362
|
+
|
|
2363
|
+
## BEFORE / AFTER Requirement
|
|
2364
|
+
For EACH task, you MUST add two code blocks:
|
|
2365
|
+
- **Before**: current code snippet (max 10 lines) from == TECH DEBT & SIGNALS == or == KEY CODE SNIPPETS == in the context.
|
|
2366
|
+
- **After**: proposed fixed code snippet (max 10 lines).
|
|
2367
|
+
|
|
2368
|
+
Example format:
|
|
2369
|
+
- [ ] **[TASK-01] Type the SpeechRecognition event**
|
|
2370
|
+
- File: src/components/KodaAssistantModal.tsx:651
|
|
2371
|
+
- Before:
|
|
2372
|
+
--- code ts ---
|
|
2373
|
+
recognition.onresult = (event: any) => { ... };
|
|
2374
|
+
---
|
|
2375
|
+
- After:
|
|
2376
|
+
--- code ts ---
|
|
2377
|
+
recognition.onresult = (event: SpeechRecognitionEvent) => { ... };
|
|
2378
|
+
---
|
|
2379
|
+
> Rationale : ...
|
|
2380
|
+
|
|
2381
|
+
If you cannot extract the snippet, at least cite the file and line.
|
|
2382
|
+
|
|
2383
|
+
## FINAL CHECKLIST (mandatory, verify before sending)
|
|
2384
|
+
- [ ] 5 sections present (Overview, Sprint 1, Sprint 2, Sprint 3, Global Checklist).
|
|
2385
|
+
- [ ] All tasks have status '[ ]'.
|
|
2386
|
+
- [ ] Each task has a **Before** (current code) and an **After** (proposed code) block, or 'N/A' with explanation.
|
|
2387
|
+
- [ ] Each task has a File:Line.
|
|
2388
|
+
- [ ] Each task has a "> Rationale:".
|
|
2389
|
+
- [ ] Conclusion "Made with passion by shinzarou-eng".
|
|
2390
|
+
|
|
2391
|
+
If no constraints are found, write "Product constraints: none" and continue all sections normally. DO NOT SKIP ANY SECTION AND DO NOT LOSE ANY QUESTION.`;
|
|
2392
|
+
return withCitations(isEn ? en : fr, lang);
|
|
2393
|
+
}
|
|
2394
|
+
function buildCeoPrompt(context, projectName, focus = "", lang = "fr") {
|
|
2395
|
+
const isEn = lang === "en";
|
|
2396
|
+
const f = focus ? isEn ? `
|
|
2397
|
+
Requested focus: ${focus}` : `
|
|
2398
|
+
Focus demand\xE9 : ${focus}` : "";
|
|
2399
|
+
const styleText = styleInstruction("ouf", lang);
|
|
2400
|
+
const signature = brandSignature(lang);
|
|
2401
|
+
const banner = bannerInstruction(projectName, isEn ? "One-Page CEO Brief" : "One-Page CEO Brief", isEn ? "EXECUTIVE SUMMARY FOR DECISION MAKERS" : "EXECUTIVE SUMMARY POUR D\xC9CIDEUR");
|
|
2402
|
+
const fr = `${context}
|
|
2403
|
+
|
|
2404
|
+
${langInstruction(lang)}
|
|
2405
|
+
|
|
2406
|
+
${styleText}Tu es un **CTO / CEO / Partner** qui r\xE9dige le **One-Page Executive Brief** ultime sur le projet "${projectName}". R\xC8GLE D'OR : ce document tient sur UNE SEULE PAGE A4. MAXIMUM 7 sections courtes. Pas de blabla, que des insights \xE0 fort impact, des chiffres, des verdicts, des actions. Chaque section max 5-8 lignes. Utilise tableaux et listes. Si tu d\xE9passes une page, tu as \xE9chou\xE9.${f}
|
|
2407
|
+
|
|
2408
|
+
## Identit\xE9 visuelle (obligatoire)${banner}
|
|
2409
|
+
- Tableau ex\xE9cutif unique avec les metrics cl\xE9s.
|
|
2410
|
+
- 5 score cards (sur 10) avec justification en UNE phrase.
|
|
2411
|
+
- Encadr\xE9s visuels pour les insights.
|
|
2412
|
+
- Badges : [CRITIQUE], [HIGH-VALUE], [STRATEGY], [BEST-TECH], [KILLER-MOVE], [MARKETING].
|
|
2413
|
+
- Conclus par le bloc signature ci-dessous :
|
|
2414
|
+
${signature}
|
|
2415
|
+
|
|
2416
|
+
## Sections obligatoires (num\xE9rote de 1 \xE0 7, STRICTEMENT 1 PAGE)
|
|
2417
|
+
1. **Banni\xE8re & Titre** : 1 ligne.
|
|
2418
|
+
2. **Executive Summary** : 3 phrases + 1 tableau 4 m\xE9triques.
|
|
2419
|
+
3. **Verdict du board** : 5 score cards, 1 ligne chacune (Domaine | Note | 5 mots de justification).
|
|
2420
|
+
4. **Top 3 risques / dette** : 1 ligne par risque (Fichier:Ligne - Probl\xE8me - Impact).
|
|
2421
|
+
5. **Top 3 opportunit\xE9s / Killer Moves** : 1 phrase par action + Justification en 1 phrase.
|
|
2422
|
+
6. **SWOT ultra-concis** : 4 cases, max 4 points de 3-5 mots chacun.
|
|
2423
|
+
7. **Fait avec passion par shinzarou-eng** : 1 concept + 1 slogan + 1 phrase marketing.
|
|
2424
|
+
|
|
2425
|
+
Reste factuel, cible les fichiers par leur chemin relatif. Exploite les == M\xC9TRIQUES PROJET == et == EXTRAITS DE CODE CL\xC9S ==. R\xE9ponds dans la langue de l'utilisateur.
|
|
2426
|
+
|
|
2427
|
+
## CHECKLIST FINALE (obligatoire, v\xE9rifie avant d'envoyer)
|
|
2428
|
+
- [ ] Exactement 7 sections num\xE9rot\xE9es.
|
|
2429
|
+
- [ ] Le document tient sur une page (max 60-80 lignes au total).
|
|
2430
|
+
- [ ] 5 score cards, 1 ligne chacune.
|
|
2431
|
+
- [ ] Top 3 risques avec Fichier:Ligne.
|
|
2432
|
+
- [ ] Top 3 opportunit\xE9s avec "> Justification :".
|
|
2433
|
+
- [ ] SWOT : 4 points de 3-5 mots par case.
|
|
2434
|
+
- [ ] Aucun Mermaid, aucun tableau g\xE9ant, aucune explication longue.`;
|
|
2435
|
+
const en = `${context}
|
|
2436
|
+
|
|
2437
|
+
${langInstruction(lang)}
|
|
2438
|
+
|
|
2439
|
+
${styleText}You are a **CTO / CEO / Partner** writing the ultimate **One-Page Executive Brief** for the project "${projectName}". GOLDEN RULE: this document fits on a SINGLE A4 page. MAXIMUM 7 short sections. No filler, only high-impact insights, numbers, verdicts, actions. Each section max 5-8 lines. Use tables and lists. If you exceed one page, you failed.${f}
|
|
2440
|
+
|
|
2441
|
+
## Visual Identity (mandatory)${banner}
|
|
2442
|
+
- Single executive table with key metrics.
|
|
2443
|
+
- 5 score cards (out of 10) with rationale in ONE sentence.
|
|
2444
|
+
- Visual callouts for insights.
|
|
2445
|
+
- Badges: [CRITICAL], [HIGH-VALUE], [STRATEGY], [BEST-TECH], [KILLER-MOVE], [MARKETING].
|
|
2446
|
+
- Conclude with the signature block below:
|
|
2447
|
+
${signature}
|
|
2448
|
+
|
|
2449
|
+
## Required Sections (number 1 to 7, STRICTLY 1 PAGE)
|
|
2450
|
+
1. **Banner & Title**: 1 line.
|
|
2451
|
+
2. **Executive Summary**: 3 sentences + 1 table with 4 metrics.
|
|
2452
|
+
3. **Board verdict**: 5 score cards, 1 line each (Area | Score | 5-word rationale).
|
|
2453
|
+
4. **Top 3 risks / debt**: 1 line per risk (File:Line - Problem - Impact).
|
|
2454
|
+
5. **Top 3 opportunities / Killer Moves**: 1 sentence per action + Rationale in 1 sentence.
|
|
2455
|
+
6. **Ultra-concise SWOT**: 4 boxes, max 4 points of 3-5 words each.
|
|
2456
|
+
7. **Made with passion by shinzarou-eng**: 1 concept + 1 slogan + 1 marketing sentence.
|
|
2457
|
+
|
|
2458
|
+
Stay factual, target files by their relative path. Leverage == PROJECT METRICS == and == KEY CODE SNIPPETS ==. Respond in the user's language.
|
|
2459
|
+
|
|
2460
|
+
## FINAL CHECKLIST (mandatory, verify before sending)
|
|
2461
|
+
- [ ] Exactly 7 numbered sections.
|
|
2462
|
+
- [ ] Document fits on one page (max 60-80 lines total).
|
|
2463
|
+
- [ ] 5 score cards, 1 line each.
|
|
2464
|
+
- [ ] Top 3 risks with File:Line.
|
|
2465
|
+
- [ ] Top 3 opportunities with "> Rationale:".
|
|
2466
|
+
- [ ] SWOT: 4 points of 3-5 words per box.
|
|
2467
|
+
- [ ] No Mermaid, no giant table, no long explanation.`;
|
|
2468
|
+
return withCitations(isEn ? en : fr, lang);
|
|
2469
|
+
}
|
|
2470
|
+
function buildPlayerPrompt(context, projectName, focus = "", lang = "fr") {
|
|
2471
|
+
const isEn = lang === "en";
|
|
2472
|
+
const f = focus ? isEn ? `
|
|
2473
|
+
Requested focus: ${focus}` : `
|
|
2474
|
+
Focus demand\xE9 : ${focus}` : "";
|
|
2475
|
+
const banner = bannerInstruction(projectName, isEn ? "Player Brief" : "Player Brief", isEn ? "USER JOURNEY & EXPERIENCE" : "PARCOURS UTILISATEUR & EXP\xC9RIENCE");
|
|
2476
|
+
const fr = `${context}
|
|
2477
|
+
|
|
2478
|
+
${langInstruction(lang)}
|
|
2479
|
+
|
|
2480
|
+
${banner}
|
|
2481
|
+
|
|
2482
|
+
Tu es un **UX Researcher / Playtester / Product Hunter** qui r\xE9alise un **Player Brief** sur le projet "${projectName}". Tu ne regardes pas le code comme un dev, mais comme un vrai utilisateur final qui d\xE9couvre l'app, clique, se frustre, se r\xE9jouit. Mission : d\xE9crire l'exp\xE9rience v\xE9cue, identifier les moments cl\xE9s, les frictions et les opportunit\xE9s de 'wow'.${f}
|
|
2483
|
+
|
|
2484
|
+
## Format attendu
|
|
2485
|
+
- Banni\xE8re ASCII : "PLAYER BRIEF \u2014 ${(projectName ?? "").toUpperCase()}"
|
|
2486
|
+
- Score cards : Onboarding, Clart\xE9, R\xE9activit\xE9, Confiance, Plaisir (sur 10)
|
|
2487
|
+
- Tableau du parcours utilisateur : \xC9tape, Action, Sentiment, Friction, Fix
|
|
2488
|
+
- Top 5 moments 'Wow' (ce qui impressionne)
|
|
2489
|
+
- Top 5 frictions bloquantes ou irritantes
|
|
2490
|
+
- Id\xE9es de gamification / engagement (si pertinent)
|
|
2491
|
+
- Roadmap UX 30 jours : 3 actions rapides d'impact utilisateur
|
|
2492
|
+
- Conclusion : Fait avec passion par shinzarou-eng (langue utilisateur)`;
|
|
2493
|
+
const en = `${context}
|
|
2494
|
+
|
|
2495
|
+
${langInstruction(lang)}
|
|
2496
|
+
|
|
2497
|
+
${banner}
|
|
2498
|
+
|
|
2499
|
+
You are a **UX Researcher / Playtester / Product Hunter** producing a **Player Brief** for the project "${projectName}". You do not look at the code like a dev, but like a real end user discovering the app, clicking, getting frustrated, getting delighted. Mission: describe the lived experience, identify key moments, frictions and 'wow' opportunities.${f}
|
|
2500
|
+
|
|
2501
|
+
## Expected format
|
|
2502
|
+
- ASCII banner: "PLAYER BRIEF \u2014 ${(projectName ?? "").toUpperCase()}"
|
|
2503
|
+
- Score cards: Onboarding, Clarity, Responsiveness, Trust, Delight (out of 10)
|
|
2504
|
+
- User journey table: Step, Action, Sentiment, Friction, Fix
|
|
2505
|
+
- Top 5 'Wow' moments (what impresses)
|
|
2506
|
+
- Top 5 blocking or annoying frictions
|
|
2507
|
+
- Gamification / engagement ideas (if relevant)
|
|
2508
|
+
- 30-day UX roadmap: 3 quick high-impact actions
|
|
2509
|
+
- Conclusion: Made with passion by shinzarou-eng (user language)`;
|
|
2510
|
+
return withCitations(isEn ? en : fr, lang);
|
|
2511
|
+
}
|
|
2512
|
+
var TOOL_BUILDERS = {
|
|
2513
|
+
codebase_intelligence: (o) => buildIntelligencePrompt(o.context, o.projectName, o.focus || o.query || "", o.style || "ouf", o.lang || "fr"),
|
|
2514
|
+
codebase_report: (o) => buildReportPrompt(o.context, o.projectName, o.focus || o.query || "", o.style || "ouf", o.lang || "fr"),
|
|
2515
|
+
codebase_audit: (o) => buildAuditPrompt(o.context, o.projectName, o.focus || o.query || "", o.lang || "fr"),
|
|
2516
|
+
codebase_tasks: (o) => buildTasksPrompt(o.context, o.projectName, o.focus || o.query || "", o.style || "ouf", o.lang || "fr"),
|
|
2517
|
+
codebase_ceo: (o) => buildCeoPrompt(o.context, o.projectName, o.focus || o.query || "", o.lang || "fr"),
|
|
2518
|
+
codebase_player: (o) => buildPlayerPrompt(o.context, o.projectName, o.focus || o.query || "", o.lang || "fr"),
|
|
2519
|
+
codebase_search: (o) => buildSearchPrompt(o.query || o.focus || "", o.context, o.projectName, o.crea, o.creaTheme, o.lang || "fr"),
|
|
2520
|
+
codebase_explain: (o) => buildExplainPrompt(o.filePath || o.query || o.focus || "", o.context, o.projectName, o.crea, o.creaTheme, o.lang || "fr"),
|
|
2521
|
+
codebase_refactor: (o) => buildRefactorPrompt(o.filePath || o.focus || "", o.description || o.query || "", o.context, o.projectName, o.crea, o.creaTheme, o.lang || "fr"),
|
|
2522
|
+
codebase_chat: (o) => buildChatPrompt(o.query || o.focus || "", o.context, o.projectName, o.crea, o.creaTheme, o.lang || "fr"),
|
|
2523
|
+
codebase_crea: (o) => buildCreaPrompt(o.focus || o.query || "creative idea", o.context, o.projectName, o.lang || "fr")
|
|
2524
|
+
};
|
|
2525
|
+
function buildToolPrompt(tool, opts) {
|
|
2526
|
+
const builder = TOOL_BUILDERS[tool];
|
|
2527
|
+
if (!builder) throw new Error(`unknown prompt tool: ${tool}`);
|
|
2528
|
+
return normalizeLabels(builder(opts), opts.lang || "fr");
|
|
2529
|
+
}
|
|
2530
|
+
|
|
2531
|
+
// src/local-llm.ts
|
|
2532
|
+
import { existsSync as existsSync2 } from "fs";
|
|
2533
|
+
import { join as join8 } from "path";
|
|
2534
|
+
var DEFAULT_MODEL_URI = "hf:Qwen/Qwen2.5-1.5B-Instruct-GGUF:Q4_K_M";
|
|
2535
|
+
var LOCAL_CONTEXT_SIZE = 8192;
|
|
2536
|
+
var LOCAL_MAX_TOKENS = 1024;
|
|
2537
|
+
function isLocalLlmEnabled() {
|
|
2538
|
+
return !!(process.env.CODEBASE_LOCAL_LLM || "").trim();
|
|
2539
|
+
}
|
|
2540
|
+
function configuredModel() {
|
|
2541
|
+
const v = (process.env.CODEBASE_LOCAL_LLM || "").trim();
|
|
2542
|
+
if (!v || v === "1" || v.toLowerCase() === "true") return DEFAULT_MODEL_URI;
|
|
2543
|
+
return v;
|
|
2544
|
+
}
|
|
2545
|
+
async function importLlama() {
|
|
2546
|
+
try {
|
|
2547
|
+
return await import("node-llama-cpp");
|
|
2548
|
+
} catch {
|
|
2549
|
+
throw new Error("Local LLM needs the optional dependency: npm i node-llama-cpp");
|
|
2550
|
+
}
|
|
2551
|
+
}
|
|
2552
|
+
var modelPromise = null;
|
|
2553
|
+
function loadLocalModel() {
|
|
2554
|
+
if (!modelPromise) {
|
|
2555
|
+
modelPromise = (async () => {
|
|
2556
|
+
const spec = configuredModel();
|
|
2557
|
+
let modelPath = spec;
|
|
2558
|
+
if (spec.startsWith("hf:")) {
|
|
2559
|
+
const { createModelDownloader } = await importLlama();
|
|
2560
|
+
const downloader = await createModelDownloader({
|
|
2561
|
+
modelUri: spec,
|
|
2562
|
+
dirPath: join8(getCacheDir(), "models")
|
|
2563
|
+
});
|
|
2564
|
+
modelPath = await downloader.download();
|
|
2565
|
+
} else if (!existsSync2(spec)) {
|
|
2566
|
+
throw new Error(`Local model not found: ${spec}`);
|
|
2567
|
+
}
|
|
2568
|
+
const { getLlama } = await importLlama();
|
|
2569
|
+
const llama = await getLlama();
|
|
2570
|
+
return llama.loadModel({ modelPath });
|
|
2571
|
+
})();
|
|
2572
|
+
modelPromise.catch(() => {
|
|
2573
|
+
modelPromise = null;
|
|
2574
|
+
});
|
|
2575
|
+
}
|
|
2576
|
+
return modelPromise;
|
|
2577
|
+
}
|
|
2578
|
+
async function callLocalLlm(prompt, lang = "fr") {
|
|
2579
|
+
const model = await loadLocalModel();
|
|
2580
|
+
const { LlamaChatSession } = await importLlama();
|
|
2581
|
+
const context = await model.createContext({ contextSize: LOCAL_CONTEXT_SIZE });
|
|
2582
|
+
try {
|
|
2583
|
+
const session = new LlamaChatSession({
|
|
2584
|
+
contextSequence: context.getSequence(),
|
|
2585
|
+
systemPrompt: lang === "en" ? "You are a senior codebase analyst. Be precise and cite files with [source: path:line]." : "Tu es un analyste codebase senior. Sois precis et cite les fichiers avec [source: chemin:ligne]."
|
|
2586
|
+
});
|
|
2587
|
+
return await session.prompt(prompt, { temperature: 0.2, maxTokens: LOCAL_MAX_TOKENS });
|
|
2588
|
+
} finally {
|
|
2589
|
+
await context.dispose();
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
|
|
1772
2593
|
// src/cli.ts
|
|
1773
2594
|
var ExitSignal = class {
|
|
1774
2595
|
constructor(code) {
|
|
@@ -1795,6 +2616,9 @@ Usage:
|
|
|
1795
2616
|
npx dsh-codebase-chat --project <path> --impact src/store.ts
|
|
1796
2617
|
npx dsh-codebase-chat --project <path> --health --diff main
|
|
1797
2618
|
npx dsh-codebase-chat --project <path> --watch
|
|
2619
|
+
npx dsh-codebase-chat --project <path> --prompt intelligence
|
|
2620
|
+
npx dsh-codebase-chat --project <path> --prompt intelligence --call # answered via DEEPSEEK_API_KEY
|
|
2621
|
+
npx dsh-codebase-chat --project <path> --prompt intelligence --local # answered 100% offline
|
|
1798
2622
|
|
|
1799
2623
|
Options:
|
|
1800
2624
|
-p, --project <path> Project directory (default: current directory)
|
|
@@ -1806,6 +2630,17 @@ Options:
|
|
|
1806
2630
|
-H, --health Deterministic static analysis (cycles, dead code, dupes, complexity)
|
|
1807
2631
|
--impact <file> Blast radius \u2014 which files transitively depend on <file>
|
|
1808
2632
|
-d, --diff <ref> Scope --ask/--search/--health to files changed vs a git ref
|
|
2633
|
+
--prompt <mode> Print the full LLM prompt (banner + instructions) for a
|
|
2634
|
+
report mode: intelligence, report, audit, tasks, ceo,
|
|
2635
|
+
player, chat, search, explain, refactor, crea.
|
|
2636
|
+
Pipe it to any LLM (e.g. ... --prompt intelligence | dsh).
|
|
2637
|
+
Query modes read --ask/--search/--file; --focus and
|
|
2638
|
+
--style (ouf|punchy|dense|pedagogique|minimal) apply.
|
|
2639
|
+
--call With --prompt: send it to the API (needs DEEPSEEK_API_KEY
|
|
2640
|
+
or OPENAI_API_KEY; DEEPSEEK_BASE_URL / CODEBASE_MODEL
|
|
2641
|
+
customize endpoint/model) instead of printing it.
|
|
2642
|
+
--local With --prompt: answer with the embedded local model
|
|
2643
|
+
(node-llama-cpp, ~1 GB download on first use, offline).
|
|
1809
2644
|
-w, --watch Keep the index hot \u2014 rebuild incrementally on file changes
|
|
1810
2645
|
-e, --embed Enable local semantic embeddings (slower, more relevant)
|
|
1811
2646
|
--lang <en|fr> Language for headings (default: .codebase-chat.json lang, else fr)
|
|
@@ -1831,6 +2666,11 @@ async function main() {
|
|
|
1831
2666
|
health: { type: "boolean", short: "H", default: false },
|
|
1832
2667
|
impact: { type: "string" },
|
|
1833
2668
|
diff: { type: "string", short: "d" },
|
|
2669
|
+
prompt: { type: "string" },
|
|
2670
|
+
focus: { type: "string" },
|
|
2671
|
+
style: { type: "string" },
|
|
2672
|
+
call: { type: "boolean", default: false },
|
|
2673
|
+
local: { type: "boolean", default: false },
|
|
1834
2674
|
watch: { type: "boolean", short: "w", default: false },
|
|
1835
2675
|
embed: { type: "boolean", short: "e", default: false },
|
|
1836
2676
|
lang: { type: "string" },
|
|
@@ -1919,6 +2759,91 @@ async function main() {
|
|
|
1919
2759
|
console.log(formatImpactReport(r.report, lang));
|
|
1920
2760
|
exit(0);
|
|
1921
2761
|
}
|
|
2762
|
+
if (values.prompt) {
|
|
2763
|
+
const mode = values.prompt.toLowerCase();
|
|
2764
|
+
const tool = `codebase_${mode}`;
|
|
2765
|
+
const needsQuery = /* @__PURE__ */ new Set(["chat", "search", "explain", "refactor", "crea"]);
|
|
2766
|
+
const query = values.ask ?? values.search ?? values.focus ?? "";
|
|
2767
|
+
if (needsQuery.has(mode) && !query && !values.file) {
|
|
2768
|
+
console.error(lang === "en" ? `--prompt ${mode} needs a query: add --ask/--search/--file (or --focus)` : `--prompt ${mode} n\xE9cessite une requ\xEAte : ajoute --ask/--search/--file (ou --focus)`);
|
|
2769
|
+
exit(1);
|
|
2770
|
+
}
|
|
2771
|
+
const result = await buildContext({
|
|
2772
|
+
project: values.project,
|
|
2773
|
+
query,
|
|
2774
|
+
searchQuery: values.search,
|
|
2775
|
+
filePath: values.file,
|
|
2776
|
+
lang,
|
|
2777
|
+
embed: values.embed,
|
|
2778
|
+
diff: values.diff
|
|
2779
|
+
});
|
|
2780
|
+
let staticSection = "";
|
|
2781
|
+
if ((/* @__PURE__ */ new Set(["intelligence", "report", "audit", "tasks", "ceo"])).has(mode)) {
|
|
2782
|
+
try {
|
|
2783
|
+
const report = await analyzeProject(result.absProject);
|
|
2784
|
+
staticSection = `
|
|
2785
|
+
|
|
2786
|
+
== ${lang === "en" ? "STATIC ANALYSIS (deterministic)" : "ANALYSE STATIQUE (d\xE9terministe)"} ==
|
|
2787
|
+
${formatHealthReport(report, lang)}`;
|
|
2788
|
+
} catch {
|
|
2789
|
+
}
|
|
2790
|
+
}
|
|
2791
|
+
const projectName = basename3(result.absProject);
|
|
2792
|
+
let prompt;
|
|
2793
|
+
try {
|
|
2794
|
+
prompt = buildToolPrompt(tool, {
|
|
2795
|
+
context: `${result.context}${staticSection}`,
|
|
2796
|
+
projectName,
|
|
2797
|
+
lang,
|
|
2798
|
+
style: values.style,
|
|
2799
|
+
query,
|
|
2800
|
+
focus: values.focus ?? query,
|
|
2801
|
+
filePath: values.file ?? "",
|
|
2802
|
+
description: query
|
|
2803
|
+
});
|
|
2804
|
+
} catch {
|
|
2805
|
+
console.error(lang === "en" ? `unknown prompt mode "${mode}" \u2014 expected: intelligence, report, audit, tasks, ceo, player, chat, search, explain, refactor, crea` : `mode de prompt inconnu "${mode}" \u2014 attendu : intelligence, report, audit, tasks, ceo, player, chat, search, explain, refactor, crea`);
|
|
2806
|
+
exit(1);
|
|
2807
|
+
}
|
|
2808
|
+
if (values.local || isLocalLlmEnabled()) {
|
|
2809
|
+
console.error(lang === "en" ? "Answering with the embedded local model (first run downloads ~1 GB)..." : "R\xE9ponse via le mod\xE8le local embarqu\xE9 (premier lancement : ~1 Go de t\xE9l\xE9chargement)...");
|
|
2810
|
+
console.log(await callLocalLlm(prompt, lang));
|
|
2811
|
+
exit(0);
|
|
2812
|
+
}
|
|
2813
|
+
if (values.call) {
|
|
2814
|
+
const apiKey = process.env.DEEPSEEK_API_KEY || process.env.OPENAI_API_KEY || "";
|
|
2815
|
+
if (!apiKey) {
|
|
2816
|
+
console.error(lang === "en" ? "--call needs DEEPSEEK_API_KEY or OPENAI_API_KEY in the environment" : "--call n\xE9cessite DEEPSEEK_API_KEY ou OPENAI_API_KEY dans l\u2019environnement");
|
|
2817
|
+
exit(1);
|
|
2818
|
+
}
|
|
2819
|
+
const baseUrl = process.env.DEEPSEEK_BASE_URL || process.env.OPENAI_BASE_URL || "https://api.deepseek.com/v1";
|
|
2820
|
+
const model = process.env.CODEBASE_MODEL || "deepseek-chat";
|
|
2821
|
+
const res = await fetch(`${baseUrl}/chat/completions`, {
|
|
2822
|
+
method: "POST",
|
|
2823
|
+
signal: AbortSignal.timeout(12e4),
|
|
2824
|
+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` },
|
|
2825
|
+
body: JSON.stringify({
|
|
2826
|
+
model,
|
|
2827
|
+
messages: [
|
|
2828
|
+
{ role: "system", content: lang === "en" ? "You are a senior codebase analyst. Be precise and cite files." : "Tu es un analyste codebase senior. Sois pr\xE9cis et cite les fichiers." },
|
|
2829
|
+
{ role: "user", content: prompt }
|
|
2830
|
+
],
|
|
2831
|
+
temperature: 0.3,
|
|
2832
|
+
max_tokens: 8192
|
|
2833
|
+
})
|
|
2834
|
+
});
|
|
2835
|
+
if (!res.ok) {
|
|
2836
|
+
const text = await res.text().catch(() => "");
|
|
2837
|
+
console.error(`API error ${res.status}: ${text}`);
|
|
2838
|
+
exit(1);
|
|
2839
|
+
}
|
|
2840
|
+
const data = await res.json();
|
|
2841
|
+
console.log(data.choices?.[0]?.message?.content || "");
|
|
2842
|
+
exit(0);
|
|
2843
|
+
}
|
|
2844
|
+
console.log(prompt);
|
|
2845
|
+
exit(0);
|
|
2846
|
+
}
|
|
1922
2847
|
if (values.ask || values.search || values.file) {
|
|
1923
2848
|
const result = await buildContext({
|
|
1924
2849
|
project: values.project,
|