ma-agents 3.13.2 → 3.14.1

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 (107) hide show
  1. package/README.md +3 -3
  2. package/lib/agents.js +9 -2
  3. package/lib/bmad-cache/bmb/.claude-plugin/marketplace.json +3 -3
  4. package/lib/bmad-cache/bmb/_git_preserved/index +0 -0
  5. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-b388526edf307cf56f8e65673466cff074105abf.idx +0 -0
  6. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/{pack-8f8b045fef5af6911495cf3b2a89f1ed75e120f7.pack → pack-b388526edf307cf56f8e65673466cff074105abf.pack} +0 -0
  7. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-b388526edf307cf56f8e65673466cff074105abf.rev +0 -0
  8. package/lib/bmad-cache/bmb/_git_preserved/packed-refs +1 -1
  9. package/lib/bmad-cache/bmb/_git_preserved/refs/heads/main +1 -1
  10. package/lib/bmad-cache/bmb/_git_preserved/shallow +1 -1
  11. package/lib/bmad-cache/bmb/package-lock.json +2 -2
  12. package/lib/bmad-cache/bmb/package.json +1 -1
  13. package/lib/bmad-cache/bmb/samples/bmad-agent-code-coach/scripts/wake.py +78 -0
  14. package/lib/bmad-cache/bmb/samples/bmad-agent-creative-muse/scripts/wake.py +78 -0
  15. package/lib/bmad-cache/bmb/samples/bmad-agent-sentinel/scripts/wake.py +78 -0
  16. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/assets/customize-template.toml +3 -0
  17. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/assets/init-sanctum-template.py +11 -5
  18. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/assets/report-shell.html +1073 -0
  19. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/assets/wake-template.py +78 -0
  20. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/customize.toml +48 -0
  21. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/count_tokens.py +78 -0
  22. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/prepass.py +258 -0
  23. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/process-template.py +20 -0
  24. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/render_report.py +387 -0
  25. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/assets/adapter-claude-code.json +9 -0
  26. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/aggregate_benchmark.py +236 -0
  27. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/memlog.py +197 -0
  28. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/run_evals.py +513 -390
  29. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/run_triggers.py +347 -251
  30. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/tests/test_env_isolation.py +79 -0
  31. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/tests/test_trigger_detection.py +123 -0
  32. package/lib/bmad-cache/bmb/skills/bmad-module-builder/scripts/tests/test-validate-module.py +82 -4
  33. package/lib/bmad-cache/bmb/skills/bmad-module-builder/scripts/validate-module.py +55 -11
  34. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/assets/customize-template.toml +3 -5
  35. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/assets/report-shell.html +860 -0
  36. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/customize.toml +59 -0
  37. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/count_tokens.py +77 -0
  38. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/init_skill.py +132 -0
  39. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/prepass-prompt-metrics.py +186 -221
  40. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/quick_validate.py +117 -0
  41. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/render_report.py +387 -0
  42. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/tests/test_canon_sync.py +46 -0
  43. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/tests/test_count_tokens.py +180 -0
  44. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/tests/test_render_report.py +171 -0
  45. package/lib/bmad-cache/cache-manifest.json +4 -4
  46. package/lib/bmad-customize/bmm-qa.customize.yaml +3 -3
  47. package/lib/bmad-extension/.claude-plugin/marketplace.json.template +3 -2
  48. package/lib/bmad-extension/skills/bmad-dev-epic/SKILL.md +101 -0
  49. package/lib/bmad-extension/skills/bmad-dev-epic/bmad-skill-manifest.yaml +3 -0
  50. package/lib/bmad-extension/skills/bmad-dev-epic/checklist.md +44 -0
  51. package/lib/bmad-extension/skills/bmad-dev-epic/customize.toml +54 -0
  52. package/lib/bmad-extension/skills/bmad-dev-epic/references/story-pipeline.md +112 -0
  53. package/lib/bmad-extension/skills/bmad-dev-epic/steps/step-01-intake.md +59 -0
  54. package/lib/bmad-extension/skills/bmad-dev-epic/steps/step-02-plan-waves.md +56 -0
  55. package/lib/bmad-extension/skills/bmad-dev-epic/steps/step-03-epic-branch.md +35 -0
  56. package/lib/bmad-extension/skills/bmad-dev-epic/steps/step-04-run-waves.md +49 -0
  57. package/lib/bmad-extension/skills/bmad-dev-epic/steps/step-05-epic-adversarial.md +31 -0
  58. package/lib/bmad-extension/skills/bmad-dev-epic/steps/step-06-release.md +57 -0
  59. package/lib/bmad-extension/skills/bmad-dev-epic/steps/step-07-report.md +40 -0
  60. package/lib/bmad-extension/skills/ma-agent-sqa/SKILL.md +3 -3
  61. package/lib/bmad-extension/skills/ma-agent-sqa/bmad-skill-manifest.yaml +1 -1
  62. package/lib/bmad-extension/skills/module-help.csv +2 -1
  63. package/lib/bmad-extension/skills/module.yaml +1 -1
  64. package/lib/bmad-extension/skills/sqa-audit/SKILL.md +2 -2
  65. package/lib/bmad-extension/skills/sqa-ieee12207/SKILL.md +3 -3
  66. package/lib/bmad-extension/skills/sqa-requirements-quality/SKILL.md +2 -2
  67. package/lib/bmad-extension-plugin/.claude-plugin/marketplace.json +4 -3
  68. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/SKILL.md +101 -0
  69. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/bmad-skill-manifest.yaml +3 -0
  70. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/checklist.md +44 -0
  71. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/customize.toml +54 -0
  72. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/references/story-pipeline.md +112 -0
  73. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/steps/step-01-intake.md +59 -0
  74. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/steps/step-02-plan-waves.md +56 -0
  75. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/steps/step-03-epic-branch.md +35 -0
  76. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/steps/step-04-run-waves.md +49 -0
  77. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/steps/step-05-epic-adversarial.md +31 -0
  78. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/steps/step-06-release.md +57 -0
  79. package/lib/bmad-extension-plugin/skills/bmad-dev-epic/steps/step-07-report.md +40 -0
  80. package/lib/bmad-extension-plugin/skills/ma-agent-sqa/SKILL.md +3 -3
  81. package/lib/bmad-extension-plugin/skills/ma-agent-sqa/bmad-skill-manifest.yaml +1 -1
  82. package/lib/bmad-extension-plugin/skills/module-help.csv +2 -1
  83. package/lib/bmad-extension-plugin/skills/module.yaml +1 -1
  84. package/lib/bmad-extension-plugin/skills/sqa-audit/SKILL.md +2 -2
  85. package/lib/bmad-extension-plugin/skills/sqa-ieee12207/SKILL.md +3 -3
  86. package/lib/bmad-extension-plugin/skills/sqa-requirements-quality/SKILL.md +2 -2
  87. package/lib/bmad.js +6 -1
  88. package/package.json +3 -3
  89. package/lib/.bmad-extension-plugin.build-22612-1782454014750/.claude-plugin/marketplace.json +0 -109
  90. package/lib/.bmad-extension-plugin.build-22612-1782454014750/skills/module-help.csv +0 -62
  91. package/lib/.bmad-extension-plugin.build-22612-1782454014750/skills/module.yaml +0 -20
  92. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-8f8b045fef5af6911495cf3b2a89f1ed75e120f7.idx +0 -0
  93. package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-8f8b045fef5af6911495cf3b2a89f1ed75e120f7.rev +0 -0
  94. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/references/sample-init-sanctum.py +0 -274
  95. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/generate-html-report.py +0 -534
  96. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/prepass-execution-deps.py +0 -337
  97. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/prepass-prompt-metrics.py +0 -425
  98. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/prepass-sanctum-architecture.py +0 -385
  99. package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/prepass-structure-capabilities.py +0 -482
  100. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/assets/Dockerfile +0 -29
  101. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/docker_setup.py +0 -115
  102. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/generate_report.py +0 -184
  103. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/pty_runner.py +0 -171
  104. package/lib/bmad-cache/bmb/skills/bmad-eval-runner/scripts/utils.py +0 -260
  105. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/extract-report-json.py +0 -287
  106. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/generate-html-report.py +0 -588
  107. package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/prepass-execution-deps.py +0 -288
@@ -0,0 +1,197 @@
1
+ #!/usr/bin/env python3
2
+ # /// script
3
+ # requires-python = ">=3.10"
4
+ # ///
5
+ """memlog -- an append-only memory log: LLM-optimal working memory for a skill.
6
+
7
+ A memlog is the dense, chronological record of everything that mattered in a piece of
8
+ work -- every decision, direction, assumption, gap, note, and event as it happened --
9
+ kept minimal like human memory: only what is important, never bloated. It persists
10
+ ACROSS sessions, so a fresh session can load it once and continue. It is NOT a
11
+ deliverable; downstream artifacts (a brief, a PRD, a report) are derived from it on
12
+ demand.
13
+
14
+ It is a FLAT log: there are no sections or grouping. Every entry is one line, recorded
15
+ at the END in the order it happened. The chronology itself is the structure.
16
+
17
+ Two invariants make it trustworthy:
18
+
19
+ 1. Append-only, chronological. Entries land at the end, in the order they happen.
20
+ Nothing is ever inserted backward, reordered, edited, or removed. There is no
21
+ edit or delete subcommand by design; history is never rewritten.
22
+ 2. Write-only / blind. Every command is an atomic, context-free write and echoes the
23
+ new state as one line of JSON, so the caller never re-reads the file mid-session.
24
+ The one time the file is read is on resume, and the caller reads it itself, not
25
+ via this script.
26
+
27
+ Atomicity: every write goes to a temp file, is flushed and fsync'd, then atomically
28
+ renamed over the target, so a crash never leaves a half-written entry.
29
+
30
+ The file shape (.memlog.md):
31
+
32
+ ---
33
+ subject: Onboarding flow for a budgeting app
34
+ status: active
35
+ updated: 2026-06-06T14:22
36
+ ---
37
+
38
+ - (note) user picked the lean draft path
39
+ - (decision) lead with one pre-categorized account; defer multi-account import
40
+ - (direction) optimize for the anxious first-timer, not the power user
41
+ - (assumption) open-banking consent is available in the target market
42
+ - (gap) no data yet on week-1 retention baseline
43
+ - (event) ran baseline eval mode
44
+
45
+ Each entry carries a typed tag drawn from a fixed vocabulary so the chronology stays
46
+ machine-scannable: decision, direction, assumption, gap, note, event.
47
+
48
+ Commands:
49
+ init --path FILE [--field k=v ...] create the memlog (errors if it exists)
50
+ append --path FILE --type T --text STR append one typed entry at the end
51
+ set-complete --path FILE flip frontmatter status to complete
52
+
53
+ The path is the memlog file itself (conventionally {run-folder}/.memlog.md).
54
+ """
55
+ import argparse
56
+ import json
57
+ import os
58
+ import sys
59
+ from datetime import datetime
60
+ from pathlib import Path
61
+
62
+ ENTRY_TYPES = ("decision", "direction", "assumption", "gap", "note", "event")
63
+
64
+
65
+ def now() -> str:
66
+ return datetime.now().strftime("%Y-%m-%dT%H:%M")
67
+
68
+
69
+ def split(text: str) -> tuple[dict, str]:
70
+ """Return (frontmatter dict in source order, body str). Frontmatter is plain key: value.
71
+
72
+ The closing fence is the first line that is *exactly* `---`, so a `---` inside a
73
+ field value (subject is free user text) never truncates the frontmatter.
74
+ """
75
+ lines = text.splitlines()
76
+ if not lines or lines[0] != "---":
77
+ raise ValueError(".memlog.md has no frontmatter")
78
+ end = next((i for i in range(1, len(lines)) if lines[i] == "---"), None)
79
+ if end is None:
80
+ raise ValueError(".memlog.md frontmatter is not terminated")
81
+ meta: dict[str, str] = {}
82
+ for line in lines[1:end]:
83
+ if ":" in line:
84
+ k, v = line.split(":", 1)
85
+ meta[k.strip()] = v.strip()
86
+ return meta, "\n".join(lines[end + 1:]).lstrip("\n")
87
+
88
+
89
+ def render(meta: dict, body: str) -> str:
90
+ # Neutralize newlines in values so a multi-line field can't break the fence on re-read.
91
+ fm = "\n".join(f"{k}: {' '.join(str(v).splitlines())}" for k, v in meta.items())
92
+ return "---\n" + fm + "\n---\n\n" + body.rstrip("\n") + "\n"
93
+
94
+
95
+ def touch(meta: dict) -> None:
96
+ """Stamp `updated` and keep it last so the field order stays predictable."""
97
+ meta.pop("updated", None)
98
+ meta["updated"] = now()
99
+
100
+
101
+ def write_atomic(path: Path, text: str) -> None:
102
+ """Temp + flush + fsync + atomic rename, so a crash never half-writes an entry."""
103
+ tmp = path.with_suffix(path.suffix + ".tmp")
104
+ with open(tmp, "w", encoding="utf-8") as f:
105
+ f.write(text)
106
+ f.flush()
107
+ os.fsync(f.fileno())
108
+ os.replace(tmp, path)
109
+
110
+
111
+ def entry_count(body: str) -> int:
112
+ return sum(1 for ln in body.splitlines() if ln.startswith("- "))
113
+
114
+
115
+ def ack(path: Path, meta: dict, body: str, entry_type: str = "") -> None:
116
+ """Echo new state so the caller never re-reads the file to know where it stands."""
117
+ out = {
118
+ "ok": True,
119
+ "memlog": str(path),
120
+ "status": meta.get("status", ""),
121
+ "n": entry_count(body),
122
+ }
123
+ if entry_type:
124
+ out["type"] = entry_type
125
+ print(json.dumps(out))
126
+
127
+
128
+ def cmd_init(args) -> int:
129
+ path = Path(args.path)
130
+ if path.exists():
131
+ print(f"error: {path} already exists; use append/set-complete to update it", file=sys.stderr)
132
+ return 2
133
+ path.parent.mkdir(parents=True, exist_ok=True)
134
+ meta: dict[str, str] = {}
135
+ for pair in args.field or []:
136
+ if "=" not in pair:
137
+ print(f"error: --field expects key=value, got {pair!r}", file=sys.stderr)
138
+ return 2
139
+ k, v = pair.split("=", 1)
140
+ meta[k.strip()] = v.strip()
141
+ meta.setdefault("status", "active")
142
+ touch(meta)
143
+ write_atomic(path, render(meta, ""))
144
+ ack(path, meta, "")
145
+ return 0
146
+
147
+
148
+ def cmd_append(args) -> int:
149
+ path = Path(args.path)
150
+ if args.type not in ENTRY_TYPES:
151
+ print(f"error: --type must be one of {', '.join(ENTRY_TYPES)}; got {args.type!r}", file=sys.stderr)
152
+ return 2
153
+ meta, body = split(path.read_text(encoding="utf-8"))
154
+ text = " ".join(args.text.split()) # collapse newlines/runs -> one-line entry
155
+ entry = f"- ({args.type}) {text}"
156
+ body = (body.rstrip("\n") + "\n" + entry) if body.strip() else entry # always at the end
157
+ touch(meta)
158
+ write_atomic(path, render(meta, body))
159
+ ack(path, meta, body, args.type)
160
+ return 0
161
+
162
+
163
+ def cmd_set_complete(args) -> int:
164
+ path = Path(args.path)
165
+ meta, body = split(path.read_text(encoding="utf-8"))
166
+ meta["status"] = "complete"
167
+ touch(meta)
168
+ write_atomic(path, render(meta, body))
169
+ ack(path, meta, body)
170
+ return 0
171
+
172
+
173
+ def main(argv: list[str] | None = None) -> int:
174
+ p = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
175
+ sub = p.add_subparsers(dest="cmd", required=True)
176
+
177
+ pi = sub.add_parser("init", help="create the memlog")
178
+ pi.add_argument("--path", required=True, help="memlog file path (e.g. {run-folder}/.memlog.md)")
179
+ pi.add_argument("--field", action="append", metavar="KEY=VALUE", help="frontmatter field (repeatable)")
180
+ pi.set_defaults(func=cmd_init)
181
+
182
+ pa = sub.add_parser("append", help="append one typed entry at the end")
183
+ pa.add_argument("--path", required=True)
184
+ pa.add_argument("--type", required=True, choices=ENTRY_TYPES, help="entry kind")
185
+ pa.add_argument("--text", required=True)
186
+ pa.set_defaults(func=cmd_append)
187
+
188
+ pc = sub.add_parser("set-complete", help="flip frontmatter status to complete")
189
+ pc.add_argument("--path", required=True)
190
+ pc.set_defaults(func=cmd_set_complete)
191
+
192
+ args = p.parse_args(argv)
193
+ return args.func(args)
194
+
195
+
196
+ if __name__ == "__main__":
197
+ sys.exit(main())