kibi-cli 0.18.1 → 1.0.1
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 +2 -34
- 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 +91 -0
- package/dist/cli-operation-metadata.d.ts +94 -0
- package/dist/cli-operation-metadata.d.ts.map +1 -0
- package/dist/cli-operation-metadata.js +121 -0
- package/dist/cli-protocol.d.ts +1 -1
- package/dist/cli-protocol.d.ts.map +1 -1
- package/dist/cli-protocol.js +42 -11
- package/dist/cli-register-foundation.d.ts.map +1 -1
- package/dist/cli-register-foundation.js +28 -19
- 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 +60 -13
- package/dist/cli-register-reporting.d.ts.map +1 -1
- package/dist/cli-register-reporting.js +23 -14
- package/dist/cli-register-skills.d.ts.map +1 -1
- package/dist/cli-register-skills.js +8 -6
- package/dist/cli-register-verification.d.ts +3 -0
- package/dist/cli-register-verification.d.ts.map +1 -0
- package/dist/cli-register-verification.js +16 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -1
- package/dist/commands/aggregated-checks.d.ts +1 -2
- package/dist/commands/aggregated-checks.d.ts.map +1 -1
- package/dist/commands/aggregated-checks.js +14 -9
- package/dist/commands/branch.d.ts +36 -0
- package/dist/commands/branch.d.ts.map +1 -1
- package/dist/commands/branch.js +371 -40
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +48 -77
- package/dist/commands/coverage.js +1 -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 +38 -25
- package/dist/commands/doctor.d.ts +4 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +259 -24
- package/dist/commands/engine.d.ts +8 -0
- package/dist/commands/engine.d.ts.map +1 -0
- package/dist/commands/engine.js +103 -0
- package/dist/commands/gaps.js +1 -1
- package/dist/commands/gc.d.ts +5 -2
- package/dist/commands/gc.d.ts.map +1 -1
- package/dist/commands/gc.js +140 -71
- package/dist/commands/github-init.d.ts +56 -0
- package/dist/commands/github-init.d.ts.map +1 -0
- package/dist/commands/github-init.js +310 -0
- package/dist/commands/graph.js +1 -1
- package/dist/commands/init-helpers.d.ts +1 -1
- package/dist/commands/init-helpers.d.ts.map +1 -1
- package/dist/commands/init-helpers.js +73 -25
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +79 -24
- package/dist/commands/legacy-storage-migration.d.ts +54 -0
- package/dist/commands/legacy-storage-migration.d.ts.map +1 -0
- package/dist/commands/legacy-storage-migration.js +277 -0
- package/dist/commands/migrate.d.ts +7 -0
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +244 -91
- package/dist/commands/query.d.ts.map +1 -1
- package/dist/commands/query.js +3 -1
- package/dist/commands/report.d.ts +24 -0
- package/dist/commands/report.d.ts.map +1 -0
- package/dist/commands/report.js +191 -0
- 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 +26 -3
- package/dist/commands/sync/cache.d.ts.map +1 -1
- package/dist/commands/sync/cache.js +141 -5
- package/dist/commands/sync/discovery.d.ts +23 -2
- package/dist/commands/sync/discovery.d.ts.map +1 -1
- package/dist/commands/sync/discovery.js +196 -15
- package/dist/commands/sync/extraction.d.ts +8 -1
- package/dist/commands/sync/extraction.d.ts.map +1 -1
- package/dist/commands/sync/extraction.js +38 -4
- package/dist/commands/sync/manifest.d.ts +8 -5
- package/dist/commands/sync/manifest.d.ts.map +1 -1
- package/dist/commands/sync/manifest.js +142 -39
- 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 +223 -44
- 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 +6 -0
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +710 -48
- package/dist/commands/verify.d.ts +10 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +126 -0
- package/dist/diagnostics.d.ts +1 -1
- package/dist/diagnostics.d.ts.map +1 -1
- 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 +156 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +1625 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +5 -6
- package/dist/extractors/manifest.d.ts +8 -1
- package/dist/extractors/manifest.d.ts.map +1 -1
- package/dist/extractors/manifest.js +51 -9
- package/dist/extractors/markdown.d.ts +2 -1
- package/dist/extractors/markdown.d.ts.map +1 -1
- package/dist/extractors/markdown.js +21 -3
- package/dist/extractors/playwright-cases.d.ts +24 -0
- package/dist/extractors/playwright-cases.d.ts.map +1 -0
- package/dist/extractors/playwright-cases.js +126 -0
- package/dist/extractors/relationships.d.ts +2 -0
- package/dist/extractors/relationships.d.ts.map +1 -1
- package/dist/extractors/relationships.js +16 -17
- package/dist/extractors/symbol-coordinates.d.ts +81 -3
- package/dist/extractors/symbol-coordinates.d.ts.map +1 -1
- package/dist/extractors/symbol-coordinates.js +389 -51
- package/dist/extractors/symbols-coordinator.js +11 -1
- package/dist/intent-search.d.ts +60 -0
- package/dist/intent-search.d.ts.map +1 -0
- package/dist/intent-search.js +433 -0
- package/dist/operations/bootstrap/activation.d.ts.map +1 -0
- package/dist/operations/{autopilot → bootstrap}/activation.js +48 -31
- package/dist/operations/{autopilot → bootstrap}/candidate-helpers.d.ts.map +1 -1
- package/dist/operations/bootstrap/candidates.d.ts +4 -0
- package/dist/operations/{autopilot → bootstrap}/candidates.d.ts.map +1 -1
- package/dist/operations/{autopilot → bootstrap}/candidates.js +22 -8
- package/dist/operations/{autopilot → bootstrap}/discovery-evidence.d.ts +2 -2
- package/dist/operations/{autopilot → bootstrap}/discovery-evidence.d.ts.map +1 -1
- package/dist/operations/{autopilot → bootstrap}/discovery-evidence.js +46 -6
- package/dist/operations/{autopilot → bootstrap}/discovery.d.ts +1 -1
- package/dist/operations/bootstrap/discovery.d.ts.map +1 -0
- package/dist/operations/{autopilot → bootstrap}/discovery.js +21 -14
- package/dist/operations/bootstrap/generate.d.ts +8 -0
- package/dist/operations/bootstrap/generate.d.ts.map +1 -0
- package/dist/operations/bootstrap/generate.js +204 -0
- package/dist/operations/{autopilot → bootstrap}/guidance-actions.d.ts +2 -2
- package/dist/operations/{autopilot → bootstrap}/guidance-actions.d.ts.map +1 -1
- package/dist/operations/{autopilot → bootstrap}/guidance-actions.js +4 -4
- package/dist/operations/{autopilot → bootstrap}/guidance.d.ts +2 -2
- package/dist/operations/{autopilot → bootstrap}/guidance.d.ts.map +1 -1
- package/dist/operations/{autopilot → bootstrap}/guidance.js +2 -0
- package/dist/operations/{autopilot → bootstrap}/markdown-candidates.d.ts +2 -2
- package/dist/operations/{autopilot → bootstrap}/markdown-candidates.d.ts.map +1 -1
- package/dist/operations/{autopilot → bootstrap}/markdown-candidates.js +4 -3
- package/dist/operations/bootstrap/presentation.d.ts +15 -0
- package/dist/operations/bootstrap/presentation.d.ts.map +1 -0
- package/dist/operations/bootstrap/presentation.js +177 -0
- package/dist/operations/{autopilot → bootstrap}/requirement-claims.d.ts.map +1 -1
- package/dist/operations/{autopilot → bootstrap}/types.d.ts +63 -21
- package/dist/operations/bootstrap/types.d.ts.map +1 -0
- package/dist/operations/bootstrap/types.js +25 -0
- package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
- package/dist/operations/modeling/model-requirement.js +4 -17
- package/dist/operations/modeling/predicate-applicability.d.ts +16 -0
- package/dist/operations/modeling/predicate-applicability.d.ts.map +1 -0
- package/dist/operations/modeling/predicate-applicability.js +276 -0
- package/dist/operations/modeling/predicate-applyplan.d.ts +13 -2
- package/dist/operations/modeling/predicate-applyplan.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-applyplan.js +100 -3
- package/dist/operations/modeling/predicate-bindings.d.ts +6 -0
- package/dist/operations/modeling/predicate-bindings.d.ts.map +1 -0
- package/dist/operations/modeling/predicate-bindings.js +122 -0
- package/dist/operations/modeling/predicate-catalog-4.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-catalog-4.js +155 -0
- package/dist/operations/modeling/predicate-inference-1.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-inference-1.js +8 -0
- package/dist/operations/modeling/predicate-inference-launcher.d.ts +10 -0
- package/dist/operations/modeling/predicate-inference-launcher.d.ts.map +1 -0
- package/dist/operations/modeling/predicate-inference-launcher.js +13 -0
- package/dist/operations/modeling/predicate-inference.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-inference.js +4 -0
- package/dist/operations/modeling/predicate-loader.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-loader.js +7 -0
- package/dist/operations/modeling/predicate-ranker.d.ts +8 -1
- package/dist/operations/modeling/predicate-ranker.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-ranker.js +156 -24
- package/dist/operations/modeling/predicate-score-3.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-score-3.js +6 -0
- package/dist/operations/modeling/predicate-types.d.ts +34 -0
- package/dist/operations/modeling/predicate-types.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-usage-hints-3.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-usage-hints-3.js +40 -0
- package/dist/operations/modeling/predicate-utils.d.ts.map +1 -1
- package/dist/operations/modeling/predicate-utils.js +2 -0
- package/dist/operations/modeling/suggest-predicates.d.ts +1 -1
- package/dist/operations/modeling/suggest-predicates.d.ts.map +1 -1
- package/dist/operations/modeling/suggest-predicates.js +170 -32
- package/dist/operations/mutation/delete.d.ts.map +1 -1
- package/dist/operations/mutation/delete.js +415 -19
- package/dist/operations/mutation/entity-projection.d.ts +11 -0
- package/dist/operations/mutation/entity-projection.d.ts.map +1 -0
- package/dist/operations/mutation/entity-projection.js +14 -0
- package/dist/operations/mutation/relationships.d.ts +10 -0
- package/dist/operations/mutation/relationships.d.ts.map +1 -1
- package/dist/operations/mutation/relationships.js +71 -1
- package/dist/operations/mutation/serialization.d.ts.map +1 -1
- package/dist/operations/mutation/serialization.js +1 -0
- package/dist/operations/mutation/source-authoring.d.ts +61 -0
- package/dist/operations/mutation/source-authoring.d.ts.map +1 -0
- package/dist/operations/mutation/source-authoring.js +543 -0
- package/dist/operations/mutation/symbol-compiler-lock.d.ts +51 -0
- package/dist/operations/mutation/symbol-compiler-lock.d.ts.map +1 -0
- package/dist/operations/mutation/symbol-compiler-lock.js +274 -0
- package/dist/operations/mutation/symbol-granularity.d.ts.map +1 -1
- package/dist/operations/mutation/symbol-granularity.js +34 -3
- package/dist/operations/mutation/symbol-refresh.d.ts +18 -1
- package/dist/operations/mutation/symbol-refresh.d.ts.map +1 -1
- package/dist/operations/mutation/symbol-refresh.js +225 -63
- package/dist/operations/mutation/types.d.ts +57 -1
- package/dist/operations/mutation/types.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.js +363 -24
- package/dist/operations/mutation/validation.d.ts.map +1 -1
- package/dist/operations/mutation/validation.js +1 -0
- package/dist/operations/planning/apply-plan.d.ts +117 -0
- package/dist/operations/planning/apply-plan.d.ts.map +1 -0
- package/dist/operations/planning/apply-plan.js +1437 -0
- package/dist/operations/planning/compile-intent.d.ts +106 -0
- package/dist/operations/planning/compile-intent.d.ts.map +1 -0
- package/dist/operations/planning/compile-intent.js +562 -0
- package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/analyze-prose.js +6 -2
- package/dist/operations/semantic-advisor/clauses.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/clauses.js +15 -2
- package/dist/operations/semantic-advisor/ingestion-boundary.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/ingestion-boundary.js +7 -3
- package/dist/operations/semantic-advisor/predicate-rules-launcher.d.ts +51 -0
- package/dist/operations/semantic-advisor/predicate-rules-launcher.d.ts.map +1 -0
- package/dist/operations/semantic-advisor/predicate-rules-launcher.js +96 -0
- package/dist/operations/semantic-advisor/types.d.ts +13 -5
- package/dist/operations/semantic-advisor/types.d.ts.map +1 -1
- package/dist/operations/verification/ingest-verification.d.ts +29 -0
- package/dist/operations/verification/ingest-verification.d.ts.map +1 -0
- package/dist/operations/verification/ingest-verification.js +192 -0
- package/dist/prolog/codec.d.ts.map +1 -1
- package/dist/prolog/codec.js +2 -1
- package/dist/prolog.d.ts +8 -0
- package/dist/prolog.d.ts.map +1 -1
- package/dist/prolog.js +66 -16
- package/dist/public/branch-resolver.d.ts +1 -0
- package/dist/public/branch-resolver.d.ts.map +1 -1
- package/dist/public/branch-resolver.js +1 -0
- package/dist/public/check-types.d.ts +2 -2
- package/dist/public/check-types.d.ts.map +1 -1
- package/dist/public/check-types.js +16 -16
- package/dist/public/diagnostic-usage.d.ts.map +1 -1
- package/dist/public/diagnostic-usage.js +69 -1
- package/dist/public/distribution-parity.d.ts +1 -1
- package/dist/public/distribution-parity.d.ts.map +1 -1
- package/dist/public/distribution-parity.js +1 -0
- package/dist/public/ignore-policy.d.ts.map +1 -1
- package/dist/public/ignore-policy.js +16 -4
- package/dist/public/impact/coverage-depth-quality.d.ts +6 -1
- package/dist/public/impact/coverage-depth-quality.d.ts.map +1 -1
- package/dist/public/impact/coverage-depth-quality.js +21 -3
- package/dist/public/impact/full-kb-quality.d.ts +4 -2
- package/dist/public/impact/full-kb-quality.d.ts.map +1 -1
- package/dist/public/impact/full-kb-quality.js +61 -1
- package/dist/public/impact/manifest.d.ts.map +1 -1
- package/dist/public/impact/manifest.js +2 -5
- package/dist/public/operational-artifacts.d.ts.map +1 -1
- package/dist/public/operational-artifacts.js +7 -1
- package/dist/public/operations/catalog.d.ts +682 -67
- package/dist/public/operations/catalog.d.ts.map +1 -1
- package/dist/public/operations/catalog.js +126 -4
- package/dist/public/operations/check-executor.d.ts +2 -2
- package/dist/public/operations/check-executor.d.ts.map +1 -1
- package/dist/public/operations/check-executor.js +72 -13
- package/dist/public/operations/check-format-shared.d.ts +3 -0
- package/dist/public/operations/check-format-shared.d.ts.map +1 -1
- package/dist/public/operations/check-format-shared.js +3 -0
- package/dist/public/operations/check-helpers.d.ts +27 -2
- package/dist/public/operations/check-helpers.d.ts.map +1 -1
- package/dist/public/operations/check-helpers.js +62 -26
- package/dist/public/operations/contracts.d.ts +11 -0
- package/dist/public/operations/contracts.d.ts.map +1 -0
- package/dist/public/operations/contracts.js +325 -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 +37 -1
- package/dist/public/operations/discovery-executors.d.ts.map +1 -1
- package/dist/public/operations/discovery-executors.js +246 -9
- package/dist/public/operations/index.d.ts +9 -4
- package/dist/public/operations/index.d.ts.map +1 -1
- package/dist/public/operations/index.js +8 -3
- package/dist/public/operations/migration-plan.d.ts +101 -0
- package/dist/public/operations/migration-plan.d.ts.map +1 -0
- package/dist/public/operations/migration-plan.js +537 -0
- package/dist/public/operations/node-ports.d.ts.map +1 -1
- package/dist/public/operations/node-ports.js +68 -8
- package/dist/public/operations/prolog-json.d.ts +14 -0
- package/dist/public/operations/prolog-json.d.ts.map +1 -1
- package/dist/public/operations/prolog-json.js +55 -6
- package/dist/public/operations/repair-plan.d.ts.map +1 -1
- package/dist/public/operations/repair-plan.js +1 -0
- package/dist/public/operations/result-envelope.d.ts +13 -0
- package/dist/public/operations/result-envelope.d.ts.map +1 -0
- package/dist/public/operations/result-envelope.js +104 -0
- package/dist/public/operations/runtime-types.d.ts +126 -5
- package/dist/public/operations/runtime-types.d.ts.map +1 -1
- package/dist/public/operations/source-relationship-parity.d.ts +13 -0
- package/dist/public/operations/source-relationship-parity.d.ts.map +1 -0
- package/dist/public/operations/source-relationship-parity.js +162 -0
- package/dist/public/operations/specs/{autopilot.d.ts → bootstrap.d.ts} +9 -9
- package/dist/public/operations/specs/bootstrap.d.ts.map +1 -0
- package/dist/public/operations/specs/{autopilot.js → bootstrap.js} +8 -7
- package/dist/public/operations/specs/check.d.ts +4 -4
- package/dist/public/operations/specs/check.d.ts.map +1 -1
- package/dist/public/operations/specs/check.js +4 -3
- package/dist/public/operations/specs/discovery.d.ts +87 -3
- package/dist/public/operations/specs/discovery.d.ts.map +1 -1
- package/dist/public/operations/specs/discovery.js +53 -3
- package/dist/public/operations/specs/modeling.d.ts +3 -3
- package/dist/public/operations/specs/modeling.js +3 -3
- package/dist/public/operations/specs/mutation-schemas.d.ts +190 -47
- package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
- package/dist/public/operations/specs/mutation-schemas.js +3 -1
- package/dist/public/operations/specs/mutation.d.ts +42 -2
- package/dist/public/operations/specs/mutation.d.ts.map +1 -1
- package/dist/public/operations/specs/mutation.js +26 -2
- package/dist/public/operations/specs/planning.d.ts +270 -0
- package/dist/public/operations/specs/planning.d.ts.map +1 -0
- package/dist/public/operations/specs/planning.js +191 -0
- package/dist/public/operations/specs/reporting.d.ts +4 -1
- package/dist/public/operations/specs/reporting.d.ts.map +1 -1
- package/dist/public/operations/specs/reporting.js +46 -1
- package/dist/public/operations/specs/upsert.d.ts +204 -47
- package/dist/public/operations/specs/upsert.d.ts.map +1 -1
- package/dist/public/operations/specs/upsert.js +9 -0
- package/dist/public/operations/specs/verification.d.ts +78 -0
- package/dist/public/operations/specs/verification.d.ts.map +1 -0
- package/dist/public/operations/specs/verification.js +62 -0
- package/dist/public/operations/symbol-repair-plan.d.ts +11 -0
- package/dist/public/operations/symbol-repair-plan.d.ts.map +1 -0
- package/dist/public/operations/symbol-repair-plan.js +123 -0
- package/dist/public/operations/types.d.ts +52 -1
- package/dist/public/operations/types.d.ts.map +1 -1
- package/dist/public/playwright-case-id.d.ts +8 -0
- package/dist/public/playwright-case-id.d.ts.map +1 -0
- package/dist/public/playwright-case-id.js +25 -0
- package/dist/public/schemas/entity.d.ts.map +1 -1
- package/dist/public/schemas/entity.js +4 -2
- package/dist/public/skills/kibi-bootstrap/SKILL.md +58 -0
- package/dist/public/skills/kibi-bootstrap/resources/bootstrap.md +11 -0
- package/dist/public/skills/kibi-bootstrap/resources/branch-lifecycle.md +7 -0
- package/dist/public/skills/kibi-bootstrap/resources/operation-access.md +5 -0
- package/dist/public/skills/kibi-bootstrap/resources/source-authoring.md +8 -0
- package/dist/public/skills/kibi-freshness/SKILL.md +40 -10
- package/dist/public/skills/kibi-freshness/resources/branch-lifecycle.md +7 -0
- package/dist/public/skills/kibi-freshness/resources/operation-access.md +6 -0
- package/dist/public/skills/kibi-freshness/resources/source-authoring.md +7 -0
- package/dist/public/skills/kibi-traceability/SKILL.md +47 -47
- package/dist/public/skills/kibi-traceability/resources/branch-lifecycle.md +7 -0
- package/dist/public/skills/kibi-traceability/resources/operation-access.md +5 -0
- package/dist/public/skills/kibi-traceability/resources/source-authoring.md +6 -0
- package/dist/public/skills/kibi-traceability/resources/traceability.md +8 -0
- package/dist/public/skills/kibi-usage/SKILL.md +115 -239
- package/dist/public/skills/kibi-usage/resources/branch-lifecycle.md +31 -0
- package/dist/public/skills/kibi-usage/resources/kb-improvement.md +38 -0
- package/dist/public/skills/kibi-usage/resources/operation-access.md +36 -38
- package/dist/public/skills/kibi-usage/resources/relationship-directions.md +3 -3
- package/dist/public/skills/kibi-usage/resources/source-authoring.md +31 -0
- package/dist/public/skills/kibi-usage/resources/workflows.md +56 -3
- package/dist/public/symbol-granularity.d.ts +1 -1
- package/dist/public/symbol-granularity.d.ts.map +1 -1
- package/dist/public/symbol-granularity.js +1 -0
- package/dist/public/telemetry-acceptance.d.ts +7 -0
- package/dist/public/telemetry-acceptance.d.ts.map +1 -1
- package/dist/public/telemetry-acceptance.js +8 -1
- package/dist/public/telemetry-remediation.js +1 -1
- package/dist/public/verification-receipt.d.ts +206 -39
- package/dist/public/verification-receipt.d.ts.map +1 -1
- package/dist/public/verification-receipt.js +171 -4
- package/dist/relationships/shards.d.ts +16 -0
- package/dist/relationships/shards.d.ts.map +1 -1
- package/dist/relationships/shards.js +87 -2
- package/dist/report/brand.d.ts +19 -0
- package/dist/report/brand.d.ts.map +1 -0
- package/dist/report/brand.js +112 -0
- package/dist/report/html-report.d.ts +19 -0
- package/dist/report/html-report.d.ts.map +1 -0
- package/dist/report/html-report.js +963 -0
- package/dist/report/relative-time.d.ts +4 -0
- package/dist/report/relative-time.d.ts.map +1 -0
- package/dist/report/relative-time.js +46 -0
- package/dist/report/report-view.d.ts +17 -0
- package/dist/report/report-view.d.ts.map +1 -0
- package/dist/report/report-view.js +33 -0
- package/dist/report/repository.d.ts +35 -0
- package/dist/report/repository.d.ts.map +1 -0
- package/dist/report/repository.js +151 -0
- package/dist/runtime/cli-runtime.d.ts.map +1 -1
- package/dist/runtime/cli-runtime.js +98 -42
- package/dist/schemas/entity.schema.json +1148 -273
- package/dist/traceability/evidence-model.d.ts +2 -2
- package/dist/traceability/evidence-model.d.ts.map +1 -1
- package/dist/traceability/evidence-model.js +2 -2
- package/dist/traceability/git-staged.d.ts.map +1 -1
- package/dist/traceability/git-staged.js +15 -40
- package/dist/traceability/markdown-validate.d.ts.map +1 -1
- package/dist/traceability/markdown-validate.js +12 -7
- package/dist/traceability/staged-impact-contract.d.ts +3 -3
- package/dist/traceability/staged-impact-contract.d.ts.map +1 -1
- package/dist/traceability/staged-impact-contract.js +10 -38
- package/dist/traceability/staged-symbols-manifest.d.ts.map +1 -1
- package/dist/traceability/staged-symbols-manifest.js +8 -3
- package/dist/traceability/temp-kb.d.ts.map +1 -1
- package/dist/traceability/temp-kb.js +3 -0
- package/dist/types/entities.d.ts +3 -0
- package/dist/types/entities.d.ts.map +1 -1
- package/dist/utils/branch-resolver.d.ts +24 -10
- package/dist/utils/branch-resolver.d.ts.map +1 -1
- package/dist/utils/branch-resolver.js +121 -38
- package/dist/utils/branch-store-locator.d.ts +23 -0
- package/dist/utils/branch-store-locator.d.ts.map +1 -0
- package/dist/utils/branch-store-locator.js +90 -0
- package/dist/utils/branch-store.d.ts +15 -0
- package/dist/utils/branch-store.d.ts.map +1 -0
- package/dist/utils/branch-store.js +130 -0
- package/dist/utils/config.d.ts +39 -37
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +107 -119
- package/dist/utils/kb-manifest.d.ts +35 -0
- package/dist/utils/kb-manifest.d.ts.map +1 -0
- package/dist/utils/kb-manifest.js +154 -0
- package/dist/utils/kb-paths.d.ts +54 -0
- package/dist/utils/kb-paths.d.ts.map +1 -0
- package/dist/utils/kb-paths.js +125 -0
- package/dist/utils/manifest-paths.d.ts +4 -4
- package/dist/utils/manifest-paths.d.ts.map +1 -1
- package/dist/utils/manifest-paths.js +8 -56
- package/dist/utils/rule-registry.d.ts +48 -20
- package/dist/utils/rule-registry.d.ts.map +1 -1
- package/dist/utils/rule-registry.js +82 -77
- package/dist/utils/schema-version.d.ts +5 -5
- package/dist/utils/schema-version.d.ts.map +1 -1
- package/dist/utils/schema-version.js +26 -6
- package/dist/utils/strict-modeling.d.ts +0 -4
- package/dist/utils/strict-modeling.d.ts.map +1 -1
- package/dist/utils/strict-modeling.js +7 -8
- package/dist/verification/playwright-reporter.d.ts +21 -0
- package/dist/verification/playwright-reporter.d.ts.map +1 -0
- package/dist/verification/playwright-reporter.js +114 -0
- package/package.json +51 -8
- package/schema/config.json +2 -2
- package/schema/manifest.json +26 -0
- package/src/public/branch-resolver.ts +1 -0
- package/src/public/check-types.ts +22 -19
- package/src/public/diagnostic-usage.ts +79 -1
- package/src/public/distribution-parity.ts +1 -0
- package/src/public/ignore-policy.ts +16 -10
- package/src/public/impact/coverage-depth-quality.ts +36 -0
- package/src/public/impact/full-kb-quality.ts +118 -5
- package/src/public/impact/manifest.ts +2 -4
- package/src/public/operational-artifacts.ts +9 -1
- package/src/public/operations/catalog.ts +146 -9
- package/src/public/operations/check-executor.ts +102 -15
- package/src/public/operations/check-format-shared.ts +6 -0
- package/src/public/operations/check-helpers.ts +74 -35
- package/src/public/operations/contracts.ts +366 -0
- package/src/public/operations/discovery-entities.ts +3 -2
- package/src/public/operations/discovery-executors.ts +343 -15
- package/src/public/operations/index.ts +9 -4
- package/src/public/operations/migration-plan.ts +740 -0
- package/src/public/operations/node-ports.ts +84 -10
- package/src/public/operations/prolog-json.ts +73 -6
- package/src/public/operations/repair-plan.ts +1 -0
- package/src/public/operations/result-envelope.ts +136 -0
- package/src/public/operations/runtime-types.ts +130 -5
- package/src/public/operations/source-relationship-parity.ts +226 -0
- package/src/public/operations/specs/{autopilot.ts → bootstrap.ts} +17 -16
- package/src/public/operations/specs/check.ts +4 -3
- package/src/public/operations/specs/discovery.ts +57 -3
- package/src/public/operations/specs/modeling.ts +3 -3
- package/src/public/operations/specs/mutation-schemas.ts +6 -1
- package/src/public/operations/specs/mutation.ts +27 -2
- package/src/public/operations/specs/planning.ts +234 -0
- package/src/public/operations/specs/reporting.ts +55 -1
- package/src/public/operations/specs/upsert.ts +10 -0
- package/src/public/operations/specs/verification.ts +78 -0
- package/src/public/operations/symbol-repair-plan.ts +164 -0
- package/src/public/operations/types.ts +62 -1
- package/src/public/playwright-case-id.ts +35 -0
- package/src/public/schemas/entity.ts +7 -2
- package/src/public/skills/kibi-bootstrap/SKILL.md +58 -0
- package/src/public/skills/kibi-bootstrap/resources/bootstrap.md +11 -0
- package/src/public/skills/kibi-bootstrap/resources/branch-lifecycle.md +7 -0
- package/src/public/skills/kibi-bootstrap/resources/operation-access.md +5 -0
- package/src/public/skills/kibi-bootstrap/resources/source-authoring.md +8 -0
- package/src/public/skills/kibi-freshness/SKILL.md +40 -10
- package/src/public/skills/kibi-freshness/resources/branch-lifecycle.md +7 -0
- package/src/public/skills/kibi-freshness/resources/operation-access.md +6 -0
- package/src/public/skills/kibi-freshness/resources/source-authoring.md +7 -0
- package/src/public/skills/kibi-traceability/SKILL.md +47 -47
- package/src/public/skills/kibi-traceability/resources/branch-lifecycle.md +7 -0
- package/src/public/skills/kibi-traceability/resources/operation-access.md +5 -0
- package/src/public/skills/kibi-traceability/resources/source-authoring.md +6 -0
- package/src/public/skills/kibi-traceability/resources/traceability.md +8 -0
- package/src/public/skills/kibi-usage/SKILL.md +115 -239
- package/src/public/skills/kibi-usage/resources/branch-lifecycle.md +31 -0
- package/src/public/skills/kibi-usage/resources/kb-improvement.md +38 -0
- package/src/public/skills/kibi-usage/resources/operation-access.md +36 -38
- package/src/public/skills/kibi-usage/resources/relationship-directions.md +3 -3
- package/src/public/skills/kibi-usage/resources/source-authoring.md +31 -0
- package/src/public/skills/kibi-usage/resources/workflows.md +56 -3
- package/src/public/symbol-granularity.ts +1 -0
- package/src/public/telemetry-acceptance.ts +16 -1
- package/src/public/telemetry-remediation.ts +1 -1
- package/src/public/verification-receipt.ts +248 -6
- package/src/schemas/entity.schema.json +1148 -273
- package/templates/github/kibi-badge.yml +86 -0
- package/templates/github/kibi-report.yml +84 -0
- package/dist/operations/autopilot/activation.d.ts.map +0 -1
- package/dist/operations/autopilot/candidates.d.ts +0 -4
- package/dist/operations/autopilot/discovery.d.ts.map +0 -1
- package/dist/operations/autopilot/generate.d.ts +0 -8
- package/dist/operations/autopilot/generate.d.ts.map +0 -1
- package/dist/operations/autopilot/generate.js +0 -112
- package/dist/operations/autopilot/presentation.d.ts +0 -13
- package/dist/operations/autopilot/presentation.d.ts.map +0 -1
- package/dist/operations/autopilot/presentation.js +0 -91
- package/dist/operations/autopilot/types.d.ts.map +0 -1
- package/dist/operations/autopilot/types.js +0 -8
- package/dist/public/operations/specs/autopilot.d.ts.map +0 -1
- package/dist/public/skills/init-kibi/SKILL.md +0 -62
- package/src/public/skills/init-kibi/SKILL.md +0 -62
- /package/dist/operations/{autopilot → bootstrap}/activation.d.ts +0 -0
- /package/dist/operations/{autopilot → bootstrap}/candidate-helpers.d.ts +0 -0
- /package/dist/operations/{autopilot → bootstrap}/candidate-helpers.js +0 -0
- /package/dist/operations/{autopilot → bootstrap}/requirement-claims.d.ts +0 -0
- /package/dist/operations/{autopilot → bootstrap}/requirement-claims.js +0 -0
package/dist/commands/sync.js
CHANGED
|
@@ -16,42 +16,241 @@
|
|
|
16
16
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
*/
|
|
18
18
|
import { execSync } from "node:child_process";
|
|
19
|
-
import {
|
|
19
|
+
import { createHash } from "node:crypto";
|
|
20
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFileSync, } from "node:fs";
|
|
20
21
|
import * as path from "node:path";
|
|
21
22
|
import { branchErrorToDiagnostic, createDocsNotIndexedDiagnostic, createInvalidAuthoringDiagnostic, createKbMissingDiagnostic, formatSyncSummary, } from "../diagnostics.js";
|
|
23
|
+
import { EngineClient, acquireEnginePublicationLease, engineSocketPath, ensureJournaledBranchStoreAsync, fsyncJournaledBranchStore, } from "../engine.js";
|
|
22
24
|
import { isCliDebugEnabled } from "../env.js";
|
|
23
|
-
import {
|
|
25
|
+
import { extractRelationshipShard, validateRelationships, } from "../extractors/relationships.js";
|
|
26
|
+
import { acquireSymbolCompilerLock, releaseSymbolCompilerLock, } from "../operations/mutation/symbol-compiler-lock.js";
|
|
24
27
|
import { analyzeSemanticAdvisorInput } from "../operations/semantic-advisor/analyze-prose.js";
|
|
25
28
|
import { validateSemanticInventoryBoundary } from "../operations/semantic-advisor/ingestion-boundary.js";
|
|
26
29
|
import { PrologProcess } from "../prolog.js";
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
30
|
+
import { resolveBranchAttachment } from "../utils/branch-resolver.js";
|
|
31
|
+
import { branchStoreManifestPath, branchStorePath, ensureBranchStoreManifest, expectedBranchStoreManifest, } from "../utils/branch-store-locator.js";
|
|
32
|
+
import { loadEntityPaths } from "../utils/config.js";
|
|
33
|
+
import { SYNC_CACHE_TTL_MS, SYNC_CACHE_VERSION, hashFile, hashManifestWithCoordinates, hashNormalized, readSyncCache, toCacheKey, writeSyncCache, } from "./sync/cache.js";
|
|
34
|
+
import { clearRecoveredPendingSourceReceipts, discoverSourceFiles, } from "./sync/discovery.js";
|
|
35
|
+
import { normalizeExtractionSources, processExtractions, } from "./sync/extraction.js";
|
|
32
36
|
import { refreshManifestCoordinates } from "./sync/manifest.js";
|
|
33
|
-
import { persistEntities, persistRelationships } from "./sync/persistence.js";
|
|
34
|
-
import { atomicPublish, cleanupStaging, createUniqueStagingPath, prepareStagingEnvironment, } from "./sync/staging.js";
|
|
37
|
+
import { persistEntities, persistRelationships, retractEntitiesById, retractEntitiesForSources, retractEntityRelationshipsById, retractRelationships, } from "./sync/persistence.js";
|
|
38
|
+
import { atomicPublish, atomicPublishGeneration, cleanupStaging, createUniqueStagingPath, prepareStagingEnvironment, } from "./sync/staging.js";
|
|
35
39
|
export class SyncError extends Error {
|
|
36
40
|
constructor(message) {
|
|
37
41
|
super(message);
|
|
38
42
|
this.name = "SyncError";
|
|
39
43
|
}
|
|
40
44
|
}
|
|
45
|
+
function relationshipKey(relationship) {
|
|
46
|
+
return `${relationship.type}\0${relationship.from}\0${relationship.to}`;
|
|
47
|
+
}
|
|
48
|
+
function relationshipFromKey(key) {
|
|
49
|
+
const [type, from, to] = key.split("\0");
|
|
50
|
+
if (type === undefined || from === undefined || to === undefined) {
|
|
51
|
+
throw new SyncError(`Invalid cached relationship key: ${key}`);
|
|
52
|
+
}
|
|
53
|
+
return { type, from, to };
|
|
54
|
+
}
|
|
55
|
+
function assertNoUnresolvedGitConflicts(workspaceRoot) {
|
|
56
|
+
let conflicted = "";
|
|
57
|
+
try {
|
|
58
|
+
conflicted = execSync("git diff --name-only --diff-filter=U --", {
|
|
59
|
+
cwd: workspaceRoot,
|
|
60
|
+
encoding: "utf8",
|
|
61
|
+
timeout: 5000,
|
|
62
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
63
|
+
}).trim();
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// A non-Git workspace is handled by branch resolution below. Do not turn
|
|
67
|
+
// a missing Git binary into a misleading conflict diagnostic.
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (conflicted) {
|
|
71
|
+
throw new SyncError(`Unresolved Git conflicts block Kibi compilation; resolve these authored files first: ${conflicted.split("\n").join(", ")}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function trackedRelationshipFiles(workspaceRoot, relationshipsDir, recoverMissingPendingSources = false, recoveredPendingReceiptPaths = []) {
|
|
75
|
+
let tracked;
|
|
76
|
+
try {
|
|
77
|
+
tracked = new Set(execSync("git ls-files --cached -- .kb/relationships", {
|
|
78
|
+
cwd: workspaceRoot,
|
|
79
|
+
encoding: "utf8",
|
|
80
|
+
timeout: 5000,
|
|
81
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
82
|
+
})
|
|
83
|
+
.split("\n")
|
|
84
|
+
.filter(Boolean)
|
|
85
|
+
.map((file) => file.replaceAll("\\", "/")));
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// A non-Git workspace has no tracked relationship inputs. The caller's
|
|
89
|
+
// branch resolver will produce the user-facing attachment diagnostic.
|
|
90
|
+
return [];
|
|
91
|
+
}
|
|
92
|
+
const pending = new Set();
|
|
93
|
+
const pendingRoot = path.join(workspaceRoot, ".kb", "recovery", "pending-sources");
|
|
94
|
+
if (existsSync(pendingRoot)) {
|
|
95
|
+
for (const receiptName of readdirSync(pendingRoot)) {
|
|
96
|
+
if (!receiptName.endsWith(".json"))
|
|
97
|
+
continue;
|
|
98
|
+
let receipt;
|
|
99
|
+
try {
|
|
100
|
+
receipt = JSON.parse(readFileSync(path.join(pendingRoot, receiptName), "utf8"));
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// Malformed receipts are left for explicit recovery diagnostics. They
|
|
104
|
+
// must never make an unrelated relationship shard disappear silently.
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
if (typeof receipt.path !== "string" ||
|
|
108
|
+
typeof receipt.afterHash !== "string") {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const relative = receipt.path.replaceAll("\\", "/");
|
|
112
|
+
if (!relative.startsWith(".kb/relationships/"))
|
|
113
|
+
continue;
|
|
114
|
+
const absolute = path.resolve(workspaceRoot, relative);
|
|
115
|
+
if (!absolute.startsWith(`${path.resolve(workspaceRoot)}${path.sep}`)) {
|
|
116
|
+
throw new SyncError(`Pending source path escapes workspace: ${relative}`);
|
|
117
|
+
}
|
|
118
|
+
if (!existsSync(absolute)) {
|
|
119
|
+
if (recoverMissingPendingSources) {
|
|
120
|
+
const receiptPath = path.join(pendingRoot, receiptName);
|
|
121
|
+
if (!recoveredPendingReceiptPaths.some((candidate) => candidate.receiptPath === receiptPath)) {
|
|
122
|
+
recoveredPendingReceiptPaths.push({
|
|
123
|
+
receiptPath,
|
|
124
|
+
path: relative,
|
|
125
|
+
afterHash: receipt.afterHash,
|
|
126
|
+
rawHash: createHash("sha256")
|
|
127
|
+
.update(readFileSync(receiptPath))
|
|
128
|
+
.digest("hex"),
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
throw new SyncError(`Pending source is missing: ${relative}`);
|
|
134
|
+
}
|
|
135
|
+
const actual = createHash("sha256")
|
|
136
|
+
.update(readFileSync(absolute))
|
|
137
|
+
.digest("hex");
|
|
138
|
+
if (actual !== receipt.afterHash) {
|
|
139
|
+
throw new SyncError(`Pending source hash drift blocks sync for ${relative}`);
|
|
140
|
+
}
|
|
141
|
+
pending.add(relative);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
return readdirSync(relationshipsDir)
|
|
146
|
+
.filter((file) => file.endsWith(".yaml") || file.endsWith(".yml"))
|
|
147
|
+
.map((file) => path.join(relationshipsDir, file))
|
|
148
|
+
.filter((file) => {
|
|
149
|
+
const relative = path
|
|
150
|
+
.relative(workspaceRoot, file)
|
|
151
|
+
.replaceAll(path.sep, "/");
|
|
152
|
+
return tracked.has(relative) || pending.has(relative);
|
|
153
|
+
})
|
|
154
|
+
.sort();
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
return [];
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function normalizedEntityHash(result) {
|
|
161
|
+
const entity = { ...result.entity };
|
|
162
|
+
// Manifest defaults are generated at extraction time. They must not turn a
|
|
163
|
+
// one-record edit into 10,000 false-positive symbol updates.
|
|
164
|
+
entity.created_at = undefined;
|
|
165
|
+
entity.updated_at = undefined;
|
|
166
|
+
return hashNormalized({
|
|
167
|
+
entity,
|
|
168
|
+
sourceFile: result.sourceFile,
|
|
169
|
+
relationships: result.relationships
|
|
170
|
+
.map(relationshipKey)
|
|
171
|
+
.sort((left, right) => left.localeCompare(right)),
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
// implements REQ-kibi-proposition-complete-ingestion
|
|
175
|
+
function semanticBoundaryRelationships(result, shardRelationships) {
|
|
176
|
+
const relationships = new Map();
|
|
177
|
+
for (const relationship of [...result.relationships, ...shardRelationships]) {
|
|
178
|
+
if (relationship.from !== result.entity.id)
|
|
179
|
+
continue;
|
|
180
|
+
relationships.set(relationshipKey(relationship), relationship);
|
|
181
|
+
}
|
|
182
|
+
return [...relationships.values()];
|
|
183
|
+
}
|
|
184
|
+
async function checkpointNoopSync(workspaceRoot, branch) {
|
|
185
|
+
const engine = new EngineClient({
|
|
186
|
+
workspaceRoot,
|
|
187
|
+
branch,
|
|
188
|
+
timeout: 120_000,
|
|
189
|
+
});
|
|
190
|
+
try {
|
|
191
|
+
await engine.start();
|
|
192
|
+
const checkpoint = await engine.checkpoint();
|
|
193
|
+
if (!checkpoint.success) {
|
|
194
|
+
throw new SyncError(`Failed to publish the no-op sync checkpoint: ${checkpoint.error ?? "Unknown error"}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
finally {
|
|
198
|
+
await engine.terminate();
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
function compilerCacheHasEntityDelta(cache) {
|
|
202
|
+
return (cache.entityHashes !== undefined && cache.sourceEntityIds !== undefined);
|
|
203
|
+
}
|
|
204
|
+
function compilerCacheIsFresh(cache, workspaceRoot, sourceFiles, nowMs) {
|
|
205
|
+
const sourceKeys = sourceFiles.map((file) => toCacheKey(workspaceRoot, file));
|
|
206
|
+
if (Object.keys(cache.hashes).some((key) => !sourceKeys.includes(key))) {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
return sourceKeys.every((key) => {
|
|
210
|
+
const lastSeen = cache.seenAt[key];
|
|
211
|
+
const lastSeenMs = lastSeen ? Date.parse(lastSeen) : Number.NaN;
|
|
212
|
+
return (typeof cache.hashes[key] === "string" &&
|
|
213
|
+
lastSeen !== undefined &&
|
|
214
|
+
!Number.isNaN(lastSeenMs) &&
|
|
215
|
+
nowMs - lastSeenMs <= SYNC_CACHE_TTL_MS);
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
function compilerCacheFilesMatch(cache, workspaceRoot, sourceFiles, relationshipFiles, sourceHashOf) {
|
|
219
|
+
for (const file of sourceFiles) {
|
|
220
|
+
if (cache.hashes[toCacheKey(workspaceRoot, file)] !== sourceHashOf(file))
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
const relationshipKeys = new Set(relationshipFiles.map((file) => toCacheKey(workspaceRoot, file)));
|
|
224
|
+
if (Object.keys(cache.relationshipHashes ?? {}).some((key) => !relationshipKeys.has(key))) {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
for (const file of relationshipFiles) {
|
|
228
|
+
if (cache.relationshipHashes?.[toCacheKey(workspaceRoot, file)] !==
|
|
229
|
+
hashFile(workspaceRoot, file)) {
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
41
235
|
// implements REQ-003, REQ-007
|
|
42
236
|
export async function syncCommand(options = {}, runtime = {}) {
|
|
43
237
|
const validateOnly = options.validateOnly ?? false;
|
|
44
238
|
const rebuild = options.rebuild ?? false;
|
|
239
|
+
const recoveryBackupPath = options.recoveryBackupPath;
|
|
240
|
+
const workspaceRoot = path.resolve(options.workspaceRoot ?? process.cwd());
|
|
45
241
|
const startTime = Date.now();
|
|
46
242
|
const diagnostics = [];
|
|
47
243
|
const entityCounts = {};
|
|
48
244
|
let published = false;
|
|
49
245
|
let currentBranch;
|
|
50
246
|
let stagingPath;
|
|
247
|
+
let publicationLease;
|
|
248
|
+
let compilerLock;
|
|
249
|
+
let operationFailure;
|
|
51
250
|
const getCurrentCommit = () => {
|
|
52
251
|
try {
|
|
53
252
|
return execSync("git rev-parse HEAD", {
|
|
54
|
-
cwd:
|
|
253
|
+
cwd: workspaceRoot,
|
|
55
254
|
encoding: "utf8",
|
|
56
255
|
timeout: 5000,
|
|
57
256
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -63,22 +262,72 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
63
262
|
};
|
|
64
263
|
const withOptionalCommit = (value, commit) => commit !== undefined ? { ...value, commit } : value;
|
|
65
264
|
try {
|
|
265
|
+
if (!validateOnly) {
|
|
266
|
+
compilerLock = await (runtime.acquireSymbolCompilerLock ?? acquireSymbolCompilerLock)(workspaceRoot);
|
|
267
|
+
}
|
|
268
|
+
assertNoUnresolvedGitConflicts(workspaceRoot);
|
|
66
269
|
// Branch resolution
|
|
67
|
-
const branchResult =
|
|
270
|
+
const branchResult = resolveBranchAttachment(workspaceRoot);
|
|
68
271
|
if ("error" in branchResult) {
|
|
69
272
|
const diagnostic = branchErrorToDiagnostic(branchResult.code, branchResult.error);
|
|
70
273
|
diagnostics.push(diagnostic);
|
|
71
274
|
console.error(`Failed to resolve active branch: ${branchResult.error}`);
|
|
72
275
|
throw new SyncError(`Failed to resolve active branch: ${branchResult.error}`);
|
|
73
276
|
}
|
|
74
|
-
|
|
277
|
+
if (branchResult.migrationRequired && !validateOnly) {
|
|
278
|
+
throw new SyncError(`Sync blocked: KB is attached through legacy branch storage for '${branchResult.gitBranch}'. Run 'kibi branch migrate --from ${branchResult.kbBranch} --to ${branchResult.gitBranch} --apply' first.`);
|
|
279
|
+
}
|
|
280
|
+
currentBranch = branchResult.kbBranch;
|
|
281
|
+
// Cut over legacy branches before creating a staging copy. If another
|
|
282
|
+
// CLI/MCP operation has an engine attached, stop that single writer so the
|
|
283
|
+
// atomic publish below cannot race its RDF lock.
|
|
284
|
+
const livePathForEngine = branchStorePath(workspaceRoot, currentBranch);
|
|
285
|
+
if (!validateOnly && recoveryBackupPath === undefined) {
|
|
286
|
+
ensureBranchStoreManifest(workspaceRoot, currentBranch);
|
|
287
|
+
await ensureJournaledBranchStoreAsync(livePathForEngine);
|
|
288
|
+
}
|
|
289
|
+
const needsExclusiveGenerationPublish = !validateOnly && (rebuild || recoveryBackupPath !== undefined);
|
|
290
|
+
if (needsExclusiveGenerationPublish) {
|
|
291
|
+
// Recovery intentionally avoids attaching the broken live store. The
|
|
292
|
+
// clean rebuild is compiled into staging and published only after it
|
|
293
|
+
// can be reopened successfully.
|
|
294
|
+
const existingEngine = new EngineClient({
|
|
295
|
+
workspaceRoot,
|
|
296
|
+
branch: currentBranch,
|
|
297
|
+
timeout: 2_000,
|
|
298
|
+
allowPublicationLock: true,
|
|
299
|
+
});
|
|
300
|
+
const engineSocketExists = existsSync(engineSocketPath(workspaceRoot, currentBranch));
|
|
301
|
+
try {
|
|
302
|
+
publicationLease = acquireEnginePublicationLease(workspaceRoot, currentBranch);
|
|
303
|
+
// This client is explicitly allowed to attach under its own lease so
|
|
304
|
+
// a daemon that appeared between the socket probe and lease creation
|
|
305
|
+
// is still stopped before publication.
|
|
306
|
+
if (engineSocketExists ||
|
|
307
|
+
existsSync(engineSocketPath(workspaceRoot, currentBranch))) {
|
|
308
|
+
await existingEngine.start(false);
|
|
309
|
+
}
|
|
310
|
+
if (existingEngine.isRunning()) {
|
|
311
|
+
await existingEngine.stop(false);
|
|
312
|
+
}
|
|
313
|
+
else if (engineSocketExists ||
|
|
314
|
+
existsSync(engineSocketPath(workspaceRoot, currentBranch))) {
|
|
315
|
+
throw new SyncError(`Kibi engine socket remains present but is not reachable: ${engineSocketPath(workspaceRoot, currentBranch)}`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
finally {
|
|
319
|
+
await existingEngine.terminate();
|
|
320
|
+
}
|
|
321
|
+
}
|
|
75
322
|
if (isCliDebugEnabled()) {
|
|
76
323
|
// eslint-disable-next-line no-console
|
|
77
324
|
console.log("[kibi-debug] currentBranch:", currentBranch);
|
|
78
325
|
}
|
|
79
|
-
const
|
|
80
|
-
const
|
|
81
|
-
|
|
326
|
+
const paths = loadEntityPaths(workspaceRoot);
|
|
327
|
+
const { markdownFiles, manifestFiles, relationshipsDir, recoveredPendingReceiptPaths, } = await discoverSourceFiles(workspaceRoot, {
|
|
328
|
+
trackedOnly: true,
|
|
329
|
+
recoverMissingPendingSources: recoveryBackupPath !== undefined,
|
|
330
|
+
});
|
|
82
331
|
if (isCliDebugEnabled()) {
|
|
83
332
|
// eslint-disable-next-line no-console
|
|
84
333
|
console.log("[kibi-debug] markdownFiles:", markdownFiles.length);
|
|
@@ -86,10 +335,70 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
86
335
|
console.log("[kibi-debug] manifestFiles:", manifestFiles.length);
|
|
87
336
|
}
|
|
88
337
|
const sourceFiles = [...markdownFiles, ...manifestFiles].sort();
|
|
89
|
-
const cachePath = path.join(
|
|
338
|
+
const cachePath = path.join(livePathForEngine, "sync-cache.json");
|
|
90
339
|
const syncCache = readSyncCache(cachePath);
|
|
91
340
|
const nowIso = new Date().toISOString();
|
|
92
341
|
const nowMs = Date.now();
|
|
342
|
+
const currentSourceKeys = new Set(sourceFiles.map((file) => toCacheKey(workspaceRoot, file)));
|
|
343
|
+
const relationshipShardFiles = existsSync(relationshipsDir)
|
|
344
|
+
? trackedRelationshipFiles(workspaceRoot, relationshipsDir, recoveryBackupPath !== undefined, recoveredPendingReceiptPaths)
|
|
345
|
+
: [];
|
|
346
|
+
// No-op is a first-class compiler result. Hashing the configured inputs is
|
|
347
|
+
// sufficient when normalized entity/shard inventories are already fresh;
|
|
348
|
+
// avoid rebuilding maps and rediscovering RDF state for the common path.
|
|
349
|
+
// Symbol manifests hash together with their generated coordinate artifact
|
|
350
|
+
// so artifact-only changes never masquerade as no-ops.
|
|
351
|
+
const fastPathSourceHashOf = (file) => manifestFiles.includes(file)
|
|
352
|
+
? hashManifestWithCoordinates(workspaceRoot, file, path.join(path.dirname(file), "symbol-coordinates.yaml"))
|
|
353
|
+
: hashFile(workspaceRoot, file);
|
|
354
|
+
if (!validateOnly &&
|
|
355
|
+
!rebuild &&
|
|
356
|
+
!options.refreshSymbolCoordinates &&
|
|
357
|
+
runtime.createProlog === undefined &&
|
|
358
|
+
compilerCacheHasEntityDelta(syncCache) &&
|
|
359
|
+
compilerCacheIsFresh(syncCache, workspaceRoot, sourceFiles, nowMs) &&
|
|
360
|
+
compilerCacheFilesMatch(syncCache, workspaceRoot, sourceFiles, relationshipShardFiles, fastPathSourceHashOf)) {
|
|
361
|
+
await checkpointNoopSync(workspaceRoot, currentBranch);
|
|
362
|
+
console.log("✓ Imported 0 entities, 0 relationships (no changes)");
|
|
363
|
+
return withOptionalCommit({
|
|
364
|
+
branch: currentBranch,
|
|
365
|
+
timestamp: new Date().toISOString(),
|
|
366
|
+
entityCounts,
|
|
367
|
+
relationshipCount: 0,
|
|
368
|
+
success: true,
|
|
369
|
+
published: false,
|
|
370
|
+
failures: diagnostics,
|
|
371
|
+
durationMs: Date.now() - startTime,
|
|
372
|
+
exitCode: 0,
|
|
373
|
+
}, getCurrentCommit());
|
|
374
|
+
}
|
|
375
|
+
// Explicit coordinate refresh must precede fingerprinting so the manifest
|
|
376
|
+
// overlay that is persisted into RDF observes the newly generated
|
|
377
|
+
// coordinates. Refresh failures are fatal: cache state may never advance
|
|
378
|
+
// on a partially published compiler dependency.
|
|
379
|
+
const refreshedManifestKeys = new Set();
|
|
380
|
+
if (!validateOnly && options.refreshSymbolCoordinates) {
|
|
381
|
+
for (const file of manifestFiles) {
|
|
382
|
+
await refreshManifestCoordinates(file, workspaceRoot, {
|
|
383
|
+
refreshSymbolCoordinates: options.refreshSymbolCoordinates,
|
|
384
|
+
});
|
|
385
|
+
refreshedManifestKeys.add(toCacheKey(workspaceRoot, file));
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
// The generated coordinate artifact is a compiler dependency of every
|
|
389
|
+
// symbol manifest: its existence, emptiness, content, and deletion must
|
|
390
|
+
// all change the effective source hash even when authored YAML is stable.
|
|
391
|
+
const coordinatesPathForManifest = (manifestFile) => path.join(path.dirname(manifestFile), "symbol-coordinates.yaml");
|
|
392
|
+
const effectiveSourceHash = (file) => manifestFiles.includes(file)
|
|
393
|
+
? hashManifestWithCoordinates(workspaceRoot, file, coordinatesPathForManifest(file))
|
|
394
|
+
: hashFile(workspaceRoot, file);
|
|
395
|
+
const changedSourceHashes = new Map();
|
|
396
|
+
for (const file of sourceFiles) {
|
|
397
|
+
const key = toCacheKey(workspaceRoot, file);
|
|
398
|
+
const hash = effectiveSourceHash(file);
|
|
399
|
+
if (syncCache.hashes[key] !== hash)
|
|
400
|
+
changedSourceHashes.set(key, hash);
|
|
401
|
+
}
|
|
93
402
|
const nextHashes = {};
|
|
94
403
|
const nextSeenAt = {};
|
|
95
404
|
const nextSemanticHashes = {
|
|
@@ -98,15 +407,74 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
98
407
|
const nextSemanticContracts = {
|
|
99
408
|
...syncCache.semanticContracts,
|
|
100
409
|
};
|
|
410
|
+
const nextRelationshipHashes = {};
|
|
411
|
+
const nextShardRelationships = {};
|
|
412
|
+
const addedShardRelationships = [];
|
|
413
|
+
const removedShardRelationships = [];
|
|
101
414
|
const initialSemanticBaseline = Object.keys(syncCache.hashes).length === 0;
|
|
102
|
-
const shardResults = extractFromRelationshipShards(relationshipsDir);
|
|
103
|
-
const allRelationships = flattenRelationships(shardResults);
|
|
104
415
|
const changedMarkdownFiles = [];
|
|
105
416
|
const changedManifestFiles = [];
|
|
417
|
+
const forceEntitySourceKeys = new Set();
|
|
418
|
+
// A removed source has no file left to extract, but its entities must be
|
|
419
|
+
// retracted from the branch. Keep this separate from failed extraction:
|
|
420
|
+
// malformed current files remain authoritative until a later successful
|
|
421
|
+
// sync rather than deleting their last known-good entities.
|
|
422
|
+
const deletedSourceFiles = Object.keys(syncCache.hashes)
|
|
423
|
+
.filter((key) => !currentSourceKeys.has(key))
|
|
424
|
+
.map((key) => path.resolve(workspaceRoot, key));
|
|
425
|
+
const currentRelationshipKeys = new Set();
|
|
426
|
+
for (const shardPath of relationshipShardFiles) {
|
|
427
|
+
const key = toCacheKey(workspaceRoot, shardPath);
|
|
428
|
+
currentRelationshipKeys.add(key);
|
|
429
|
+
let hash;
|
|
430
|
+
try {
|
|
431
|
+
hash = hashFile(workspaceRoot, shardPath);
|
|
432
|
+
nextRelationshipHashes[key] = hash;
|
|
433
|
+
}
|
|
434
|
+
catch (error) {
|
|
435
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
436
|
+
console.warn(`Warning: Failed to hash relationship shard ${shardPath}: ${message}`);
|
|
437
|
+
}
|
|
438
|
+
const previousKeys = syncCache.shardRelationships?.[key] ?? [];
|
|
439
|
+
const shardChanged = syncCache.shardRelationships === undefined ||
|
|
440
|
+
hash === undefined ||
|
|
441
|
+
syncCache.relationshipHashes?.[key] !== hash;
|
|
442
|
+
const currentKeys = shardChanged
|
|
443
|
+
? extractRelationshipShard(shardPath)
|
|
444
|
+
.relationships.map(relationshipKey)
|
|
445
|
+
.sort((left, right) => left.localeCompare(right))
|
|
446
|
+
: previousKeys;
|
|
447
|
+
nextShardRelationships[key] = currentKeys;
|
|
448
|
+
if (shardChanged) {
|
|
449
|
+
const previous = new Set(previousKeys);
|
|
450
|
+
const current = new Set(currentKeys);
|
|
451
|
+
for (const edge of previous) {
|
|
452
|
+
if (!current.has(edge)) {
|
|
453
|
+
removedShardRelationships.push(relationshipFromKey(edge));
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
for (const edge of current) {
|
|
457
|
+
if (!previous.has(edge)) {
|
|
458
|
+
addedShardRelationships.push(relationshipFromKey(edge));
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
for (const [key, previousKeys] of Object.entries(syncCache.shardRelationships ?? {})) {
|
|
464
|
+
if (currentRelationshipKeys.has(key))
|
|
465
|
+
continue;
|
|
466
|
+
for (const edge of previousKeys) {
|
|
467
|
+
removedShardRelationships.push(relationshipFromKey(edge));
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
const relationshipChanged = addedShardRelationships.length > 0 ||
|
|
471
|
+
removedShardRelationships.length > 0;
|
|
106
472
|
for (const file of sourceFiles) {
|
|
107
473
|
try {
|
|
108
|
-
const key = toCacheKey(file);
|
|
109
|
-
const hash =
|
|
474
|
+
const key = toCacheKey(workspaceRoot, file);
|
|
475
|
+
const hash = changedSourceHashes.get(key) ?? syncCache.hashes[key];
|
|
476
|
+
if (hash === undefined)
|
|
477
|
+
continue;
|
|
110
478
|
const lastSeen = syncCache.seenAt[key];
|
|
111
479
|
const lastSeenMs = lastSeen ? Date.parse(lastSeen) : Number.NaN;
|
|
112
480
|
const expired = !lastSeen ||
|
|
@@ -114,8 +482,10 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
114
482
|
nowMs - lastSeenMs > SYNC_CACHE_TTL_MS;
|
|
115
483
|
nextHashes[key] = hash;
|
|
116
484
|
nextSeenAt[key] = nowIso;
|
|
117
|
-
const isChanged = expired ||
|
|
485
|
+
const isChanged = expired || changedSourceHashes.has(key) || validateOnly || rebuild;
|
|
118
486
|
if (isChanged) {
|
|
487
|
+
if (expired)
|
|
488
|
+
forceEntitySourceKeys.add(key);
|
|
119
489
|
if (markdownFiles.includes(file)) {
|
|
120
490
|
changedMarkdownFiles.push(file);
|
|
121
491
|
}
|
|
@@ -129,41 +499,121 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
129
499
|
console.warn(`Warning: Failed to hash ${file}: ${message}`);
|
|
130
500
|
}
|
|
131
501
|
}
|
|
132
|
-
//
|
|
133
|
-
//
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
502
|
+
// A v1 cache has only whole-file hashes. Perform one compiler-metadata
|
|
503
|
+
// backfill so subsequent edits can be reduced to normalized entity deltas.
|
|
504
|
+
if (syncCache.entityHashes === undefined ||
|
|
505
|
+
syncCache.sourceEntityIds === undefined) {
|
|
506
|
+
for (const file of markdownFiles) {
|
|
507
|
+
if (!changedMarkdownFiles.includes(file))
|
|
508
|
+
changedMarkdownFiles.push(file);
|
|
509
|
+
}
|
|
137
510
|
for (const file of manifestFiles) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
refreshSymbolCoordinates: options.refreshSymbolCoordinates,
|
|
141
|
-
});
|
|
142
|
-
if (!changedManifestFiles.includes(file)) {
|
|
143
|
-
changedManifestFiles.push(file);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
catch (error) {
|
|
147
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
148
|
-
console.warn(`Warning: Failed to refresh symbol coordinates in ${file}: ${message}`);
|
|
149
|
-
}
|
|
511
|
+
if (!changedManifestFiles.includes(file))
|
|
512
|
+
changedManifestFiles.push(file);
|
|
150
513
|
}
|
|
151
514
|
}
|
|
515
|
+
// Explicitly requested refreshes force coordinate-bearing symbols through
|
|
516
|
+
// extraction and RDF persistence even when normalized entity hashes match
|
|
517
|
+
// the cached state, repairing warm-cache RDF divergence.
|
|
518
|
+
for (const file of manifestFiles) {
|
|
519
|
+
if (!refreshedManifestKeys.has(toCacheKey(workspaceRoot, file)) ||
|
|
520
|
+
changedManifestFiles.includes(file)) {
|
|
521
|
+
continue;
|
|
522
|
+
}
|
|
523
|
+
changedManifestFiles.push(file);
|
|
524
|
+
}
|
|
525
|
+
for (const key of refreshedManifestKeys) {
|
|
526
|
+
forceEntitySourceKeys.add(key);
|
|
527
|
+
}
|
|
152
528
|
const performedFullReindex = changedMarkdownFiles.length === markdownFiles.length &&
|
|
153
529
|
changedManifestFiles.length === manifestFiles.length;
|
|
154
|
-
const
|
|
155
|
-
|
|
530
|
+
const extraction = await processExtractions(changedMarkdownFiles, changedManifestFiles, validateOnly, workspaceRoot);
|
|
531
|
+
const { failedCacheKeys, errors } = extraction;
|
|
532
|
+
const extractedResults = normalizeExtractionSources(extraction.results, workspaceRoot);
|
|
533
|
+
const nextEntityHashes = {
|
|
534
|
+
...(syncCache.entityHashes ?? {}),
|
|
535
|
+
};
|
|
536
|
+
const nextSourceEntityIds = {
|
|
537
|
+
...(syncCache.sourceEntityIds ?? {}),
|
|
538
|
+
};
|
|
539
|
+
const removedEntityIds = new Set();
|
|
540
|
+
const changedEntityIds = new Set();
|
|
541
|
+
const supportsEntityDelta = syncCache.entityHashes !== undefined &&
|
|
542
|
+
syncCache.sourceEntityIds !== undefined;
|
|
543
|
+
const useEntityDelta = supportsEntityDelta &&
|
|
544
|
+
!validateOnly &&
|
|
545
|
+
!rebuild &&
|
|
546
|
+
runtime.createProlog === undefined;
|
|
547
|
+
// Re-materialize every authored shard edge whenever a source entity is
|
|
548
|
+
// refreshed. Entity-delta sync retracts outgoing relationships for changed
|
|
549
|
+
// entities before persisting their extracted relationships. Manifest
|
|
550
|
+
// entities commonly carry no inline links, so a manifest-only edit (for
|
|
551
|
+
// example, a generated coordinate refresh) would otherwise drop valid
|
|
552
|
+
// shard-only edges and leave the cache claiming they were already synced.
|
|
553
|
+
const materializeAllRelationships = !useEntityDelta ||
|
|
554
|
+
changedMarkdownFiles.length > 0 ||
|
|
555
|
+
changedManifestFiles.length > 0;
|
|
556
|
+
const allRelationships = materializeAllRelationships
|
|
557
|
+
? Object.values(nextShardRelationships).flat().map(relationshipFromKey)
|
|
558
|
+
: [...addedShardRelationships, ...removedShardRelationships];
|
|
559
|
+
for (const deletedSource of deletedSourceFiles) {
|
|
560
|
+
const sourceKey = toCacheKey(workspaceRoot, deletedSource);
|
|
561
|
+
for (const id of nextSourceEntityIds[sourceKey] ?? []) {
|
|
562
|
+
removedEntityIds.add(id);
|
|
563
|
+
delete nextEntityHashes[id];
|
|
564
|
+
}
|
|
565
|
+
delete nextSourceEntityIds[sourceKey];
|
|
566
|
+
}
|
|
567
|
+
const resultsBySource = new Map();
|
|
568
|
+
for (const result of extractedResults) {
|
|
569
|
+
const sourceKey = toCacheKey(workspaceRoot, result.entity.source);
|
|
570
|
+
const sourceResults = resultsBySource.get(sourceKey) ?? [];
|
|
571
|
+
sourceResults.push(result);
|
|
572
|
+
resultsBySource.set(sourceKey, sourceResults);
|
|
573
|
+
}
|
|
574
|
+
for (const changedSource of [
|
|
575
|
+
...changedMarkdownFiles,
|
|
576
|
+
...changedManifestFiles,
|
|
577
|
+
]) {
|
|
578
|
+
const sourceKey = toCacheKey(workspaceRoot, changedSource);
|
|
579
|
+
if (failedCacheKeys.has(sourceKey))
|
|
580
|
+
continue;
|
|
581
|
+
const sourceResults = resultsBySource.get(sourceKey) ?? [];
|
|
582
|
+
const previousIds = new Set(nextSourceEntityIds[sourceKey] ?? []);
|
|
583
|
+
const currentIds = sourceResults.map(({ entity }) => entity.id).sort();
|
|
584
|
+
const currentIdSet = new Set(currentIds);
|
|
585
|
+
for (const previousId of previousIds) {
|
|
586
|
+
if (!currentIdSet.has(previousId)) {
|
|
587
|
+
removedEntityIds.add(previousId);
|
|
588
|
+
delete nextEntityHashes[previousId];
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
for (const result of sourceResults) {
|
|
592
|
+
const hash = normalizedEntityHash(result);
|
|
593
|
+
if (forceEntitySourceKeys.has(sourceKey) ||
|
|
594
|
+
nextEntityHashes[result.entity.id] !== hash) {
|
|
595
|
+
changedEntityIds.add(result.entity.id);
|
|
596
|
+
}
|
|
597
|
+
nextEntityHashes[result.entity.id] = hash;
|
|
598
|
+
}
|
|
599
|
+
nextSourceEntityIds[sourceKey] = currentIds;
|
|
600
|
+
}
|
|
601
|
+
const results = useEntityDelta
|
|
602
|
+
? extractedResults.filter(({ entity }) => changedEntityIds.has(entity.id))
|
|
603
|
+
: extractedResults;
|
|
604
|
+
for (const result of extractedResults) {
|
|
156
605
|
if (result.entity.type !== "req")
|
|
157
606
|
continue;
|
|
158
|
-
const key = toCacheKey(result.entity.source);
|
|
607
|
+
const key = toCacheKey(workspaceRoot, result.entity.source);
|
|
608
|
+
const relationships = semanticBoundaryRelationships(result, allRelationships);
|
|
159
609
|
const payload = {
|
|
160
610
|
type: result.entity.type,
|
|
161
611
|
id: result.entity.id,
|
|
162
612
|
properties: result.entity,
|
|
163
|
-
relationships
|
|
613
|
+
relationships,
|
|
164
614
|
};
|
|
165
615
|
const semantic = analyzeSemanticAdvisorInput({ payload });
|
|
166
|
-
const boundary = validateSemanticInventoryBoundary(payload,
|
|
616
|
+
const boundary = validateSemanticInventoryBoundary(payload, relationships, semantic.receipt);
|
|
167
617
|
const previousSemanticHash = syncCache.semanticHashes[key];
|
|
168
618
|
const advertisedContract = result.entity.semantic_inventory_version !== undefined ||
|
|
169
619
|
result.entity.semantic_source_hash !== undefined ||
|
|
@@ -212,7 +662,13 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
212
662
|
exitCode: 1,
|
|
213
663
|
}, getCurrentCommit());
|
|
214
664
|
}
|
|
215
|
-
if (results.length === 0 &&
|
|
665
|
+
if (results.length === 0 &&
|
|
666
|
+
removedEntityIds.size === 0 &&
|
|
667
|
+
!relationshipChanged &&
|
|
668
|
+
(useEntityDelta || changedMarkdownFiles.length === 0) &&
|
|
669
|
+
(useEntityDelta || changedManifestFiles.length === 0) &&
|
|
670
|
+
deletedSourceFiles.length === 0 &&
|
|
671
|
+
!rebuild) {
|
|
216
672
|
const evictedHashes = {};
|
|
217
673
|
const evictedSeenAt = {};
|
|
218
674
|
const evictedSemanticHashes = {};
|
|
@@ -228,9 +684,19 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
228
684
|
evictedSemanticContracts[key] = nextSemanticContracts[key] === true;
|
|
229
685
|
}
|
|
230
686
|
}
|
|
687
|
+
// The durable KB checkpoint must precede the cache write: if the
|
|
688
|
+
// checkpoint fails, cached fingerprints must stay stale so the next
|
|
689
|
+
// sync recompiles instead of trusting uncommitted compiler output.
|
|
690
|
+
if (runtime.createProlog === undefined) {
|
|
691
|
+
await checkpointNoopSync(workspaceRoot, currentBranch);
|
|
692
|
+
}
|
|
231
693
|
writeSyncCache(cachePath, {
|
|
232
694
|
version: SYNC_CACHE_VERSION,
|
|
233
695
|
hashes: evictedHashes,
|
|
696
|
+
relationshipHashes: nextRelationshipHashes,
|
|
697
|
+
entityHashes: nextEntityHashes,
|
|
698
|
+
sourceEntityIds: nextSourceEntityIds,
|
|
699
|
+
shardRelationships: nextShardRelationships,
|
|
234
700
|
seenAt: evictedSeenAt,
|
|
235
701
|
semanticHashes: evictedSemanticHashes,
|
|
236
702
|
semanticContracts: evictedSemanticContracts,
|
|
@@ -248,12 +714,141 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
248
714
|
exitCode: 0,
|
|
249
715
|
}, getCurrentCommit());
|
|
250
716
|
}
|
|
251
|
-
const livePath =
|
|
717
|
+
const livePath = branchStorePath(workspaceRoot, currentBranch);
|
|
252
718
|
const kbExists = existsSync(livePath);
|
|
253
719
|
if (!kbExists && !rebuild) {
|
|
254
720
|
diagnostics.push(createKbMissingDiagnostic(currentBranch, livePath));
|
|
255
721
|
}
|
|
256
|
-
|
|
722
|
+
// implements REQ-core-journaled-engine-delta-sync
|
|
723
|
+
// Normal syncs are compiled directly into the long-lived single-writer
|
|
724
|
+
// engine. Rebuilds retain generation replacement semantics, and injected
|
|
725
|
+
// Prolog runtimes keep the staging path used by the contract fixtures.
|
|
726
|
+
// This is the cutover that avoids copying and rewriting a complete branch
|
|
727
|
+
// for a one-symbol or relationship-only change.
|
|
728
|
+
if (!validateOnly && !rebuild && runtime.createProlog === undefined) {
|
|
729
|
+
const engine = new EngineClient({
|
|
730
|
+
workspaceRoot,
|
|
731
|
+
branch: currentBranch,
|
|
732
|
+
timeout: 120_000,
|
|
733
|
+
});
|
|
734
|
+
const engineProlog = engine;
|
|
735
|
+
try {
|
|
736
|
+
await engine.start();
|
|
737
|
+
const successfulChangedSources = [
|
|
738
|
+
...changedMarkdownFiles,
|
|
739
|
+
...changedManifestFiles,
|
|
740
|
+
].filter((file) => !failedCacheKeys.has(toCacheKey(workspaceRoot, file)));
|
|
741
|
+
const removedCount = useEntityDelta
|
|
742
|
+
? await retractEntitiesById(engineProlog, [...removedEntityIds])
|
|
743
|
+
: await retractEntitiesForSources(engineProlog, [
|
|
744
|
+
...successfulChangedSources,
|
|
745
|
+
...deletedSourceFiles,
|
|
746
|
+
]);
|
|
747
|
+
if (useEntityDelta) {
|
|
748
|
+
await retractEntityRelationshipsById(engineProlog, [
|
|
749
|
+
...changedEntityIds,
|
|
750
|
+
]);
|
|
751
|
+
const exactRemovedEdges = removedShardRelationships.filter((relationship) => !removedEntityIds.has(relationship.from) &&
|
|
752
|
+
!removedEntityIds.has(relationship.to) &&
|
|
753
|
+
!changedEntityIds.has(relationship.from));
|
|
754
|
+
await retractRelationships(engineProlog, exactRemovedEdges);
|
|
755
|
+
}
|
|
756
|
+
else if (relationshipChanged) {
|
|
757
|
+
const cleared = await engine.query("kb_retract_all_relationships");
|
|
758
|
+
if (!cleared.success) {
|
|
759
|
+
throw new SyncError(`Failed to clear changed relationship shards: ${cleared.error || "Unknown error"}`);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
const entityIds = new Set();
|
|
763
|
+
for (const { entity } of results) {
|
|
764
|
+
entityCounts[entity.type] = (entityCounts[entity.type] || 0) + 1;
|
|
765
|
+
}
|
|
766
|
+
const { entityCount, kbModified: entitiesModified } = await persistEntities(engineProlog, results, entityIds, {
|
|
767
|
+
loadExistingEntityIds: !useEntityDelta,
|
|
768
|
+
});
|
|
769
|
+
const validationErrors = useEntityDelta
|
|
770
|
+
? []
|
|
771
|
+
: validateRelationships(allRelationships, entityIds);
|
|
772
|
+
if (validationErrors.length > 0) {
|
|
773
|
+
console.warn(`Warning: ${validationErrors.length} dangling relationship(s) found`);
|
|
774
|
+
}
|
|
775
|
+
const danglingKeys = new Set(validationErrors.map(({ relationship }) => `${relationship.type}|${relationship.from}|${relationship.to}`));
|
|
776
|
+
const shardDeltaByKey = new Map();
|
|
777
|
+
const shardCandidates = useEntityDelta && !materializeAllRelationships
|
|
778
|
+
? [
|
|
779
|
+
...addedShardRelationships,
|
|
780
|
+
...allRelationships.filter((relationship) => changedEntityIds.has(relationship.from)),
|
|
781
|
+
]
|
|
782
|
+
: allRelationships;
|
|
783
|
+
for (const relationship of shardCandidates) {
|
|
784
|
+
if (!danglingKeys.has(`${relationship.type}|${relationship.from}|${relationship.to}`)) {
|
|
785
|
+
shardDeltaByKey.set(relationshipKey(relationship), relationship);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
const { relationshipCount, kbModified: relationshipsModified } = await persistRelationships(engineProlog, results, [
|
|
789
|
+
...shardDeltaByKey.values(),
|
|
790
|
+
]);
|
|
791
|
+
const kbModified = removedCount > 0 ||
|
|
792
|
+
relationshipChanged ||
|
|
793
|
+
entitiesModified ||
|
|
794
|
+
relationshipsModified;
|
|
795
|
+
if (kbModified)
|
|
796
|
+
engine.invalidateCache();
|
|
797
|
+
const saveResult = await engine.save();
|
|
798
|
+
if (!saveResult.success) {
|
|
799
|
+
throw new SyncError(`Failed to save journaled KB: ${saveResult.error || "Unknown error"}`);
|
|
800
|
+
}
|
|
801
|
+
const evictedHashes = {};
|
|
802
|
+
const evictedSeenAt = {};
|
|
803
|
+
const evictedSemanticHashes = {};
|
|
804
|
+
const evictedSemanticContracts = {};
|
|
805
|
+
for (const [key, hash] of Object.entries(nextHashes)) {
|
|
806
|
+
if (failedCacheKeys.has(key))
|
|
807
|
+
continue;
|
|
808
|
+
evictedHashes[key] = hash;
|
|
809
|
+
evictedSeenAt[key] = nextSeenAt[key] ?? nowIso;
|
|
810
|
+
if (nextSemanticHashes[key] !== undefined) {
|
|
811
|
+
evictedSemanticHashes[key] = nextSemanticHashes[key];
|
|
812
|
+
evictedSemanticContracts[key] = nextSemanticContracts[key] === true;
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
writeSyncCache(path.join(livePath, "sync-cache.json"), {
|
|
816
|
+
version: SYNC_CACHE_VERSION,
|
|
817
|
+
hashes: evictedHashes,
|
|
818
|
+
relationshipHashes: nextRelationshipHashes,
|
|
819
|
+
entityHashes: nextEntityHashes,
|
|
820
|
+
sourceEntityIds: nextSourceEntityIds,
|
|
821
|
+
shardRelationships: nextShardRelationships,
|
|
822
|
+
seenAt: evictedSeenAt,
|
|
823
|
+
semanticHashes: evictedSemanticHashes,
|
|
824
|
+
semanticContracts: evictedSemanticContracts,
|
|
825
|
+
});
|
|
826
|
+
published = true;
|
|
827
|
+
if (performedFullReindex &&
|
|
828
|
+
markdownFiles.length > 0 &&
|
|
829
|
+
entityCount < markdownFiles.length) {
|
|
830
|
+
diagnostics.push(createDocsNotIndexedDiagnostic(markdownFiles.length, entityCount));
|
|
831
|
+
}
|
|
832
|
+
console.log(`✓ Imported ${entityCount} entities, ${relationshipCount} relationships (removed ${removedCount} entities)`);
|
|
833
|
+
const commit = getCurrentCommit();
|
|
834
|
+
const summary = withOptionalCommit({
|
|
835
|
+
branch: currentBranch,
|
|
836
|
+
timestamp: new Date().toISOString(),
|
|
837
|
+
entityCounts,
|
|
838
|
+
relationshipCount,
|
|
839
|
+
success: true,
|
|
840
|
+
published,
|
|
841
|
+
failures: diagnostics,
|
|
842
|
+
durationMs: Date.now() - startTime,
|
|
843
|
+
}, commit);
|
|
844
|
+
console.log(formatSyncSummary(summary));
|
|
845
|
+
return { ...summary, exitCode: 0 };
|
|
846
|
+
}
|
|
847
|
+
finally {
|
|
848
|
+
await engine.terminate();
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
stagingPath = createUniqueStagingPath(currentBranch, workspaceRoot);
|
|
257
852
|
const runtimeContext = {
|
|
258
853
|
currentBranch,
|
|
259
854
|
livePath,
|
|
@@ -262,6 +857,12 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
262
857
|
validateOnly,
|
|
263
858
|
};
|
|
264
859
|
await prepareStagingEnvironment(stagingPath, livePath, rebuild);
|
|
860
|
+
// Staging is a new compiled artifact, so install the exact identity fence
|
|
861
|
+
// before the engine attaches. The manifest is published with the staged
|
|
862
|
+
// store during the atomic swap.
|
|
863
|
+
if (!existsSync(branchStoreManifestPath(stagingPath))) {
|
|
864
|
+
writeFileSync(branchStoreManifestPath(stagingPath), `${JSON.stringify(expectedBranchStoreManifest(currentBranch), null, 2)}\n`, { mode: 0o600 });
|
|
865
|
+
}
|
|
265
866
|
try {
|
|
266
867
|
const prolog = runtime.createProlog?.({ timeout: 120000 }) ??
|
|
267
868
|
new PrologProcess({ timeout: 120000 });
|
|
@@ -276,6 +877,20 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
276
877
|
for (const { entity } of results) {
|
|
277
878
|
entityCounts[entity.type] = (entityCounts[entity.type] || 0) + 1;
|
|
278
879
|
}
|
|
880
|
+
// A copied generation retains entities from old source contents. Remove
|
|
881
|
+
// only successfully extracted/deleted sources before applying the new
|
|
882
|
+
// entities; failed extraction deliberately leaves the previous data.
|
|
883
|
+
await retractEntitiesForSources(prolog, [
|
|
884
|
+
...changedMarkdownFiles,
|
|
885
|
+
...changedManifestFiles,
|
|
886
|
+
...deletedSourceFiles,
|
|
887
|
+
].filter((file) => !failedCacheKeys.has(toCacheKey(workspaceRoot, file))));
|
|
888
|
+
if (relationshipChanged) {
|
|
889
|
+
const clearRelationships = await prolog.query("kb_retract_all_relationships");
|
|
890
|
+
if (!clearRelationships.success) {
|
|
891
|
+
throw new SyncError(`Failed to clear changed relationship shards: ${clearRelationships.error || "Unknown error"}`);
|
|
892
|
+
}
|
|
893
|
+
}
|
|
279
894
|
const { entityCount, kbModified: entitiesModified } = await persistEntities(prolog, results, entityIds);
|
|
280
895
|
const validationErrors = validateRelationships(allRelationships, entityIds);
|
|
281
896
|
if (validationErrors.length > 0) {
|
|
@@ -333,8 +948,46 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
333
948
|
}
|
|
334
949
|
await prolog.query("kb_detach");
|
|
335
950
|
await prolog.terminate();
|
|
336
|
-
|
|
337
|
-
|
|
951
|
+
const journaledLive = existsSync(path.join(livePath, "storage.json"));
|
|
952
|
+
if (recoveryBackupPath !== undefined) {
|
|
953
|
+
if (!existsSync(livePath)) {
|
|
954
|
+
throw new SyncError(`Recovery target disappeared before publication: ${livePath}`);
|
|
955
|
+
}
|
|
956
|
+
if (existsSync(recoveryBackupPath)) {
|
|
957
|
+
throw new SyncError(`Recovery backup path already exists: ${recoveryBackupPath}`);
|
|
958
|
+
}
|
|
959
|
+
mkdirSync(path.dirname(recoveryBackupPath), { recursive: true });
|
|
960
|
+
// Same-filesystem renames give us a recoverable two-step publication:
|
|
961
|
+
// the original bytes stay at the reported backup path if anything
|
|
962
|
+
// later needs forensic inspection.
|
|
963
|
+
renameSync(livePath, recoveryBackupPath);
|
|
964
|
+
try {
|
|
965
|
+
renameSync(stagingPath, livePath);
|
|
966
|
+
}
|
|
967
|
+
catch (error) {
|
|
968
|
+
renameSync(recoveryBackupPath, livePath);
|
|
969
|
+
throw error;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
else if (rebuild && journaledLive) {
|
|
973
|
+
atomicPublishGeneration(stagingPath, livePath);
|
|
974
|
+
}
|
|
975
|
+
else {
|
|
976
|
+
atomicPublish(stagingPath, livePath);
|
|
977
|
+
}
|
|
978
|
+
fsyncJournaledBranchStore(livePath);
|
|
979
|
+
try {
|
|
980
|
+
if (recoveryBackupPath !== undefined &&
|
|
981
|
+
recoveredPendingReceiptPaths.length > 0) {
|
|
982
|
+
clearRecoveredPendingSourceReceipts(workspaceRoot, recoveredPendingReceiptPaths);
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
finally {
|
|
986
|
+
// Receipt compare-and-delete can fail closed after publication when a
|
|
987
|
+
// newer receipt wins a race. Staging bytes are still disposable;
|
|
988
|
+
// leave the published store and surface the pending intent error.
|
|
989
|
+
cleanupStaging(stagingPath);
|
|
990
|
+
}
|
|
338
991
|
const evictedHashes = {};
|
|
339
992
|
const evictedSeenAt = {};
|
|
340
993
|
const evictedSemanticHashes = {};
|
|
@@ -354,6 +1007,10 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
354
1007
|
writeSyncCache(liveCachePath, {
|
|
355
1008
|
version: SYNC_CACHE_VERSION,
|
|
356
1009
|
hashes: evictedHashes,
|
|
1010
|
+
relationshipHashes: nextRelationshipHashes,
|
|
1011
|
+
entityHashes: nextEntityHashes,
|
|
1012
|
+
sourceEntityIds: nextSourceEntityIds,
|
|
1013
|
+
shardRelationships: nextShardRelationships,
|
|
357
1014
|
seenAt: evictedSeenAt,
|
|
358
1015
|
semanticHashes: evictedSemanticHashes,
|
|
359
1016
|
semanticContracts: evictedSemanticContracts,
|
|
@@ -385,6 +1042,7 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
385
1042
|
}
|
|
386
1043
|
}
|
|
387
1044
|
catch (error) {
|
|
1045
|
+
operationFailure = { error };
|
|
388
1046
|
if (stagingPath) {
|
|
389
1047
|
cleanupStaging(stagingPath);
|
|
390
1048
|
}
|
|
@@ -409,5 +1067,9 @@ export async function syncCommand(options = {}, runtime = {}) {
|
|
|
409
1067
|
}
|
|
410
1068
|
throw error;
|
|
411
1069
|
}
|
|
1070
|
+
finally {
|
|
1071
|
+
publicationLease?.release();
|
|
1072
|
+
releaseSymbolCompilerLock(compilerLock, operationFailure);
|
|
1073
|
+
}
|
|
412
1074
|
}
|
|
413
1075
|
export { normalizeMarkdownPath } from "./sync/discovery.js";
|