helixevo 0.5.0 → 0.6.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/CHANGELOG.md +15 -0
- package/README.md +10 -7
- package/dashboard/app/coevolution/client.tsx +21 -1
- package/dashboard/app/commands/page.tsx +63 -9
- package/dashboard/app/guide/page.tsx +68 -9
- package/dashboard/app/ontology/client.tsx +57 -9
- package/dashboard/app/page.tsx +10 -0
- package/dashboard/app/topology/client.tsx +3 -0
- package/dashboard/components/sidebar-nav.tsx +9 -5
- package/dashboard/lib/data.ts +631 -52
- package/dist/cli.js +528 -49
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -10024,6 +10024,7 @@ function refreshTopologyReviewCandidates() {
|
|
|
10024
10024
|
}
|
|
10025
10025
|
function loadResolvedTopologyReviewCandidates() {
|
|
10026
10026
|
const candidates = loadStoredTopologyReviewCandidates();
|
|
10027
|
+
const concepts = activeOntologyExtensions();
|
|
10027
10028
|
const latestDecisionByCandidate = new Map;
|
|
10028
10029
|
for (const decision of loadTopologyReviewDecisions()) {
|
|
10029
10030
|
const existing = latestDecisionByCandidate.get(decision.candidateId);
|
|
@@ -10034,10 +10035,18 @@ function loadResolvedTopologyReviewCandidates() {
|
|
|
10034
10035
|
return candidates.map((candidate) => {
|
|
10035
10036
|
const latestDecision = latestDecisionByCandidate.get(candidate.id);
|
|
10036
10037
|
const status = latestDecision?.decision ?? "open";
|
|
10038
|
+
const semanticBindings = matchTopologyOntologyBindings({
|
|
10039
|
+
...candidate,
|
|
10040
|
+
status,
|
|
10041
|
+
latestDecision,
|
|
10042
|
+
lastActivityAt: maxTimestamp(candidate.lastObservedAt, latestDecision?.decidedAt)
|
|
10043
|
+
}, concepts);
|
|
10037
10044
|
return {
|
|
10038
10045
|
...candidate,
|
|
10039
10046
|
status,
|
|
10040
10047
|
latestDecision,
|
|
10048
|
+
semanticBindings,
|
|
10049
|
+
semanticConceptIds: uniqueStrings(semanticBindings.map((binding) => binding.conceptId)),
|
|
10041
10050
|
lastActivityAt: maxTimestamp(candidate.lastObservedAt, latestDecision?.decidedAt)
|
|
10042
10051
|
};
|
|
10043
10052
|
}).sort((a, b) => topologyStatusRank(b.status) - topologyStatusRank(a.status) || priorityRank(b.priority) - priorityRank(a.priority) || b.confidence - a.confidence || b.lastActivityAt.localeCompare(a.lastActivityAt) || a.title.localeCompare(b.title));
|
|
@@ -10450,6 +10459,7 @@ function deprecateOntologyExtension(params) {
|
|
|
10450
10459
|
if (!current)
|
|
10451
10460
|
return null;
|
|
10452
10461
|
const governance = getActiveGovernanceSummary();
|
|
10462
|
+
const adoption = loadResolvedOntologyExtensions().find((entry) => entry.id === params.conceptId);
|
|
10453
10463
|
const deprecated = {
|
|
10454
10464
|
...current,
|
|
10455
10465
|
status: "deprecated",
|
|
@@ -10459,12 +10469,13 @@ function deprecateOntologyExtension(params) {
|
|
|
10459
10469
|
deprecated,
|
|
10460
10470
|
...extensions.filter((entry) => entry.id !== params.conceptId)
|
|
10461
10471
|
]);
|
|
10472
|
+
const consumerWarning = adoption && adoption.adoptionCount > 0 ? ` Warning: ${adoption.adoptionCount} active semantic consumer${adoption.adoptionCount === 1 ? "" : "s"} were visible before deprecation.` : "";
|
|
10462
10473
|
appendOntologyChangeEvent({
|
|
10463
10474
|
id: `ontology_change_deprecated_${slugFragment(current.id)}_${Date.now()}`,
|
|
10464
10475
|
timestamp: new Date().toISOString(),
|
|
10465
10476
|
changeType: "concept-deprecated",
|
|
10466
10477
|
conceptIds: [current.id],
|
|
10467
|
-
reason: params.rationale.trim() || `Deprecated ontology extension ${current.name}
|
|
10478
|
+
reason: (params.rationale.trim() || `Deprecated ontology extension ${current.name}`) + consumerWarning,
|
|
10468
10479
|
evidenceIds: current.evidenceIds,
|
|
10469
10480
|
approvedBy: "operator",
|
|
10470
10481
|
ontologyVersion: ONTOLOGY_SPEC_VERSION
|
|
@@ -10473,19 +10484,37 @@ function deprecateOntologyExtension(params) {
|
|
|
10473
10484
|
concept: deprecated,
|
|
10474
10485
|
operation: "deprecate",
|
|
10475
10486
|
sourceId: `${current.id}:deprecate`,
|
|
10476
|
-
summary: `Deprecated ontology extension ${deprecated.name} under ${governance.activeMode} governance
|
|
10487
|
+
summary: `Deprecated ontology extension ${deprecated.name} under ${governance.activeMode} governance.${consumerWarning}`,
|
|
10477
10488
|
metrics: {
|
|
10478
10489
|
observations: deprecated.observationCount ?? 0,
|
|
10479
|
-
confidence: deprecated.confidence ?? 0
|
|
10490
|
+
confidence: deprecated.confidence ?? 0,
|
|
10491
|
+
adoptionCount: adoption?.adoptionCount ?? 0
|
|
10480
10492
|
}
|
|
10481
10493
|
});
|
|
10482
|
-
|
|
10494
|
+
const resolved = loadResolvedOntologyExtensions().find((entry) => entry.id === params.conceptId);
|
|
10495
|
+
if (resolved) {
|
|
10496
|
+
return {
|
|
10497
|
+
...resolved,
|
|
10498
|
+
warning: consumerWarning.trim() || resolved.warning,
|
|
10499
|
+
adoptionCount: adoption?.adoptionCount ?? resolved.adoptionCount
|
|
10500
|
+
};
|
|
10501
|
+
}
|
|
10502
|
+
return {
|
|
10503
|
+
...deprecated,
|
|
10504
|
+
semanticBindings: [],
|
|
10505
|
+
adoptionCount: adoption?.adoptionCount ?? 0,
|
|
10506
|
+
bindingsByTargetType: adoption?.bindingsByTargetType ?? emptyOntologyBindingCounts(),
|
|
10507
|
+
lastActivityAt: deprecated.lastObservedAt ?? deprecated.createdAt,
|
|
10508
|
+
warning: consumerWarning.trim() || undefined
|
|
10509
|
+
};
|
|
10483
10510
|
}
|
|
10484
10511
|
function getOntologyReviewSummary() {
|
|
10485
10512
|
const kernel = loadOntologyKernelSnapshot();
|
|
10486
10513
|
const extensions = loadOntologyExtensions();
|
|
10514
|
+
const resolvedExtensions = loadResolvedOntologyExtensions();
|
|
10487
10515
|
const frontier = loadResolvedOntologyFrontierConcepts();
|
|
10488
10516
|
const changeEvents = loadOntologyChangeEvents();
|
|
10517
|
+
const adoption = getOntologyAdoptionSummary();
|
|
10489
10518
|
const byConceptKind = ontologyKindCounts();
|
|
10490
10519
|
for (const concept of [...extensions, ...frontier]) {
|
|
10491
10520
|
byConceptKind[concept.conceptKind] = (byConceptKind[concept.conceptKind] ?? 0) + 1;
|
|
@@ -10501,9 +10530,10 @@ function getOntologyReviewSummary() {
|
|
|
10501
10530
|
deprecated: extensions.filter((concept) => concept.status === "deprecated").length,
|
|
10502
10531
|
changeEvents: changeEvents.length,
|
|
10503
10532
|
byConceptKind,
|
|
10533
|
+
adoption,
|
|
10504
10534
|
backlog: frontier.filter((concept) => concept.reviewStatus === "open" || concept.reviewStatus === "deferred").slice(0, 10),
|
|
10505
10535
|
recentChanges: changeEvents.slice(0, 10),
|
|
10506
|
-
recentExtensions:
|
|
10536
|
+
recentExtensions: resolvedExtensions.slice(0, 8)
|
|
10507
10537
|
};
|
|
10508
10538
|
}
|
|
10509
10539
|
function buildDerivedEvolutionArtifact(iteration, proposal) {
|
|
@@ -10629,7 +10659,15 @@ function loadPressureInterventions() {
|
|
|
10629
10659
|
return loadNativePressureInterventions().slice().sort((a, b) => (b.completedAt ?? b.createdAt).localeCompare(a.completedAt ?? a.createdAt));
|
|
10630
10660
|
}
|
|
10631
10661
|
function loadTransferEvents() {
|
|
10632
|
-
|
|
10662
|
+
const concepts = activeOntologyExtensions();
|
|
10663
|
+
return loadNativeTransferEvents().slice().map((event) => {
|
|
10664
|
+
const semanticBindings = matchTransferOntologyBindings(event, concepts);
|
|
10665
|
+
return {
|
|
10666
|
+
...event,
|
|
10667
|
+
semanticBindings,
|
|
10668
|
+
semanticConceptIds: uniqueStrings(semanticBindings.map((binding) => binding.conceptId))
|
|
10669
|
+
};
|
|
10670
|
+
}).sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
10633
10671
|
}
|
|
10634
10672
|
function normalizePressureValue(value) {
|
|
10635
10673
|
return (value ?? "").trim().toLowerCase().replace(/[\s_/]+/g, "-");
|
|
@@ -10764,16 +10802,301 @@ function deriveGovernanceSummary(pressureSignals = loadPressureSignals(), interv
|
|
|
10764
10802
|
function getActiveGovernanceSummary() {
|
|
10765
10803
|
return deriveGovernanceSummary();
|
|
10766
10804
|
}
|
|
10805
|
+
function emptyOntologyBindingCounts() {
|
|
10806
|
+
return {};
|
|
10807
|
+
}
|
|
10808
|
+
function ontologyReviewKeyBody(reviewKey) {
|
|
10809
|
+
return normalizePressureValue((reviewKey ?? "").split(":").slice(1).join("-"));
|
|
10810
|
+
}
|
|
10811
|
+
function ontologyMotifTerm(motifId) {
|
|
10812
|
+
return normalizePressureValue(motifId.replace(/^motif_/, ""));
|
|
10813
|
+
}
|
|
10814
|
+
function ontologyConceptTerms(concept) {
|
|
10815
|
+
return uniqueStrings([
|
|
10816
|
+
normalizePressureValue(concept.name),
|
|
10817
|
+
...(concept.aliases ?? []).map((alias) => normalizePressureValue(alias)),
|
|
10818
|
+
normalizePressureValue(concept.reviewKey),
|
|
10819
|
+
ontologyReviewKeyBody(concept.reviewKey),
|
|
10820
|
+
...(concept.relatedMotifIds ?? []).map((id) => ontologyMotifTerm(id)),
|
|
10821
|
+
...(concept.derivedFromKinds ?? []).map((value) => normalizePressureValue(value))
|
|
10822
|
+
].filter(Boolean));
|
|
10823
|
+
}
|
|
10824
|
+
function ontologyBindingId(conceptId, targetType, targetId, sourceKind) {
|
|
10825
|
+
return `ontology_binding_${slugFragment(conceptId)}_${targetType}_${slugFragment(targetId)}_${sourceKind}`;
|
|
10826
|
+
}
|
|
10827
|
+
function buildOntologyBinding(params) {
|
|
10828
|
+
return {
|
|
10829
|
+
id: ontologyBindingId(params.concept.id, params.targetType, params.targetId, params.sourceKind),
|
|
10830
|
+
conceptId: params.concept.id,
|
|
10831
|
+
conceptName: params.concept.name,
|
|
10832
|
+
conceptKind: params.concept.conceptKind,
|
|
10833
|
+
targetType: params.targetType,
|
|
10834
|
+
targetId: params.targetId,
|
|
10835
|
+
sourceKind: params.sourceKind,
|
|
10836
|
+
confidence: Math.min(0.95, Math.max(0.5, params.confidence)),
|
|
10837
|
+
reasons: params.reasons,
|
|
10838
|
+
effectSummary: params.effectSummary
|
|
10839
|
+
};
|
|
10840
|
+
}
|
|
10841
|
+
function dedupeOntologyBindings(bindings) {
|
|
10842
|
+
const byKey = new Map;
|
|
10843
|
+
for (const binding of bindings) {
|
|
10844
|
+
const key = `${binding.conceptId}::${binding.targetType}::${binding.targetId}`;
|
|
10845
|
+
const existing = byKey.get(key);
|
|
10846
|
+
if (!existing || binding.confidence > existing.confidence)
|
|
10847
|
+
byKey.set(key, binding);
|
|
10848
|
+
}
|
|
10849
|
+
return [...byKey.values()].sort((a, b) => b.confidence - a.confidence || a.conceptName.localeCompare(b.conceptName)).slice(0, 4);
|
|
10850
|
+
}
|
|
10851
|
+
function activeOntologyExtensions() {
|
|
10852
|
+
return loadOntologyExtensions().filter((concept) => concept.status === "active");
|
|
10853
|
+
}
|
|
10854
|
+
function matchSignalOntologyBindings(signal, motifIds, concepts) {
|
|
10855
|
+
const capability = normalizePressureValue(signal.capability);
|
|
10856
|
+
const region = normalizePressureValue(signal.region);
|
|
10857
|
+
const kind = normalizePressureValue(signal.kind);
|
|
10858
|
+
const motifTerms = uniqueStrings(motifIds.map((id) => ontologyMotifTerm(id)).filter(Boolean));
|
|
10859
|
+
const bindings = [];
|
|
10860
|
+
for (const concept of concepts) {
|
|
10861
|
+
const terms = ontologyConceptTerms(concept);
|
|
10862
|
+
if (concept.conceptKind === "capability") {
|
|
10863
|
+
if (capability && terms.includes(capability)) {
|
|
10864
|
+
bindings.push(buildOntologyBinding({
|
|
10865
|
+
concept,
|
|
10866
|
+
targetType: "pressure-signal",
|
|
10867
|
+
targetId: signal.id,
|
|
10868
|
+
sourceKind: "capability-match",
|
|
10869
|
+
confidence: 0.86,
|
|
10870
|
+
reasons: [`Signal capability ${signal.capability} matches approved capability concept ${concept.name}.`],
|
|
10871
|
+
effectSummary: "Sharpens project or capability interpretation for this pressure signal."
|
|
10872
|
+
}));
|
|
10873
|
+
continue;
|
|
10874
|
+
}
|
|
10875
|
+
if (region && terms.includes(region)) {
|
|
10876
|
+
bindings.push(buildOntologyBinding({
|
|
10877
|
+
concept,
|
|
10878
|
+
targetType: "pressure-signal",
|
|
10879
|
+
targetId: signal.id,
|
|
10880
|
+
sourceKind: "pressure-region",
|
|
10881
|
+
confidence: 0.74,
|
|
10882
|
+
reasons: [`Signal region ${signal.region} aligns with approved capability concept ${concept.name}.`],
|
|
10883
|
+
effectSummary: "Adds semantic coverage to a recurring pressure region."
|
|
10884
|
+
}));
|
|
10885
|
+
}
|
|
10886
|
+
continue;
|
|
10887
|
+
}
|
|
10888
|
+
if (concept.conceptKind === "pressure-type") {
|
|
10889
|
+
if ((concept.relatedMotifIds ?? []).some((id) => motifIds.includes(id))) {
|
|
10890
|
+
bindings.push(buildOntologyBinding({
|
|
10891
|
+
concept,
|
|
10892
|
+
targetType: "pressure-signal",
|
|
10893
|
+
targetId: signal.id,
|
|
10894
|
+
sourceKind: "motif-match",
|
|
10895
|
+
confidence: 0.9,
|
|
10896
|
+
reasons: [`Signal participates in approved motif family ${concept.name}.`],
|
|
10897
|
+
effectSummary: "Marks this signal as part of an approved recurring pressure family."
|
|
10898
|
+
}));
|
|
10899
|
+
continue;
|
|
10900
|
+
}
|
|
10901
|
+
if (motifTerms.some((term) => terms.includes(term))) {
|
|
10902
|
+
bindings.push(buildOntologyBinding({
|
|
10903
|
+
concept,
|
|
10904
|
+
targetType: "pressure-signal",
|
|
10905
|
+
targetId: signal.id,
|
|
10906
|
+
sourceKind: "motif-match",
|
|
10907
|
+
confidence: 0.84,
|
|
10908
|
+
reasons: [`Signal motif region aligns with approved pressure family ${concept.name}.`],
|
|
10909
|
+
effectSummary: "Carries an approved recurring pressure family into live signal interpretation."
|
|
10910
|
+
}));
|
|
10911
|
+
continue;
|
|
10912
|
+
}
|
|
10913
|
+
if (kind && terms.includes(kind)) {
|
|
10914
|
+
bindings.push(buildOntologyBinding({
|
|
10915
|
+
concept,
|
|
10916
|
+
targetType: "pressure-signal",
|
|
10917
|
+
targetId: signal.id,
|
|
10918
|
+
sourceKind: "pressure-region",
|
|
10919
|
+
confidence: 0.78,
|
|
10920
|
+
reasons: [`Signal kind ${signal.kind} matches approved pressure family ${concept.name}.`],
|
|
10921
|
+
effectSummary: "Adds semantic identity to recurring pressure of the same kind."
|
|
10922
|
+
}));
|
|
10923
|
+
}
|
|
10924
|
+
}
|
|
10925
|
+
}
|
|
10926
|
+
return dedupeOntologyBindings(bindings);
|
|
10927
|
+
}
|
|
10928
|
+
function matchMotifOntologyBindings(motif, concepts) {
|
|
10929
|
+
const capability = normalizePressureValue(motif.capability);
|
|
10930
|
+
const key = normalizePressureValue(motif.key);
|
|
10931
|
+
const kind = normalizePressureValue(motif.kind);
|
|
10932
|
+
const bindings = [];
|
|
10933
|
+
for (const concept of concepts) {
|
|
10934
|
+
const terms = ontologyConceptTerms(concept);
|
|
10935
|
+
if (concept.conceptKind === "capability" && capability && terms.includes(capability)) {
|
|
10936
|
+
bindings.push(buildOntologyBinding({
|
|
10937
|
+
concept,
|
|
10938
|
+
targetType: "pressure-motif",
|
|
10939
|
+
targetId: motif.id,
|
|
10940
|
+
sourceKind: "capability-match",
|
|
10941
|
+
confidence: 0.84,
|
|
10942
|
+
reasons: [`Motif capability ${motif.capability} matches approved capability concept ${concept.name}.`],
|
|
10943
|
+
effectSummary: "Makes recurring capability pressure visible as semantic adoption."
|
|
10944
|
+
}));
|
|
10945
|
+
continue;
|
|
10946
|
+
}
|
|
10947
|
+
if (concept.conceptKind === "pressure-type") {
|
|
10948
|
+
if ((concept.relatedMotifIds ?? []).includes(motif.id)) {
|
|
10949
|
+
bindings.push(buildOntologyBinding({
|
|
10950
|
+
concept,
|
|
10951
|
+
targetType: "pressure-motif",
|
|
10952
|
+
targetId: motif.id,
|
|
10953
|
+
sourceKind: "motif-match",
|
|
10954
|
+
confidence: 0.92,
|
|
10955
|
+
reasons: [`Motif ${motif.key} directly matches approved pressure family ${concept.name}.`],
|
|
10956
|
+
effectSummary: "Confirms this recurring motif is an approved semantic family."
|
|
10957
|
+
}));
|
|
10958
|
+
continue;
|
|
10959
|
+
}
|
|
10960
|
+
if ([key, kind].filter(Boolean).some((value) => terms.includes(value))) {
|
|
10961
|
+
bindings.push(buildOntologyBinding({
|
|
10962
|
+
concept,
|
|
10963
|
+
targetType: "pressure-motif",
|
|
10964
|
+
targetId: motif.id,
|
|
10965
|
+
sourceKind: "pressure-region",
|
|
10966
|
+
confidence: 0.86,
|
|
10967
|
+
reasons: [`Motif identity aligns with approved pressure family ${concept.name}.`],
|
|
10968
|
+
effectSummary: "Carries approved semantic family identity into motif-level routing."
|
|
10969
|
+
}));
|
|
10970
|
+
}
|
|
10971
|
+
}
|
|
10972
|
+
}
|
|
10973
|
+
return dedupeOntologyBindings(bindings);
|
|
10974
|
+
}
|
|
10975
|
+
function matchTransferOntologyBindings(event, concepts) {
|
|
10976
|
+
const capabilityTerms = uniqueStrings((event.capabilityIds ?? []).map((value) => normalizePressureValue(value)).filter(Boolean));
|
|
10977
|
+
const motifTerms = uniqueStrings((event.motifIds ?? []).map((value) => ontologyMotifTerm(value)).filter(Boolean));
|
|
10978
|
+
const bindings = [];
|
|
10979
|
+
for (const concept of concepts) {
|
|
10980
|
+
const terms = ontologyConceptTerms(concept);
|
|
10981
|
+
if (concept.conceptKind === "capability" && capabilityTerms.some((value) => terms.includes(value))) {
|
|
10982
|
+
bindings.push(buildOntologyBinding({
|
|
10983
|
+
concept,
|
|
10984
|
+
targetType: "transfer-event",
|
|
10985
|
+
targetId: event.id,
|
|
10986
|
+
sourceKind: "capability-match",
|
|
10987
|
+
confidence: 0.82,
|
|
10988
|
+
reasons: [`Transfer capabilities align with approved concept ${concept.name}.`],
|
|
10989
|
+
effectSummary: "Shows semantic adoption through reusable transfer evidence."
|
|
10990
|
+
}));
|
|
10991
|
+
continue;
|
|
10992
|
+
}
|
|
10993
|
+
if (concept.conceptKind === "pressure-type") {
|
|
10994
|
+
if ((concept.relatedMotifIds ?? []).some((id) => (event.motifIds ?? []).includes(id))) {
|
|
10995
|
+
bindings.push(buildOntologyBinding({
|
|
10996
|
+
concept,
|
|
10997
|
+
targetType: "transfer-event",
|
|
10998
|
+
targetId: event.id,
|
|
10999
|
+
sourceKind: "transfer-motif",
|
|
11000
|
+
confidence: 0.88,
|
|
11001
|
+
reasons: [`Transfer realizes approved recurring family ${concept.name}.`],
|
|
11002
|
+
effectSummary: "Connects realized transfer evidence to an approved recurring pressure family."
|
|
11003
|
+
}));
|
|
11004
|
+
continue;
|
|
11005
|
+
}
|
|
11006
|
+
if (motifTerms.some((value) => terms.includes(value))) {
|
|
11007
|
+
bindings.push(buildOntologyBinding({
|
|
11008
|
+
concept,
|
|
11009
|
+
targetType: "transfer-event",
|
|
11010
|
+
targetId: event.id,
|
|
11011
|
+
sourceKind: "transfer-motif",
|
|
11012
|
+
confidence: 0.8,
|
|
11013
|
+
reasons: [`Transfer motif linkage aligns with approved family ${concept.name}.`],
|
|
11014
|
+
effectSummary: "Carries approved semantic family identity into realized transfer outcomes."
|
|
11015
|
+
}));
|
|
11016
|
+
}
|
|
11017
|
+
}
|
|
11018
|
+
}
|
|
11019
|
+
return dedupeOntologyBindings(bindings);
|
|
11020
|
+
}
|
|
11021
|
+
function matchTopologyOntologyBindings(candidate, concepts) {
|
|
11022
|
+
const descriptor = normalizePressureValue(topologyMotifDescriptor(candidate) ?? candidate.changeType);
|
|
11023
|
+
const bindings = [];
|
|
11024
|
+
for (const concept of concepts) {
|
|
11025
|
+
const terms = ontologyConceptTerms(concept);
|
|
11026
|
+
if (concept.conceptKind === "topology-motif" && descriptor && terms.includes(descriptor)) {
|
|
11027
|
+
bindings.push(buildOntologyBinding({
|
|
11028
|
+
concept,
|
|
11029
|
+
targetType: "topology-review",
|
|
11030
|
+
targetId: candidate.id,
|
|
11031
|
+
sourceKind: "topology-descriptor",
|
|
11032
|
+
confidence: 0.86,
|
|
11033
|
+
reasons: [`Topology review descriptor ${descriptor} aligns with approved topology concept ${concept.name}.`],
|
|
11034
|
+
effectSummary: "Adds semantic identity to recurring structural review patterns."
|
|
11035
|
+
}));
|
|
11036
|
+
continue;
|
|
11037
|
+
}
|
|
11038
|
+
if (concept.conceptKind === "pressure-type" && (concept.relatedMotifIds ?? []).some((id) => (candidate.relatedMotifIds ?? []).includes(id))) {
|
|
11039
|
+
bindings.push(buildOntologyBinding({
|
|
11040
|
+
concept,
|
|
11041
|
+
targetType: "topology-review",
|
|
11042
|
+
targetId: candidate.id,
|
|
11043
|
+
sourceKind: "motif-match",
|
|
11044
|
+
confidence: 0.72,
|
|
11045
|
+
reasons: [`Topology candidate inherits recurring pressure motif semantics from approved family ${concept.name}.`],
|
|
11046
|
+
effectSummary: "Links structural review back to an approved recurring pressure family."
|
|
11047
|
+
}));
|
|
11048
|
+
}
|
|
11049
|
+
}
|
|
11050
|
+
return dedupeOntologyBindings(bindings);
|
|
11051
|
+
}
|
|
11052
|
+
function applyOntologyInfluenceToRoute(params) {
|
|
11053
|
+
const { recommendation, signal, semanticBindings, governanceProfile } = params;
|
|
11054
|
+
if (semanticBindings.length === 0)
|
|
11055
|
+
return recommendation;
|
|
11056
|
+
const conceptIds = uniqueStrings(semanticBindings.map((binding) => binding.conceptId));
|
|
11057
|
+
const conceptNames = uniqueStrings(semanticBindings.map((binding) => binding.conceptName));
|
|
11058
|
+
const hasCapability = semanticBindings.some((binding) => binding.conceptKind === "capability");
|
|
11059
|
+
const hasPressureType = semanticBindings.some((binding) => binding.conceptKind === "pressure-type");
|
|
11060
|
+
const hasTopologyMotif = semanticBindings.some((binding) => binding.conceptKind === "topology-motif");
|
|
11061
|
+
const reasons = [...recommendation.reasons];
|
|
11062
|
+
let confidence = recommendation.confidence;
|
|
11063
|
+
let semanticInfluence = "explanatory";
|
|
11064
|
+
if (recommendation.route === "generalize" && hasPressureType && governanceProfile.riskTolerance >= 0.4 && governanceProfile.reviewThreshold <= 0.82) {
|
|
11065
|
+
confidence = Math.min(0.95, confidence + 0.04);
|
|
11066
|
+
semanticInfluence = "weighted";
|
|
11067
|
+
reasons.push(`Approved semantic family ${conceptNames.join(", ")} reinforces network-level reuse inside the current governance envelope.`);
|
|
11068
|
+
} else if (recommendation.route === "specialize" && hasCapability && signal.projectId && governanceProfile.reviewThreshold <= 0.86) {
|
|
11069
|
+
confidence = Math.min(0.95, confidence + 0.03);
|
|
11070
|
+
semanticInfluence = "weighted";
|
|
11071
|
+
reasons.push(`Approved capability concept ${conceptNames.join(", ")} sharpens project-bounded specialization without widening scope.`);
|
|
11072
|
+
} else if (recommendation.route === "evolve" && hasPressureType && signal.relatedFailureId) {
|
|
11073
|
+
confidence = Math.min(0.95, confidence + 0.02);
|
|
11074
|
+
semanticInfluence = "weighted";
|
|
11075
|
+
reasons.push(`Approved semantic family ${conceptNames.join(", ")} sharpens this failure-linked repair lane.`);
|
|
11076
|
+
} else if (recommendation.route === "manual-review" && (hasTopologyMotif || hasPressureType)) {
|
|
11077
|
+
reasons.push(`Approved semantic family ${conceptNames.join(", ")} confirms the pattern is real, but governance still prefers explicit operator review.`);
|
|
11078
|
+
} else {
|
|
11079
|
+
reasons.push(`Approved semantic family ${conceptNames.join(", ")} is visible here, but current governance/evidence still keeps the route bounded to ${recommendation.route}.`);
|
|
11080
|
+
}
|
|
11081
|
+
return {
|
|
11082
|
+
...recommendation,
|
|
11083
|
+
confidence,
|
|
11084
|
+
reasons,
|
|
11085
|
+
semanticInfluence,
|
|
11086
|
+
semanticConceptIds: conceptIds
|
|
11087
|
+
};
|
|
11088
|
+
}
|
|
10767
11089
|
function buildRouteRecommendation(params) {
|
|
10768
|
-
const { signal, relatedSignals, linkedInterventions, governanceMode } = params;
|
|
11090
|
+
const { signal, relatedSignals, linkedInterventions, governanceMode, governanceProfile, semanticBindings } = params;
|
|
10769
11091
|
const projectSpread = new Set(relatedSignals.map((entry) => entry.projectId ?? entry.projectPath).filter(Boolean)).size;
|
|
10770
11092
|
const recurrenceCount = relatedSignals.length;
|
|
10771
11093
|
const activeTypes = [...new Set(linkedInterventions.map((intervention) => intervention.interventionType))];
|
|
10772
11094
|
const reasons = [];
|
|
11095
|
+
let recommendation;
|
|
10773
11096
|
if (activeTypes.length >= 3 && !linkedInterventions.some((intervention) => intervention.status === "completed" && intervention.impact === "resolving")) {
|
|
10774
11097
|
reasons.push("Multiple intervention lanes already touch this pressure region without clear closure.");
|
|
10775
11098
|
reasons.push("Operator review is safer than blindly piling on another automated response.");
|
|
10776
|
-
|
|
11099
|
+
recommendation = {
|
|
10777
11100
|
route: "manual-review",
|
|
10778
11101
|
scope: projectSpread >= 2 ? "network" : signal.projectId ? "project" : "local",
|
|
10779
11102
|
confidence: 0.58,
|
|
@@ -10781,25 +11104,21 @@ function buildRouteRecommendation(params) {
|
|
|
10781
11104
|
triggeredBy: "mixed-signal",
|
|
10782
11105
|
reasons
|
|
10783
11106
|
};
|
|
10784
|
-
}
|
|
10785
|
-
if (projectSpread >= 2 && recurrenceCount >= 2) {
|
|
11107
|
+
} else if (projectSpread >= 2 && recurrenceCount >= 2 && governanceMode !== "project-critical") {
|
|
10786
11108
|
reasons.push(`This pressure region repeats across ${projectSpread} projects.`);
|
|
10787
11109
|
reasons.push("A network-level abstraction can absorb repeated local demand more efficiently than one-off fixes.");
|
|
10788
|
-
|
|
10789
|
-
|
|
10790
|
-
|
|
10791
|
-
|
|
10792
|
-
|
|
10793
|
-
|
|
10794
|
-
|
|
10795
|
-
|
|
10796
|
-
|
|
10797
|
-
}
|
|
10798
|
-
}
|
|
10799
|
-
if (signal.projectId && signal.priority === "high" && signal.suggestedAction === "specialize") {
|
|
11110
|
+
recommendation = {
|
|
11111
|
+
route: "generalize",
|
|
11112
|
+
scope: "network",
|
|
11113
|
+
confidence: Math.min(0.95, 0.7 + Math.min(0.15, (projectSpread - 1) * 0.08)),
|
|
11114
|
+
governanceMode,
|
|
11115
|
+
triggeredBy: "recurring-cross-project-gap",
|
|
11116
|
+
reasons
|
|
11117
|
+
};
|
|
11118
|
+
} else if (signal.projectId && signal.priority === "high" && signal.suggestedAction === "specialize") {
|
|
10800
11119
|
reasons.push("The pressure is high priority and bounded to a known project context.");
|
|
10801
11120
|
reasons.push("Project-layer adaptation is the shortest truthful path to response.");
|
|
10802
|
-
|
|
11121
|
+
recommendation = {
|
|
10803
11122
|
route: "specialize",
|
|
10804
11123
|
scope: "project",
|
|
10805
11124
|
confidence: 0.82,
|
|
@@ -10807,11 +11126,10 @@ function buildRouteRecommendation(params) {
|
|
|
10807
11126
|
triggeredBy: "high-priority-local-gap",
|
|
10808
11127
|
reasons
|
|
10809
11128
|
};
|
|
10810
|
-
}
|
|
10811
|
-
if (signal.relatedFailureId && signal.severity >= 0.8) {
|
|
11129
|
+
} else if (signal.relatedFailureId && signal.severity >= 0.8) {
|
|
10812
11130
|
reasons.push("This pressure is tied to a concrete failure with strong corrective evidence.");
|
|
10813
11131
|
reasons.push("An evolution proposal can test a direct skill-level response against replay and regression evidence.");
|
|
10814
|
-
|
|
11132
|
+
recommendation = {
|
|
10815
11133
|
route: "evolve",
|
|
10816
11134
|
scope: signal.projectId ? "project" : "local",
|
|
10817
11135
|
confidence: 0.78,
|
|
@@ -10819,11 +11137,10 @@ function buildRouteRecommendation(params) {
|
|
|
10819
11137
|
triggeredBy: "accepted-iteration-pattern",
|
|
10820
11138
|
reasons
|
|
10821
11139
|
};
|
|
10822
|
-
}
|
|
10823
|
-
if (governanceMode === "exploration" || signal.suggestedAction === "research" || !signal.projectId) {
|
|
11140
|
+
} else if (governanceMode === "exploration" || signal.suggestedAction === "research" || !signal.projectId) {
|
|
10824
11141
|
reasons.push("The pressure still looks under-specified or capability-oriented.");
|
|
10825
11142
|
reasons.push("Research is the best way to widen evidence before committing to structural change.");
|
|
10826
|
-
|
|
11143
|
+
recommendation = {
|
|
10827
11144
|
route: "research",
|
|
10828
11145
|
scope: signal.projectId ? "project" : "local",
|
|
10829
11146
|
confidence: 0.68,
|
|
@@ -10831,11 +11148,10 @@ function buildRouteRecommendation(params) {
|
|
|
10831
11148
|
triggeredBy: "insufficient-evidence",
|
|
10832
11149
|
reasons
|
|
10833
11150
|
};
|
|
10834
|
-
}
|
|
10835
|
-
if (signal.projectId) {
|
|
11151
|
+
} else if (signal.projectId) {
|
|
10836
11152
|
reasons.push("The pressure is project-scoped and can likely be handled without network-wide promotion yet.");
|
|
10837
11153
|
reasons.push("Specialization is the most direct bounded intervention available.");
|
|
10838
|
-
|
|
11154
|
+
recommendation = {
|
|
10839
11155
|
route: "specialize",
|
|
10840
11156
|
scope: "project",
|
|
10841
11157
|
confidence: 0.7,
|
|
@@ -10843,17 +11159,24 @@ function buildRouteRecommendation(params) {
|
|
|
10843
11159
|
triggeredBy: "project-bounded-recurrence",
|
|
10844
11160
|
reasons
|
|
10845
11161
|
};
|
|
11162
|
+
} else {
|
|
11163
|
+
reasons.push("No single route is dominant from the current evidence.");
|
|
11164
|
+
reasons.push("Research keeps the loop moving while preserving optionality.");
|
|
11165
|
+
recommendation = {
|
|
11166
|
+
route: "research",
|
|
11167
|
+
scope: "local",
|
|
11168
|
+
confidence: 0.6,
|
|
11169
|
+
governanceMode,
|
|
11170
|
+
triggeredBy: "insufficient-evidence",
|
|
11171
|
+
reasons
|
|
11172
|
+
};
|
|
10846
11173
|
}
|
|
10847
|
-
|
|
10848
|
-
|
|
10849
|
-
|
|
10850
|
-
|
|
10851
|
-
|
|
10852
|
-
|
|
10853
|
-
governanceMode,
|
|
10854
|
-
triggeredBy: "insufficient-evidence",
|
|
10855
|
-
reasons
|
|
10856
|
-
};
|
|
11174
|
+
return applyOntologyInfluenceToRoute({
|
|
11175
|
+
recommendation,
|
|
11176
|
+
signal,
|
|
11177
|
+
semanticBindings,
|
|
11178
|
+
governanceProfile
|
|
11179
|
+
});
|
|
10857
11180
|
}
|
|
10858
11181
|
function interventionEvidenceAccepted(intervention, acceptedProposalIds, acceptedArtifactIds, realizedTransferEventIds) {
|
|
10859
11182
|
if (intervention.status !== "completed" || intervention.impact !== "resolving")
|
|
@@ -10882,6 +11205,7 @@ function loadResolvedPressureSignals() {
|
|
|
10882
11205
|
const history = loadHistory();
|
|
10883
11206
|
const artifacts = loadEvolutionArtifacts();
|
|
10884
11207
|
const governance = deriveGovernanceSummary(pressureSignals, interventions);
|
|
11208
|
+
const concepts = activeOntologyExtensions();
|
|
10885
11209
|
const acceptedProposalIds = new Set(history.iterations.flatMap((iteration) => iteration.proposals).filter((proposal) => proposal.outcome === "accepted").map((proposal) => proposal.id));
|
|
10886
11210
|
const acceptedArtifactIds = new Set(artifacts.filter((artifact) => artifact.outcome === "accepted").map((artifact) => artifact.id));
|
|
10887
11211
|
const realizedTransferEventIds = new Set(transferEvents.filter((event) => event.status === "realized").map((event) => event.id));
|
|
@@ -10908,17 +11232,22 @@ function loadResolvedPressureSignals() {
|
|
|
10908
11232
|
const relatedSignals = signalsByRegion.get(pressureRegionKey(signal)) ?? [signal];
|
|
10909
11233
|
const projectSpread = new Set(relatedSignals.map((entry) => entry.projectId ?? entry.projectPath).filter(Boolean)).size;
|
|
10910
11234
|
const motifIds = relatedSignals.length >= 2 || projectSpread >= 2 ? [motifIdForSignal(signal)] : [];
|
|
11235
|
+
const semanticBindings = matchSignalOntologyBindings(signal, motifIds, concepts);
|
|
10911
11236
|
const routeRecommendation = buildRouteRecommendation({
|
|
10912
11237
|
signal,
|
|
10913
11238
|
relatedSignals,
|
|
10914
11239
|
linkedInterventions,
|
|
10915
|
-
governanceMode: governance.activeMode
|
|
11240
|
+
governanceMode: governance.activeMode,
|
|
11241
|
+
governanceProfile: governance.profile,
|
|
11242
|
+
semanticBindings
|
|
10916
11243
|
});
|
|
10917
11244
|
const lifecycle = addressingInterventions.length > 0 || signal.status === "addressed" ? "addressed" : activeInterventions.length > 0 ? "in-progress" : hasNewerEquivalentSignal ? "stale" : "open";
|
|
10918
11245
|
const lastActivityAt = [signal.detectedAt, latestInterventionAt].filter(Boolean).sort((a, b) => b.localeCompare(a))[0] ?? signal.detectedAt;
|
|
10919
11246
|
const interventionTypes = [...new Set(linkedInterventions.map((intervention) => intervention.interventionType))];
|
|
10920
11247
|
const addressedAt = addressingInterventions.map((intervention) => intervention.completedAt ?? intervention.createdAt).sort((a, b) => b.localeCompare(a))[0];
|
|
10921
|
-
const
|
|
11248
|
+
const semanticNames = uniqueStrings(semanticBindings.map((binding) => binding.conceptName));
|
|
11249
|
+
const semanticNote = semanticNames.length > 0 ? ` • semantic family ${semanticNames.join(", ")}` : "";
|
|
11250
|
+
const responseSummary = lifecycle === "addressed" ? `Addressed by ${interventionTypes.join(", ") || "linked intervention"} evidence${semanticNote}` : lifecycle === "in-progress" ? `Response underway via ${interventionTypes.join(", ")}${semanticNote}` : lifecycle === "stale" ? "Superseded by newer pressure in the same project/capability region" : `No linked response yet • recommend ${routeRecommendation.route}${semanticNote}`;
|
|
10922
11251
|
return {
|
|
10923
11252
|
...signal,
|
|
10924
11253
|
lifecycle,
|
|
@@ -10926,6 +11255,8 @@ function loadResolvedPressureSignals() {
|
|
|
10926
11255
|
interventionTypes,
|
|
10927
11256
|
motifIds,
|
|
10928
11257
|
routeRecommendation,
|
|
11258
|
+
semanticBindings,
|
|
11259
|
+
semanticConceptIds: uniqueStrings(semanticBindings.map((binding) => binding.conceptId)),
|
|
10929
11260
|
lastActivityAt,
|
|
10930
11261
|
addressedAt,
|
|
10931
11262
|
responseSummary
|
|
@@ -10936,6 +11267,7 @@ function loadPressureMotifs() {
|
|
|
10936
11267
|
const resolvedSignals = loadResolvedPressureSignals();
|
|
10937
11268
|
const interventions = loadPressureInterventions();
|
|
10938
11269
|
const transferEvents = loadTransferEvents();
|
|
11270
|
+
const concepts = activeOntologyExtensions();
|
|
10939
11271
|
const groups = new Map;
|
|
10940
11272
|
for (const signal of resolvedSignals) {
|
|
10941
11273
|
const regionKey = pressureRegionKey(signal);
|
|
@@ -10980,7 +11312,15 @@ function loadPressureMotifs() {
|
|
|
10980
11312
|
const linkedInterventionIds = linkedInterventions.map((intervention) => intervention.id);
|
|
10981
11313
|
const linkedTransferEventIds = linkedTransferEvents.map((event) => event.id);
|
|
10982
11314
|
const highPriorityCount = signals.filter((signal) => signal.priority === "high").length;
|
|
10983
|
-
const
|
|
11315
|
+
const semanticBindings = matchMotifOntologyBindings({
|
|
11316
|
+
id: motifId,
|
|
11317
|
+
key: regionKey,
|
|
11318
|
+
kind: signals[0]?.kind ?? regionKey,
|
|
11319
|
+
capability
|
|
11320
|
+
}, concepts);
|
|
11321
|
+
const semanticNames = uniqueStrings(semanticBindings.map((binding) => binding.conceptName));
|
|
11322
|
+
const semanticNote = semanticNames.length > 0 ? ` • semantic family ${semanticNames.join(", ")}` : "";
|
|
11323
|
+
const responseSummary = lifecycle === "addressed" ? realizedTransfers.length > 0 ? `Promoted into reusable transfer evidence${semanticNote}` : `All linked pressure in this recurring region is addressed${semanticNote}` : lifecycle === "in-progress" ? `Promotion or response underway via ${interventionTypes.join(", ") || "linked intervention"}${semanticNote}` : lifecycle === "stale" ? "Recurring pressure has been superseded by newer equivalent signals" : `Recurring demand is waiting for ${recommendation.route}${semanticNote}`;
|
|
10984
11324
|
motifs.push({
|
|
10985
11325
|
id: motifId,
|
|
10986
11326
|
key: regionKey,
|
|
@@ -10999,6 +11339,8 @@ function loadPressureMotifs() {
|
|
|
10999
11339
|
suggestedRoute: recommendation,
|
|
11000
11340
|
lifecycle,
|
|
11001
11341
|
interventionTypes,
|
|
11342
|
+
semanticBindings,
|
|
11343
|
+
semanticConceptIds: uniqueStrings(semanticBindings.map((binding) => binding.conceptId)),
|
|
11002
11344
|
lastActivityAt,
|
|
11003
11345
|
addressedAt,
|
|
11004
11346
|
responseSummary
|
|
@@ -11009,6 +11351,116 @@ function loadPressureMotifs() {
|
|
|
11009
11351
|
return lifecycleWeight(b.lifecycle) - lifecycleWeight(a.lifecycle) || b.highPriorityCount - a.highPriorityCount || b.recurrenceCount - a.recurrenceCount || b.lastActivityAt.localeCompare(a.lastActivityAt);
|
|
11010
11352
|
});
|
|
11011
11353
|
}
|
|
11354
|
+
function collectOntologyAdoptionState() {
|
|
11355
|
+
const extensions = loadOntologyExtensions();
|
|
11356
|
+
const activeExtensions = extensions.filter((concept) => concept.status === "active");
|
|
11357
|
+
const byConceptKind = ontologyKindCounts();
|
|
11358
|
+
const bindingsByTargetType = emptyOntologyBindingCounts();
|
|
11359
|
+
const consumerMap = new Map;
|
|
11360
|
+
const conceptById = new Map(extensions.map((concept) => [concept.id, concept]));
|
|
11361
|
+
function ensureConsumer(concept) {
|
|
11362
|
+
const existing = consumerMap.get(concept.id);
|
|
11363
|
+
if (existing)
|
|
11364
|
+
return existing;
|
|
11365
|
+
const created = {
|
|
11366
|
+
conceptId: concept.id,
|
|
11367
|
+
conceptName: concept.name,
|
|
11368
|
+
conceptKind: concept.conceptKind,
|
|
11369
|
+
status: concept.status,
|
|
11370
|
+
totalBindings: 0,
|
|
11371
|
+
bindingsByTargetType: emptyOntologyBindingCounts(),
|
|
11372
|
+
activeTargetIds: [],
|
|
11373
|
+
lastActivityAt: concept.lastObservedAt ?? concept.createdAt
|
|
11374
|
+
};
|
|
11375
|
+
consumerMap.set(concept.id, created);
|
|
11376
|
+
return created;
|
|
11377
|
+
}
|
|
11378
|
+
function registerBinding(binding) {
|
|
11379
|
+
const concept = conceptById.get(binding.conceptId);
|
|
11380
|
+
if (!concept || concept.status !== "active")
|
|
11381
|
+
return;
|
|
11382
|
+
const consumer = ensureConsumer(concept);
|
|
11383
|
+
consumer.totalBindings += 1;
|
|
11384
|
+
consumer.bindingsByTargetType[binding.targetType] = (consumer.bindingsByTargetType[binding.targetType] ?? 0) + 1;
|
|
11385
|
+
if (!consumer.activeTargetIds.includes(binding.targetId) && consumer.activeTargetIds.length < 12) {
|
|
11386
|
+
consumer.activeTargetIds.push(binding.targetId);
|
|
11387
|
+
}
|
|
11388
|
+
consumer.lastActivityAt = maxTimestamp(consumer.lastActivityAt, concept.lastObservedAt, concept.createdAt);
|
|
11389
|
+
bindingsByTargetType[binding.targetType] = (bindingsByTargetType[binding.targetType] ?? 0) + 1;
|
|
11390
|
+
byConceptKind[concept.conceptKind] = (byConceptKind[concept.conceptKind] ?? 0) + 1;
|
|
11391
|
+
}
|
|
11392
|
+
const signals = loadResolvedPressureSignals();
|
|
11393
|
+
for (const signal of signals) {
|
|
11394
|
+
for (const binding of signal.semanticBindings ?? [])
|
|
11395
|
+
registerBinding(binding);
|
|
11396
|
+
if (signal.routeRecommendation?.semanticConceptIds?.length) {
|
|
11397
|
+
for (const conceptId of signal.routeRecommendation.semanticConceptIds) {
|
|
11398
|
+
const concept = conceptById.get(conceptId);
|
|
11399
|
+
if (!concept || concept.status !== "active")
|
|
11400
|
+
continue;
|
|
11401
|
+
registerBinding(buildOntologyBinding({
|
|
11402
|
+
concept,
|
|
11403
|
+
targetType: "route-recommendation",
|
|
11404
|
+
targetId: `${signal.id}:route`,
|
|
11405
|
+
sourceKind: "pressure-region",
|
|
11406
|
+
confidence: signal.routeRecommendation.semanticInfluence === "weighted" ? 0.82 : 0.72,
|
|
11407
|
+
reasons: signal.routeRecommendation.reasons.slice(0, 2),
|
|
11408
|
+
effectSummary: `Route recommendation ${signal.routeRecommendation.route} is semantically informed by ${concept.name}.`
|
|
11409
|
+
}));
|
|
11410
|
+
}
|
|
11411
|
+
}
|
|
11412
|
+
}
|
|
11413
|
+
for (const motif of loadPressureMotifs()) {
|
|
11414
|
+
for (const binding of motif.semanticBindings ?? [])
|
|
11415
|
+
registerBinding(binding);
|
|
11416
|
+
}
|
|
11417
|
+
for (const event of loadTransferEvents()) {
|
|
11418
|
+
for (const binding of event.semanticBindings ?? [])
|
|
11419
|
+
registerBinding(binding);
|
|
11420
|
+
}
|
|
11421
|
+
for (const candidate of loadResolvedTopologyReviewCandidates()) {
|
|
11422
|
+
for (const binding of candidate.semanticBindings ?? [])
|
|
11423
|
+
registerBinding(binding);
|
|
11424
|
+
}
|
|
11425
|
+
const activeConsumers = [...consumerMap.values()].sort((a, b) => b.totalBindings - a.totalBindings || (b.lastActivityAt ?? "").localeCompare(a.lastActivityAt ?? ""));
|
|
11426
|
+
const atRiskConcepts = activeConsumers.filter((consumer) => consumer.totalBindings > 0).map((consumer) => ({
|
|
11427
|
+
...consumer,
|
|
11428
|
+
warning: `${consumer.totalBindings} active consumer${consumer.totalBindings === 1 ? "" : "s"} would be affected by deprecating ${consumer.conceptName}.`
|
|
11429
|
+
}));
|
|
11430
|
+
return {
|
|
11431
|
+
summary: {
|
|
11432
|
+
activeConcepts: activeConsumers.length,
|
|
11433
|
+
unusedExtensions: activeExtensions.filter((concept) => !consumerMap.has(concept.id)).length,
|
|
11434
|
+
totalBindings: activeConsumers.reduce((sum, consumer) => sum + consumer.totalBindings, 0),
|
|
11435
|
+
routesInfluenced: signals.filter((signal) => signal.routeRecommendation?.semanticInfluence && signal.routeRecommendation.semanticInfluence !== "none").length,
|
|
11436
|
+
conceptsWithConsumers: activeConsumers.length,
|
|
11437
|
+
conceptsAtDeprecationRisk: atRiskConcepts.length,
|
|
11438
|
+
bindingsByTargetType,
|
|
11439
|
+
usageByConceptKind: byConceptKind,
|
|
11440
|
+
topActiveConcepts: activeConsumers.slice(0, 8),
|
|
11441
|
+
atRiskConcepts: atRiskConcepts.slice(0, 8)
|
|
11442
|
+
},
|
|
11443
|
+
consumerMap: new Map(activeConsumers.map((consumer) => [consumer.conceptId, consumer]))
|
|
11444
|
+
};
|
|
11445
|
+
}
|
|
11446
|
+
function getOntologyAdoptionSummary() {
|
|
11447
|
+
return collectOntologyAdoptionState().summary;
|
|
11448
|
+
}
|
|
11449
|
+
function loadResolvedOntologyExtensions() {
|
|
11450
|
+
const extensions = loadOntologyExtensions();
|
|
11451
|
+
const { consumerMap } = collectOntologyAdoptionState();
|
|
11452
|
+
return extensions.map((concept) => {
|
|
11453
|
+
const consumer = consumerMap.get(concept.id);
|
|
11454
|
+
return {
|
|
11455
|
+
...concept,
|
|
11456
|
+
semanticBindings: [],
|
|
11457
|
+
adoptionCount: consumer?.totalBindings ?? 0,
|
|
11458
|
+
bindingsByTargetType: consumer?.bindingsByTargetType ?? emptyOntologyBindingCounts(),
|
|
11459
|
+
lastActivityAt: maxTimestamp(concept.lastObservedAt, consumer?.lastActivityAt, concept.createdAt),
|
|
11460
|
+
warning: consumer?.warning
|
|
11461
|
+
};
|
|
11462
|
+
}).sort((a, b) => b.adoptionCount - a.adoptionCount || b.lastActivityAt.localeCompare(a.lastActivityAt) || a.name.localeCompare(b.name));
|
|
11463
|
+
}
|
|
11012
11464
|
function matchPressureSignals(filters) {
|
|
11013
11465
|
const capabilities = new Set((filters.capabilities ?? []).map((value) => normalizePressureValue(value)));
|
|
11014
11466
|
const relatedFailureIds = new Set(filters.relatedFailureIds ?? []);
|
|
@@ -16373,6 +16825,8 @@ function printStatus2() {
|
|
|
16373
16825
|
console.log(` Extensions: ${summary.extensions} active • ${summary.deprecated} deprecated`);
|
|
16374
16826
|
console.log(` Frontier: ${summary.frontier} total • ${summary.reviewOpen} open • ${summary.deferred} deferred • ${summary.rejected} rejected`);
|
|
16375
16827
|
console.log(` Change log: ${summary.changeEvents} events`);
|
|
16828
|
+
console.log(` Adoption: ${summary.adoption.activeConcepts} active concepts • ${summary.adoption.totalBindings} bindings • ${summary.adoption.routesInfluenced} routes influenced`);
|
|
16829
|
+
console.log(` Coverage: ${summary.adoption.unusedExtensions} unused extensions • ${summary.adoption.conceptsAtDeprecationRisk} deprecation-sensitive concepts`);
|
|
16376
16830
|
if (summary.backlog.length > 0) {
|
|
16377
16831
|
console.log(`
|
|
16378
16832
|
Frontier concepts ready for review`);
|
|
@@ -16384,7 +16838,8 @@ function printStatus2() {
|
|
|
16384
16838
|
console.log(`
|
|
16385
16839
|
Approved extensions`);
|
|
16386
16840
|
for (const concept of summary.recentExtensions.slice(0, 5)) {
|
|
16387
|
-
|
|
16841
|
+
const warning = concept.warning ? " • deprecation risk" : "";
|
|
16842
|
+
console.log(` • ${concept.id} (${concept.conceptKind}) • ${concept.status} • ${concept.adoptionCount} bindings${warning}`);
|
|
16388
16843
|
}
|
|
16389
16844
|
}
|
|
16390
16845
|
console.log();
|
|
@@ -16452,14 +16907,18 @@ async function ontologyCommand(options) {
|
|
|
16452
16907
|
✓ Deprecated ontology extension: ${concept.id}`);
|
|
16453
16908
|
console.log(` kind: ${concept.conceptKind}`);
|
|
16454
16909
|
console.log(` status: ${concept.status}`);
|
|
16910
|
+
if (concept.warning) {
|
|
16911
|
+
console.log(` warning: ${concept.warning}`);
|
|
16912
|
+
}
|
|
16455
16913
|
console.log();
|
|
16456
16914
|
return;
|
|
16457
16915
|
}
|
|
16458
16916
|
printStatus2();
|
|
16459
16917
|
if (options.verbose) {
|
|
16918
|
+
const summary = getOntologyReviewSummary();
|
|
16460
16919
|
const frontier = loadResolvedOntologyFrontierConcepts().slice(0, 8);
|
|
16461
16920
|
const changes = loadOntologyChangeEvents().slice(0, 8);
|
|
16462
|
-
const extensions =
|
|
16921
|
+
const extensions = loadResolvedOntologyExtensions().slice(0, 8);
|
|
16463
16922
|
if (frontier.length > 0) {
|
|
16464
16923
|
console.log(" Recent frontier concepts");
|
|
16465
16924
|
for (const concept of frontier) {
|
|
@@ -16470,7 +16929,26 @@ async function ontologyCommand(options) {
|
|
|
16470
16929
|
if (extensions.length > 0) {
|
|
16471
16930
|
console.log(" Recent approved extensions");
|
|
16472
16931
|
for (const concept of extensions) {
|
|
16473
|
-
|
|
16932
|
+
const warning = concept.warning ? ` • ${concept.warning}` : "";
|
|
16933
|
+
console.log(` • ${concept.id} • ${concept.conceptKind} • ${concept.status} • ${concept.adoptionCount} bindings${warning}`);
|
|
16934
|
+
}
|
|
16935
|
+
console.log();
|
|
16936
|
+
}
|
|
16937
|
+
if (summary.adoption.topActiveConcepts.length > 0) {
|
|
16938
|
+
console.log(" Top active concepts");
|
|
16939
|
+
for (const concept of summary.adoption.topActiveConcepts) {
|
|
16940
|
+
console.log(` • ${concept.conceptId} • ${concept.totalBindings} bindings • ${Object.entries(concept.bindingsByTargetType).map(([target, count]) => `${target}:${count}`).join(" • ")}`);
|
|
16941
|
+
}
|
|
16942
|
+
console.log();
|
|
16943
|
+
}
|
|
16944
|
+
if (summary.adoption.unusedExtensions > 0) {
|
|
16945
|
+
console.log(` Unused approved extensions: ${summary.adoption.unusedExtensions}`);
|
|
16946
|
+
console.log();
|
|
16947
|
+
}
|
|
16948
|
+
if (summary.adoption.atRiskConcepts.length > 0) {
|
|
16949
|
+
console.log(" Deprecation-sensitive concepts");
|
|
16950
|
+
for (const concept of summary.adoption.atRiskConcepts) {
|
|
16951
|
+
console.log(` • ${concept.conceptId} • ${concept.warning}`);
|
|
16474
16952
|
}
|
|
16475
16953
|
console.log();
|
|
16476
16954
|
}
|
|
@@ -16507,6 +16985,7 @@ Examples:
|
|
|
16507
16985
|
$ helixevo topology --prepare <id> Prepare an accepted topology candidate
|
|
16508
16986
|
$ helixevo topology --apply <planId> Apply a safe prepared topology plan
|
|
16509
16987
|
$ helixevo topology --rollback <planId> Roll back an applied topology plan
|
|
16988
|
+
$ helixevo ontology --status --verbose Show frontier, extension, adoption, and deprecation-risk visibility
|
|
16510
16989
|
$ helixevo ontology --refresh Derive frontier concepts from recurring evidence
|
|
16511
16990
|
$ helixevo ontology --review <id> --decision promote
|
|
16512
16991
|
Promote a reviewed frontier concept into approved extensions
|
|
@@ -16533,7 +17012,7 @@ program2.command("health").description("Assess network health: cohesion, coverag
|
|
|
16533
17012
|
program2.command("metrics").description("Show correction rates, skill trends, and evolution impact").option("--verbose", "Show detailed per-skill breakdown").action(metricsCommand);
|
|
16534
17013
|
program2.command("project-setup").description("Analyze a project folder and match it against your skill set").argument("<path>", "Path to the project folder").option("--verbose", "Show detailed analysis").option("--dry-run", "Analyze without saving project profile").action(projectSetupCommand);
|
|
16535
17014
|
program2.command("topology").description("Reviewed topology execution control [--status] [--prepare <candidateId>] [--apply <planId>] [--rollback <planId>]").option("--status", "Show topology review and execution state").option("--prepare <candidateId>", "Prepare an accepted topology review candidate").option("--apply <planId>", "Apply a safe prepared topology plan").option("--rollback <planId>", "Roll back an applied topology plan").option("--verbose", "Show detailed topology plan state").action(topologyCommand);
|
|
16536
|
-
program2.command("ontology").description("Governed ontology frontier control [--status] [--refresh] [--review <conceptId>] [--decision <promote|reject|defer>] [--deprecate <conceptId>]").option("--status", "Show ontology kernel, frontier, and extension state").option("--refresh", "Derive frontier concepts from recurring runtime evidence").option("--review <conceptId>", "Review a frontier concept").option("--decision <decision>", "Decision for --review: promote, reject, or defer").option("--rationale <text>", "Optional rationale for review or deprecate actions").option("--deprecate <conceptId>", "Deprecate an approved ontology extension").option("--verbose", "Show detailed ontology frontier state").action(ontologyCommand);
|
|
17015
|
+
program2.command("ontology").description("Governed ontology frontier and semantic adoption control [--status] [--refresh] [--review <conceptId>] [--decision <promote|reject|defer>] [--deprecate <conceptId>]").option("--status", "Show ontology kernel, frontier, and extension state").option("--refresh", "Derive frontier concepts from recurring runtime evidence").option("--review <conceptId>", "Review a frontier concept").option("--decision <decision>", "Decision for --review: promote, reject, or defer").option("--rationale <text>", "Optional rationale for review or deprecate actions").option("--deprecate <conceptId>", "Deprecate an approved ontology extension").option("--verbose", "Show detailed ontology frontier state").action(ontologyCommand);
|
|
16537
17016
|
program2.hook("postAction", () => {
|
|
16538
17017
|
checkForUpdates().catch(() => {});
|
|
16539
17018
|
});
|