/* run-backfill-revisions — coordinates backfilling revision counts for tracked entities using Git history. Do not handle entity creation or deletion beyond revision updates. Do not perform any operations related to transport or configuration orchestration. Do not parse raw content from files or directories. RFC-1097: step 6 — compass.migrate codemod run Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order. RFC-1097: sweep — werkstatt-engine clean Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics. */ /** * Annotation revision counts from Git history for all tracked entities. * Updates entities and manifests with accurate revision numbers. */ import path from "node:path"; import { getFileRevisionFromHistory } from "./git.ts"; import { getManifestFileName, loadDirectoryManifest, saveDirectoryManifest, upsertManifestRecord, } from "./manifests.ts"; import { readJsonFile, writeJsonFile } from "./json.ts"; import { deletedLogPath } from "./paths.ts"; import { loadEntitiesById, loadPathsCurrent, saveEntitiesById } from "./registry.ts"; import type { DeletedLogItem } from "./types.ts"; export async function runBackfillRevisions(args: { cwd: string }): Promise { const { cwd } = args; const entities = await loadEntitiesById(cwd); const paths = await loadPathsCurrent(cwd); const deletedLog = await readJsonFile(deletedLogPath(cwd)).catch(() => []); const deletedByEntityId = new Map(deletedLog.map((item) => [item.entityId, item])); const manifestCache = new Map>>(); let updatedEntities = 0; let updatedActiveRecords = 0; let updatedDeletedLog = 0; for (const [entityId, entity] of Object.entries(entities)) { const repoPath = entity.currentPath; if (!repoPath) { continue; } const revision = await getFileRevisionFromHistory(cwd, repoPath); if (revision === entity.revision) { continue; } entity.revision = revision; updatedEntities += 1; const deletedItem = deletedByEntityId.get(entityId); if (deletedItem) { deletedItem.lastRevision = revision; updatedDeletedLog += 1; } if (entity.status !== "active" || paths[repoPath] !== entityId) { continue; } const repoDir = path.posix.dirname(repoPath); const fileName = getManifestFileName(repoPath); let manifest = manifestCache.get(repoDir); if (manifest === undefined) { manifest = await loadDirectoryManifest(cwd, repoDir); manifestCache.set(repoDir, manifest); } if (!manifest) { continue; } upsertManifestRecord(manifest, fileName, { entityId, createdAt: entity.createdAt, updatedAt: entity.updatedAt, revision: entity.revision, contentHash: entity.contentHash, gitSha: entity.gitSha, status: entity.status, }); updatedActiveRecords += 1; } await saveEntitiesById(cwd, entities); await Promise.all( Array.from(manifestCache.values()) .filter((manifest): manifest is NonNullable => Boolean(manifest)) .map((manifest) => saveDirectoryManifest(cwd, manifest)), ); if (updatedDeletedLog > 0) { await writeJsonFile(deletedLogPath(cwd), deletedLog); } console.log(""); console.log("Integrity revision backfill"); console.log(` updated entities ${updatedEntities}`); console.log(` updated manifest rows ${updatedActiveRecords}`); console.log(` updated deleted log ${updatedDeletedLog}`); }