@mnemom/agent-alignment-protocol 0.6.0 → 0.6.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/index.js +18 -0
- package/dist/index.mjs +18 -0
- package/package.json +2 -2
- package/src/verification/api.ts +27 -1
package/dist/index.js
CHANGED
|
@@ -747,6 +747,13 @@ function hasRoleKeyword(agentId) {
|
|
|
747
747
|
const lower = agentId.toLowerCase();
|
|
748
748
|
return ROLE_KEYWORDS.some((kw) => lower.includes(kw));
|
|
749
749
|
}
|
|
750
|
+
function getClpiRole(card) {
|
|
751
|
+
const ext = card.extensions;
|
|
752
|
+
if (!ext) return null;
|
|
753
|
+
const clpi = ext["clpi"];
|
|
754
|
+
if (!clpi || typeof clpi["role"] !== "string") return null;
|
|
755
|
+
return clpi["role"] || null;
|
|
756
|
+
}
|
|
750
757
|
function analyzeFaultLines(coherenceResult, cards, options) {
|
|
751
758
|
const reputationScores = options?.reputationScores;
|
|
752
759
|
const agentBoundedActions = /* @__PURE__ */ new Map();
|
|
@@ -757,6 +764,10 @@ function analyzeFaultLines(coherenceResult, cards, options) {
|
|
|
757
764
|
for (const { agentId, card } of cards) {
|
|
758
765
|
agentConflictMap.set(agentId, new Set(card.values.conflicts_with ?? []));
|
|
759
766
|
}
|
|
767
|
+
const agentRoleMap = /* @__PURE__ */ new Map();
|
|
768
|
+
for (const { agentId, card } of cards) {
|
|
769
|
+
agentRoleMap.set(agentId, getClpiRole(card));
|
|
770
|
+
}
|
|
760
771
|
const faultLines = [];
|
|
761
772
|
for (const divergence of coherenceResult.divergence_report) {
|
|
762
773
|
const {
|
|
@@ -789,6 +800,13 @@ function analyzeFaultLines(coherenceResult, cards, options) {
|
|
|
789
800
|
})()) {
|
|
790
801
|
classification = "priority_mismatch";
|
|
791
802
|
} else if (agents_declaring.length >= 1 && agents_missing.length >= 1 && (() => {
|
|
803
|
+
const declaringRoles = new Set(agents_declaring.map((id2) => agentRoleMap.get(id2) ?? null).filter(Boolean));
|
|
804
|
+
const missingRoles = new Set(agents_missing.map((id2) => agentRoleMap.get(id2) ?? null).filter(Boolean));
|
|
805
|
+
if (declaringRoles.size > 0) {
|
|
806
|
+
const declaringRoleArr = [...declaringRoles];
|
|
807
|
+
const isRoleExclusive = declaringRoleArr.every((role) => !missingRoles.has(role));
|
|
808
|
+
if (isRoleExclusive) return true;
|
|
809
|
+
}
|
|
792
810
|
const allInvolved = [...agents_declaring, ...agents_missing];
|
|
793
811
|
return allInvolved.some((id2) => hasRoleKeyword(id2));
|
|
794
812
|
})()) {
|
package/dist/index.mjs
CHANGED
|
@@ -690,6 +690,13 @@ function hasRoleKeyword(agentId) {
|
|
|
690
690
|
const lower = agentId.toLowerCase();
|
|
691
691
|
return ROLE_KEYWORDS.some((kw) => lower.includes(kw));
|
|
692
692
|
}
|
|
693
|
+
function getClpiRole(card) {
|
|
694
|
+
const ext = card.extensions;
|
|
695
|
+
if (!ext) return null;
|
|
696
|
+
const clpi = ext["clpi"];
|
|
697
|
+
if (!clpi || typeof clpi["role"] !== "string") return null;
|
|
698
|
+
return clpi["role"] || null;
|
|
699
|
+
}
|
|
693
700
|
function analyzeFaultLines(coherenceResult, cards, options) {
|
|
694
701
|
const reputationScores = options?.reputationScores;
|
|
695
702
|
const agentBoundedActions = /* @__PURE__ */ new Map();
|
|
@@ -700,6 +707,10 @@ function analyzeFaultLines(coherenceResult, cards, options) {
|
|
|
700
707
|
for (const { agentId, card } of cards) {
|
|
701
708
|
agentConflictMap.set(agentId, new Set(card.values.conflicts_with ?? []));
|
|
702
709
|
}
|
|
710
|
+
const agentRoleMap = /* @__PURE__ */ new Map();
|
|
711
|
+
for (const { agentId, card } of cards) {
|
|
712
|
+
agentRoleMap.set(agentId, getClpiRole(card));
|
|
713
|
+
}
|
|
703
714
|
const faultLines = [];
|
|
704
715
|
for (const divergence of coherenceResult.divergence_report) {
|
|
705
716
|
const {
|
|
@@ -732,6 +743,13 @@ function analyzeFaultLines(coherenceResult, cards, options) {
|
|
|
732
743
|
})()) {
|
|
733
744
|
classification = "priority_mismatch";
|
|
734
745
|
} else if (agents_declaring.length >= 1 && agents_missing.length >= 1 && (() => {
|
|
746
|
+
const declaringRoles = new Set(agents_declaring.map((id2) => agentRoleMap.get(id2) ?? null).filter(Boolean));
|
|
747
|
+
const missingRoles = new Set(agents_missing.map((id2) => agentRoleMap.get(id2) ?? null).filter(Boolean));
|
|
748
|
+
if (declaringRoles.size > 0) {
|
|
749
|
+
const declaringRoleArr = [...declaringRoles];
|
|
750
|
+
const isRoleExclusive = declaringRoleArr.every((role) => !missingRoles.has(role));
|
|
751
|
+
if (isRoleExclusive) return true;
|
|
752
|
+
}
|
|
735
753
|
const allInvolved = [...agents_declaring, ...agents_missing];
|
|
736
754
|
return allInvolved.some((id2) => hasRoleKeyword(id2));
|
|
737
755
|
})()) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mnemom/agent-alignment-protocol",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Agent Alignment Protocol (AAP) - Verification and drift detection for AI agents",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -54,4 +54,4 @@
|
|
|
54
54
|
"engines": {
|
|
55
55
|
"node": ">=18.0.0"
|
|
56
56
|
}
|
|
57
|
-
}
|
|
57
|
+
}
|
package/src/verification/api.ts
CHANGED
|
@@ -788,6 +788,15 @@ function hasRoleKeyword(agentId: string): boolean {
|
|
|
788
788
|
return ROLE_KEYWORDS.some(kw => lower.includes(kw));
|
|
789
789
|
}
|
|
790
790
|
|
|
791
|
+
/** Extract the CLPI role from a card's extensions, if present. */
|
|
792
|
+
function getClpiRole(card: AlignmentCard): string | null {
|
|
793
|
+
const ext = (card as unknown as { extensions?: Record<string, unknown> }).extensions;
|
|
794
|
+
if (!ext) return null;
|
|
795
|
+
const clpi = ext['clpi'] as Record<string, unknown> | undefined;
|
|
796
|
+
if (!clpi || typeof clpi['role'] !== 'string') return null;
|
|
797
|
+
return clpi['role'] || null;
|
|
798
|
+
}
|
|
799
|
+
|
|
791
800
|
/**
|
|
792
801
|
* Analyze fault lines in a fleet based on a FleetCoherenceResult.
|
|
793
802
|
*
|
|
@@ -815,6 +824,12 @@ export function analyzeFaultLines(
|
|
|
815
824
|
agentConflictMap.set(agentId, new Set(card.values.conflicts_with ?? []));
|
|
816
825
|
}
|
|
817
826
|
|
|
827
|
+
// Build lookup: agentId → CLPI role (from extensions.clpi.role)
|
|
828
|
+
const agentRoleMap = new Map<string, string | null>();
|
|
829
|
+
for (const { agentId, card } of cards) {
|
|
830
|
+
agentRoleMap.set(agentId, getClpiRole(card));
|
|
831
|
+
}
|
|
832
|
+
|
|
818
833
|
const faultLines: FaultLine[] = [];
|
|
819
834
|
|
|
820
835
|
for (const divergence of coherenceResult.divergence_report) {
|
|
@@ -863,7 +878,18 @@ export function analyzeFaultLines(
|
|
|
863
878
|
agents_declaring.length >= 1 &&
|
|
864
879
|
agents_missing.length >= 1 &&
|
|
865
880
|
(() => {
|
|
866
|
-
// complementary:
|
|
881
|
+
// complementary: the declaring agents all share a CLPI role that the missing
|
|
882
|
+
// agents do NOT share — indicating intentional role specialization, not a gap.
|
|
883
|
+
// Primary check: extensions.clpi.role (authoritative)
|
|
884
|
+
const declaringRoles = new Set(agents_declaring.map(id => agentRoleMap.get(id) ?? null).filter(Boolean));
|
|
885
|
+
const missingRoles = new Set(agents_missing.map(id => agentRoleMap.get(id) ?? null).filter(Boolean));
|
|
886
|
+
if (declaringRoles.size > 0) {
|
|
887
|
+
// All declaring agents share a role that none of the missing agents have
|
|
888
|
+
const declaringRoleArr = [...declaringRoles];
|
|
889
|
+
const isRoleExclusive = declaringRoleArr.every(role => !missingRoles.has(role));
|
|
890
|
+
if (isRoleExclusive) return true;
|
|
891
|
+
}
|
|
892
|
+
// Fallback: agent ID contains a role keyword (original heuristic)
|
|
867
893
|
const allInvolved = [...agents_declaring, ...agents_missing];
|
|
868
894
|
return allInvolved.some(id => hasRoleKeyword(id));
|
|
869
895
|
})()
|