@event4u/agent-config 1.39.0 → 1.40.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 (45) hide show
  1. package/.agent-src/commands/orchestrate.md +123 -0
  2. package/.agent-src/commands/sync-gitignore/fix.md +135 -0
  3. package/.agent-src/commands/sync-gitignore.md +31 -5
  4. package/.agent-src/skills/learning-to-rule-or-skill/SKILL.md +30 -2
  5. package/.agent-src/skills/subagent-orchestration/SKILL.md +9 -0
  6. package/.agent-src/skills/using-git-worktrees/SKILL.md +25 -0
  7. package/.agent-src/templates/agent-settings.md +9 -0
  8. package/.agent-src/templates/scripts/work_engine/orchestration.py +168 -0
  9. package/.claude-plugin/marketplace.json +3 -1
  10. package/CHANGELOG.md +42 -0
  11. package/README.md +5 -5
  12. package/bin/install.php +13 -6
  13. package/config/agent-settings.template.yml +21 -0
  14. package/docs/DISTRIBUTION_CHECKLIST.md +169 -0
  15. package/docs/architecture.md +1 -1
  16. package/docs/catalog.md +3 -2
  17. package/docs/contracts/audit-log-v1.md +142 -0
  18. package/docs/contracts/command-clusters.md +2 -0
  19. package/docs/contracts/file-ownership-matrix.json +20 -0
  20. package/docs/contracts/orchestration-dsl-v1.md +152 -0
  21. package/docs/getting-started.md +1 -1
  22. package/docs/installation.md +132 -0
  23. package/docs/setup/per-ide/aider.md +48 -0
  24. package/docs/setup/per-ide/claude-code.md +108 -0
  25. package/docs/setup/per-ide/claude-desktop.md +148 -0
  26. package/docs/setup/per-ide/cline.md +43 -0
  27. package/docs/setup/per-ide/codex.md +46 -0
  28. package/docs/setup/per-ide/copilot.md +80 -0
  29. package/docs/setup/per-ide/cursor.md +125 -0
  30. package/docs/setup/per-ide/gemini-cli.md +45 -0
  31. package/docs/setup/per-ide/windsurf.md +120 -0
  32. package/package.json +1 -1
  33. package/scripts/compress.py +153 -1
  34. package/scripts/extract_audit_patterns.py +202 -0
  35. package/scripts/install +156 -1
  36. package/scripts/install.py +270 -10
  37. package/scripts/install.sh +52 -7
  38. package/scripts/lint_orchestration_dsl.py +214 -0
  39. package/scripts/skill_linter.py +9 -0
  40. package/scripts/sync_gitignore.py +56 -1
  41. package/templates/claude_desktop_config.json.template +21 -0
  42. package/templates/cursor-rule.mdc.j2 +7 -0
  43. package/templates/global-install-manifest.yml +91 -0
  44. package/templates/marketing-copy.yml +64 -0
  45. package/templates/windsurf-rule.md.j2 +7 -0
@@ -0,0 +1,46 @@
1
+ # OpenAI Codex CLI Setup
2
+
3
+ OpenAI's Codex CLI (the `codex` command) reads `AGENTS.md` from the
4
+ repo root for project context.
5
+
6
+ ## Prerequisites
7
+
8
+ - Codex CLI installed: <https://github.com/openai/codex>.
9
+ - Node.js ≥ 18 (for the install entrypoints).
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npx @event4u/create-agent-config init --tools=codex
15
+ ```
16
+
17
+ Populates:
18
+
19
+ - `AGENTS.md` — agent self-orientation (Codex auto-loads)
20
+ - `.agent-settings.yml` — per-project knobs
21
+
22
+ Codex CLI reads `AGENTS.md` automatically when invoked from the repo
23
+ root. No additional configuration needed.
24
+
25
+ ## Verification
26
+
27
+ ```bash
28
+ test -f AGENTS.md
29
+ codex --help # confirm CLI installed
30
+ ```
31
+
32
+ In a Codex CLI session, the loaded `AGENTS.md` content informs every
33
+ turn — verify by asking *"what is this repo?"* and confirming the
34
+ answer matches `AGENTS.md`'s emergency-triage block.
35
+
36
+ ## Troubleshooting
37
+
38
+ | Symptom | Fix |
39
+ |---|---|
40
+ | Codex ignores `AGENTS.md` | Run from repo root, not a subdirectory. |
41
+ | Out-of-date context | `codex` re-reads on each session start — quit and restart. |
42
+
43
+ ## Cross-references
44
+
45
+ - [`AGENTS.md`](../../../AGENTS.md) — canonical agent self-orientation.
46
+ - [`docs/installation.md`](../../installation.md) — install matrix index.
@@ -0,0 +1,80 @@
1
+ # GitHub Copilot Setup
2
+
3
+ GitHub Copilot Chat (VS Code, JetBrains, Neovim, `gh copilot` CLI)
4
+ reads `.github/copilot-instructions.md` for project-level guidance and
5
+ falls back to `AGENTS.md` where supported.
6
+
7
+ ## Prerequisites
8
+
9
+ - GitHub Copilot subscription (Individual, Business, or Enterprise).
10
+ - Copilot Chat enabled in your IDE.
11
+ - Node.js ≥ 18 for the install entrypoints.
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ npx @event4u/create-agent-config init --tools=copilot
17
+ ```
18
+
19
+ Populates:
20
+
21
+ - `.github/copilot-instructions.md` — Copilot's project-level prompt
22
+ - `AGENTS.md` — canonical agent self-orientation
23
+ - `.agent-settings.yml` — per-project knobs
24
+
25
+ The package keeps `.github/copilot-instructions.md` deliberately thin
26
+ (it points back to `AGENTS.md`) so all surfaces share a single source
27
+ of truth.
28
+
29
+ ## VS Code Copilot Chat
30
+
31
+ Auto-loads `.github/copilot-instructions.md` once you reload the VS
32
+ Code window after install. Verify in the Copilot Chat panel —
33
+ *"What is this repo?"* should answer using the AGENTS.md emergency
34
+ triage block.
35
+
36
+ ## JetBrains Copilot
37
+
38
+ JetBrains Copilot 1.5+ reads the same `.github/copilot-instructions.md`
39
+ file. No extra steps; reload the project after install.
40
+
41
+ ## Neovim Copilot
42
+
43
+ `copilot.lua` and `CopilotChat.nvim` honor
44
+ `.github/copilot-instructions.md`. No extra config needed.
45
+
46
+ ## `gh copilot` CLI
47
+
48
+ The `gh copilot` plugin (`gh extension install github/gh-copilot`)
49
+ reads the repo context including `AGENTS.md` and
50
+ `.github/copilot-instructions.md` when invoked from the repo root.
51
+
52
+ ## Suppressing Copilot PR review noise
53
+
54
+ Copilot's PR auto-review can flag the package's own kernel rules as
55
+ "unusual phrasing". The package ships a Copilot-suppression rule
56
+ ([`augment-portability`](../../../.augment/rules/augment-portability.md))
57
+ that documents this trade-off.
58
+
59
+ ## Verification
60
+
61
+ ```bash
62
+ test -f .github/copilot-instructions.md
63
+ test -f AGENTS.md
64
+ gh copilot --version # if you want CLI plugin
65
+ ```
66
+
67
+ ## Troubleshooting
68
+
69
+ | Symptom | Fix |
70
+ |---|---|
71
+ | Copilot ignores the file | Reload the IDE window after install. |
72
+ | File missing after install | Re-run `npx @event4u/create-agent-config init --tools=copilot`. |
73
+ | Copilot PR review too noisy | See the `copilot-config` skill for suppression patterns. |
74
+
75
+ ## Cross-references
76
+
77
+ - [`AGENTS.md`](../../../AGENTS.md) — canonical agent self-orientation.
78
+ - [`.augment/skills/copilot-config/SKILL.md`](../../../.augment/skills/copilot-config/SKILL.md)
79
+ — tuning Copilot output and suppressing review noise.
80
+ - [`docs/installation.md`](../../installation.md) — install matrix index.
@@ -0,0 +1,125 @@
1
+ # Cursor Setup
2
+
3
+ Cursor reads two rule formats:
4
+
5
+ - **Modern (`.mdc`)** — `.cursor/rules/<rule>.mdc` with YAML frontmatter
6
+ (`description`, `globs`, `alwaysApply`). Preferred for any 2025+
7
+ Cursor build.
8
+ - **Legacy (`.cursorrules`)** — single-file aggregate at the repo root.
9
+ Still read by older Cursor versions; the package keeps it for
10
+ backward compatibility.
11
+
12
+ The package ships **both** so you don't have to pick.
13
+
14
+ ## Prerequisites
15
+
16
+ - Cursor 0.45+ (any 2025/2026 build): <https://cursor.com>.
17
+ - Node.js ≥ 18.
18
+
19
+ ## Project install
20
+
21
+ ```bash
22
+ npx @event4u/create-agent-config init --tools=cursor
23
+ ```
24
+
25
+ This populates:
26
+
27
+ - `.cursor/rules/*.mdc` — one file per rule, modern frontmatter format
28
+ - `.cursor/commands/*.md` — slash commands mirrored from `.agent-src/commands/`
29
+ - `.cursorrules` — legacy single-file aggregate
30
+ - `.agent-settings.yml` — per-project knobs
31
+
32
+ Combine surfaces if you use both Cursor and Claude Code:
33
+
34
+ ```bash
35
+ npx @event4u/create-agent-config init --tools=cursor,claude-code
36
+ ```
37
+
38
+ ## Global install
39
+
40
+ ```bash
41
+ npx @event4u/agent-config global --tools=cursor
42
+ ```
43
+
44
+ Seeds `~/.cursor/rules/imported/event4u/` with the curated kernel +
45
+ top-N skills. Cursor merges global + workspace rules — workspace wins
46
+ on conflicts.
47
+
48
+ ## Modern `.mdc` frontmatter
49
+
50
+ Each `.mdc` file has the Cursor-shaped header:
51
+
52
+ ```mdc
53
+ ---
54
+ description: Scope control — no unsolicited architectural changes
55
+ globs:
56
+ alwaysApply: true
57
+ ---
58
+
59
+ # Scope Control
60
+ ...
61
+ ```
62
+
63
+ - `alwaysApply: true` ↔ source `type: "always"` (kernel rules).
64
+ - `alwaysApply: false` ↔ Cursor model decides per turn (auto rules).
65
+ - `globs:` is intentionally empty in the package's projection — apply
66
+ per-rule if you need path-scoped rules in your fork.
67
+
68
+ ## Cursor commands
69
+
70
+ `.cursor/commands/<slug>.md` mirrors `.claude/commands/`. Nested
71
+ clusters (e.g. `council/default.md`) flatten to `council-default.md` so
72
+ Cursor's command palette stays flat.
73
+
74
+ ## Marketplace install (planned — Phase 7 / S35)
75
+
76
+ The Cursor marketplace listing is filed in
77
+ `road-to-simplicity-and-everywhere.md` Phase 7. Once accepted you'll
78
+ be able to install via Cursor's Extensions panel without `npx`.
79
+
80
+ ## MCP block (when MCP Phase 3 ships)
81
+
82
+ Add to `.cursor/mcp.json` (Cursor's project-scoped MCP config):
83
+
84
+ ```json
85
+ {
86
+ "mcpServers": {
87
+ "event4u-agent-config": {
88
+ "command": "npx",
89
+ "args": ["-y", "@event4u/agent-config-mcp"]
90
+ }
91
+ }
92
+ }
93
+ ```
94
+
95
+ Track <https://github.com/event4u-app/agent-config> for the actual
96
+ release tag — until `road-to-mcp-full-coverage` Phase 3 ships, this
97
+ block is informational.
98
+
99
+ ## Verification
100
+
101
+ ```bash
102
+ ls -la .cursor/rules/ | head -5 # *.mdc files exist
103
+ ls -la .cursor/commands/| head -5 # *.md command files exist
104
+ test -f .cursorrules # legacy aggregate exists
105
+ ```
106
+
107
+ In Cursor itself: open the chat panel — settings should show the rules
108
+ under **Project Rules**.
109
+
110
+ ## Troubleshooting
111
+
112
+ | Symptom | Fix |
113
+ |---|---|
114
+ | Rules not picked up | Cursor < 0.45 — upgrade or rely on `.cursorrules`. |
115
+ | Modern + legacy duplicate triggers | Disable `.cursorrules` in Cursor settings. |
116
+ | Command missing in palette | `task generate-tools` then reload Cursor window. |
117
+ | Global rules ignored | Cursor needs `~/.cursor/rules/` — check OS path expansion. |
118
+
119
+ ## Cross-references
120
+
121
+ - [`docs/installation.md`](../../installation.md) — install matrix index.
122
+ - [`AGENTS.md`](../../../AGENTS.md) — package self-orientation; Cursor
123
+ reads it via the projected rules.
124
+ - [`templates/cursor-rule.mdc.j2`](../../../templates/cursor-rule.mdc.j2) —
125
+ template used by the projection generator.
@@ -0,0 +1,45 @@
1
+ # Gemini CLI Setup
2
+
3
+ Google's Gemini CLI reads `GEMINI.md` (which is a symlink to `AGENTS.md`
4
+ in the package's projection) for project context.
5
+
6
+ ## Prerequisites
7
+
8
+ - Gemini CLI installed: <https://github.com/google-gemini/gemini-cli>.
9
+ - Node.js ≥ 18 (for the install entrypoints).
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npx @event4u/create-agent-config init --tools=gemini
15
+ ```
16
+
17
+ Populates:
18
+
19
+ - `GEMINI.md` → `AGENTS.md` — symlink so Gemini CLI loads the same
20
+ self-orientation as Codex / Aider / Augment.
21
+ - `AGENTS.md` — canonical content (single source of truth).
22
+ - `.agent-settings.yml` — per-project knobs.
23
+
24
+ ## Verification
25
+
26
+ ```bash
27
+ test -L GEMINI.md && readlink GEMINI.md # → AGENTS.md
28
+ gemini --version # confirm CLI installed
29
+ ```
30
+
31
+ In a Gemini CLI session: `GEMINI.md` informs every turn — verify by
32
+ asking *"what is this repo?"* and confirming the answer matches
33
+ `AGENTS.md`'s emergency-triage block.
34
+
35
+ ## Troubleshooting
36
+
37
+ | Symptom | Fix |
38
+ |---|---|
39
+ | Gemini CLI doesn't see `GEMINI.md` | Some Gemini versions require absolute paths — `gemini --context $(pwd)/GEMINI.md`. |
40
+ | Symlink broken on Windows | Re-run installer; on Windows the projection may emit a copy instead of a symlink. |
41
+
42
+ ## Cross-references
43
+
44
+ - [`AGENTS.md`](../../../AGENTS.md) — canonical agent self-orientation.
45
+ - [`docs/installation.md`](../../installation.md) — install matrix index.
@@ -0,0 +1,120 @@
1
+ # Windsurf Setup
2
+
3
+ Windsurf reads two rule formats:
4
+
5
+ - **Wave-8 (`.windsurf/rules/`)** — per-rule `.md` files with
6
+ `trigger`, `description`, `globs` frontmatter. Preferred for
7
+ Windsurf 1.5+.
8
+ - **Legacy (`.windsurfrules`)** — single-file aggregate at the repo
9
+ root. Older Windsurf builds and the Cascade chat fallback both still
10
+ read it.
11
+
12
+ The package ships **both**.
13
+
14
+ ## Prerequisites
15
+
16
+ - Windsurf 1.0+ (Codeium): <https://codeium.com/windsurf>.
17
+ - Node.js ≥ 18.
18
+
19
+ ## Project install
20
+
21
+ ```bash
22
+ npx @event4u/create-agent-config init --tools=windsurf
23
+ ```
24
+
25
+ Populates:
26
+
27
+ - `.windsurf/rules/*.md` — modern Wave-8 per-rule files
28
+ - `.windsurf/workflows/*.md` — slash-command workflows
29
+ - `.windsurfrules` — legacy single-file aggregate
30
+ - `.agent-settings.yml` — per-project knobs
31
+
32
+ Combine with other surfaces:
33
+
34
+ ```bash
35
+ npx @event4u/create-agent-config init --tools=windsurf,claude-code,cursor
36
+ ```
37
+
38
+ ## Global install
39
+
40
+ ```bash
41
+ npx @event4u/agent-config global --tools=windsurf
42
+ ```
43
+
44
+ Seeds `~/.codeium/windsurf/global_workflows/` with the curated
45
+ workflow set (see [`templates/global-install-manifest.yml`](../../../templates/global-install-manifest.yml)).
46
+ Available across every project; per-workspace `.windsurf/workflows/`
47
+ takes precedence on slug collisions.
48
+
49
+ ## Wave-8 frontmatter
50
+
51
+ Each rule under `.windsurf/rules/` has the Windsurf-shaped header:
52
+
53
+ ```md
54
+ ---
55
+ trigger: always_on
56
+ description: Scope control — no unsolicited architectural changes
57
+ globs:
58
+ ---
59
+
60
+ # Scope Control
61
+ ...
62
+ ```
63
+
64
+ - `trigger: always_on` ↔ source `type: "always"` (kernel rules).
65
+ - `trigger: model_decision` ↔ Cascade decides per turn (auto rules).
66
+ - `globs:` is intentionally empty in the package's projection — set
67
+ per-rule in your fork if you want path-scoped triggering.
68
+
69
+ ## Workflows
70
+
71
+ `.windsurf/workflows/<slug>.md` mirrors `.claude/commands/`. Cluster
72
+ commands flatten to `<cluster>-<name>.md`. Cascade lists all workflow
73
+ files in its workflow palette.
74
+
75
+ ## Cascade integration
76
+
77
+ Cascade (Windsurf's built-in agent) reads `.windsurf/rules/` and
78
+ `.windsurf/workflows/` automatically. No separate registration step is
79
+ needed once the files are on disk.
80
+
81
+ When Cascade asks a clarifying question, the package's `user-interaction`
82
+ rule (kernel, `always_on`) applies — Cascade will surface numbered
83
+ options with a single recommendation.
84
+
85
+ ## Workspace vs global precedence
86
+
87
+ | Layer | Path | Precedence |
88
+ |---|---|---|
89
+ | Workspace | `.windsurf/rules/` + `.windsurf/workflows/` | wins on conflicts |
90
+ | Global | `~/.codeium/windsurf/global_workflows/` | falls back when workspace silent |
91
+
92
+ Reuse the same `--tools=windsurf` flag for both — `init` writes
93
+ workspace, `global` writes user-level.
94
+
95
+ ## Verification
96
+
97
+ ```bash
98
+ ls .windsurf/rules/ | head -5 # *.md per-rule files
99
+ ls .windsurf/workflows/ | head -5 # *.md workflow files
100
+ test -f .windsurfrules # legacy aggregate exists
101
+ ```
102
+
103
+ In Windsurf itself: open Cascade → Workflows panel — listed workflows
104
+ should match `ls .windsurf/workflows/`.
105
+
106
+ ## Troubleshooting
107
+
108
+ | Symptom | Fix |
109
+ |---|---|
110
+ | Rules not picked up | Windsurf < 1.0 — upgrade or rely on `.windsurfrules`. |
111
+ | Workflow not in Cascade panel | Reload window after `task generate-tools`. |
112
+ | Global workflows missing | Check `~/.codeium/windsurf/global_workflows/` exists. |
113
+ | Frontmatter parse error | Re-run `python3 scripts/compress.py --generate-tools`. |
114
+
115
+ ## Cross-references
116
+
117
+ - [`docs/installation.md`](../../installation.md) — install matrix index.
118
+ - [`templates/windsurf-rule.md.j2`](../../../templates/windsurf-rule.md.j2)
119
+ — template used by the projection generator.
120
+ - [`AGENTS.md`](../../../AGENTS.md) — package self-orientation.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@event4u/agent-config",
3
- "version": "1.39.0",
3
+ "version": "1.40.0",
4
4
  "description": "Shared agent configuration \u2014 skills, rules, commands, guidelines, and templates for AI coding tools",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -26,6 +26,8 @@ import shutil
26
26
  import sys
27
27
  from pathlib import Path
28
28
 
29
+ import yaml
30
+
29
31
  sys.path.insert(0, str(Path(__file__).resolve().parent))
30
32
  from _lib.script_output import info, success, flush_summary, resolve_level # noqa: E402
31
33
 
@@ -503,6 +505,149 @@ def generate_windsurfrules() -> int:
503
505
  return len(rules)
504
506
 
505
507
 
508
+ # ── Modern editor formats (road-to-simplicity-and-everywhere Phase 5) ─
509
+ # Cursor `.cursor/rules/*.mdc` (frontmatter: description, globs,
510
+ # alwaysApply) and Windsurf `.windsurf/rules/*.md` (frontmatter:
511
+ # trigger, description, globs) are the formats current editors prefer.
512
+ # Legacy `.windsurfrules` aggregate stays for users who prefer it.
513
+
514
+ CURSOR_RULES_MDC_DIR = PROJECT_ROOT / ".cursor" / "rules"
515
+ WINDSURF_RULES_DIR = PROJECT_ROOT / ".windsurf" / "rules"
516
+ WINDSURF_WORKFLOWS_DIR = PROJECT_ROOT / ".windsurf" / "workflows"
517
+ CURSOR_COMMANDS_DIR = PROJECT_ROOT / ".cursor" / "commands"
518
+
519
+
520
+ def _parse_frontmatter(content: str) -> tuple[dict, str]:
521
+ """Split a `---`-delimited YAML frontmatter from the body."""
522
+ if not content.startswith("---"):
523
+ return {}, content
524
+ end = content.find("\n---", 3)
525
+ if end == -1:
526
+ return {}, content
527
+ raw = content[3:end].strip()
528
+ body = content[end + 4:].lstrip("\n")
529
+ try:
530
+ meta = yaml.safe_load(raw) or {}
531
+ except yaml.YAMLError:
532
+ meta = {}
533
+ return meta if isinstance(meta, dict) else {}, body
534
+
535
+
536
+ def _emit_cursor_mdc(source: Path, target: Path) -> None:
537
+ """Write a Cursor `.mdc` file with Cursor-shaped frontmatter."""
538
+ meta, body = _parse_frontmatter(source.read_text())
539
+ description = (meta.get("description") or "").replace("\n", " ").strip()
540
+ always_apply = bool(meta.get("alwaysApply") or meta.get("type") == "always")
541
+ lines = [
542
+ "---",
543
+ f"description: {description}",
544
+ "globs: ",
545
+ f"alwaysApply: {'true' if always_apply else 'false'}",
546
+ "---",
547
+ "",
548
+ body.rstrip() + "\n",
549
+ ]
550
+ target.parent.mkdir(parents=True, exist_ok=True)
551
+ target.write_text("\n".join(lines))
552
+
553
+
554
+ def _emit_windsurf_rule(source: Path, target: Path) -> None:
555
+ """Write a Windsurf rule with Wave-8 frontmatter (trigger/description/globs)."""
556
+ meta, body = _parse_frontmatter(source.read_text())
557
+ description = (meta.get("description") or "").replace("\n", " ").strip()
558
+ always_apply = bool(meta.get("alwaysApply") or meta.get("type") == "always")
559
+ trigger = "always_on" if always_apply else "model_decision"
560
+ lines = [
561
+ "---",
562
+ f"trigger: {trigger}",
563
+ f"description: {description}",
564
+ "globs: ",
565
+ "---",
566
+ "",
567
+ body.rstrip() + "\n",
568
+ ]
569
+ target.parent.mkdir(parents=True, exist_ok=True)
570
+ target.write_text("\n".join(lines))
571
+
572
+
573
+ def _clean_modern_dir(target_dir: Path, valid_names: set[str]) -> None:
574
+ """Drop files in `target_dir` whose names are not in `valid_names`."""
575
+ if not target_dir.exists():
576
+ return
577
+ for item in target_dir.iterdir():
578
+ if item.name == "README.md":
579
+ continue
580
+ if item.name not in valid_names:
581
+ if item.is_dir() and not item.is_symlink():
582
+ shutil.rmtree(item)
583
+ else:
584
+ item.unlink()
585
+
586
+
587
+ def generate_cursor_mdc_rules() -> int:
588
+ """Emit `.cursor/rules/*.mdc` per source rule (alongside legacy `.md` symlinks)."""
589
+ rules = sorted(RULES_SOURCE.glob("*.md"))
590
+ valid = {f"{r.stem}.mdc" for r in rules}
591
+ _clean_modern_dir(CURSOR_RULES_MDC_DIR, valid | {r.name for r in rules})
592
+ for rule in rules:
593
+ _emit_cursor_mdc(rule, CURSOR_RULES_MDC_DIR / f"{rule.stem}.mdc")
594
+ info(f" ✅ Wrote {len(rules)} `.cursor/rules/*.mdc` files")
595
+ return len(rules)
596
+
597
+
598
+ def generate_windsurf_modern_rules() -> int:
599
+ """Emit `.windsurf/rules/*.md` per source rule (Wave-8 frontmatter)."""
600
+ rules = sorted(RULES_SOURCE.glob("*.md"))
601
+ valid = {r.name for r in rules}
602
+ _clean_modern_dir(WINDSURF_RULES_DIR, valid)
603
+ for rule in rules:
604
+ _emit_windsurf_rule(rule, WINDSURF_RULES_DIR / rule.name)
605
+ info(f" ✅ Wrote {len(rules)} `.windsurf/rules/*.md` files")
606
+ return len(rules)
607
+
608
+
609
+ def generate_cursor_commands() -> int:
610
+ """Symlink `.cursor/commands/<slug>.md` per source command."""
611
+ if not COMMANDS_SOURCE.exists():
612
+ return 0
613
+ cmds = list(_iter_commands())
614
+ valid = {f"{slug}.md" for _, slug in cmds}
615
+ _clean_modern_dir(CURSOR_COMMANDS_DIR, valid)
616
+ CURSOR_COMMANDS_DIR.mkdir(parents=True, exist_ok=True)
617
+ count = 0
618
+ for source_file, slug in cmds:
619
+ link = CURSOR_COMMANDS_DIR / f"{slug}.md"
620
+ if link.exists() or link.is_symlink():
621
+ link.unlink()
622
+ rel = Path("../../.agent-src/commands") / source_file.relative_to(COMMANDS_SOURCE)
623
+ link.symlink_to(rel)
624
+ count += 1
625
+ info(f" ✅ Linked {count} `.cursor/commands/*.md` files")
626
+ return count
627
+
628
+
629
+ def generate_windsurf_workflows() -> int:
630
+ """Symlink `.windsurf/workflows/<slug>.md` per source command."""
631
+ if not COMMANDS_SOURCE.exists():
632
+ return 0
633
+ cmds = list(_iter_commands())
634
+ valid = {f"{slug}.md" for _, slug in cmds}
635
+ _clean_modern_dir(WINDSURF_WORKFLOWS_DIR, valid)
636
+ WINDSURF_WORKFLOWS_DIR.mkdir(parents=True, exist_ok=True)
637
+ count = 0
638
+ for source_file, slug in cmds:
639
+ link = WINDSURF_WORKFLOWS_DIR / f"{slug}.md"
640
+ if link.exists() or link.is_symlink():
641
+ link.unlink()
642
+ rel = Path("../../.agent-src/commands") / source_file.relative_to(COMMANDS_SOURCE)
643
+ link.symlink_to(rel)
644
+ count += 1
645
+ info(f" ✅ Linked {count} `.windsurf/workflows/*.md` files")
646
+ return count
647
+
648
+
649
+
650
+
506
651
  def generate_gemini_md() -> None:
507
652
  """Create GEMINI.md symlink to AGENTS.md."""
508
653
  link = PROJECT_ROOT / "GEMINI.md"
@@ -695,9 +840,15 @@ def generate_tools() -> None:
695
840
  skills = generate_claude_skills()
696
841
  commands = generate_claude_commands()
697
842
  personas = generate_persona_symlinks()
843
+ cursor_mdc = generate_cursor_mdc_rules()
844
+ windsurf_modern = generate_windsurf_modern_rules()
845
+ cursor_cmds = generate_cursor_commands()
846
+ windsurf_wf = generate_windsurf_workflows()
698
847
  summary = (
699
848
  f"✅ generate-tools — rules={rules} skills={skills} "
700
- f"commands={commands} personas={personas}"
849
+ f"commands={commands} personas={personas} "
850
+ f"cursor_mdc={cursor_mdc} windsurf_rules={windsurf_modern} "
851
+ f"cursor_commands={cursor_cmds} windsurf_workflows={windsurf_wf}"
701
852
  )
702
853
  if resolve_level() == "verbose":
703
854
  print(f"\n{summary}")
@@ -806,6 +957,7 @@ def clean_tools() -> None:
806
957
  PROJECT_ROOT / ".claude",
807
958
  PROJECT_ROOT / ".cursor",
808
959
  PROJECT_ROOT / ".clinerules",
960
+ PROJECT_ROOT / ".windsurf",
809
961
  PROJECT_ROOT / ".windsurfrules",
810
962
  PROJECT_ROOT / "GEMINI.md",
811
963
  ]