feat(harness-f2): loadSkills expõe versionId (pré-requisito da telemetria)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Xh2xNpYkUm23ijNBVjDVa
This commit is contained in:
Rafael Melgaço
2026-07-24 12:08:20 -03:00
co-authored by Claude Opus 4.8
parent 1302e0d81e
commit eb51e2d6b4
2 changed files with 15 additions and 2 deletions
+11
View File
@@ -0,0 +1,11 @@
import { describe, expect, it, vi } from 'vitest';
import { loadSkills } from './skills';
describe('loadSkills', () => {
it('loadSkills expõe versionId de cada skill', async () => {
const rows = [{ organization_id: null, id: 'ver-1', name: 'frete', description: 'd', body: 'b', matcher: { any_keywords: ['frete'] } }];
const db = { query: vi.fn().mockResolvedValue({ rows }) } as never;
const skills = await loadSkills(db, 'org1');
expect(skills[0]?.versionId).toBe('ver-1');
});
});
+4 -2
View File
@@ -62,6 +62,7 @@ export interface SkillVersionRow {
/** Skill ativa carregada por ponteiro — o que o runtime resolve no início do run. */
export interface LoadedSkill {
versionId: string;
name: string;
description: string;
body: string;
@@ -149,13 +150,14 @@ export async function setSkillPointer(
*/
export async function loadSkills(db: Queryable, tenantId: string): Promise<LoadedSkill[]> {
const { rows } = await db.query<{
id: string;
organization_id: string | null;
name: string;
description: string;
body: string;
matcher: SkillMatcher;
}>(
`select v.organization_id, v.name, v.description, v.body, v.matcher
`select v.id, v.organization_id, v.name, v.description, v.body, v.matcher
from skill_pointers p
join skill_versions v on v.id = p.version_id
where p.organization_id is null or p.organization_id = $1`,
@@ -165,7 +167,7 @@ export async function loadSkills(db: Queryable, tenantId: string): Promise<Loade
const byName = new Map<string, LoadedSkill>();
for (const r of rows) {
if (!byName.has(r.name) || r.organization_id !== null) {
byName.set(r.name, { name: r.name, description: r.description, body: r.body, matcher: r.matcher });
byName.set(r.name, { versionId: r.id, name: r.name, description: r.description, body: r.body, matcher: r.matcher });
}
}
return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name));