Coverage for integrations / social / __init__.py: 81.2%

288 statements  

« prev     ^ index     » next       coverage.py v7.14.0, created at 2026-05-12 04:49 +0000

1""" 

2HevolveSocial - Agent Social Network 

3A community-driven social network where both humans and AI agents are equal participants. 

4""" 

5import logging 

6 

7logger = logging.getLogger('hevolve_social') 

8 

9# Lazy imports to avoid circular dependencies 

10_social_bp = None 

11 

12# ── Idempotency sentinel (2026-04-19) ────────────────────────────── 

13# init_social is expensive: registers ~18 blueprints, seeds DB tables, 

14# starts gossip/peer discovery, pulls autogen→openai→langchain via 

15# init_agent_engine. Flask's register_blueprint raises on duplicate 

16# name, so a second call would crash the app. Defend against double- 

17# init by tracking whether we've already run. (Nunba's main.py has 

18# its own idempotency guard too; this is belt-and-suspenders for any 

19# downstream caller that imports this module and calls init_social 

20# again — tests, reloader, future cloud entry.) 

21_INIT_DONE = False 

22 

23 

24def get_social_blueprint(): 

25 global _social_bp 

26 if _social_bp is None: 

27 from .api import social_bp as bp 

28 _social_bp = bp 

29 return _social_bp 

30 

31 

32def init_social(app): 

33 """Initialize the social network module. Call after app = Flask(...). 

34 

35 This function is idempotent — calling it twice is safe. The second 

36 call short-circuits and logs a debug message. Rationale: this call 

37 registers 18+ blueprints, and Flask rejects duplicate blueprint 

38 names; skipping the second call is less surprising than raising.""" 

39 global _INIT_DONE 

40 if _INIT_DONE: 

41 logger.debug("init_social: already initialized, skipping second call") 

42 return 

43 _INIT_DONE = True 

44 # Block dev mode on central 

45 import os as _os_boot 

46 node_tier = _os_boot.environ.get('HEVOLVE_NODE_TIER', 'flat') 

47 if node_tier == 'central' and _os_boot.environ.get('HEVOLVE_DEV_MODE', '').lower() == 'true': 

48 _os_boot.environ['HEVOLVE_DEV_MODE'] = 'false' 

49 logger.critical("SECURITY: Dev mode FORCED OFF on central instance") 

50 

51 from .models import init_db, DB_PATH 

52 try: 

53 init_db() 

54 # Apply pending schema migrations against the canonical DB so a 

55 # daemon booting on a pre-existing v36/37/38 SQLite catches up 

56 # to SCHEMA_VERSION (currently 39: users.voice_profile column). 

57 # Idempotent — see tests/unit/test_voice_profile_migration.py. 

58 # Brings HARTOS daemon parity with Nunba main.py per MEMORY.md. 

59 from .migrations import run_migrations 

60 run_migrations() 

61 logger.info(f"HevolveSocial database initialized + migrated ({DB_PATH})") 

62 except Exception as e: 

63 logger.warning(f"HevolveSocial DB init failed (non-fatal): {e}") 

64 

65 # Phase 7a / Phase 8 — install global tenant filter on Session. 

66 # Migration v40 added `tenant_id` columns to ~34 social tables; 

67 # this teaches the ORM about them and filters every SELECT by 

68 # the current request's tenant. No-op when g.tenant_id is None 

69 # (flat/regional pass-through), so single-tenant deploys are 

70 # unaffected. Plan reference: sunny-gliding-eich.md, Part E.1. 

71 try: 

72 from .tenant_filter import ( 

73 install_tenant_filter, register_tenant_aware, 

74 ) 

75 install_tenant_filter() 

76 from .models import ( 

77 User, Post, Comment, Community, Vote, Follow, 

78 CommunityMembership, Notification, Report, 

79 ) 

80 for _cls in (User, Post, Comment, Community, Vote, Follow, 

81 CommunityMembership, Notification, Report): 

82 register_tenant_aware(_cls) 

83 except Exception as e: 

84 logger.warning(f"HevolveSocial tenant filter install skipped: {e}") 

85 

86 # Seed default achievements 

87 try: 

88 from .gamification_service import GamificationService 

89 from .models import get_db 

90 db = get_db() 

91 try: 

92 count = GamificationService.seed_achievements(db) 

93 if count > 0: 

94 db.commit() 

95 logger.info(f"HevolveSocial: seeded {count} achievements") 

96 finally: 

97 db.close() 

98 except Exception as e: 

99 logger.debug(f"HevolveSocial achievement seeding skipped: {e}") 

100 

101 # Seed default ad placements 

102 try: 

103 from .ad_service import AdService 

104 from .models import get_db as _get_db 

105 db = _get_db() 

106 try: 

107 count = AdService.seed_placements(db) 

108 if count > 0: 

109 db.commit() 

110 logger.info(f"HevolveSocial: seeded {count} ad placements") 

111 finally: 

112 db.close() 

113 except Exception as e: 

114 logger.debug(f"HevolveSocial ad placement seeding skipped: {e}") 

115 

116 # Register conversations blueprint (Phase 7c.3 — DM/group chat). 

117 # Distinct from api_channels (legacy 31-channel external adapter) 

118 # — these blueprints have non-overlapping URL prefixes. 

119 try: 

120 from .api_conversations import conversations_bp 

121 app.register_blueprint(conversations_bp) 

122 logger.info("HevolveSocial conversations registered at " 

123 "/api/social/conversations/") 

124 except Exception as e: 

125 logger.warning(f"HevolveSocial conversations blueprint skipped: {e}") 

126 

127 # Register calls blueprint (Phase 7d — voice/video/screen). 

128 # Flag-gated by `calls_v1` server-side; off → 503 on every endpoint. 

129 # The blueprint's URL prefix is /api/social so the routes live at 

130 # /api/social/calls/* (no nesting under /conversations). 

131 try: 

132 from .api_calls import calls_bp 

133 app.register_blueprint(calls_bp) 

134 logger.info("HevolveSocial calls registered at /api/social/calls/") 

135 except Exception as e: 

136 logger.warning(f"HevolveSocial calls blueprint skipped: {e}") 

137 

138 # Register gamification blueprint 

139 try: 

140 from .api_gamification import gamification_bp 

141 app.register_blueprint(gamification_bp) 

142 logger.info("HevolveSocial gamification endpoints registered") 

143 except Exception as e: 

144 logger.warning(f"HevolveSocial gamification blueprint skipped: {e}") 

145 

146 # Register hive contest blueprint (Claude Code onramp + leaderboard) 

147 try: 

148 from .api_hive_contest import hive_contest_bp 

149 app.register_blueprint(hive_contest_bp) 

150 logger.info("HevolveSocial hive contest registered at /api/hive/contest/") 

151 except Exception as e: 

152 logger.warning(f"HevolveSocial hive contest blueprint skipped: {e}") 

153 

154 # Register compute-earnings blueprint (idle-compute self-advertise + 

155 # live drawer SSE + opted-in user wallet readback) 

156 try: 

157 from .api_compute_earnings import compute_earnings_bp 

158 app.register_blueprint(compute_earnings_bp) 

159 logger.info("HevolveSocial compute earnings registered at /api/compute/earnings/") 

160 except Exception as e: 

161 logger.warning(f"HevolveSocial compute earnings blueprint skipped: {e}") 

162 

163 # Register hive contest UI (single-page local view — reads the same 

164 # /api/hive/contest/* endpoints, used by the HART shell panel and 

165 # by a direct browser visit for operators). 

166 try: 

167 from .ui_hive_contest import hive_contest_ui_bp 

168 app.register_blueprint(hive_contest_ui_bp) 

169 logger.info("HevolveSocial hive contest UI registered at /hive-contest") 

170 except Exception as e: 

171 logger.warning(f"HevolveSocial hive contest UI blueprint skipped: {e}") 

172 

173 # Register MCP tool registry blueprint (servers, tools, discover) 

174 try: 

175 from .api_mcp import mcp_bp 

176 app.register_blueprint(mcp_bp) 

177 logger.info("HevolveSocial MCP endpoints registered at /api/social/mcp/") 

178 except Exception as e: 

179 logger.warning(f"HevolveSocial marketplace+MCP blueprint skipped: {e}") 

180 

181 # Register sharing blueprint — canonical OG / share / embed home per 

182 # memory/feedback_unification_reuse_contract.md. Already serves 

183 # /api/social/share/<token>, /api/social/og-image/<type>/<id>, 

184 # /api/social/embed/<type>/<id>. F1.5 wave will EXTEND this same 

185 # blueprint with canonical short URLs (/i/, /c/, /u/, /p/) by 

186 # promoting ``_get_og_metadata`` to public + adding `invite` resource 

187 # type — NOT a parallel og_bp. 

188 try: 

189 from .api_sharing import sharing_bp 

190 app.register_blueprint(sharing_bp) 

191 logger.info("HevolveSocial sharing endpoints registered at /api/social/share/") 

192 except Exception as e: 

193 logger.warning(f"HevolveSocial sharing blueprint skipped: {e}") 

194 

195 # Register multiplayer games + compute lending blueprint 

196 try: 

197 from .api_games import games_bp 

198 app.register_blueprint(games_bp) 

199 logger.info("HevolveSocial games + compute endpoints registered at /api/social/games/, /api/social/compute/") 

200 except Exception as e: 

201 logger.warning(f"HevolveSocial games blueprint skipped: {e}") 

202 

203 # Register discovery blueprint (.well-known/hevolve-social.json) 

204 try: 

205 from .discovery import discovery_bp 

206 app.register_blueprint(discovery_bp) 

207 logger.info("HevolveSocial discovery endpoint registered at /.well-known/hevolve-social.json") 

208 except Exception as e: 

209 logger.debug(f"HevolveSocial discovery blueprint skipped: {e}") 

210 

211 # Register admin API blueprint (channels management, requires admin auth) 

212 try: 

213 from integrations.channels.admin.api import admin_bp 

214 app.register_blueprint(admin_bp) 

215 logger.info("HevolveSocial admin API registered at /api/admin") 

216 except Exception as e: 

217 logger.debug(f"HevolveSocial admin blueprint skipped: {e}") 

218 

219 # Register OAuth click-through blueprint (PR O). /start needs auth, 

220 # /callback is public (state-token authenticated) — separate blueprint 

221 # so admin_bp's before_request gate doesn't 401 the provider redirect. 

222 try: 

223 from integrations.channels.oauth_api import oauth_bp 

224 app.register_blueprint(oauth_bp) 

225 logger.info("HevolveSocial OAuth API registered at /api/oauth") 

226 except Exception as e: 

227 logger.debug(f"HevolveSocial OAuth blueprint skipped: {e}") 

228 

229 # Register user-facing channel bindings API (catalog, bindings, pairing, presence) 

230 try: 

231 from .api_channels import channel_user_bp 

232 app.register_blueprint(channel_user_bp) 

233 logger.info("HevolveSocial channel user API registered at /api/social/channels/") 

234 except Exception as e: 

235 logger.debug(f"HevolveSocial channel user blueprint skipped: {e}") 

236 

237 # Register agent dashboard blueprint (truth-grounded unified agent view) 

238 try: 

239 from .api_dashboard import dashboard_bp 

240 app.register_blueprint(dashboard_bp) 

241 logger.info("HevolveSocial dashboard registered at /api/social/dashboard/") 

242 except Exception as e: 

243 logger.debug(f"HevolveSocial dashboard blueprint skipped: {e}") 

244 

245 # Register thought experiment tracker blueprint 

246 try: 

247 from .api_tracker import tracker_bp 

248 app.register_blueprint(tracker_bp) 

249 logger.info("HevolveSocial tracker registered at /api/social/tracker/") 

250 except Exception as e: 

251 logger.debug(f"HevolveSocial tracker blueprint skipped: {e}") 

252 

253 # Register fleet OTA update approval blueprint 

254 try: 

255 from .api_fleet_update import fleet_update_bp 

256 app.register_blueprint(fleet_update_bp) 

257 logger.info("HevolveSocial fleet update registered at /api/social/fleet/") 

258 except Exception as e: 

259 logger.debug(f"HevolveSocial fleet update blueprint skipped: {e}") 

260 

261 # Register regional host request + approval blueprint 

262 try: 

263 from .api_regional_host import regional_host_bp 

264 app.register_blueprint(regional_host_bp) 

265 logger.info("HevolveSocial regional host registered at /api/social/regional-host/") 

266 except Exception as e: 

267 logger.debug(f"HevolveSocial regional host blueprint skipped: {e}") 

268 

269 # Register sync & backup blueprint 

270 try: 

271 from .sync_api import sync_bp 

272 app.register_blueprint(sync_bp) 

273 logger.info("HevolveSocial sync registered at /api/social/sync/") 

274 except Exception as e: 

275 logger.debug(f"HevolveSocial sync blueprint skipped: {e}") 

276 

277 # Register audit trail blueprint 

278 try: 

279 from .api_audit import audit_bp 

280 app.register_blueprint(audit_bp) 

281 logger.info("HevolveSocial audit registered at /api/social/audit/") 

282 except Exception as e: 

283 logger.debug(f"HevolveSocial audit blueprint skipped: {e}") 

284 

285 # Register content generation task tracking blueprint 

286 try: 

287 from integrations.agent_engine.api_content_gen import content_gen_bp 

288 app.register_blueprint(content_gen_bp) 

289 logger.info("HevolveSocial content gen registered at /api/social/content-gen/") 

290 except Exception as e: 

291 logger.debug(f"HevolveSocial content gen blueprint skipped: {e}") 

292 

293 # Register continual learning CCT management blueprint 

294 try: 

295 from integrations.agent_engine.api_learning import learning_bp 

296 app.register_blueprint(learning_bp) 

297 logger.info("Learning CCT endpoints registered at /api/learning/") 

298 except Exception as e: 

299 logger.debug(f"Learning blueprint skipped: {e}") 

300 

301 # Register OS-wide theme management blueprint 

302 try: 

303 from .api_theme import theme_bp 

304 app.register_blueprint(theme_bp) 

305 logger.info("HevolveSocial theme registered at /api/social/theme/") 

306 except Exception as e: 

307 logger.debug(f"HevolveSocial theme blueprint skipped: {e}") 

308 

309 # Register thought experiments blueprint 

310 try: 

311 from .api_thought_experiments import thought_experiments_bp 

312 app.register_blueprint(thought_experiments_bp) 

313 logger.info("Thought experiment endpoints registered at /api/social/experiments/") 

314 except Exception as e: 

315 logger.debug(f"Thought experiments blueprint skipped: {e}") 

316 

317 # Register encounter (P2P BLE meetup + mutual-like icebreaker) blueprint. 

318 # PR-A alpha skeleton — in-memory state; DB migration v38 lands 

319 # in PR-A beta. Full design: project_encounter_icebreaker.md. 

320 try: 

321 from .encounter_api import encounter_bp 

322 app.register_blueprint(encounter_bp) 

323 logger.info("HevolveSocial encounter registered at /api/social/encounter/") 

324 except Exception as e: 

325 logger.debug(f"HevolveSocial encounter blueprint skipped: {e}") 

326 

327 # Register UserConsent UI blueprint (W0c F3 prereq). JWT-authed, 

328 # append-only consent surface — the SINGLE HTTP write path for 

329 # the user_consents table after the consent-surface consolidation 

330 # (orchestrator review acd11f55, 2026-04-25). consent_service.py 

331 # retains the in-process ConsentService static-method API for 

332 # internal callers; its legacy /api/consent/<user_id>/* HTTP 

333 # route family was removed in the consolidation commit. 

334 try: 

335 from .consent_api import consent_bp 

336 app.register_blueprint(consent_bp) 

337 logger.info("HevolveSocial consent registered at /api/social/consent/") 

338 except Exception as e: 

339 logger.debug(f"HevolveSocial consent blueprint skipped: {e}") 

340 

341 # NOTE: compute_pledge_bp (api_compute_pledge.py) was consolidated into tracker_bp 

342 # and the stale file deleted 2026-04-15. All pledge endpoints live at 

343 # /api/social/tracker/experiments/*/pledge* and /api/social/tracker/pledges/* 

344 # — single source of truth. 

345 

346 # Initialize node keypair for integrity verification 

347 try: 

348 from security.node_integrity import get_or_create_keypair, get_public_key_hex 

349 get_or_create_keypair() 

350 pubkey = get_public_key_hex() 

351 logger.info(f"HevolveSocial node keypair initialized: {pubkey[:16]}...") 

352 except Exception as e: 

353 logger.debug(f"HevolveSocial keypair init skipped: {e}") 

354 

355 # ── Master Key Boot Verification ── 

356 _boot_verified = False 

357 _boot_manifest = None 

358 try: 

359 from security.master_key import full_boot_verification, is_dev_mode, get_enforcement_mode 

360 verification = full_boot_verification() 

361 enforcement = get_enforcement_mode() 

362 _boot_verified = verification['passed'] or is_dev_mode() or enforcement in ('off', 'warn') 

363 _boot_manifest = verification.get('manifest') 

364 if verification['passed']: 

365 logger.info(f"HevolveSocial boot verification PASSED: {verification['details']}") 

366 elif _boot_verified: 

367 logger.warning(f"HevolveSocial boot verification not passed but allowed " 

368 f"(enforcement={enforcement}): {verification['details']}") 

369 else: 

370 logger.critical(f"HevolveSocial boot verification FAILED: {verification['details']}") 

371 except Exception as e: 

372 _boot_verified = True # Allow if master_key module unavailable 

373 logger.debug(f"HevolveSocial boot verification skipped: {e}") 

374 

375 # ── Tier authorization (central must prove master key) ── 

376 try: 

377 from security.key_delegation import verify_tier_authorization 

378 tier_auth = verify_tier_authorization() 

379 if not tier_auth.get('authorized'): 

380 logger.critical(f"Tier authorization FAILED: {tier_auth.get('details', 'unknown')}") 

381 if node_tier == 'central': 

382 _boot_verified = False 

383 logger.critical("Central node cannot start without tier authorization") 

384 except Exception as e: 

385 logger.warning(f"Tier authorization check unavailable: {e}") 

386 

387 # ── System Requirements (HART OS Equilibrium) ── 

388 # Detect hardware, classify contribution tier, auto-gate features. 

389 # Must run BEFORE gossip/agents so env vars are set before they check. 

390 _node_capabilities = None 

391 try: 

392 from security.system_requirements import run_system_check, get_tier_name 

393 _node_capabilities = run_system_check() 

394 _tier_name = get_tier_name() 

395 logger.info( 

396 f"HevolveSocial equilibrium: tier={_tier_name}, " 

397 f"enabled={len(_node_capabilities.enabled_features)} features, " 

398 f"disabled={len(_node_capabilities.disabled_features)} features" 

399 ) 

400 if _node_capabilities.disabled_features: 

401 for _feat, _reason in _node_capabilities.disabled_features.items(): 

402 logger.info(f" Feature '{_feat}' not loaded: {_reason}") 

403 except Exception as e: 

404 logger.warning(f"HevolveSocial system requirements check skipped: {e}") 

405 # Auto-enable agent engine if not explicitly disabled 

406 import os as _os_fb 

407 if _os_fb.environ.get('HEVOLVE_AGENT_ENGINE_ENABLED') is None: 

408 _os_fb.environ['HEVOLVE_AGENT_ENGINE_ENABLED'] = 'true' 

409 

410 # Start decentralized gossip peer discovery (background thread) 

411 if _boot_verified: 

412 try: 

413 from .peer_discovery import gossip 

414 gossip.start() 

415 logger.info(f"HevolveSocial gossip started: node={gossip.node_id[:8]}, " 

416 f"seeds={len(gossip.seed_peers)}") 

417 except Exception as e: 

418 logger.debug(f"HevolveSocial gossip start skipped: {e}") 

419 

420 # Start zero-config LAN auto-discovery (additive to seed peers) 

421 import os as _os_disc 

422 if _os_disc.environ.get('HEVOLVE_AUTO_DISCOVERY', 'true').lower() != 'false': 

423 try: 

424 from .peer_discovery import auto_discovery 

425 auto_discovery.start() 

426 logger.info(f"HevolveSocial auto-discovery started " 

427 f"(UDP port {auto_discovery._port})") 

428 except Exception as e: 

429 logger.debug(f"HevolveSocial auto-discovery skipped: {e}") 

430 

431 # Start runtime integrity monitor if we have a signed manifest 

432 if _boot_manifest: 

433 try: 

434 from security.runtime_monitor import start_monitor 

435 start_monitor(_boot_manifest) 

436 logger.info("HevolveSocial runtime integrity monitor started") 

437 except Exception as e: 

438 logger.debug(f"HevolveSocial runtime monitor start skipped: {e}") 

439 else: 

440 logger.critical("HevolveSocial: gossip NOT started - boot verification failed (hard mode)") 

441 

442 # Start sync engine for regional/local tiers 

443 if _boot_verified: 

444 try: 

445 from security.key_delegation import get_node_tier 

446 node_tier = get_node_tier() 

447 if node_tier in ('regional', 'local'): 

448 from .sync_engine import sync_engine 

449 sync_engine.start_background_sync() 

450 logger.info(f"HevolveSocial sync engine started (tier={node_tier})") 

451 except Exception as e: 

452 logger.debug(f"HevolveSocial sync engine start skipped: {e}") 

453 

454 # Start distributed coding agent if enabled. Default flipped to 

455 # 'true' on 2026-05-07 — the daemon consumes self_heal goals 

456 # produced by error_advice (#102) and SelfHealingDispatcher; with 

457 # default 'false' the queue piled up indefinitely (15 stale goals 

458 # back to 2026-04-27 in the live DB at audit time). Safety is in 

459 # the daemon itself (no idle agents → early return; budget gate; 

460 # 30s poll cadence). Servers that don't want it set explicitly. 

461 import os as _os2 

462 if _os2.environ.get('HEVOLVE_CODING_AGENT_ENABLED', 'true').lower() == 'true': 

463 try: 

464 from integrations.coding_agent import init_coding_agent 

465 init_coding_agent(app) 

466 logger.info("HevolveSocial distributed coding agent initialized") 

467 except Exception as e: 

468 logger.debug(f"HevolveSocial coding agent init skipped: {e}") 

469 

470 # Agent engine init is the SINGLE responsibility of Nunba's 

471 # `main.py:_deferred_social_init` (or any standalone HARTOS launcher 

472 # that calls `init_agent_engine` directly). Calling it from inside 

473 # `init_social` produced a double-invocation in Nunba (main.py calls 

474 # init_social → init_social calls init_agent_engine → main.py calls 

475 # init_agent_engine again right after), and the deadlock smoking 

476 # gun on 2026-04-28 was exactly this path: the second invocation 

477 # fired while hartos-init's `from hart_intelligence import app` was 

478 # still mid-import, deadlocking on the per-module import lock. 

479 # Idempotency in init_agent_engine itself (added 2026-04-28) makes 

480 # the second call a no-op, but the cleaner contract is: ONE caller, 

481 # ONE call site. init_social no longer initialises the agent engine 

482 # — its caller does. 

483 logger.debug("HevolveSocial: agent engine init delegated to caller " 

484 "(see Nunba main.py:_deferred_social_init or HARTOS launcher)") 

485 

486 # Register with central registry if configured 

487 import os 

488 registry_url = os.environ.get('HEVOLVE_REGISTRY_URL', '') 

489 if registry_url and _boot_verified: 

490 try: 

491 from .integrity_service import IntegrityService 

492 from .peer_discovery import gossip as _gossip 

493 from security.node_integrity import get_public_key_hex as _get_pubkey 

494 IntegrityService.register_with_registry( 

495 registry_url, _gossip.node_id, _get_pubkey(), _gossip.version) 

496 logger.info(f"HevolveSocial registered with registry: {registry_url}") 

497 except Exception as e: 

498 logger.debug(f"HevolveSocial registry registration skipped: {e}") 

499 

500 # ── NodeWatchdog - start LAST, monitors all daemon threads ── 

501 try: 

502 from security.node_watchdog import start_watchdog 

503 watchdog = start_watchdog() 

504 

505 # Register gossip — interval must exceed worst-case gossip round 

506 # (3 peers × 10s timeout = 30s max) to avoid false FROZEN alerts. 

507 if _boot_verified: 

508 try: 

509 from .peer_discovery import gossip as _g 

510 if _g._running: 

511 watchdog.register('gossip', expected_interval=120, 

512 restart_fn=_g.start, stop_fn=_g.stop) 

513 except Exception: 

514 pass 

515 

516 # Register auto-discovery 

517 try: 

518 from .peer_discovery import auto_discovery as _ad 

519 if _ad._running: 

520 watchdog.register('auto_discovery', 

521 expected_interval=_ad._beacon_interval, 

522 restart_fn=_ad.start, stop_fn=_ad.stop) 

523 except Exception: 

524 pass 

525 

526 # Register runtime monitor 

527 if _boot_manifest: 

528 try: 

529 from security.runtime_monitor import get_monitor 

530 mon = get_monitor() 

531 if mon and mon._running: 

532 watchdog.register('runtime_monitor', 

533 expected_interval=mon._check_interval, 

534 restart_fn=mon.start, stop_fn=mon.stop) 

535 except Exception: 

536 pass 

537 

538 # Register sync engine 

539 try: 

540 from .sync_engine import sync_engine as _se 

541 if _se._running: 

542 watchdog.register('sync_engine', 

543 expected_interval=_se._interval, 

544 restart_fn=_se.start_background_sync, 

545 stop_fn=_se.stop_background_sync) 

546 except Exception: 

547 pass 

548 

549 # Register agent daemon 

550 try: 

551 from integrations.agent_engine.agent_daemon import agent_daemon as _agent_d 

552 if _agent_d._running: 

553 watchdog.register('agent_daemon', 

554 expected_interval=_agent_d._interval, 

555 restart_fn=_agent_d.start, stop_fn=_agent_d.stop) 

556 except Exception: 

557 pass 

558 

559 # Register coding daemon 

560 try: 

561 from integrations.coding_agent.coding_daemon import coding_daemon as _coding_d 

562 if _coding_d._running: 

563 watchdog.register('coding_daemon', 

564 expected_interval=_coding_d._interval, 

565 restart_fn=_coding_d.start, stop_fn=_coding_d.stop) 

566 except Exception: 

567 pass 

568 

569 # Register model lifecycle manager — interval must exceed worst-case 

570 # tick duration (nvidia-smi 5s + pressure checks + federation report). 

571 try: 

572 from integrations.service_tools.model_lifecycle import get_model_lifecycle_manager 

573 _lifecycle = get_model_lifecycle_manager() 

574 _lifecycle.start() 

575 if _lifecycle._running: 

576 watchdog.register('model_lifecycle', 

577 expected_interval=max(_lifecycle._interval * 3, 60), 

578 restart_fn=_lifecycle.start, 

579 stop_fn=_lifecycle.stop) 

580 logger.info("Model lifecycle manager started") 

581 except Exception as e: 

582 logger.debug(f"Model lifecycle manager start skipped: {e}") 

583 

584 # Distributed worker loop — claims tasks from shared Redis queue. 

585 # Self-gates: start() is a no-op when Redis is unreachable. 

586 try: 

587 from integrations.distributed_agent.worker_loop import worker_loop as _wl 

588 _wl.start() 

589 if _wl._running: 

590 watchdog.register('distributed_worker', 

591 expected_interval=_wl._interval * 4, 

592 restart_fn=_wl.start, 

593 stop_fn=_wl.stop) 

594 logger.info("Distributed worker loop started") 

595 except Exception as e: 

596 logger.debug(f"Distributed worker loop start skipped: {e}") 

597 

598 # Hive benchmark prover — rotates model benchmarks every 6 hours 

599 # and publishes baseline+score deltas into the ledger. 

600 try: 

601 from integrations.agent_engine.hive_benchmark_prover import ( 

602 get_benchmark_prover, _LOOP_INTERVAL_SECONDS as _hbp_interval, 

603 ) 

604 _hbp = get_benchmark_prover() 

605 _hbp.start_continuous_loop() 

606 if _hbp._loop_running: 

607 watchdog.register('hive_benchmark_prover', 

608 expected_interval=_hbp_interval * 2, 

609 restart_fn=_hbp.start_continuous_loop, 

610 stop_fn=_hbp.stop) 

611 logger.info("Hive benchmark prover started") 

612 except Exception as e: 

613 logger.debug(f"Hive benchmark prover start skipped: {e}") 

614 

615 watchdog.start() 

616 logger.info(f"NodeWatchdog started: monitoring " 

617 f"{len(watchdog._threads)} threads") 

618 except Exception as e: 

619 logger.debug(f"NodeWatchdog start skipped: {e}") 

620 

621 # Sync trained agents as social users on first request 

622 @app.before_request 

623 def _sync_agents_once(): 

624 if not getattr(app, '_social_agents_synced', False): 

625 app._social_agents_synced = True 

626 try: 

627 from .agent_bridge import sync_trained_agents 

628 count = sync_trained_agents() 

629 if count > 0: 

630 logger.info(f"HevolveSocial: synced {count} trained agents as social users") 

631 except Exception as e: 

632 logger.debug(f"HevolveSocial agent sync skipped: {e}") 

633 

634 

635# Module-level lazy attribute: from integrations.social import social_bp 

636def __getattr__(name): 

637 if name == 'social_bp': 

638 return get_social_blueprint() 

639 raise AttributeError(f"module {__name__!r} has no attribute {name!r}")