atomicguard 1.2.0__py3-none-any.whl → 2.0.0__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.
@@ -44,10 +44,11 @@ class MockGenerator(GeneratorInterface):
44
44
 
45
45
  def generate(
46
46
  self,
47
- _context: Context,
48
- _template: PromptTemplate | None = None,
47
+ context: Context, # noqa: ARG002 - unused but required by interface
48
+ template: PromptTemplate, # noqa: ARG002
49
49
  action_pair_id: str = "unknown",
50
50
  workflow_id: str = "unknown",
51
+ workflow_ref: str | None = None,
51
52
  ) -> Artifact:
52
53
  """Return the next predefined response."""
53
54
  if self._call_count >= len(self._responses):
@@ -66,8 +67,7 @@ class MockGenerator(GeneratorInterface):
66
67
  created_at=datetime.now().isoformat(),
67
68
  attempt_number=self._call_count,
68
69
  status=ArtifactStatus.PENDING,
69
- guard_result=None,
70
- feedback="",
70
+ guard_result=None, # Guard result set after validation
71
71
  context=ContextSnapshot(
72
72
  workflow_id=workflow_id,
73
73
  specification="",
@@ -75,6 +75,7 @@ class MockGenerator(GeneratorInterface):
75
75
  feedback_history=(),
76
76
  dependency_artifacts=(),
77
77
  ),
78
+ workflow_ref=workflow_ref,
78
79
  )
79
80
 
80
81
  @property
@@ -65,16 +65,14 @@ class OllamaGenerator(GeneratorInterface):
65
65
  def generate(
66
66
  self,
67
67
  context: Context,
68
- template: PromptTemplate | None = None,
68
+ template: PromptTemplate,
69
69
  action_pair_id: str = "unknown",
70
70
  workflow_id: str = "unknown",
71
+ workflow_ref: str | None = None,
71
72
  ) -> Artifact:
72
73
  """Generate an artifact based on context."""
73
74
  # Build prompt
74
- if template:
75
- prompt = template.render(context)
76
- else:
77
- prompt = self._build_basic_prompt(context)
75
+ prompt = template.render(context)
78
76
 
79
77
  # Call Ollama
80
78
  messages = [
@@ -104,8 +102,7 @@ class OllamaGenerator(GeneratorInterface):
104
102
  created_at=datetime.now().isoformat(),
105
103
  attempt_number=self._version_counter,
106
104
  status=ArtifactStatus.PENDING,
107
- guard_result=None,
108
- feedback="",
105
+ guard_result=None, # Guard result set after validation
109
106
  context=ContextSnapshot(
110
107
  workflow_id=workflow_id,
111
108
  specification=context.specification,
@@ -113,6 +110,7 @@ class OllamaGenerator(GeneratorInterface):
113
110
  feedback_history=(),
114
111
  dependency_artifacts=context.dependency_artifacts,
115
112
  ),
113
+ workflow_ref=workflow_ref,
116
114
  )
117
115
 
118
116
  def _extract_code(self, content: str) -> str:
@@ -137,19 +135,3 @@ class OllamaGenerator(GeneratorInterface):
137
135
 
138
136
  # No code block found - return empty to trigger guard validation failure
139
137
  return ""
140
-
141
- def _build_basic_prompt(self, context: Context) -> str:
142
- """Build a basic prompt from context."""
143
- parts = [context.specification]
144
-
145
- if context.current_artifact:
146
- parts.append(f"\nPrevious attempt:\n{context.current_artifact}")
147
-
148
- if context.feedback_history:
149
- feedback_text = "\n".join(
150
- f"Attempt {i + 1} feedback: {f}"
151
- for i, (_, f) in enumerate(context.feedback_history)
152
- )
153
- parts.append(f"\nFeedback history:\n{feedback_text}")
154
-
155
- return "\n".join(parts)
@@ -6,6 +6,7 @@ Implements the Versioned Repository R from Definition 4.
6
6
  """
7
7
 
8
8
  import json
9
+ import threading
9
10
  from pathlib import Path
10
11
  from typing import Any
11
12
 
@@ -15,6 +16,8 @@ from atomicguard.domain.models import (
15
16
  ArtifactStatus,
16
17
  ContextSnapshot,
17
18
  FeedbackEntry,
19
+ GuardResult,
20
+ SubGuardOutcome,
18
21
  )
19
22
 
20
23
 
@@ -31,6 +34,7 @@ class FilesystemArtifactDAG(ArtifactDAGInterface):
31
34
  self._objects_dir = self._base_dir / "objects"
32
35
  self._index_path = self._base_dir / "index.json"
33
36
  self._cache: dict[str, Artifact] = {}
37
+ self._lock = threading.Lock() # Thread safety for concurrent writes
34
38
  self._index: dict[str, Any] = self._load_or_create_index()
35
39
 
36
40
  def _load_or_create_index(self) -> dict[str, Any]:
@@ -52,9 +56,52 @@ class FilesystemArtifactDAG(ArtifactDAGInterface):
52
56
  json.dump(self._index, f, indent=2)
53
57
  temp_path.rename(self._index_path) # Atomic on POSIX
54
58
 
59
+ def _guard_result_to_dict(self, guard_result: GuardResult | None) -> dict | None:
60
+ """Serialize GuardResult to JSON-compatible dict."""
61
+ if guard_result is None:
62
+ return None
63
+ return {
64
+ "passed": guard_result.passed,
65
+ "feedback": guard_result.feedback,
66
+ "fatal": guard_result.fatal,
67
+ "guard_name": guard_result.guard_name,
68
+ "sub_results": [
69
+ {
70
+ "guard_name": sr.guard_name,
71
+ "passed": sr.passed,
72
+ "feedback": sr.feedback,
73
+ "execution_time_ms": sr.execution_time_ms,
74
+ }
75
+ for sr in guard_result.sub_results
76
+ ],
77
+ }
78
+
79
+ def _dict_to_guard_result(self, data: dict | None) -> GuardResult | None:
80
+ """Deserialize GuardResult from JSON dict."""
81
+ if data is None:
82
+ return None
83
+ # Handle legacy format where guard_result was just a boolean
84
+ if isinstance(data, bool):
85
+ return GuardResult(passed=data, feedback="")
86
+ return GuardResult(
87
+ passed=data["passed"],
88
+ feedback=data.get("feedback", ""),
89
+ fatal=data.get("fatal", False),
90
+ guard_name=data.get("guard_name"),
91
+ sub_results=tuple(
92
+ SubGuardOutcome(
93
+ guard_name=sr["guard_name"],
94
+ passed=sr["passed"],
95
+ feedback=sr["feedback"],
96
+ execution_time_ms=sr.get("execution_time_ms", 0.0),
97
+ )
98
+ for sr in data.get("sub_results", [])
99
+ ),
100
+ )
101
+
55
102
  def _artifact_to_dict(self, artifact: Artifact) -> dict:
56
103
  """Serialize artifact to JSON-compatible dict."""
57
- return {
104
+ result = {
58
105
  "artifact_id": artifact.artifact_id,
59
106
  "workflow_id": artifact.workflow_id,
60
107
  "content": artifact.content,
@@ -64,8 +111,7 @@ class FilesystemArtifactDAG(ArtifactDAGInterface):
64
111
  "created_at": artifact.created_at,
65
112
  "attempt_number": artifact.attempt_number,
66
113
  "status": artifact.status.value,
67
- "guard_result": artifact.guard_result,
68
- "feedback": artifact.feedback,
114
+ "guard_result": self._guard_result_to_dict(artifact.guard_result),
69
115
  "context": {
70
116
  "workflow_id": artifact.context.workflow_id,
71
117
  "specification": artifact.context.specification,
@@ -78,6 +124,10 @@ class FilesystemArtifactDAG(ArtifactDAGInterface):
78
124
  "dependency_artifacts": dict(artifact.context.dependency_artifacts),
79
125
  },
80
126
  }
127
+ # Include metadata if present
128
+ if artifact.metadata:
129
+ result["metadata"] = dict(artifact.metadata)
130
+ return result
81
131
 
82
132
  def _dict_to_artifact(self, data: dict) -> Artifact:
83
133
  """Deserialize artifact from JSON dict."""
@@ -98,6 +148,25 @@ class FilesystemArtifactDAG(ArtifactDAGInterface):
98
148
  # Deserialize dict → tuple for immutability
99
149
  dependency_artifacts=tuple(dep_data.items()),
100
150
  )
151
+ # Get metadata if present
152
+ metadata = data.get("metadata", {})
153
+
154
+ # Handle legacy format: guard_result was bool, feedback was separate field
155
+ guard_result_data = data.get("guard_result")
156
+ if guard_result_data is None and "feedback" in data:
157
+ # Legacy artifact with no guard_result but has feedback
158
+ # This shouldn't happen often, but handle gracefully
159
+ pass
160
+ elif isinstance(guard_result_data, bool):
161
+ # Legacy format: convert bool + feedback to GuardResult
162
+ guard_result_data = {
163
+ "passed": guard_result_data,
164
+ "feedback": data.get("feedback", ""),
165
+ "fatal": False,
166
+ "guard_name": None,
167
+ "sub_results": [],
168
+ }
169
+
101
170
  return Artifact(
102
171
  artifact_id=data["artifact_id"],
103
172
  workflow_id=data.get("workflow_id", "unknown"),
@@ -108,9 +177,9 @@ class FilesystemArtifactDAG(ArtifactDAGInterface):
108
177
  created_at=data["created_at"],
109
178
  attempt_number=data["attempt_number"],
110
179
  status=ArtifactStatus(data["status"]),
111
- guard_result=data["guard_result"],
112
- feedback=data["feedback"],
180
+ guard_result=self._dict_to_guard_result(guard_result_data),
113
181
  context=context,
182
+ metadata=metadata, # Will be converted to MappingProxyType in __post_init__
114
183
  )
115
184
 
116
185
  def _get_object_path(self, artifact_id: str) -> Path:
@@ -122,52 +191,55 @@ class FilesystemArtifactDAG(ArtifactDAGInterface):
122
191
  """
123
192
  Append artifact to DAG (immutable, append-only).
124
193
 
194
+ Thread-safe: uses lock to ensure atomic index updates.
195
+
125
196
  Args:
126
197
  artifact: The artifact to store
127
198
 
128
199
  Returns:
129
200
  The artifact_id
130
201
  """
131
- # 1. Serialize to JSON
132
- artifact_dict = self._artifact_to_dict(artifact)
133
-
134
- # 2. Write to objects/{prefix}/{artifact_id}.json
135
- object_path = self._get_object_path(artifact.artifact_id)
136
- object_path.parent.mkdir(parents=True, exist_ok=True)
137
- with open(object_path, "w") as f:
138
- json.dump(artifact_dict, f, indent=2)
139
-
140
- # 3. Update index
141
- self._index["artifacts"][artifact.artifact_id] = {
142
- "path": str(object_path.relative_to(self._base_dir)),
143
- "workflow_id": artifact.workflow_id,
144
- "action_pair_id": artifact.action_pair_id,
145
- "parent_action_pair_id": artifact.parent_action_pair_id,
146
- "status": artifact.status.value,
147
- "created_at": artifact.created_at,
148
- }
149
-
150
- # Track by action pair
151
- if artifact.action_pair_id not in self._index["action_pairs"]:
152
- self._index["action_pairs"][artifact.action_pair_id] = []
153
- self._index["action_pairs"][artifact.action_pair_id].append(
154
- artifact.artifact_id
155
- )
156
-
157
- # Track by workflow
158
- if "workflows" not in self._index:
159
- self._index["workflows"] = {}
160
- if artifact.workflow_id not in self._index["workflows"]:
161
- self._index["workflows"][artifact.workflow_id] = []
162
- self._index["workflows"][artifact.workflow_id].append(artifact.artifact_id)
163
-
164
- # 4. Atomically update index
165
- self._update_index_atomic()
166
-
167
- # 5. Add to cache
168
- self._cache[artifact.artifact_id] = artifact
169
-
170
- return artifact.artifact_id
202
+ with self._lock:
203
+ # 1. Serialize to JSON
204
+ artifact_dict = self._artifact_to_dict(artifact)
205
+
206
+ # 2. Write to objects/{prefix}/{artifact_id}.json
207
+ object_path = self._get_object_path(artifact.artifact_id)
208
+ object_path.parent.mkdir(parents=True, exist_ok=True)
209
+ with open(object_path, "w") as f:
210
+ json.dump(artifact_dict, f, indent=2)
211
+
212
+ # 3. Update index
213
+ self._index["artifacts"][artifact.artifact_id] = {
214
+ "path": str(object_path.relative_to(self._base_dir)),
215
+ "workflow_id": artifact.workflow_id,
216
+ "action_pair_id": artifact.action_pair_id,
217
+ "parent_action_pair_id": artifact.parent_action_pair_id,
218
+ "status": artifact.status.value,
219
+ "created_at": artifact.created_at,
220
+ }
221
+
222
+ # Track by action pair
223
+ if artifact.action_pair_id not in self._index["action_pairs"]:
224
+ self._index["action_pairs"][artifact.action_pair_id] = []
225
+ self._index["action_pairs"][artifact.action_pair_id].append(
226
+ artifact.artifact_id
227
+ )
228
+
229
+ # Track by workflow
230
+ if "workflows" not in self._index:
231
+ self._index["workflows"] = {}
232
+ if artifact.workflow_id not in self._index["workflows"]:
233
+ self._index["workflows"][artifact.workflow_id] = []
234
+ self._index["workflows"][artifact.workflow_id].append(artifact.artifact_id)
235
+
236
+ # 4. Atomically update index
237
+ self._update_index_atomic()
238
+
239
+ # 5. Add to cache
240
+ self._cache[artifact.artifact_id] = artifact
241
+
242
+ return artifact.artifact_id
171
243
 
172
244
  def get_artifact(self, artifact_id: str) -> Artifact:
173
245
  """Retrieve artifact by ID (cache-first)."""
@@ -238,8 +310,8 @@ class FilesystemArtifactDAG(ArtifactDAGInterface):
238
310
  attempt_number=artifact.attempt_number,
239
311
  status=new_status,
240
312
  guard_result=artifact.guard_result,
241
- feedback=artifact.feedback,
242
313
  context=artifact.context,
314
+ metadata=artifact.metadata,
243
315
  )
244
316
 
245
317
  # Update file
@@ -294,3 +366,18 @@ class FilesystemArtifactDAG(ArtifactDAGInterface):
294
366
  # Sort by created_at descending and return the latest
295
367
  candidates.sort(key=lambda x: x[1], reverse=True)
296
368
  return self.get_artifact(candidates[0][0])
369
+
370
+ def get_all(self) -> list[Artifact]:
371
+ """Return all artifacts in the DAG.
372
+
373
+ Returns:
374
+ List of all artifacts, sorted by created_at.
375
+ """
376
+ # Get all artifact IDs from index and sort by created_at
377
+ artifact_ids_with_times = [
378
+ (aid, info.get("created_at", ""))
379
+ for aid, info in self._index.get("artifacts", {}).items()
380
+ ]
381
+ artifact_ids_with_times.sort(key=lambda x: x[1])
382
+
383
+ return [self.get_artifact(aid) for aid, _ in artifact_ids_with_times]
@@ -59,3 +59,13 @@ class InMemoryArtifactDAG(ArtifactDAGInterface):
59
59
  # Sort by created_at descending and return the latest
60
60
  candidates.sort(key=lambda a: a.created_at, reverse=True)
61
61
  return candidates[0]
62
+
63
+ def get_all(self) -> list[Artifact]:
64
+ """Return all artifacts in the DAG.
65
+
66
+ Returns:
67
+ List of all artifacts, sorted by created_at.
68
+ """
69
+ artifacts = list(self._artifacts.values())
70
+ artifacts.sort(key=lambda a: a.created_at)
71
+ return artifacts
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: atomicguard
3
- Version: 1.2.0
3
+ Version: 2.0.0
4
4
  Summary: A Dual-State Agent Framework for reliable LLM code generation with guard-validated loops
5
5
  Author-email: Matthew Thompson <thompsonson@gmail.com>
6
6
  Maintainer-email: Matthew Thompson <thompsonson@gmail.com>
@@ -0,0 +1,42 @@
1
+ atomicguard/__init__.py,sha256=x11KrkPPhOTMy1ZALeVGMRjpNB8x6EukvdngV9e3_hk,3207
2
+ atomicguard/application/__init__.py,sha256=ttnQx0Jd_G2EsSoc2TNq8VdeoY2k4Q0LK3iRpe0O8Ck,643
3
+ atomicguard/application/action_pair.py,sha256=e-yilKIY1TNDn1JBbMq3fM0IDP82lIwHCDuMRog8fnc,2206
4
+ atomicguard/application/agent.py,sha256=DpK-ZtXp-DhPYkziI9c0hucIw4LZRPWCMlRhOS2oCfc,5912
5
+ atomicguard/application/checkpoint_service.py,sha256=F4EoWmWWIonwc4HAre01EPk9rwTWpLL-gDp-Vvcfs6c,4580
6
+ atomicguard/application/resume_service.py,sha256=H6fvIm8b3BuyF9d8lscVIHi9En37xlmSOkURbrmWpO8,8143
7
+ atomicguard/application/workflow.py,sha256=v6jQOPx-kzFFNvA98hSqCgor8gzP2eE8_Ng--WZ91kE,24992
8
+ atomicguard/domain/__init__.py,sha256=HGPu98AL_HgN2nWdiZU_r3fJq6kD8FNfauQSSMVcocM,1193
9
+ atomicguard/domain/exceptions.py,sha256=Zj1iz31AiksyWnyKR8KfnNLRGhZdetrYhCIwFOapBtY,1376
10
+ atomicguard/domain/extraction.py,sha256=O7ZG9pXTA11kT4n8fQIbV0FA73Ui2boveIbwB5dZ0OY,7660
11
+ atomicguard/domain/interfaces.py,sha256=44JDQ7XF7sXhf3ReWJUEJS4vJXdR_qbR9lfQ_beCTuM,7054
12
+ atomicguard/domain/models.py,sha256=Bjh8VTx7SQ8K0UxjN3lUfNunNPJ-90IZjtTv77KaU-g,11652
13
+ atomicguard/domain/multiagent.py,sha256=Id1DphL_HuxodlIFeaBl_kOny7sadotlJsvYsc4xd6Y,8707
14
+ atomicguard/domain/prompts.py,sha256=QtyBgOFldW9RmfvNAwFeyP2mKE-kFjDn758KmrxMq8Q,3328
15
+ atomicguard/domain/workflow.py,sha256=bVIZmYI3lxHOKuxtX3E3DkFQBBrsU0S73AMqrpdfrIo,21883
16
+ atomicguard/guards/__init__.py,sha256=OzpOjwmyHGpTQSDVSDeGEuXUJNOyiNpZxZVnTVMIOyg,956
17
+ atomicguard/guards/composite/__init__.py,sha256=AedlMBxFw4uTFExVWL6RJRR7vRwMOK3sgjhutkXz838,217
18
+ atomicguard/guards/composite/base.py,sha256=VGydlOD4gmXdiDHvWXF5jSppXcJAoJYSCyDj7Lrbng0,1213
19
+ atomicguard/guards/dynamic/__init__.py,sha256=pjBBeD_yYavvn-I7s5I3nTDOlZtPTq1Hqmim_RgW5cE,321
20
+ atomicguard/guards/dynamic/test_runner.py,sha256=d5cPb5cCM-UnfZjTYGOHn4XoS-N66nr5EBHqPoDGwNM,7196
21
+ atomicguard/guards/interactive/__init__.py,sha256=PlP5LNB4CMZ4fJ7Xr8gjjpn8VwLnB3zs5M2Em9xyVCc,226
22
+ atomicguard/guards/interactive/human.py,sha256=G8SstAEdcMpHR2b8ugyG9drk9aBjw4_pE6E4UrTtcUo,2960
23
+ atomicguard/guards/static/__init__.py,sha256=KANeEg_yhrKGzSmA0yf2SewOE9qkUwnJly4mWkBzsm4,305
24
+ atomicguard/guards/static/imports.py,sha256=nWS3FNNqle7YWU5_tgRgYMRAXwEcWlxee8Q4MdomN5w,6292
25
+ atomicguard/guards/static/syntax.py,sha256=mPVgGDY3pzwtXuulmmuEwYAQG7rNG0fgSGB1puYRI6Y,919
26
+ atomicguard/infrastructure/__init__.py,sha256=Y3Ot6sRgTind-8s5kCnNtRYJGN3uq84QmbAUESx8Pio,581
27
+ atomicguard/infrastructure/registry.py,sha256=XilDY2sUedwm5z1Xrp39HfQ9e3paixyJxL_hwGaVbqs,3662
28
+ atomicguard/infrastructure/llm/__init__.py,sha256=wQg_FCAHmwbDXWm0bF5WX-9v7sutAS7RabhHCGiZZzo,338
29
+ atomicguard/infrastructure/llm/huggingface.py,sha256=fGC3uQu0AwM_WzfyJKTe8aNJHTA92wecSiaxo01pOHU,5130
30
+ atomicguard/infrastructure/llm/mock.py,sha256=z_NTiPwzc7zPYN4RbzkhQEldzrdhYy7Pb9ai_pFQ_gQ,2782
31
+ atomicguard/infrastructure/llm/ollama.py,sha256=RMWct-DiY5noLu0dCM3j-7sybB5QJJGL2ZL9pMjRwZ8,4243
32
+ atomicguard/infrastructure/persistence/__init__.py,sha256=KS95wmO_qVF6It63_884lWDoa-IB0WvRma_nXS2uTq4,483
33
+ atomicguard/infrastructure/persistence/checkpoint.py,sha256=MS4qpJ_jcl6Ibw7h3KncWgDqz7CEIlFJdrpFcu2vEgs,13966
34
+ atomicguard/infrastructure/persistence/filesystem.py,sha256=ZLudEu0HvhnicciGZzOG_xX85UptfcawJGg-5V1LU1Q,14988
35
+ atomicguard/infrastructure/persistence/memory.py,sha256=r-vTR9GdThLV4EGMNM_LAxO7KhXZvh11W-Jdfp6hmk0,2342
36
+ atomicguard/schemas/__init__.py,sha256=9z3gWBHsq8FHD2qE_TPy31wkTa_qXPfVgJrNdIu8p4g,3735
37
+ atomicguard-2.0.0.dist-info/licenses/LICENSE,sha256=ROMMFVruZ18U24pKTNte9AK_YIqoMfXnMzoxqBNmKS4,1073
38
+ atomicguard-2.0.0.dist-info/METADATA,sha256=dNW8Oae14_d_ujCJgSfwb87L23STUibFEH_WU8PaW58,6831
39
+ atomicguard-2.0.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
40
+ atomicguard-2.0.0.dist-info/entry_points.txt,sha256=MMVrkEyWFFCMoNIlpSWRY9FJYlEMGmaauvzMxEjwzTI,226
41
+ atomicguard-2.0.0.dist-info/top_level.txt,sha256=J_6ENELjnacSYJ5N3FGwomp-sVeAJQohPkJBh6pu6iY,12
42
+ atomicguard-2.0.0.dist-info/RECORD,,
@@ -1,37 +0,0 @@
1
- atomicguard/__init__.py,sha256=vW_pYf3hdmq4rgIYWc0319HMUAB-JkeraoqEdFIe--U,3051
2
- atomicguard/application/__init__.py,sha256=-myJt7VuC1tMjO424NhjY6iZZuUdHGnFCJKFapFCAhw,409
3
- atomicguard/application/action_pair.py,sha256=JfQH88gTZCMl5qa5frqLJnhebn-KgO_oGAol6sD58ys,2214
4
- atomicguard/application/agent.py,sha256=ND2_pnRGwcWM5MovM8dnratrMph2gz9UmwXEgTeA59s,5907
5
- atomicguard/application/workflow.py,sha256=mfWz2pdBqQsGC5rBZ5S1x_jaNe2aLvqoG20TvWyAsnM,23309
6
- atomicguard/domain/__init__.py,sha256=BRmYKYFU-kLG1wPpRrXKxZ2jb4QgMea83r0gbDX_Da0,1149
7
- atomicguard/domain/exceptions.py,sha256=Zj1iz31AiksyWnyKR8KfnNLRGhZdetrYhCIwFOapBtY,1376
8
- atomicguard/domain/interfaces.py,sha256=73vRiPzTLkVAiBc2srn-EUNFSQfleooQNx6r3odIQFM,6574
9
- atomicguard/domain/models.py,sha256=sVuHzuP98pgHefTz1mk1bYptgoeAySekRyBG2zMz7TE,8496
10
- atomicguard/domain/prompts.py,sha256=SMGcP0kYc9azCbGku5EG0JZZs83D80WkJO-DWiuFV58,2785
11
- atomicguard/guards/__init__.py,sha256=OzpOjwmyHGpTQSDVSDeGEuXUJNOyiNpZxZVnTVMIOyg,956
12
- atomicguard/guards/composite/__init__.py,sha256=AedlMBxFw4uTFExVWL6RJRR7vRwMOK3sgjhutkXz838,217
13
- atomicguard/guards/composite/base.py,sha256=VGydlOD4gmXdiDHvWXF5jSppXcJAoJYSCyDj7Lrbng0,1213
14
- atomicguard/guards/dynamic/__init__.py,sha256=pjBBeD_yYavvn-I7s5I3nTDOlZtPTq1Hqmim_RgW5cE,321
15
- atomicguard/guards/dynamic/test_runner.py,sha256=d5cPb5cCM-UnfZjTYGOHn4XoS-N66nr5EBHqPoDGwNM,7196
16
- atomicguard/guards/interactive/__init__.py,sha256=PlP5LNB4CMZ4fJ7Xr8gjjpn8VwLnB3zs5M2Em9xyVCc,226
17
- atomicguard/guards/interactive/human.py,sha256=G8SstAEdcMpHR2b8ugyG9drk9aBjw4_pE6E4UrTtcUo,2960
18
- atomicguard/guards/static/__init__.py,sha256=KANeEg_yhrKGzSmA0yf2SewOE9qkUwnJly4mWkBzsm4,305
19
- atomicguard/guards/static/imports.py,sha256=nWS3FNNqle7YWU5_tgRgYMRAXwEcWlxee8Q4MdomN5w,6292
20
- atomicguard/guards/static/syntax.py,sha256=mPVgGDY3pzwtXuulmmuEwYAQG7rNG0fgSGB1puYRI6Y,919
21
- atomicguard/infrastructure/__init__.py,sha256=Y3Ot6sRgTind-8s5kCnNtRYJGN3uq84QmbAUESx8Pio,581
22
- atomicguard/infrastructure/registry.py,sha256=XilDY2sUedwm5z1Xrp39HfQ9e3paixyJxL_hwGaVbqs,3662
23
- atomicguard/infrastructure/llm/__init__.py,sha256=wQg_FCAHmwbDXWm0bF5WX-9v7sutAS7RabhHCGiZZzo,338
24
- atomicguard/infrastructure/llm/huggingface.py,sha256=8VpkjuIzxAKOj3C6OBufS394AuDtbhreuPNv1rm-qJg,5756
25
- atomicguard/infrastructure/llm/mock.py,sha256=883Y7e2Q1yWapvp3rXn03bHEvuRnFwDe0CZsTZziG_E,2639
26
- atomicguard/infrastructure/llm/ollama.py,sha256=pLSZX_X5U1aPvIxCsF_wsQ_AHsTspqU3xkYHWLbgJQ0,4832
27
- atomicguard/infrastructure/persistence/__init__.py,sha256=KS95wmO_qVF6It63_884lWDoa-IB0WvRma_nXS2uTq4,483
28
- atomicguard/infrastructure/persistence/checkpoint.py,sha256=MS4qpJ_jcl6Ibw7h3KncWgDqz7CEIlFJdrpFcu2vEgs,13966
29
- atomicguard/infrastructure/persistence/filesystem.py,sha256=4upoycWCOlWRoSlVm4Ux_Kj8r3hX3Nm8N80x-IfBSLw,11440
30
- atomicguard/infrastructure/persistence/memory.py,sha256=JTnTwXSKYYDnQEYbjwAFVpklZVAlQlCDIt9zxcQjlz0,2042
31
- atomicguard/schemas/__init__.py,sha256=9z3gWBHsq8FHD2qE_TPy31wkTa_qXPfVgJrNdIu8p4g,3735
32
- atomicguard-1.2.0.dist-info/licenses/LICENSE,sha256=ROMMFVruZ18U24pKTNte9AK_YIqoMfXnMzoxqBNmKS4,1073
33
- atomicguard-1.2.0.dist-info/METADATA,sha256=slCf2YR0p3mYoZR2XnP96NUdCiD-qr5tLgMGo-LU4jk,6831
34
- atomicguard-1.2.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
35
- atomicguard-1.2.0.dist-info/entry_points.txt,sha256=MMVrkEyWFFCMoNIlpSWRY9FJYlEMGmaauvzMxEjwzTI,226
36
- atomicguard-1.2.0.dist-info/top_level.txt,sha256=J_6ENELjnacSYJ5N3FGwomp-sVeAJQohPkJBh6pu6iY,12
37
- atomicguard-1.2.0.dist-info/RECORD,,