@softspark/ai-toolkit 2.1.1 → 2.1.2

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.
package/AGENTS.md CHANGED
@@ -386,3 +386,50 @@ Testing expert. Use for writing tests (unit, integration, e2e), TDD workflow, te
386
386
 
387
387
  ---
388
388
 
389
+ <!-- TOOLKIT:jira-rules START -->
390
+ <!-- Auto-injected by ai-toolkit. Re-run to update. -->
391
+
392
+ # Jira MCP Server
393
+
394
+ Tools: `sync_tasks`, `read_cached_tasks`, `update_task_status`, `add_task_comment`, `reassign_task`, `get_task_statuses`, `get_task_details`, `log_task_time`, `get_task_time_tracking`
395
+
396
+ ## Key Rules
397
+
398
+ - **Always `sync_tasks` first** before reading — cache may be stale.
399
+ - **Time format:** `"2h 30m"` — hours and minutes only, never days.
400
+ - **Status changes:** call `get_task_statuses` first to check valid transitions.
401
+ - **Multi-instance:** project key determines which Jira instance is used (mapped in config.json).
402
+
403
+ ## Workflow
404
+
405
+ 1. `sync_tasks(jql="assignee=currentUser() AND status!=Done")` — fetch fresh
406
+ 2. `read_cached_tasks()` — work offline
407
+ 3. `get_task_details(task_key="PROJ-123")` — deep dive
408
+ 4. `update_task_status(...)` / `add_task_comment(...)` / `log_task_time(...)` — mutate
409
+
410
+ <!-- TOOLKIT:jira-rules END -->
411
+ <!-- TOOLKIT:rag-mcp-rules START -->
412
+ <!-- Auto-injected by ai-toolkit. Re-run to update. -->
413
+
414
+ ## INSTANT ACTION RULE (GOLDEN RULE)
415
+
416
+ **ANY technical question? -> INSTANTLY call `smart_query()` OR `hybrid_search_kb()` BEFORE outputting text!**
417
+
418
+ 1. **Search First:** `smart_query()` or `hybrid_search_kb()` (NEVER skip, even if you "know").
419
+ 2. **Cite Sources:** always include `[PATH: kb/...]`.
420
+ 3. **Strict Order:** Semantic Search -> Files -> External Docs -> General Knowledge.
421
+
422
+ Default tool: `smart_query()`. Use `hybrid_search_kb()` for speed, `crag_search()` for vague queries, `multi_hop_search()` for complex reasoning.
423
+
424
+ ## kb_id vs file_path
425
+
426
+ - `get_document(path=...)` takes `kb_id` from search results (e.g., `local/softspark/project/reference/api.md`)
427
+ - `Read`/`Edit` take filesystem `file_path` (e.g., `./reference/api.md`)
428
+ - **DO NOT CONFUSE** these fields.
429
+
430
+ ## SOPs
431
+
432
+ ALWAYS check `kb/procedures/` first: `smart_query("SOP for <task>")`.
433
+
434
+ <!-- TOOLKIT:rag-mcp-rules END -->
435
+
package/CHANGELOG.md CHANGED
@@ -7,6 +7,13 @@ Versioning follows [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ---
9
9
 
10
+ ## v2.1.2 — Idempotent Update Fix (2026-04-13)
11
+
12
+ ### Fixed
13
+ - **`ai-toolkit update` no longer dirties git** — generators now skip custom rule emission when called by `inject_with_rules()` (which handles injection separately). Previously, `update` caused AGENTS.md and other generated files to gain extra blank lines on every run.
14
+
15
+ ---
16
+
10
17
  ## v2.1.1 — Custom Rules in Generators & README Restructure (2026-04-13)
11
18
 
12
19
  ### Fixed
package/README.md CHANGED
@@ -10,12 +10,12 @@
10
10
 
11
11
  ---
12
12
 
13
- ## What's New in v2.1.1
13
+ ## What's New in v2.1.2
14
14
 
15
- - **Custom rules in generators** — `generate:all` now preserves registered rules from other repos across all platforms
16
- - **README restructured** — 951 292 lines with TOC, "What's New" section, and links to KB docs
17
- - **CLI help completeness** — added missing `--persona` option and `codex` to `--editors`
18
- - **3 new KB docs** — CLI Reference, Unique Features, Ecosystem Comparison (moved from README)
15
+ - **Idempotent update** — `ai-toolkit update` no longer dirties git with extra blank lines in generated files
16
+ - **Custom rules in generators** — `generate:all` preserves registered rules from other repos across all platforms
17
+ - **README restructured** — 951 292 lines with TOC, links to KB docs
18
+ - **3 new KB docs** — CLI Reference, Unique Features, Ecosystem Comparison
19
19
 
20
20
  See [CHANGELOG.md](CHANGELOG.md) for full history.
21
21
 
package/bin/ai-toolkit.js CHANGED
@@ -405,8 +405,9 @@ function handleConfig(args) {
405
405
  */
406
406
  function handleGenerateAll(_args) {
407
407
  for (const [name, gen] of Object.entries(GENERATORS)) {
408
- // Skip agents-md — codex-md generates a superset to the same AGENTS.md
409
- if (name === 'agents-md') continue;
408
+ // Skip codex-md — it injects a Codex config block via markers (used by install --local --editors codex)
409
+ // agents-md generates the full agent list which is the standalone AGENTS.md
410
+ if (name === 'codex-md') continue;
410
411
  writeGeneratorOutput(gen);
411
412
  }
412
413
  // Directory-based generators (multi-file output)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softspark/ai-toolkit",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "description": "Professional-grade AI coding toolkit: 92 skills, 44 agents, multi-platform support (Claude, Cursor, Windsurf, Copilot, Gemini, Cline, Roo Code, Aider, Augment, Google Antigravity, Codex CLI), machine-enforced safety constitution, persona presets, skill security auditor, expanded lifecycle hooks, 11 plugin packs, and benchmark tooling.",
5
5
  "keywords": [
6
6
  "claude",
@@ -46,7 +46,7 @@
46
46
  "evaluate": "python3 scripts/evaluate_skills.py",
47
47
  "benchmark:ecosystem": "python3 scripts/benchmark_ecosystem.py --offline",
48
48
  "benchmark:harvest": "python3 scripts/harvest_ecosystem.py --offline",
49
- "generate:agents": "python3 scripts/generate_codex.py > AGENTS.md",
49
+ "generate:agents": "python3 scripts/generate_agents_md.py > AGENTS.md",
50
50
  "generate:cursor": "python3 scripts/generate_cursor_rules.py > .cursorrules",
51
51
  "generate:llms": "python3 scripts/generate_llms_txt.py > llms.txt && python3 scripts/generate_llms_txt.py --full > llms-full.txt",
52
52
  "generate:windsurf": "python3 scripts/generate_windsurf.py > .windsurfrules",
@@ -6,6 +6,7 @@ Usage: ./scripts/generate_agents_md.py > AGENTS.md
6
6
  """
7
7
  from __future__ import annotations
8
8
 
9
+ import os
9
10
  import sys
10
11
  from pathlib import Path
11
12
 
@@ -87,16 +88,17 @@ def main() -> None:
87
88
  print("---")
88
89
  print()
89
90
 
90
- # Registered custom rules from ~/.softspark/ai-toolkit/rules/
91
- if RULES_DIR.is_dir():
92
- for rule_file in sorted(RULES_DIR.glob("*.md")):
93
- rule_name = rule_file.stem
94
- print(f"<!-- TOOLKIT:{rule_name} START -->")
95
- print("<!-- Auto-injected by ai-toolkit. Re-run to update. -->")
96
- print()
97
- print(rule_file.read_text(encoding="utf-8").rstrip())
98
- print()
99
- print(f"<!-- TOOLKIT:{rule_name} END -->")
91
+ # Registered custom rules skip when called by inject_with_rules()
92
+ if not os.environ.get("_TOOLKIT_INJECT_MODE"):
93
+ if RULES_DIR.is_dir():
94
+ for rule_file in sorted(RULES_DIR.glob("*.md")):
95
+ rule_name = rule_file.stem
96
+ print(f"<!-- TOOLKIT:{rule_name} START -->")
97
+ print("<!-- Auto-injected by ai-toolkit. Re-run to update. -->")
98
+ print()
99
+ print(rule_file.read_text(encoding="utf-8").rstrip())
100
+ print()
101
+ print(f"<!-- TOOLKIT:{rule_name} END -->")
100
102
  print()
101
103
 
102
104
 
@@ -8,6 +8,7 @@ Usage: ./scripts/generate_codex.py > AGENTS.md
8
8
  """
9
9
  from __future__ import annotations
10
10
 
11
+ import os
11
12
  import sys
12
13
  from pathlib import Path
13
14
 
@@ -88,17 +89,19 @@ def main() -> None:
88
89
 
89
90
  print_toolkit_end()
90
91
 
91
- # Registered custom rules from ~/.softspark/ai-toolkit/rules/
92
- if RULES_DIR.is_dir():
93
- for rule_file in sorted(RULES_DIR.glob("*.md")):
94
- rule_name = rule_file.stem
95
- print()
96
- print(f"<!-- TOOLKIT:{rule_name} START -->")
97
- print("<!-- Auto-injected by ai-toolkit. Re-run to update. -->")
98
- print()
99
- print(rule_file.read_text(encoding="utf-8").rstrip())
100
- print()
101
- print(f"<!-- TOOLKIT:{rule_name} END -->")
92
+ # Registered custom rules skip when called by inject_with_rules()
93
+ # (which handles injection separately via inject_section)
94
+ if not os.environ.get("_TOOLKIT_INJECT_MODE"):
95
+ if RULES_DIR.is_dir():
96
+ for rule_file in sorted(RULES_DIR.glob("*.md")):
97
+ rule_name = rule_file.stem
98
+ print()
99
+ print(f"<!-- TOOLKIT:{rule_name} START -->")
100
+ print("<!-- Auto-injected by ai-toolkit. Re-run to update. -->")
101
+ print()
102
+ print(rule_file.read_text(encoding="utf-8").rstrip())
103
+ print()
104
+ print(f"<!-- TOOLKIT:{rule_name} END -->")
102
105
 
103
106
 
104
107
  if __name__ == "__main__":
@@ -26,6 +26,7 @@ Usage::
26
26
  """
27
27
  from __future__ import annotations
28
28
 
29
+ import os
29
30
  import sys
30
31
  from pathlib import Path
31
32
 
@@ -142,14 +143,15 @@ def render_generator(config: dict) -> None:
142
143
  print()
143
144
  print_toolkit_end()
144
145
 
145
- # Registered custom rules from ~/.softspark/ai-toolkit/rules/
146
- if RULES_DIR.is_dir():
147
- for rule_file in sorted(RULES_DIR.glob("*.md")):
148
- rule_name = rule_file.stem
149
- print()
150
- print(f"<!-- TOOLKIT:{rule_name} START -->")
151
- print("<!-- Auto-injected by ai-toolkit. Re-run to update. -->")
152
- print()
153
- print(rule_file.read_text(encoding="utf-8").rstrip())
154
- print()
155
- print(f"<!-- TOOLKIT:{rule_name} END -->")
146
+ # Registered custom rules skip when called by inject_with_rules()
147
+ if not os.environ.get("_TOOLKIT_INJECT_MODE"):
148
+ if RULES_DIR.is_dir():
149
+ for rule_file in sorted(RULES_DIR.glob("*.md")):
150
+ rule_name = rule_file.stem
151
+ print()
152
+ print(f"<!-- TOOLKIT:{rule_name} START -->")
153
+ print("<!-- Auto-injected by ai-toolkit. Re-run to update. -->")
154
+ print()
155
+ print(rule_file.read_text(encoding="utf-8").rstrip())
156
+ print()
157
+ print(f"<!-- TOOLKIT:{rule_name} END -->")
@@ -1,6 +1,7 @@
1
1
  """Install AI tool configs (Cursor, Windsurf, Gemini, Augment, Codex) and local project setup."""
2
2
  from __future__ import annotations
3
3
 
4
+ import os
4
5
  import shutil
5
6
  import subprocess
6
7
  from pathlib import Path
@@ -78,7 +79,8 @@ def inject_with_rules(
78
79
  else:
79
80
  cmd = ["bash", str(scripts_dir / generator_script)]
80
81
 
81
- result = subprocess.run(cmd, capture_output=True, text=True)
82
+ env = {**os.environ, "_TOOLKIT_INJECT_MODE": "1"}
83
+ result = subprocess.run(cmd, capture_output=True, text=True, env=env)
82
84
  if result.returncode != 0:
83
85
  print(f" ERROR: {generator_script} failed: {result.stderr.strip()}")
84
86
  return