chore(bmad-module): frontmatter/CRLF, test hygiene, fixture corrections
- frontmatter: accept a block that ends at EOF (optional trailing newline). - legacy-resolver: accept CRLF frontmatter delimiters. - integration.test.sh: unique mktemp stderr capture, explicit if/then/else assertions (drop the SC2015 && ok || ko chains), plus unknown-flag and invalid-channel usage-error cases. - test-installation-components: clear the resolution cache in a finally. - acme-devlog fixtures: correct the uninstall note to the flat TOML layout, replace `ls -t | head` with a glob/-nt lookup, drop the always-on devlog config file: fact, "run" -> "invoke" wording, and reconcile the devlog-write template contract with the bundled template. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
cbf87c414d
commit
08dc71f8cc
|
|
@ -3,7 +3,7 @@ import { parse as parseYaml } from './vendor/yaml.mjs';
|
||||||
// Parse YAML frontmatter from a markdown string. Returns the parsed object,
|
// Parse YAML frontmatter from a markdown string. Returns the parsed object,
|
||||||
// or null if no frontmatter block is present / it failed to parse.
|
// or null if no frontmatter block is present / it failed to parse.
|
||||||
export function parseFrontmatter(content) {
|
export function parseFrontmatter(content) {
|
||||||
const m = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n/);
|
const m = content.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/);
|
||||||
if (!m) return null;
|
if (!m) return null;
|
||||||
try {
|
try {
|
||||||
return parseYaml(m[1]);
|
return parseYaml(m[1]);
|
||||||
|
|
|
||||||
|
|
@ -305,7 +305,7 @@ async function readModuleYaml(yamlAbs) {
|
||||||
async function parseSkillFrontmatter(skillDirAbs) {
|
async function parseSkillFrontmatter(skillDirAbs) {
|
||||||
try {
|
try {
|
||||||
const content = await fs.readFile(path.join(skillDirAbs, 'SKILL.md'), 'utf8');
|
const content = await fs.readFile(path.join(skillDirAbs, 'SKILL.md'), 'utf8');
|
||||||
const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
const match = content.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/);
|
||||||
if (!match) return { name: '', description: '' };
|
if (!match) return { name: '', description: '' };
|
||||||
const parsed = parseYaml(match[1]) || {};
|
const parsed = parseYaml(match[1]) || {};
|
||||||
return { name: parsed.name || '', description: parsed.description || '' };
|
return { name: parsed.name || '', description: parsed.description || '' };
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ See `docs/index.md` (in this repo) for the customization recipe.
|
||||||
## Uninstall
|
## Uninstall
|
||||||
|
|
||||||
```
|
```
|
||||||
bmad-module remove devlog # leaves _bmad/custom/devlog/ intact
|
bmad-module remove devlog # leaves _bmad/custom/bmad-agent-historian*.toml intact
|
||||||
bmad-module remove devlog --purge # removes user customizations too
|
bmad-module remove devlog --purge # removes user customizations too
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,16 @@ if [ -f "$today_file" ]; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Fall back to the most recent .md by mtime.
|
# Fall back to the most recent .md by mtime. Glob + `-nt` instead of parsing
|
||||||
latest=$(ls -t "${devlog_path}"/*.md 2>/dev/null | head -n 1 || true)
|
# `ls` so filenames with spaces/newlines are handled safely (and ShellCheck
|
||||||
|
# stays happy).
|
||||||
|
latest=""
|
||||||
|
for f in "${devlog_path}"/*.md; do
|
||||||
|
[ -e "$f" ] || continue
|
||||||
|
if [ -z "$latest" ] || [ "$f" -nt "$latest" ]; then
|
||||||
|
latest="$f"
|
||||||
|
fi
|
||||||
|
done
|
||||||
if [ -n "$latest" ]; then
|
if [ -n "$latest" ]; then
|
||||||
echo "=== Most recent devlog ($(basename "$latest" .md)) ==="
|
echo "=== Most recent devlog ($(basename "$latest" .md)) ==="
|
||||||
cat "$latest"
|
cat "$latest"
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,11 @@ activation_steps_append = []
|
||||||
|
|
||||||
# Persistent facts the agent keeps in mind for the whole session.
|
# Persistent facts the agent keeps in mind for the whole session.
|
||||||
# `file:` entries are loaded as content; literal entries are facts verbatim.
|
# `file:` entries are loaded as content; literal entries are facts verbatim.
|
||||||
|
# Note: the devlog config is intentionally NOT loaded here as an always-on
|
||||||
|
# `file:` fact — it may not exist on first run, which would fail activation
|
||||||
|
# before the `/bmad-devlog-setup` fallback can create it. Skills read the
|
||||||
|
# config after checking it exists.
|
||||||
persistent_facts = [
|
persistent_facts = [
|
||||||
"file:{project-root}/_bmad/devlog/config.yaml",
|
|
||||||
"The devlog is a primary source. Never invent context that isn't written down.",
|
"The devlog is a primary source. Never invent context that isn't written down.",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ Walks devlog entries in a date range and produces a structured summary: themes,
|
||||||
|
|
||||||
### Step 1: Resolve config
|
### Step 1: Resolve config
|
||||||
|
|
||||||
Read `{project-root}/_bmad/devlog/config.yaml`. If missing, run `/bmad-devlog-setup` first.
|
Read `{project-root}/_bmad/devlog/config.yaml`. If missing, invoke `/bmad-devlog-setup` first.
|
||||||
|
|
||||||
### Step 2: Parse the range argument
|
### Step 2: Parse the range argument
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ Read `{project-root}/_bmad/devlog/config.yaml`. Expect:
|
||||||
- `devlog_path` (absolute path)
|
- `devlog_path` (absolute path)
|
||||||
- `entry_format` (`iso` | `weekly` | `monthly`)
|
- `entry_format` (`iso` | `weekly` | `monthly`)
|
||||||
|
|
||||||
If config is missing, run `/bmad-devlog-setup` first.
|
If config is missing, invoke `/bmad-devlog-setup` first.
|
||||||
|
|
||||||
### Step 2: Determine the entry file
|
### Step 2: Determine the entry file
|
||||||
|
|
||||||
|
|
@ -26,7 +26,7 @@ If config is missing, run `/bmad-devlog-setup` first.
|
||||||
|
|
||||||
### Step 3: Initialize if absent
|
### Step 3: Initialize if absent
|
||||||
|
|
||||||
If the file doesn't exist, copy `./assets/template.md` to the target path. Substitute `{{date}}`, `{{author}}` (from `user_name`), and `{{week}}`/`{{month}}` placeholders.
|
If the file doesn't exist, copy `./assets/template.md` to the target path. Substitute `{{date}}` and `{{author}}` (from `user_name`). For `weekly`/`monthly`, render the `{{date}}` heading from the period value (e.g. `2026-W21` or `2026-05`) instead of reusing the daily date.
|
||||||
|
|
||||||
### Step 4: Collect entry content
|
### Step 4: Collect entry content
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,11 +34,13 @@ ko() { printf ' \033[31m✗\033[0m %s\n' "$*"; fail=$((fail+1)); }
|
||||||
|
|
||||||
# Wrapper that captures stdout/stderr/exit code into globals.
|
# Wrapper that captures stdout/stderr/exit code into globals.
|
||||||
run() {
|
run() {
|
||||||
|
local stderr_file
|
||||||
|
stderr_file="$(mktemp)"
|
||||||
set +e
|
set +e
|
||||||
STDOUT="$(node "${MODULE_JS}" "$@" 2>/tmp/bmad-module-stderr.$$)"
|
STDOUT="$(node "${MODULE_JS}" "$@" 2>"${stderr_file}")"
|
||||||
EXIT=$?
|
EXIT=$?
|
||||||
STDERR="$(cat /tmp/bmad-module-stderr.$$)"
|
STDERR="$(cat "${stderr_file}")"
|
||||||
rm -f /tmp/bmad-module-stderr.$$
|
rm -f "${stderr_file}"
|
||||||
set -e
|
set -e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,15 +117,22 @@ ok "skeleton seeded at ${WORKDIR}/_bmad/"
|
||||||
note "list (no modules)"
|
note "list (no modules)"
|
||||||
run list
|
run list
|
||||||
assert_exit 0 "list empty"
|
assert_exit 0 "list empty"
|
||||||
[[ "${STDOUT}" == *"no modules installed"* ]] && ok "stdout reports empty" \
|
if [[ "${STDOUT}" == *"no modules installed"* ]]; then ok "stdout reports empty"
|
||||||
|| ko "expected 'no modules installed' in stdout: ${STDOUT}"
|
else ko "expected 'no modules installed' in stdout: ${STDOUT}"; fi
|
||||||
|
|
||||||
|
# ─── 1a. usage errors: unknown flag / invalid channel reject early ───────────
|
||||||
|
note "unknown flag and invalid channel → exit 2"
|
||||||
|
run install "${EXAMPLES}/minimal/acme-md-lint" --bogus
|
||||||
|
assert_exit 2 "unknown flag rejected"
|
||||||
|
run install "${EXAMPLES}/minimal/acme-md-lint" --channel stabl --dry-run
|
||||||
|
assert_exit 2 "invalid channel rejected"
|
||||||
|
|
||||||
# ─── 2. dry-run install of minimal module ────────────────────────────────────
|
# ─── 2. dry-run install of minimal module ────────────────────────────────────
|
||||||
note "install --dry-run examples/minimal/acme-md-lint"
|
note "install --dry-run examples/minimal/acme-md-lint"
|
||||||
run install "${EXAMPLES}/minimal/acme-md-lint" --dry-run
|
run install "${EXAMPLES}/minimal/acme-md-lint" --dry-run
|
||||||
assert_exit 0 "dry-run install"
|
assert_exit 0 "dry-run install"
|
||||||
[[ "${STDOUT}" == *"dry-run"* ]] && ok "stdout mentions dry-run" \
|
if [[ "${STDOUT}" == *"dry-run"* ]]; then ok "stdout mentions dry-run"
|
||||||
|| ko "expected 'dry-run' in stdout: ${STDOUT}"
|
else ko "expected 'dry-run' in stdout: ${STDOUT}"; fi
|
||||||
assert_path_absent "_bmad/mdlint"
|
assert_path_absent "_bmad/mdlint"
|
||||||
|
|
||||||
# ─── 3. real install of minimal module ───────────────────────────────────────
|
# ─── 3. real install of minimal module ───────────────────────────────────────
|
||||||
|
|
@ -141,13 +150,13 @@ assert_grep ',"mdlint",' "_bmad/_config/files-manifest.csv"
|
||||||
note "list (after minimal install)"
|
note "list (after minimal install)"
|
||||||
run list
|
run list
|
||||||
assert_exit 0 "list one"
|
assert_exit 0 "list one"
|
||||||
[[ "${STDOUT}" == *"mdlint"* ]] && ok "stdout includes mdlint" \
|
if [[ "${STDOUT}" == *"mdlint"* ]]; then ok "stdout includes mdlint"
|
||||||
|| ko "expected 'mdlint' in stdout: ${STDOUT}"
|
else ko "expected 'mdlint' in stdout: ${STDOUT}"; fi
|
||||||
|
|
||||||
run list --json
|
run list --json
|
||||||
assert_exit 0 "list --json"
|
assert_exit 0 "list --json"
|
||||||
[[ "${STDOUT}" == *"\"name\": \"mdlint\""* ]] && ok "json includes mdlint name" \
|
if [[ "${STDOUT}" == *"\"name\": \"mdlint\""* ]]; then ok "json includes mdlint name"
|
||||||
|| ko "expected mdlint in JSON: ${STDOUT}"
|
else ko "expected mdlint in JSON: ${STDOUT}"; fi
|
||||||
|
|
||||||
# ─── 5. idempotent re-install ────────────────────────────────────────────────
|
# ─── 5. idempotent re-install ────────────────────────────────────────────────
|
||||||
note "install acme-md-lint again (idempotent / collision)"
|
note "install acme-md-lint again (idempotent / collision)"
|
||||||
|
|
@ -190,8 +199,8 @@ assert_path_exists "_bmad/devlog/module-help.csv"
|
||||||
assert_path_absent "_bmad/devlog/docs"
|
assert_path_absent "_bmad/devlog/docs"
|
||||||
assert_path_absent "_bmad/devlog/README.md"
|
assert_path_absent "_bmad/devlog/README.md"
|
||||||
assert_path_absent "_bmad/devlog/CHANGELOG.md"
|
assert_path_absent "_bmad/devlog/CHANGELOG.md"
|
||||||
[[ "${STDOUT}" == *"hooks"* ]] && ok "warns about hooks not auto-activated" \
|
if [[ "${STDOUT}" == *"hooks"* ]]; then ok "warns about hooks not auto-activated"
|
||||||
|| ko "expected hooks warning in stdout: ${STDOUT}"
|
else ko "expected hooks warning in stdout: ${STDOUT}"; fi
|
||||||
|
|
||||||
# ─── 9a. parity: central config + agent roster (gap #3) ──────────────────────
|
# ─── 9a. parity: central config + agent roster (gap #3) ──────────────────────
|
||||||
note "config generation + agent roster"
|
note "config generation + agent roster"
|
||||||
|
|
@ -213,8 +222,9 @@ assert_path_exists "_bmad-output/journal"
|
||||||
# ─── 9c. parity: merged help catalog (gap #1) ────────────────────────────────
|
# ─── 9c. parity: merged help catalog (gap #1) ────────────────────────────────
|
||||||
note "bmad-help.csv merge"
|
note "bmad-help.csv merge"
|
||||||
assert_path_exists "_bmad/_config/bmad-help.csv"
|
assert_path_exists "_bmad/_config/bmad-help.csv"
|
||||||
head -1 _bmad/_config/bmad-help.csv | grep -q '^module,skill,display-name,' \
|
if head -1 _bmad/_config/bmad-help.csv | grep -q '^module,skill,display-name,'; then
|
||||||
&& ok "bmad-help.csv has canonical header" || ko "bmad-help.csv header wrong"
|
ok "bmad-help.csv has canonical header"
|
||||||
|
else ko "bmad-help.csv header wrong"; fi
|
||||||
assert_grep '^devlog,bmad-devlog-write,' "_bmad/_config/bmad-help.csv"
|
assert_grep '^devlog,bmad-devlog-write,' "_bmad/_config/bmad-help.csv"
|
||||||
assert_grep '^devlog,bmad-agent-historian,' "_bmad/_config/bmad-help.csv"
|
assert_grep '^devlog,bmad-agent-historian,' "_bmad/_config/bmad-help.csv"
|
||||||
# the core baseline row is still present
|
# the core baseline row is still present
|
||||||
|
|
@ -224,8 +234,8 @@ assert_grep ',bmad-help,Help,' "_bmad/_config/bmad-help.csv"
|
||||||
note "install examples/legacy/bmad-mini-legacy (legacy marketplace.json)"
|
note "install examples/legacy/bmad-mini-legacy (legacy marketplace.json)"
|
||||||
run install "${EXAMPLES}/legacy/bmad-mini-legacy"
|
run install "${EXAMPLES}/legacy/bmad-mini-legacy"
|
||||||
assert_exit 0 "install legacy mini"
|
assert_exit 0 "install legacy mini"
|
||||||
[[ "${STDOUT}" == *"resolved legacy module mlg"* ]] && ok "stdout reports legacy resolution" \
|
if [[ "${STDOUT}" == *"resolved legacy module mlg"* ]]; then ok "stdout reports legacy resolution"
|
||||||
|| ko "expected 'resolved legacy module mlg' in stdout: ${STDOUT}"
|
else ko "expected 'resolved legacy module mlg' in stdout: ${STDOUT}"; fi
|
||||||
# Synthetic plugin.json is staged; marketplace.json is preserved verbatim.
|
# Synthetic plugin.json is staged; marketplace.json is preserved verbatim.
|
||||||
assert_path_exists "_bmad/mlg/.claude-plugin/plugin.json"
|
assert_path_exists "_bmad/mlg/.claude-plugin/plugin.json"
|
||||||
assert_path_exists "_bmad/mlg/.claude-plugin/marketplace.json"
|
assert_path_exists "_bmad/mlg/.claude-plugin/marketplace.json"
|
||||||
|
|
@ -273,13 +283,15 @@ run remove mdlint
|
||||||
assert_exit 0 "remove mdlint"
|
assert_exit 0 "remove mdlint"
|
||||||
assert_path_absent "_bmad/mdlint"
|
assert_path_absent "_bmad/mdlint"
|
||||||
assert_path_exists "_bmad/custom/mdlint/override.md"
|
assert_path_exists "_bmad/custom/mdlint/override.md"
|
||||||
[[ "${STDOUT}" == *"preserved"* ]] && ok "stdout mentions preserved customs" \
|
if [[ "${STDOUT}" == *"preserved"* ]]; then ok "stdout mentions preserved customs"
|
||||||
|| ko "expected 'preserved' in stdout: ${STDOUT}"
|
else ko "expected 'preserved' in stdout: ${STDOUT}"; fi
|
||||||
# manifest rows for mdlint should be gone
|
# manifest rows for mdlint should be gone
|
||||||
grep -q ',"mdlint",' _bmad/_config/files-manifest.csv && \
|
if grep -q ',"mdlint",' _bmad/_config/files-manifest.csv; then
|
||||||
ko "mdlint rows still in files-manifest.csv" || ok "files-manifest.csv pruned"
|
ko "mdlint rows still in files-manifest.csv"
|
||||||
grep -q '"acme-md-lint"' _bmad/_config/skill-manifest.csv && \
|
else ok "files-manifest.csv pruned"; fi
|
||||||
ko "acme-md-lint row still in skill-manifest.csv" || ok "skill-manifest.csv pruned"
|
if grep -q '"acme-md-lint"' _bmad/_config/skill-manifest.csv; then
|
||||||
|
ko "acme-md-lint row still in skill-manifest.csv"
|
||||||
|
else ok "skill-manifest.csv pruned"; fi
|
||||||
|
|
||||||
# ─── 11. remove --purge ──────────────────────────────────────────────────────
|
# ─── 11. remove --purge ──────────────────────────────────────────────────────
|
||||||
note "remove devlog --purge"
|
note "remove devlog --purge"
|
||||||
|
|
@ -290,14 +302,18 @@ assert_exit 0 "remove --purge"
|
||||||
assert_path_absent "_bmad/devlog"
|
assert_path_absent "_bmad/devlog"
|
||||||
assert_path_absent "_bmad/custom/devlog"
|
assert_path_absent "_bmad/custom/devlog"
|
||||||
# config blocks and help rows for devlog are stripped on removal
|
# config blocks and help rows for devlog are stripped on removal
|
||||||
grep -q '\[modules\.devlog]' _bmad/config.toml \
|
if grep -q '\[modules\.devlog]' _bmad/config.toml; then
|
||||||
&& ko "[modules.devlog] still in config.toml" || ok "config.toml [modules.devlog] stripped"
|
ko "[modules.devlog] still in config.toml"
|
||||||
grep -q '\[agents\.bmad-agent-historian]' _bmad/config.toml \
|
else ok "config.toml [modules.devlog] stripped"; fi
|
||||||
&& ko "[agents.bmad-agent-historian] still in config.toml" || ok "config.toml agent block stripped"
|
if grep -q '\[agents\.bmad-agent-historian]' _bmad/config.toml; then
|
||||||
grep -q '\[modules\.devlog]' _bmad/config.user.toml \
|
ko "[agents.bmad-agent-historian] still in config.toml"
|
||||||
&& ko "[modules.devlog] still in config.user.toml" || ok "config.user.toml [modules.devlog] stripped"
|
else ok "config.toml agent block stripped"; fi
|
||||||
grep -q '^devlog,' _bmad/_config/bmad-help.csv \
|
if grep -q '\[modules\.devlog]' _bmad/config.user.toml; then
|
||||||
&& ko "devlog rows still in bmad-help.csv" || ok "bmad-help.csv devlog rows removed"
|
ko "[modules.devlog] still in config.user.toml"
|
||||||
|
else ok "config.user.toml [modules.devlog] stripped"; fi
|
||||||
|
if grep -q '^devlog,' _bmad/_config/bmad-help.csv; then
|
||||||
|
ko "devlog rows still in bmad-help.csv"
|
||||||
|
else ok "bmad-help.csv devlog rows removed"; fi
|
||||||
# [core] survives the removal
|
# [core] survives the removal
|
||||||
assert_grep '^user_name = "Tester"' "_bmad/config.toml"
|
assert_grep '^user_name = "Tester"' "_bmad/config.toml"
|
||||||
|
|
||||||
|
|
@ -330,8 +346,8 @@ run install "${EXAMPLES}/minimal/acme-md-lint" --project-dir "${IDEPROJ}"
|
||||||
assert_exit 0 "install into IDE project"
|
assert_exit 0 "install into IDE project"
|
||||||
assert_path_exists "${IDEPROJ}/.claude/skills/acme-md-lint/SKILL.md"
|
assert_path_exists "${IDEPROJ}/.claude/skills/acme-md-lint/SKILL.md"
|
||||||
assert_path_exists "${IDEPROJ}/.agents/skills/acme-md-lint/SKILL.md"
|
assert_path_exists "${IDEPROJ}/.agents/skills/acme-md-lint/SKILL.md"
|
||||||
[[ "${STDOUT}" == *"claude-code"* ]] && ok "stdout reports claude-code distribution" \
|
if [[ "${STDOUT}" == *"claude-code"* ]]; then ok "stdout reports claude-code distribution"
|
||||||
|| ko "expected claude-code in stdout: ${STDOUT}"
|
else ko "expected claude-code in stdout: ${STDOUT}"; fi
|
||||||
# Canonical end-state: skill source dirs removed from _bmad/ after distribution.
|
# Canonical end-state: skill source dirs removed from _bmad/ after distribution.
|
||||||
if find "${IDEPROJ}/_bmad" -name SKILL.md | grep -q .; then
|
if find "${IDEPROJ}/_bmad" -name SKILL.md | grep -q .; then
|
||||||
ko "SKILL.md still under _bmad after distribution"
|
ko "SKILL.md still under _bmad after distribution"
|
||||||
|
|
@ -354,9 +370,9 @@ run install "${EXAMPLES}/minimal-npm/acme-npmtool"
|
||||||
assert_exit 0 "install npm fixture"
|
assert_exit 0 "install npm fixture"
|
||||||
assert_path_exists "_bmad/npmtool/package.json"
|
assert_path_exists "_bmad/npmtool/package.json"
|
||||||
if command -v npm >/dev/null 2>&1; then
|
if command -v npm >/dev/null 2>&1; then
|
||||||
[[ "${STDOUT}" == *"installed npm dependencies for npmtool"* ]] \
|
if [[ "${STDOUT}" == *"installed npm dependencies for npmtool"* ]]; then
|
||||||
&& ok "npm dependencies installed" \
|
ok "npm dependencies installed"
|
||||||
|| ko "expected npm install confirmation in stdout: ${STDOUT}"
|
else ko "expected npm install confirmation in stdout: ${STDOUT}"; fi
|
||||||
# The fixture has zero deps, so npm writes package-lock.json (not node_modules);
|
# The fixture has zero deps, so npm writes package-lock.json (not node_modules);
|
||||||
# its presence proves npm actually ran inside the installed module dir.
|
# its presence proves npm actually ran inside the installed module dir.
|
||||||
assert_path_exists "_bmad/npmtool/package-lock.json"
|
assert_path_exists "_bmad/npmtool/package-lock.json"
|
||||||
|
|
|
||||||
|
|
@ -3739,8 +3739,12 @@ async function runTests() {
|
||||||
|
|
||||||
const om = new OfficialModules();
|
const om = new OfficialModules();
|
||||||
const tracked = [];
|
const tracked = [];
|
||||||
const result = await om.install('devlog', bmadDir, (p) => tracked.push(p), { skipModuleInstaller: true, moduleConfig: {} });
|
let result;
|
||||||
|
try {
|
||||||
|
result = await om.install('devlog', bmadDir, (p) => tracked.push(p), { skipModuleInstaller: true, moduleConfig: {} });
|
||||||
|
} finally {
|
||||||
CustomModuleManager._resolutionCache.delete('devlog');
|
CustomModuleManager._resolutionCache.delete('devlog');
|
||||||
|
}
|
||||||
|
|
||||||
assert(result.success === true && result.module === 'devlog', 'install() routes plugin-json resolution and succeeds');
|
assert(result.success === true && result.module === 'devlog', 'install() routes plugin-json resolution and succeeds');
|
||||||
assert(
|
assert(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue