mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-10-26 06:43:15 +08:00
fix(cli): quote the skill description so strict YAML readers accept it (#1554)
The installed SKILL.md carried an unquoted `description` whose value contains "Triggers on: ". In YAML a colon-space inside an unquoted scalar is a nested-mapping indicator, so strict readers — js-yaml's `load`, the frontmatter parser in `npx skills` — reject the whole document. The skill does not load wrongly; it does not load at all, and nothing in the install output says why. Quoting the scalar fixes it without touching a word of the text. The test checks the RULE rather than this string: for every skill, any frontmatter value containing ": " must be quoted. Pinning the current wording would let the next skill someone adds reintroduce exactly this bug. Verified by reverting the fix — the test goes red, and green again with it restored. Reported by @xezzon. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This commit is contained in:
+7
-2
@@ -1255,12 +1255,17 @@ int cbm_replace_binary(const char *path, const unsigned char *data, int len, int
|
||||
static const char skill_content[] =
|
||||
"---\n"
|
||||
"name: codebase-memory\n"
|
||||
"description: Use the codebase knowledge graph for structural code queries. "
|
||||
/* #1554: the value contains "Triggers on: " — a colon-space, which YAML
|
||||
* reads as a nested-mapping indicator inside an unquoted scalar. Strict
|
||||
* parsers (js-yaml's load, the frontmatter reader in `npx skills`) reject
|
||||
* the whole file, so the skill silently fails to load rather than loading
|
||||
* wrongly. Quoting the scalar is the fix; the text itself is unchanged. */
|
||||
"description: \"Use the codebase knowledge graph for structural code queries. "
|
||||
"Triggers on: explore the codebase, understand the architecture, what functions exist, "
|
||||
"show me the structure, who calls this function, what does X call, trace the call chain, "
|
||||
"find callers of, show dependencies, impact analysis, dead code, unused functions, "
|
||||
"high fan-out, refactor candidates, code quality audit, graph query syntax, "
|
||||
"Cypher query examples, edge types, how to use search_graph.\n"
|
||||
"Cypher query examples, edge types, how to use search_graph.\"\n"
|
||||
"---\n"
|
||||
"\n"
|
||||
"# Codebase Memory — Knowledge Graph Tools\n"
|
||||
|
||||
@@ -12101,6 +12101,59 @@ TEST(cli_sha256_file_matches_known_vector) {
|
||||
* words people already type is not. Both flags must be accepted, do nothing,
|
||||
* and say so once. A genuinely unknown flag must still be rejected, or this
|
||||
* degenerates into ignoring typos. */
|
||||
/* #1554: the skill's `description` contained "Triggers on: " — a colon-space,
|
||||
* which YAML reads as a nested-mapping indicator inside an UNQUOTED scalar.
|
||||
* Strict readers (js-yaml's load, the frontmatter parser in `npx skills`)
|
||||
* reject the whole document, so the installed skill silently fails to load.
|
||||
*
|
||||
* The rule is checked for EVERY skill, not just the one that broke: any
|
||||
* frontmatter scalar whose value contains ": " must be quoted. Pinning only
|
||||
* the current text would let the next added skill reintroduce it. */
|
||||
TEST(cli_skill_frontmatter_scalars_with_colons_are_quoted_issue1554) {
|
||||
const cbm_skill_t *sk = cbm_get_skills();
|
||||
ASSERT_NOT_NULL(sk);
|
||||
for (int i = 0; i < CBM_SKILL_COUNT; i++) {
|
||||
const char *body = sk[i].content;
|
||||
ASSERT_NOT_NULL(body);
|
||||
/* Frontmatter is the block between the first two "---" lines. */
|
||||
ASSERT_TRUE(strncmp(body, "---\n", 4) == 0);
|
||||
const char *end = strstr(body + 4, "\n---\n");
|
||||
ASSERT_NOT_NULL(end);
|
||||
|
||||
const char *line = body + 4;
|
||||
while (line < end) {
|
||||
const char *eol = strchr(line, '\n');
|
||||
if (!eol || eol > end) {
|
||||
break;
|
||||
}
|
||||
const char *sep = NULL;
|
||||
for (const char *c = line; c < eol - 1; c++) {
|
||||
if (c[0] == ':' && c[1] == ' ') {
|
||||
sep = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sep) {
|
||||
const char *value = sep + 2;
|
||||
/* A value that itself contains ": " must be quoted, or a
|
||||
* strict parser treats it as a nested mapping. */
|
||||
bool has_inner_colon = false;
|
||||
for (const char *c = value; c < eol - 1; c++) {
|
||||
if (c[0] == ':' && c[1] == ' ') {
|
||||
has_inner_colon = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (has_inner_colon) {
|
||||
ASSERT_TRUE(value[0] == '"' || value[0] == '\'');
|
||||
}
|
||||
}
|
||||
line = eol + 1;
|
||||
}
|
||||
}
|
||||
PASS();
|
||||
}
|
||||
|
||||
TEST(cli_update_accepts_retired_variant_flags_issue1544) {
|
||||
char *ui_argv[] = {"--dry-run", "--ui", "--yes"};
|
||||
char *standard_argv[] = {"--dry-run", "--standard", "--yes"};
|
||||
@@ -12189,6 +12242,7 @@ SUITE(cli) {
|
||||
RUN_TEST(cli_install_config_failure_keeps_published_binary);
|
||||
RUN_TEST(cli_update_download_failure_does_not_quiesce_sessions);
|
||||
RUN_TEST(cli_update_already_current_does_not_quiesce_sessions);
|
||||
RUN_TEST(cli_skill_frontmatter_scalars_with_colons_are_quoted_issue1554);
|
||||
RUN_TEST(cli_update_accepts_retired_variant_flags_issue1544);
|
||||
RUN_TEST(cli_update_agent_configs_finish_before_guard_release);
|
||||
RUN_TEST(cli_uninstall_quiesces_active_cohort_before_removing_binary_and_index);
|
||||
|
||||
Reference in New Issue
Block a user