| 498 | /* ── Build per-function semantic data ────────────────────────────── */ |
| 499 | |
| 500 | static void build_api_vec(const cbm_gbuf_t *gbuf, int64_t node_id, cbm_sem_vec_t *out) { |
| 501 | memset(out, 0, sizeof(*out)); |
| 502 | /* Sorted neighbors: stable MAX_CALLEES subset + stable float-accumulation |
| 503 | * order (see collect_sorted_call_neighbors). */ |
| 504 | int n = 0; |
| 505 | const char **names = collect_sorted_call_neighbors(gbuf, node_id, /*outbound=*/true, &n); |
| 506 | if (!names) { |
| 507 | return; |
| 508 | } |
| 509 | for (int i = 0; i < n && i < MAX_CALLEES; i++) { |
| 510 | cbm_sem_vec_t callee_ri; |
| 511 | cbm_sem_random_index(names[i], &callee_ri); |
| 512 | cbm_sem_vec_add_scaled(out, &callee_ri, PSE_UNIT_POS); |
| 513 | } |
| 514 | free((void *)names); |
| 515 | cbm_sem_normalize(out); |
| 516 | } |
| 517 | |
| 518 | static void build_type_vec(const char *props_json, cbm_sem_vec_t *out) { |
| 519 | memset(out, 0, sizeof(*out)); |
no test coverage detected