Feature: Namespaced Project Domain Model As a developer I want spec-aligned project domain models So that projects use namespaced names with linked resources # parse_namespaced_name Scenario: Parse bare name defaults to local namespace When I parse the project namespaced name "my-project" Then the nsproject parsed namespace should be "local" And the nsproject parsed name should be "my-project" And the nsproject parsed server should be empty Scenario: Parse name with explicit namespace When I parse the project namespaced name "freemo/code-coverage" Then the nsproject parsed namespace should be "freemo" And the nsproject parsed name should be "code-coverage" And the nsproject parsed server should be empty Scenario: Parse name with server qualifier When I parse the project namespaced name "dev:freemo/code-coverage" Then the nsproject parsed server should be "dev" And the nsproject parsed namespace should be "freemo" And the nsproject parsed name should be "code-coverage" Scenario: Parse local namespace When I parse the project namespaced name "local/my-project" Then the nsproject parsed namespace should be "local" And the nsproject parsed name should be "my-project" Scenario: ParsedName qualified_name with server When I parse the project namespaced name "prod:myorg/api" Then the nsproject qualified name should be "prod:myorg/api" Scenario: ParsedName qualified_name without server When I parse the project namespaced name "myorg/api" Then the nsproject qualified name should be "myorg/api" Scenario: ParsedName namespaced_name When I parse the project namespaced name "dev:myorg/api" Then the nsproject namespaced name should be "myorg/api" Scenario: ParsedName is_local for bare name When I parse the project namespaced name "my-project" Then the nsproject parsed name should be local Scenario: ParsedName is_remote with server When I parse the project namespaced name "dev:myorg/api" Then the nsproject parsed name should be remote Scenario: ParsedName is_remote with non-local namespace When I parse the project namespaced name "freemo/api" Then the nsproject parsed name should be remote Scenario: Reject empty name When I try to parse an empty project namespaced name Then a nsproject validation error should be raised Scenario: Reject reserved namespace system When I try to parse the project namespaced name "system/my-project" Then a nsproject validation error should be raised Scenario: Reject reserved namespace admin When I try to parse the project namespaced name "admin/my-project" Then a nsproject validation error should be raised Scenario: Reject provider namespace openai When I try to parse the project namespaced name "openai/my-project" Then a nsproject validation error should be raised Scenario: Reject provider namespace anthropic When I try to parse the project namespaced name "anthropic/my-model" Then a nsproject validation error should be raised Scenario: Reject invalid characters in name When I try to parse the project namespaced name "my@project" Then a nsproject validation error should be raised # TemporalScope enum Scenario: TemporalScope has three values Then the nsproject TemporalScope enum should have values "current, recent, all" # ContextConfig model Scenario: ContextConfig defaults Given a default ContextConfig Then the nsproject ctx max_file_size should be 1000000 And the nsproject ctx max_total_size should be 52428800 And the nsproject ctx indexing_strategy should be "full_text" And the nsproject ctx chunking_policy should be "smart" And the nsproject ctx chunk_size should be 1000 And the nsproject ctx summarize should be true And the nsproject ctx auto_refresh should be true And the nsproject ctx temporal_scope should be "current" And the nsproject ctx retention_policy should be empty Scenario: ContextConfig merges default ignore patterns Given a ContextConfig with custom ignore patterns Then the nsproject ctx ignore patterns should include defaults And the nsproject ctx ignore patterns should include the custom pattern Scenario: ContextConfig with memory tier settings Given a ContextConfig with hot_max_tokens 4096 and warm_max_decisions 50 Then the nsproject ctx hot_max_tokens should be 4096 And the nsproject ctx warm_max_decisions should be 50 Scenario: ContextConfig is frozen Given a default ContextConfig When I try to mutate a ContextConfig field Then a nsproject validation error should be raised Scenario: ContextConfig rejects zero max_file_size When I try to create a ContextConfig with max_file_size 0 Then a nsproject validation error should be raised Scenario: ContextConfig rejects negative chunk_size When I try to create a ContextConfig with chunk_size -1 Then a nsproject validation error should be raised # LinkedResource model Scenario: Create a LinkedResource with defaults Given a LinkedResource with resource_id "01HZQX7K8M3N4P5R6S7T8V9W0X" Then the nsproject linked rid should be "01HZQX7K8M3N4P5R6S7T8V9W0X" And the nsproject linked read_only should be false And the nsproject linked alias should be empty And the nsproject linked_at should be set Scenario: Create a LinkedResource with alias Given a LinkedResource with id "01HZQX7K8M3N4P5R6S7T8V9W0X" and alias "main-repo" Then the nsproject linked alias should be "main-repo" Scenario: LinkedResource rejects invalid ULID When I try to create a LinkedResource with resource_id "invalid" Then a nsproject validation error should be raised Scenario: LinkedResource rejects empty alias When I try to create a LinkedResource with empty alias Then a nsproject validation error should be raised Scenario: LinkedResource is frozen Given a LinkedResource with resource_id "01HZQX7K8M3N4P5R6S7T8V9W0X" When I try to mutate a LinkedResource field Then a nsproject validation error should be raised # NamespacedProject model Scenario: Create a minimal NamespacedProject Given a NamespacedProject with name "my-project" Then the nsproject name should be "my-project" And the nsproject namespace should be "local" And the nsproject server should be empty And the nsproject namespaced name should be "local/my-project" And the nsproject qualified name should be "local/my-project" And the nsproject linked resources should be empty And the nsproject created_at should be set And the nsproject updated_at should be set Scenario: Create a NamespacedProject with namespace Given a project "api" under namespace "freemo" Then the nsproject namespace should be "freemo" And the nsproject namespaced name should be "freemo/api" Scenario: Create a NamespacedProject with server Given a project "api" under namespace "freemo" on server "dev" Then the nsproject server should be "dev" And the nsproject qualified name should be "dev:freemo/api" Scenario: NamespacedProject is_local Given a NamespacedProject with name "my-project" Then the nsproject should be local Scenario: NamespacedProject is_remote with namespace Given a project "api" under namespace "freemo" Then the nsproject should be remote Scenario: NamespacedProject is_remote with server Given a project "api" under namespace "freemo" on server "dev" Then the nsproject should be remote # NamespacedProject - validation Scenario: NamespacedProject rejects invalid name When I try to create a NamespacedProject with name "123invalid" Then a nsproject validation error should be raised Scenario: NamespacedProject rejects reserved namespace When I try to create a NamespacedProject with namespace "system" Then a nsproject validation error should be raised Scenario: NamespacedProject rejects provider namespace When I try to create a NamespacedProject with namespace "openai" Then a nsproject validation error should be raised Scenario: NamespacedProject rejects duplicate linked resources When I try to create a NamespacedProject with duplicate linked resources Then a nsproject validation error should be raised # NamespacedProject - domain methods Scenario: Link a resource to a project Given a NamespacedProject with name "my-project" When I link resource "01HZQX7K8M3N4P5R6S7T8V9W0X" to the project Then the nsproject should have 1 linked resource And the nsproject first linked resource_id should be "01HZQX7K8M3N4P5R6S7T8V9W0X" Scenario: Link a resource with read_only and alias Given a NamespacedProject with name "my-project" When I link resource "01HZQX7K8M3N4P5R6S7T8V9W0X" with read_only true and alias "docs" Then the nsproject should have 1 linked resource And the nsproject first linked resource should be read_only And the nsproject first linked resource alias should be "docs" Scenario: Unlink a resource from a project Given a NamespacedProject with name "my-project" And I link resource "01HZQX7K8M3N4P5R6S7T8V9W0X" to the project When I unlink resource "01HZQX7K8M3N4P5R6S7T8V9W0X" from the project Then the nsproject linked resources should be empty Scenario: Link duplicate resource fails Given a NamespacedProject with name "my-project" And I link resource "01HZQX7K8M3N4P5R6S7T8V9W0X" to the project When I try to link resource "01HZQX7K8M3N4P5R6S7T8V9W0X" again Then a nsproject validation error should be raised Scenario: Unlink non-existent resource fails Given a NamespacedProject with name "my-project" When I try to unlink resource "01HZQX7K8M3N4P5R6S7T8V9W0X" from the project Then a nsproject validation error should be raised Scenario: Get linked resource by resource_id Given a NamespacedProject with name "my-project" And I link resource "01HZQX7K8M3N4P5R6S7T8V9W0X" to the project When I get linked resource "01HZQX7K8M3N4P5R6S7T8V9W0X" from the project Then the nsproject retrieved link should not be empty Scenario: Get linked resource by alias Given a NamespacedProject with name "my-project" And I link resource "01HZQX7K8M3N4P5R6S7T8V9W0X" with read_only false and alias "main" When I get linked resource by alias "main" from the project Then the nsproject retrieved link should not be empty And the nsproject retrieved link alias should be "main" Scenario: Get non-existent linked resource returns None Given a NamespacedProject with name "my-project" When I get linked resource "01HZQX7K8M3N4P5R6S7T8V9W0X" from the project Then the nsproject retrieved link should be empty Scenario: Link resource with empty resource_id fails Given a NamespacedProject with name "my-project" When I try to link an empty resource_id to the project Then a nsproject validation error should be raised Scenario: Unlink resource with empty resource_id fails Given a NamespacedProject with name "my-project" When I try to unlink an empty resource_id from the project Then a nsproject validation error should be raised