ma-agents 3.13.2 → 3.14.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.
- package/lib/agents.js +7 -0
- package/lib/bmad-cache/bmb/.claude-plugin/marketplace.json +3 -3
- package/lib/bmad-cache/bmb/_git_preserved/index +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-b388526edf307cf56f8e65673466cff074105abf.idx +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/{pack-8f8b045fef5af6911495cf3b2a89f1ed75e120f7.pack → pack-b388526edf307cf56f8e65673466cff074105abf.pack} +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-b388526edf307cf56f8e65673466cff074105abf.rev +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/packed-refs +1 -1
- package/lib/bmad-cache/bmb/_git_preserved/refs/heads/main +1 -1
- package/lib/bmad-cache/bmb/_git_preserved/shallow +1 -1
- package/lib/bmad-cache/bmb/package-lock.json +2 -2
- package/lib/bmad-cache/bmb/package.json +1 -1
- package/lib/bmad-cache/bmb/samples/bmad-agent-code-coach/scripts/wake.py +78 -0
- package/lib/bmad-cache/bmb/samples/bmad-agent-creative-muse/scripts/wake.py +78 -0
- package/lib/bmad-cache/bmb/samples/bmad-agent-sentinel/scripts/wake.py +78 -0
- package/lib/bmad-cache/bmb/skills/bmad-agent-builder/assets/customize-template.toml +3 -0
- package/lib/bmad-cache/bmb/skills/bmad-agent-builder/assets/init-sanctum-template.py +11 -5
- package/lib/bmad-cache/bmb/skills/bmad-agent-builder/assets/report-shell.html +1073 -0
- package/lib/bmad-cache/bmb/skills/bmad-agent-builder/assets/wake-template.py +78 -0
- package/lib/bmad-cache/bmb/skills/bmad-agent-builder/customize.toml +48 -0
- package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/count_tokens.py +78 -0
- package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/prepass.py +258 -0
- package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/process-template.py +20 -0
- package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/render_report.py +387 -0
- package/lib/bmad-cache/bmb/skills/bmad-eval-runner/assets/adapter-claude-code.json +9 -0
- package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/aggregate_benchmark.py +236 -0
- package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/memlog.py +197 -0
- package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/run_evals.py +513 -390
- package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/run_triggers.py +347 -251
- package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/tests/test_env_isolation.py +79 -0
- package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/tests/test_trigger_detection.py +123 -0
- package/lib/bmad-cache/bmb/skills/bmad-module-builder/scripts/tests/test-validate-module.py +82 -4
- package/lib/bmad-cache/bmb/skills/bmad-module-builder/scripts/validate-module.py +55 -11
- package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/assets/customize-template.toml +3 -5
- package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/assets/report-shell.html +860 -0
- package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/customize.toml +59 -0
- package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/count_tokens.py +77 -0
- package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/init_skill.py +132 -0
- package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/prepass-prompt-metrics.py +186 -221
- package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/quick_validate.py +117 -0
- package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/render_report.py +387 -0
- package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/tests/test_canon_sync.py +46 -0
- package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/tests/test_count_tokens.py +180 -0
- package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/tests/test_render_report.py +171 -0
- package/lib/bmad-cache/cache-manifest.json +4 -4
- package/lib/bmad-extension/.claude-plugin/marketplace.json.template +1 -1
- package/lib/bmad-extension-plugin/.claude-plugin/marketplace.json +2 -2
- package/lib/bmad.js +6 -1
- package/lib/templates/instruction-block-git.template.md +25 -25
- package/lib/templates/instruction-block-onprem.template.md +86 -86
- package/lib/templates/instruction-block-universal.template.md +29 -29
- package/package.json +3 -3
- package/lib/.bmad-extension-plugin.build-22612-1782454014750/.claude-plugin/marketplace.json +0 -109
- package/lib/.bmad-extension-plugin.build-22612-1782454014750/skills/module-help.csv +0 -62
- package/lib/.bmad-extension-plugin.build-22612-1782454014750/skills/module.yaml +0 -20
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-8f8b045fef5af6911495cf3b2a89f1ed75e120f7.idx +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-8f8b045fef5af6911495cf3b2a89f1ed75e120f7.rev +0 -0
- package/lib/bmad-cache/bmb/skills/bmad-agent-builder/references/sample-init-sanctum.py +0 -274
- package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/generate-html-report.py +0 -534
- package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/prepass-execution-deps.py +0 -337
- package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/prepass-prompt-metrics.py +0 -425
- package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/prepass-sanctum-architecture.py +0 -385
- package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/prepass-structure-capabilities.py +0 -482
- package/lib/bmad-cache/bmb/skills/bmad-eval-runner/assets/Dockerfile +0 -29
- package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/docker_setup.py +0 -115
- package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/generate_report.py +0 -184
- package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/pty_runner.py +0 -171
- package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/utils.py +0 -260
- package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/extract-report-json.py +0 -287
- package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/generate-html-report.py +0 -588
- package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/prepass-execution-deps.py +0 -288
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# DO NOT EDIT -- overwritten on every update.
|
|
2
|
+
#
|
|
3
|
+
# Customization surface for bmad-workflow-builder. This governs how the builder
|
|
4
|
+
# builds: the org-wide context, standards, budgets, and gates applied to every
|
|
5
|
+
# skill it produces. It is distinct from the per-built-skill customize.toml the
|
|
6
|
+
# builder decides on during an individual build.
|
|
7
|
+
#
|
|
8
|
+
# Override files (not edited here):
|
|
9
|
+
# {project-root}/_bmad/custom/bmad-workflow-builder.toml (team)
|
|
10
|
+
# {project-root}/_bmad/custom/bmad-workflow-builder.user.toml (personal)
|
|
11
|
+
|
|
12
|
+
[workflow]
|
|
13
|
+
|
|
14
|
+
# --- Configurable below. Overrides merge per BMad structural rules: ---
|
|
15
|
+
# scalars: override wins • arrays: append
|
|
16
|
+
|
|
17
|
+
# Steps to run before standard activation (config load, greet).
|
|
18
|
+
# Use for org pre-flight loads or compliance checks.
|
|
19
|
+
activation_steps_prepend = []
|
|
20
|
+
|
|
21
|
+
# Steps to run after greet, before the build/analyze loop begins.
|
|
22
|
+
# Use for context-heavy setup once the user has been acknowledged.
|
|
23
|
+
activation_steps_append = []
|
|
24
|
+
|
|
25
|
+
# Standards the builder keeps in mind for the whole session, loaded as context
|
|
26
|
+
# into every build and analyze. Each entry is a literal sentence, a `skill:`
|
|
27
|
+
# skill, or a `file:` path/glob whose contents load as facts. Use for house
|
|
28
|
+
# conventions you want present but not hard-gated (for gates, see build_standards).
|
|
29
|
+
# "Name the output consumer in every skill's overview."
|
|
30
|
+
# "file:{project-root}/_bmad/standards/skill-house-style.md"
|
|
31
|
+
persistent_facts = ["file:{project-root}/**/project-context.md"]
|
|
32
|
+
|
|
33
|
+
# Executed when a build or analyze run completes, after the user has been told
|
|
34
|
+
# the artifact is ready. String scalar (one instruction) or array (in order).
|
|
35
|
+
on_complete = ""
|
|
36
|
+
|
|
37
|
+
# --- Builder gates and budgets ---
|
|
38
|
+
|
|
39
|
+
# Hard standards every BUILT skill must satisfy. Unlike persistent_facts
|
|
40
|
+
# (context), these are enforced: applied as build criteria and checked again as
|
|
41
|
+
# a conformance pass during Analyze. Each entry is a `skill:`, `file:`, or
|
|
42
|
+
# plain-text directive. Append-only. Empty by default (no org gates).
|
|
43
|
+
# "Every skill must ship at least one eval case."
|
|
44
|
+
# "skill:acme-co:security-review"
|
|
45
|
+
build_standards = []
|
|
46
|
+
|
|
47
|
+
# Eval requirement for a build to be declared done. Empty (default) keeps evals
|
|
48
|
+
# opt-in, offered at the eval beat but never forced. Set a directive to gate the
|
|
49
|
+
# build on evals and to flag their absence during Analyze:
|
|
50
|
+
# "baseline" -- require a passing baseline run (skill beats the bare model)
|
|
51
|
+
# "any" -- require at least one eval case to exist and pass
|
|
52
|
+
evals_required = ""
|
|
53
|
+
|
|
54
|
+
# SKILL.md token budget, measured via scripts/count_tokens.py (cl100k_base).
|
|
55
|
+
# Tiered: aim under _desired; between _desired and _budget warns the user; over
|
|
56
|
+
# _budget is a hard finding the builder resolves by progressive disclosure
|
|
57
|
+
# (lifting sections to references/ or assets/) until it is back under budget.
|
|
58
|
+
skill_md_token_desired = 2000
|
|
59
|
+
skill_md_token_budget = 3000
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# /// script
|
|
3
|
+
# requires-python = ">=3.9"
|
|
4
|
+
# dependencies = ["tiktoken"]
|
|
5
|
+
# ///
|
|
6
|
+
"""count_tokens — the single length metric for skill authoring.
|
|
7
|
+
|
|
8
|
+
Token counts replace line counts everywhere in the builder and eval-runner.
|
|
9
|
+
This script reports the token length of a file or of text piped on stdin, using
|
|
10
|
+
the tiktoken cl100k_base encoding. When tiktoken is not installed it falls back
|
|
11
|
+
to a character-based estimate (len(text) // 4) and says so, so the script always
|
|
12
|
+
runs under a bare python3 even with no third-party packages present.
|
|
13
|
+
|
|
14
|
+
Usage:
|
|
15
|
+
count_tokens.py <file> count the tokens in a file
|
|
16
|
+
count_tokens.py --stdin count the tokens read from stdin
|
|
17
|
+
|
|
18
|
+
Output (one line of JSON on stdout):
|
|
19
|
+
{"tokens": <int>, "method": "tiktoken"} when tiktoken loaded
|
|
20
|
+
{"tokens": <int>, "method": "fallback"} when it fell back to chars // 4
|
|
21
|
+
|
|
22
|
+
Budgets this feeds: SKILL.md ~1500-2500, multi-branch reference ~4500,
|
|
23
|
+
single-purpose reference ~9000.
|
|
24
|
+
"""
|
|
25
|
+
import argparse
|
|
26
|
+
import json
|
|
27
|
+
import sys
|
|
28
|
+
|
|
29
|
+
ENCODING = "cl100k_base"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def count_tokens(text: str) -> tuple[int, str]:
|
|
33
|
+
"""Return (token_count, method).
|
|
34
|
+
|
|
35
|
+
Tries tiktoken's cl100k_base encoding first. If tiktoken cannot be imported
|
|
36
|
+
or initialized, estimates with len(text) // 4 and reports method "fallback".
|
|
37
|
+
"""
|
|
38
|
+
try:
|
|
39
|
+
import tiktoken
|
|
40
|
+
except Exception:
|
|
41
|
+
return len(text) // 4, "fallback"
|
|
42
|
+
try:
|
|
43
|
+
enc = tiktoken.get_encoding(ENCODING)
|
|
44
|
+
except Exception:
|
|
45
|
+
return len(text) // 4, "fallback"
|
|
46
|
+
return len(enc.encode(text)), "tiktoken"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def read_input(args) -> str:
|
|
50
|
+
if args.stdin:
|
|
51
|
+
return sys.stdin.read()
|
|
52
|
+
with open(args.file, encoding="utf-8") as f:
|
|
53
|
+
return f.read()
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def main(argv: list[str] | None = None) -> int:
|
|
57
|
+
p = argparse.ArgumentParser(
|
|
58
|
+
description=__doc__,
|
|
59
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
60
|
+
)
|
|
61
|
+
p.add_argument("file", nargs="?", help="path to the file to count")
|
|
62
|
+
p.add_argument("--stdin", action="store_true", help="read text from stdin instead of a file")
|
|
63
|
+
args = p.parse_args(argv)
|
|
64
|
+
|
|
65
|
+
if not args.stdin and not args.file:
|
|
66
|
+
p.error("provide a file path or --stdin")
|
|
67
|
+
if args.stdin and args.file:
|
|
68
|
+
p.error("provide either a file path or --stdin, not both")
|
|
69
|
+
|
|
70
|
+
text = read_input(args)
|
|
71
|
+
tokens, method = count_tokens(text)
|
|
72
|
+
print(json.dumps({"tokens": tokens, "method": method}))
|
|
73
|
+
return 0
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
if __name__ == "__main__":
|
|
77
|
+
sys.exit(main())
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# /// script
|
|
3
|
+
# requires-python = ">=3.9"
|
|
4
|
+
# ///
|
|
5
|
+
"""init_skill — deterministic scaffolder for a new skill.
|
|
6
|
+
|
|
7
|
+
Creates the skill directory and writes SKILL.md from the builder's template, which
|
|
8
|
+
carries the embedded archetype guidance and the delete-when-done marker. The name
|
|
9
|
+
is normalized to hyphen-case and capped at 64 chars. Only the resource directories
|
|
10
|
+
the build flow asked for are stubbed, so the skill starts as small as it can. A
|
|
11
|
+
customize.toml is emitted only when customization was accepted, never by default.
|
|
12
|
+
|
|
13
|
+
This script does the mechanical scaffolding so the model spends its turns on the
|
|
14
|
+
content, not on mkdir and string substitution.
|
|
15
|
+
|
|
16
|
+
Usage:
|
|
17
|
+
init_skill.py --name "My New Skill" --dest /path/to/skills
|
|
18
|
+
init_skill.py --name foo --dest DIR --dirs references,scripts,assets
|
|
19
|
+
init_skill.py --name foo --dest DIR --customizable
|
|
20
|
+
init_skill.py --name foo --dest DIR \
|
|
21
|
+
--template /abs/SKILL-template.md --customize-template /abs/customize-template.toml
|
|
22
|
+
|
|
23
|
+
Output: one JSON object on stdout describing what was created.
|
|
24
|
+
Exit code 0 on success, 1 on failure (e.g. the target already exists).
|
|
25
|
+
"""
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
import argparse
|
|
29
|
+
import json
|
|
30
|
+
import re
|
|
31
|
+
import sys
|
|
32
|
+
from pathlib import Path
|
|
33
|
+
|
|
34
|
+
KNOWN_DIRS = ("references", "scripts", "assets", "agents")
|
|
35
|
+
SCRIPT_DIR = Path(__file__).resolve().parent
|
|
36
|
+
DEFAULT_TEMPLATE = SCRIPT_DIR.parent / "assets" / "SKILL-template.md"
|
|
37
|
+
DEFAULT_CUSTOMIZE = SCRIPT_DIR.parent / "assets" / "customize-template.toml"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def normalize_name(raw: str, max_len: int = 64) -> str:
|
|
41
|
+
"""Lowercase, collapse non-alphanumerics to single hyphens, trim, cap at max_len."""
|
|
42
|
+
s = raw.strip().lower()
|
|
43
|
+
s = re.sub(r"[^a-z0-9]+", "-", s)
|
|
44
|
+
s = s.strip("-")
|
|
45
|
+
if len(s) > max_len:
|
|
46
|
+
s = s[:max_len].rstrip("-")
|
|
47
|
+
return s
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def fill_template(template: str, skill_name: str) -> str:
|
|
51
|
+
return template.replace("{skill-name}", skill_name)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def scaffold(args) -> dict:
|
|
55
|
+
skill_name = normalize_name(args.name)
|
|
56
|
+
if not skill_name:
|
|
57
|
+
raise ValueError(f"name {args.name!r} normalized to an empty string")
|
|
58
|
+
|
|
59
|
+
skill_dir = Path(args.dest) / skill_name
|
|
60
|
+
if skill_dir.exists():
|
|
61
|
+
raise FileExistsError(f"{skill_dir} already exists")
|
|
62
|
+
|
|
63
|
+
template_path = Path(args.template) if args.template else DEFAULT_TEMPLATE
|
|
64
|
+
if not template_path.is_file():
|
|
65
|
+
raise FileNotFoundError(f"template not found: {template_path}")
|
|
66
|
+
|
|
67
|
+
requested = []
|
|
68
|
+
for d in (args.dirs or "").split(","):
|
|
69
|
+
d = d.strip()
|
|
70
|
+
if not d:
|
|
71
|
+
continue
|
|
72
|
+
if d not in KNOWN_DIRS:
|
|
73
|
+
raise ValueError(f"unknown resource dir {d!r}; known: {', '.join(KNOWN_DIRS)}")
|
|
74
|
+
requested.append(d)
|
|
75
|
+
|
|
76
|
+
skill_dir.mkdir(parents=True)
|
|
77
|
+
created = [str(skill_dir)]
|
|
78
|
+
|
|
79
|
+
skill_md = skill_dir / "SKILL.md"
|
|
80
|
+
skill_md.write_text(fill_template(template_path.read_text(encoding="utf-8"), skill_name), encoding="utf-8")
|
|
81
|
+
created.append(str(skill_md))
|
|
82
|
+
|
|
83
|
+
for d in requested:
|
|
84
|
+
sub = skill_dir / d
|
|
85
|
+
sub.mkdir()
|
|
86
|
+
created.append(str(sub))
|
|
87
|
+
|
|
88
|
+
customize_emitted = False
|
|
89
|
+
if args.customizable:
|
|
90
|
+
ct_path = Path(args.customize_template) if args.customize_template else DEFAULT_CUSTOMIZE
|
|
91
|
+
if not ct_path.is_file():
|
|
92
|
+
raise FileNotFoundError(f"customize template not found: {ct_path}")
|
|
93
|
+
target = skill_dir / "customize.toml"
|
|
94
|
+
target.write_text(
|
|
95
|
+
ct_path.read_text(encoding="utf-8").replace("{skill-name}", skill_name),
|
|
96
|
+
encoding="utf-8",
|
|
97
|
+
)
|
|
98
|
+
created.append(str(target))
|
|
99
|
+
customize_emitted = True
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
"ok": True,
|
|
103
|
+
"skill_name": skill_name,
|
|
104
|
+
"skill_dir": str(skill_dir),
|
|
105
|
+
"dirs_stubbed": requested,
|
|
106
|
+
"customize_toml": customize_emitted,
|
|
107
|
+
"created": created,
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def main(argv: list[str] | None = None) -> int:
|
|
112
|
+
p = argparse.ArgumentParser(description="Deterministic scaffolder for a new skill")
|
|
113
|
+
p.add_argument("--name", required=True, help="raw skill name; normalized to hyphen-case <=64")
|
|
114
|
+
p.add_argument("--dest", required=True, help="parent directory the skill folder is created under")
|
|
115
|
+
p.add_argument("--dirs", default="", help="comma-separated resource dirs to stub (references,scripts,assets,agents)")
|
|
116
|
+
p.add_argument("--customizable", action="store_true", help="emit customize.toml (only when customization was accepted)")
|
|
117
|
+
p.add_argument("--template", help="override path to the SKILL.md template")
|
|
118
|
+
p.add_argument("--customize-template", help="override path to the customize.toml template")
|
|
119
|
+
args = p.parse_args(argv)
|
|
120
|
+
|
|
121
|
+
try:
|
|
122
|
+
result = scaffold(args)
|
|
123
|
+
except (FileExistsError, FileNotFoundError, ValueError) as e:
|
|
124
|
+
print(json.dumps({"ok": False, "error": str(e)}))
|
|
125
|
+
return 1
|
|
126
|
+
|
|
127
|
+
print(json.dumps(result, indent=2))
|
|
128
|
+
return 0
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
if __name__ == "__main__":
|
|
132
|
+
sys.exit(main())
|