// Grounded context-pack assembler (Epic #189, Issue #199). Converts a list of
// `RetrievalReference` (the ranked output of `searchVectorsForScope`) into a
// `LocalKnowledgeGroundedContextPack` — a deliberately metadata-only projection that the
// future #200 Conversation Center integration hands to the LLM grounding prompt and the
// answer surface UI.
//
// This pack is structurally distinct from the connected-context layer's
// `GroundedAnswerContextPackSummary` (in `@oscharko-dev/keiko-contracts/bff-wire`): that
// one is shaped around `ConnectedContextPack`, scope kinds (workspace-root, directory,
// files), exploration usage / budget, and uncertainty. Local Knowledge has a different
// runtime model — capsule-set composition, citation-per-chunk — and a different privacy
// contract (we never carry raw text in this PR; `outputMode === "raw"` lands in #200
// where the workspace FS port is wired and we can read the parsed_unit's character
// span from disk). Keeping the two pack types distinct prevents accidental cross-wiring
// when the BFF layer eventually surfaces both.
//
// The pack is pure data — no IO, no allocation beyond the returned record + its
// citation array. Sorting and de-duplication are stable on `chunkId` so the pack is
// byte-identical across runs with the same inputs (load-bearing for the audit ledger).
// Bumped when the wire shape changes. Consumers (audit ledger, future #200 wire) pin
// against this literal so an unrecognised pack is rejected at the boundary.
export const LOCAL_KNOWLEDGE_GROUNDED_CONTEXT_PACK_VERSION = "1";
export function assembleGroundedContext(references, _options = {}) {
    const capsuleIds = collectSortedUnique(references.map((r) => r.capsuleId));
    const sourceIds = collectSortedUnique(references.map((r) => r.citation.sourceId));
    return {
        schemaVersion: LOCAL_KNOWLEDGE_GROUNDED_CONTEXT_PACK_VERSION,
        scope: {
            capsuleIds,
            sourceIds,
            capsuleCount: capsuleIds.length,
            sourceCount: sourceIds.length,
        },
        citations: references.map((r) => r.citation),
        counts: {
            totalReferences: references.length,
            distinctCapsules: capsuleIds.length,
            distinctSources: sourceIds.length,
        },
    };
}
function collectSortedUnique(values) {
    const seen = new Map();
    for (const value of values) {
        const key = String(value);
        if (!seen.has(key))
            seen.set(key, value);
    }
    return [...seen.values()].sort((a, b) => String(a).localeCompare(String(b)));
}
