julee 0.1.1__py3-none-any.whl → 0.1.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. julee/api/app.py +9 -8
  2. julee/api/dependencies.py +15 -15
  3. julee/api/requests.py +10 -9
  4. julee/api/responses.py +2 -1
  5. julee/api/routers/__init__.py +5 -5
  6. julee/api/routers/assembly_specifications.py +5 -4
  7. julee/api/routers/documents.py +1 -1
  8. julee/api/routers/knowledge_service_configs.py +4 -3
  9. julee/api/routers/knowledge_service_queries.py +7 -6
  10. julee/api/routers/system.py +4 -3
  11. julee/api/routers/workflows.py +4 -5
  12. julee/api/services/system_initialization.py +6 -6
  13. julee/api/tests/routers/test_assembly_specifications.py +4 -3
  14. julee/api/tests/routers/test_documents.py +5 -4
  15. julee/api/tests/routers/test_knowledge_service_configs.py +7 -6
  16. julee/api/tests/routers/test_knowledge_service_queries.py +4 -3
  17. julee/api/tests/routers/test_system.py +5 -4
  18. julee/api/tests/routers/test_workflows.py +5 -4
  19. julee/api/tests/test_app.py +5 -4
  20. julee/api/tests/test_dependencies.py +3 -2
  21. julee/api/tests/test_requests.py +2 -1
  22. julee/contrib/__init__.py +15 -0
  23. julee/contrib/polling/__init__.py +47 -0
  24. julee/contrib/polling/domain/__init__.py +17 -0
  25. julee/contrib/polling/domain/models/__init__.py +13 -0
  26. julee/contrib/polling/domain/models/polling_config.py +39 -0
  27. julee/contrib/polling/domain/services/__init__.py +11 -0
  28. julee/contrib/polling/domain/services/poller.py +39 -0
  29. julee/contrib/polling/infrastructure/__init__.py +15 -0
  30. julee/contrib/polling/infrastructure/services/__init__.py +12 -0
  31. julee/contrib/polling/infrastructure/services/polling/__init__.py +12 -0
  32. julee/contrib/polling/infrastructure/services/polling/http/__init__.py +12 -0
  33. julee/contrib/polling/infrastructure/services/polling/http/http_poller_service.py +80 -0
  34. julee/contrib/polling/infrastructure/temporal/__init__.py +20 -0
  35. julee/contrib/polling/infrastructure/temporal/activities.py +42 -0
  36. julee/contrib/polling/infrastructure/temporal/activity_names.py +20 -0
  37. julee/contrib/polling/infrastructure/temporal/proxies.py +45 -0
  38. julee/contrib/polling/tests/__init__.py +6 -0
  39. julee/contrib/polling/tests/unit/__init__.py +6 -0
  40. julee/contrib/polling/tests/unit/infrastructure/__init__.py +7 -0
  41. julee/contrib/polling/tests/unit/infrastructure/services/__init__.py +6 -0
  42. julee/contrib/polling/tests/unit/infrastructure/services/polling/__init__.py +6 -0
  43. julee/contrib/polling/tests/unit/infrastructure/services/polling/http/__init__.py +7 -0
  44. julee/contrib/polling/tests/unit/infrastructure/services/polling/http/test_http_poller_service.py +163 -0
  45. julee/docs/__init__.py +5 -0
  46. julee/docs/sphinx_hcd/__init__.py +82 -0
  47. julee/docs/sphinx_hcd/accelerators.py +1078 -0
  48. julee/docs/sphinx_hcd/apps.py +499 -0
  49. julee/docs/sphinx_hcd/config.py +148 -0
  50. julee/docs/sphinx_hcd/epics.py +448 -0
  51. julee/docs/sphinx_hcd/integrations.py +306 -0
  52. julee/docs/sphinx_hcd/journeys.py +783 -0
  53. julee/docs/sphinx_hcd/personas.py +435 -0
  54. julee/docs/sphinx_hcd/stories.py +932 -0
  55. julee/docs/sphinx_hcd/utils.py +180 -0
  56. julee/domain/models/__init__.py +5 -6
  57. julee/domain/models/assembly/assembly.py +7 -7
  58. julee/domain/models/assembly/tests/factories.py +2 -1
  59. julee/domain/models/assembly/tests/test_assembly.py +16 -13
  60. julee/domain/models/assembly_specification/assembly_specification.py +11 -10
  61. julee/domain/models/assembly_specification/knowledge_service_query.py +14 -9
  62. julee/domain/models/assembly_specification/tests/factories.py +2 -1
  63. julee/domain/models/assembly_specification/tests/test_assembly_specification.py +9 -6
  64. julee/domain/models/assembly_specification/tests/test_knowledge_service_query.py +3 -1
  65. julee/domain/models/custom_fields/content_stream.py +3 -2
  66. julee/domain/models/custom_fields/tests/test_custom_fields.py +2 -1
  67. julee/domain/models/document/document.py +12 -10
  68. julee/domain/models/document/tests/factories.py +3 -2
  69. julee/domain/models/document/tests/test_document.py +6 -3
  70. julee/domain/models/knowledge_service_config/knowledge_service_config.py +4 -4
  71. julee/domain/models/policy/__init__.py +4 -4
  72. julee/domain/models/policy/document_policy_validation.py +17 -17
  73. julee/domain/models/policy/policy.py +12 -10
  74. julee/domain/models/policy/tests/factories.py +2 -1
  75. julee/domain/models/policy/tests/test_document_policy_validation.py +3 -1
  76. julee/domain/models/policy/tests/test_policy.py +2 -1
  77. julee/domain/repositories/__init__.py +3 -3
  78. julee/domain/repositories/assembly.py +3 -1
  79. julee/domain/repositories/assembly_specification.py +2 -0
  80. julee/domain/repositories/base.py +33 -16
  81. julee/domain/repositories/document.py +3 -1
  82. julee/domain/repositories/document_policy_validation.py +3 -1
  83. julee/domain/repositories/knowledge_service_config.py +2 -0
  84. julee/domain/repositories/knowledge_service_query.py +1 -0
  85. julee/domain/repositories/policy.py +3 -1
  86. julee/domain/use_cases/decorators.py +3 -2
  87. julee/domain/use_cases/extract_assemble_data.py +23 -13
  88. julee/domain/use_cases/initialize_system_data.py +13 -13
  89. julee/domain/use_cases/tests/test_extract_assemble_data.py +10 -10
  90. julee/domain/use_cases/tests/test_initialize_system_data.py +2 -2
  91. julee/domain/use_cases/tests/test_validate_document.py +11 -11
  92. julee/domain/use_cases/validate_document.py +26 -15
  93. julee/maintenance/__init__.py +1 -0
  94. julee/maintenance/release.py +188 -0
  95. julee/repositories/__init__.py +4 -1
  96. julee/repositories/memory/assembly.py +6 -5
  97. julee/repositories/memory/assembly_specification.py +9 -9
  98. julee/repositories/memory/base.py +12 -11
  99. julee/repositories/memory/document.py +8 -7
  100. julee/repositories/memory/document_policy_validation.py +7 -6
  101. julee/repositories/memory/knowledge_service_config.py +9 -7
  102. julee/repositories/memory/knowledge_service_query.py +9 -7
  103. julee/repositories/memory/policy.py +6 -5
  104. julee/repositories/memory/tests/test_document.py +6 -4
  105. julee/repositories/memory/tests/test_document_policy_validation.py +2 -1
  106. julee/repositories/memory/tests/test_policy.py +2 -1
  107. julee/repositories/minio/assembly.py +4 -4
  108. julee/repositories/minio/assembly_specification.py +6 -8
  109. julee/repositories/minio/client.py +22 -25
  110. julee/repositories/minio/document.py +11 -11
  111. julee/repositories/minio/document_policy_validation.py +5 -5
  112. julee/repositories/minio/knowledge_service_config.py +8 -8
  113. julee/repositories/minio/knowledge_service_query.py +6 -9
  114. julee/repositories/minio/policy.py +4 -4
  115. julee/repositories/minio/tests/fake_client.py +11 -9
  116. julee/repositories/minio/tests/test_assembly.py +3 -1
  117. julee/repositories/minio/tests/test_assembly_specification.py +2 -1
  118. julee/repositories/minio/tests/test_client_protocol.py +5 -5
  119. julee/repositories/minio/tests/test_document.py +7 -6
  120. julee/repositories/minio/tests/test_document_policy_validation.py +3 -1
  121. julee/repositories/minio/tests/test_knowledge_service_config.py +4 -2
  122. julee/repositories/minio/tests/test_knowledge_service_query.py +3 -2
  123. julee/repositories/minio/tests/test_policy.py +3 -1
  124. julee/repositories/temporal/activities.py +5 -5
  125. julee/repositories/temporal/proxies.py +5 -5
  126. julee/services/knowledge_service/__init__.py +1 -2
  127. julee/services/knowledge_service/anthropic/knowledge_service.py +8 -7
  128. julee/services/knowledge_service/anthropic/tests/test_knowledge_service.py +11 -10
  129. julee/services/knowledge_service/factory.py +8 -8
  130. julee/services/knowledge_service/knowledge_service.py +22 -18
  131. julee/services/knowledge_service/memory/knowledge_service.py +13 -12
  132. julee/services/knowledge_service/memory/test_knowledge_service.py +10 -7
  133. julee/services/knowledge_service/test_factory.py +11 -10
  134. julee/services/temporal/activities.py +10 -10
  135. julee/services/temporal/proxies.py +2 -2
  136. julee/util/domain.py +6 -6
  137. julee/util/repos/minio/file_storage.py +8 -9
  138. julee/util/repos/temporal/client_proxies/file_storage.py +3 -4
  139. julee/util/repos/temporal/data_converter.py +6 -6
  140. julee/util/repos/temporal/minio_file_storage.py +1 -1
  141. julee/util/repos/temporal/proxies/file_storage.py +2 -3
  142. julee/util/repositories.py +6 -7
  143. julee/util/temporal/activities.py +1 -1
  144. julee/util/temporal/decorators.py +28 -33
  145. julee/util/tests/test_decorators.py +13 -15
  146. julee/util/validation/repository.py +3 -3
  147. julee/util/validation/type_guards.py +12 -11
  148. julee/worker.py +9 -8
  149. julee/workflows/__init__.py +2 -2
  150. julee/workflows/extract_assemble.py +2 -1
  151. julee/workflows/validate_document.py +3 -2
  152. {julee-0.1.1.dist-info → julee-0.1.3.dist-info}/METADATA +4 -1
  153. julee-0.1.3.dist-info/RECORD +197 -0
  154. julee-0.1.1.dist-info/RECORD +0 -161
  155. {julee-0.1.1.dist-info → julee-0.1.3.dist-info}/WHEEL +0 -0
  156. {julee-0.1.1.dist-info → julee-0.1.3.dist-info}/licenses/LICENSE +0 -0
  157. {julee-0.1.1.dist-info → julee-0.1.3.dist-info}/top_level.txt +0 -0
@@ -8,11 +8,13 @@ All domain models use Pydantic BaseModel for validation, serialization,
8
8
  and type safety, following the patterns established in the sample project.
9
9
  """
10
10
 
11
- from pydantic import BaseModel, Field, field_validator, model_validator
12
- from pydantic import ValidationInfo
13
- from typing import Callable, Optional, List, Dict, Any
11
+ from collections.abc import Callable
14
12
  from datetime import datetime, timezone
15
13
  from enum import Enum
14
+ from typing import Any
15
+
16
+ from pydantic import BaseModel, Field, ValidationInfo, field_validator, model_validator
17
+
16
18
  from julee.domain.models.custom_fields.content_stream import (
17
19
  ContentStream,
18
20
  )
@@ -75,21 +77,21 @@ class Document(BaseModel):
75
77
 
76
78
  # Document processing state
77
79
  status: DocumentStatus = DocumentStatus.CAPTURED
78
- knowledge_service_id: Optional[str] = None
79
- assembly_types: List[str] = Field(default_factory=list)
80
+ knowledge_service_id: str | None = None
81
+ assembly_types: list[str] = Field(default_factory=list)
80
82
 
81
83
  # Timestamps
82
- created_at: Optional[datetime] = Field(
84
+ created_at: datetime | None = Field(
83
85
  default_factory=lambda: datetime.now(timezone.utc)
84
86
  )
85
- updated_at: Optional[datetime] = Field(
87
+ updated_at: datetime | None = Field(
86
88
  default_factory=lambda: datetime.now(timezone.utc)
87
89
  )
88
90
 
89
91
  # Additional data and content stream
90
- additional_metadata: Dict[str, Any] = Field(default_factory=dict)
91
- content: Optional[ContentStream] = Field(default=None, exclude=True)
92
- content_string: Optional[str] = Field(
92
+ additional_metadata: dict[str, Any] = Field(default_factory=dict)
93
+ content: ContentStream | None = Field(default=None, exclude=True)
94
+ content_string: str | None = Field(
93
95
  default=None,
94
96
  description="Small content as string (few KB max). Use for "
95
97
  "workflow-generated content to avoid ContentStream serialization "
@@ -8,14 +8,15 @@ Document domain objects with sensible defaults.
8
8
  import io
9
9
  from datetime import datetime, timezone
10
10
  from typing import Any
11
+
11
12
  from factory.base import Factory
12
- from factory.faker import Faker
13
13
  from factory.declarations import LazyAttribute, LazyFunction
14
+ from factory.faker import Faker
14
15
 
15
- from julee.domain.models.document import Document, DocumentStatus
16
16
  from julee.domain.models.custom_fields.content_stream import (
17
17
  ContentStream,
18
18
  )
19
+ from julee.domain.models.document import Document, DocumentStatus
19
20
 
20
21
 
21
22
  # Helper functions to generate content bytes consistently
@@ -19,11 +19,14 @@ Design decisions documented:
19
19
  - Documents act as readable streams with standard methods
20
20
  """
21
21
 
22
- import pytest
23
22
  import json
24
23
 
24
+ import pytest
25
+ from pydantic import ValidationError
26
+
25
27
  from julee.domain.models.document import Document
26
- from .factories import DocumentFactory, ContentStreamFactory
28
+
29
+ from .factories import ContentStreamFactory, DocumentFactory
27
30
 
28
31
 
29
32
  class TestDocumentInstantiation:
@@ -164,7 +167,7 @@ class TestDocumentInstantiation:
164
167
  assert doc.content_multihash.strip() == multihash.strip()
165
168
  else:
166
169
  # Should raise validation error
167
- with pytest.raises(Exception): # Could be ValueError or ValidationError
170
+ with pytest.raises((ValueError, ValidationError)):
168
171
  Document(
169
172
  document_id=document_id,
170
173
  original_filename=original_filename,
@@ -13,11 +13,11 @@ All domain models use Pydantic BaseModel for validation, serialization,
13
13
  and type safety, following the patterns established in the sample project.
14
14
  """
15
15
 
16
- from pydantic import BaseModel, Field, field_validator
17
- from typing import Optional
18
16
  from datetime import datetime, timezone
19
17
  from enum import Enum
20
18
 
19
+ from pydantic import BaseModel, Field, field_validator
20
+
21
21
 
22
22
  class ServiceApi(str, Enum):
23
23
  """Supported knowledge service APIs."""
@@ -48,10 +48,10 @@ class KnowledgeServiceConfig(BaseModel):
48
48
  )
49
49
 
50
50
  # Timestamps
51
- created_at: Optional[datetime] = Field(
51
+ created_at: datetime | None = Field(
52
52
  default_factory=lambda: datetime.now(timezone.utc)
53
53
  )
54
- updated_at: Optional[datetime] = Field(
54
+ updated_at: datetime | None = Field(
55
55
  default_factory=lambda: datetime.now(timezone.utc)
56
56
  )
57
57
 
@@ -1,11 +1,11 @@
1
- from .policy import (
2
- Policy,
3
- PolicyStatus,
4
- )
5
1
  from .document_policy_validation import (
6
2
  DocumentPolicyValidation,
7
3
  DocumentPolicyValidationStatus,
8
4
  )
5
+ from .policy import (
6
+ Policy,
7
+ PolicyStatus,
8
+ )
9
9
 
10
10
  __all__ = [
11
11
  "Policy",
@@ -17,11 +17,11 @@ All domain models use Pydantic BaseModel for validation, serialization,
17
17
  and type safety, following the patterns established in the sample project.
18
18
  """
19
19
 
20
- from pydantic import BaseModel, Field, field_validator
21
- from typing import Optional, List, Tuple
22
20
  from datetime import datetime, timezone
23
21
  from enum import Enum
24
22
 
23
+ from pydantic import BaseModel, Field, field_validator
24
+
25
25
 
26
26
  class DocumentPolicyValidationStatus(str, Enum):
27
27
  """Status of a document policy validation process."""
@@ -70,7 +70,7 @@ class DocumentPolicyValidation(BaseModel):
70
70
  status: DocumentPolicyValidationStatus = DocumentPolicyValidationStatus.PENDING
71
71
 
72
72
  # Initial validation results
73
- validation_scores: List[Tuple[str, int]] = Field(
73
+ validation_scores: list[tuple[str, int]] = Field(
74
74
  default_factory=list,
75
75
  description="List of (knowledge_service_query_id, actual_score) "
76
76
  "tuples representing the scores achieved during initial validation. "
@@ -78,13 +78,13 @@ class DocumentPolicyValidation(BaseModel):
78
78
  )
79
79
 
80
80
  # Transformation results (if applicable)
81
- transformed_document_id: Optional[str] = Field(
81
+ transformed_document_id: str | None = Field(
82
82
  default=None,
83
83
  description="ID of the document after transformations have been "
84
84
  "applied. Only present if the policy includes transformation queries "
85
85
  "and they were executed",
86
86
  )
87
- post_transform_validation_scores: Optional[List[Tuple[str, int]]] = Field(
87
+ post_transform_validation_scores: list[tuple[str, int]] | None = Field(
88
88
  default=None,
89
89
  description="List of (knowledge_service_query_id, actual_score) "
90
90
  "tuples representing scores achieved after transformation. "
@@ -93,19 +93,19 @@ class DocumentPolicyValidation(BaseModel):
93
93
  )
94
94
 
95
95
  # Validation metadata
96
- started_at: Optional[datetime] = Field(
96
+ started_at: datetime | None = Field(
97
97
  default_factory=lambda: datetime.now(timezone.utc),
98
98
  description="When the validation process was initiated",
99
99
  )
100
- completed_at: Optional[datetime] = Field(
100
+ completed_at: datetime | None = Field(
101
101
  default=None, description="When the validation process completed"
102
102
  )
103
- error_message: Optional[str] = Field(
103
+ error_message: str | None = Field(
104
104
  default=None, description="Error message if validation process failed"
105
105
  )
106
106
 
107
107
  # Results summary
108
- passed: Optional[bool] = Field(
108
+ passed: bool | None = Field(
109
109
  default=None,
110
110
  description="Whether the document passed policy validation. "
111
111
  "None while validation is in progress, True/False when complete",
@@ -128,8 +128,8 @@ class DocumentPolicyValidation(BaseModel):
128
128
  @field_validator("validation_scores")
129
129
  @classmethod
130
130
  def validation_scores_must_be_valid(
131
- cls, v: List[Tuple[str, int]]
132
- ) -> List[Tuple[str, int]]:
131
+ cls, v: list[tuple[str, int]]
132
+ ) -> list[tuple[str, int]]:
133
133
  if not isinstance(v, list):
134
134
  raise ValueError("Validation scores must be a list")
135
135
 
@@ -142,8 +142,8 @@ class DocumentPolicyValidation(BaseModel):
142
142
  @field_validator("post_transform_validation_scores")
143
143
  @classmethod
144
144
  def post_transform_scores_must_be_valid(
145
- cls, v: Optional[List[Tuple[str, int]]]
146
- ) -> Optional[List[Tuple[str, int]]]:
145
+ cls, v: list[tuple[str, int]] | None
146
+ ) -> list[tuple[str, int]] | None:
147
147
  if v is None:
148
148
  return v
149
149
 
@@ -158,7 +158,7 @@ class DocumentPolicyValidation(BaseModel):
158
158
 
159
159
  @field_validator("error_message")
160
160
  @classmethod
161
- def error_message_must_be_valid(cls, v: Optional[str]) -> Optional[str]:
161
+ def error_message_must_be_valid(cls, v: str | None) -> str | None:
162
162
  if v is None:
163
163
  return v
164
164
  if not isinstance(v, str):
@@ -167,7 +167,7 @@ class DocumentPolicyValidation(BaseModel):
167
167
 
168
168
  @field_validator("transformed_document_id")
169
169
  @classmethod
170
- def transformed_document_id_must_be_valid(cls, v: Optional[str]) -> Optional[str]:
170
+ def transformed_document_id_must_be_valid(cls, v: str | None) -> str | None:
171
171
  if v is None:
172
172
  return v
173
173
  if not isinstance(v, str) or not v.strip():
@@ -178,8 +178,8 @@ class DocumentPolicyValidation(BaseModel):
178
178
 
179
179
  @classmethod
180
180
  def _validate_score_tuples(
181
- cls, scores: List[Tuple[str, int]], field_name: str
182
- ) -> List[Tuple[str, int]]:
181
+ cls, scores: list[tuple[str, int]], field_name: str
182
+ ) -> list[tuple[str, int]]:
183
183
  """Helper method to validate score tuple lists."""
184
184
  validated_scores = []
185
185
  query_ids_seen = set()
@@ -13,11 +13,11 @@ All domain models use Pydantic BaseModel for validation, serialization,
13
13
  and type safety, following the patterns established in the sample project.
14
14
  """
15
15
 
16
- from pydantic import BaseModel, Field, field_validator
17
- from typing import Optional, List, Tuple
18
16
  from datetime import datetime, timezone
19
17
  from enum import Enum
20
18
 
19
+ from pydantic import BaseModel, Field, field_validator
20
+
21
21
 
22
22
  class PolicyStatus(str, Enum):
23
23
  """Status of a policy configuration."""
@@ -38,9 +38,11 @@ class Policy(BaseModel):
38
38
  be applied to improve document quality before re-validation.
39
39
 
40
40
  The policy operates in two modes:
41
+
41
42
  1. Validation-only: Calculates scores and passes/fails based on criteria
42
43
  2. Validation with transformation: Calculates scores, applies
43
44
  transformations, then re-calculates scores for final pass/fail
45
+
44
46
  """
45
47
 
46
48
  # Core policy identification
@@ -53,12 +55,12 @@ class Policy(BaseModel):
53
55
 
54
56
  # Policy configuration
55
57
  status: PolicyStatus = PolicyStatus.ACTIVE
56
- validation_scores: List[Tuple[str, int]] = Field(
58
+ validation_scores: list[tuple[str, int]] = Field(
57
59
  description="List of (knowledge_service_query_id, required_score) "
58
60
  "tuples where required_score is between 0 and 100. All scores "
59
61
  "must be met or exceeded for the policy to pass"
60
62
  )
61
- transformation_queries: Optional[List[str]] = Field(
63
+ transformation_queries: list[str] | None = Field(
62
64
  default=None,
63
65
  description="Optional list of knowledge service query IDs for "
64
66
  "transformations to apply before re-validation. If not provided "
@@ -67,10 +69,10 @@ class Policy(BaseModel):
67
69
 
68
70
  # Policy metadata
69
71
  version: str = Field(default="0.1.0", description="Policy version")
70
- created_at: Optional[datetime] = Field(
72
+ created_at: datetime | None = Field(
71
73
  default_factory=lambda: datetime.now(timezone.utc)
72
74
  )
73
- updated_at: Optional[datetime] = Field(default=None)
75
+ updated_at: datetime | None = Field(default=None)
74
76
 
75
77
  @field_validator("policy_id")
76
78
  @classmethod
@@ -96,8 +98,8 @@ class Policy(BaseModel):
96
98
  @field_validator("validation_scores")
97
99
  @classmethod
98
100
  def validation_scores_must_be_valid(
99
- cls, v: List[Tuple[str, int]]
100
- ) -> List[Tuple[str, int]]:
101
+ cls, v: list[tuple[str, int]]
102
+ ) -> list[tuple[str, int]]:
101
103
  if not isinstance(v, list):
102
104
  raise ValueError("Validation scores must be a list")
103
105
 
@@ -145,8 +147,8 @@ class Policy(BaseModel):
145
147
  @field_validator("transformation_queries")
146
148
  @classmethod
147
149
  def transformation_queries_must_be_valid(
148
- cls, v: Optional[List[str]]
149
- ) -> Optional[List[str]]:
150
+ cls, v: list[str] | None
151
+ ) -> list[str] | None:
150
152
  if v is None:
151
153
  return v
152
154
 
@@ -6,9 +6,10 @@ Policy domain objects with sensible defaults.
6
6
  """
7
7
 
8
8
  from datetime import datetime, timezone
9
+
9
10
  from factory.base import Factory
10
- from factory.faker import Faker
11
11
  from factory.declarations import LazyFunction
12
+ from factory.faker import Faker
12
13
 
13
14
  from julee.domain.models.policy import (
14
15
  DocumentPolicyValidation,
@@ -13,14 +13,16 @@ Tests focus on:
13
13
  - Edge cases and error conditions
14
14
  """
15
15
 
16
- import pytest
17
16
  from datetime import datetime, timezone
17
+
18
+ import pytest
18
19
  from pydantic import ValidationError
19
20
 
20
21
  from julee.domain.models.policy import (
21
22
  DocumentPolicyValidation,
22
23
  DocumentPolicyValidationStatus,
23
24
  )
25
+
24
26
  from .factories import DocumentPolicyValidationFactory
25
27
 
26
28
 
@@ -5,8 +5,9 @@ These tests verify the behavior of Policy domain objects,
5
5
  including validation, serialization, and business logic.
6
6
  """
7
7
 
8
- import pytest
9
8
  from datetime import datetime, timezone
9
+
10
+ import pytest
10
11
  from pydantic import ValidationError
11
12
 
12
13
  from julee.domain.models.policy import (
@@ -6,14 +6,14 @@ Extract, Assemble, Publish workflow, following the Clean Architecture
6
6
  patterns established in the Fun-Police framework.
7
7
  """
8
8
 
9
- from .base import BaseRepository
10
- from .document import DocumentRepository
11
9
  from .assembly import AssemblyRepository
12
10
  from .assembly_specification import AssemblySpecificationRepository
11
+ from .base import BaseRepository
12
+ from .document import DocumentRepository
13
+ from .document_policy_validation import DocumentPolicyValidationRepository
13
14
  from .knowledge_service_config import KnowledgeServiceConfigRepository
14
15
  from .knowledge_service_query import KnowledgeServiceQueryRepository
15
16
  from .policy import PolicyRepository
16
- from .document_policy_validation import DocumentPolicyValidationRepository
17
17
 
18
18
  __all__ = [
19
19
  "BaseRepository",
@@ -27,8 +27,10 @@ In Temporal workflow contexts, these protocols are implemented by workflow
27
27
  stubs that delegate to activities for durability and proper error handling.
28
28
  """
29
29
 
30
- from typing import runtime_checkable, Protocol
30
+ from typing import Protocol, runtime_checkable
31
+
31
32
  from julee.domain.models import Assembly
33
+
32
34
  from .base import BaseRepository
33
35
 
34
36
 
@@ -30,9 +30,11 @@ stubs that delegate to activities for durability and proper error handling.
30
30
  """
31
31
 
32
32
  from typing import Protocol, runtime_checkable
33
+
33
34
  from julee.domain.models.assembly_specification import (
34
35
  AssemblySpecification,
35
36
  )
37
+
36
38
  from .base import BaseRepository
37
39
 
38
40
 
@@ -23,7 +23,8 @@ In Temporal workflow contexts, these protocols are implemented by workflow
23
23
  stubs that delegate to activities for durability and proper error handling.
24
24
  """
25
25
 
26
- from typing import Protocol, Optional, runtime_checkable, TypeVar, List, Dict
26
+ from typing import Protocol, TypeVar, runtime_checkable
27
+
27
28
  from pydantic import BaseModel
28
29
 
29
30
  # Type variable bound to Pydantic BaseModel for domain entities
@@ -42,7 +43,7 @@ class BaseRepository(Protocol[T]):
42
43
  T: The domain entity type (must extend Pydantic BaseModel)
43
44
  """
44
45
 
45
- async def get(self, entity_id: str) -> Optional[T]:
46
+ async def get(self, entity_id: str) -> T | None:
46
47
  """Retrieve an entity by ID.
47
48
 
48
49
  Args:
@@ -51,14 +52,16 @@ class BaseRepository(Protocol[T]):
51
52
  Returns:
52
53
  Entity if found, None otherwise
53
54
 
54
- Implementation Notes:
55
+ .. rubric:: Implementation Notes
56
+
55
57
  - Must be idempotent: multiple calls return same result
56
58
  - Should handle missing entities gracefully (return None)
57
59
  - Loads complete entity with all relationships
60
+
58
61
  """
59
62
  ...
60
63
 
61
- async def get_many(self, entity_ids: List[str]) -> Dict[str, Optional[T]]:
64
+ async def get_many(self, entity_ids: list[str]) -> dict[str, T | None]:
62
65
  """Retrieve multiple entities by ID.
63
66
 
64
67
  Args:
@@ -67,7 +70,8 @@ class BaseRepository(Protocol[T]):
67
70
  Returns:
68
71
  Dict mapping entity_id to entity (or None if not found)
69
72
 
70
- Implementation Notes:
73
+ .. rubric:: Implementation Notes
74
+
71
75
  - Must be idempotent: multiple calls return same result
72
76
  - Should handle missing entities gracefully (return None for missing)
73
77
  - Implementations may optimize with batch operations or fall back
@@ -75,10 +79,12 @@ class BaseRepository(Protocol[T]):
75
79
  - Keys in returned dict correspond exactly to input entity_ids
76
80
  - Missing entities have None values in the returned dict
77
81
 
78
- Workflow Context:
82
+ .. rubric:: Workflow Context
83
+
79
84
  In Temporal workflows, this method is implemented as an activity
80
85
  to ensure batch operations are durably stored and consistent
81
86
  across workflow replays.
87
+
82
88
  """
83
89
  ...
84
90
 
@@ -88,38 +94,46 @@ class BaseRepository(Protocol[T]):
88
94
  Args:
89
95
  entity: Complete entity to save
90
96
 
91
- Implementation Notes:
97
+ .. rubric:: Implementation Notes
98
+
92
99
  - Must be idempotent: saving same entity state is safe
93
100
  - Should update the updated_at timestamp
94
101
  - Must save complete entity with all relationships
95
102
  - Handles both new entities and updates to existing ones
103
+
96
104
  """
97
105
  ...
98
106
 
99
- async def list_all(self) -> List[T]:
107
+ async def list_all(self) -> list[T]:
100
108
  """List all entities.
101
109
 
102
110
  Returns:
103
111
  List of all entities in the repository
104
112
 
105
- Implementation Notes:
113
+ .. rubric:: Implementation Notes
114
+
106
115
  - Must be idempotent: multiple calls return same result
107
116
  - Returns empty list if no entities exist
108
117
  - Should return entities in a consistent order (e.g., by ID)
109
118
  - For large datasets, consider pagination at the use case level
110
119
 
111
- Workflow Context:
120
+ .. rubric:: Workflow Context
121
+
112
122
  In Temporal workflows, this method is implemented as an activity
113
123
  to ensure the list operation is durably stored and consistent
114
124
  across workflow replays.
115
125
 
116
- Default Implementation:
126
+ .. rubric:: Default Implementation
127
+
117
128
  Base protocol provides a default that returns empty list.
118
129
  Repository implementations should override this method as needed.
119
130
 
120
- TODO: This default implementation returns empty list to avoid
121
- breaking existing repositories. Specific repositories should
122
- implement proper list_all() functionality as needed.
131
+ .. note::
132
+
133
+ This default implementation returns empty list to avoid
134
+ breaking existing repositories. Specific repositories should
135
+ implement proper list_all() functionality as needed.
136
+
123
137
  """
124
138
  return []
125
139
 
@@ -132,15 +146,18 @@ class BaseRepository(Protocol[T]):
132
146
  Returns:
133
147
  Unique entity ID string
134
148
 
135
- Implementation Notes:
149
+ .. rubric:: Implementation Notes
150
+
136
151
  - Must generate globally unique identifiers
137
152
  - May use UUIDs, database sequences, or distributed ID generators
138
153
  - Should be fast and reliable
139
154
  - Failure here should be rare but handled gracefully
140
155
 
141
- Workflow Context:
156
+ .. rubric:: Workflow Context
157
+
142
158
  In Temporal workflows, this method is implemented as an activity
143
159
  to ensure the generated ID is durably stored and consistent
144
160
  across workflow replays.
161
+
145
162
  """
146
163
  ...
@@ -29,8 +29,10 @@ In Temporal workflow contexts, these protocols are implemented by workflow
29
29
  stubs that delegate to activities for durability and proper error handling.
30
30
  """
31
31
 
32
- from typing import runtime_checkable, Protocol
32
+ from typing import Protocol, runtime_checkable
33
+
33
34
  from julee.domain.models import Document
35
+
34
36
  from .base import BaseRepository
35
37
 
36
38
 
@@ -29,8 +29,10 @@ In Temporal workflow contexts, these protocols are implemented by workflow
29
29
  stubs that delegate to activities for durability and proper error handling.
30
30
  """
31
31
 
32
- from typing import runtime_checkable, Protocol
32
+ from typing import Protocol, runtime_checkable
33
+
33
34
  from julee.domain.models.policy import DocumentPolicyValidation
35
+
34
36
  from .base import BaseRepository
35
37
 
36
38
 
@@ -31,9 +31,11 @@ stubs that delegate to activities for durability and proper error handling.
31
31
  """
32
32
 
33
33
  from typing import Protocol, runtime_checkable
34
+
34
35
  from julee.domain.models.knowledge_service_config import (
35
36
  KnowledgeServiceConfig,
36
37
  )
38
+
37
39
  from .base import BaseRepository
38
40
 
39
41
 
@@ -25,6 +25,7 @@ from typing import Protocol, runtime_checkable
25
25
  from julee.domain.models.assembly_specification import (
26
26
  KnowledgeServiceQuery,
27
27
  )
28
+
28
29
  from .base import BaseRepository
29
30
 
30
31
 
@@ -29,8 +29,10 @@ In Temporal workflow contexts, these protocols are implemented by workflow
29
29
  stubs that delegate to activities for durability and proper error handling.
30
30
  """
31
31
 
32
- from typing import runtime_checkable, Protocol
32
+ from typing import Protocol, runtime_checkable
33
+
33
34
  from julee.domain.models import Policy
35
+
34
36
  from .base import BaseRepository
35
37
 
36
38
 
@@ -7,8 +7,9 @@ following the patterns established in the sample use cases.
7
7
  """
8
8
 
9
9
  import logging
10
+ from collections.abc import Awaitable, Callable
10
11
  from functools import wraps
11
- from typing import Any, Callable, Dict, Optional, TypeVar, Awaitable
12
+ from typing import Any, TypeVar
12
13
 
13
14
  logger = logging.getLogger(__name__)
14
15
 
@@ -17,7 +18,7 @@ F = TypeVar("F", bound=Callable[..., Awaitable[Any]])
17
18
 
18
19
  def try_use_case_step(
19
20
  step_name: str,
20
- extra_context: Optional[Dict[str, Any]] = None,
21
+ extra_context: dict[str, Any] | None = None,
21
22
  ) -> Callable[[F], F]:
22
23
  """
23
24
  Decorator that wraps use case steps with consistent error handling and