kibi-cli 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-json-command.d.ts +1 -2
- package/dist/cli-json-command.d.ts.map +1 -1
- package/dist/cli-json-command.js +88 -44
- package/dist/cli-operation-loader.d.ts +3 -0
- package/dist/cli-operation-loader.d.ts.map +1 -0
- package/dist/cli-operation-loader.js +58 -0
- package/dist/cli-operation-metadata.d.ts +82 -0
- package/dist/cli-operation-metadata.d.ts.map +1 -0
- package/dist/cli-operation-metadata.js +106 -0
- package/dist/cli-protocol.d.ts +1 -1
- package/dist/cli-protocol.d.ts.map +1 -1
- package/dist/cli-protocol.js +4 -3
- package/dist/cli-register-foundation.d.ts.map +1 -1
- package/dist/cli-register-foundation.js +14 -17
- package/dist/cli-register-json.d.ts +3 -0
- package/dist/cli-register-json.d.ts.map +1 -0
- package/dist/cli-register-json.js +35 -0
- package/dist/cli-register-maintenance.d.ts.map +1 -1
- package/dist/cli-register-maintenance.js +41 -8
- package/dist/cli-register-reporting.d.ts.map +1 -1
- package/dist/cli-register-reporting.js +18 -14
- package/dist/cli-register-skills.d.ts.map +1 -1
- package/dist/cli-register-skills.js +8 -6
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -2
- package/dist/commands/aggregated-checks.d.ts.map +1 -1
- package/dist/commands/aggregated-checks.js +1 -0
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +30 -12
- package/dist/commands/coverage.d.ts +5 -0
- package/dist/commands/coverage.d.ts.map +1 -1
- package/dist/commands/coverage.js +6 -1
- package/dist/commands/discovery-shared.d.ts +2 -1
- package/dist/commands/discovery-shared.d.ts.map +1 -1
- package/dist/commands/discovery-shared.js +35 -13
- package/dist/commands/discovery-table.d.ts.map +1 -1
- package/dist/commands/discovery-table.js +96 -5
- package/dist/commands/engine.d.ts +8 -0
- package/dist/commands/engine.d.ts.map +1 -0
- package/dist/commands/engine.js +100 -0
- package/dist/commands/gaps.js +1 -1
- package/dist/commands/graph.js +1 -1
- package/dist/commands/query.d.ts.map +1 -1
- package/dist/commands/query.js +3 -1
- package/dist/commands/search.d.ts.map +1 -1
- package/dist/commands/search.js +3 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +2 -1
- package/dist/commands/sync/cache.d.ts +12 -0
- package/dist/commands/sync/cache.d.ts.map +1 -1
- package/dist/commands/sync/cache.js +38 -1
- package/dist/commands/sync/persistence.d.ts +10 -1
- package/dist/commands/sync/persistence.d.ts.map +1 -1
- package/dist/commands/sync/persistence.js +276 -43
- package/dist/commands/sync/staging.d.ts +10 -1
- package/dist/commands/sync/staging.d.ts.map +1 -1
- package/dist/commands/sync/staging.js +84 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +521 -27
- package/dist/commands/usage-metrics.d.ts +66 -2
- package/dist/commands/usage-metrics.d.ts.map +1 -1
- package/dist/commands/usage-metrics.js +34 -24
- package/dist/commands/usage-remediation.d.ts +9 -0
- package/dist/commands/usage-remediation.d.ts.map +1 -0
- package/dist/commands/usage-remediation.js +52 -0
- package/dist/engine-daemon.d.ts +3 -0
- package/dist/engine-daemon.d.ts.map +1 -0
- package/dist/engine-daemon.js +34 -0
- package/dist/engine.d.ts +63 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +1256 -0
- package/dist/extractors/markdown.d.ts +8 -0
- package/dist/extractors/markdown.d.ts.map +1 -1
- package/dist/extractors/markdown.js +69 -2
- package/dist/extractors/relationships.d.ts +2 -0
- package/dist/extractors/relationships.d.ts.map +1 -1
- package/dist/extractors/relationships.js +15 -17
- package/dist/operations/modeling/logic-modeling.d.ts.map +1 -1
- package/dist/operations/modeling/logic-modeling.js +14 -5
- package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
- package/dist/operations/modeling/model-requirement.js +27 -2
- package/dist/operations/modeling/predicate-applyplan.d.ts +1 -1
- package/dist/operations/modeling/predicate-applyplan.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-applyplan.js +18 -6
- package/dist/operations/modeling/predicate-inference.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-inference.js +5 -17
- package/dist/operations/modeling/predicate-loader.js +1 -1
- package/dist/operations/modeling/predicate-types.d.ts +9 -1
- package/dist/operations/modeling/predicate-types.d.ts.map +1 -1
- package/dist/operations/modeling/suggest-predicates.d.ts.map +1 -1
- package/dist/operations/modeling/suggest-predicates.js +35 -11
- package/dist/operations/mutation/audit.js +1 -1
- package/dist/operations/mutation/contradictions.d.ts +1 -1
- package/dist/operations/mutation/contradictions.d.ts.map +1 -1
- package/dist/operations/mutation/contradictions.js +23 -18
- package/dist/operations/mutation/serialization.d.ts.map +1 -1
- package/dist/operations/mutation/serialization.js +6 -3
- package/dist/operations/mutation/upsert.d.ts +3 -1
- package/dist/operations/mutation/upsert.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.js +51 -12
- package/dist/operations/mutation/validate-upsert.d.ts.map +1 -1
- package/dist/operations/mutation/validate-upsert.js +18 -2
- package/dist/operations/mutation/validation.d.ts.map +1 -1
- package/dist/operations/mutation/validation.js +8 -0
- package/dist/operations/semantic-advisor/analysis-receipt.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/analysis-receipt.js +7 -1
- package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/analyze-prose.js +76 -61
- package/dist/operations/semantic-advisor/clauses.d.ts +1 -0
- package/dist/operations/semantic-advisor/clauses.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/clauses.js +7 -7
- package/dist/operations/semantic-advisor/ingestion-boundary.d.ts +18 -0
- package/dist/operations/semantic-advisor/ingestion-boundary.d.ts.map +1 -0
- package/dist/operations/semantic-advisor/ingestion-boundary.js +167 -0
- package/dist/operations/semantic-advisor/shared.d.ts +8 -0
- package/dist/operations/semantic-advisor/shared.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/shared.js +37 -3
- package/dist/operations/semantic-advisor/types.d.ts +5 -0
- package/dist/operations/semantic-advisor/types.d.ts.map +1 -1
- package/dist/prolog/codec.d.ts.map +1 -1
- package/dist/prolog/codec.js +9 -2
- package/dist/prolog.d.ts +14 -0
- package/dist/prolog.d.ts.map +1 -1
- package/dist/prolog.js +279 -69
- package/dist/public/diagnostic-usage.d.ts +17 -0
- package/dist/public/diagnostic-usage.d.ts.map +1 -0
- package/dist/public/diagnostic-usage.js +152 -0
- package/dist/public/distribution-parity.d.ts +90 -0
- package/dist/public/distribution-parity.d.ts.map +1 -0
- package/dist/public/distribution-parity.js +367 -0
- package/dist/public/impact/full-kb-quality.d.ts +2 -0
- package/dist/public/impact/full-kb-quality.d.ts.map +1 -1
- package/dist/public/impact/full-kb-quality.js +53 -1
- package/dist/public/impact-diagnostics.d.ts +2 -0
- package/dist/public/impact-diagnostics.d.ts.map +1 -1
- package/dist/public/impact-diagnostics.js +1 -0
- package/dist/public/operations/catalog.d.ts +151 -6
- package/dist/public/operations/catalog.d.ts.map +1 -1
- package/dist/public/operations/check-executor.d.ts.map +1 -1
- package/dist/public/operations/check-executor.js +4 -0
- package/dist/public/operations/discovery-entities.d.ts.map +1 -1
- package/dist/public/operations/discovery-entities.js +3 -2
- package/dist/public/operations/discovery-executors.d.ts +6 -0
- package/dist/public/operations/discovery-executors.d.ts.map +1 -1
- package/dist/public/operations/discovery-executors.js +58 -5
- package/dist/public/operations/index.d.ts +4 -0
- package/dist/public/operations/index.d.ts.map +1 -1
- package/dist/public/operations/index.js +4 -0
- package/dist/public/operations/legacy-migration-plan.d.ts +113 -0
- package/dist/public/operations/legacy-migration-plan.d.ts.map +1 -0
- package/dist/public/operations/legacy-migration-plan.js +409 -0
- package/dist/public/operations/node-ports.d.ts.map +1 -1
- package/dist/public/operations/node-ports.js +90 -0
- package/dist/public/operations/prolog-json.d.ts.map +1 -1
- package/dist/public/operations/prolog-json.js +14 -4
- package/dist/public/operations/repair-plan.d.ts +184 -0
- package/dist/public/operations/repair-plan.d.ts.map +1 -0
- package/dist/public/operations/repair-plan.js +397 -0
- package/dist/public/operations/runtime-types.d.ts +38 -0
- package/dist/public/operations/runtime-types.d.ts.map +1 -1
- package/dist/public/operations/specs/check.d.ts +2 -2
- package/dist/public/operations/specs/check.js +2 -2
- package/dist/public/operations/specs/discovery.d.ts +1 -1
- package/dist/public/operations/specs/discovery.js +1 -1
- package/dist/public/operations/specs/modeling.d.ts +19 -1
- package/dist/public/operations/specs/modeling.d.ts.map +1 -1
- package/dist/public/operations/specs/modeling.js +16 -1
- package/dist/public/operations/specs/mutation-schemas.d.ts +96 -1
- package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
- package/dist/public/operations/specs/mutation-schemas.js +40 -1
- package/dist/public/operations/specs/reporting.d.ts +42 -1
- package/dist/public/operations/specs/reporting.d.ts.map +1 -1
- package/dist/public/operations/specs/reporting.js +70 -6
- package/dist/public/operations/specs/semantic.js +1 -1
- package/dist/public/operations/specs/upsert.d.ts +96 -1
- package/dist/public/operations/specs/upsert.d.ts.map +1 -1
- package/dist/public/operations/workspace-snapshot.d.ts +10 -0
- package/dist/public/operations/workspace-snapshot.d.ts.map +1 -0
- package/dist/public/operations/workspace-snapshot.js +20 -0
- package/dist/public/schemas/entity.d.ts.map +1 -1
- package/dist/public/schemas/entity.js +43 -1
- package/dist/public/skills/init-kibi/SKILL.md +2 -2
- package/dist/public/skills/kibi-freshness/SKILL.md +2 -2
- package/dist/public/skills/kibi-traceability/SKILL.md +8 -2
- package/dist/public/skills/kibi-usage/SKILL.md +12 -6
- package/dist/public/skills/kibi-usage/resources/fact-lanes.md +1 -1
- package/dist/public/skills/kibi-usage/resources/logic-ir.md +1 -1
- package/dist/public/skills/kibi-usage/resources/operation-access.md +1 -1
- package/dist/public/skills/kibi-usage/resources/workflows.md +19 -2
- package/dist/public/telemetry-acceptance.d.ts +89 -0
- package/dist/public/telemetry-acceptance.d.ts.map +1 -0
- package/dist/public/telemetry-acceptance.js +597 -0
- package/dist/public/telemetry-remediation.d.ts +33 -0
- package/dist/public/telemetry-remediation.d.ts.map +1 -0
- package/dist/public/telemetry-remediation.js +257 -0
- package/dist/public/verification-receipt.d.ts +75 -0
- package/dist/public/verification-receipt.d.ts.map +1 -0
- package/dist/public/verification-receipt.js +129 -0
- package/dist/runtime/cli-runtime.d.ts.map +1 -1
- package/dist/runtime/cli-runtime.js +33 -37
- package/dist/schemas/entity.schema.json +96 -2
- package/dist/traceability/temp-kb.d.ts.map +1 -1
- package/dist/traceability/temp-kb.js +36 -3
- package/dist/types/entities.d.ts +1 -0
- package/dist/types/entities.d.ts.map +1 -1
- package/dist/utils/rule-registry.d.ts +2 -0
- package/dist/utils/rule-registry.d.ts.map +1 -1
- package/package.json +36 -4
- package/src/public/diagnostic-usage.ts +206 -0
- package/src/public/distribution-parity.ts +580 -0
- package/src/public/impact/full-kb-quality.ts +74 -1
- package/src/public/impact-diagnostics.ts +16 -0
- package/src/public/operations/check-executor.ts +4 -0
- package/src/public/operations/discovery-entities.ts +3 -2
- package/src/public/operations/discovery-executors.ts +68 -5
- package/src/public/operations/index.ts +4 -0
- package/src/public/operations/legacy-migration-plan.ts +688 -0
- package/src/public/operations/node-ports.ts +109 -0
- package/src/public/operations/prolog-json.ts +15 -3
- package/src/public/operations/repair-plan.ts +562 -0
- package/src/public/operations/runtime-types.ts +47 -0
- package/src/public/operations/specs/check.ts +2 -2
- package/src/public/operations/specs/discovery.ts +1 -1
- package/src/public/operations/specs/modeling.ts +19 -1
- package/src/public/operations/specs/mutation-schemas.ts +47 -1
- package/src/public/operations/specs/reporting.ts +91 -6
- package/src/public/operations/specs/semantic.ts +1 -1
- package/src/public/operations/workspace-snapshot.ts +28 -0
- package/src/public/schemas/entity.ts +44 -1
- package/src/public/skills/init-kibi/SKILL.md +2 -2
- package/src/public/skills/kibi-freshness/SKILL.md +2 -2
- package/src/public/skills/kibi-traceability/SKILL.md +8 -2
- package/src/public/skills/kibi-usage/SKILL.md +12 -6
- package/src/public/skills/kibi-usage/resources/fact-lanes.md +1 -1
- package/src/public/skills/kibi-usage/resources/logic-ir.md +1 -1
- package/src/public/skills/kibi-usage/resources/operation-access.md +1 -1
- package/src/public/skills/kibi-usage/resources/workflows.md +19 -2
- package/src/public/telemetry-acceptance.ts +859 -0
- package/src/public/telemetry-remediation.ts +462 -0
- package/src/public/verification-receipt.ts +170 -0
- package/src/schemas/entity.schema.json +96 -2
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import * as path from "node:path";
|
|
19
19
|
import { toPrologAtom, toPrologString } from "../../prolog/codec.js";
|
|
20
|
+
import { loadEntities } from "../../public/operations/discovery-entities.js";
|
|
21
|
+
import { appendOnlyVerificationReceiptHistoryErrors } from "../../public/verification-receipt.js";
|
|
20
22
|
// Field categorization for typed fact serialization
|
|
21
23
|
// NOTE: base entity fields (status, owner, priority, severity) are NOT listed here —
|
|
22
24
|
// they are emitted in the base props block above. Only fact-specific atom fields go here.
|
|
@@ -112,6 +114,117 @@ function serializeTypedFactFields(entity) {
|
|
|
112
114
|
}
|
|
113
115
|
return fields;
|
|
114
116
|
}
|
|
117
|
+
function parsePrologList(value) {
|
|
118
|
+
if (typeof value !== "string")
|
|
119
|
+
return [];
|
|
120
|
+
const text = value.trim();
|
|
121
|
+
if (text.length < 2 || !text.startsWith("[") || !text.endsWith("]")) {
|
|
122
|
+
return [];
|
|
123
|
+
}
|
|
124
|
+
const body = text.slice(1, -1).trim();
|
|
125
|
+
if (body.length === 0)
|
|
126
|
+
return [];
|
|
127
|
+
const values = [];
|
|
128
|
+
// IDs are atoms in the Kibi schema. Keep the parser deliberately narrow so
|
|
129
|
+
// a malformed response cannot turn into a destructive path or goal.
|
|
130
|
+
for (const part of body.split(",")) {
|
|
131
|
+
const valuePart = part.trim();
|
|
132
|
+
if (!valuePart)
|
|
133
|
+
continue;
|
|
134
|
+
if (valuePart.startsWith("'") && valuePart.endsWith("'")) {
|
|
135
|
+
values.push(valuePart.slice(1, -1).replaceAll("''", "'"));
|
|
136
|
+
}
|
|
137
|
+
else if (/^[A-Za-z0-9_.:/@+-]+$/.test(valuePart)) {
|
|
138
|
+
values.push(valuePart);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return values;
|
|
142
|
+
}
|
|
143
|
+
async function entityIdsForSource(prolog, sourceFile) {
|
|
144
|
+
const candidates = new Set([
|
|
145
|
+
sourceFile,
|
|
146
|
+
path.relative(process.cwd(), sourceFile),
|
|
147
|
+
path.basename(sourceFile),
|
|
148
|
+
]);
|
|
149
|
+
const ids = new Set();
|
|
150
|
+
for (const candidate of candidates) {
|
|
151
|
+
const result = await prolog.query(`kb_entities_by_source(${toPrologString(candidate)}, Ids)`);
|
|
152
|
+
if (result.success) {
|
|
153
|
+
for (const id of parsePrologList(result.bindings?.Ids))
|
|
154
|
+
ids.add(id);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return [...ids];
|
|
158
|
+
}
|
|
159
|
+
/** Remove entities owned by changed/deleted source files before re-upserting. */
|
|
160
|
+
export async function retractEntitiesForSources(prolog, sourceFiles) {
|
|
161
|
+
const ids = new Set();
|
|
162
|
+
for (const sourceFile of sourceFiles) {
|
|
163
|
+
for (const id of await entityIdsForSource(prolog, sourceFile))
|
|
164
|
+
ids.add(id);
|
|
165
|
+
}
|
|
166
|
+
if (ids.size === 0)
|
|
167
|
+
return 0;
|
|
168
|
+
const goals = [...ids].map((id) => `kb_retract_entity(${toPrologAtom(id)})`);
|
|
169
|
+
const batchRunner = prolog.queryBatch?.bind(prolog);
|
|
170
|
+
if (batchRunner) {
|
|
171
|
+
const result = await batchRunner(goals);
|
|
172
|
+
if (!result.success) {
|
|
173
|
+
throw new Error(result.error ?? "Failed to retract changed source entities");
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
for (const goal of goals) {
|
|
178
|
+
const result = await prolog.query(goal);
|
|
179
|
+
if (!result.success) {
|
|
180
|
+
throw new Error(result.error ?? "Failed to retract changed source entity");
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return ids.size;
|
|
185
|
+
}
|
|
186
|
+
/** Remove an exact entity delta without scanning every indexed source. */
|
|
187
|
+
export async function retractEntitiesById(prolog, entityIds) {
|
|
188
|
+
const ids = [...new Set(entityIds)];
|
|
189
|
+
if (ids.length === 0)
|
|
190
|
+
return 0;
|
|
191
|
+
const goals = ids.map((id) => `kb_retract_entity(${toPrologAtom(id)})`);
|
|
192
|
+
const batchRunner = prolog.queryBatch?.bind(prolog);
|
|
193
|
+
const result = batchRunner
|
|
194
|
+
? await batchRunner(goals)
|
|
195
|
+
: await prolog.query(`rdf_transaction((${goals.join(", ")}))`);
|
|
196
|
+
if (!result.success) {
|
|
197
|
+
throw new Error(result.error ?? "Failed to retract entity delta");
|
|
198
|
+
}
|
|
199
|
+
return ids.length;
|
|
200
|
+
}
|
|
201
|
+
/** Clear outgoing inline relationships for entities whose payload changed. */
|
|
202
|
+
export async function retractEntityRelationshipsById(prolog, entityIds) {
|
|
203
|
+
const ids = [...new Set(entityIds)];
|
|
204
|
+
if (ids.length === 0)
|
|
205
|
+
return;
|
|
206
|
+
const goals = ids.map((id) => `kb_retract_entity_relationships(${toPrologAtom(id)})`);
|
|
207
|
+
const batchRunner = prolog.queryBatch?.bind(prolog);
|
|
208
|
+
const result = batchRunner
|
|
209
|
+
? await batchRunner(goals)
|
|
210
|
+
: await prolog.query(`rdf_transaction((${goals.join(", ")}))`);
|
|
211
|
+
if (!result.success) {
|
|
212
|
+
throw new Error(result.error ?? "Failed to retract relationship delta");
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
export async function retractRelationships(prolog, relationships) {
|
|
216
|
+
if (relationships.length === 0)
|
|
217
|
+
return 0;
|
|
218
|
+
const goals = relationships.map((relationship) => `kb_retract_relationship(${toPrologAtom(relationship.type)}, ${toPrologAtom(relationship.from)}, ${toPrologAtom(relationship.to)})`);
|
|
219
|
+
const batchRunner = prolog.queryBatch?.bind(prolog);
|
|
220
|
+
const result = batchRunner
|
|
221
|
+
? await batchRunner(goals)
|
|
222
|
+
: await prolog.query(`rdf_transaction((${goals.join(", ")}))`);
|
|
223
|
+
if (!result.success) {
|
|
224
|
+
throw new Error(result.error ?? "Failed to retract relationship shard delta");
|
|
225
|
+
}
|
|
226
|
+
return relationships.length;
|
|
227
|
+
}
|
|
115
228
|
function isQueryFailedError(error) {
|
|
116
229
|
const lowered = error.toLowerCase();
|
|
117
230
|
// Only match session-corruption errors that might benefit from a Prolog process restart.
|
|
@@ -138,19 +251,27 @@ async function tryResetPrologProcess(prolog) {
|
|
|
138
251
|
}
|
|
139
252
|
export async function persistEntities(
|
|
140
253
|
// implements REQ-009
|
|
141
|
-
prolog, results, entityIds) {
|
|
254
|
+
prolog, results, entityIds, options = {}) {
|
|
142
255
|
let entityCount = 0;
|
|
143
256
|
let kbModified = false;
|
|
144
|
-
|
|
145
|
-
const
|
|
146
|
-
if (
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
257
|
+
const existingEntityIds = new Set();
|
|
258
|
+
const pendingEntityGoals = [];
|
|
259
|
+
if (options.loadExistingEntityIds !== false) {
|
|
260
|
+
// Generation rebuilds need the complete endpoint inventory for local
|
|
261
|
+
// relationship validation. Journal deltas rely on Prolog's authoritative
|
|
262
|
+
// endpoint checks and must not materialize 10,000 IDs for one upsert.
|
|
263
|
+
const existingIdsResult = await prolog.query("findall(Id, kb_entity(Id, _, _), ExistingIds)");
|
|
264
|
+
if (existingIdsResult.success && existingIdsResult.bindings?.ExistingIds) {
|
|
265
|
+
const raw = existingIdsResult.bindings.ExistingIds;
|
|
266
|
+
const cleaned = raw.trim().replace(/^\[/, "").replace(/\]$/, "");
|
|
267
|
+
if (cleaned) {
|
|
268
|
+
for (const atom of cleaned.split(",")) {
|
|
269
|
+
const id = atom.trim().replace(/^'|'$/g, "");
|
|
270
|
+
if (id) {
|
|
271
|
+
entityIds.add(id);
|
|
272
|
+
existingEntityIds.add(id);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
154
275
|
}
|
|
155
276
|
}
|
|
156
277
|
}
|
|
@@ -159,6 +280,24 @@ prolog, results, entityIds) {
|
|
|
159
280
|
}
|
|
160
281
|
for (const { entity, sourceFile } of results) {
|
|
161
282
|
try {
|
|
283
|
+
if (entity.type === "test" && existingEntityIds.has(entity.id)) {
|
|
284
|
+
const existing = await loadEntities(prolog, {
|
|
285
|
+
id: entity.id,
|
|
286
|
+
type: "test",
|
|
287
|
+
});
|
|
288
|
+
const previous = Array.isArray(existing[0]?.verification_receipts)
|
|
289
|
+
? existing[0].verification_receipts.filter((receipt) => receipt !== null &&
|
|
290
|
+
typeof receipt === "object" &&
|
|
291
|
+
!Array.isArray(receipt))
|
|
292
|
+
: [];
|
|
293
|
+
const next = Array.isArray(entity.verification_receipts)
|
|
294
|
+
? entity.verification_receipts
|
|
295
|
+
: undefined;
|
|
296
|
+
const receiptErrors = appendOnlyVerificationReceiptHistoryErrors(previous, next);
|
|
297
|
+
if (receiptErrors.length > 0) {
|
|
298
|
+
throw new Error(receiptErrors.join("; "));
|
|
299
|
+
}
|
|
300
|
+
}
|
|
162
301
|
const props = [
|
|
163
302
|
`id=${toPrologAtom(entity.id)}`,
|
|
164
303
|
`title=${toPrologString(entity.title)}`,
|
|
@@ -179,14 +318,45 @@ prolog, results, entityIds) {
|
|
|
179
318
|
props.push(`severity=${toPrologAtom(entity.severity)}`);
|
|
180
319
|
if (entity.text_ref)
|
|
181
320
|
props.push(`text_ref=${toPrologString(entity.text_ref)}`);
|
|
321
|
+
if (entity.type === "req" && entity.semantic_text) {
|
|
322
|
+
props.push(`semantic_text=${toPrologString(entity.semantic_text)}`);
|
|
323
|
+
}
|
|
182
324
|
if (entity.type === "req" && entity.logic_claims) {
|
|
183
325
|
props.push(`logic_claims=[${entity.logic_claims.map(toPrologAtom).join(",")}]`);
|
|
184
326
|
}
|
|
327
|
+
if (entity.type === "req" && entity.semantic_clauses) {
|
|
328
|
+
props.push(`semantic_clauses=[${entity.semantic_clauses.map(toPrologString).join(",")}]`);
|
|
329
|
+
}
|
|
330
|
+
if (entity.type === "req" && entity.semantic_inventory_version) {
|
|
331
|
+
props.push(`semantic_inventory_version=${toPrologString(entity.semantic_inventory_version)}`);
|
|
332
|
+
}
|
|
333
|
+
if (entity.type === "req" && entity.semantic_source_field) {
|
|
334
|
+
props.push(`semantic_source_field=${toPrologString(entity.semantic_source_field)}`);
|
|
335
|
+
}
|
|
336
|
+
if (entity.type === "req" && entity.semantic_source_hash) {
|
|
337
|
+
props.push(`semantic_source_hash=${toPrologString(entity.semantic_source_hash)}`);
|
|
338
|
+
}
|
|
185
339
|
if (entity.type === "req" && entity.semantic_inventory) {
|
|
186
340
|
props.push(`semantic_inventory=${toPrologString(JSON.stringify(entity.semantic_inventory))}`);
|
|
187
341
|
}
|
|
188
342
|
if (sourceFile)
|
|
189
343
|
props.push(`sourceFile=${toPrologString(sourceFile)}`);
|
|
344
|
+
if (entity.type === "symbol") {
|
|
345
|
+
if (entity.symbol_role)
|
|
346
|
+
props.push(`symbol_role=${toPrologAtom(entity.symbol_role)}`);
|
|
347
|
+
if (entity.granularity_reason)
|
|
348
|
+
props.push(`granularity_reason=${toPrologAtom(entity.granularity_reason)}`);
|
|
349
|
+
for (const key of [
|
|
350
|
+
"sourceLine",
|
|
351
|
+
"sourceColumn",
|
|
352
|
+
"sourceEndLine",
|
|
353
|
+
"sourceEndColumn",
|
|
354
|
+
]) {
|
|
355
|
+
const value = entity[key];
|
|
356
|
+
if (typeof value === "number")
|
|
357
|
+
props.push(`${key}=${value}`);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
190
360
|
// Add typed fact fields for fact entities
|
|
191
361
|
if (entity.type === "fact") {
|
|
192
362
|
const factFields = serializeTypedFactFields(entity);
|
|
@@ -199,21 +369,62 @@ prolog, results, entityIds) {
|
|
|
199
369
|
if (entity.verification_perspective !== undefined) {
|
|
200
370
|
props.push(`verification_perspective=${toPrologAtom(entity.verification_perspective)}`);
|
|
201
371
|
}
|
|
372
|
+
if (entity.verification_receipts !== undefined) {
|
|
373
|
+
props.push(`verification_receipts=${toPrologString(JSON.stringify(entity.verification_receipts))}`);
|
|
374
|
+
}
|
|
202
375
|
}
|
|
203
376
|
const propsList = `[${props.join(", ")}]`;
|
|
204
377
|
const goal = `kb_assert_entity(${entity.type}, ${propsList})`;
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
kbModified = true;
|
|
378
|
+
pendingEntityGoals.push({
|
|
379
|
+
entity,
|
|
380
|
+
sourceFile: sourceFile ?? entity.source,
|
|
381
|
+
goal,
|
|
382
|
+
});
|
|
211
383
|
}
|
|
212
384
|
catch (error) {
|
|
213
385
|
const message = error instanceof Error ? error.message : String(error);
|
|
214
386
|
throw new Error(`Failed to upsert entity ${entity.id}: ${message}${semanticEntityContext(entity, sourceFile ?? entity.source)}`);
|
|
215
387
|
}
|
|
216
388
|
}
|
|
389
|
+
// Persist a changed source as a bounded set of RDF edits. This retains the
|
|
390
|
+
// per-entity fallback diagnostics while avoiding one Prolog round-trip and
|
|
391
|
+
// journal flush for every symbol/document in the common case.
|
|
392
|
+
const batchRunner = prolog.queryBatch?.bind(prolog);
|
|
393
|
+
const batchSize = 250;
|
|
394
|
+
for (let offset = 0; offset < pendingEntityGoals.length; offset += batchSize) {
|
|
395
|
+
const chunk = pendingEntityGoals.slice(offset, offset + batchSize);
|
|
396
|
+
const result = batchRunner
|
|
397
|
+
? await batchRunner(chunk.map(({ goal }) => goal))
|
|
398
|
+
: { success: false, error: "batch unsupported" };
|
|
399
|
+
if (result.success) {
|
|
400
|
+
entityCount += chunk.length;
|
|
401
|
+
kbModified = true;
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
// A malformed entity should retain the precise existing error. The batch
|
|
405
|
+
// transaction has rolled back, so retrying sequentially is safe.
|
|
406
|
+
for (const item of chunk) {
|
|
407
|
+
try {
|
|
408
|
+
const single = await prolog.query(item.goal);
|
|
409
|
+
if (!single.success) {
|
|
410
|
+
const detail = single.error ||
|
|
411
|
+
(batchRunner ? result.error : undefined) ||
|
|
412
|
+
`kb_assert_entity failed for ${item.entity.id}`;
|
|
413
|
+
throw new Error(`Failed to upsert entity ${item.entity.id}: ${detail}${semanticEntityContext(item.entity, item.sourceFile)}`);
|
|
414
|
+
}
|
|
415
|
+
entityCount++;
|
|
416
|
+
kbModified = true;
|
|
417
|
+
}
|
|
418
|
+
catch (error) {
|
|
419
|
+
if (error instanceof Error &&
|
|
420
|
+
error.message.startsWith("Failed to upsert entity ")) {
|
|
421
|
+
throw error;
|
|
422
|
+
}
|
|
423
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
424
|
+
throw new Error(`Failed to upsert entity ${item.entity.id}: ${message}${semanticEntityContext(item.entity, item.sourceFile)}`);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
217
428
|
return { entityCount, kbModified };
|
|
218
429
|
}
|
|
219
430
|
function semanticEntityContext(entity, sourceFile) {
|
|
@@ -249,25 +460,14 @@ export async function persistRelationships(prolog, results, shardRelationships)
|
|
|
249
460
|
}
|
|
250
461
|
// Collect all relationships from results and shards
|
|
251
462
|
const failedRelationships = [];
|
|
463
|
+
const pendingRelationships = [];
|
|
252
464
|
for (const { relationships } of results) {
|
|
253
465
|
for (const rel of relationships) {
|
|
254
466
|
try {
|
|
255
467
|
const fromId = idLookup.get(rel.from) || rel.from;
|
|
256
468
|
const toId = idLookup.get(rel.to) || rel.to;
|
|
257
469
|
const goal = `kb_assert_relationship(${toPrologAtom(rel.type)}, ${toPrologAtom(fromId)}, ${toPrologAtom(toId)}, [])`;
|
|
258
|
-
|
|
259
|
-
if (result.success) {
|
|
260
|
-
relCount++;
|
|
261
|
-
kbModified = true;
|
|
262
|
-
}
|
|
263
|
-
else {
|
|
264
|
-
failedRelationships.push({
|
|
265
|
-
rel,
|
|
266
|
-
fromId,
|
|
267
|
-
toId,
|
|
268
|
-
error: result.error || "Unknown error",
|
|
269
|
-
});
|
|
270
|
-
}
|
|
470
|
+
pendingRelationships.push({ rel, fromId, toId, goal });
|
|
271
471
|
}
|
|
272
472
|
catch (error) {
|
|
273
473
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -281,19 +481,12 @@ export async function persistRelationships(prolog, results, shardRelationships)
|
|
|
281
481
|
for (const rel of shardRelationships) {
|
|
282
482
|
try {
|
|
283
483
|
const goal = `kb_assert_relationship(${toPrologAtom(rel.type)}, ${toPrologAtom(rel.from)}, ${toPrologAtom(rel.to)}, [])`;
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
failedRelationships.push({
|
|
291
|
-
rel,
|
|
292
|
-
fromId: rel.from,
|
|
293
|
-
toId: rel.to,
|
|
294
|
-
error: result.error || "Unknown error",
|
|
295
|
-
});
|
|
296
|
-
}
|
|
484
|
+
pendingRelationships.push({
|
|
485
|
+
rel,
|
|
486
|
+
fromId: rel.from,
|
|
487
|
+
toId: rel.to,
|
|
488
|
+
goal,
|
|
489
|
+
});
|
|
297
490
|
}
|
|
298
491
|
catch (error) {
|
|
299
492
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -305,6 +498,46 @@ export async function persistRelationships(prolog, results, shardRelationships)
|
|
|
305
498
|
});
|
|
306
499
|
}
|
|
307
500
|
}
|
|
501
|
+
const relationshipBatchRunner = prolog.queryBatch?.bind(prolog);
|
|
502
|
+
const relationshipBatchSize = 250;
|
|
503
|
+
for (let offset = 0; offset < pendingRelationships.length; offset += relationshipBatchSize) {
|
|
504
|
+
const chunk = pendingRelationships.slice(offset, offset + relationshipBatchSize);
|
|
505
|
+
const batch = relationshipBatchRunner
|
|
506
|
+
? await relationshipBatchRunner(chunk.map(({ goal }) => goal))
|
|
507
|
+
: { success: false, error: "batch unsupported" };
|
|
508
|
+
if (batch.success) {
|
|
509
|
+
relCount += chunk.length;
|
|
510
|
+
kbModified = true;
|
|
511
|
+
continue;
|
|
512
|
+
}
|
|
513
|
+
for (const item of chunk) {
|
|
514
|
+
try {
|
|
515
|
+
const single = await prolog.query(item.goal);
|
|
516
|
+
if (single.success) {
|
|
517
|
+
relCount++;
|
|
518
|
+
kbModified = true;
|
|
519
|
+
}
|
|
520
|
+
else {
|
|
521
|
+
failedRelationships.push({
|
|
522
|
+
rel: item.rel,
|
|
523
|
+
fromId: item.fromId,
|
|
524
|
+
toId: item.toId,
|
|
525
|
+
error: single.error ||
|
|
526
|
+
(relationshipBatchRunner ? batch.error : undefined) ||
|
|
527
|
+
"Unknown error",
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
catch (error) {
|
|
532
|
+
failedRelationships.push({
|
|
533
|
+
rel: item.rel,
|
|
534
|
+
fromId: item.fromId,
|
|
535
|
+
toId: item.toId,
|
|
536
|
+
error: error instanceof Error ? error.message : String(error),
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
308
541
|
// Retry failed relationships
|
|
309
542
|
const retryCount = 3;
|
|
310
543
|
let resetAttempted = false;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, renameSync, rmSync } from "node:fs";
|
|
1
|
+
import { existsSync, mkdirSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { copyFileSync } from "node:fs";
|
|
3
3
|
import fg from "fast-glob";
|
|
4
4
|
import { copyCleanSnapshot } from "../../utils/branch-resolver.js";
|
|
@@ -13,11 +13,20 @@ interface StagingDeps {
|
|
|
13
13
|
moduleDir: string;
|
|
14
14
|
renameSync: typeof renameSync;
|
|
15
15
|
rmSync: typeof rmSync;
|
|
16
|
+
writeFileSync: typeof writeFileSync;
|
|
16
17
|
}
|
|
17
18
|
export declare function createUniqueStagingPath(currentBranch: string, rootDir: string, pid?: number, now?: number): string;
|
|
18
19
|
export declare function cleanupAbandonedStagingDirectories(stagingPath: string, deps?: Partial<StagingDeps>): Promise<void>;
|
|
19
20
|
export declare function prepareStagingEnvironment(stagingPath: string, livePath: string, rebuild: boolean, deps?: Partial<StagingDeps>): Promise<void>;
|
|
20
21
|
export declare function atomicPublish(stagingPath: string, livePath: string, deps?: Partial<StagingDeps>): void;
|
|
22
|
+
/**
|
|
23
|
+
* Publish a rebuilt journal generation without replacing the branch directory.
|
|
24
|
+
* The legacy backup, sync metadata, and sentinel stay in place; only the
|
|
25
|
+
* journal database and CURRENT pointer move. A short-lived rollback pair is
|
|
26
|
+
* retained until both moves succeed so an interrupted publication can be
|
|
27
|
+
* repaired on the next engine start.
|
|
28
|
+
*/
|
|
29
|
+
export declare function atomicPublishGeneration(stagingPath: string, livePath: string, deps?: Partial<StagingDeps>): void;
|
|
21
30
|
export declare function cleanupStaging(stagingPath: string, deps?: Partial<StagingDeps>): void;
|
|
22
31
|
export {};
|
|
23
32
|
//# sourceMappingURL=staging.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"staging.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/staging.ts"],"names":[],"mappings":"AAkBA,OAAO,
|
|
1
|
+
{"version":3,"file":"staging.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/staging.ts"],"names":[],"mappings":"AAkBA,OAAO,EACL,UAAU,EACV,SAAS,EACT,UAAU,EACV,MAAM,EACN,aAAa,EACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,MAAM,WAAW,CAAC;AAC3B,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAEnE,UAAU,WAAW;IACnB,iBAAiB,EAAE,OAAO,iBAAiB,CAAC;IAC5C,YAAY,EAAE,OAAO,YAAY,CAAC;IAClC,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,EAAE,EAAE,OAAO,EAAE,CAAC;IACd,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACzC,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,MAAM,EAAE,OAAO,MAAM,CAAC;IACtB,aAAa,EAAE,OAAO,aAAa,CAAC;CACrC;AA+BD,wBAAgB,uBAAuB,CACrC,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,GAAG,SAAc,EACjB,GAAG,SAAa,GACf,MAAM,CAOR;AAGD,wBAAsB,kCAAkC,CACtD,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAC1B,OAAO,CAAC,IAAI,CAAC,CAqDf;AAED,wBAAsB,yBAAyB,CAE7C,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,OAAO,EAChB,IAAI,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAC1B,OAAO,CAAC,IAAI,CAAC,CA6Cf;AA0CD,wBAAgB,aAAa,CAE3B,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAC1B,IAAI,CAeN;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAC1B,IAAI,CA6DN;AAED,wBAAgB,cAAc,CAE5B,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAC1B,IAAI,CAKN"}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
You should have received a copy of the GNU Affero General Public License
|
|
16
16
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
*/
|
|
18
|
-
import { existsSync, mkdirSync, renameSync, rmSync } from "node:fs";
|
|
18
|
+
import { existsSync, mkdirSync, renameSync, rmSync, writeFileSync, } from "node:fs";
|
|
19
19
|
import { copyFileSync } from "node:fs";
|
|
20
20
|
import * as path from "node:path";
|
|
21
21
|
import fg from "fast-glob";
|
|
@@ -42,6 +42,7 @@ function resolveDeps(overrides) {
|
|
|
42
42
|
moduleDir: import.meta.dirname,
|
|
43
43
|
renameSync,
|
|
44
44
|
rmSync,
|
|
45
|
+
writeFileSync,
|
|
45
46
|
...overrides,
|
|
46
47
|
};
|
|
47
48
|
}
|
|
@@ -104,6 +105,22 @@ stagingPath, livePath, rebuild, deps) {
|
|
|
104
105
|
// Start fresh with schema only
|
|
105
106
|
await copySchemaToStaging(stagingPath, resolved);
|
|
106
107
|
}
|
|
108
|
+
// Every new staging generation uses the journaled store format. This also
|
|
109
|
+
// makes `--rebuild` publish a native RDF database instead of recreating the
|
|
110
|
+
// legacy full-snapshot path.
|
|
111
|
+
const markerPath = path.join(stagingPath, "storage.json");
|
|
112
|
+
const canWriteMetadata = deps === undefined || deps.writeFileSync !== undefined;
|
|
113
|
+
if (canWriteMetadata &&
|
|
114
|
+
resolved.existsSync(stagingPath) &&
|
|
115
|
+
!resolved.existsSync(markerPath)) {
|
|
116
|
+
resolved.mkdirSync(path.join(stagingPath, "rdf"), { recursive: true });
|
|
117
|
+
resolved.writeFileSync(markerPath, '{"format":"kibi.rdf-journal.v1","schemaVersion":1}\n', { mode: 0o600 });
|
|
118
|
+
const generation = rebuild
|
|
119
|
+
? `generation-${process.pid}-${Date.now()}`
|
|
120
|
+
: "generation-1";
|
|
121
|
+
resolved.writeFileSync(path.join(stagingPath, "CURRENT"), `${generation}:0\n`, { mode: 0o600 });
|
|
122
|
+
resolved.writeFileSync(path.join(stagingPath, "kb.rdf"), "KIBI_STORAGE_FORMAT=kibi.rdf-journal.v1\n", { mode: 0o600 });
|
|
123
|
+
}
|
|
107
124
|
}
|
|
108
125
|
async function copySchemaToStaging(stagingPath, deps) {
|
|
109
126
|
const possibleSchemaPaths = [
|
|
@@ -154,6 +171,72 @@ stagingPath, livePath, deps) {
|
|
|
154
171
|
resolved.renameSync(stagingPath, livePath);
|
|
155
172
|
}
|
|
156
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Publish a rebuilt journal generation without replacing the branch directory.
|
|
176
|
+
* The legacy backup, sync metadata, and sentinel stay in place; only the
|
|
177
|
+
* journal database and CURRENT pointer move. A short-lived rollback pair is
|
|
178
|
+
* retained until both moves succeed so an interrupted publication can be
|
|
179
|
+
* repaired on the next engine start.
|
|
180
|
+
*/
|
|
181
|
+
export function atomicPublishGeneration(stagingPath, livePath, deps) {
|
|
182
|
+
const resolved = resolveDeps(deps);
|
|
183
|
+
const liveParent = path.dirname(livePath);
|
|
184
|
+
if (!resolved.existsSync(liveParent)) {
|
|
185
|
+
resolved.mkdirSync(liveParent, { recursive: true });
|
|
186
|
+
}
|
|
187
|
+
if (!resolved.existsSync(livePath)) {
|
|
188
|
+
resolved.renameSync(stagingPath, livePath);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const generationStamp = `${Date.now()}.${process.pid}`;
|
|
192
|
+
const liveRdf = path.join(livePath, "rdf");
|
|
193
|
+
const stagedRdf = path.join(stagingPath, "rdf");
|
|
194
|
+
const oldRdf = `${liveRdf}.old.${generationStamp}`;
|
|
195
|
+
const liveCurrent = path.join(livePath, "CURRENT");
|
|
196
|
+
const stagedCurrent = path.join(stagingPath, "CURRENT");
|
|
197
|
+
const oldCurrent = `${liveCurrent}.old.${generationStamp}`;
|
|
198
|
+
if (!resolved.existsSync(stagedRdf) || !resolved.existsSync(stagedCurrent)) {
|
|
199
|
+
throw new Error("Rebuilt journal generation is missing rdf or CURRENT");
|
|
200
|
+
}
|
|
201
|
+
let oldRdfMoved = false;
|
|
202
|
+
let oldCurrentMoved = false;
|
|
203
|
+
try {
|
|
204
|
+
if (resolved.existsSync(liveRdf)) {
|
|
205
|
+
resolved.renameSync(liveRdf, oldRdf);
|
|
206
|
+
oldRdfMoved = true;
|
|
207
|
+
}
|
|
208
|
+
resolved.renameSync(stagedRdf, liveRdf);
|
|
209
|
+
if (resolved.existsSync(liveCurrent)) {
|
|
210
|
+
resolved.renameSync(liveCurrent, oldCurrent);
|
|
211
|
+
oldCurrentMoved = true;
|
|
212
|
+
}
|
|
213
|
+
resolved.renameSync(stagedCurrent, liveCurrent);
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
// Restore the old pointer/database whenever publication fails. If the
|
|
217
|
+
// process itself crashes, ensureJournaledBranchStoreAsync performs the
|
|
218
|
+
// same recovery from the `.old.<stamp>` siblings.
|
|
219
|
+
try {
|
|
220
|
+
if (resolved.existsSync(liveCurrent))
|
|
221
|
+
resolved.rmSync(liveCurrent, { force: true });
|
|
222
|
+
if (oldCurrentMoved && resolved.existsSync(oldCurrent))
|
|
223
|
+
resolved.renameSync(oldCurrent, liveCurrent);
|
|
224
|
+
if (resolved.existsSync(liveRdf))
|
|
225
|
+
resolved.rmSync(liveRdf, { recursive: true, force: true });
|
|
226
|
+
if (oldRdfMoved && resolved.existsSync(oldRdf))
|
|
227
|
+
resolved.renameSync(oldRdf, liveRdf);
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
// Preserve the original publication error; startup recovery will report
|
|
231
|
+
// the remaining sibling paths if the rollback itself was interrupted.
|
|
232
|
+
}
|
|
233
|
+
throw error;
|
|
234
|
+
}
|
|
235
|
+
if (resolved.existsSync(oldRdf))
|
|
236
|
+
resolved.rmSync(oldRdf, { recursive: true, force: true });
|
|
237
|
+
if (resolved.existsSync(oldCurrent))
|
|
238
|
+
resolved.rmSync(oldCurrent, { force: true });
|
|
239
|
+
}
|
|
157
240
|
export function cleanupStaging(
|
|
158
241
|
// implements REQ-003
|
|
159
242
|
stagingPath, deps) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAc,WAAW,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAc,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAyBjE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAsC7C,qBAAa,SAAU,SAAQ,KAAK;gBACtB,OAAO,EAAE,MAAM;CAI5B;AAoDD,MAAM,WAAW,UAAW,SAAQ,WAAW;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,yBAAyB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,UAAU,kBAAkB;IAC1B,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,yBAAyB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3E,UAAU,CAAC,EAAE,CACX,OAAO,EAAE,yBAAyB,GAAG;QAAE,UAAU,EAAE,OAAO,CAAA;KAAE,KACzD,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,aAAa,CAAC;CAChE;AAsDD,wBAAsB,WAAW,CAC/B,OAAO,GAAE;IACP,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wBAAwB,CAAC,EAAE,OAAO,CAAC;CAC/B,EACN,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,UAAU,CAAC,CAy6BrB;AAED,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC"}
|