@phase2 @acms @analyzer
Feature: Domain-Specific Analyzers
  As a CleverAgents developer
  I want domain-specific analyzers that produce UKO triples from resources
  So that the ACMS can index code, documents, SQL, and infrastructure into the UKO knowledge graph

  # ---------------------------------------------------------------------------
  # AnalyzerProtocol conformance
  # ---------------------------------------------------------------------------

  @analyzer_protocol
  Scenario: PythonAnalyzer satisfies AnalyzerProtocol
    Given a PythonAnalyzer analyzer
    Then the analyzer should satisfy the AnalyzerProtocol
    And the current analyzer domain should be "python"

  @analyzer_protocol
  Scenario: MarkdownAnalyzer satisfies AnalyzerProtocol
    Given a MarkdownAnalyzer analyzer
    Then the analyzer should satisfy the AnalyzerProtocol
    And the current analyzer domain should be "markdown"

  @analyzer_protocol
  Scenario: PostgreSQLAnalyzer satisfies AnalyzerProtocol
    Given a PostgreSQLAnalyzer analyzer
    Then the analyzer should satisfy the AnalyzerProtocol
    And the current analyzer domain should be "postgresql"

  @analyzer_protocol
  Scenario: DockerComposeAnalyzer satisfies AnalyzerProtocol
    Given a DockerComposeAnalyzer analyzer
    Then the analyzer should satisfy the AnalyzerProtocol
    And the current analyzer domain should be "docker-compose"

  # ---------------------------------------------------------------------------
  # AnalyzerRegistry
  # ---------------------------------------------------------------------------

  @analyzer_registry
  Scenario: Register all 4 analyzers and verify count
    Given a fresh analyzer registry
    When I register all 4 domain analyzers
    Then the registry should contain 4 analyzers

  @analyzer_registry
  Scenario: Lookup by extension returns correct analyzer for .py
    Given a fresh analyzer registry with all domain analyzers registered
    When I look up extension ".py" in the registry
    Then the current analyzer domain should be "python"

  @analyzer_registry
  Scenario: Lookup by extension returns correct analyzer for .sql
    Given a fresh analyzer registry with all domain analyzers registered
    When I look up extension ".sql" in the registry
    Then the current analyzer domain should be "postgresql"

  @analyzer_registry
  Scenario: Lookup for unknown extension returns None
    Given a fresh analyzer registry with all domain analyzers registered
    When I look up extension ".rs" in the registry
    Then the extension lookup result should be None

  @analyzer_registry
  Scenario: Register duplicate extension first wins
    Given a fresh analyzer registry
    When I register a PythonAnalyzer
    And I register a duplicate analyzer that also claims ".py"
    And I look up extension ".py" in the registry
    Then the current analyzer domain should be "python"

  @analyzer_registry
  Scenario: list_extensions returns all registered extensions
    Given a fresh analyzer registry with all domain analyzers registered
    Then the registry extensions should include ".py"
    And the registry extensions should include ".pyi"
    And the registry extensions should include ".md"
    And the registry extensions should include ".markdown"
    And the registry extensions should include ".sql"
    And the registry extensions should include ".ddl"
    And the registry extensions should include ".yml"
    And the registry extensions should include ".yaml"

  # ---------------------------------------------------------------------------
  # PythonAnalyzer
  # ---------------------------------------------------------------------------

  @python_analyzer
  Scenario: Analyze Python class definition
    Given a PythonAnalyzer analyzer
    When I analyze the Python content:
      """
      class MyService:
          pass
      """
    Then the triples should include predicate "rdf:type" with object_uri "uko-code:Module"
    And the triples should include predicate "rdf:type" with object_uri "uko-py:Class"
    And the triples should include predicate "uko:contains" linking subject "module" to object "MyService"

  @python_analyzer
  Scenario: Analyze Python function with docstring
    Given a PythonAnalyzer analyzer
    When I analyze the Python content:
      """
      def process_data():
          '''Process incoming data.'''
          pass
      """
    Then the triples should include predicate "rdf:type" with object_uri "uko-py:Function"
    And the triples should include predicate "uko-doc:hasDocstring"

  @python_analyzer
  Scenario: Analyze Python imports
    Given a PythonAnalyzer analyzer
    When I analyze the Python content:
      """
      import os
      from pathlib import Path
      """
    Then the triples should include predicate "uko:references" with object_uri containing "os"
    And the triples should include predicate "uko:references" with object_uri containing "pathlib"

  @python_analyzer
  Scenario: Analyze empty Python content raises ValueError
    Given a PythonAnalyzer analyzer
    Then analyzing empty content with this analyzer should raise ValueError

  @python_analyzer
  Scenario: Analyze invalid Python syntax returns empty list
    Given a PythonAnalyzer analyzer
    When I analyze the Python content:
      """
      def broken(
          pass
      class ???
      """
    Then no triples should be returned

  # ---------------------------------------------------------------------------
  # MarkdownAnalyzer
  # ---------------------------------------------------------------------------

  @markdown_analyzer
  Scenario: Analyze heading hierarchy
    Given a MarkdownAnalyzer analyzer
    When I analyze the Markdown content:
      """
      # Introduction
      Some text.
      ## Details
      More text.
      """
    Then the triples should include predicate "rdf:type" with object_uri "uko-doc:Document"
    And the triples should include predicate "rdf:type" with object_uri "uko-doc:Section"
    And the triples should include predicate "uko-doc:headingLevel" with object_value "1"
    And the triples should include predicate "uko-doc:headingLevel" with object_value "2"

  @markdown_analyzer
  Scenario: Analyze code block with language
    Given a MarkdownAnalyzer analyzer
    When I analyze the Markdown content:
      """
      # Example
      ```python
      print("hello")
      ```
      """
    Then the triples should include predicate "rdf:type" with object_uri "uko-code:CodeBlock"
    And the triples should include predicate "uko-code:language" with object_value "python"

  @markdown_analyzer
  Scenario: Analyze links
    Given a MarkdownAnalyzer analyzer
    When I analyze the Markdown content:
      """
      # Resources
      See [Example](https://example.com) for details.
      """
    Then the triples should include predicate "uko:references" with object_value "https://example.com"

  @markdown_analyzer
  Scenario: Analyze empty Markdown content raises ValueError
    Given a MarkdownAnalyzer analyzer
    Then analyzing empty content with this analyzer should raise ValueError

  @markdown_analyzer
  Scenario: Analyze content with no headings still produces Document triple
    Given a MarkdownAnalyzer analyzer
    When I analyze the Markdown content:
      """
      Just some plain text without any headings.
      Another line of text.
      """
    Then the triples should include predicate "rdf:type" with object_uri "uko-doc:Document"
    And the triples should not include predicate "rdf:type" with object_uri "uko-doc:Section"

  # ---------------------------------------------------------------------------
  # Cross-analyzer
  # ---------------------------------------------------------------------------

  @analyzer_cross
  Scenario: All analyzers use UKO URI scheme
    Given a PythonAnalyzer analyzer
    And a MarkdownAnalyzer analyzer
    And a PostgreSQLAnalyzer analyzer
    And a DockerComposeAnalyzer analyzer
    When each analyzer processes its sample content
    Then every triple subject_uri should start with "uko://"

  @analyzer_cross
  Scenario: Confidence scores default to 1.0
    Given a PythonAnalyzer analyzer
    When I analyze the Python content:
      """
      class Example:
          pass
      """
    Then every triple confidence should be 1.0
