continuum-toolkit 1.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.
Files changed (72) hide show
  1. cli/__init__.py +12 -0
  2. cli/main.py +415 -0
  3. confidence/__init__.py +13 -0
  4. confidence/calculator.py +308 -0
  5. confidence/models.py +40 -0
  6. context/__init__.py +17 -0
  7. context/models.py +108 -0
  8. context/pruner.py +228 -0
  9. context/selector.py +193 -0
  10. continuum_toolkit-1.0.0.dist-info/METADATA +511 -0
  11. continuum_toolkit-1.0.0.dist-info/RECORD +72 -0
  12. continuum_toolkit-1.0.0.dist-info/WHEEL +5 -0
  13. continuum_toolkit-1.0.0.dist-info/entry_points.txt +2 -0
  14. continuum_toolkit-1.0.0.dist-info/licenses/LICENSE +21 -0
  15. continuum_toolkit-1.0.0.dist-info/top_level.txt +13 -0
  16. contradictions/__init__.py +19 -0
  17. contradictions/detector.py +442 -0
  18. contradictions/models.py +75 -0
  19. core/__init__.py +97 -0
  20. core/enums.py +130 -0
  21. core/evidence.py +117 -0
  22. core/interfaces.py +209 -0
  23. core/schema.py +391 -0
  24. core/serializer.py +84 -0
  25. core/state_models.py +530 -0
  26. daemon/__init__.py +12 -0
  27. daemon/service.py +170 -0
  28. extractors/__init__.py +51 -0
  29. extractors/base.py +117 -0
  30. extractors/config/parsers.py +288 -0
  31. extractors/config/secret_sanitizer.py +91 -0
  32. extractors/config_extractor.py +172 -0
  33. extractors/conversation/analyzers.py +193 -0
  34. extractors/conversation/models.py +148 -0
  35. extractors/conversation_extractor.py +166 -0
  36. extractors/git_extractor.py +305 -0
  37. extractors/parsers/base.py +91 -0
  38. extractors/parsers/comment_parser.py +51 -0
  39. extractors/parsers/js_ts_parser.py +171 -0
  40. extractors/parsers/python_parser.py +180 -0
  41. extractors/verification/runners.py +278 -0
  42. extractors/verification_extractor.py +263 -0
  43. extractors/workspace_extractor.py +221 -0
  44. graph/__init__.py +24 -0
  45. graph/diff.py +109 -0
  46. graph/manager.py +473 -0
  47. graph/models.py +62 -0
  48. graph/propagator.py +194 -0
  49. graph/query.py +86 -0
  50. graph/snapshot.py +85 -0
  51. handoff/__init__.py +28 -0
  52. handoff/adapters/__init__.py +45 -0
  53. handoff/adapters/base.py +90 -0
  54. handoff/adapters/claude_adapter.py +176 -0
  55. handoff/adapters/codex_gpt_adapter.py +151 -0
  56. handoff/adapters/gemini_adapter.py +151 -0
  57. handoff/adapters/local_model_adapter.py +130 -0
  58. handoff/models.py +88 -0
  59. handoff/packager.py +288 -0
  60. pipeline/__init__.py +9 -0
  61. pipeline/orchestrator.py +260 -0
  62. resolution/__init__.py +15 -0
  63. resolution/resolver.py +311 -0
  64. storage/__init__.py +18 -0
  65. storage/hooks.py +125 -0
  66. storage/manager.py +127 -0
  67. storage/models.py +39 -0
  68. storage/recovery.py +98 -0
  69. watcher/__init__.py +17 -0
  70. watcher/detector.py +136 -0
  71. watcher/models.py +62 -0
  72. watcher/updater.py +163 -0
core/schema.py ADDED
@@ -0,0 +1,391 @@
1
+ """
2
+ Project Continuum - Schema Generator and Validator
3
+ ==================================================
4
+ Provides JSON Schema definitions, versioning metadata, and validation
5
+ utilities for CanonicalProjectState and all its subcomponents.
6
+ """
7
+
8
+ import json
9
+ from typing import Any, Dict, List, Tuple
10
+ from core.enums import Status, EvidenceType, EvidenceLevel, NodeType, RelationType, TargetModel
11
+
12
+
13
+ CANONICAL_STATE_SCHEMA_VERSION = "1.0.0"
14
+
15
+ def get_canonical_project_state_schema() -> Dict[str, Any]:
16
+ """
17
+ Returns the full JSON Schema (Draft 2020-12 / Draft-07 compatible)
18
+ for Project Continuum's Canonical Project State.
19
+ """
20
+ return {
21
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
22
+ "$id": f"https://project-continuum.dev/schemas/v{CANONICAL_STATE_SCHEMA_VERSION}/canonical-project-state.json",
23
+ "title": "CanonicalProjectState",
24
+ "description": "Root container for Project Continuum's verified state, segregating physical ground truth, conversational claims, and agent execution intent.",
25
+ "type": "object",
26
+ "required": [
27
+ "schema_version",
28
+ "project_id",
29
+ "created_at",
30
+ "updated_at",
31
+ "project_state",
32
+ "conversational_state",
33
+ "agent_execution_state",
34
+ "evidence_pool",
35
+ "graph_nodes",
36
+ "graph_edges",
37
+ "contradictions"
38
+ ],
39
+ "properties": {
40
+ "schema_version": {
41
+ "type": "string",
42
+ "pattern": r"^\d+\.\d+\.\d+$",
43
+ "default": CANONICAL_STATE_SCHEMA_VERSION
44
+ },
45
+ "project_id": {"type": "string"},
46
+ "created_at": {"type": "string", "format": "date-time"},
47
+ "updated_at": {"type": "string", "format": "date-time"},
48
+
49
+ # 1. Project State
50
+ "project_state": {
51
+ "type": "object",
52
+ "required": ["root_path", "detected_languages", "files", "manifests", "symbols", "git_state", "test_results", "build_status", "todo_markers", "evidence_ids", "last_scanned_at"],
53
+ "properties": {
54
+ "root_path": {"type": "string"},
55
+ "detected_languages": {"type": "array", "items": {"type": "string"}},
56
+ "files": {"type": "array", "items": {"type": "string"}},
57
+ "manifests": {
58
+ "type": "array",
59
+ "items": {
60
+ "type": "object",
61
+ "required": ["manifest_type", "file_path", "dependencies", "dev_dependencies", "scripts"],
62
+ "properties": {
63
+ "manifest_type": {"type": "string"},
64
+ "file_path": {"type": "string"},
65
+ "project_name": {"type": ["string", "null"]},
66
+ "version": {"type": ["string", "null"]},
67
+ "dependencies": {"type": "object"},
68
+ "dev_dependencies": {"type": "object"},
69
+ "scripts": {"type": "object"},
70
+ "evidence_id": {"type": ["string", "null"]}
71
+ }
72
+ }
73
+ },
74
+ "symbols": {
75
+ "type": "array",
76
+ "items": {
77
+ "type": "object",
78
+ "required": ["name", "kind", "file_path", "line_start", "line_end", "exported"],
79
+ "properties": {
80
+ "name": {"type": "string"},
81
+ "kind": {"type": "string"},
82
+ "file_path": {"type": "string"},
83
+ "line_start": {"type": "integer", "minimum": 1},
84
+ "line_end": {"type": "integer", "minimum": 1},
85
+ "exported": {"type": "boolean"},
86
+ "docstring": {"type": ["string", "null"]},
87
+ "parameters": {"type": "array", "items": {"type": "string"}},
88
+ "return_type": {"type": ["string", "null"]},
89
+ "evidence_id": {"type": ["string", "null"]}
90
+ }
91
+ }
92
+ },
93
+ "git_state": {
94
+ "type": "object",
95
+ "required": ["is_repo", "is_dirty", "staged_files", "unstaged_files", "untracked_files", "recent_commits", "evidence_ids"],
96
+ "properties": {
97
+ "is_repo": {"type": "boolean"},
98
+ "branch": {"type": ["string", "null"]},
99
+ "head_commit": {"type": ["string", "null"]},
100
+ "is_dirty": {"type": "boolean"},
101
+ "staged_files": {"type": "array", "items": {"type": "string"}},
102
+ "unstaged_files": {"type": "array", "items": {"type": "string"}},
103
+ "untracked_files": {"type": "array", "items": {"type": "string"}},
104
+ "recent_commits": {"type": "array", "items": {"type": "object"}},
105
+ "evidence_ids": {"type": "array", "items": {"type": "string"}}
106
+ }
107
+ },
108
+ "test_results": {
109
+ "type": "array",
110
+ "items": {
111
+ "type": "object",
112
+ "required": ["test_id", "name", "suite", "status", "exit_code", "duration_ms"],
113
+ "properties": {
114
+ "test_id": {"type": "string"},
115
+ "name": {"type": "string"},
116
+ "suite": {"type": "string"},
117
+ "status": {"type": "string", "enum": [s.value for s in Status]},
118
+ "exit_code": {"type": "integer"},
119
+ "duration_ms": {"type": "number"},
120
+ "output_snippet": {"type": "string"},
121
+ "error_message": {"type": ["string", "null"]},
122
+ "evidence_id": {"type": ["string", "null"]}
123
+ }
124
+ }
125
+ },
126
+ "build_status": {"type": "string", "enum": [s.value for s in Status]},
127
+ "todo_markers": {"type": "array", "items": {"type": "object"}},
128
+ "evidence_ids": {"type": "array", "items": {"type": "string"}},
129
+ "last_scanned_at": {"type": "string"}
130
+ }
131
+ },
132
+
133
+ # 2. Conversational State
134
+ "conversational_state": {
135
+ "type": "object",
136
+ "required": ["session_id", "user_requirements", "architectural_decisions", "agent_claims", "assumptions", "unresolved_questions", "transcript_provenance"],
137
+ "properties": {
138
+ "session_id": {"type": "string"},
139
+ "user_requirements": {
140
+ "type": "array",
141
+ "items": {
142
+ "type": "object",
143
+ "required": ["id", "title", "description", "status"],
144
+ "properties": {
145
+ "id": {"type": "string"},
146
+ "title": {"type": "string"},
147
+ "description": {"type": "string"},
148
+ "source_turn": {"type": ["integer", "null"]},
149
+ "status": {"type": "string", "enum": [s.value for s in Status]},
150
+ "evidence_id": {"type": ["string", "null"]}
151
+ }
152
+ }
153
+ },
154
+ "architectural_decisions": {
155
+ "type": "array",
156
+ "items": {
157
+ "type": "object",
158
+ "required": ["id", "title", "rationale", "constraints", "recorded_at"],
159
+ "properties": {
160
+ "id": {"type": "string"},
161
+ "title": {"type": "string"},
162
+ "rationale": {"type": "string"},
163
+ "constraints": {"type": "array", "items": {"type": "string"}},
164
+ "recorded_at": {"type": "string"},
165
+ "evidence_id": {"type": ["string", "null"]}
166
+ }
167
+ }
168
+ },
169
+ "agent_claims": {
170
+ "type": "array",
171
+ "items": {
172
+ "type": "object",
173
+ "required": ["id", "claim_text", "claimed_status", "source_agent"],
174
+ "properties": {
175
+ "id": {"type": "string"},
176
+ "claim_text": {"type": "string"},
177
+ "target_component": {"type": ["string", "null"]},
178
+ "claimed_status": {"type": "string", "enum": [s.value for s in Status]},
179
+ "source_agent": {"type": "string"},
180
+ "turn_id": {"type": ["integer", "null"]},
181
+ "confidence_claimed": {"type": ["number", "null"]},
182
+ "evidence_id": {"type": ["string", "null"]}
183
+ }
184
+ }
185
+ },
186
+ "assumptions": {"type": "array", "items": {"type": "string"}},
187
+ "unresolved_questions": {
188
+ "type": "array",
189
+ "items": {
190
+ "type": "object",
191
+ "required": ["id", "question", "context", "blocking", "asked_at"],
192
+ "properties": {
193
+ "id": {"type": "string"},
194
+ "question": {"type": "string"},
195
+ "context": {"type": "string"},
196
+ "blocking": {"type": "boolean"},
197
+ "asked_at": {"type": "string"},
198
+ "evidence_id": {"type": ["string", "null"]}
199
+ }
200
+ }
201
+ },
202
+ "transcript_provenance": {"type": "array", "items": {"type": "string"}}
203
+ }
204
+ },
205
+
206
+ # 3. Agent Execution State
207
+ "agent_execution_state": {
208
+ "type": "object",
209
+ "required": ["agent_id", "model_name", "active_tasks", "modified_files_in_flight", "last_error_encountered", "next_action", "execution_context_metadata", "updated_at"],
210
+ "properties": {
211
+ "agent_id": {"type": "string"},
212
+ "model_name": {"type": "string"},
213
+ "active_tasks": {
214
+ "type": "array",
215
+ "items": {
216
+ "type": "object",
217
+ "required": ["id", "title", "status", "target_files", "target_symbols", "notes"],
218
+ "properties": {
219
+ "id": {"type": "string"},
220
+ "title": {"type": "string"},
221
+ "status": {"type": "string", "enum": [s.value for s in Status]},
222
+ "target_files": {"type": "array", "items": {"type": "string"}},
223
+ "target_symbols": {"type": "array", "items": {"type": "string"}},
224
+ "notes": {"type": "string"}
225
+ }
226
+ }
227
+ },
228
+ "modified_files_in_flight": {"type": "array", "items": {"type": "string"}},
229
+ "last_error_encountered": {"type": ["string", "null"]},
230
+ "next_action": {
231
+ "type": ["object", "null"],
232
+ "properties": {
233
+ "action_type": {"type": "string"},
234
+ "target_uri": {"type": "string"},
235
+ "description": {"type": "string"},
236
+ "prerequisites": {"type": "array", "items": {"type": "string"}}
237
+ }
238
+ },
239
+ "execution_context_metadata": {"type": "object"},
240
+ "updated_at": {"type": "string"}
241
+ }
242
+ },
243
+
244
+ # Global Evidence Pool
245
+ "evidence_pool": {
246
+ "type": "object",
247
+ "additionalProperties": {
248
+ "type": "object",
249
+ "required": ["id", "type", "level", "summary", "raw_payload", "checksum", "created_at"],
250
+ "properties": {
251
+ "id": {"type": "string"},
252
+ "type": {"type": "string", "enum": [e.value for e in EvidenceType]},
253
+ "level": {"type": "integer", "enum": [int(l.value) for l in EvidenceLevel]},
254
+ "summary": {"type": "string"},
255
+ "raw_payload": {"type": "object"},
256
+ "provenance": {
257
+ "type": ["object", "null"],
258
+ "properties": {
259
+ "extractor_name": {"type": "string"},
260
+ "source_uri": {"type": "string"},
261
+ "locator": {"type": "string"},
262
+ "collected_at": {"type": "string"},
263
+ "environment_info": {"type": "object"}
264
+ }
265
+ },
266
+ "checksum": {"type": "string"},
267
+ "created_at": {"type": "string"},
268
+ "metadata": {"type": "object"}
269
+ }
270
+ }
271
+ },
272
+
273
+ # Graph Nodes
274
+ "graph_nodes": {
275
+ "type": "object",
276
+ "additionalProperties": {
277
+ "type": "object",
278
+ "required": ["id", "name", "node_type", "status", "confidence_score", "evidence_ids"],
279
+ "properties": {
280
+ "id": {"type": "string"},
281
+ "name": {"type": "string"},
282
+ "node_type": {"type": "string", "enum": [n.value for n in NodeType]},
283
+ "status": {"type": "string", "enum": [s.value for s in Status]},
284
+ "confidence_score": {"type": "number", "minimum": 0.0, "maximum": 100.0},
285
+ "evidence_ids": {"type": "array", "items": {"type": "string"}},
286
+ "metadata": {"type": "object"}
287
+ }
288
+ }
289
+ },
290
+
291
+ # Graph Edges
292
+ "graph_edges": {
293
+ "type": "array",
294
+ "items": {
295
+ "type": "object",
296
+ "required": ["source_id", "target_id", "relation"],
297
+ "properties": {
298
+ "source_id": {"type": "string"},
299
+ "target_id": {"type": "string"},
300
+ "relation": {"type": "string", "enum": [r.value for r in RelationType]}
301
+ }
302
+ }
303
+ },
304
+
305
+ # Contradictions
306
+ "contradictions": {
307
+ "type": "array",
308
+ "items": {
309
+ "type": "object",
310
+ "required": ["id", "severity", "claim_text", "explanation", "detected_at", "resolved"],
311
+ "properties": {
312
+ "id": {"type": "string"},
313
+ "severity": {"type": "string", "enum": ["HIGH", "MEDIUM", "LOW"]},
314
+ "claim_id": {"type": ["string", "null"]},
315
+ "claim_text": {"type": "string"},
316
+ "physical_evidence_id": {"type": ["string", "null"]},
317
+ "explanation": {"type": "string"},
318
+ "detected_at": {"type": "string"},
319
+ "resolved": {"type": "boolean"}
320
+ }
321
+ }
322
+ }
323
+ }
324
+ }
325
+
326
+
327
+ def validate_canonical_state_dict(data: Dict[str, Any]) -> Tuple[bool, List[str]]:
328
+ """
329
+ Lightweight validator that verifies dictionary structure against Canonical schema rules.
330
+ Returns (is_valid, list_of_errors).
331
+ """
332
+ errors: List[str] = []
333
+
334
+ # Required top level keys
335
+ required_top = [
336
+ "schema_version", "project_id", "created_at", "updated_at",
337
+ "project_state", "conversational_state", "agent_execution_state",
338
+ "evidence_pool", "graph_nodes", "graph_edges", "contradictions"
339
+ ]
340
+ for key in required_top:
341
+ if key not in data:
342
+ errors.append(f"Missing required top-level field: '{key}'")
343
+
344
+ if errors:
345
+ return False, errors
346
+
347
+ # Check state separation
348
+ if not isinstance(data.get("project_state"), dict):
349
+ errors.append("'project_state' must be an object")
350
+ if not isinstance(data.get("conversational_state"), dict):
351
+ errors.append("'conversational_state' must be an object")
352
+ if not isinstance(data.get("agent_execution_state"), dict):
353
+ errors.append("'agent_execution_state' must be an object")
354
+
355
+ # Validate statuses inside test_results
356
+ for test in data.get("project_state", {}).get("test_results", []):
357
+ st = test.get("status")
358
+ if st not in [s.value for s in Status]:
359
+ errors.append(f"Invalid TestResult status '{st}'")
360
+
361
+ # Validate evidence pool
362
+ for ev_id, ev in data.get("evidence_pool", {}).items():
363
+ if not isinstance(ev, dict):
364
+ errors.append(f"Evidence '{ev_id}' must be an object")
365
+ continue
366
+ ev_type = ev.get("type")
367
+ if ev_type not in [e.value for e in EvidenceType]:
368
+ errors.append(f"Invalid EvidenceType '{ev_type}' in evidence '{ev_id}'")
369
+ ev_lvl = ev.get("level")
370
+ if ev_lvl not in [int(l.value) for l in EvidenceLevel]:
371
+ errors.append(f"Invalid EvidenceLevel '{ev_lvl}' in evidence '{ev_id}'")
372
+
373
+ # Validate Graph Nodes
374
+ for n_id, node in data.get("graph_nodes", {}).items():
375
+ if not isinstance(node, dict):
376
+ errors.append(f"GraphNode '{n_id}' must be an object")
377
+ continue
378
+ nt = node.get("node_type")
379
+ if nt not in [n.value for n in NodeType]:
380
+ errors.append(f"Invalid NodeType '{nt}' in node '{n_id}'")
381
+ conf = node.get("confidence_score", 0.0)
382
+ if not (0.0 <= conf <= 100.0):
383
+ errors.append(f"Confidence score {conf} out of range [0, 100] in node '{n_id}'")
384
+
385
+ # Validate Graph Edges
386
+ for edge in data.get("graph_edges", []):
387
+ rel = edge.get("relation")
388
+ if rel not in [r.value for r in RelationType]:
389
+ errors.append(f"Invalid RelationType '{rel}' in edge")
390
+
391
+ return (len(errors) == 0, errors)
core/serializer.py ADDED
@@ -0,0 +1,84 @@
1
+ """
2
+ Project Continuum - Canonical State Serializer & Deserializer
3
+ ============================================================
4
+ Handles deterministic JSON round-trip serialization, file persistence,
5
+ integrity checks, and schema validation.
6
+ """
7
+
8
+ import json
9
+ from pathlib import Path
10
+ from typing import Any, Dict, Optional, Union
11
+
12
+ from core.state_models import CanonicalProjectState
13
+ from core.schema import validate_canonical_state_dict
14
+
15
+
16
+ class StateSerializationError(Exception):
17
+ """Raised when serialization or deserialization fails."""
18
+ pass
19
+
20
+
21
+ class StateValidationError(Exception):
22
+ """Raised when a state object violates schema contracts."""
23
+ pass
24
+
25
+
26
+ class CanonicalStateSerializer:
27
+ """
28
+ Serializer/Deserializer for Project Continuum Canonical Project State.
29
+ Ensures deterministic ordering, schema validation, and strict state isolation.
30
+ """
31
+
32
+ @staticmethod
33
+ def to_dict(state: CanonicalProjectState) -> Dict[str, Any]:
34
+ """Converts CanonicalProjectState to a validated python dictionary."""
35
+ d = state.to_dict()
36
+ is_valid, errors = validate_canonical_state_dict(d)
37
+ if not is_valid:
38
+ raise StateValidationError(f"State failed schema validation: {', '.join(errors)}")
39
+ return d
40
+
41
+ @staticmethod
42
+ def to_json(state: CanonicalProjectState, indent: int = 2) -> str:
43
+ """Serializes CanonicalProjectState to a formatted JSON string with deterministic sorting."""
44
+ state_dict = CanonicalStateSerializer.to_dict(state)
45
+ return json.dumps(state_dict, indent=indent, sort_keys=True, ensure_ascii=False)
46
+
47
+ @staticmethod
48
+ def from_dict(data: Dict[str, Any], validate: bool = True) -> CanonicalProjectState:
49
+ """Constructs and validates a CanonicalProjectState instance from a dict."""
50
+ if validate:
51
+ is_valid, errors = validate_canonical_state_dict(data)
52
+ if not is_valid:
53
+ raise StateValidationError(f"State dict failed schema validation: {', '.join(errors)}")
54
+ return CanonicalProjectState.from_dict(data)
55
+
56
+ @staticmethod
57
+ def from_json(json_str: str, validate: bool = True) -> CanonicalProjectState:
58
+ """Parses a JSON string into CanonicalProjectState."""
59
+ try:
60
+ data = json.loads(json_str)
61
+ except json.JSONDecodeError as e:
62
+ raise StateSerializationError(f"Malformed JSON: {e}") from e
63
+ return CanonicalStateSerializer.from_dict(data, validate=validate)
64
+
65
+ @staticmethod
66
+ def save_to_file(state: CanonicalProjectState, file_path: Union[str, Path], indent: int = 2) -> None:
67
+ """Writes canonical state JSON atomically to disk."""
68
+ target_path = Path(file_path)
69
+ target_path.parent.mkdir(parents=True, exist_ok=True)
70
+ json_content = CanonicalStateSerializer.to_json(state, indent=indent)
71
+
72
+ # Write to temp file then rename for atomic write
73
+ temp_file = target_path.with_suffix(f"{target_path.suffix}.tmp")
74
+ temp_file.write_text(json_content, encoding="utf-8")
75
+ temp_file.replace(target_path)
76
+
77
+ @staticmethod
78
+ def load_from_file(file_path: Union[str, Path], validate: bool = True) -> CanonicalProjectState:
79
+ """Reads canonical state from a JSON file."""
80
+ target_path = Path(file_path)
81
+ if not target_path.exists():
82
+ raise FileNotFoundError(f"State file not found: {target_path}")
83
+ content = target_path.read_text(encoding="utf-8")
84
+ return CanonicalStateSerializer.from_json(content, validate=validate)