diff --git a/.DS_Store b/.DS_Store index 5008ddf..433fa90 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/main.js b/main.js index f41e7ad..1a0f530 100644 --- a/main.js +++ b/main.js @@ -1,5 +1,5 @@ // Loading required packages -require("./requires.js") +require("./requires.js"); console.log(start); const https = require("https"); @@ -55,30 +55,33 @@ req.end(); // Initialising map to be used to store the functionality later on for reloadability -mapFunctions = new Map() - +mapFunctions = new Map(); // Loading the Function Map -var path = `${mainDir}/services/modules` +var path = `${mainDir}/services/modules`; var folders = fs.readdirSync(path).filter(function (file) { - return fs.statSync(path+'/'+file).isDirectory(); + return fs.statSync(path + "/" + file).isDirectory(); }); -folders.forEach(element => { - var commandFiles = fs.readdirSync(`${path}/${element}`).filter(file => file.endsWith('.js') && !file.startsWith("index")); - for (const file of commandFiles) { - delete require.cache[require.resolve(`${path}/${element}/${file}`)]; - const command = require(`${path}/${element}/${file}`); - mapFunctions.set(command.name, command); - } +folders.forEach((element) => { + var commandFiles = fs + .readdirSync(`${path}/${element}`) + .filter((file) => file.endsWith(".js") && !file.startsWith("index")); + for (const file of commandFiles) { + delete require.cache[require.resolve(`${path}/${element}/${file}`)]; + const command = require(`${path}/${element}/${file}`); + mapFunctions.set(command.name, command); + } }); // The startup information for the project, here you can add stuff that might be nice to see when the app starts -mapFunctions.get("Startup_function").function() -console.log("------------------------------------ Status ------------------------------------"); +mapFunctions.get("Startup_function").function(); +console.log( + "------------------------------------ Status ------------------------------------" +); console.log(__dirname); console.log(platform); -console.log(`The Startup took ${new Date() - start}ms`) +console.log(`The Startup took ${new Date() - start}ms`); console.log(`${mapFunctions.size} Function modules loaded`); console.log("--------------------------------------------------------------------------------"); @@ -87,17 +90,17 @@ console.log("------------------------------------------------------------------- let mainWindow; function createWindow() { - mainWindow = new electron.BrowserWindow({ - width: 1200, - height: 800, - webPreferences: { - nodeIntegration: false, - contextIsolation: true, - preload: `${mainDir}/electron/main/preload.js` - } - }); + mainWindow = new electron.BrowserWindow({ + width: 1200, + height: 800, + webPreferences: { + nodeIntegration: false, + contextIsolation: true, + preload: `${mainDir}/electron/main/preload.js`, + }, + }); - mainWindow.loadFile('./electron/main/index.html'); + mainWindow.loadFile("./electron/main/index.html"); } electron.app.whenReady().then(createWindow); @@ -107,21 +110,11 @@ electron.ipcMain.handle('get-module-names', async () => { "ai_modules":[], "transcription_modules":[] } - mapFunctions.forEach(e => { - switch(e.type){ - case "llm": - module_array.ai_modules.push({"name": e.name, "displayname": e.displayname}) - break; - case "transcription": - module_array.transcription_modules.push({"name": e.name, "displayname": e.displayname}) - break; - } - }) - // console.log(module_array); - return module_array + }); + // console.log(module_array); + return module_array; }); - // electron.ipcMain.on("get_modules", async (event, args) => { // let module_array = { // "ai_modules":[], @@ -142,130 +135,183 @@ electron.ipcMain.handle('get-module-names', async () => { // mainWindow.webContents.send("modules", module_array) // }) -var globalArgs = {} -var globalFinalHtmlPath = "" +var globalArgs = {}; +var globalFinalHtmlPath = ""; electron.ipcMain.on("file_submit", async (event, args) => { - try { - globalArgs = args - let curstep = 0 - let totalsteps = 4 + try { + globalArgs = args; + let curstep = 0; + let totalsteps = 4; - const TEMPLATE_MAP = { - "followup-report": "followup_report.txt", - "agenda": "agenda.txt", - "result-protocol": "result_protocol.txt", - "sprint-planning": "sprint_planning_note.txt", - "custom": "custom_document.txt" - }; + const TEMPLATE_MAP = { + "followup-report": "followup_report.txt", + agenda: "agenda.txt", + "result-protocol": "result_protocol.txt", + "sprint-planning": "sprint_planning_note.txt", + custom: "custom_document.txt", + }; - const templateFile = TEMPLATE_MAP[args.document.type]; + const templateFile = TEMPLATE_MAP[args.document.type]; - if (!templateFile) { - throw new Error("Unknown document type: " + args.document.type); - } - - console.log(args); - let audiopath = "" - let transcriptpath = "" - - console.log("\n\n Running the Video to Audio Extractor"); - // This code handles the Video to Audio extraction module call - await mapFunctions.get("module-handler").function(args.video.module, {inputVideoPath: args.video.inputVideoPath, outputType: mapFunctions.get(args.transcription.module).audioformat}).then(resp => { - console.log(resp); - audiopath = resp - curstep++ - mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps}) - }).catch(err => { - mainWindow.webContents.send("error", err) - console.log(err); - return - }) - - - console.log("\n\n Running the Audio to Transcription module"); - // TODO implement transcription module - // This code handles the Audio to Text transcription module call - await mapFunctions.get("module-handler").function(args.transcription.module, audiopath).then(resp => { - console.log(resp); - transcriptpath = resp - curstep++ - mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps}) - }).catch(err => { - mainWindow.webContents.send("error", err) - console.log(err); - return - }) - - - console.log("\n\n Running the Transcription Summarizer module"); - // This code summarises the transcript, so that it can be used by an llm - // await mapFunctions.get("summarize-transcription").function('A:\\programing\\@projects\\video2document\\storage\\transcripts\\IMG_2978.json').then(resp => { - await mapFunctions.get("summarize-transcription2").function(transcriptpath).then(resp => { - console.log(resp); - transcriptpath = resp - curstep++ - mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps}) - }).catch(err => { - mainWindow.webContents.send("error", err) - console.log(err); - return - }) - - console.log("\n\n Running the LLM module"); - // TODO implement documentation module - // This code handles the Text to Document processing module call - - console.log(`\n\n Running the LLM for Document Style ${args.document.type}`); - - await mapFunctions.get("module-handler").function(args.document.module, { inputTranscriptPath: transcriptpath, documentTypePath: "./storage/documentType/" + templateFile, language: "en" }).then(resp => { - console.log(resp); - globalFinalHtmlPath = resp - curstep++ - mainWindow.webContents.send("progress", {curstep:curstep, totalsteps:totalsteps}) - }).catch(err => { - mainWindow.webContents.send("error", err) - console.log(err); - return - }) - - - await mapFunctions.get("extract-speaker-snippets").function({audioPath: audiopath, jsonPath: transcriptpath }).then(resp => { - mainWindow.webContents.send("speakerAudios", resp) - }).catch(err => { - mainWindow.webContents.send("error", err) - console.log(err); - return - }) - } catch (error) { - console.log(error); + if (!templateFile) { + throw new Error("Unknown document type: " + args.document.type); } -}) -electron.ipcMain.on("file_download", async() => { - await mapFunctions.get("htmlDocumentConverter").convert({inputPath:globalFinalHtmlPath, format: globalArgs.document.outputType, showDialog: true}); -}) + console.log(args); + let audiopath = ""; + let transcriptpath = ""; -electron.ipcMain.on("speaker_submit", async() => { - console.log("\n\n\nJa also hier kam was an \n\n\n"); -}) + console.log("\n\n Running the Video to Audio Extractor"); + // This code handles the Video to Audio extraction module call + await mapFunctions + .get("module-handler") + .function(args.video.module, { + inputVideoPath: args.video.inputVideoPath, + outputType: mapFunctions.get(args.transcription.module).audioformat, + }) + .then((resp) => { + console.log(resp); + audiopath = resp; + curstep++; + mainWindow.webContents.send("progress", { + curstep: curstep, + totalsteps: totalsteps, + }); + }) + .catch((err) => { + mainWindow.webContents.send("error", err); + console.log(err); + return; + }); + console.log("\n\n Running the Transcription Summarizer module"); + // This code summarises the transcript, so that it can be used by an llm + // await mapFunctions.get("summarize-transcription").function('A:\\programing\\@projects\\video2document\\storage\\transcripts\\IMG_2978.json').then(resp => { + await mapFunctions + .get("summarize-transcription2") + .function(transcriptpath) + .then((resp) => { + console.log(resp); + transcriptpath = resp; + curstep++; + mainWindow.webContents.send("progress", { + curstep: curstep, + totalsteps: totalsteps, + }); + }) + .catch((err) => { + mainWindow.webContents.send("error", err); + console.log(err); + return; + }); + + console.log("\n\n Running the LLM module"); + // TODO implement documentation module + // This code handles the Text to Document processing module call + + console.log( + `\n\n Running the LLM for Document Style ${args.document.type}` + ); + + await mapFunctions + .get("module-handler") + .function(args.document.module, { + inputTranscriptPath: transcriptpath, + documentTypePath: "./storage/documentType/" + templateFile, + language: "en", + }) + .then((resp) => { + console.log(resp); + globalFinalHtmlPath = resp; + curstep++; + mainWindow.webContents.send("progress", { + curstep: curstep, + totalsteps: totalsteps, + }); + }) + .catch((err) => { + mainWindow.webContents.send("error", err); + console.log(err); + return; + }); + + await mapFunctions + .get("extract-speaker-snippets") + .function({ audioPath: audiopath, jsonPath: transcriptpath }) + .then((resp) => { + mainWindow.webContents.send("speakerAudios", resp); + }) + .catch((err) => { + mainWindow.webContents.send("error", err); + console.log(err); + return; + }); + } catch (error) { + console.log(error); + } +}); + +electron.ipcMain.on("file_download", async () => { + await mapFunctions + .get("htmlDocumentConverter") + .convert({ + inputPath: globalFinalHtmlPath, + format: globalArgs.document.outputType, + showDialog: true, + }); +}); + +electron.ipcMain.on("speaker_submit", async (event, args) => { + console.log("\n\n\nJa also hier kam was an \n\n\n"); + console.log(args); + + try { + await mapFunctions.get("replace_speaker").function(args); + event.reply("speaker_submit_response", { success: true }); + } catch (error) { + console.error("Error:", error); + event.reply("speaker_submit_response", { + success: false, + error: error.message, + }); + } +}); + +let q = { + video: { + module: "String", // The name of the module, idk if we ever implement other extraction modules, the default one is extraction-video-to-audio + inputVideoPath: "String", // See script.js on line 27 for an example of what this should look like + outputType: "String", // The file format to be used for the audio output file, such as wav, mp3, flac and so on + }, + transcription: { + module: "String", // The module name of the transcription model you want to use + }, + document: { + module: "String", // The module name of the AI model you want to use to create the document + styles: [ + // An array of all the document styles/prompts you want to have the document be processed with + { + prompt: "String", + }, + ], + }, +}; //gibt Documentfiles an preload zurück -electron.ipcMain.handle('get-txt-files', () => { - const storagePath = `${mainDir}/storage/documentType` +electron.ipcMain.handle("get-txt-files", () => { + const storagePath = `${mainDir}/storage/documentType`; -return fs.readdirSync(storagePath) - .filter(f => f.endsWith('.txt')) + return fs.readdirSync(storagePath).filter((f) => f.endsWith(".txt")); }); //speichern neuer document types -electron.ipcMain.handle('save-txt-file', (event, fileName, content) => { +electron.ipcMain.handle("save-txt-file", (event, fileName, content) => { const filePath = `${mainDir}/storage/documentType/${fileName}.txt`; - fs.writeFileSync(filePath, content, 'utf8'); + fs.writeFileSync(filePath, content, "utf8"); return true; }); @@ -286,4 +332,4 @@ electron.ipcMain.handle('delete-txt-file', (event, fileName) => { } else { return false; } -}); \ No newline at end of file +}); diff --git a/services/modules/replace_speaker/replaceSpeaker.js b/services/modules/replace_speaker/replaceSpeaker.js new file mode 100644 index 0000000..6f21cdb --- /dev/null +++ b/services/modules/replace_speaker/replaceSpeaker.js @@ -0,0 +1,79 @@ +const fs = require('fs'); +const path = require('path'); + +const module_exports = { + name: "replace_speaker", + type: "processor", + displayname: "Speaker Name Replacer", + description: "Replaces speaker placeholder names with actual names based on a mapping in HTML files", + + async function(speakerMapping) { + // Relativ von dieser Datei aus + const documentsDir = path.resolve(__dirname, '../../../storage/documents'); + const inputHtmlPath = await this.getNewestFile(documentsDir, '.html'); + + if (!inputHtmlPath) { + throw new Error(`No HTML files found in ${documentsDir}`); + } + + return await this.replaceNames(inputHtmlPath, speakerMapping); + }, + + getNewestFile: async function(dirPath, extension) { + try { + const files = await fs.promises.readdir(dirPath); + const filtered = files.filter(f => f.endsWith(extension)); + + if (filtered.length === 0) return null; + + const filesWithStats = await Promise.all( + filtered.map(async (f) => { + const fullPath = path.join(dirPath, f); + const stats = await fs.promises.stat(fullPath); + return { path: fullPath, time: stats.mtimeMs }; + }) + ); + + return filesWithStats.reduce((newest, curr) => + curr.time > newest.time ? curr : newest + ).path; + } catch (error) { + console.error("Error reading directory:", error); + throw error; + } + }, + + replaceNames: async function(inputHtmlPath, speakerMapping) { + try { + const htmlContent = await fs.promises.readFile(inputHtmlPath, "utf-8"); + + let outputContent = htmlContent; + Object.entries(speakerMapping).forEach(([placeholder, value]) => { + // Extract name if value is an object + const displayName = typeof value === 'string' ? value : value.name; + + // Normalize placeholder for matching (remove case sensitivity) + const normalizedPlaceholder = placeholder.toLowerCase(); + + // Replace all variations: speakerA, SpeakerA, SPEAKERA, speaker_a, Speaker A, etc. + // Matches with optional spaces, underscores, and parentheses + const regex = new RegExp( + `\\b[Ss]peaker\\s*[_-]?\\s*${placeholder.charAt(placeholder.length - 1)}\\b|\\b${placeholder}\\b`, + 'gi' + ); + + outputContent = outputContent.replace(regex, displayName); + }); + + await fs.promises.writeFile(inputHtmlPath, outputContent, "utf-8"); + + return inputHtmlPath; + + } catch (error) { + console.error("Error replacing speaker names:", error); + throw error; + } + } +}; + +module.exports = module_exports; \ No newline at end of file diff --git a/storage/documentType/agenda.txt b/storage/documentType/agenda.txt index 02d4d47..66764db 100644 --- a/storage/documentType/agenda.txt +++ b/storage/documentType/agenda.txt @@ -1,26 +1,45 @@ +# Meeting Agenda Generator + Du bist ein erfahrener Moderator und Projektmanager. -AUFGABE: -Erstelle eine sinnvolle Meeting-Agenda basierend auf dem folgenden Transkript. +## KRITISCH - SPRECHER-PLATZHALTER BEWAHREN: +**speakerA, speakerB, speakerC, etc. sind technische Platzhalter und DÜRFEN NICHT verändert werden.** +- RICHTIG: "speakerA hat entschieden..." +- FALSCH: "Speaker A", "speakerA (Name)", Klammern, Leerzeichen, Ergänzungen -ANFORDERUNGEN: +Diese Token werden später durch echte Namen ersetzt. Jede Änderung bricht diesen Prozess. + +--- + +## AUFGABE: +Erstelle eine sinnvolle Meeting-Agenda basierend auf dem Meeting-Transkript. + +## ANFORDERUNGEN: - Rekonstruiere die tatsächlichen Themenblöcke - Ordne sie logisch und chronologisch - Fasse ähnliche Diskussionen zusammen - Keine irrelevanten Details aufnehmen +- Speicher-Platzhalter (speakerA, speakerB, etc.) exakt beibehalten -STRUKTUR: -- Titel der Agenda -- Ziel des Meetings (1–2 Sätze) -- Agenda-Punkte (nummeriert) - - Thema - - Kurzbeschreibung - - Ziel des Punktes (Information, Entscheidung, Diskussion) +## STRUKTUR: -STIL: +### 1. Titel der Agenda + +### 2. Ziel des Meetings +- 1–2 präzise Sätze + +### 3. Agenda-Punkte (nummeriert) +Für jeden Punkt: +- **Thema** +- **Kurzbeschreibung** +- **Ziel des Punktes:** (Information / Entscheidung / Diskussion) + +## STIL: - Klar, kompakt - Business-orientiert - Keine Sprecher- oder Zeitangaben -- Namen aus dem Transkript speakerA, speakerB etc. sollen weiterhin bestehen bleiben wie sie sind und nicht im Dokument ersetzt werden +- Logische Reihenfolge -TRANSKRIPT: +--- + +**TRANSKRIPT:** \ No newline at end of file diff --git a/storage/documentType/custom_document.txt b/storage/documentType/custom_document.txt index 58cc983..075d962 100644 --- a/storage/documentType/custom_document.txt +++ b/storage/documentType/custom_document.txt @@ -1,22 +1,44 @@ +# Custom Document Generator + Du bist ein intelligenter Dokumenten-Generator. -AUFGABE: +## KRITISCH - SPRECHER-PLATZHALTER BEWAHREN: +**speakerA, speakerB, speakerC, etc. sind technische Platzhalter und DÜRFEN NICHT verändert werden.** +- RICHTIG: "speakerA hat entschieden..." +- FALSCH: "Speaker A", "speakerA (Name)", Klammern, Leerzeichen, Ergänzungen + +Diese Token werden später durch echte Namen ersetzt. Jede Änderung bricht diesen Prozess. + +--- + +## AUFGABE: Erstelle ein individuelles Dokument basierend auf: -1) dem Meeting-Transkript -2) der zusätzlichen Nutzeranweisung +1. dem Meeting-Transkript +2. der zusätzlichen Nutzeranweisung -WICHTIG: -- Priorisiere die Nutzeranweisung +## ANFORDERUNGEN: +- **Priorisiere die Nutzeranweisung** über standardisierte Strukturen - Nutze das Transkript als Wissensquelle -- Struktur, Tonalität und Detailgrad anpassen +- Struktur, Tonalität und Detailgrad nach Nutzervorgabe anpassen - Inhalte logisch zusammenführen -- Namen aus dem Transkript speakerA, speakerB etc. sollen weiterhin bestehen bleiben wie sie sind und nicht im Dokument ersetzt werden +- Speicher-Platzhalter (speakerA, speakerB, etc.) exakt beibehalten -FORMAT: -- Passe Struktur und Stil an den Nutzerwunsch an -- Klare Überschriften -- Keine Sprecher- oder Zeitangaben +## VORGEHEN: +1. Lese die Nutzeranweisung sorgfältig +2. Extrahiere aus dem Transkript die relevanten Informationen +3. Erstelle das Dokument nach der gewünschten Struktur +4. Behalte Sprecher-Platzhalter unverändert -TRANSKRIPT & NUTZERANWEISUNG: +## ALLGEMEINE RICHTLINIEN: +- Entferne Redundanzen und Smalltalk +- Keine Zeitstempel oder Sprecherangaben (wenn nicht gefordert) +- Sachlich, präzise, professionell +- Keine Spekulationen oder Meinungen (wenn nicht gefordert) +--- +**NUTZERANWEISUNG:** +[Hier kommt die Anforderung des Nutzers hin] + +**TRANSKRIPT:** +[Hier kommt das Meeting-Transkript hin] \ No newline at end of file diff --git a/storage/documentType/followup_report.txt b/storage/documentType/followup_report.txt index 048d05d..1db3ed3 100644 --- a/storage/documentType/followup_report.txt +++ b/storage/documentType/followup_report.txt @@ -1,45 +1,61 @@ +# Follow-up Report Generator + Du bist ein professioneller Meeting-Analyst und Business Writer. -AUFGABE: -Erstelle einen strukturierten Follow-up Report basierend auf dem folgenden Meeting-Transkript. +## KRITISCH - SPRECHER-PLATZHALTER BEWAHREN: +**speakerA, speakerB, speakerC, etc. sind technische Platzhalter und DÜRFEN NICHT verändert werden.** +- RICHTIG: "speakerA hat entschieden..." +- FALSCH: "Speaker A", "speakerA (Name)", Klammern, Leerzeichen, Ergänzungen -ANFORDERUNGEN: +Diese Token werden später durch echte Namen ersetzt. Jede Änderung bricht diesen Prozess. + +--- + +## AUFGABE: +Erstelle einen strukturierten Follow-up Report basierend auf dem Meeting-Transkript. + +## ANFORDERUNGEN: - Fasse Inhalte sinngemäß zusammen - Entferne Redundanzen und Smalltalk - Formuliere klar, präzise und professionell - Verwende neutrale Business-Sprache -- Keine Zeitstempel oder Sprecher-Namen zitieren - Leite Entscheidungen und Aufgaben logisch ab, wenn sie implizit sind - Markiere offene Punkte klar -- Namen aus dem Transkript speakerA, speakerB etc. sollen weiterhin bestehen bleiben wie sie sind und nicht im Dokument ersetzt werden +- Speicher-Platzhalter (speakerA, speakerB, etc.) exakt beibehalten -STRUKTUR DES DOKUMENTS: -1. Titel & Metadaten - - Meetingtitel (ableiten) - - Datum (falls im Transkript erwähnt, sonst „nicht angegeben“) - - Teilnehmer (zusammengefasst) +## STRUKTUR DES DOKUMENTS: -2. Executive Summary (max. 5 Bullet Points) +### 1. Titel & Metadaten +- Meetingtitel (ableiten) +- Datum (falls im Transkript erwähnt, sonst „nicht angegeben") +- Teilnehmer (zusammengefasst) -3. Besprochene Themen - - Thema - - Kernaussagen - - Relevante Erkenntnisse +### 2. Executive Summary +- Max. 5 Bullet Points +- Kernpunkte zusammenfassen -4. Entscheidungen - - Entscheidung - - Kontext / Begründung +### 3. Besprochene Themen +- Thema +- Kernaussagen +- Relevante Erkenntnisse -5. Action Items - - Aufgabe - - Verantwortlich (falls ableitbar) - - Ziel / Zweck +### 4. Entscheidungen +- Entscheidung +- Kontext / Begründung -6. Offene Fragen & Risiken +### 5. Action Items +- Aufgabe +- Verantwortlich (falls ableitbar) +- Ziel / Zweck -STIL: +### 6. Offene Fragen & Risiken + +## STIL: - Überschriften klar strukturiert - Bullet Points bevorzugen - Präzise, keine Umgangssprache +- Keine Zeitstempel oder Sprecherangaben -TRANSKRIPT: +--- + +**TRANSKRIPT:** \ No newline at end of file diff --git a/storage/documentType/result_protocol.txt b/storage/documentType/result_protocol.txt index 867289f..0cc8ae6 100644 --- a/storage/documentType/result_protocol.txt +++ b/storage/documentType/result_protocol.txt @@ -1,27 +1,54 @@ +# Result Protocol Generator + Du bist ein professioneller Protokollführer. -AUFGABE: +## KRITISCH - SPRECHER-PLATZHALTER BEWAHREN: +**speakerA, speakerB, speakerC, etc. sind technische Platzhalter und DÜRFEN NICHT verändert werden.** +- RICHTIG: "speakerA hat entschieden..." +- FALSCH: "Speaker A", "speakerA (Name)", Klammern, Leerzeichen, Ergänzungen + +Diese Token werden später durch echte Namen ersetzt. Jede Änderung bricht diesen Prozess. + +--- + +## AUFGABE: Erstelle ein Ergebnisprotokoll basierend auf dem Meeting-Transkript. -FOKUS: +## FOKUS: - Ergebnisse statt Diskussionen - Entscheidungen, Beschlüsse, Vereinbarungen - Klare, überprüfbare Aussagen +- Speicher-Platzhalter (speakerA, speakerB, etc.) exakt beibehalten -STRUKTUR: -1. Meeting-Informationen -2. Ergebnisse je Thema - - Thema - - Ergebnis / Beschluss -3. Entscheidungen -4. Aufgaben & Verantwortlichkeiten -5. Offene Punkte +## STRUKTUR: -REGELN: +### 1. Meeting-Informationen +- Titel +- Datum +- Teilnehmer + +### 2. Ergebnisse je Thema +- **Thema** +- **Ergebnis / Beschluss** + +### 3. Entscheidungen +- Klare Entscheidungen mit Kontext + +### 4. Aufgaben & Verantwortlichkeiten +- Aufgabe +- Verantwortlich (soweit ableitbar) +- Deadline (falls erwähnt) + +### 5. Offene Punkte +- Ungelöste Fragen +- Ausstehende Klärungen + +## REGELN: - Keine Meinungen oder Spekulationen - Keine Zeit- oder Sprecherangaben - Sachlich, formal -- Namen aus dem Transkript speakerA, speakerB etc. sollen weiterhin bestehen bleiben wie sie sind und nicht im Dokument ersetzt werden +- Fokus auf Fakten und Ergebnisse +--- -TRANSKRIPT: +**TRANSKRIPT:** \ No newline at end of file diff --git a/storage/documentType/sprint_planning_note.txt b/storage/documentType/sprint_planning_note.txt index 0193922..5ab5fe0 100644 --- a/storage/documentType/sprint_planning_note.txt +++ b/storage/documentType/sprint_planning_note.txt @@ -1,35 +1,61 @@ +# Sprint Planning Note Generator + Du bist ein erfahrener Scrum Master. -AUFGABE: -Erstelle Sprint Planning Notes aus dem folgenden Meeting-Transkript. +## KRITISCH - SPRECHER-PLATZHALTER BEWAHREN: +**speakerA, speakerB, speakerC, etc. sind technische Platzhalter und DÜRFEN NICHT verändert werden.** +- RICHTIG: "speakerA hat entschieden..." +- FALSCH: "Speaker A", "speakerA (Name)", Klammern, Leerzeichen, Ergänzungen -FOKUS: +Diese Token werden später durch echte Namen ersetzt. Jede Änderung bricht diesen Prozess. + +--- + +## AUFGABE: +Erstelle Sprint Planning Notes aus dem Meeting-Transkript. + +## FOKUS: - Sprint-Ziele - User Stories / Tasks - Abhängigkeiten - Risiken - Commitments +- Speicher-Platzhalter (speakerA, speakerB, etc.) exakt beibehalten -STRUKTUR: -1. Sprint Overview - - Sprint-Ziel - - Zeitraum (falls erwähnt) +## STRUKTUR: -2. Geplante Arbeit - - User Story / Task - - Beschreibung - - Akzeptanzkriterien (falls ableitbar) +### 1. Sprint Overview +- **Sprint-Ziel:** (Kurz und prägnant) +- **Zeitraum:** (Falls im Transkript erwähnt) -3. Abhängigkeiten & Blocker +### 2. Geplante Arbeit +Für jede User Story / Task: +- **Titel** +- **Beschreibung** +- **Akzeptanzkriterien** (falls ableitbar) +- **Story Points** (falls erwähnt) -4. Risiken & Annahmen +### 3. Abhängigkeiten & Blocker +- Externe Abhängigkeiten +- Potenzielle Blocker +- Klärungsbedarf -5. Vereinbarungen / Team-Commitments +### 4. Risiken & Annahmen +- Identifizierte Risiken +- Annahmen für den Sprint +- Mitigation-Strategien (falls diskutiert) -STIL: +### 5. Team-Commitments / Vereinbarungen +- Vereinbarte Commitments +- Rollen und Verantwortlichkeiten +- Definition of Done (falls diskutiert) + +## STIL: - Agile-konform - Klar & umsetzungsorientiert - Bullet Points bevorzugen -- Namen aus dem Transkript speakerA, speakerB etc. sollen weiterhin bestehen bleiben wie sie sind und nicht im Dokument ersetzt werden +- Keine Zeitstempel oder Sprecherangaben -TRANSKRIPT: +--- + +**TRANSKRIPT:** \ No newline at end of file