@brainervirus/workit-cursor 0.6.1 → 0.8.0

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 (77) hide show
  1. package/.cursor-plugin/plugin.json +33 -5
  2. package/README.md +88 -6
  3. package/assets/logo.svg +4 -0
  4. package/assets/templates/execution-contract.md +58 -0
  5. package/assets/templates/greeting.md +1 -0
  6. package/assets/templates/headers.md +3 -0
  7. package/assets/templates/hygiene/.editorconfig +8 -0
  8. package/assets/templates/hygiene/.gitattributes +3 -0
  9. package/assets/templates/hygiene/CHANGELOG.md +14 -0
  10. package/assets/templates/hygiene/CONTRIBUTING.md +3 -0
  11. package/assets/templates/hygiene/LICENSE +21 -0
  12. package/assets/templates/hygiene/README.md +3 -0
  13. package/assets/templates/issue-update.md +6 -0
  14. package/assets/templates/plan-template.md +25 -0
  15. package/assets/templates/spec-template.md +51 -0
  16. package/assets/templates/superpowers-doc-contract.md +70 -0
  17. package/dist/cursor-session-start.js +351 -0
  18. package/dist/mcp-server.js +27687 -0
  19. package/hooks/hooks-cursor.json +1 -1
  20. package/mcp.json +2 -6
  21. package/package.json +20 -7
  22. package/rules/ask-question-only.mdc +1 -1
  23. package/rules/sdd-docs-path.mdc +2 -2
  24. package/skills/wk-changelog/SKILL.md +1 -1
  25. package/skills/wk-commit/SKILL.md +1 -1
  26. package/skills/wk-docs-refresh/SKILL.md +1 -1
  27. package/skills/wk-handoff/SKILL.md +2 -2
  28. package/skills/wk-implement/SKILL.md +5 -5
  29. package/skills/wk-issue-update/SKILL.md +2 -0
  30. package/skills/wk-pr/SKILL.md +2 -0
  31. package/skills/wk-release-notes/SKILL.md +1 -1
  32. package/skills/wk-verify/SKILL.md +1 -1
  33. package/vendor/superpowers/skills/brainstorming/SKILL.md +159 -0
  34. package/vendor/superpowers/skills/brainstorming/scripts/frame-template.html +213 -0
  35. package/vendor/superpowers/skills/brainstorming/scripts/helper.js +167 -0
  36. package/vendor/superpowers/skills/brainstorming/scripts/server.cjs +723 -0
  37. package/vendor/superpowers/skills/brainstorming/spec-document-reviewer-prompt.md +49 -0
  38. package/vendor/superpowers/skills/brainstorming/visual-companion.md +222 -0
  39. package/vendor/superpowers/skills/dispatching-parallel-agents/SKILL.md +185 -0
  40. package/vendor/superpowers/skills/executing-plans/SKILL.md +70 -0
  41. package/vendor/superpowers/skills/finishing-a-development-branch/SKILL.md +241 -0
  42. package/vendor/superpowers/skills/receiving-code-review/SKILL.md +213 -0
  43. package/vendor/superpowers/skills/requesting-code-review/SKILL.md +103 -0
  44. package/vendor/superpowers/skills/requesting-code-review/code-reviewer.md +172 -0
  45. package/vendor/superpowers/skills/subagent-driven-development/SKILL.md +418 -0
  46. package/vendor/superpowers/skills/subagent-driven-development/implementer-prompt.md +139 -0
  47. package/vendor/superpowers/skills/subagent-driven-development/task-reviewer-prompt.md +188 -0
  48. package/vendor/superpowers/skills/systematic-debugging/CREATION-LOG.md +119 -0
  49. package/vendor/superpowers/skills/systematic-debugging/SKILL.md +296 -0
  50. package/vendor/superpowers/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  51. package/vendor/superpowers/skills/systematic-debugging/condition-based-waiting.md +115 -0
  52. package/vendor/superpowers/skills/systematic-debugging/defense-in-depth.md +122 -0
  53. package/vendor/superpowers/skills/systematic-debugging/root-cause-tracing.md +169 -0
  54. package/vendor/superpowers/skills/systematic-debugging/test-academic.md +14 -0
  55. package/vendor/superpowers/skills/systematic-debugging/test-pressure-1.md +58 -0
  56. package/vendor/superpowers/skills/systematic-debugging/test-pressure-2.md +68 -0
  57. package/vendor/superpowers/skills/systematic-debugging/test-pressure-3.md +69 -0
  58. package/vendor/superpowers/skills/test-driven-development/SKILL.md +371 -0
  59. package/vendor/superpowers/skills/test-driven-development/testing-anti-patterns.md +299 -0
  60. package/vendor/superpowers/skills/using-git-worktrees/SKILL.md +202 -0
  61. package/vendor/superpowers/skills/using-superpowers/SKILL.md +62 -0
  62. package/vendor/superpowers/skills/using-superpowers/references/antigravity-tools.md +23 -0
  63. package/vendor/superpowers/skills/using-superpowers/references/codex-tools.md +39 -0
  64. package/vendor/superpowers/skills/using-superpowers/references/pi-tools.md +16 -0
  65. package/vendor/superpowers/skills/verification-before-completion/SKILL.md +139 -0
  66. package/vendor/superpowers/skills/writing-plans/SKILL.md +174 -0
  67. package/vendor/superpowers/skills/writing-plans/plan-document-reviewer-prompt.md +49 -0
  68. package/vendor/superpowers/skills/writing-skills/SKILL.md +689 -0
  69. package/vendor/superpowers/skills/writing-skills/anthropic-best-practices.md +1150 -0
  70. package/vendor/superpowers/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
  71. package/vendor/superpowers/skills/writing-skills/graphviz-conventions.dot +172 -0
  72. package/vendor/superpowers/skills/writing-skills/persuasion-principles.md +187 -0
  73. package/vendor/superpowers/skills/writing-skills/testing-skills-with-subagents.md +384 -0
  74. package/hooks/session-start +0 -53
  75. package/marketplace.json +0 -10
  76. package/mcp/run-server.sh +0 -56
  77. package/mcp/server.ts +0 -1163
@@ -0,0 +1,351 @@
1
+ #!/usr/bin/env node
2
+
3
+ // packages/workit-cursor/hooks/session-start.ts
4
+ import { existsSync, readFileSync } from "node:fs";
5
+ import path2 from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+
8
+ // packages/workit-core/src/core/logger.ts
9
+ import { appendFileSync, mkdirSync, readdirSync, unlinkSync } from "node:fs";
10
+ import os from "node:os";
11
+ import path from "node:path";
12
+ var REDACTED = "[REDACTED]";
13
+ var DEFAULT_MAX_RATE = 20;
14
+ var DEFAULT_RATE_WINDOW_MS = 1000;
15
+ var DEFAULT_MAX_FIELD_LENGTH = 200;
16
+ var DEFAULT_MAX_STACK_LINES = 30;
17
+ var DAY_FILE = /^workit-\d{4}-\d{2}-\d{2}\.jsonl$/;
18
+ var RETAINED_DAYS = 7;
19
+ var SECRET_VALUE = /\b(?:Bearer|Basic|Digest|Token)\s+\S+/gi;
20
+ var KEY_EQ_VALUE = /\b([A-Za-z0-9_-]*(?:token|secret|password|passwd|apikey|api[_-]?key|authorization|credential|bearer)[A-Za-z0-9_-]*)([:=]\s*).+/gi;
21
+ var URL_QUERY = /(https?:\/\/[^?#\s]+)\?[^#\s]*/g;
22
+ var splitKey = (key) => key.split(/[_-]+|(?<=[a-z0-9])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/).map((word) => word.toLowerCase());
23
+ var SENSITIVE_WORDS = new Set([
24
+ "token",
25
+ "secret",
26
+ "password",
27
+ "passwd",
28
+ "authorization",
29
+ "credential",
30
+ "credentials",
31
+ "cookie",
32
+ "api",
33
+ "apikey",
34
+ "apitoken",
35
+ "accesstoken",
36
+ "clientsecret",
37
+ "refreshtoken",
38
+ "key",
39
+ "bearer",
40
+ "prompt",
41
+ "message",
42
+ "messages",
43
+ "content",
44
+ "body",
45
+ "args",
46
+ "argument",
47
+ "result",
48
+ "results",
49
+ "output",
50
+ "issue",
51
+ "description",
52
+ "summary",
53
+ "payload",
54
+ "script",
55
+ "command",
56
+ "text",
57
+ "query"
58
+ ]);
59
+ var STACK_WORDS = new Set(["stack", "stacktrace", "trace"]);
60
+ var escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
61
+ var resolveStateDir = () => {
62
+ const override = process.env.WORKFLOW_TOOLKIT_STATE;
63
+ if (override)
64
+ return override;
65
+ const home = os.homedir();
66
+ if (process.env.XDG_STATE_HOME)
67
+ return path.join(process.env.XDG_STATE_HOME, "workit");
68
+ switch (os.platform()) {
69
+ case "darwin":
70
+ return path.join(home, "Library", "Application Support", "workit");
71
+ case "win32":
72
+ return path.join(process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local"), "workit");
73
+ default:
74
+ return path.join(process.env.HOME ?? home, ".local", "state", "workit");
75
+ }
76
+ };
77
+ var homePattern = new RegExp(`${escapeRegExp(os.homedir())}(?=[/\\\\]|$)|\\$HOME(?=[/\\\\]|$)`, "g");
78
+ var applyPatterns = (value) => {
79
+ let out = value;
80
+ out = out.replace(SECRET_VALUE, REDACTED);
81
+ out = out.replace(KEY_EQ_VALUE, "$1$2[REDACTED]");
82
+ out = out.replace(URL_QUERY, "$1?[REDACTED]");
83
+ out = out.replace(homePattern, "~");
84
+ if (process.platform === "win32")
85
+ out = out.replace(/\\/g, "/");
86
+ return out;
87
+ };
88
+ var redactString = (value, options) => {
89
+ const out = applyPatterns(value);
90
+ if (out.length > options.maxFieldLength) {
91
+ return `${out.slice(0, options.maxFieldLength)}…`;
92
+ }
93
+ return out;
94
+ };
95
+ var boundStack = (value, options) => {
96
+ if (typeof value !== "string")
97
+ return redact(value, options);
98
+ const lines = value.split(`
99
+ `);
100
+ const kept = lines.slice(0, options.maxStackLines).map(applyPatterns);
101
+ const dropped = lines.length - kept.length;
102
+ const body = dropped > 0 ? [...kept, ` ... ${dropped} more`] : kept;
103
+ return body.join(`
104
+ `);
105
+ };
106
+ var redact = (value, options = DEFAULT_OPTIONS) => {
107
+ if (value === null || value === undefined)
108
+ return null;
109
+ if (typeof value === "boolean" || typeof value === "number")
110
+ return value;
111
+ if (typeof value === "string")
112
+ return redactString(value, options);
113
+ if (value instanceof Date)
114
+ return value.toISOString();
115
+ if (Array.isArray(value))
116
+ return value.map((entry) => redact(entry, options));
117
+ if (typeof value === "object") {
118
+ const out = {};
119
+ for (const [key, entry] of Object.entries(value)) {
120
+ const words = splitKey(key);
121
+ if (words.some((word) => STACK_WORDS.has(word)))
122
+ out[key] = boundStack(entry, options);
123
+ else if (words.some((word) => SENSITIVE_WORDS.has(word)))
124
+ out[key] = REDACTED;
125
+ else
126
+ out[key] = redact(entry, options);
127
+ }
128
+ return out;
129
+ }
130
+ return null;
131
+ };
132
+ var DEFAULT_OPTIONS = {
133
+ maxFieldLength: DEFAULT_MAX_FIELD_LENGTH,
134
+ maxStackLines: DEFAULT_MAX_STACK_LINES
135
+ };
136
+ var dailyFileName = (date) => {
137
+ const y = date.getFullYear();
138
+ const m = String(date.getMonth() + 1).padStart(2, "0");
139
+ const d = String(date.getDate()).padStart(2, "0");
140
+ return `workit-${y}-${m}-${d}.jsonl`;
141
+ };
142
+ var pruneOldFiles = (dir) => {
143
+ try {
144
+ const files = readdirSync(dir).filter((name) => DAY_FILE.test(name)).sort().reverse();
145
+ for (const file of files.slice(RETAINED_DAYS)) {
146
+ try {
147
+ unlinkSync(path.join(dir, file));
148
+ } catch {}
149
+ }
150
+ } catch {}
151
+ };
152
+ var createLogger = (options = {}) => {
153
+ const stateDir = options.stateDir ?? resolveStateDir();
154
+ const logDir = path.join(stateDir, "logs");
155
+ const now = options.now ?? (() => new Date);
156
+ const maxRate = options.maxRate ?? DEFAULT_MAX_RATE;
157
+ const rateWindowMs = options.rateWindowMs ?? DEFAULT_RATE_WINDOW_MS;
158
+ const redactOptions = {
159
+ maxFieldLength: options.maxFieldLength ?? DEFAULT_MAX_FIELD_LENGTH,
160
+ maxStackLines: options.maxStackLines ?? DEFAULT_MAX_STACK_LINES
161
+ };
162
+ let windowStart = 0;
163
+ const windowCounts = { debug: 0, info: 0, warn: 0, error: 0 };
164
+ const emit = (level, message, context) => {
165
+ const date = now();
166
+ const elapsed = date.getTime() - windowStart;
167
+ if (elapsed >= rateWindowMs || windowStart === 0) {
168
+ windowStart = date.getTime();
169
+ windowCounts.debug = 0;
170
+ windowCounts.info = 0;
171
+ windowCounts.warn = 0;
172
+ windowCounts.error = 0;
173
+ }
174
+ windowCounts[level] += 1;
175
+ if (windowCounts[level] > maxRate)
176
+ return;
177
+ let event = null;
178
+ try {
179
+ event = {
180
+ level,
181
+ time: date.toISOString(),
182
+ message: redactString(message, redactOptions),
183
+ context: redact(context ?? {}, redactOptions)
184
+ };
185
+ const line = `${JSON.stringify(event)}
186
+ `;
187
+ mkdirSync(logDir, { recursive: true, mode: 448 });
188
+ appendFileSync(path.join(logDir, dailyFileName(date)), line, { mode: 384 });
189
+ pruneOldFiles(logDir);
190
+ } catch {
191
+ try {
192
+ event = {
193
+ level,
194
+ time: date.toISOString(),
195
+ message: redactString(message, redactOptions),
196
+ context: { redaction_failed: true }
197
+ };
198
+ mkdirSync(logDir, { recursive: true, mode: 448 });
199
+ appendFileSync(path.join(logDir, dailyFileName(date)), `${JSON.stringify(event)}
200
+ `, {
201
+ mode: 384
202
+ });
203
+ } catch {}
204
+ }
205
+ for (const sink of [options.appLog, options.stderr]) {
206
+ if (!sink)
207
+ continue;
208
+ if (!event)
209
+ continue;
210
+ try {
211
+ sink(event);
212
+ } catch {}
213
+ }
214
+ };
215
+ return {
216
+ debug: (message, context) => emit("debug", message, context),
217
+ info: (message, context) => emit("info", message, context),
218
+ warn: (message, context) => emit("warn", message, context),
219
+ error: (message, context) => emit("error", message, context),
220
+ guard: (name, fn) => {
221
+ try {
222
+ return fn();
223
+ } catch (err) {
224
+ emit("warn", "detector_failed", {
225
+ detector: name,
226
+ error: err instanceof Error ? err.message : String(err)
227
+ });
228
+ return;
229
+ }
230
+ }
231
+ };
232
+ };
233
+
234
+ // packages/workit-core/src/core/boundary.ts
235
+ var EVENT = {
236
+ initialization: "initialization",
237
+ provenance: "provenance",
238
+ assets: "assets",
239
+ configurationSource: "configuration_source",
240
+ hooks: "hooks",
241
+ mcpConnection: "mcp_connection",
242
+ migration: "migration",
243
+ installSteps: "install_steps",
244
+ uncaughtFailure: "uncaught_failure",
245
+ toolsFailed: "tools_failed",
246
+ doctor: "doctor"
247
+ };
248
+ var errorDetail = (err) => {
249
+ if (err instanceof Error) {
250
+ return { error_name: err.name, error: err.message };
251
+ }
252
+ return { error_name: "unknown", error: String(err) };
253
+ };
254
+
255
+ // packages/workit-core/src/core/config.ts
256
+ var diagnosticLogger;
257
+ var setDiagnosticLogger = (logger) => {
258
+ diagnosticLogger = logger;
259
+ };
260
+ var PRESETS = {
261
+ gitflow: {
262
+ allowed: ["feature/*", "bugfix/*", "hotfix/*", "release/*"],
263
+ protected: ["main", "develop", "master", "prod", "production"]
264
+ },
265
+ "github-flow": { allowed: ["*"], protected: ["main"] },
266
+ "trunk-based": { allowed: ["*"], protected: ["main"] },
267
+ custom: { allowed: [], protected: [] }
268
+ };
269
+ var DEFAULTS = {
270
+ locale: "en",
271
+ localeOptions: ["en", "es-CL", "es-MX", "es-AR", "pt-BR"],
272
+ timezone: "America/Santiago",
273
+ branchPolicy: {
274
+ preset: "gitflow",
275
+ allowed: [...PRESETS.gitflow.allowed],
276
+ protected: [...PRESETS.gitflow.protected]
277
+ }
278
+ };
279
+
280
+ // packages/workit-cursor/hooks/session-start.ts
281
+ var logger = createLogger({
282
+ stderr: (event) => process.stderr.write(`${JSON.stringify(event)}
283
+ `)
284
+ });
285
+ var hookDir = path2.dirname(fileURLToPath(import.meta.url));
286
+ var pluginDir = path2.resolve(hookDir, "..");
287
+ var marker = path2.join(pluginDir, ".workflow-toolkit-root");
288
+ setDiagnosticLogger(logger);
289
+ logger.info(EVENT.initialization, { host: "cursor-hook", hook_dir: hookDir });
290
+ var resolveRepoRoot = () => {
291
+ if (process.env.WORKFLOW_TOOLKIT_ROOT && existsSync(path2.join(process.env.WORKFLOW_TOOLKIT_ROOT, "templates"))) {
292
+ return process.env.WORKFLOW_TOOLKIT_ROOT;
293
+ }
294
+ if (existsSync(marker)) {
295
+ return readFileSync(marker, "utf8").replace(/\n+$/, "");
296
+ }
297
+ const ownAssets = path2.join(pluginDir, "assets");
298
+ if (existsSync(path2.join(ownAssets, "templates"))) {
299
+ return ownAssets;
300
+ }
301
+ return path2.resolve(hookDir, "../../workit-core");
302
+ };
303
+ var body = null;
304
+ var repoRoot = resolveRepoRoot();
305
+ try {
306
+ const contract = path2.join(repoRoot, "templates", "superpowers-doc-contract.md");
307
+ if (existsSync(contract))
308
+ body = readFileSync(contract, "utf8");
309
+ } catch (err) {
310
+ logger.error(EVENT.hooks, { boundary: "session-start", root: repoRoot, ...errorDetail(err) });
311
+ body = null;
312
+ }
313
+ if (body === null) {
314
+ process.stdout.write(`{}
315
+ `);
316
+ process.exit(0);
317
+ }
318
+ var context = `<workflow-toolkit-askquestion-hard-gate>
319
+ HARD-GATE: Any user choice with options → call Cursor AskQuestion directly with workflow-specific copy. NEVER A/B/C in chat. Overrides Superpowers brainstorming conversational options.
320
+ </workflow-toolkit-askquestion-hard-gate>
321
+
322
+ <workflow-toolkit-visual-companion>
323
+ HARD-GATE: NEVER offer Superpowers visual companion or open a browser tab. For UI wireframes use workflow_present_ascii; for flows use workflow_present_flow. Overrides Superpowers brainstorming visual companion offer.
324
+ </workflow-toolkit-visual-companion>
325
+
326
+ <workflow-toolkit-no-worktrees>
327
+ HARD-GATE: NEVER using-git-worktrees or git worktree. In-place feature/* or bugfix/* checkout only via workflow_resolve_branch + workflow_branch_setup. Dirty tree → native AskQuestion before checkout.
328
+ </workflow-toolkit-no-worktrees>
329
+
330
+ <workflow-toolkit-sdd-path>
331
+ HARD-GATE: NEVER .superpowers/sdd. ALWAYS workflow_sdd_context with plan_path first — resolves canonical docs/<slug>/sdd/ and creates nothing (no empty ledger; progress.md appears only on the first confirmed append). workflow_sdd_task_brief, workflow_sdd_review_package, workflow_sdd_append_progress only.
332
+ </workflow-toolkit-sdd-path>
333
+
334
+ <workflow-toolkit-todowrite>
335
+ HARD-GATE: After workflow_sdd_context, call Cursor TodoWrite with returned todos (merge: false). SDD ledger is persistence — TodoWrite is the native task list UI. Keep in_progress/completed in sync each task.
336
+ </workflow-toolkit-todowrite>
337
+
338
+ <workflow-toolkit-superpowers-doc-contract>
339
+ ${body}
340
+ </workflow-toolkit-superpowers-doc-contract>
341
+
342
+ <workflow-toolkit-reminder>
343
+ HARD-GATE: Bounded user choices → call Cursor AskQuestion directly (never A/B/C or 1/2/3 lists in prose). After a plan is approved → AskQuestion menu with: Subagent-driven, Inline, Handoff (new session only), Review spec first, Review plan first. Tools with confirmed → call them; never fabricate results.
344
+ Delivering docs → clickable markdown link (docs/<slug>/spec.md) + 3-5 bullet summary.
345
+ </workflow-toolkit-reminder>`;
346
+ process.stdout.write(JSON.stringify({ additional_context: context }, null, 2) + `
347
+ `);
348
+ process.exit(0);
349
+ export {
350
+ logger
351
+ };