rbin-task-flow 1.19.4 → 1.23.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 (65) hide show
  1. package/.claude/skills/rbin-coding-standards/SKILL.md +29 -0
  2. package/.claude/skills/rbin-coding-standards/reference.md +42 -0
  3. package/.claude/skills/rbin-git/SKILL.md +39 -0
  4. package/.claude/skills/task-flow-audit/SKILL.md +15 -0
  5. package/.claude/skills/task-flow-check/SKILL.md +15 -0
  6. package/.claude/skills/task-flow-estimate/SKILL.md +15 -0
  7. package/.claude/skills/task-flow-generate-flow/SKILL.md +15 -0
  8. package/.claude/skills/task-flow-improve-changes/SKILL.md +15 -0
  9. package/.claude/skills/task-flow-refactor/SKILL.md +14 -0
  10. package/.claude/skills/task-flow-report/SKILL.md +15 -0
  11. package/.claude/skills/task-flow-review/SKILL.md +14 -0
  12. package/.claude/skills/task-flow-run/SKILL.md +28 -0
  13. package/.claude/skills/task-flow-run/workflow.md +59 -0
  14. package/.claude/skills/task-flow-status/SKILL.md +13 -0
  15. package/.claude/skills/task-flow-sync/SKILL.md +30 -0
  16. package/.claude/skills/task-flow-sync/workflow.md +57 -0
  17. package/.claude/skills/task-flow-think/SKILL.md +17 -0
  18. package/.codex/config.toml +10 -0
  19. package/.cursor/rules/code_comments.mdc +4 -4
  20. package/.cursor/rules/coding_standards.mdc +57 -810
  21. package/.cursor/rules/commit_practices.mdc +5 -138
  22. package/.cursor/rules/cursor_rules.mdc +4 -3
  23. package/.cursor/rules/git_control.mdc +5 -86
  24. package/.cursor/rules/graphify-task-flow.mdc +31 -0
  25. package/.cursor/rules/rbin-git-policy.mdc +47 -0
  26. package/.cursor/rules/self_improve.mdc +3 -3
  27. package/.cursor/rules/task-flow-cursor.mdc +51 -0
  28. package/.cursor/rules/task-flow-sync.mdc +46 -0
  29. package/.cursor/rules/task_analysis.mdc +31 -179
  30. package/.cursor/rules/task_audit.mdc +6 -5
  31. package/.cursor/rules/task_check.mdc +2 -3
  32. package/.cursor/rules/task_estimate.mdc +3 -4
  33. package/.cursor/rules/task_execution.mdc +26 -138
  34. package/.cursor/rules/task_generate_flow.mdc +2 -3
  35. package/.cursor/rules/task_generation.mdc +22 -140
  36. package/.cursor/rules/task_improve_changes.mdc +3 -4
  37. package/.cursor/rules/task_refactor.mdc +4 -5
  38. package/.cursor/rules/task_report.mdc +3 -4
  39. package/.cursor/rules/task_review.mdc +4 -5
  40. package/.cursor/rules/task_status.mdc +4 -4
  41. package/.cursor/rules/task_work.mdc +23 -210
  42. package/.task-flow/AI-PLATFORMS.md +104 -0
  43. package/.task-flow/CODEX.md +141 -0
  44. package/.task-flow/CURSOR.md +94 -0
  45. package/.task-flow/GRAPHIFY.md +112 -0
  46. package/.task-flow/OPTIMIZATION-IMPLEMENTATION-TASKS.md +365 -0
  47. package/.task-flow/OPTIMIZATION-PLAN.md +264 -0
  48. package/.task-flow/README.md +19 -4
  49. package/.task-flow/docs/coding-standards-full.md +851 -0
  50. package/.task-flow/platforms/claude-code.md +352 -0
  51. package/.task-flow/platforms/codex.md +379 -0
  52. package/.task-flow/platforms/cursor.md +333 -0
  53. package/AGENTS.md +69 -31
  54. package/CLAUDE.md +56 -48
  55. package/README.md +86 -10
  56. package/bin/cli.js +41 -16
  57. package/lib/codex.js +45 -0
  58. package/lib/cursor.js +41 -0
  59. package/lib/gitignore.js +101 -0
  60. package/lib/graphify.js +118 -0
  61. package/lib/install.js +106 -52
  62. package/lib/profiles.js +110 -0
  63. package/lib/skills.js +34 -0
  64. package/lib/utils.js +38 -2
  65. package/package.json +6 -2
package/README.md CHANGED
@@ -33,6 +33,8 @@
33
33
  <a id="português"></a>
34
34
  # 🇧🇷 Português
35
35
 
36
+ > **v1.23.0** — Menos tokens no Cursor (2 regras always-on, checklist de standards, skills). De **1.22**: `npm install -g rbin-task-flow@1.23` e `rbin-task-flow update`. [CHANGELOG](CHANGELOG.md) · [Publicação](RELEASE-1.23.0.md).
37
+
36
38
  ## O Que É Este Projeto?
37
39
 
38
40
  RBIN Task Flow é um sistema de gerenciamento de tarefas alimentado por IA que configura automaticamente Claude Code e Cursor IDE em qualquer projeto. Você define tarefas em texto simples e a IA gera subtarefas detalhadas e acionáveis automaticamente.
@@ -70,7 +72,12 @@ rbin-task-flow init
70
72
 
71
73
  ```bash
72
74
  rbin-task-flow init # Inicializa no projeto atual
73
- rbin-task-flow update # Atualiza configurações
75
+ rbin-task-flow init --profile minimal # 2 regras always-on + skills (menos tokens no Cursor)
76
+ rbin-task-flow init --share-ai-config # Versiona .cursor/skills/ e .cursor/rules/ no git (time)
77
+ rbin-task-flow update # Atualiza configurações (mantém profile em install-meta.json)
78
+ rbin-task-flow update --profile standard # Passa a copiar todas as regras .mdc
79
+ rbin-task-flow reset # Reinstala o Task Flow do zero
80
+ rbin-task-flow reset --graphify # Reset + graphify extract (CLI Graphify no PATH)
74
81
  rbin-task-flow version-check # Verifica atualizações de modelos
75
82
  rbin-task-flow info # Mostra informações
76
83
  rbin-task-flow check # Roda lint/fix e build quando existirem
@@ -80,7 +87,21 @@ rbin-task-flow report <ids> # Gera relatório (ex: "1" ou "1,2" ou "all")
80
87
 
81
88
  ### Comandos da IA - Por Que Usar?
82
89
 
83
- Após inicializar, use estes comandos na IA (Cursor/Claude) para gerenciar tarefas automaticamente:
90
+ Após inicializar, use estes comandos na IA (Cursor/Claude/Codex) para gerenciar tarefas automaticamente.
91
+
92
+ **Otimizar por plataforma:** [.task-flow/AI-PLATFORMS.md](.task-flow/AI-PLATFORMS.md) · [Claude](.task-flow/platforms/claude-code.md) · [Cursor](.task-flow/platforms/cursor.md) · [Codex](.task-flow/platforms/codex.md) · [Graphify](.task-flow/GRAPHIFY.md)
93
+
94
+ **Graphify (opcional):** `rbin-task-flow init --graphify` configura coexistência e pode rodar `graphify extract` (CLI via `rbin-install-dev`).
95
+
96
+ **Claude Code / Cursor skills (v1.20+):** `init` copia 14 skills para `.claude/skills/` e `.cursor/skills/` — use `/task-flow-sync`, `/task-flow-run`, etc.
97
+
98
+ **Codex (v1.21+):** `AGENTS.md` com sync/run embutidos, `.task-flow/CODEX.md` sob demanda, `.codex/config.toml` (64 KiB).
99
+
100
+ **Cursor (v1.23+):** `task-flow-cursor.mdc` + `rbin-git-policy.mdc` (2 always-on) + skills — ver `.task-flow/CURSOR.md`.
101
+
102
+ **Perfil minimal:** `init --profile minimal` instala só as 2 regras always-on e as 14 skills; workflows via `@task-flow-*` (sem `task_work`, `coding_standards` glob, etc.). `standard` (padrão) copia todas as regras `.cursor/rules/`.
103
+
104
+ **Compartilhar com o time:** `init --share-ai-config` não ignora `.cursor/skills/` nem `.cursor/rules/` no `.gitignore` (só `.cursor/settings.json` e overrides locais). Padrão: `.cursor/` inteiro ignorado — menos ruído no repo, config local por dev.
84
105
 
85
106
  | Comando | Por Que Usar | Feature Principal |
86
107
  |---------|--------------|-------------------|
@@ -160,9 +181,10 @@ seu-projeto/
160
181
  │ │ ├── cursor_rules.mdc
161
182
  │ │ ├── self_improve.mdc
162
183
  │ │ ├── code_comments.mdc
163
- │ │ ├── commit_practices.mdc
164
- │ │ ├── git_control.mdc
165
- │ │ └── task_execution.mdc
184
+ │ │ ├── rbin-git-policy.mdc # always-on (git + commits)
185
+ │ │ ├── git_control.mdc # legacy pointer
186
+ │ │ ├── commit_practices.mdc # legacy pointer
187
+ │ │ └── task_execution.mdc # command index stub
166
188
  │ └── settings.json # Configurações do modelo Cursor
167
189
 
168
190
  ├── .claude/
@@ -253,6 +275,11 @@ Para atualizar configurações em um projeto existente:
253
275
  cd /caminho/para/seu/projeto
254
276
  rbin-task-flow update
255
277
 
278
+ # Para reiniciar o Task Flow do zero, incluindo .task-flow/.internal
279
+ rbin-task-flow reset
280
+ # Com grafo de código (requer graphify no PATH):
281
+ rbin-task-flow reset --graphify
282
+
256
283
  # Ou usando método legacy
257
284
  ~/.rbin-task-flow/install.sh
258
285
  # Digite o caminho do projeto
@@ -295,6 +322,17 @@ rbin-task-flow/
295
322
  └── README.md # Este arquivo
296
323
  ```
297
324
 
325
+ ## Desenvolvimento (template / CI)
326
+
327
+ Regressão de tamanho das regras always-on (meta P0: ≤ ~5 KB):
328
+
329
+ ```bash
330
+ npm run measure:rules
331
+ # ou: node scripts/measure-rule-bytes.js --max-kb 5
332
+ ```
333
+
334
+ Lista cada `.cursor/rules/*.mdc` (bytes, linhas, `alwaysApply`), soma always-on vs demais e sai com código **1** se always-on exceder o limite (`--max-kb` ou `RBIN_MAX_ALWAYS_ON_KB`).
335
+
298
336
  ## Notas Importantes
299
337
 
300
338
  - ⚠️ Este é um **repositório template** - não use RBIN Task Flow aqui
@@ -380,6 +418,8 @@ Para problemas ou perguntas:
380
418
  <a id="english"></a>
381
419
  # 🇬🇧 English
382
420
 
421
+ > **v1.23.0** — Lower Cursor token use (2 always-on rules, standards checklist, skills). From **1.22**: `npm install -g rbin-task-flow@1.23` then `rbin-task-flow update`. [CHANGELOG](CHANGELOG.md) · [Release guide](RELEASE-1.23.0.md).
422
+
383
423
  ## What Is This Project?
384
424
 
385
425
  RBIN Task Flow is an AI-powered task management system that automatically configures Claude Code and Cursor IDE in any project. You define tasks in plain text and the AI automatically generates detailed, actionable subtasks.
@@ -417,7 +457,12 @@ rbin-task-flow init
417
457
 
418
458
  ```bash
419
459
  rbin-task-flow init # Initialize in current project
420
- rbin-task-flow update # Update configurations
460
+ rbin-task-flow init --profile minimal # 2 always-on rules + skills only (lower Cursor token cost)
461
+ rbin-task-flow init --share-ai-config # Commit .cursor/skills and rules with the team
462
+ rbin-task-flow update # Update configs (keeps profile from .task-flow/install-meta.json)
463
+ rbin-task-flow update --profile standard # Install all .cursor/rules/*.mdc
464
+ rbin-task-flow reset # Reinstall Task Flow from scratch
465
+ rbin-task-flow reset --graphify # Reset + graphify extract (Graphify CLI on PATH)
421
466
  rbin-task-flow version-check # Check for model updates
422
467
  rbin-task-flow info # Show information
423
468
  rbin-task-flow check # Run lint/fix and build when available
@@ -427,7 +472,21 @@ rbin-task-flow report <ids> # Generate report (e.g., "1" or "1,2" or "all")
427
472
 
428
473
  ### AI Commands - Why Use Them?
429
474
 
430
- After initializing, use these commands in your AI (Cursor/Claude) to automatically manage tasks:
475
+ After initializing, use these commands in your AI (Cursor/Claude/Codex) to automatically manage tasks.
476
+
477
+ **Per-platform optimization:** [index](.task-flow/AI-PLATFORMS.md) · [Claude](.task-flow/platforms/claude-code.md) · [Cursor](.task-flow/platforms/cursor.md) · [Codex](.task-flow/platforms/codex.md) · [Graphify](.task-flow/GRAPHIFY.md)
478
+
479
+ **Graphify (optional):** `rbin-task-flow init --graphify` — cooperative setup + optional `graphify extract` (CLI from `rbin-install-dev`).
480
+
481
+ **Claude / Cursor skills (v1.20+):** installs 14 skills — use `/task-flow-sync`, `/task-flow-run`, etc.
482
+
483
+ **Codex (v1.21+):** optimized `AGENTS.md`, `.task-flow/CODEX.md`, `.codex/config.toml`.
484
+
485
+ **Cursor (v1.23+):** 2 always-on rules + 14 skills — `@task-flow-sync`, `@task-flow-run`.
486
+
487
+ **Minimal profile:** `init --profile minimal` copies only `task-flow-cursor.mdc` and `rbin-git-policy.mdc` plus skills; use `@task-flow-*` for workflows. `standard` (default) copies all rules under `.cursor/rules/`.
488
+
489
+ **Share with team:** `init --share-ai-config` leaves `.cursor/skills/` and `.cursor/rules/` out of `.gitignore` (see comment block in `.gitignore` for token vs team trade-off). Default ignores all of `.cursor/`.
431
490
 
432
491
  | Command | Why Use It | Key Feature |
433
492
  |---------|------------|-------------|
@@ -507,9 +566,10 @@ your-project/
507
566
  │ │ ├── cursor_rules.mdc
508
567
  │ │ ├── self_improve.mdc
509
568
  │ │ ├── code_comments.mdc
510
- │ │ ├── commit_practices.mdc
511
- │ │ ├── git_control.mdc
512
- │ │ └── task_execution.mdc
569
+ │ │ ├── rbin-git-policy.mdc # always-on (git + commits)
570
+ │ │ ├── git_control.mdc # legacy pointer
571
+ │ │ ├── commit_practices.mdc # legacy pointer
572
+ │ │ └── task_execution.mdc # command index stub
513
573
  │ └── settings.json # Cursor model settings
514
574
 
515
575
  ├── .claude/
@@ -600,6 +660,11 @@ To update configs in an existing project:
600
660
  cd /path/to/your/project
601
661
  rbin-task-flow update
602
662
 
663
+ # To reset Task Flow from scratch, including .task-flow/.internal
664
+ rbin-task-flow reset
665
+ # With code knowledge graph (requires graphify on PATH):
666
+ rbin-task-flow reset --graphify
667
+
603
668
  # Or using legacy method
604
669
  ~/.rbin-task-flow/install.sh
605
670
  # Enter the project path
@@ -642,6 +707,17 @@ rbin-task-flow/
642
707
  └── README.md # This file
643
708
  ```
644
709
 
710
+ ## Development (template / CI)
711
+
712
+ Always-on rule size regression (P0 target: ≤ ~5 KB):
713
+
714
+ ```bash
715
+ npm run measure:rules
716
+ # or: node scripts/measure-rule-bytes.js --max-kb 5
717
+ ```
718
+
719
+ Prints each `.cursor/rules/*.mdc` (bytes, lines, `alwaysApply`), totals always-on vs other, exits **1** if always-on exceeds the limit (`--max-kb` or `RBIN_MAX_ALWAYS_ON_KB`).
720
+
645
721
  ## Important Notes
646
722
 
647
723
  - ⚠️ This is a **template repository** - don't use RBIN Task Flow here
package/bin/cli.js CHANGED
@@ -3,6 +3,7 @@
3
3
  const { program } = require('commander');
4
4
  const path = require('path');
5
5
  const { installInProject } = require('../lib/install');
6
+ const { parseProfileOption } = require('../lib/profiles');
6
7
  const { checkVersionUpdates } = require('../lib/version');
7
8
  const { estimateTask } = require('../lib/estimate');
8
9
  const { generateReport } = require('../lib/report');
@@ -15,23 +16,42 @@ program
15
16
  .description('AI-powered task management for Claude and Cursor')
16
17
  .version(require('../package.json').version);
17
18
 
18
- program
19
- .command('init')
20
- .description('Initialize RBIN Task Flow in current directory')
21
- .option('-p, --path <path>', 'Target directory (default: current directory)')
22
- .action(async (options) => {
23
- const targetPath = options.path || process.cwd();
24
- await installInProject(targetPath);
25
- });
19
+ function addInstallCommand(name, description, extra = {}) {
20
+ program
21
+ .command(name)
22
+ .description(description)
23
+ .option('-p, --path <path>', 'Target directory (default: current directory)')
24
+ .option('-g, --graphify', 'Run graphify extract after install (requires graphify CLI)')
25
+ .option(
26
+ '--profile <profile>',
27
+ 'Cursor rules: minimal (2 always-on + skills) or standard (all rules); update without flag keeps .task-flow/install-meta.json'
28
+ )
29
+ .option(
30
+ '--share-ai-config',
31
+ 'Do not gitignore .cursor/skills/ or .cursor/rules/ (team can commit shared AI config; see .gitignore comment)'
32
+ )
33
+ .action(async (options) => {
34
+ const targetPath = options.path || process.cwd();
35
+ try {
36
+ const profile =
37
+ options.profile !== undefined ? parseProfileOption(options.profile) : undefined;
38
+ const shareAiConfig = options.shareAiConfig ? true : undefined;
39
+ await installInProject(targetPath, {
40
+ ...extra,
41
+ graphify: options.graphify,
42
+ profile,
43
+ shareAiConfig,
44
+ });
45
+ } catch (error) {
46
+ console.error(chalk.red('\n' + error.message + '\n'));
47
+ process.exit(1);
48
+ }
49
+ });
50
+ }
26
51
 
27
- program
28
- .command('update')
29
- .description('Update RBIN Task Flow in current directory')
30
- .option('-p, --path <path>', 'Target directory (default: current directory)')
31
- .action(async (options) => {
32
- const targetPath = options.path || process.cwd();
33
- await installInProject(targetPath, { update: true });
34
- });
52
+ addInstallCommand('init', 'Initialize RBIN Task Flow in current directory');
53
+ addInstallCommand('update', 'Update RBIN Task Flow in current directory', { update: true });
54
+ addInstallCommand('reset', 'Reset RBIN Task Flow in current directory', { reset: true });
35
55
 
36
56
  program
37
57
  .command('version-check')
@@ -90,7 +110,12 @@ program
90
110
  console.log(chalk.yellow('Repository:'), 'https://github.com/rbinoliveira/rbin-task-flow');
91
111
  console.log(chalk.yellow('\nCommands:'));
92
112
  console.log(chalk.cyan(' rbin-task-flow init') + ' - Initialize in current directory');
113
+ console.log(chalk.cyan(' rbin-task-flow init --profile minimal') + ' - Low-token install (2 always-on rules + skills)');
114
+ console.log(chalk.cyan(' rbin-task-flow init --share-ai-config') + ' - Version .cursor/skills and rules in git');
115
+ console.log(chalk.cyan(' rbin-task-flow init --graphify') + ' - Init + graphify extract (if CLI installed)');
93
116
  console.log(chalk.cyan(' rbin-task-flow update') + ' - Update configurations');
117
+ console.log(chalk.cyan(' rbin-task-flow reset') + ' - Reset task flow files from scratch');
118
+ console.log(chalk.cyan(' rbin-task-flow reset --graphify') + ' - Reset + graphify extract (if CLI installed)');
94
119
  console.log(chalk.cyan(' rbin-task-flow version-check') + ' - Check for model updates');
95
120
  console.log(chalk.cyan(' rbin-task-flow estimate <ids>') + ' - Estimate time (e.g., "1" or "1,2" or "all")');
96
121
  console.log(chalk.cyan(' rbin-task-flow report <ids>') + ' - Generate report (e.g., "1" or "1,2" or "all")');
package/lib/codex.js ADDED
@@ -0,0 +1,45 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const { showSuccess, showInfo, showWarning } = require('./utils');
4
+
5
+ const TEMPLATE_DIR = path.join(__dirname, '..');
6
+ const CODEX_CONFIG_SRC = path.join(TEMPLATE_DIR, '.codex', 'config.toml');
7
+
8
+ async function setupCodexIntegration(targetPath, options = {}) {
9
+ const codexDir = path.join(targetPath, '.codex');
10
+ const configDest = path.join(codexDir, 'config.toml');
11
+
12
+ await fs.ensureDir(codexDir);
13
+
14
+ const force = options.forceCodexConfig === true;
15
+ if (!fs.existsSync(configDest) || force) {
16
+ if (fs.existsSync(CODEX_CONFIG_SRC)) {
17
+ await fs.copy(CODEX_CONFIG_SRC, configDest, { overwrite: force });
18
+ showSuccess('Codex config (.codex/config.toml — project_doc_max_bytes)');
19
+ }
20
+ } else {
21
+ showInfo('Codex config preserved (.codex/config.toml already exists)');
22
+ }
23
+
24
+ const codexWorkflows = path.join(targetPath, '.task-flow', 'CODEX.md');
25
+ if (fs.existsSync(codexWorkflows)) {
26
+ showInfo('Codex workflows: .task-flow/CODEX.md (read on demand)');
27
+ }
28
+
29
+ showInfo('Codex entry: AGENTS.md — embedded sync/run + command table');
30
+ showInfo('Verify: codex --ask-for-approval never "Summarize RBIN Task Flow instructions."');
31
+
32
+ const agentsPath = path.join(targetPath, 'AGENTS.md');
33
+ if (fs.existsSync(agentsPath)) {
34
+ const size = fs.statSync(agentsPath).size;
35
+ if (size > 28 * 1024) {
36
+ showWarning(
37
+ `AGENTS.md is ${Math.round(size / 1024)} KiB — may truncate with default 32 KiB; .codex/config.toml raises limit`
38
+ );
39
+ }
40
+ }
41
+
42
+ return true;
43
+ }
44
+
45
+ module.exports = { setupCodexIntegration };
package/lib/cursor.js ADDED
@@ -0,0 +1,41 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const { showSuccess, showInfo } = require('./utils');
4
+
5
+ async function setupCursorIntegration(targetPath, options = {}) {
6
+ const profile = options.profile || 'standard';
7
+ const skillsDir = path.join(targetPath, '.cursor', 'skills');
8
+ const cursorMd = path.join(targetPath, '.task-flow', 'CURSOR.md');
9
+ const coreRule = path.join(targetPath, '.cursor', 'rules', 'task-flow-cursor.mdc');
10
+
11
+ if (fs.existsSync(coreRule)) {
12
+ showSuccess('Cursor bootstrap rule (task-flow-cursor.mdc — always on)');
13
+ }
14
+
15
+ if (fs.existsSync(skillsDir)) {
16
+ const count = (await fs.readdir(skillsDir)).filter((name) =>
17
+ fs.statSync(path.join(skillsDir, name)).isDirectory()
18
+ ).length;
19
+ showInfo(`Cursor skills: ${count} in .cursor/skills/ — use @task-flow-run, @task-flow-sync, …`);
20
+ }
21
+
22
+ if (fs.existsSync(cursorMd)) {
23
+ showInfo('Cursor guide: .task-flow/CURSOR.md');
24
+ }
25
+
26
+ const gitPolicy = path.join(targetPath, '.cursor', 'rules', 'rbin-git-policy.mdc');
27
+ if (fs.existsSync(gitPolicy)) {
28
+ showSuccess('Git policy (rbin-git-policy.mdc — always on)');
29
+ }
30
+
31
+ if (profile === 'minimal') {
32
+ showInfo('Minimal profile: 2 always-on rules; workflows via @task-flow-* skills only');
33
+ showInfo('Full rules: rbin-task-flow update --profile standard');
34
+ } else {
35
+ showInfo('Rules: 2 always-on + intelligent/glob rules; prefer @task-flow-* skills for workflows');
36
+ }
37
+
38
+ return true;
39
+ }
40
+
41
+ module.exports = { setupCursorIntegration };
@@ -0,0 +1,101 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+
4
+ const MARKER_START = '# RBIN Task Flow (rbin-task-flow)';
5
+ const MARKER_END = '# END RBIN Task Flow (rbin-task-flow)';
6
+
7
+ const ENTRIES_DEFAULT = [
8
+ '.claude/',
9
+ '.cursor/',
10
+ '.task-flow/',
11
+ 'graphify-out/',
12
+ 'CLAUDE.md',
13
+ 'AGENTS.md',
14
+ ];
15
+
16
+ const ENTRIES_SHARE_AI_CONFIG = [
17
+ '.claude/',
18
+ '.cursor/settings.json',
19
+ '.cursor/rules/*.local.mdc',
20
+ '.task-flow/',
21
+ 'graphify-out/',
22
+ 'CLAUDE.md',
23
+ 'AGENTS.md',
24
+ ];
25
+
26
+ const STRIP_PATTERNS = [
27
+ ...ENTRIES_DEFAULT,
28
+ ...ENTRIES_SHARE_AI_CONFIG,
29
+ MARKER_START,
30
+ MARKER_END,
31
+ '# share-ai-config:',
32
+ '# Trade-off:',
33
+ '# Default (no flag):',
34
+ ];
35
+
36
+ function escapeRegExp(value) {
37
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
38
+ }
39
+
40
+ function stripRbinGitignoreBlock(content) {
41
+ let next = content;
42
+
43
+ const blockRegex = new RegExp(
44
+ `\\n?${escapeRegExp(MARKER_START)}[\\s\\S]*?${escapeRegExp(MARKER_END)}\\n?`,
45
+ 'g'
46
+ );
47
+ next = next.replace(blockRegex, '\n');
48
+
49
+ for (const entry of STRIP_PATTERNS) {
50
+ const lineRegex = new RegExp(`^${escapeRegExp(entry)}\\s*$`, 'gm');
51
+ next = next.replace(lineRegex, '');
52
+ }
53
+
54
+ return next.replace(/\n{3,}/g, '\n\n');
55
+ }
56
+
57
+ function buildRbinGitignoreBlock(shareAiConfig) {
58
+ const lines = ['', MARKER_START, ''];
59
+
60
+ if (shareAiConfig) {
61
+ lines.push(
62
+ '# share-ai-config: .cursor/skills/ and .cursor/rules/ are NOT ignored — commit them for team consistency.',
63
+ '# Trade-off: shared AI config improves workflow parity; each developer still pays token cost when the Agent loads rules/skills.',
64
+ '# Default (no flag): entire .cursor/ stays local and gitignored — lower repo noise, no team sync of rules.',
65
+ ''
66
+ );
67
+ lines.push(...ENTRIES_SHARE_AI_CONFIG);
68
+ } else {
69
+ lines.push(...ENTRIES_DEFAULT);
70
+ }
71
+
72
+ lines.push(MARKER_END, '');
73
+ return lines.join('\n');
74
+ }
75
+
76
+ async function updateGitignore(targetPath, { shareAiConfig = false } = {}) {
77
+ const gitignorePath = path.join(targetPath, '.gitignore');
78
+
79
+ if (!fs.existsSync(gitignorePath)) {
80
+ await fs.writeFile(gitignorePath, '');
81
+ }
82
+
83
+ let content = await fs.readFile(gitignorePath, 'utf8');
84
+ content = stripRbinGitignoreBlock(content);
85
+
86
+ if (!content.endsWith('\n')) {
87
+ content += '\n';
88
+ }
89
+
90
+ content += buildRbinGitignoreBlock(shareAiConfig);
91
+ await fs.writeFile(gitignorePath, content);
92
+
93
+ return { shareAiConfig };
94
+ }
95
+
96
+ module.exports = {
97
+ MARKER_START,
98
+ buildRbinGitignoreBlock,
99
+ stripRbinGitignoreBlock,
100
+ updateGitignore,
101
+ };
@@ -0,0 +1,118 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const { spawnSync } = require('child_process');
4
+ const { showSuccess, showWarning, showInfo } = require('./utils');
5
+
6
+ const GRAPHIFY_OUT = 'graphify-out/';
7
+ const UPSTREAM_GRAPHIFY_RULE = 'graphify.mdc';
8
+
9
+ function graphifyCliAvailable() {
10
+ const result = spawnSync('graphify', ['--help'], {
11
+ encoding: 'utf8',
12
+ stdio: ['ignore', 'pipe', 'pipe'],
13
+ });
14
+ return result.status === 0 || result.status === 1;
15
+ }
16
+
17
+ function demoteUpstreamGraphifyRule(targetPath) {
18
+ const rulePath = path.join(targetPath, '.cursor', 'rules', UPSTREAM_GRAPHIFY_RULE);
19
+ if (!fs.existsSync(rulePath)) {
20
+ return false;
21
+ }
22
+
23
+ let content = fs.readFileSync(rulePath, 'utf8');
24
+ const hadAlwaysApply = /alwaysApply:\s*true/i.test(content);
25
+
26
+ if (!hadAlwaysApply) {
27
+ return false;
28
+ }
29
+
30
+ content = content.replace(/alwaysApply:\s*true/gi, 'alwaysApply: false');
31
+
32
+ if (!content.includes('RBIN Task Flow')) {
33
+ const notice = [
34
+ '',
35
+ '- **RBIN Task Flow:** This file was set to `alwaysApply: false` by `rbin-task-flow` to avoid competing with Task Flow rules. Use [.cursor/rules/graphify-task-flow.mdc](mdc:.cursor/rules/graphify-task-flow.mdc) and [.task-flow/GRAPHIFY.md](mdc:.task-flow/GRAPHIFY.md) instead.',
36
+ '',
37
+ ].join('\n');
38
+ content = content.trimEnd() + notice;
39
+ }
40
+
41
+ fs.writeFileSync(rulePath, content);
42
+ return true;
43
+ }
44
+
45
+ function ensureGraphifyGitignore(targetPath) {
46
+ const gitignorePath = path.join(targetPath, '.gitignore');
47
+ if (!fs.existsSync(gitignorePath)) {
48
+ return false;
49
+ }
50
+
51
+ let content = fs.readFileSync(gitignorePath, 'utf8');
52
+ const entry = GRAPHIFY_OUT.replace(/\/$/, '');
53
+ const linePattern = new RegExp(`^${entry}\\/?$`, 'm');
54
+
55
+ if (linePattern.test(content)) {
56
+ return false;
57
+ }
58
+
59
+ if (!content.endsWith('\n')) {
60
+ content += '\n';
61
+ }
62
+ content += `\n${entry}/\n`;
63
+ fs.writeFileSync(gitignorePath, content);
64
+ return true;
65
+ }
66
+
67
+ function runGraphifyExtract(targetPath) {
68
+ if (!graphifyCliAvailable()) {
69
+ showWarning('Graphify CLI not found — skip extract (install via rbin-install-dev Graphify module)');
70
+ return false;
71
+ }
72
+
73
+ showInfo('Running graphify extract (may take a few minutes)...');
74
+ const result = spawnSync('graphify', ['extract', '.'], {
75
+ cwd: targetPath,
76
+ encoding: 'utf8',
77
+ stdio: 'inherit',
78
+ });
79
+
80
+ if (result.status !== 0) {
81
+ showWarning('graphify extract failed — you can run it later: graphify extract .');
82
+ return false;
83
+ }
84
+
85
+ showSuccess('Graphify knowledge graph (graphify-out/)');
86
+ return true;
87
+ }
88
+
89
+ async function setupGraphifyIntegration(targetPath, options = {}) {
90
+ const demoted = demoteUpstreamGraphifyRule(targetPath);
91
+ if (demoted) {
92
+ showSuccess('Graphify upstream rule demoted (alwaysApply: false) — Task Flow keeps priority');
93
+ }
94
+
95
+ const gitignoreUpdated = ensureGraphifyGitignore(targetPath);
96
+ if (gitignoreUpdated) {
97
+ showSuccess('graphify-out/ added to .gitignore');
98
+ }
99
+
100
+ if (options.extract) {
101
+ runGraphifyExtract(targetPath);
102
+ } else if (graphifyCliAvailable()) {
103
+ const graphJson = path.join(targetPath, 'graphify-out', 'graph.json');
104
+ if (!fs.existsSync(graphJson)) {
105
+ showInfo('Graphify CLI detected — run: graphify extract . (or: rbin-task-flow init --graphify)');
106
+ }
107
+ }
108
+
109
+ showInfo('Graphify + Task Flow guide: .task-flow/GRAPHIFY.md');
110
+ }
111
+
112
+ module.exports = {
113
+ setupGraphifyIntegration,
114
+ demoteUpstreamGraphifyRule,
115
+ ensureGraphifyGitignore,
116
+ runGraphifyExtract,
117
+ graphifyCliAvailable,
118
+ };