Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions docs/agent-map.html

Large diffs are not rendered by default.

22 changes: 19 additions & 3 deletions scripts/agent-docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,19 @@ function formatBulletBlock(raw: string): string {
.join('\n');
}

/** Normalize for duplicate detection (catalog vs stage prose often differ by a period). */
export function proseKey(s: string): string {
return s
.toLowerCase()
.replace(/[\s.]+$/g, '')
.replace(/\s+/g, ' ')
.trim();
}

export function isSameProse(a: string, b: string): boolean {
return Boolean(a) && Boolean(b) && proseKey(a) === proseKey(b);
}

/** First prose paragraph from a source file's leading block comment. */
export function summaryFromSourceJsdoc(source: string): string | undefined {
const m = source.match(/^\/\*\*([\s\S]*?)\*\//);
Expand Down Expand Up @@ -203,9 +216,12 @@ export function loadAgentDocs(
...(stage?.status ? { status: stage.status } : {}),
};

if (stage?.purpose && stage.purpose.length > (doc.summary?.length ?? 0) + 20) {
out[id] = { ...doc, purpose: stage.purpose };
} else if (stage?.purpose && stage.purpose !== doc.summary) {
// Only keep purpose when it adds real information beyond the catalog summary.
if (
stage?.purpose &&
!isSameProse(stage.purpose, doc.summary) &&
stage.purpose.length > (doc.summary?.length ?? 0) + 20
) {
out[id] = { ...doc, purpose: stage.purpose };
} else {
out[id] = doc;
Expand Down
14 changes: 12 additions & 2 deletions scripts/generate-agent-map-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1533,9 +1533,19 @@ ${tilesHtml}
html += '<div class="badge' + (n.contract_status === 'stub' ? ' stub' : '') + '"><i></i>' + escape(n.contract_status) + '</div>';

const summary = doc.summary || '';
const purpose = doc.purpose && doc.purpose !== summary ? doc.purpose : '';
const purpose = doc.purpose || '';
const sameProse = function (a, b) {
if (!a || !b) return false;
const key = function (s) {
return String(s).toLowerCase().replace(/[\s.]+$/g, '').replace(/\s+/g, ' ').trim();
};
return key(a) === key(b);
};
// Catalog one-liner and stage purpose are often identical aside from a period — show once.
if (summary) html += '<p class="p-summary">' + escape(summary) + '</p>';
if (purpose) html += '<p class="p-purpose">' + escape(purpose) + '</p>';
if (purpose && !sameProse(purpose, summary)) {
html += '<p class="p-purpose">' + escape(purpose) + '</p>';
}

html += '<dl>';
html += '<dt>Stage</dt><dd>' + escape(STAGE_NAMES[n.stage] || n.stage) + '</dd>';
Expand Down
Loading