@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 +47 -0
- package/CHANGELOG.md +7 -0
- package/README.md +5 -5
- package/bin/ai-toolkit.js +3 -2
- package/package.json +2 -2
- package/scripts/generate_agents_md.py +12 -10
- package/scripts/generate_codex.py +14 -11
- package/scripts/generator_base.py +13 -11
- package/scripts/install_steps/ai_tools.py +3 -1
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.
|
|
13
|
+
## What's New in v2.1.2
|
|
14
14
|
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
17
|
-
- **
|
|
18
|
-
- **3 new KB docs** — CLI Reference, Unique Features, Ecosystem Comparison
|
|
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
|
|
409
|
-
|
|
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.
|
|
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/
|
|
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
|
|
91
|
-
if
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
|
146
|
-
if
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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
|
-
|
|
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
|