@event4u/agent-config 1.39.0 → 1.41.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/.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 +75 -0
  11. package/README.md +52 -26
  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 +5 -3
  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 +47 -0
  20. package/docs/contracts/mcp-discovery-phase-notice.md +56 -0
  21. package/docs/contracts/mcp-tool-stub-envelope.md +78 -0
  22. package/docs/contracts/orchestration-dsl-v1.md +152 -0
  23. package/docs/getting-started.md +1 -1
  24. package/docs/installation.md +132 -0
  25. package/docs/setup/mcp-client-config.md +94 -13
  26. package/docs/setup/mcp-cloud-setup.md +32 -1
  27. package/docs/setup/per-ide/aider.md +48 -0
  28. package/docs/setup/per-ide/claude-code.md +108 -0
  29. package/docs/setup/per-ide/claude-desktop.md +173 -0
  30. package/docs/setup/per-ide/cline.md +43 -0
  31. package/docs/setup/per-ide/codex.md +46 -0
  32. package/docs/setup/per-ide/copilot.md +80 -0
  33. package/docs/setup/per-ide/cursor.md +125 -0
  34. package/docs/setup/per-ide/gemini-cli.md +45 -0
  35. package/docs/setup/per-ide/windsurf.md +120 -0
  36. package/package.json +1 -1
  37. package/scripts/_lib/script_output.py +15 -11
  38. package/scripts/ai_council/session.py +14 -8
  39. package/scripts/chat_history.py +29 -53
  40. package/scripts/command_suggester/settings.py +15 -13
  41. package/scripts/compile_router.py +13 -9
  42. package/scripts/compress.py +175 -20
  43. package/scripts/council_cli.py +9 -3
  44. package/scripts/extract_audit_patterns.py +202 -0
  45. package/scripts/install +156 -1
  46. package/scripts/install.py +270 -10
  47. package/scripts/install.sh +52 -7
  48. package/scripts/lint_orchestration_dsl.py +214 -0
  49. package/scripts/mcp_parity_smoke.py +20 -2
  50. package/scripts/mcp_server/catalog.py +125 -0
  51. package/scripts/mcp_server/consumer_tool_catalog.json +275 -0
  52. package/scripts/mcp_server/telemetry.py +128 -0
  53. package/scripts/mcp_server/tools.py +474 -15
  54. package/scripts/mcp_telemetry_health.py +214 -0
  55. package/scripts/mcp_telemetry_query.py +203 -0
  56. package/scripts/mcp_telemetry_store.py +211 -0
  57. package/scripts/memory_signal.py +12 -10
  58. package/scripts/pack_mcp_content.py +18 -4
  59. package/scripts/skill_linter.py +9 -0
  60. package/scripts/sync_gitignore.py +56 -1
  61. package/templates/claude_desktop_config.json.template +22 -0
  62. package/templates/cursor-rule.mdc.j2 +7 -0
  63. package/templates/global-install-manifest.yml +91 -0
  64. package/templates/marketing-copy.yml +64 -0
  65. package/templates/windsurf-rule.md.j2 +7 -0
@@ -41,6 +41,7 @@ from typing import Any
41
41
  _SCRIPTS_DIR = Path(__file__).resolve().parent
42
42
  sys.path.insert(0, str(_SCRIPTS_DIR))
43
43
 
44
+ from mcp_server.catalog import load_raw as load_tool_catalog_raw # noqa: E402
44
45
  from mcp_server.prompts import scan_commands, scan_skills # noqa: E402
45
46
  from mcp_server.resources import scan_contexts, scan_guidelines, scan_rules # noqa: E402
46
47
 
@@ -130,11 +131,15 @@ def _collect_entries(root: Path) -> tuple[dict[str, dict[str, Any]], list[str]]:
130
131
  return uris, errors
131
132
 
132
133
 
133
- def _content_signature(uris: dict[str, dict[str, Any]]) -> tuple[str, str]:
134
- """SHA-256 over sorted (uri, body) pairs.
134
+ def _content_signature(
135
+ uris: dict[str, dict[str, Any]],
136
+ tool_catalog: dict[str, Any],
137
+ ) -> tuple[str, str]:
138
+ """SHA-256 over sorted (uri, body) pairs plus the tool catalog JSON.
135
139
 
136
140
  Returns (full_hex, 12-char prefix). The prefix is the wire-surface
137
141
  `skillSetSignature`; the full hex is the diagnostic `content_hash_sha256`.
142
+ Including the catalog ensures a stub edit produces a new release_key.
138
143
  """
139
144
  hasher = hashlib.sha256()
140
145
  for uri in sorted(uris):
@@ -142,6 +147,10 @@ def _content_signature(uris: dict[str, dict[str, Any]]) -> tuple[str, str]:
142
147
  hasher.update(b"\x00")
143
148
  hasher.update(uris[uri]["body"].encode("utf-8"))
144
149
  hasher.update(b"\x1e")
150
+ hasher.update(b"\x1d")
151
+ hasher.update(
152
+ json.dumps(tool_catalog, ensure_ascii=False, sort_keys=True).encode("utf-8")
153
+ )
145
154
  digest = hasher.hexdigest()
146
155
  return digest, digest[:12]
147
156
 
@@ -164,6 +173,7 @@ def _build_manifest(
164
173
  git_sha: str,
165
174
  built_at: str,
166
175
  counts: dict[str, int],
176
+ tool_count: int,
167
177
  ) -> dict[str, Any]:
168
178
  short = git_sha[:7] if git_sha and git_sha != "0" * 40 else "unknown"
169
179
  return {
@@ -176,6 +186,7 @@ def _build_manifest(
176
186
  "built_at": built_at,
177
187
  "packer_version": PACKER_VERSION,
178
188
  "content_uri_count": counts,
189
+ "tool_count": tool_count,
179
190
  }
180
191
 
181
192
 
@@ -188,7 +199,8 @@ def pack(root: Path, out_dir: Path) -> dict[str, Any]:
188
199
  sys.stderr.write(f" - {line}\n")
189
200
  raise SystemExit(2)
190
201
 
191
- content_hash, signature = _content_signature(uris)
202
+ tool_catalog = load_tool_catalog_raw()
203
+ content_hash, signature = _content_signature(uris, tool_catalog)
192
204
  counts = _count_kinds(uris)
193
205
  built_at = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
194
206
  manifest = _build_manifest(
@@ -198,11 +210,13 @@ def pack(root: Path, out_dir: Path) -> dict[str, Any]:
198
210
  git_sha=_git_sha(root),
199
211
  built_at=built_at,
200
212
  counts=counts,
213
+ tool_count=len(tool_catalog.get("tools", [])),
201
214
  )
202
215
 
203
216
  blob = {
204
217
  "schema_version": SCHEMA_VERSION,
205
218
  "uris": uris,
219
+ "tool_catalog": tool_catalog,
206
220
  "manifest": manifest,
207
221
  }
208
222
  # Compact JSON for the bundle (saves ~20 KB vs indent=2). The R2
@@ -265,7 +279,7 @@ def main(argv: list[str] | None = None) -> int:
265
279
  f"release={manifest['release_key']} "
266
280
  f"skills={c['skill']} commands={c['command']} "
267
281
  f"rules={c['rule']} guidelines={c['guideline']} "
268
- f"contexts={c['context']}\n"
282
+ f"contexts={c['context']} tools={manifest['tool_count']}\n"
269
283
  )
270
284
  return 0
271
285
 
@@ -1605,6 +1605,15 @@ def gather_changed_candidate_files(root: Path) -> list[Path]:
1605
1605
  if path.is_symlink():
1606
1606
  continue
1607
1607
  norm = raw.replace("\\", "/")
1608
+ # Only lint source-of-truth and source-mirror dirs. Projection
1609
+ # dirs (.windsurf/, .cursor/, .clinerules/, .claude/) use
1610
+ # tool-native frontmatter (e.g. Windsurf's trigger/globs) that
1611
+ # the linter does not validate — they regenerate from source.
1612
+ if not (
1613
+ norm.startswith(".agent-src.uncompressed/")
1614
+ or norm.startswith(".agent-src/")
1615
+ ):
1616
+ continue
1608
1617
  if path.name == "SKILL.md" or "/rules/" in norm or "/commands/" in norm:
1609
1618
  files.append(path)
1610
1619
  return sorted(set(files))
@@ -14,7 +14,13 @@ are preserved). Call with `--replace` for a destructive full rewrite.
14
14
 
15
15
  Usage:
16
16
  python3 scripts/sync_gitignore.py [--path .gitignore] [--template config/gitignore-block.txt]
17
- [--dry-run] [--replace] [--quiet]
17
+ [--dry-run] [--replace] [--cleanup-legacy] [--quiet]
18
+
19
+ `--cleanup-legacy` additionally scrubs legacy patterns (pre-/agents/ layout
20
+ runtime artefacts) from anywhere in the target file — inside the managed
21
+ block and outside, where older installers or hand-edits dropped them.
22
+ Runs before the regular sync, so a single invocation removes garbage and
23
+ re-adds the current canonical entries.
18
24
 
19
25
  Exit codes:
20
26
  0 — no changes needed (or --dry-run ran successfully)
@@ -34,6 +40,20 @@ SECTION_FOOTER = "# event4u/agent-config — END"
34
40
  DEFAULT_GITIGNORE = ".gitignore"
35
41
  DEFAULT_TEMPLATE = Path(__file__).resolve().parent.parent / "config" / "gitignore-block.txt"
36
42
 
43
+ # Legacy patterns that lived in older versions of config/gitignore-block.txt
44
+ # before runtime artefacts moved under /agents/ (May 2026). They get stripped
45
+ # wherever they appear in the consumer's .gitignore — inside the managed block
46
+ # or outside (older installers / hand-edits). Current canonical equivalents
47
+ # (e.g. /agents/.agent-chat-history) come from the template and are NOT
48
+ # affected. Leading-slash variants are matched defensively.
49
+ LEGACY_PATTERNS: tuple[str, ...] = (
50
+ ".agent-chat-history",
51
+ ".agent-chat-history.bak",
52
+ ".agent-chat-history.*.bak",
53
+ ".agent-prices.md",
54
+ ".council-tmp/",
55
+ )
56
+
37
57
 
38
58
  def _strip(ln: str) -> str:
39
59
  return ln.rstrip("\n").rstrip()
@@ -149,6 +169,26 @@ def sync_block(existing_lines: list[str],
149
169
  return head + new_block + tail, missing
150
170
 
151
171
 
172
+ def cleanup_legacy(lines: list[str]) -> tuple[list[str], list[str]]:
173
+ """Strip legacy entries from anywhere in the file.
174
+
175
+ A line is legacy when its stripped, leading-whitespace-trimmed content
176
+ matches a `LEGACY_PATTERNS` entry — with or without a leading slash.
177
+ Comments and blank lines are untouched; current managed entries (e.g.
178
+ `/agents/.agent-chat-history`) are not in the legacy set and survive.
179
+ """
180
+ legacy = set(LEGACY_PATTERNS)
181
+ kept: list[str] = []
182
+ removed: list[str] = []
183
+ for ln in lines:
184
+ s = _strip(ln).lstrip()
185
+ if s in legacy or (s.startswith("/") and s[1:] in legacy):
186
+ removed.append(s)
187
+ continue
188
+ kept.append(ln)
189
+ return kept, removed
190
+
191
+
152
192
  def format_file(lines: list[str]) -> str:
153
193
  """Join lines with newlines and enforce exactly one trailing newline."""
154
194
  text = "\n".join(lines)
@@ -174,6 +214,9 @@ def main(argv: list[str] | None = None) -> int:
174
214
  ap.add_argument("--replace", action="store_true",
175
215
  help="rewrite the block in full (discards user-added "
176
216
  "lines inside the block)")
217
+ ap.add_argument("--cleanup-legacy", action="store_true",
218
+ help="strip legacy patterns (pre-/agents/ layout) from "
219
+ "anywhere in the file before syncing the block")
177
220
  ap.add_argument("--quiet", action="store_true",
178
221
  help="suppress summary on success")
179
222
  args = ap.parse_args(argv)
@@ -193,6 +236,10 @@ def main(argv: list[str] | None = None) -> int:
193
236
  existing_text = ""
194
237
  existing_lines = []
195
238
 
239
+ removed_legacy: list[str] = []
240
+ if args.cleanup_legacy:
241
+ existing_lines, removed_legacy = cleanup_legacy(existing_lines)
242
+
196
243
  new_lines, added = sync_block(
197
244
  existing_lines, template_lines, replace=args.replace,
198
245
  )
@@ -211,6 +258,10 @@ def main(argv: list[str] | None = None) -> int:
211
258
  print(f"\n(dry-run) would add {len(added)} entr"
212
259
  f"{'y' if len(added) == 1 else 'ies'} to {target}",
213
260
  file=sys.stderr)
261
+ if removed_legacy:
262
+ print(f"(dry-run) would remove {len(removed_legacy)} legacy "
263
+ f"entr{'y' if len(removed_legacy) == 1 else 'ies'}: "
264
+ f"{', '.join(removed_legacy)}", file=sys.stderr)
214
265
  return 0
215
266
 
216
267
  target.parent.mkdir(parents=True, exist_ok=True)
@@ -219,6 +270,10 @@ def main(argv: list[str] | None = None) -> int:
219
270
  action = "replaced" if args.replace else "updated"
220
271
  print(f"✅ {target}: {action} block "
221
272
  f"({len(added)} entr{'y' if len(added) == 1 else 'ies'} added)")
273
+ if removed_legacy:
274
+ print(f" removed {len(removed_legacy)} legacy "
275
+ f"entr{'y' if len(removed_legacy) == 1 else 'ies'}: "
276
+ f"{', '.join(removed_legacy)}")
222
277
  return 0
223
278
 
224
279
 
@@ -0,0 +1,22 @@
1
+ {
2
+ "//": "Claude Desktop config template — agent-config",
3
+ "//1": "Copy this to one of:",
4
+ "//2": " macOS ~/Library/Application Support/Claude/claude_desktop_config.json",
5
+ "//3": " Windows %APPDATA%\\Claude\\claude_desktop_config.json",
6
+ "//4": " Linux ~/.config/Claude/claude_desktop_config.json",
7
+ "//5": "Strip the leading '_disabled_' prefix on the mcpServers entry below to enable the MCP connector.",
8
+ "//6": "Replace https://your-worker.workers.dev with the URL of your own deployed Cloudflare Worker (see docs/setup/mcp-cloud-setup.md). The Worker is read-only and identity-stable per release; full client setup details in docs/setup/mcp-client-config.md.",
9
+ "//7": "If your Worker has MCP-Token set (recommended), uncomment the --header / env lines below and paste the token. Otherwise drop them.",
10
+ "//8": "Restart Claude Desktop fully (Cmd+Q on macOS) after editing — the menubar process keeps the old config cached otherwise.",
11
+
12
+ "_disabled_mcpServers": {
13
+ "agent-config": {
14
+ "command": "npx",
15
+ "args": [
16
+ "-y",
17
+ "mcp-remote",
18
+ "https://your-worker.workers.dev"
19
+ ]
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,7 @@
1
+ ---
2
+ description: {{ description }}
3
+ globs: {{ globs | default("") }}
4
+ alwaysApply: {{ "true" if always_apply else "false" }}
5
+ ---
6
+
7
+ {{ body }}
@@ -0,0 +1,91 @@
1
+ # Global Install Manifest — road-to-simplicity-and-everywhere Phase 3
2
+ #
3
+ # Curated subset of rules + skills shipped to user-scope directories
4
+ # (~/.claude/, ~/.cursor/, ~/.codeium/windsurf/, ~/.config/agent-config/)
5
+ # by `scripts/install --global`. Without curation we'd dump 200+ skills
6
+ # into user dirs — that is the failure mode anthropics/claude-code#53950
7
+ # flagged.
8
+ #
9
+ # Schema (v1):
10
+ # kernel_rules: list[str] — rule IDs from router.json's `kernel`.
11
+ # Always shipped to every enabled surface.
12
+ # top_skills: list[entry] — curated universal skills.
13
+ # entry.id : skill directory under .agent-src/skills/
14
+ # entry.surfaces : subset of [claude-code, cursor, windsurf, fallback]
15
+ # — fallback is always written.
16
+ #
17
+ # Source: kernel_rules mirrors router.json; top_skills is a 15-pick
18
+ # distilled from .agent-src/skills/ — universal coding-loop helpers
19
+ # (work, commit, PR, review, quality, analyze, handoff). Per-stack
20
+ # skills (laravel, react-shadcn-ui, php-coder) stay project-local.
21
+ #
22
+ # Per-tool target paths (handled by scripts/install.py global subcommand):
23
+ # claude-code : ~/.claude/skills/event4u/<id>/SKILL.md
24
+ # ~/.claude/rules/event4u/<rule>.md
25
+ # cursor : ~/.cursor/rules/imported/event4u/<rule>.mdc
26
+ # ~/.cursor/skills/event4u/<id>/ (skills surface; mirrors agent-os)
27
+ # windsurf : ~/.codeium/windsurf/global_workflows/event4u/<id>.md
28
+ # fallback : ~/.config/agent-config/{rules,skills}/event4u/
29
+ #
30
+ # All writes are namespaced under `event4u/` so `--global --uninstall`
31
+ # can `rm -rf` the namespace dir without touching user-added files.
32
+
33
+ schema_version: 1
34
+
35
+ # Always-loaded rules — mirrors router.json's `kernel` array.
36
+ # Symlinked / copied into every enabled surface's rules dir.
37
+ kernel_rules:
38
+ - agent-authority
39
+ - ask-when-uncertain
40
+ - commit-policy
41
+ - direct-answers
42
+ - language-and-tone
43
+ - no-cheap-questions
44
+ - non-destructive-by-default
45
+ - scope-control
46
+ - verify-before-complete
47
+
48
+ # Top-N curated skills. The 15 picks below are coding-loop universals:
49
+ # the agent reaches for them on almost any task, regardless of stack.
50
+ # Per-stack and domain skills are deliberately omitted — they belong in
51
+ # project-local installs where the stack signal is unambiguous.
52
+ top_skills:
53
+ # --- Workflow drivers (most-touched commands) ---
54
+ - id: work
55
+ surfaces: [claude-code, cursor, windsurf, fallback]
56
+ - id: commit
57
+ surfaces: [claude-code, cursor, windsurf, fallback]
58
+ - id: create-pr
59
+ surfaces: [claude-code, cursor, windsurf, fallback]
60
+ - id: review-changes
61
+ surfaces: [claude-code, cursor, windsurf, fallback]
62
+ - id: quality-fix
63
+ surfaces: [claude-code, cursor, windsurf, fallback]
64
+
65
+ # --- Session / context management ---
66
+ - id: agent-handoff
67
+ surfaces: [claude-code, cursor, windsurf, fallback]
68
+ - id: agent-status
69
+ surfaces: [claude-code, cursor, windsurf, fallback]
70
+ - id: project-analyze
71
+ surfaces: [claude-code, cursor, windsurf, fallback]
72
+ - id: project-health
73
+ surfaces: [claude-code, cursor, windsurf, fallback]
74
+
75
+ # --- Investigation / debugging ---
76
+ - id: bug-investigate
77
+ surfaces: [claude-code, cursor, windsurf, fallback]
78
+ - id: bug-fix
79
+ surfaces: [claude-code, cursor, windsurf, fallback]
80
+ - id: systematic-debugging
81
+ surfaces: [claude-code, cursor, windsurf, fallback]
82
+
83
+ # --- Ticket / PR drivers ---
84
+ - id: implement-ticket
85
+ surfaces: [claude-code, cursor, windsurf, fallback]
86
+ - id: prepare-for-review
87
+ surfaces: [claude-code, cursor, windsurf, fallback]
88
+
89
+ # --- Onboarding (single command, surfaces a project) ---
90
+ - id: onboard
91
+ surfaces: [claude-code, cursor, windsurf, fallback]
@@ -0,0 +1,64 @@
1
+ # marketing-copy.yml — single source of truth for all marketplace
2
+ # listings, GitHub repo metadata, npm package descriptions, and
3
+ # README taglines. Edit here once; downstream surfaces sync on
4
+ # `task generate-tools` (Phase 7 / S38 of road-to-simplicity-and-everywhere).
5
+
6
+ tagline: >-
7
+ Shared agent configuration — skills, rules, and slash commands for
8
+ AI coding tools (Claude Code, Cursor, Windsurf, Cline, Aider,
9
+ Codex, Gemini CLI, Copilot, Augment).
10
+
11
+ short_description: >-
12
+ Project-installable + global agent skill suite — works across
13
+ every major AI coding tool. One install, every editor.
14
+
15
+ # GitHub repo topics (set via `gh repo edit --add-topic ...`).
16
+ # Keep this list short and high-signal; GitHub caps display at ~6.
17
+ github_topics:
18
+ - agent
19
+ - claude-code
20
+ - cursor
21
+ - windsurf
22
+ - cline
23
+ - mcp
24
+ - agents-md
25
+ - skill-files
26
+ - copilot
27
+ - aider
28
+
29
+ # Marketplace listings (Anthropic, Cursor, Smithery) read these.
30
+ listing:
31
+ name: event4u/agent-config
32
+ category: agent-tooling
33
+ primary_surface: claude-code
34
+ also_supports:
35
+ - claude-desktop
36
+ - cursor
37
+ - windsurf
38
+ - cline
39
+ - aider
40
+ - codex
41
+ - gemini-cli
42
+ - copilot
43
+ - augment
44
+
45
+ # npm package metadata (synced into packages/create-agent-config/package.json
46
+ # and any future @event4u/agent-config packages).
47
+ npm:
48
+ package: "@event4u/create-agent-config"
49
+ description: >-
50
+ Zero-config installer for event4u/agent-config — picks tools,
51
+ runs the install, works in any directory.
52
+ keywords:
53
+ - agent
54
+ - claude
55
+ - cursor
56
+ - windsurf
57
+ - skills
58
+ - mcp
59
+
60
+ # Authoritative URLs.
61
+ urls:
62
+ homepage: https://github.com/event4u-app/agent-config
63
+ bugs: https://github.com/event4u-app/agent-config/issues
64
+ docs: https://github.com/event4u-app/agent-config/blob/main/docs/installation.md
@@ -0,0 +1,7 @@
1
+ ---
2
+ trigger: {{ trigger }}
3
+ description: {{ description }}
4
+ globs: {{ globs | default("") }}
5
+ ---
6
+
7
+ {{ body }}