mirror of
https://github.com/Kaelio/ktx.git
synced 2026-07-19 11:41:02 +02:00
Implement adapter-owned ingest finalization v1
Moves finalization from runner-owned post-processors into typed SourceAdapter.finalize() contracts. Adds finalization report schema, scope derivation, override replay context, and migrates historic-SQL projection. Removes IngestBundlePostProcessorPort wiring and HistoricSqlProjectionPostProcessor.
This commit is contained in:
parent
e8d461fcb8
commit
013998387e
25 changed files with 3176 additions and 295 deletions
|
|
@ -14,6 +14,11 @@ import { NOTION_DEFAULT_MAX_KNOWLEDGE_CREATES_PER_RUN } from './adapters/notion/
|
|||
import { validateFinalIngestArtifacts, validateProvenanceRawPaths } from './artifact-gates.js';
|
||||
import { selectRelevantCanonicalPins } from './canonical-pins.js';
|
||||
import { finalGateRepairPaths, repairFinalGateFailure } from './final-gate-repair.js';
|
||||
import {
|
||||
compareFinalizationDeclarations,
|
||||
deriveFinalizationTouchedSources,
|
||||
deriveFinalizationWikiPageKeys,
|
||||
} from './finalization-scope.js';
|
||||
import { FileIngestTraceWriter, ingestTracePathForJob, type IngestTraceWriter, traceTimed } from './ingest-trace.js';
|
||||
import { integrateWorkUnitPatch } from './isolated-diff/patch-integrator.js';
|
||||
import { resolveTextualConflict } from './isolated-diff/textual-conflict-resolver.js';
|
||||
|
|
@ -33,8 +38,8 @@ import type {
|
|||
import { buildSyncId, rawSourcesDirForSync } from './raw-sources-paths.js';
|
||||
import {
|
||||
buildStageIndexFromReportBody,
|
||||
postProcessorSavedMemoryCounts,
|
||||
type IngestReportPostProcessorOutcome,
|
||||
type IngestReportFinalizationProvenanceExclusion,
|
||||
type IngestReportFinalizationOutcome,
|
||||
type IngestReportProvenanceDetail,
|
||||
type IngestReportSnapshot,
|
||||
type IngestReportWorkUnit,
|
||||
|
|
@ -174,6 +179,11 @@ type ProvenanceRowOrigin =
|
|||
actionIndex: number;
|
||||
action: MemoryAction;
|
||||
}
|
||||
| {
|
||||
source: 'finalization_action';
|
||||
actionIndex: number;
|
||||
action: MemoryAction;
|
||||
}
|
||||
| {
|
||||
source: 'artifact_resolution';
|
||||
resolutionIndex: number;
|
||||
|
|
@ -411,6 +421,19 @@ export class IngestBundleRunner {
|
|||
return false;
|
||||
}
|
||||
|
||||
private async loadSourcesByConnection(
|
||||
workdir: string,
|
||||
connectionIds: string[],
|
||||
): Promise<Map<string, SemanticLayerSource[]>> {
|
||||
const service = this.deps.semanticLayerService.forWorktree(workdir);
|
||||
const result = new Map<string, SemanticLayerSource[]>();
|
||||
for (const connectionId of connectionIds) {
|
||||
const { sources } = await service.loadAllSources(connectionId);
|
||||
result.set(connectionId, sources);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private resolveContextCuratorBudget(
|
||||
bundleRef: IngestBundleJob['bundleRef'],
|
||||
stageIndex: StageIndex,
|
||||
|
|
@ -466,6 +489,7 @@ export class IngestBundleRunner {
|
|||
currentHashes: Map<string, string>;
|
||||
stageIndex: StageIndex;
|
||||
reconcileActions: MemoryAction[];
|
||||
finalizationActions: MemoryAction[];
|
||||
}): ProvenancePlan {
|
||||
const rows: IngestProvenanceInsert[] = [];
|
||||
const diagnostics: ProvenanceRowDiagnostic[] = [];
|
||||
|
|
@ -523,6 +547,15 @@ export class IngestBundleRunner {
|
|||
});
|
||||
}
|
||||
});
|
||||
input.finalizationActions.forEach((action, actionIndex) => {
|
||||
for (const rawPath of action.rawPaths ?? []) {
|
||||
pushActionProvenance(rawPath, action, {
|
||||
source: 'finalization_action',
|
||||
actionIndex,
|
||||
action,
|
||||
});
|
||||
}
|
||||
});
|
||||
(input.stageIndex.artifactResolutions ?? []).forEach((resolution, resolutionIndex) => {
|
||||
const hash = input.currentHashes.get(resolution.rawPath) ?? '';
|
||||
pushRow(
|
||||
|
|
@ -569,6 +602,35 @@ export class IngestBundleRunner {
|
|||
return { rows, diagnostics };
|
||||
}
|
||||
|
||||
private partitionFinalizationActionsForProvenance(input: {
|
||||
actions: MemoryAction[];
|
||||
currentRawPaths: Set<string>;
|
||||
currentEvictionRawPaths: Set<string>;
|
||||
overrideEvictionRawPaths: Set<string>;
|
||||
}): { actions: MemoryAction[]; exclusions: IngestReportFinalizationProvenanceExclusion[] } {
|
||||
const defensible = new Set([
|
||||
...input.currentRawPaths,
|
||||
...input.currentEvictionRawPaths,
|
||||
...input.overrideEvictionRawPaths,
|
||||
]);
|
||||
const actions: MemoryAction[] = [];
|
||||
const exclusions: IngestReportFinalizationProvenanceExclusion[] = [];
|
||||
for (const action of input.actions) {
|
||||
const rawPaths = action.rawPaths ?? [];
|
||||
if (rawPaths.length === 0) {
|
||||
exclusions.push({ action, reason: 'missing_raw_paths' });
|
||||
continue;
|
||||
}
|
||||
const invalidRawPaths = rawPaths.filter((rawPath) => !defensible.has(rawPath)).sort();
|
||||
if (invalidRawPaths.length > 0) {
|
||||
exclusions.push({ action, reason: 'raw_path_not_defensible', invalidRawPaths });
|
||||
continue;
|
||||
}
|
||||
actions.push(action);
|
||||
}
|
||||
return { actions, exclusions };
|
||||
}
|
||||
|
||||
private toReportProvenanceRows(rows: IngestProvenanceInsert[]): IngestReportProvenanceDetail[] {
|
||||
return rows.map(({ rawPath, artifactKind, artifactKey, actionType, targetConnectionId }) => ({
|
||||
rawPath,
|
||||
|
|
@ -951,6 +1013,7 @@ export class IngestBundleRunner {
|
|||
let latestEvictionInputs: string[] = [];
|
||||
let latestUnresolvedCards: UnresolvedCardInfo[] = [];
|
||||
let latestReportProvenanceRows: IngestReportProvenanceDetail[] = [];
|
||||
let latestFinalizationOutcome: IngestReportFinalizationOutcome | undefined;
|
||||
let activeFailureDetails: Record<string, unknown> | undefined;
|
||||
let latestIsolatedDiffSummary:
|
||||
| {
|
||||
|
|
@ -1174,7 +1237,7 @@ export class IngestBundleRunner {
|
|||
let unresolvedCards: UnresolvedCardInfo[] | undefined;
|
||||
let sourceContextReport: { capped?: boolean; warnings?: string[] } | undefined;
|
||||
let parseArtifacts: unknown;
|
||||
let postProcessorOutcome: IngestReportPostProcessorOutcome | undefined;
|
||||
let finalizationOutcome: IngestReportFinalizationOutcome | undefined;
|
||||
let wikiSlRefRepairResult: WikiSlRefRepairResult | null = null;
|
||||
let reconcileNotes: string[] = [];
|
||||
let triageResult: PageTriageRunResult | null = null;
|
||||
|
|
@ -1954,62 +2017,215 @@ export class IngestBundleRunner {
|
|||
|
||||
await stage4?.updateProgress(1.0, reconcileOutcome.skipped ? 'No reconciliation needed' : 'Reconciled');
|
||||
|
||||
const postProcessor = this.deps.postProcessors?.[job.sourceKey];
|
||||
activePhase = 'post_processor';
|
||||
if (postProcessor) {
|
||||
const stagePostProcessor = ctx?.startPhase(0.04);
|
||||
emitStageProgress('post_processor', 87, 'Running deterministic imports');
|
||||
await stagePostProcessor?.updateProgress(0.0, 'Running deterministic imports');
|
||||
try {
|
||||
const result = await traceTimed(
|
||||
runTrace,
|
||||
'post_processor',
|
||||
'post_processor',
|
||||
{ sourceKey: job.sourceKey },
|
||||
() =>
|
||||
postProcessor.run({
|
||||
connectionId: job.connectionId,
|
||||
sourceKey: job.sourceKey,
|
||||
syncId,
|
||||
jobId: job.jobId,
|
||||
runId: createdRunRow.id,
|
||||
workdir: sessionWorktree.workdir,
|
||||
parseArtifacts,
|
||||
}),
|
||||
);
|
||||
postProcessorOutcome = {
|
||||
const preFinalizationSha = await sessionWorktree.git.revParseHead();
|
||||
const preFinalizationSourcesByConnection = await this.loadSourcesByConnection(
|
||||
sessionWorktree.workdir,
|
||||
slConnectionIds,
|
||||
);
|
||||
let finalizationActions: MemoryAction[] = [];
|
||||
let finalizationTouchedPaths: string[] = [];
|
||||
let finalizationTouchedSources: TouchedSlSource[] = [];
|
||||
let finalizationChangedWikiPageKeys: string[] = [];
|
||||
let finalizationSha: string | null = null;
|
||||
|
||||
activePhase = 'finalization';
|
||||
if (adapter.finalize) {
|
||||
const stageFinalization = ctx?.startPhase(0.04);
|
||||
emitStageProgress('finalization', 87, 'Running deterministic finalization');
|
||||
await stageFinalization?.updateProgress(0.0, 'Running deterministic finalization');
|
||||
await runTrace.event('debug', 'finalization', 'finalization_started', { sourceKey: job.sourceKey });
|
||||
const result = await adapter.finalize({
|
||||
connectionId: job.connectionId,
|
||||
sourceKey: job.sourceKey,
|
||||
syncId,
|
||||
jobId: job.jobId,
|
||||
runId: createdRunRow.id,
|
||||
stagedDir,
|
||||
workdir: sessionWorktree.workdir,
|
||||
...(overrideReport ? {} : { parseArtifacts }),
|
||||
stageIndex,
|
||||
workUnitOutcomes,
|
||||
reconciliationActions: reconcileActions,
|
||||
...(overrideReport
|
||||
? {
|
||||
overrideReplay: {
|
||||
priorJobId: overrideReport.jobId,
|
||||
priorRunId: overrideReport.runId,
|
||||
priorSyncId: overrideReport.body.syncId,
|
||||
evictionRawPaths: overrideReport.body.evictionInputs,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
});
|
||||
if (result.errors.length > 0) {
|
||||
finalizationOutcome = {
|
||||
sourceKey: job.sourceKey,
|
||||
status: result.errors.length > 0 && result.touchedSources.length === 0 ? 'failed' : 'success',
|
||||
status: 'failed',
|
||||
commitSha: null,
|
||||
touchedPaths: [],
|
||||
declaredTouchedSources: result.touchedSources,
|
||||
derivedTouchedSources: [],
|
||||
declaredChangedWikiPageKeys: result.changedWikiPageKeys,
|
||||
derivedChangedWikiPageKeys: [],
|
||||
mismatches: [],
|
||||
result: result.result,
|
||||
errors: result.errors,
|
||||
warnings: result.warnings,
|
||||
touchedSources: result.touchedSources,
|
||||
actions: result.actions ?? [],
|
||||
provenanceExclusions: [],
|
||||
};
|
||||
emitStageProgress('post_processor', 88, 'Deterministic imports complete');
|
||||
await stagePostProcessor?.updateProgress(1.0, 'Deterministic imports complete');
|
||||
} catch (error) {
|
||||
postProcessorOutcome = {
|
||||
latestFinalizationOutcome = finalizationOutcome;
|
||||
await runTrace.event('error', 'finalization', 'finalization_failed', {
|
||||
sourceKey: job.sourceKey,
|
||||
errors: result.errors,
|
||||
warnings: result.warnings,
|
||||
});
|
||||
throw new Error(`deterministic finalization failed: ${result.errors.join('; ')}`);
|
||||
}
|
||||
|
||||
const changedBeforeFinalization = new Set([
|
||||
...projectionTouchedPaths,
|
||||
...workUnitOutcomes.flatMap((outcome) => outcome.patchTouchedPaths ?? []),
|
||||
...(preReconciliationSha && preFinalizationSha !== preReconciliationSha
|
||||
? (await sessionWorktree.git.diffNameStatus(preReconciliationSha, preFinalizationSha)).map(
|
||||
(entry) => entry.path,
|
||||
)
|
||||
: []),
|
||||
]);
|
||||
finalizationTouchedPaths = await sessionWorktree.git.changedPaths();
|
||||
const overlapping = finalizationTouchedPaths.filter((path) => changedBeforeFinalization.has(path));
|
||||
if (overlapping.length > 0) {
|
||||
await runTrace.event('error', 'finalization', 'finalization_failed', {
|
||||
sourceKey: job.sourceKey,
|
||||
reason: 'path_overlap',
|
||||
overlappingPaths: overlapping.sort(),
|
||||
});
|
||||
throw new Error(
|
||||
`finalization modified path(s) already changed earlier in this run: ${overlapping.sort().join(', ')}`,
|
||||
);
|
||||
}
|
||||
|
||||
const finalizationCommit =
|
||||
finalizationTouchedPaths.length > 0
|
||||
? await sessionWorktree.git.commitFiles(
|
||||
finalizationTouchedPaths,
|
||||
`ingest(${job.sourceKey}): deterministic finalization syncId=${syncId}`,
|
||||
this.deps.storage.systemGitAuthor.name,
|
||||
this.deps.storage.systemGitAuthor.email,
|
||||
)
|
||||
: await sessionWorktree.git.commitStaged(
|
||||
`ingest(${job.sourceKey}): deterministic finalization syncId=${syncId}`,
|
||||
this.deps.storage.systemGitAuthor.name,
|
||||
this.deps.storage.systemGitAuthor.email,
|
||||
);
|
||||
finalizationSha = finalizationCommit.created ? finalizationCommit.commitHash : null;
|
||||
const postFinalizationSha = await sessionWorktree.git.revParseHead();
|
||||
finalizationTouchedPaths =
|
||||
preFinalizationSha !== postFinalizationSha
|
||||
? (await sessionWorktree.git.diffNameStatus(preFinalizationSha, postFinalizationSha)).map(
|
||||
(entry) => entry.path,
|
||||
)
|
||||
: [];
|
||||
|
||||
const changedConnectionIds = [
|
||||
...new Set([
|
||||
...slConnectionIds,
|
||||
...finalizationTouchedPaths
|
||||
.filter((path) => path.startsWith('semantic-layer/'))
|
||||
.map((path) => path.split('/')[1])
|
||||
.filter((connectionId): connectionId is string => Boolean(connectionId)),
|
||||
]),
|
||||
].sort();
|
||||
const postFinalizationSourcesByConnection = await this.loadSourcesByConnection(
|
||||
sessionWorktree.workdir,
|
||||
changedConnectionIds,
|
||||
);
|
||||
const scope = await deriveFinalizationTouchedSources({
|
||||
changedPaths: finalizationTouchedPaths,
|
||||
beforeSourcesByConnection: preFinalizationSourcesByConnection,
|
||||
afterSourcesByConnection: postFinalizationSourcesByConnection,
|
||||
});
|
||||
if (scope.unresolvedPaths.length > 0) {
|
||||
await runTrace.event('error', 'finalization', 'finalization_failed', {
|
||||
sourceKey: job.sourceKey,
|
||||
reason: 'unresolved_semantic_layer_paths',
|
||||
unresolvedPaths: scope.unresolvedPaths,
|
||||
});
|
||||
throw new Error(`could not resolve finalization semantic-layer path(s): ${scope.unresolvedPaths.join(', ')}`);
|
||||
}
|
||||
finalizationTouchedSources = scope.touchedSources;
|
||||
finalizationChangedWikiPageKeys = deriveFinalizationWikiPageKeys(finalizationTouchedPaths);
|
||||
const mismatches = compareFinalizationDeclarations({
|
||||
declaredTouchedSources: result.touchedSources,
|
||||
derivedTouchedSources: finalizationTouchedSources,
|
||||
declaredChangedWikiPageKeys: result.changedWikiPageKeys,
|
||||
derivedChangedWikiPageKeys: finalizationChangedWikiPageKeys,
|
||||
});
|
||||
if (mismatches.length > 0) {
|
||||
finalizationOutcome = {
|
||||
sourceKey: job.sourceKey,
|
||||
status: 'failed',
|
||||
errors: [error instanceof Error ? error.message : String(error)],
|
||||
warnings: [],
|
||||
touchedSources: [],
|
||||
commitSha: finalizationSha,
|
||||
touchedPaths: finalizationTouchedPaths,
|
||||
declaredTouchedSources: result.touchedSources,
|
||||
derivedTouchedSources: finalizationTouchedSources,
|
||||
declaredChangedWikiPageKeys: result.changedWikiPageKeys,
|
||||
derivedChangedWikiPageKeys: finalizationChangedWikiPageKeys,
|
||||
mismatches,
|
||||
result: result.result,
|
||||
errors: ['finalization touched artifact declaration mismatch'],
|
||||
warnings: result.warnings,
|
||||
actions: result.actions ?? [],
|
||||
provenanceExclusions: [],
|
||||
};
|
||||
await this.deps.runs.markFailed(runRow.id);
|
||||
throw error;
|
||||
latestFinalizationOutcome = finalizationOutcome;
|
||||
await runTrace.event('error', 'finalization', 'finalization_failed', {
|
||||
sourceKey: job.sourceKey,
|
||||
reason: 'declaration_mismatch',
|
||||
mismatches,
|
||||
});
|
||||
throw new Error(
|
||||
`finalization touched artifact declaration mismatch: ${mismatches
|
||||
.map((mismatch) => `${mismatch.direction}:${mismatch.artifactKind}:${mismatch.key}`)
|
||||
.join(', ')}`,
|
||||
);
|
||||
}
|
||||
finalizationActions = result.actions ?? [];
|
||||
finalizationOutcome = {
|
||||
sourceKey: job.sourceKey,
|
||||
status: 'success',
|
||||
commitSha: finalizationSha,
|
||||
touchedPaths: finalizationTouchedPaths,
|
||||
declaredTouchedSources: result.touchedSources,
|
||||
derivedTouchedSources: finalizationTouchedSources,
|
||||
declaredChangedWikiPageKeys: result.changedWikiPageKeys,
|
||||
derivedChangedWikiPageKeys: finalizationChangedWikiPageKeys,
|
||||
mismatches,
|
||||
result: result.result,
|
||||
errors: [],
|
||||
warnings: result.warnings,
|
||||
actions: finalizationActions,
|
||||
provenanceExclusions: [],
|
||||
};
|
||||
latestFinalizationOutcome = finalizationOutcome;
|
||||
emitStageProgress('finalization', 88, 'Deterministic finalization complete');
|
||||
await stageFinalization?.updateProgress(1.0, 'Deterministic finalization complete');
|
||||
await runTrace.event('debug', 'finalization', 'finalization_committed', {
|
||||
sourceKey: job.sourceKey,
|
||||
commitSha: finalizationSha,
|
||||
touchedPaths: finalizationTouchedPaths,
|
||||
touchedSources: finalizationTouchedSources,
|
||||
changedWikiPageKeys: finalizationChangedWikiPageKeys,
|
||||
warnings: result.warnings,
|
||||
});
|
||||
} else {
|
||||
await runTrace.event('debug', 'finalization', 'finalization_skipped', { sourceKey: job.sourceKey });
|
||||
}
|
||||
await runTrace.event('debug', 'post_processor', 'post_processor_finished', {
|
||||
sourceKey: job.sourceKey,
|
||||
status: postProcessorOutcome?.status ?? 'skipped',
|
||||
touchedSources: postProcessorOutcome?.touchedSources ?? [],
|
||||
warnings: postProcessorOutcome?.warnings ?? [],
|
||||
});
|
||||
|
||||
const repairConnectionIds = [
|
||||
...new Set([
|
||||
...slConnectionIds,
|
||||
...(postProcessorOutcome?.touchedSources ?? []).map((source) => source.connectionId),
|
||||
...finalizationTouchedSources.map((source) => source.connectionId),
|
||||
]),
|
||||
].sort();
|
||||
activePhase = 'wiki_sl_ref_repair';
|
||||
|
|
@ -2044,6 +2260,7 @@ export class IngestBundleRunner {
|
|||
.flatMap((outcome) => outcome.patchTouchedPaths ?? [])
|
||||
.flatMap((path) => this.wikiPageKeysFromPaths([path])),
|
||||
...this.wikiPageKeysFromActions(reconcileActions),
|
||||
...finalizationChangedWikiPageKeys,
|
||||
...postReconciliationPaths.flatMap((path) => this.wikiPageKeysFromPaths([path])),
|
||||
...wikiSlRefRepairResult.repairs.filter((repair) => repair.scope === 'GLOBAL').map((repair) => repair.pageKey),
|
||||
]);
|
||||
|
|
@ -2052,7 +2269,7 @@ export class IngestBundleRunner {
|
|||
...workUnitOutcomes.flatMap((outcome) => outcome.touchedSlSources),
|
||||
...this.touchedSlSourcesFromActions(reconcileActions, job.connectionId),
|
||||
...this.touchedSlSourcesFromPaths(postReconciliationPaths),
|
||||
...(postProcessorOutcome?.touchedSources ?? []),
|
||||
...finalizationTouchedSources,
|
||||
]);
|
||||
const finalWikiGateScope = await this.wikiPageKeysForFinalGates({
|
||||
wikiService: this.deps.wikiService.forWorktree(sessionWorktree.workdir),
|
||||
|
|
@ -2066,9 +2283,7 @@ export class IngestBundleRunner {
|
|||
...projectionTouchedPaths,
|
||||
...workUnitOutcomes.flatMap((outcome) => outcome.patchTouchedPaths ?? []),
|
||||
...postReconciliationPaths,
|
||||
...(postProcessorOutcome?.touchedSources ?? []).map(
|
||||
(source) => `semantic-layer/${source.connectionId}/${source.sourceName}.yaml`,
|
||||
),
|
||||
...finalizationTouchedPaths,
|
||||
];
|
||||
const targetPolicyTraceData = {
|
||||
allowedTargetConnectionIds: slConnectionIds,
|
||||
|
|
@ -2235,12 +2450,23 @@ export class IngestBundleRunner {
|
|||
latestArtifactResolutions = stageIndex.artifactResolutions ?? [];
|
||||
latestEvictionInputs = eviction?.deletedRawPaths ?? [];
|
||||
latestUnresolvedCards = unresolvedCards ?? [];
|
||||
const finalizationProvenance = this.partitionFinalizationActionsForProvenance({
|
||||
actions: finalizationActions,
|
||||
currentRawPaths: new Set(currentHashes.keys()),
|
||||
currentEvictionRawPaths: new Set(stageIndex.evictionsApplied.map((entry) => entry.rawPath)),
|
||||
overrideEvictionRawPaths: new Set(overrideReport?.body.evictionInputs ?? []),
|
||||
});
|
||||
if (finalizationOutcome) {
|
||||
finalizationOutcome.provenanceExclusions = finalizationProvenance.exclusions;
|
||||
latestFinalizationOutcome = finalizationOutcome;
|
||||
}
|
||||
const provenancePlan = this.buildProvenancePlan({
|
||||
job,
|
||||
syncId,
|
||||
currentHashes,
|
||||
stageIndex,
|
||||
reconcileActions,
|
||||
finalizationActions: finalizationProvenance.actions,
|
||||
});
|
||||
const provenanceRows = provenancePlan.rows;
|
||||
const currentRawPaths = new Set(currentHashes.keys());
|
||||
|
|
@ -2300,13 +2526,15 @@ export class IngestBundleRunner {
|
|||
commitSha,
|
||||
touchedPaths: mergeResult.touchedPaths,
|
||||
});
|
||||
const memoryFlowSavedActions = stageIndex.workUnits.flatMap((wu) => wu.actions).concat(reconcileActions);
|
||||
const postProcessorMemoryCounts = postProcessorSavedMemoryCounts(postProcessorOutcome);
|
||||
const memoryFlowSavedActions = stageIndex.workUnits
|
||||
.flatMap((wu) => wu.actions)
|
||||
.concat(reconcileActions)
|
||||
.concat(finalizationActions);
|
||||
memoryFlow?.emit({
|
||||
type: 'saved',
|
||||
commitSha,
|
||||
wikiCount: countMemoryFlowActions(memoryFlowSavedActions, 'wiki') + postProcessorMemoryCounts.wikiCount,
|
||||
slCount: countMemoryFlowActions(memoryFlowSavedActions, 'sl') + postProcessorMemoryCounts.slCount,
|
||||
wikiCount: countMemoryFlowActions(memoryFlowSavedActions, 'wiki'),
|
||||
slCount: countMemoryFlowActions(memoryFlowSavedActions, 'sl'),
|
||||
});
|
||||
await stage6?.updateProgress(1.0, commitSha ? `Saved changes (${commitSha.slice(0, 8)})` : 'No changes to save');
|
||||
|
||||
|
|
@ -2325,7 +2553,7 @@ export class IngestBundleRunner {
|
|||
memoryFlowSavedActions
|
||||
.filter((action) => action.target === 'sl')
|
||||
.map((action) => actionTargetConnectionId(action, job.connectionId))
|
||||
.concat((postProcessorOutcome?.touchedSources ?? []).map((source) => source.connectionId)),
|
||||
.concat(finalizationTouchedSources.map((source) => source.connectionId)),
|
||||
),
|
||||
].sort();
|
||||
for (const connectionId of touchedConnections) {
|
||||
|
|
@ -2416,7 +2644,7 @@ export class IngestBundleRunner {
|
|||
overrideOf: overrideReport?.jobId ?? null,
|
||||
provenanceRows: reportProvenanceRows,
|
||||
toolTranscripts: reportToolTranscripts,
|
||||
postProcessor: postProcessorOutcome,
|
||||
finalization: finalizationOutcome,
|
||||
wikiSlRefRepairs: wikiSlRefRepairResult.repairs,
|
||||
wikiSlRefRepairWarnings: wikiSlRefRepairResult.warnings,
|
||||
...(reportMemoryFlow ? { memoryFlow: reportMemoryFlow } : {}),
|
||||
|
|
@ -2585,6 +2813,7 @@ export class IngestBundleRunner {
|
|||
artifactResolutions: latestArtifactResolutions,
|
||||
evictionInputs: latestEvictionInputs,
|
||||
reconciliationActions: latestReconciliationActions,
|
||||
finalization: latestFinalizationOutcome,
|
||||
evictionDecisions: [],
|
||||
unresolvedCards: latestUnresolvedCards,
|
||||
supersededBy: null,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue