pulse-framework-cli 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/commands/checkpoint.d.ts +2 -0
  2. package/dist/commands/checkpoint.js +129 -0
  3. package/dist/commands/correct.d.ts +2 -0
  4. package/dist/commands/correct.js +77 -0
  5. package/dist/commands/doctor.d.ts +2 -0
  6. package/dist/commands/doctor.js +183 -0
  7. package/dist/commands/escalate.d.ts +2 -0
  8. package/dist/commands/escalate.js +226 -0
  9. package/dist/commands/init.d.ts +2 -0
  10. package/dist/commands/init.js +570 -0
  11. package/dist/commands/learn.d.ts +2 -0
  12. package/dist/commands/learn.js +137 -0
  13. package/dist/commands/profile.d.ts +2 -0
  14. package/dist/commands/profile.js +39 -0
  15. package/dist/commands/reset.d.ts +2 -0
  16. package/dist/commands/reset.js +130 -0
  17. package/dist/commands/review.d.ts +2 -0
  18. package/dist/commands/review.js +129 -0
  19. package/dist/commands/run.d.ts +2 -0
  20. package/dist/commands/run.js +272 -0
  21. package/dist/commands/start.d.ts +2 -0
  22. package/dist/commands/start.js +196 -0
  23. package/dist/commands/status.d.ts +2 -0
  24. package/dist/commands/status.js +239 -0
  25. package/dist/commands/watch.d.ts +2 -0
  26. package/dist/commands/watch.js +98 -0
  27. package/dist/hooks/install.d.ts +1 -0
  28. package/dist/hooks/install.js +89 -0
  29. package/dist/index.d.ts +2 -0
  30. package/dist/index.js +40 -0
  31. package/dist/lib/artifacts.d.ts +7 -0
  32. package/dist/lib/artifacts.js +52 -0
  33. package/dist/lib/briefing.d.ts +77 -0
  34. package/dist/lib/briefing.js +231 -0
  35. package/dist/lib/clipboard.d.ts +9 -0
  36. package/dist/lib/clipboard.js +116 -0
  37. package/dist/lib/config.d.ts +14 -0
  38. package/dist/lib/config.js +167 -0
  39. package/dist/lib/context-export.d.ts +30 -0
  40. package/dist/lib/context-export.js +149 -0
  41. package/dist/lib/exec.d.ts +9 -0
  42. package/dist/lib/exec.js +23 -0
  43. package/dist/lib/git.d.ts +24 -0
  44. package/dist/lib/git.js +74 -0
  45. package/dist/lib/input.d.ts +15 -0
  46. package/dist/lib/input.js +80 -0
  47. package/dist/lib/notifications.d.ts +2 -0
  48. package/dist/lib/notifications.js +25 -0
  49. package/dist/lib/paths.d.ts +4 -0
  50. package/dist/lib/paths.js +39 -0
  51. package/dist/lib/prompts.d.ts +43 -0
  52. package/dist/lib/prompts.js +270 -0
  53. package/dist/lib/scanner.d.ts +37 -0
  54. package/dist/lib/scanner.js +413 -0
  55. package/dist/lib/types.d.ts +37 -0
  56. package/dist/lib/types.js +2 -0
  57. package/package.json +42 -0
  58. package/templates/.cursorrules +159 -0
  59. package/templates/AGENTS.md +198 -0
  60. package/templates/cursor/mcp.json +9 -0
  61. package/templates/cursor/pulse.mdc +144 -0
  62. package/templates/roles/architect.cursorrules +15 -0
  63. package/templates/roles/backend.cursorrules +12 -0
  64. package/templates/roles/frontend.cursorrules +12 -0
@@ -0,0 +1,272 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.registerRunCommand = registerRunCommand;
37
+ const artifacts_js_1 = require("../lib/artifacts.js");
38
+ const config_js_1 = require("../lib/config.js");
39
+ const input_js_1 = require("../lib/input.js");
40
+ const paths_js_1 = require("../lib/paths.js");
41
+ const git_js_1 = require("../lib/git.js");
42
+ const notifications_js_1 = require("../lib/notifications.js");
43
+ const clipboard_js_1 = require("../lib/clipboard.js");
44
+ const prompts_js_1 = require("../lib/prompts.js");
45
+ function registerRunCommand(program) {
46
+ program
47
+ .command("run")
48
+ .description("Combined workflow: Start → Watch → Checkpoints → Review")
49
+ .option("-t, --template <id>", "Vorlage: feature, bugfix, refactor, concept, analyze, review")
50
+ .option("--minutes <n>", "Minutes between checkpoint reminders")
51
+ .option("--no-watch", "Don't start watcher")
52
+ .option("--action <text>", "ACTION direkt angeben")
53
+ .option("-C, --clipboard", "Prompt in Zwischenablage kopieren")
54
+ .action(async (opts) => {
55
+ const repoRoot = await (0, paths_js_1.findRepoRoot)(process.cwd());
56
+ if (!repoRoot)
57
+ throw new Error("Nicht in einem Git-Repository.");
58
+ const [state, config] = await Promise.all([(0, artifacts_js_1.loadState)(repoRoot), (0, config_js_1.loadConfig)(repoRoot)]);
59
+ // Use preset checkpoint interval if not specified
60
+ const minutes = opts.minutes
61
+ ? Math.max(5, Number(opts.minutes))
62
+ : config.checkpointReminderMinutes ?? 30;
63
+ const presetProfile = config.preset ? `${config.preset}/${state.profile}` : state.profile;
64
+ // ════════════════════════════════════════════════════════════════════════
65
+ // HEADER
66
+ // ════════════════════════════════════════════════════════════════════════
67
+ // eslint-disable-next-line no-console
68
+ console.log(`
69
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
70
+ ┃ 🚀 PULSE Run ┃
71
+ ┃ Profile: ${presetProfile.padEnd(49)}┃
72
+ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
73
+ `);
74
+ // ════════════════════════════════════════════════════════════════════════
75
+ // PHASE 1: Create prompt
76
+ // ════════════════════════════════════════════════════════════════════════
77
+ // eslint-disable-next-line no-console
78
+ console.log(`━━━ PHASE 1: Prompt ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`);
79
+ // Template auswählen
80
+ let template = opts.template ? (0, prompts_js_1.getTemplateById)(opts.template) : undefined;
81
+ if (!template && !opts.action) {
82
+ const choices = prompts_js_1.PROMPT_TEMPLATES.map((t) => ({
83
+ value: t.id,
84
+ label: `${t.name} - ${t.description}`,
85
+ }));
86
+ const selectedId = await (0, input_js_1.promptSelect)("📋 Vorlage wählen", choices, "feature");
87
+ template = (0, prompts_js_1.getTemplateById)(selectedId);
88
+ }
89
+ // 6-Elemente sammeln
90
+ const el = {
91
+ role: template?.defaults.role,
92
+ context: template?.defaults.context,
93
+ output: template?.defaults.output,
94
+ action: opts.action,
95
+ };
96
+ const layer = template?.layer ?? state.profile;
97
+ if (!el.action?.trim()) {
98
+ el.action = await (0, input_js_1.promptText)("⚡ ACTION (Was soll gemacht werden?)", "");
99
+ }
100
+ if (!el.context?.trim()) {
101
+ el.context = await (0, input_js_1.promptText)("📍 KONTEXT (Projekt, Stack)", "");
102
+ }
103
+ // Prompt generieren
104
+ const prompt = (0, prompts_js_1.renderSixElementPrompt)(layer, el);
105
+ // Artefakt speichern
106
+ const ts = (0, artifacts_js_1.timestampId)();
107
+ const filename = `${ts}-run.md`;
108
+ const content = [
109
+ `# Pulse Run (${ts})`,
110
+ ``,
111
+ `- Profile: **${presetProfile}**`,
112
+ `- Layer: **${layer}**`,
113
+ template ? `- Vorlage: **${template.name}**` : "",
114
+ `- Checkpoint interval: **${minutes} min**`,
115
+ ``,
116
+ `## Prompt`,
117
+ ``,
118
+ "```",
119
+ prompt.trimEnd(),
120
+ "```",
121
+ ``,
122
+ ]
123
+ .filter((line) => line !== "")
124
+ .join("\n");
125
+ const artifactPath = await (0, artifacts_js_1.writeArtifact)(repoRoot, "pulses", filename, content);
126
+ // eslint-disable-next-line no-console
127
+ console.log(`✅ Template: ${template?.name ?? "custom"}`);
128
+ // eslint-disable-next-line no-console
129
+ console.log(`✅ Artefakt: ${artifactPath}`);
130
+ // Clipboard
131
+ if (opts.clipboard) {
132
+ const clipMsg = await (0, clipboard_js_1.copyAndNotify)(prompt);
133
+ // eslint-disable-next-line no-console
134
+ console.log(clipMsg);
135
+ }
136
+ // eslint-disable-next-line no-console
137
+ console.log(`\n┌${"─".repeat(58)}┐`);
138
+ // eslint-disable-next-line no-console
139
+ console.log(`│ PROMPT ${opts.clipboard ? "(copied)" : "(copy and paste into Cursor)"}${" ".repeat(opts.clipboard ? 35 : 19)}│`);
140
+ // eslint-disable-next-line no-console
141
+ console.log(`└${"─".repeat(58)}┘\n`);
142
+ // eslint-disable-next-line no-console
143
+ console.log(prompt.trimEnd());
144
+ // eslint-disable-next-line no-console
145
+ console.log(`\n${"─".repeat(60)}\n`);
146
+ // ════════════════════════════════════════════════════════════════════════
147
+ // PHASE 2: Watch Loop
148
+ // ════════════════════════════════════════════════════════════════════════
149
+ if (opts.watch === false) {
150
+ // eslint-disable-next-line no-console
151
+ console.log(`━━━ PHASE 2: Übersprungen ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`);
152
+ // eslint-disable-next-line no-console
153
+ console.log("Watcher not started (--no-watch).\n");
154
+ // eslint-disable-next-line no-console
155
+ console.log("💡 Next steps:");
156
+ // eslint-disable-next-line no-console
157
+ console.log(" 1. Prompt in Cursor einfügen");
158
+ // eslint-disable-next-line no-console
159
+ console.log(" 2. `pulse checkpoint` alle 5-10 Min");
160
+ // eslint-disable-next-line no-console
161
+ console.log(" 3. Bei Problemen: `pulse escalate`");
162
+ // eslint-disable-next-line no-console
163
+ console.log(" 4. Am Ende: `pulse review`\n");
164
+ return;
165
+ }
166
+ // eslint-disable-next-line no-console
167
+ console.log(`━━━ PHASE 2: Watcher ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`);
168
+ // eslint-disable-next-line no-console
169
+ console.log(`⏱️ Checkpoint interval: ${minutes} min (${config.preset ?? "custom"} preset)`);
170
+ // eslint-disable-next-line no-console
171
+ console.log(`📍 Watcher running... (Ctrl+C to stop)\n`);
172
+ // eslint-disable-next-line no-console
173
+ console.log(` 1. Kopiere den Prompt oben in Cursor`);
174
+ // eslint-disable-next-line no-console
175
+ console.log(` 2. Arbeite los`);
176
+ // eslint-disable-next-line no-console
177
+ console.log(` 3. Ctrl+C wenn fertig\n`);
178
+ await (0, notifications_js_1.notify)(config.notifications, "Pulse Run gestartet", `Checkpoint reminder every ${minutes} min. Ctrl+C to exit.`);
179
+ // Update state
180
+ state.lastCheckpointAt = new Date().toISOString();
181
+ await (0, artifacts_js_1.saveState)(repoRoot, state);
182
+ let checkpointCount = 0;
183
+ let lastReminderAt = Date.now();
184
+ // Polling loop
185
+ const interval = setInterval(async () => {
186
+ const now = Date.now();
187
+ const shouldRemind = now - lastReminderAt >= minutes * 60_000;
188
+ if (!shouldRemind)
189
+ return;
190
+ lastReminderAt = now;
191
+ const status = await (0, git_js_1.gitStatusPorcelain)(repoRoot);
192
+ const dirty = status.trim().length > 0;
193
+ if (dirty) {
194
+ checkpointCount++;
195
+ await (0, notifications_js_1.notify)(config.notifications, `⏱️ Checkpoint #${checkpointCount}`, `${minutes} min passed. Time for: pulse checkpoint`);
196
+ // eslint-disable-next-line no-console
197
+ console.log(`\n┌${"─".repeat(58)}┐`);
198
+ // eslint-disable-next-line no-console
199
+ console.log(`│ ⏰ CHECKPOINT REMINDER #${checkpointCount}${" ".repeat(58 - 26 - String(checkpointCount).length)}│`);
200
+ // eslint-disable-next-line no-console
201
+ console.log(`└${"─".repeat(58)}┘`);
202
+ // eslint-disable-next-line no-console
203
+ console.log(` Zeit: ${new Date().toLocaleTimeString()}`);
204
+ // eslint-disable-next-line no-console
205
+ console.log(` Status: Uncommitted Changes vorhanden`);
206
+ // eslint-disable-next-line no-console
207
+ console.log(` → pulse checkpoint -m 'deine message'\n`);
208
+ }
209
+ else {
210
+ // eslint-disable-next-line no-console
211
+ console.log(`\n✨ [${new Date().toLocaleTimeString()}] Repo is clean - no checkpoint needed\n`);
212
+ }
213
+ }, 30_000); // Check every 30 seconds
214
+ // ════════════════════════════════════════════════════════════════════════
215
+ // PHASE 3: Cleanup on exit
216
+ // ════════════════════════════════════════════════════════════════════════
217
+ const cleanup = async (signal) => {
218
+ clearInterval(interval);
219
+ // eslint-disable-next-line no-console
220
+ console.log(`\n\n━━━ PHASE 3: Abschluss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`);
221
+ // eslint-disable-next-line no-console
222
+ console.log(`🛑 ${signal} empfangen - Beende Pulse Run...\n`);
223
+ // Check final status
224
+ const status = await (0, git_js_1.gitStatusPorcelain)(repoRoot);
225
+ const dirty = status.trim().length > 0;
226
+ if (dirty) {
227
+ // eslint-disable-next-line no-console
228
+ console.log("📝 Uncommitted Changes gefunden:\n");
229
+ const stat = await (0, git_js_1.gitDiffStat)(repoRoot);
230
+ // eslint-disable-next-line no-console
231
+ console.log(stat);
232
+ // eslint-disable-next-line no-console
233
+ console.log("");
234
+ const doCheckpoint = await (0, input_js_1.promptConfirm)("Create checkpoint?", true);
235
+ if (doCheckpoint) {
236
+ const msg = await (0, input_js_1.promptText)("Commit message", "checkpoint: work in progress");
237
+ const { exec } = await Promise.resolve().then(() => __importStar(require("../lib/exec.js")));
238
+ await exec("git", ["add", "-A"], { cwd: repoRoot });
239
+ await exec("git", ["commit", "-m", msg], { cwd: repoRoot });
240
+ // eslint-disable-next-line no-console
241
+ console.log("✅ Committed.\n");
242
+ }
243
+ }
244
+ else {
245
+ // eslint-disable-next-line no-console
246
+ console.log("✨ Keine uncommitted Changes.\n");
247
+ }
248
+ // Offer review
249
+ const doReview = await (0, input_js_1.promptConfirm)("Create review?", dirty);
250
+ if (doReview) {
251
+ // eslint-disable-next-line no-console
252
+ console.log("\n💡 Führe aus: pulse review\n");
253
+ }
254
+ // Summary
255
+ // eslint-disable-next-line no-console
256
+ console.log(`┌${"─".repeat(58)}┐`);
257
+ // eslint-disable-next-line no-console
258
+ console.log(`│ 👋 Pulse Run beendet${" ".repeat(37)}│`);
259
+ // eslint-disable-next-line no-console
260
+ console.log(`│ │`);
261
+ // eslint-disable-next-line no-console
262
+ console.log(`│ Checkpoints: ${checkpointCount}${" ".repeat(43 - String(checkpointCount).length)}│`);
263
+ // eslint-disable-next-line no-console
264
+ console.log(`│ Artefakt: .pulse/pulses/${filename}${" ".repeat(Math.max(0, 32 - filename.length))}│`);
265
+ // eslint-disable-next-line no-console
266
+ console.log(`└${"─".repeat(58)}┘\n`);
267
+ process.exit(0);
268
+ };
269
+ process.on("SIGINT", () => cleanup("SIGINT"));
270
+ process.on("SIGTERM", () => cleanup("SIGTERM"));
271
+ });
272
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerStartCommand(program: Command): void;
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerStartCommand = registerStartCommand;
4
+ const artifacts_js_1 = require("../lib/artifacts.js");
5
+ const config_js_1 = require("../lib/config.js");
6
+ const input_js_1 = require("../lib/input.js");
7
+ const paths_js_1 = require("../lib/paths.js");
8
+ const clipboard_js_1 = require("../lib/clipboard.js");
9
+ const git_js_1 = require("../lib/git.js");
10
+ const prompts_js_1 = require("../lib/prompts.js");
11
+ function registerStartCommand(program) {
12
+ program
13
+ .command("start")
14
+ .alias("s") // Kurzform: pulse s
15
+ .description("Start a new Pulse with 6-element prompt")
16
+ .option("-t, --template <id>", "Template: feature, bugfix, refactor, concept, analyze, review")
17
+ .option("-q, --quick", "Quick-Mode: Ask only for ACTION")
18
+ .option("--role <text>", "ROLE")
19
+ .option("--context <text>", "CONTEXT")
20
+ .option("--input <text>", "INPUT")
21
+ .option("--action <text>", "ACTION")
22
+ .option("--output <text>", "OUTPUT")
23
+ .option("--examples <text>", "EXAMPLES")
24
+ .option("--ist <text>", "AS-IS state (for AS-IS/TO-BE prompt)")
25
+ .option("--soll <text>", "TO-BE state (for AS-IS/TO-BE prompt)")
26
+ .option("-C, --clipboard", "Copy prompt to clipboard")
27
+ .option("--no-branch-check", "Skip branch check (for MCP/Automation)")
28
+ .action(async (opts) => {
29
+ const repoRoot = await (0, paths_js_1.findRepoRoot)(process.cwd());
30
+ if (!repoRoot)
31
+ throw new Error("Not in a git repository.");
32
+ const [state, config] = await Promise.all([(0, artifacts_js_1.loadState)(repoRoot), (0, config_js_1.loadConfig)(repoRoot)]);
33
+ // eslint-disable-next-line no-console
34
+ console.log("\n🎯 PULSE Start\n");
35
+ // ══════════════════════════════════════════════════════════════════════
36
+ // Branch check: Warning on main/master (only interactive, not with --quick)
37
+ // ══════════════════════════════════════════════════════════════════════
38
+ const skipBranchCheck = opts.branchCheck === false || opts.quick;
39
+ if (!skipBranchCheck) {
40
+ const currentBranch = await (0, git_js_1.gitCurrentBranch)(repoRoot);
41
+ const isMain = await (0, git_js_1.gitIsMainBranch)(repoRoot);
42
+ if (isMain) {
43
+ // eslint-disable-next-line no-console
44
+ console.log(`⚠️ You are on '${currentBranch}' – Feature branch recommended!\n`);
45
+ const createBranch = await (0, input_js_1.promptConfirm)("Create feature branch?", true);
46
+ if (createBranch) {
47
+ const branchName = await (0, input_js_1.promptText)("Branch name (e.g., feature/user-dashboard)", "feature/");
48
+ if (branchName && branchName !== "feature/") {
49
+ const success = await (0, git_js_1.gitCreateBranch)(repoRoot, branchName);
50
+ if (success) {
51
+ // eslint-disable-next-line no-console
52
+ console.log(`✅ Branch created: ${branchName}\n`);
53
+ }
54
+ else {
55
+ // eslint-disable-next-line no-console
56
+ console.log(`❌ Could not create branch\n`);
57
+ }
58
+ }
59
+ }
60
+ else {
61
+ // eslint-disable-next-line no-console
62
+ console.log(`ℹ️ Working on '${currentBranch}' (not recommended)\n`);
63
+ }
64
+ }
65
+ }
66
+ // ══════════════════════════════════════════════════════════════════════
67
+ // AS-IS/TO-BE Quick Prompt (for quick bug fixes)
68
+ // ══════════════════════════════════════════════════════════════════════
69
+ if (opts.ist || opts.soll) {
70
+ const ist = opts.ist ?? (await (0, input_js_1.promptText)("AS-IS (current state)", ""));
71
+ const soll = opts.soll ?? (await (0, input_js_1.promptText)("TO-BE (desired state)", ""));
72
+ const error = await (0, input_js_1.promptText)("ERROR log (optional, Enter to skip)", "");
73
+ const prompt = (0, prompts_js_1.renderIstSollPrompt)({ ist, soll, error, context: opts.context });
74
+ await saveAndPrint(repoRoot, "istsoll", prompt, undefined, opts.clipboard);
75
+ return;
76
+ }
77
+ // ══════════════════════════════════════════════════════════════════════
78
+ // Template selection (interactive or via flag)
79
+ // ══════════════════════════════════════════════════════════════════════
80
+ let template = opts.template ? (0, prompts_js_1.getTemplateById)(opts.template) : undefined;
81
+ let layer = state.profile;
82
+ // If no template and no flags → interactive selection
83
+ if (!template && (0, prompts_js_1.countProvidedElements)(opts) < 2 && !opts.quick) {
84
+ // eslint-disable-next-line no-console
85
+ console.log("What do you want to do?\n");
86
+ const choices = prompts_js_1.PROMPT_TEMPLATES.map((t) => ({
87
+ value: t.id,
88
+ label: `${t.name} - ${t.description}`,
89
+ }));
90
+ const selectedId = await (0, input_js_1.promptSelect)("Choose template", choices, "feature");
91
+ template = (0, prompts_js_1.getTemplateById)(selectedId);
92
+ }
93
+ // Merge template defaults
94
+ const el = {
95
+ role: opts.role ?? template?.defaults.role,
96
+ context: opts.context ?? template?.defaults.context,
97
+ input: opts.input ?? template?.defaults.input,
98
+ action: opts.action ?? template?.defaults.action,
99
+ output: opts.output ?? template?.defaults.output,
100
+ examples: opts.examples ?? template?.defaults.examples,
101
+ };
102
+ if (template) {
103
+ layer = template.layer;
104
+ }
105
+ // ══════════════════════════════════════════════════════════════════════
106
+ // Interaktive Abfrage der fehlenden Elemente
107
+ // ══════════════════════════════════════════════════════════════════════
108
+ if (opts.quick) {
109
+ // Quick Mode: Nur ACTION
110
+ el.action = el.action ?? (await (0, input_js_1.promptText)("⚡ ACTION (what needs to be done?)", ""));
111
+ }
112
+ else if ((0, prompts_js_1.countProvidedElements)(el) < 3) {
113
+ // Guided Mode: Die wichtigsten Elemente abfragen
114
+ // eslint-disable-next-line no-console
115
+ console.log("\n📝 Create 6-element prompt\n");
116
+ if (!el.action?.trim()) {
117
+ el.action = await (0, input_js_1.promptText)("⚡ ACTION (What should the AI do?)", "");
118
+ }
119
+ if (!el.context?.trim()) {
120
+ el.context = await (0, input_js_1.promptText)("📍 CONTEXT (Project, Stack, Situation)", el.context ?? "");
121
+ }
122
+ if (!el.role?.trim()) {
123
+ el.role = await (0, input_js_1.promptText)("👤 ROLE (Who should the AI be?)", el.role ?? "Senior Software Engineer");
124
+ }
125
+ // Optional: Mehr Details?
126
+ const wantMore = await (0, input_js_1.promptText)("Enter more details? (y/n)", "n");
127
+ if (wantMore.toLowerCase() === "j" || wantMore.toLowerCase() === "y") {
128
+ if (!el.input?.trim()) {
129
+ el.input = await (0, input_js_1.promptText)("📥 INPUT (Code, Error, Screenshot description)", "");
130
+ }
131
+ if (!el.output?.trim()) {
132
+ el.output = await (0, input_js_1.promptText)("📤 OUTPUT (What is the expected outcome?)", "");
133
+ }
134
+ }
135
+ }
136
+ // ══════════════════════════════════════════════════════════════════════
137
+ // Generate and save prompt
138
+ // ══════════════════════════════════════════════════════════════════════
139
+ const prompt = (0, prompts_js_1.renderSixElementPrompt)(layer, el);
140
+ const actionWarning = (0, prompts_js_1.validateOneAction)(el.action);
141
+ await saveAndPrint(repoRoot, "start", prompt, {
142
+ layer,
143
+ elementCount: (0, prompts_js_1.countProvidedElements)(el),
144
+ actionWarning,
145
+ template: template?.name,
146
+ }, opts.clipboard);
147
+ if (config.enforcement !== "advisory" && actionWarning) {
148
+ // eslint-disable-next-line no-console
149
+ console.log(`\n⚠️ ${actionWarning}`);
150
+ }
151
+ });
152
+ }
153
+ // Helper: Save and output
154
+ async function saveAndPrint(repoRoot, type, prompt, meta, clipboard) {
155
+ const ts = (0, artifacts_js_1.timestampId)();
156
+ const filename = `${ts}-${type}.md`;
157
+ const content = [
158
+ `# Pulse: ${type.toUpperCase()} (${ts})`,
159
+ ``,
160
+ meta?.layer ? `- Layer: **${meta.layer}**` : "",
161
+ meta?.template ? `- Template: **${meta.template}**` : "",
162
+ meta?.elementCount ? `- Elements: **${meta.elementCount}/6**` : "",
163
+ meta?.actionWarning ? `- ⚠️ ${meta.actionWarning}` : "",
164
+ ``,
165
+ `## Prompt (copy and paste into Cursor/ChatGPT)`,
166
+ ``,
167
+ "```",
168
+ prompt.trimEnd(),
169
+ "```",
170
+ ``,
171
+ `## Tips`,
172
+ `- Observe safeguards: MAX 30 min autonomous`,
173
+ `- Git commit every 5-10 min`,
174
+ `- If stuck: \`pulse escalate\``,
175
+ ``,
176
+ ]
177
+ .filter((line) => line !== "")
178
+ .join("\n");
179
+ const p = await (0, artifacts_js_1.writeArtifact)(repoRoot, "pulses", filename, content);
180
+ // eslint-disable-next-line no-console
181
+ console.log(`\n✅ Saved: ${p}`);
182
+ // Clipboard
183
+ if (clipboard) {
184
+ const clipboardMsg = await (0, clipboard_js_1.copyAndNotify)(prompt);
185
+ // eslint-disable-next-line no-console
186
+ console.log(clipboardMsg);
187
+ }
188
+ // eslint-disable-next-line no-console
189
+ console.log(`\n${"─".repeat(60)}`);
190
+ // eslint-disable-next-line no-console
191
+ console.log(`\n📋 PROMPT${clipboard ? " (copied)" : " (copy)"}:\n`);
192
+ // eslint-disable-next-line no-console
193
+ console.log(prompt.trimEnd());
194
+ // eslint-disable-next-line no-console
195
+ console.log(`\n${"─".repeat(60)}\n`);
196
+ }
@@ -0,0 +1,2 @@
1
+ import type { Command } from "commander";
2
+ export declare function registerStatusCommand(program: Command): void;