affaan-m/ECC · error · Error

${pattern.source} is missing the ${pattern.category} row

Error message

${pattern.source} is missing the ${pattern.category} row

What it means

This throw occurs inside the loop over `tablePatterns` in `parseReadmeExpectations`. The script scans README.md's comparison table for three markdown rows — Agents, Commands, Skills — each expected in the form `| Agents | 68 agents |`. If any single row's regex fails to match, the error names which source (`README.md comparison table`) and which category is missing. All three counts feed the cross-document consistency check.

Source

Thrown at scripts/ci/catalog.js:125

  }

  expectations.push({
    category: 'agents',
    mode: 'exact',
    expected: Number(projectTreeAgentsMatch[1]),
    source: 'README.md project tree (agents)'
  });

  const tablePatterns = [
    { category: 'agents', regex: /\|\s*(?:\*\*)?Agents(?:\*\*)?\s*\|\s*(?:(?:PASS:|\u2705)\s*)?(\d+)\s+agents\s*\|/i, source: 'README.md comparison table' },
    { category: 'commands', regex: /\|\s*(?:\*\*)?Commands(?:\*\*)?\s*\|\s*(?:(?:PASS:|\u2705)\s*)?(\d+)\s+commands(?:\s*\([^)]*\))?\s*\|/i, source: 'README.md comparison table' },
    { category: 'skills', regex: /\|\s*(?:\*\*)?Skills(?:\*\*)?\s*\|\s*(?:(?:PASS:|\u2705)\s*)?(\d+)\s+skills\s*\|/i, source: 'README.md comparison table' }
  ];

  for (const pattern of tablePatterns) {
    const match = readmeContent.match(pattern.regex);
    if (!match) {
      throw new Error(`${pattern.source} is missing the ${pattern.category} row`);
    }

    expectations.push({
      category: pattern.category,
      mode: 'exact',
      expected: Number(match[1]),
      source: `${pattern.source} (${pattern.category})`
    });
  }

  return expectations;
}

function parseZhRootReadmeExpectations(readmeContent) {
  const match = readmeContent.match(/你现在可以使用\s+(\d+)\s+个代理、\s*(\d+)\s*个技能和\s*(\d+)\s*个命令/i);
  if (!match) {
    throw new Error('README.zh-CN.md is missing the quick-start catalog summary');
  }

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Open README.md and restore the missing row to the exact form `| Agents | N agents |` (or `| Commands | N commands |` / `| Skills | N skills |`), matching the regex which tolerates optional `**` bold and optional `PASS:`/`✅` prefixes.
  2. Run `node scripts/ci/catalog.js --write` to let the sync functions rewrite all documented counts from the live catalog.
  3. Confirm the row lives in a markdown table (pipe-delimited) and the unit word follows the number with a single space.
  4. Re-run `node scripts/ci/catalog.js` to confirm all three rows now match.

Example fix

// before (README.md comparison table, skills row dropped)
| **Agents** | 68 agents |
| **Commands** | 94 commands |

// after
| **Agents** | 68 agents |
| **Commands** | 94 commands |
| **Skills** | 284 skills |
Defensive patterns

Strategy: validation

Validate before calling

const fs = require('fs');
const readme = fs.readFileSync('README.md', 'utf8');
const rows = [
  { cat: 'agents', re: /\|\s*(?:\*\*)?Agents(?:\*\*)?\s*\|\s*(?:(?:PASS:|\u2705)\s*)?(\d+)\s+agents\s*\|/i },
  { cat: 'commands', re: /\|\s*(?:\*\*)?Commands(?:\*\*)?\s*\|\s*(?:(?:PASS:|\u2705)\s*)?(\d+)\s+commands(?:\s*\([^)]*\))?\s*\|/i },
  { cat: 'skills', re: /\|\s*(?:\*\*)?Skills(?:\*\*)?\s*\|\s*(?:(?:PASS:|\u2705)\s*)?(\d+)\s+skills\s*\|/i },
];
for (const { cat, re } of rows) {
  if (!re.test(readme)) {
    console.error(`README.md comparison table missing ${cat} row`);
    process.exit(1);
  }
}

Type guard

function hasComparisonTableRow(readmeContent, category) {
  const map = {
    agents: /\|\s*(?:\*\*)?Agents(?:\*\*)?\s*\|\s*(?:(?:PASS:|\u2705)\s*)?(\d+)\s+agents\s*\|/i,
    commands: /\|\s*(?:\*\*)?Commands(?:\*\*)?\s*\|\s*(?:(?:PASS:|\u2705)\s*)?(\d+)\s+commands(?:\s*\([^)]*\))?\s*\|/i,
    skills: /\|\s*(?:\*\*)?Skills(?:\*\*)?\s*\|\s*(?:(?:PASS:|\u2705)\s*)?(\d+)\s+skills\s*\|/i,
  };
  const m = readmeContent.match(map[category]);
  return m !== null && Number.isInteger(Number(m[1]));
}

Try / catch

try {
  runCatalogCheck();
} catch (error) {
  if (/comparison table is missing the .* row/i.test(error.message)) {
    console.error('Restore the markdown table row with the exact unit word (agents/commands/skills) after the count.');
    console.error('Run: node scripts/ci/catalog.js --write');
  }
  throw error;
}

Prevention

When it happens

Trigger: Triggered by `node scripts/ci/catalog.js` when the comparison-table section of README.md is missing the Agents, Commands, or Skills row, or the row's wording deviates (e.g. `| **Agents** | 68 |` without the trailing `agents` unit word, or `68` spelled out, or a `PASS:`/emoji prefix in an unexpected position). The check fires per-row, so only the first missing row is reported.

Common situations: The comparison table is reformatted to remove unit words (`agents`, `commands`, `skills`). A row is deleted during a table consolidation. Counts are updated by hand but the unit suffix is dropped. The table is moved to a different doc without updating README.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/34901276574aa82a. Report an issue: GitHub.