rbin-task-flow 1.19.5 → 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 +78 -10
  56. package/bin/cli.js +40 -25
  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 +83 -47
  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,8 +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
74
79
  rbin-task-flow reset # Reinstala o Task Flow do zero
80
+ rbin-task-flow reset --graphify # Reset + graphify extract (CLI Graphify no PATH)
75
81
  rbin-task-flow version-check # Verifica atualizações de modelos
76
82
  rbin-task-flow info # Mostra informações
77
83
  rbin-task-flow check # Roda lint/fix e build quando existirem
@@ -81,7 +87,21 @@ rbin-task-flow report <ids> # Gera relatório (ex: "1" ou "1,2" ou "all")
81
87
 
82
88
  ### Comandos da IA - Por Que Usar?
83
89
 
84
- 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.
85
105
 
86
106
  | Comando | Por Que Usar | Feature Principal |
87
107
  |---------|--------------|-------------------|
@@ -161,9 +181,10 @@ seu-projeto/
161
181
  │ │ ├── cursor_rules.mdc
162
182
  │ │ ├── self_improve.mdc
163
183
  │ │ ├── code_comments.mdc
164
- │ │ ├── commit_practices.mdc
165
- │ │ ├── git_control.mdc
166
- │ │ └── 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
167
188
  │ └── settings.json # Configurações do modelo Cursor
168
189
 
169
190
  ├── .claude/
@@ -256,6 +277,8 @@ rbin-task-flow update
256
277
 
257
278
  # Para reiniciar o Task Flow do zero, incluindo .task-flow/.internal
258
279
  rbin-task-flow reset
280
+ # Com grafo de código (requer graphify no PATH):
281
+ rbin-task-flow reset --graphify
259
282
 
260
283
  # Ou usando método legacy
261
284
  ~/.rbin-task-flow/install.sh
@@ -299,6 +322,17 @@ rbin-task-flow/
299
322
  └── README.md # Este arquivo
300
323
  ```
301
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
+
302
336
  ## Notas Importantes
303
337
 
304
338
  - ⚠️ Este é um **repositório template** - não use RBIN Task Flow aqui
@@ -384,6 +418,8 @@ Para problemas ou perguntas:
384
418
  <a id="english"></a>
385
419
  # 🇬🇧 English
386
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
+
387
423
  ## What Is This Project?
388
424
 
389
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.
@@ -421,8 +457,12 @@ rbin-task-flow init
421
457
 
422
458
  ```bash
423
459
  rbin-task-flow init # Initialize in current project
424
- 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
425
464
  rbin-task-flow reset # Reinstall Task Flow from scratch
465
+ rbin-task-flow reset --graphify # Reset + graphify extract (Graphify CLI on PATH)
426
466
  rbin-task-flow version-check # Check for model updates
427
467
  rbin-task-flow info # Show information
428
468
  rbin-task-flow check # Run lint/fix and build when available
@@ -432,7 +472,21 @@ rbin-task-flow report <ids> # Generate report (e.g., "1" or "1,2" or "all")
432
472
 
433
473
  ### AI Commands - Why Use Them?
434
474
 
435
- 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/`.
436
490
 
437
491
  | Command | Why Use It | Key Feature |
438
492
  |---------|------------|-------------|
@@ -512,9 +566,10 @@ your-project/
512
566
  │ │ ├── cursor_rules.mdc
513
567
  │ │ ├── self_improve.mdc
514
568
  │ │ ├── code_comments.mdc
515
- │ │ ├── commit_practices.mdc
516
- │ │ ├── git_control.mdc
517
- │ │ └── 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
518
573
  │ └── settings.json # Cursor model settings
519
574
 
520
575
  ├── .claude/
@@ -607,6 +662,8 @@ rbin-task-flow update
607
662
 
608
663
  # To reset Task Flow from scratch, including .task-flow/.internal
609
664
  rbin-task-flow reset
665
+ # With code knowledge graph (requires graphify on PATH):
666
+ rbin-task-flow reset --graphify
610
667
 
611
668
  # Or using legacy method
612
669
  ~/.rbin-task-flow/install.sh
@@ -650,6 +707,17 @@ rbin-task-flow/
650
707
  └── README.md # This file
651
708
  ```
652
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
+
653
721
  ## Important Notes
654
722
 
655
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,32 +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
- });
26
-
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
- });
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
+ }
35
51
 
36
- program
37
- .command('reset')
38
- .description('Reset RBIN Task Flow in current directory')
39
- .option('-p, --path <path>', 'Target directory (default: current directory)')
40
- .action(async (options) => {
41
- const targetPath = options.path || process.cwd();
42
- await installInProject(targetPath, { reset: true });
43
- });
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 });
44
55
 
45
56
  program
46
57
  .command('version-check')
@@ -99,8 +110,12 @@ program
99
110
  console.log(chalk.yellow('Repository:'), 'https://github.com/rbinoliveira/rbin-task-flow');
100
111
  console.log(chalk.yellow('\nCommands:'));
101
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)');
102
116
  console.log(chalk.cyan(' rbin-task-flow update') + ' - Update configurations');
103
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)');
104
119
  console.log(chalk.cyan(' rbin-task-flow version-check') + ' - Check for model updates');
105
120
  console.log(chalk.cyan(' rbin-task-flow estimate <ids>') + ' - Estimate time (e.g., "1" or "1,2" or "all")');
106
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
+ };