{"record":{"id":"c073fff8b34aa82f","repo":"stablyai/orca","slug":"verify-skills-cli-runtime-skills-list-omitted","errorCode":null,"errorMessage":"[verify-skills-cli-runtime] skills list omitted ${topic}","messagePattern":"\\[verify-skills-cli-runtime\\] skills list omitted (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"config/scripts/verify-skills-cli-runtime.cjs","lineNumber":184,"sourceCode":"function parseJson(label, output) {\n  try {\n    return JSON.parse(output)\n  } catch {\n    throw new Error(`[verify-skills-cli-runtime] ${label} emitted invalid JSON:\\n${output}`)\n  }\n}\n\nfunction verifySkillsCliRuntime(outDir, artifactRoot = dirname(outDir), options = {}) {\n  const absoluteOutDir = resolve(outDir)\n  const closure = collectRuntimeClosure(absoluteOutDir, resolve(artifactRoot))\n  if (options.executeCommands === false) {\n    return { closureFiles: closure.length, commands: 0 }\n  }\n  const list = parseJson('skills list', runCli(absoluteOutDir, ['skills', 'list', '--json']))\n  const topicNames = new Set(list.topics?.map((topic) => topic.name))\n  for (const topic of ['orca-cli', 'computer-use']) {\n    if (!topicNames.has(topic)) {\n      throw new Error(`[verify-skills-cli-runtime] skills list omitted ${topic}`)\n    }\n    const guide = runCli(absoluteOutDir, ['skills', 'get', topic])\n    if (!guide.includes(`name: ${topic}`)) {\n      throw new Error(`[verify-skills-cli-runtime] skills get ${topic} returned the wrong guide`)\n    }\n  }\n\n  const install = parseJson(\n    'skills install --dry-run',\n    runCli(absoluteOutDir, [\n      'skills',\n      'install',\n      '--skill',\n      'orca-cli',\n      '--agent',\n      'codex',\n      '--dry-run',\n      '--json'","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/verify-skills-cli-runtime.cjs#L166-L202","documentation":"Thrown by verifySkillsCliRuntime() when the skills list --json output does not include an expected topic ('orca-cli' or 'computer-use'). The script iterates a hardcoded list of required topics and checks topicNames.has(topic). This verifies that the built CLI advertises the topics the runtime expects to be present.","triggerScenarios":"skills list returns valid JSON with a topics array, but none of the objects have name === 'orca-cli' or name === 'computer-use'. Caused by a topic being renamed, removed, filtered out, or the topics array being absent/empty in the list response.","commonSituations":"A topic was renamed in the skills registry (e.g. 'orca-cli' → 'orca'); a conditional registration that skips topics in a minimal build; a packaging step that omits topic manifests from the outDir; a schema change where the name field moved or was nested differently.","solutions":["Run skills list --json and inspect the topics array — confirm the name field shape and whether the expected topics appear under a different name.","If a topic was intentionally renamed, update the hardcoded array ['orca-cli', 'computer-use'] in verifySkillsCliRuntime.","If a topic is missing from the build, check the skills bundling/packaging step that copies topic manifests into outDir.","Verify the topics array is populated and not an empty/undefined value due to a list() implementation change."],"exampleFix":"// before: required topic renamed but verifier not updated\nfor (const topic of ['orca-cli', 'computer-use']) {\n  if (!topicNames.has(topic)) {\n    throw new Error(`[verify-skills-cli-runtime] skills list omitted ${topic}`)\n  }\n}\n\n// after: align verifier with renamed topic\nfor (const topic of ['orca', 'computer-use']) {\n  if (!topicNames.has(topic)) {\n    throw new Error(`[verify-skills-cli-runtime] skills list omitted ${topic}`)\n  }\n}","handlingStrategy":"validation","validationCode":"const REQUIRED_TOPICS = ['orca-cli', 'computer-use']\nfunction validateTopics(list) {\n  const names = new Set((list.topics ?? []).map((t) => t.name))\n  const missing = REQUIRED_TOPICS.filter((t) => !names.has(t))\n  if (missing.length > 0) {\n    throw new Error(`Missing required topics: ${missing.join(', ')}. Found: ${[...names].join(', ')}`)\n  }\n}","typeGuard":"function isTopicList(value) {\n  return value !== null && typeof value === 'object' &&\n    Array.isArray(value.topics) &&\n    value.topics.every((t) => typeof t?.name === 'string')\n}","tryCatchPattern":"try {\n  const list = parseJson('skills list', runCli(outDir, ['skills', 'list', '--json']))\n  if (!isTopicList(list)) {\n    throw new Error('skills list returned unexpected schema')\n  }\n  validateTopics(list)\n} catch (err) {\n  console.error('Topic validation failed:', err.message)\n  throw err\n}","preventionTips":["When renaming a topic, update REQUIRED_TOPICS in the same commit.","Add a unit test that asserts the skills registry includes all required topics.","Document the required-topic contract near the topic registration code."],"tags":["ci","skills-cli","topic-registration","verification","schema"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}