@unit @repository @remaining_branches
Feature: Repository remaining branches and lines coverage
  Exercise the last uncovered lines and branches in repositories.py:
  - ToolRepository.add DuplicateToolError re-raise (lines 3541-3542)
  - ToolRepository.add DatabaseError wrap (line 3542)
  - ToolRepository.get_by_name success path returning domain (line 3558)
  - ResourceRepository.link_child when parent type row is absent (branch 2298→2310)
  - ResourceRepository.resolve_namespaced_name ULID fallback (branch 2711→2714)
  - ResourceRepository.get_children returning populated list (branch 2426→2420)
  - ResourceRepository.get_parents returning populated list (branch 2459→2453)
  - ResourceRepository._get_ancestors via link_child cycle detection (branch 2635→2633)
  - ResourceRepository._build_cycle_path via link_child (branch 2661→2659)
  - NamespacedProjectRepository.update success path (branch 2928→2931)
  - AutomationProfileRepository.upsert inserting brand new profile (branch 4193→4200)
  - ValidationAttachmentRepository.attach with project_name scope (branch 3633→3634)
  - LifecyclePlanRepository.update with multiple project links (branch 1395→1394)

  # ── ToolRepository.add: DuplicateToolError re-raise ───────────

  Scenario: remaining cov tool add re-raises DuplicateToolError for duplicate tool
    Given remaining cov an in-memory database with tool tables
    And remaining cov a tool "local/dup-tool" has been added
    When remaining cov the same tool "local/dup-tool" is added again
    Then remaining cov a DuplicateToolError should be raised for the duplicate

  # ── ToolRepository.add: DatabaseError wrapping ────────────────

  Scenario: remaining cov tool add wraps non-duplicate DatabaseError
    Given remaining cov a ToolRepository with a session that raises DatabaseError on create
    When remaining cov a tool is added and a DatabaseError is expected
    Then remaining cov a DatabaseError mentioning "Failed to add tool" should be raised

  # ── ToolRepository.get_by_name: success returns domain ────────

  Scenario: remaining cov tool get_by_name returns domain object for existing tool
    Given remaining cov an in-memory database with tool tables
    And remaining cov a tool "local/findable-tool" has been added
    When remaining cov get_by_name is invoked for "local/findable-tool"
    Then remaining cov get_by_name should return a non-None result with name "local/findable-tool"

  # ── ResourceRepository.link_child: parent type row absent ─────

  Scenario: remaining cov link_child succeeds when parent type row is missing from DB
    Given remaining cov an in-memory resource database
    And remaining cov two resources with a type that has no ResourceTypeModel row
    When remaining cov link_child is called for those resources
    Then remaining cov the link should be created successfully

  # ── ResourceRepository.resolve_namespaced_name: ULID fallback ─

  Scenario: remaining cov resolve_namespaced_name falls back to ULID lookup
    Given remaining cov an in-memory resource database
    And remaining cov a resource exists with a known ULID but no namespaced name
    When remaining cov resolve_namespaced_name is called with the ULID
    Then remaining cov the resource should be resolved successfully

  Scenario: remaining cov resolve_namespaced_name returns None for unknown ULID
    Given remaining cov an in-memory resource database
    When remaining cov resolve_namespaced_name is called with unknown ULID "01JQXG0000000000000000ZZZZ"
    Then remaining cov resolve_namespaced_name should return None

  # ── ResourceRepository.get_children: populated list ───────────

  Scenario: remaining cov get_children returns linked child resources
    Given remaining cov an in-memory resource database
    And remaining cov a parent resource linked to two child resources
    When remaining cov get_children is called on the parent resource
    Then remaining cov 2 child resources should be returned

  # ── ResourceRepository.get_parents: populated list ────────────

  Scenario: remaining cov get_parents returns linked parent resources
    Given remaining cov an in-memory resource database
    And remaining cov a child resource linked from two parent resources
    When remaining cov get_parents is called on the child resource
    Then remaining cov 2 parent resources should be returned

  # ── ResourceRepository._get_ancestors + _build_cycle_path ─────

  Scenario: remaining cov link_child detects cycle and builds cycle path
    Given remaining cov an in-memory resource database
    And remaining cov resources "cyc-A" and "cyc-B" linked as A->B
    When remaining cov link_child is called to create B->A forming a cycle
    Then remaining cov a CycleDetectedError should be raised with a path

  # ── NamespacedProjectRepository.update: success path ──────────

  Scenario: remaining cov project update succeeds for existing project
    Given remaining cov an in-memory project database
    And remaining cov a project "local/updatable-proj" exists
    When remaining cov the project "local/updatable-proj" is updated with new description
    Then remaining cov the project update should succeed

  # ── AutomationProfileRepository.upsert: new insert path ──────

  Scenario: remaining cov profile upsert inserts a new profile when none exists
    Given remaining cov an in-memory automation profile database
    When remaining cov a brand new profile "local/fresh-profile" is upserted
    Then remaining cov the profile "local/fresh-profile" should be retrievable

  # ── ValidationAttachmentRepository.attach: project_name scope ─

  Scenario: remaining cov validation attach with project_name scope only
    Given remaining cov an in-memory database with validation tables
    When remaining cov a validation is attached using project scope "my-project"
    Then remaining cov the returned attachment has project_name "my-project"

  Scenario: remaining cov validation attach with both project and plan scope
    Given remaining cov an in-memory database with validation tables
    When remaining cov a validation is attached using project-plan scope "proj-x" "PLAN-42"
    Then remaining cov the returned attachment has project "proj-x" and plan "PLAN-42"

  # ── LifecyclePlanRepository.update: multiple project links ────

  Scenario: remaining cov plan update iterates over multiple project links
    Given remaining cov an in-memory lifecycle plan database
    And remaining cov a plan with action "local/multi-link-action" exists
    When remaining cov the plan is updated with 3 project links
    Then remaining cov the plan should have 3 project links after retrieval
