| 2367 | } |
| 2368 | |
| 2369 | int main(int argc, char **argv) { |
| 2370 | /* Must remain the first statement: see allocator binding contract above. */ |
| 2371 | cbm_alloc_init(); |
| 2372 | #ifndef _WIN32 |
| 2373 | pid_t process_initial_ppid = getppid(); |
| 2374 | #endif |
| 2375 | #ifdef _WIN32 |
| 2376 | { |
| 2377 | int win_argc = 0; |
| 2378 | char **win_argv = cbm_win_utf8_argv(&win_argc); |
| 2379 | if (win_argv) { |
| 2380 | argc = win_argc; |
| 2381 | argv = win_argv; |
| 2382 | } |
| 2383 | } |
| 2384 | #endif |
| 2385 | cbm_daemon_process_role_t role = cbm_daemon_process_role(argc, argv); |
| 2386 | if (role == CBM_DAEMON_PROCESS_INVALID) { |
| 2387 | (void)fprintf(stderr, "codebase-memory-mcp: invalid internal process arguments\n"); |
| 2388 | return EXIT_FAILURE; |
| 2389 | } |
| 2390 | #ifndef _WIN32 |
| 2391 | if (role == CBM_DAEMON_PROCESS_DAEMON) { |
| 2392 | (void)umask(077); |
| 2393 | } |
| 2394 | #endif |
| 2395 | |
| 2396 | cbm_cli_set_version(CBM_VERSION); |
| 2397 | cbm_profile_init(); |
| 2398 | cbm_log_init_from_env(); |
| 2399 | |
| 2400 | cbm_mcp_tool_profile_t tool_profile = CBM_MCP_TOOL_PROFILE_ALL; |
| 2401 | if (role == CBM_DAEMON_PROCESS_MCP_CLIENT && |
| 2402 | cbm_mcp_parse_tool_profile_args(argc, (const char *const *)argv, &tool_profile) != 0) { |
| 2403 | (void)fprintf(stderr, "codebase-memory-mcp: --tool-profile requires the supported value " |
| 2404 | "'analysis' or 'scout'\n"); |
| 2405 | return 2; |
| 2406 | } |
| 2407 | const char *hook_event = NULL; |
| 2408 | const char *hook_dialect = NULL; |
| 2409 | if (role == CBM_DAEMON_PROCESS_HOOK_CLIENT && |
| 2410 | !main_hook_options(argc, argv, &hook_event, &hook_dialect)) { |
| 2411 | return EXIT_SUCCESS; /* hook adapters are contractually fail-open */ |
| 2412 | } |
| 2413 | |
| 2414 | /* Hook augmentation is contractually fail-open and time-bounded. It is |
| 2415 | * daemon-backed but CONNECT-ONLY: a hook never spawns a daemon (a cold |
| 2416 | * spawn cannot fit the fail-open budget and livelocks against the |
| 2417 | * last-client-exit teardown), it recycles whichever daemon an MCP |
| 2418 | * session or `daemon start` already brought up. Arm the deadline before |
| 2419 | * hashing and IPC. */ |
| 2420 | if (role == CBM_DAEMON_PROCESS_HOOK_CLIENT) { |
| 2421 | #ifndef _WIN32 |
| 2422 | cbm_hook_augment_arm_deadline(); |
| 2423 | #endif |
| 2424 | } |
| 2425 | |
| 2426 | if (role == CBM_DAEMON_PROCESS_STATELESS) { |
nothing calls this directly
no test coverage detected