coulomb-social/scripts/bubble-corpus-utils.mjs
tegwick b897aa1ee6
Some checks failed
Use-case regression gate / usecase-regressions (push) Has been cancelled
feat: prepare isolated recovery and guarded fresh ReichelAg capture
Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a10e2d-a5ef-7e92-b03d-b1694e915680
2026-10-06 22:11:42 +02:00

30 lines
1.2 KiB
JavaScript

/** Pure capture guards; fixtures must never contain real cookies or notes. */
export function normalizeBubbleRef(value) {
if (typeof value !== 'string') return value;
if (!value.startsWith('LOOKUP__')) return value;
return value.match(/[0-9]+x[0-9]+/)?.[0] || value;
}
export function assertSessionFresh(state, now = Date.now() / 1000) {
if ((state.cookies || []).some(c => c.name.endsWith('.sig') &&
c.expires > 0 && c.expires <= now)) {
throw new Error('bubble_session_expired');
}
}
export function mergeCapturedRecord(existing, source, id) {
return { ...(existing || {}), ...source, _id: normalizeBubbleRef(id) };
}
export function selectTargetArticles(articles, rootId) {
const root = articles[normalizeBubbleRef(rootId)];
const spaceId = normalizeBubbleRef(root?.space_custom_space);
if (!root || !spaceId) throw new Error('target_space_identity_missing');
const selected = Object.values(articles).filter(a =>
normalizeBubbleRef(a.space_custom_space) === spaceId);
if (selected.length <= 1) throw new Error('target_protocols_not_captured');
if (selected.some(a => !Object.hasOwn(a, 'content_text'))) {
throw new Error('target_protocol_bodies_incomplete');
}
return [spaceId, selected];
}