fix(#2414): mempalace-capture rooms example must be dicts with name key (#2464)

* fix(#2414): mempalace-capture rooms example must be dicts with name key

The skill's Step 3 'Add the drawer (verbatim)' example wrote a flat list
of bare strings under rooms: in the embedded mempalace.yaml. mempalace's
miner (detect_room + _mine_impl) indexes room["name"] — a bare-string
list crashes the first 'mempalace mine' invocation with

  TypeError: string indices must be integers, not 'str'

Following the documented example verbatim and running the capture crashed
every time, before any file was routed. The bug shipped in #2220's fix
(commit d8af61be4) — the same commit that replaced the invalid --room
flag with detect_room() staging also introduced this rooms: block with
the wrong (string, not dict) entry shape.

Fix: convert each '- <room>' to '- name: <room>' in both shipped source
files (skills/gsd-mempalace-capture/SKILL.md and commands/gsd/mempalace-capture.md).
The two files are byte-for-byte duplicates of the broken block; both are
corrected in lockstep so the installer regenerates consistent copies into
the user's runtime config dir (gsd-pristine/ and gsd-local-patches/ are
install-time-generated, no separate edit needed).

Tests: tests/mempalace-capture-headless-invocation.test.cjs gains a #2414
describe block that extracts the YAML block from each file, parses it with
js-yaml, and asserts every entry under rooms: is a dict carrying a
non-empty 'name' string. A second belt-and-suspenders check forbids any
bare '- <word>' line under rooms: so a future reversion can't slip back in
silently if the YAML parser is ever removed/refactored.

References: #2414; #2220 (same origin commit, distinct failure mode);
mempalace's miner dict-shape contract (miner.py:1708 built-in default
uses [{"name": "general", "description": "All project files"}]).

* chore(#2414): backfill pr:2464 in .changeset/eager-pandas-jump.md
This commit is contained in:
Tom Boucher
2026-07-20 16:52:34 -04:00
committed by GitHub
parent 953b8043ea
commit 903182fed3
20 changed files with 122 additions and 32 deletions

View File

@@ -0,0 +1,5 @@
---
type: Fixed
pr: 2464
---
**`/gsd-mempalace-capture` no longer crashes on first invocation** — the skill's own documented `rooms:` example wrote a flat list of bare strings, but mempalace's miner expects each entry as a dict with a `name` key, so following the example verbatim and running `mempalace mine` crashed with `TypeError: string indices must be integers, not 'str'`. Both `skills/gsd-mempalace-capture/SKILL.md` and `commands/gsd/mempalace-capture.md` now ship the corrected `- name: <room>` shape, so the documented example runs successfully end-to-end.

View File

@@ -64,12 +64,16 @@ On any error or timeout, stop and let the phase continue -- capture is best-effo
# One-time: declare the GSD room taxonomy so detect_room() recognizes these folders
mkdir -p "$STAGE"
[ -f "$STAGE/mempalace.yaml" ] || cat > "$STAGE/mempalace.yaml" <<'YAML'
# Each entry MUST be a dict with a `name` key (the miner's detect_room()
# indexes room["name"] — a bare-string list crashes _mine_impl with
# TypeError: string indices must be integers, not 'str'). Optional fields:
# `description`, `keywords` (matched against folder-path segments).
rooms:
- decisions
- planning
- milestones
- problems
- general
- name: decisions
- name: planning
- name: milestones
- name: problems
- name: general
YAML
# Suppress MemPalace cache artifacts written into the scanned tree
[ -f "$STAGE/.gitignore" ] || echo "mempalace_embedder.json" > "$STAGE/.gitignore"

View File

@@ -64,12 +64,16 @@ On any error or timeout, stop and let the phase continue -- capture is best-effo
# One-time: declare the GSD room taxonomy so detect_room() recognizes these folders
mkdir -p "$STAGE"
[ -f "$STAGE/mempalace.yaml" ] || cat > "$STAGE/mempalace.yaml" <<'YAML'
# Each entry MUST be a dict with a `name` key (the miner's detect_room()
# indexes room["name"] — a bare-string list crashes _mine_impl with
# TypeError: string indices must be integers, not 'str'). Optional fields:
# `description`, `keywords` (matched against folder-path segments).
rooms:
- decisions
- planning
- milestones
- problems
- general
- name: decisions
- name: planning
- name: milestones
- name: problems
- name: general
YAML
# Suppress MemPalace cache artifacts written into the scanned tree
[ -f "$STAGE/.gitignore" ] || echo "mempalace_embedder.json" > "$STAGE/.gitignore"

View File

@@ -393,7 +393,7 @@
"skills/gsd-ingest-docs/SKILL.md": "f4e43968af317ed8",
"skills/gsd-manager/SKILL.md": "6e51785860784d8c",
"skills/gsd-map-codebase/SKILL.md": "552f914f43b2181c",
"skills/gsd-mempalace-capture/SKILL.md": "ece243a29d87cfca",
"skills/gsd-mempalace-capture/SKILL.md": "0f8eae8ef21ea89a",
"skills/gsd-mempalace-recall/SKILL.md": "2d95e385fee26dee",
"skills/gsd-milestone-summary/SKILL.md": "2955ab3e3a444ca3",
"skills/gsd-mvp-phase/SKILL.md": "1cf7622d655840ac",

View File

@@ -63,7 +63,7 @@
"commands/gsd-ingest-docs.md": "6718b04c597a5428",
"commands/gsd-manager.md": "8f4ae79774902293",
"commands/gsd-map-codebase.md": "e4e170d4ef2d46c6",
"commands/gsd-mempalace-capture.md": "d57b339a2743f5a4",
"commands/gsd-mempalace-capture.md": "63c35058ba60209f",
"commands/gsd-mempalace-recall.md": "38716c0983a3ef9c",
"commands/gsd-milestone-summary.md": "ff5e11e6b33d4b5e",
"commands/gsd-mvp-phase.md": "ffc5905aed8f450a",
@@ -440,7 +440,7 @@
"skills/gsd-ns-context/skills/extract-learnings/SKILL.md": "48846bf26ccaf0e7",
"skills/gsd-ns-context/skills/graphify/SKILL.md": "3d6341614add6ccd",
"skills/gsd-ns-context/skills/map-codebase/SKILL.md": "2017007dcd69d153",
"skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "b3c600b306f179eb",
"skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "9923f0164d27f27f",
"skills/gsd-ns-context/skills/mempalace-recall/SKILL.md": "646e59e76acd548f",
"skills/gsd-ns-ideate/SKILL.md": "d70360a5f7e8ac90",
"skills/gsd-ns-ideate/skills/capture/SKILL.md": "74651f6959cfbbd3",

View File

@@ -62,7 +62,7 @@
"commands/gsd-ingest-docs.md": "ded9013d0de7e77b",
"commands/gsd-manager.md": "72d5b31b88f77703",
"commands/gsd-map-codebase.md": "ecd69887996ae561",
"commands/gsd-mempalace-capture.md": "3812fc95963f92d7",
"commands/gsd-mempalace-capture.md": "7ec09056410d8e63",
"commands/gsd-mempalace-recall.md": "38716c0983a3ef9c",
"commands/gsd-milestone-summary.md": "908509042caf5beb",
"commands/gsd-mvp-phase.md": "1ef0d7c2871be49a",

View File

@@ -391,7 +391,7 @@
"skills/gsd-ingest-docs/SKILL.md": "eb85e654917a503a",
"skills/gsd-manager/SKILL.md": "1370d93741e47828",
"skills/gsd-map-codebase/SKILL.md": "cf65e61890448285",
"skills/gsd-mempalace-capture/SKILL.md": "fa47f3e3fb1264eb",
"skills/gsd-mempalace-capture/SKILL.md": "175c5441158a0a9c",
"skills/gsd-mempalace-recall/SKILL.md": "c3f412d5a64f3921",
"skills/gsd-milestone-summary/SKILL.md": "33d51a325d314f3a",
"skills/gsd-mvp-phase/SKILL.md": "f9a1348c6c297579",

View File

@@ -344,7 +344,7 @@
"skills/gsd-ns-context/skills/extract-learnings/SKILL.md": "d39269bea995fabc",
"skills/gsd-ns-context/skills/graphify/SKILL.md": "030050fcd08d129d",
"skills/gsd-ns-context/skills/map-codebase/SKILL.md": "fa6a37402430af7d",
"skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "ece243a29d87cfca",
"skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "0f8eae8ef21ea89a",
"skills/gsd-ns-context/skills/mempalace-recall/SKILL.md": "2d95e385fee26dee",
"skills/gsd-ns-ideate/SKILL.md": "c10342345c01c91f",
"skills/gsd-ns-ideate/skills/capture/SKILL.md": "fb53053848bb6695",

View File

@@ -63,7 +63,7 @@
"commands/gsd-ingest-docs.md": "ab3e58239c23d61d",
"commands/gsd-manager.md": "bfe9e261fa918876",
"commands/gsd-map-codebase.md": "5093093d42240325",
"commands/gsd-mempalace-capture.md": "c687b6d88b50f45c",
"commands/gsd-mempalace-capture.md": "abe0eb543cedb9fb",
"commands/gsd-mempalace-recall.md": "6efef238d8c62569",
"commands/gsd-milestone-summary.md": "e3a36fbd695a1833",
"commands/gsd-mvp-phase.md": "671791ba61c4654a",
@@ -463,7 +463,7 @@
"skills/gsd-ingest-docs/SKILL.md": "2df55e0ec95d57d9",
"skills/gsd-manager/SKILL.md": "816db4d4ed618537",
"skills/gsd-map-codebase/SKILL.md": "b304ec25e9a95c93",
"skills/gsd-mempalace-capture/SKILL.md": "cb6238896332cedf",
"skills/gsd-mempalace-capture/SKILL.md": "b6aee382ec1a6c2b",
"skills/gsd-mempalace-recall/SKILL.md": "70c8491f53f4161b",
"skills/gsd-milestone-summary/SKILL.md": "9eb030a1ac307fa1",
"skills/gsd-mvp-phase/SKILL.md": "236fcdd69f47d101",

View File

@@ -27,7 +27,7 @@
".agents/skills/gsd-ingest-docs/SKILL.md": "5bd2838bf0b6dc1b",
".agents/skills/gsd-manager/SKILL.md": "cb1cf56f5d3f66d6",
".agents/skills/gsd-map-codebase/SKILL.md": "cd27dc028718426b",
".agents/skills/gsd-mempalace-capture/SKILL.md": "361675ada00a54b6",
".agents/skills/gsd-mempalace-capture/SKILL.md": "fb426a6700b98eed",
".agents/skills/gsd-mempalace-recall/SKILL.md": "7205b02250e89f25",
".agents/skills/gsd-milestone-summary/SKILL.md": "af84ecb400f23556",
".agents/skills/gsd-mvp-phase/SKILL.md": "72b65ae927b280fe",

View File

@@ -366,7 +366,7 @@
"skills/gsd-ingest-docs/SKILL.md": "10500de29525f6cf",
"skills/gsd-manager/SKILL.md": "9946975bec15e737",
"skills/gsd-map-codebase/SKILL.md": "39e7fd6bcc561f9d",
"skills/gsd-mempalace-capture/SKILL.md": "a9f9dd7fb904d09f",
"skills/gsd-mempalace-capture/SKILL.md": "1ccddd50b3d77a4a",
"skills/gsd-mempalace-recall/SKILL.md": "89523db66f834b2f",
"skills/gsd-milestone-summary/SKILL.md": "5ca1dabfe0cd85f0",
"skills/gsd-mvp-phase/SKILL.md": "60ac3c3fa6a6a19b",

View File

@@ -63,7 +63,7 @@
"commands/gsd-ingest-docs.md": "9e7f8757b9408c01",
"commands/gsd-manager.md": "f300b708a5487c76",
"commands/gsd-map-codebase.md": "12f705917eb202fb",
"commands/gsd-mempalace-capture.md": "06323113ec60df3e",
"commands/gsd-mempalace-capture.md": "8f5afec4dde75478",
"commands/gsd-mempalace-recall.md": "08c910285469a394",
"commands/gsd-milestone-summary.md": "adfad2cf43fc5aad",
"commands/gsd-mvp-phase.md": "e8debeee627a0bf2",
@@ -441,7 +441,7 @@
"skills/gsd-ingest-docs/SKILL.md": "1a2e87caa9011682",
"skills/gsd-manager/SKILL.md": "8a506b1b8b3841c3",
"skills/gsd-map-codebase/SKILL.md": "74a827b893d70dfa",
"skills/gsd-mempalace-capture/SKILL.md": "b5ad8d540b6320be",
"skills/gsd-mempalace-capture/SKILL.md": "ff7e3bcfa0d23d5f",
"skills/gsd-mempalace-recall/SKILL.md": "04364d3012644204",
"skills/gsd-milestone-summary/SKILL.md": "1d0b245b74176236",
"skills/gsd-mvp-phase/SKILL.md": "485356f67c196015",

View File

@@ -370,7 +370,7 @@
"skills/gsd/gsd-ns-context/skills/extract-learnings/SKILL.md": "36e59d6e514dcaf0",
"skills/gsd/gsd-ns-context/skills/graphify/SKILL.md": "169eefd42c444cde",
"skills/gsd/gsd-ns-context/skills/map-codebase/SKILL.md": "9d36eee52586bb34",
"skills/gsd/gsd-ns-context/skills/mempalace-capture/SKILL.md": "4a2733dd32cdf737",
"skills/gsd/gsd-ns-context/skills/mempalace-capture/SKILL.md": "b55a640c7bae4c97",
"skills/gsd/gsd-ns-context/skills/mempalace-recall/SKILL.md": "5d06922e0d7ab7d9",
"skills/gsd/gsd-ns-ideate/SKILL.md": "b36bb4700ed6723a",
"skills/gsd/gsd-ns-ideate/skills/capture/SKILL.md": "76fc7c1200124ece",

View File

@@ -63,7 +63,7 @@
"command/gsd-ingest-docs.md": "e655ecf1d4433ba9",
"command/gsd-manager.md": "1cdc133079833552",
"command/gsd-map-codebase.md": "704cb63214f51523",
"command/gsd-mempalace-capture.md": "8b6bc24d7baf1e9b",
"command/gsd-mempalace-capture.md": "081236c25ce5b337",
"command/gsd-mempalace-recall.md": "d358cdd89c935877",
"command/gsd-milestone-summary.md": "4ab29b777f62f0bb",
"command/gsd-mvp-phase.md": "273a1c26ca13274b",
@@ -465,7 +465,7 @@
"skills/gsd-ingest-docs/SKILL.md": "f049f06a6ec7da43",
"skills/gsd-manager/SKILL.md": "a37ecdbe32952262",
"skills/gsd-map-codebase/SKILL.md": "e06d6ac1b7632cbe",
"skills/gsd-mempalace-capture/SKILL.md": "80ffe0ee9b833502",
"skills/gsd-mempalace-capture/SKILL.md": "ddb5c1322d6237ad",
"skills/gsd-mempalace-recall/SKILL.md": "2091c48e6e986e28",
"skills/gsd-milestone-summary/SKILL.md": "da645171ca2299d8",
"skills/gsd-mvp-phase/SKILL.md": "eeb0ac0f88647475",

View File

@@ -428,7 +428,7 @@
"skills/gsd-ingest-docs/SKILL.md": "6366644e623ae9e4",
"skills/gsd-manager/SKILL.md": "8a11a1beb8e35a9c",
"skills/gsd-map-codebase/SKILL.md": "73ab0afb2398de2c",
"skills/gsd-mempalace-capture/SKILL.md": "5ed5ae9c018c89df",
"skills/gsd-mempalace-capture/SKILL.md": "aeb01fa8be356ba8",
"skills/gsd-mempalace-recall/SKILL.md": "c6e0195e55cd934c",
"skills/gsd-milestone-summary/SKILL.md": "3ea93ccaa0d4d967",
"skills/gsd-mvp-phase/SKILL.md": "d2f98f1e955797b6",

View File

@@ -63,7 +63,7 @@
"commands/gsd-ingest-docs.md": "b47c812c247e58a4",
"commands/gsd-manager.md": "86ece154b34b6d1b",
"commands/gsd-map-codebase.md": "9aba6b4eed565912",
"commands/gsd-mempalace-capture.md": "8b6bc24d7baf1e9b",
"commands/gsd-mempalace-capture.md": "081236c25ce5b337",
"commands/gsd-mempalace-recall.md": "d358cdd89c935877",
"commands/gsd-milestone-summary.md": "86a827271bc647c5",
"commands/gsd-mvp-phase.md": "d45fd76cb9cff3ef",
@@ -465,7 +465,7 @@
"skills/gsd-ingest-docs/SKILL.md": "8f294b4894f782a5",
"skills/gsd-manager/SKILL.md": "cf40f237b4f20aa7",
"skills/gsd-map-codebase/SKILL.md": "73f714297815f74c",
"skills/gsd-mempalace-capture/SKILL.md": "80ffe0ee9b833502",
"skills/gsd-mempalace-capture/SKILL.md": "ddb5c1322d6237ad",
"skills/gsd-mempalace-recall/SKILL.md": "2091c48e6e986e28",
"skills/gsd-milestone-summary/SKILL.md": "175366bb500b5e64",
"skills/gsd-mvp-phase/SKILL.md": "0531d0e907af41ce",

View File

@@ -369,7 +369,7 @@
"skills/gsd-ns-context/skills/extract-learnings/SKILL.md": "8d38e55e5f8b774b",
"skills/gsd-ns-context/skills/graphify/SKILL.md": "ac3661e6e576188b",
"skills/gsd-ns-context/skills/map-codebase/SKILL.md": "cf65e61890448285",
"skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "fa47f3e3fb1264eb",
"skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "175c5441158a0a9c",
"skills/gsd-ns-context/skills/mempalace-recall/SKILL.md": "c3f412d5a64f3921",
"skills/gsd-ns-ideate/SKILL.md": "4a0d2691054b23e5",
"skills/gsd-ns-ideate/skills/capture/SKILL.md": "05fa421c95fbad2d",

View File

@@ -341,7 +341,7 @@
"skills/gsd-ns-context/skills/extract-learnings/SKILL.md": "1fc6ba92fc18eb86",
"skills/gsd-ns-context/skills/graphify/SKILL.md": "371ce22f2fe319bc",
"skills/gsd-ns-context/skills/map-codebase/SKILL.md": "cfc5310b903d594a",
"skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "211b03370a105fae",
"skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "52cb3eacc890c44c",
"skills/gsd-ns-context/skills/mempalace-recall/SKILL.md": "73b0b7a6301cb214",
"skills/gsd-ns-ideate/SKILL.md": "aa399385b735c7c1",
"skills/gsd-ns-ideate/skills/capture/SKILL.md": "3b7fc696b2107bcf",

View File

@@ -63,7 +63,7 @@
"commands/gsd-ingest-docs.md": "7a3c21ae5d5d133a",
"commands/gsd-manager.md": "9f54653a7c589b00",
"commands/gsd-map-codebase.md": "709e9572953accc6",
"commands/gsd-mempalace-capture.md": "be4316828baebe52",
"commands/gsd-mempalace-capture.md": "c0892e814b04350a",
"commands/gsd-mempalace-recall.md": "5ac67fa4b7f2b03b",
"commands/gsd-milestone-summary.md": "f8fa9c357c08b74b",
"commands/gsd-mvp-phase.md": "cba67bcb55250e5f",
@@ -412,7 +412,7 @@
"skills/gsd-ns-context/skills/extract-learnings/SKILL.md": "6de7eeaaf4939e5d",
"skills/gsd-ns-context/skills/graphify/SKILL.md": "d54c2b44e8059299",
"skills/gsd-ns-context/skills/map-codebase/SKILL.md": "f48d48b43e2cc4bd",
"skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "fa47f3e3fb1264eb",
"skills/gsd-ns-context/skills/mempalace-capture/SKILL.md": "175c5441158a0a9c",
"skills/gsd-ns-context/skills/mempalace-recall/SKILL.md": "c3f412d5a64f3921",
"skills/gsd-ns-ideate/SKILL.md": "4a0d2691054b23e5",
"skills/gsd-ns-ideate/skills/capture/SKILL.md": "c848255c134a860f",

View File

@@ -5,6 +5,12 @@
// --room flag (only `search` does). The fix replaced the flag with a
// detect_room()-based staging approach.
//
// #2414 extension: the staging block also embeds a `rooms:` YAML example.
// mempalace's miner (`detect_room()` and `_mine_impl`) requires each entry
// to be a DICT with at least a `name` key — a bare-string list crashes the
// first `mine` invocation with `TypeError: string indices must be integers,
// not 'str'`. The fix converts each `- <room>` to `- name: <room>`.
//
// Docs sources:
// CLI reference: https://mempalaceofficial.com/reference/cli.html
// Mining guide: https://mempalaceofficial.com/guide/mining.html
@@ -14,6 +20,7 @@ const { describe, test } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('fs');
const path = require('path');
const yaml = require('js-yaml');
const ROOT = path.resolve(__dirname, '..');
@@ -71,3 +78,73 @@ describe('#2220 — headless mempalace mine has no --room flag', () => {
assert.ok(content.includes('.mempalace-stage/'), '.gitignore must exclude .planning/.mempalace-stage/');
});
});
// ─── #2414: rooms: entries MUST be dicts with a `name` key ───────────────────
//
// The skill files embed a `rooms:` YAML example inside a bash heredoc. The
// miner's `detect_room()` and `_mine_impl` index `room["name"]` — a bare-string
// list crashes the first `mine` invocation with
// `TypeError: string indices must be integers, not 'str'`.
//
// This describe block extracts the YAML block from each file, parses it with
// js-yaml, and asserts every entry under `rooms:` is a dict carrying a `name`
// key. It also forbids the pre-fix shape (`- decisions` etc.) so a future
// reversion can't slip back in silently.
describe('#2414 — rooms: entries are dicts with a name key (not bare strings)', () => {
// Extract the YAML `rooms:` block from a markdown file. The block lives
// inside a bash heredoc that ends with `YAML` on its own line. We capture
// from the line beginning with `rooms:` through the closing `YAML` sentinel.
function extractRoomsYaml(content) {
const lines = content.split(/\r?\n/);
const start = lines.findIndex((l) => /^\s*rooms:\s*$/.test(l));
if (start === -1) return null;
let end = -1;
for (let i = start + 1; i < lines.length; i++) {
// The heredoc terminator in the embedded bash is `YAML` on its own line
// (possibly with leading whitespace from the markdown fence indentation).
if (/^\s*YAML\s*$/.test(lines[i])) { end = i; break; }
}
if (end === -1) return null;
return lines.slice(start, end).join('\n');
}
for (const rel of SKILL_FILES) {
test(`${rel}: every rooms: entry is a dict with a \`name\` key`, () => {
const content = fs.readFileSync(path.join(ROOT, rel), 'utf8');
const yamlBlock = extractRoomsYaml(content);
assert.ok(yamlBlock, `${rel}: could not locate a rooms: YAML block`);
const parsed = yaml.load(yamlBlock);
assert.ok(parsed && Array.isArray(parsed.rooms), `${rel}: rooms: must parse to an array`);
assert.ok(parsed.rooms.length >= 5, `${rel}: expected the GSD room taxonomy (≥5 rooms), got ${parsed.rooms.length}`);
for (const [i, entry] of parsed.rooms.entries()) {
assert.ok(
entry !== null && typeof entry === 'object' && !Array.isArray(entry),
`${rel}: rooms:[${i}] must be a dict, got ${JSON.stringify(entry)} (a bare-string list crashes mempalace miner's detect_room with TypeError: string indices must be integers — #2414)`,
);
assert.ok(
typeof entry.name === 'string' && entry.name.length > 0,
`${rel}: rooms:[${i}] must have a non-empty name string, got ${JSON.stringify(entry)}`,
);
}
});
test(`${rel}: no bare-string rooms: entries remain (forbid the pre-fix shape)`, () => {
// Direct guard against the pre-fix shape — any line under rooms: that
// matches `^- <word>$` (no colon) is the broken form. Belt-and-suspenders
// alongside the parse-and-shape check above; keeps the assertion readable
// when the YAML parser is removed/refactored in the future.
const content = fs.readFileSync(path.join(ROOT, rel), 'utf8');
const yamlBlock = extractRoomsYaml(content);
assert.ok(yamlBlock, `${rel}: could not locate a rooms: YAML block`);
const bareStringEntries = yamlBlock
.split(/\r?\n/)
.filter((l) => /^\s*-\s+[A-Za-z][A-Za-z0-9_-]*\s*$/.test(l));
assert.strictEqual(
bareStringEntries.length,
0,
`${rel}: rooms: must not contain bare-string entries (crashes mempalace miner — #2414). Offenders: ${JSON.stringify(bareStringEntries)}`,
);
});
}
});