-
Notifications
You must be signed in to change notification settings - Fork 0
feat: l9-codegraph — CodeGraph + PlanGraph dual-graph engine #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,177 @@ | ||
| # --- L9_META --- | ||
| # l9_schema: 1 | ||
| # layer: [domain] | ||
| # tags: [plangraph, constellation, revopsos] | ||
| # status: active | ||
| # --- /L9_META --- | ||
| # RevOpsOS constellation — 8-service revenue operations platform | ||
|
|
||
| constellation: revopsos | ||
|
|
||
| services: | ||
| ENRICH: | ||
| status: built | ||
| description: Contact and company data enrichment from external sources | ||
| depends_on: [] | ||
|
|
||
| GRAPH: | ||
| status: built | ||
| description: Relationship graph engine — maps accounts, contacts, and deals | ||
| depends_on: [] | ||
|
|
||
| SCORE: | ||
| status: planned | ||
| description: ML-based lead and account scoring | ||
| depends_on: [ENRICH, GRAPH] | ||
|
|
||
| ROUTE: | ||
| status: planned | ||
| description: Intelligent lead and opportunity routing to reps/queues | ||
| depends_on: [SCORE, GRAPH] | ||
|
|
||
| FORECAST: | ||
| status: planned | ||
| description: Revenue forecast engine using pipeline + historical signals | ||
| depends_on: [SCORE, ROUTE] | ||
|
|
||
| SIGNAL: | ||
| status: planned | ||
| description: Real-time intent and behavioral signal ingestion | ||
| depends_on: [ENRICH] | ||
|
|
||
| HEALTH: | ||
| status: planned | ||
| description: Account health scoring and churn risk detection | ||
| depends_on: [SCORE, ENRICH] | ||
|
|
||
| HANDOFF: | ||
| status: planned | ||
| description: Sales-to-CS handoff automation and playbook execution | ||
| depends_on: [ROUTE, SCORE] | ||
|
|
||
| interfaces: | ||
| - name: enrich_inbound | ||
| service: ENRICH | ||
| direction: inbound | ||
| protocol: http | ||
| description: Accepts raw contact/company records for enrichment | ||
|
|
||
| - name: enrich_outbound | ||
| service: ENRICH | ||
| direction: outbound | ||
| protocol: http | ||
| description: Emits enriched records to downstream services | ||
|
|
||
| - name: graph_inbound | ||
| service: GRAPH | ||
| direction: inbound | ||
| protocol: bolt | ||
| description: Receives entity relationship data | ||
|
|
||
| - name: graph_query | ||
| service: GRAPH | ||
| direction: outbound | ||
| protocol: bolt | ||
| description: Serves graph queries to SCORE and ROUTE | ||
|
|
||
| - name: score_inbound | ||
| service: SCORE | ||
| direction: inbound | ||
| protocol: http | ||
| description: Accepts enriched + graph data for scoring | ||
|
|
||
| - name: score_outbound | ||
| service: SCORE | ||
| direction: outbound | ||
| protocol: http | ||
| description: Emits scored leads/accounts to ROUTE, FORECAST, HEALTH, HANDOFF | ||
|
|
||
| - name: route_inbound | ||
| service: ROUTE | ||
| direction: inbound | ||
| protocol: http | ||
| description: Accepts scored leads for routing decisions | ||
|
|
||
| - name: route_outbound | ||
| service: ROUTE | ||
| direction: outbound | ||
| protocol: http | ||
| description: Emits routing decisions to CRM and HANDOFF | ||
|
|
||
| - name: forecast_inbound | ||
| service: FORECAST | ||
| direction: inbound | ||
| protocol: http | ||
| description: Accepts pipeline + score data for forecasting | ||
|
|
||
| - name: signal_inbound | ||
| service: SIGNAL | ||
| direction: inbound | ||
| protocol: webhook | ||
| description: Receives real-time behavioral events | ||
|
|
||
| - name: signal_outbound | ||
| service: SIGNAL | ||
| direction: outbound | ||
| protocol: http | ||
| description: Forwards processed signals to ENRICH and SCORE | ||
|
|
||
| - name: health_inbound | ||
| service: HEALTH | ||
| direction: inbound | ||
| protocol: http | ||
| description: Accepts account data for health scoring | ||
|
|
||
| - name: handoff_inbound | ||
| service: HANDOFF | ||
| direction: inbound | ||
| protocol: http | ||
| description: Triggers handoff workflows from routing decisions | ||
|
|
||
| flows: | ||
| - from: ENRICH | ||
| to: SCORE | ||
| label: enriched_data | ||
|
|
||
| - from: GRAPH | ||
| to: SCORE | ||
| label: graph_context | ||
|
|
||
| - from: SCORE | ||
| to: ROUTE | ||
| label: scored_leads | ||
|
|
||
| - from: SCORE | ||
| to: FORECAST | ||
| label: score_signals | ||
|
|
||
| - from: SCORE | ||
| to: HEALTH | ||
| label: health_inputs | ||
|
|
||
| - from: SCORE | ||
| to: HANDOFF | ||
| label: handoff_triggers | ||
|
|
||
| - from: ROUTE | ||
| to: FORECAST | ||
| label: routing_outcomes | ||
|
|
||
| - from: ROUTE | ||
| to: HANDOFF | ||
| label: handoff_assignments | ||
|
|
||
| - from: SIGNAL | ||
| to: ENRICH | ||
| label: signal_enrichment | ||
| feedback: false | ||
|
|
||
| - from: HANDOFF | ||
| to: ROUTE | ||
| label: handoff_feedback | ||
| feedback: true | ||
|
|
||
| - from: FORECAST | ||
| to: SCORE | ||
| label: forecast_feedback | ||
| feedback: true | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| # --- L9_META --- | ||
| # l9_schema: 1 | ||
| # layer: [api] | ||
| # tags: [chassis, lifecycle, boot] | ||
| # status: active | ||
| # --- /L9_META --- | ||
| """engine/boot.py — CodegraphLifecycle: chassis LifecycleHook for l9-codegraph.""" | ||
| from __future__ import annotations | ||
|
|
||
| import logging | ||
| from typing import Any | ||
|
|
||
| from chassis.chassis_app import LifecycleHook | ||
| from engine.settings import Settings | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
| settings = Settings() | ||
|
|
||
|
|
||
| class CodegraphLifecycle(LifecycleHook): | ||
| """Wires Neo4j connections for CodeGraph + PlanGraph engines.""" | ||
|
|
||
| def __init__(self) -> None: | ||
| self._driver: Any = None | ||
|
|
||
| async def startup(self) -> None: | ||
| logger.info("CodegraphLifecycle.startup — Neo4j: %s", settings.neo4j_uri) | ||
| # Import here to avoid loading neo4j at module level (keeps tests fast) | ||
| from neo4j import AsyncGraphDatabase | ||
| self._driver = AsyncGraphDatabase.driver( | ||
| settings.neo4j_uri, | ||
| auth=(settings.neo4j_user, settings.neo4j_password), | ||
| ) | ||
| logger.info("CodegraphLifecycle.startup complete") | ||
|
Comment on lines
+26
to
+34
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Driver created at startup is unused. The Consider either:
Current implementation creates unnecessary Neo4j connections. Option A: Remove unused driver setupIf handlers will continue managing their own connections: async def startup(self) -> None:
logger.info("CodegraphLifecycle.startup — Neo4j: %s", settings.neo4j_uri)
- # Import here to avoid loading neo4j at module level (keeps tests fast)
- from neo4j import AsyncGraphDatabase
- self._driver = AsyncGraphDatabase.driver(
- settings.neo4j_uri,
- auth=(settings.neo4j_user, settings.neo4j_password),
- )
+ # Handlers manage their own Neo4j connections
logger.info("CodegraphLifecycle.startup complete")
async def shutdown(self) -> None:
- if self._driver:
- await self._driver.close()
logger.info("CodegraphLifecycle.shutdown complete")🤖 Prompt for AI Agents |
||
|
|
||
| async def shutdown(self) -> None: | ||
| if self._driver: | ||
| await self._driver.close() | ||
| logger.info("CodegraphLifecycle.shutdown complete") | ||
|
|
||
| async def execute( | ||
| self, | ||
| action: str, | ||
| payload: dict[str, Any], | ||
| tenant: str, | ||
| trace_id: str, | ||
| ) -> dict[str, Any]: | ||
| logger.info("execute action=%s tenant=%s trace_id=%s", action, tenant, trace_id) | ||
| # Inject tenant + trace_id into payload so handlers can log them | ||
| enriched = {**payload, "tenant": tenant, "trace_id": trace_id} | ||
|
|
||
| try: | ||
| if action == "search_codegraph": | ||
| from engine.codegraph.handler import handle_search_codegraph | ||
| data = await handle_search_codegraph(enriched) | ||
| elif action == "build_codegraph": | ||
| from engine.codegraph.handler import handle_build_codegraph | ||
| data = await handle_build_codegraph(enriched) | ||
| elif action == "search_plangraph": | ||
| from engine.plangraph.handler import handle_search_plangraph | ||
| data = await handle_search_plangraph(enriched) | ||
| elif action == "build_order": | ||
| from engine.plangraph.handler import handle_build_order | ||
| data = await handle_build_order(enriched) | ||
| elif action == "check_drift": | ||
| from engine.plangraph.handler import handle_check_drift | ||
| data = await handle_check_drift(enriched) | ||
| elif action == "load_constellation": | ||
| from engine.plangraph.handler import handle_load_constellation | ||
| data = await handle_load_constellation(enriched) | ||
| elif action == "health": | ||
| data = {"status": "healthy", "service": "l9-codegraph"} | ||
| else: | ||
| return { | ||
| "status": "failed", | ||
| "action": action, | ||
| "tenant": tenant, | ||
| "data": {"error": f"Unknown action: '{action}'"}, | ||
| "meta": {"trace_id": trace_id}, | ||
| } | ||
| except Exception as exc: | ||
| logger.exception("Handler failed action=%s: %s", action, exc) | ||
| return { | ||
| "status": "failed", | ||
| "action": action, | ||
| "tenant": tenant, | ||
| "data": {"error": str(exc)}, | ||
| "meta": {"trace_id": trace_id}, | ||
| } | ||
|
|
||
| return { | ||
| "status": "ok", | ||
| "action": action, | ||
| "tenant": tenant, | ||
| "data": data, | ||
| "meta": {"trace_id": trace_id}, | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| # --- L9_META --- | ||
| # l9_schema: 1 | ||
| # layer: [engine] | ||
| # tags: [codegraph, repograph] | ||
| # status: active | ||
| # --- /L9_META --- | ||
| """Code Graph Engine — RepoGraph-inspired structural code intelligence.""" | ||
|
|
||
| from .builder import CodeGraphBuilder | ||
| from .retriever import EgoGraphRetriever | ||
|
|
||
| __all__ = ["CodeGraphBuilder", "EgoGraphRetriever"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add YAML document start marker.
The YAML linter flags a missing document start marker. Adding
---improves YAML standards compliance and compatibility with multi-document parsers.📝 Proposed fix
# --- L9_META --- # l9_schema: 1 # layer: [domain] # tags: [plangraph, constellation, revopsos] # status: active # --- /L9_META --- +--- # RevOpsOS constellation — 8-service revenue operations platform constellation: revopsos📝 Committable suggestion
🧰 Tools
🪛 GitHub Check: YAML Validation
[warning] 9-9:
9:1 [document-start] missing document start "---"
🤖 Prompt for AI Agents