vigil-codeintel 0.1.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 (131) hide show
  1. vigil_codeintel-0.1.0.dist-info/METADATA +780 -0
  2. vigil_codeintel-0.1.0.dist-info/RECORD +131 -0
  3. vigil_codeintel-0.1.0.dist-info/WHEEL +5 -0
  4. vigil_codeintel-0.1.0.dist-info/entry_points.txt +3 -0
  5. vigil_codeintel-0.1.0.dist-info/licenses/LICENSE +21 -0
  6. vigil_codeintel-0.1.0.dist-info/top_level.txt +3 -0
  7. vigil_forensic/__init__.py +224 -0
  8. vigil_forensic/_git_utils.py +178 -0
  9. vigil_forensic/_shared.py +510 -0
  10. vigil_forensic/_stubs.py +156 -0
  11. vigil_forensic/gate_checks/__init__.py +1 -0
  12. vigil_forensic/gate_checks/_ast_helpers.py +629 -0
  13. vigil_forensic/gate_checks/_deployment_detector.py +573 -0
  14. vigil_forensic/gate_checks/atomic_write_checks.py +1143 -0
  15. vigil_forensic/gate_checks/authority_checks.py +95 -0
  16. vigil_forensic/gate_checks/boundary_breach_checks.py +202 -0
  17. vigil_forensic/gate_checks/broad_except_checks.py +301 -0
  18. vigil_forensic/gate_checks/broad_except_hidden_sentinel_checks.py +365 -0
  19. vigil_forensic/gate_checks/common.py +253 -0
  20. vigil_forensic/gate_checks/config_safety_checks.py +704 -0
  21. vigil_forensic/gate_checks/config_ssot_checks.py +78 -0
  22. vigil_forensic/gate_checks/conflict_checks.py +193 -0
  23. vigil_forensic/gate_checks/context_fallback_checks.py +697 -0
  24. vigil_forensic/gate_checks/context_health_checks.py +289 -0
  25. vigil_forensic/gate_checks/contract_shape_drift_checks.py +459 -0
  26. vigil_forensic/gate_checks/dirty_baseline_check.py +274 -0
  27. vigil_forensic/gate_checks/duplication_checks.py +387 -0
  28. vigil_forensic/gate_checks/embedded_string_checks.py +123 -0
  29. vigil_forensic/gate_checks/empty_output_checks.py +87 -0
  30. vigil_forensic/gate_checks/encoding_checks.py +847 -0
  31. vigil_forensic/gate_checks/export_completeness_checks.py +156 -0
  32. vigil_forensic/gate_checks/fallback_checks.py +41 -0
  33. vigil_forensic/gate_checks/file_proliferation_checks.py +171 -0
  34. vigil_forensic/gate_checks/fix_without_test_checks.py +69 -0
  35. vigil_forensic/gate_checks/forensic_cluster_runners/__init__.py +9 -0
  36. vigil_forensic/gate_checks/forensic_cluster_runners/_helpers.py +71 -0
  37. vigil_forensic/gate_checks/forensic_cluster_runners/advanced_checks.py +322 -0
  38. vigil_forensic/gate_checks/forensic_cluster_runners/core.py +273 -0
  39. vigil_forensic/gate_checks/forensic_cluster_runners/integrity_checks.py +203 -0
  40. vigil_forensic/gate_checks/forensic_cluster_runners/quality_checks.py +666 -0
  41. vigil_forensic/gate_checks/forensic_clusters/__init__.py +193 -0
  42. vigil_forensic/gate_checks/forensic_clusters/allowlist.py +426 -0
  43. vigil_forensic/gate_checks/forensic_clusters/allowlist_writer.py +302 -0
  44. vigil_forensic/gate_checks/forensic_clusters/api_protocol.py +231 -0
  45. vigil_forensic/gate_checks/forensic_clusters/async_quality.py +1156 -0
  46. vigil_forensic/gate_checks/forensic_clusters/code_style.py +808 -0
  47. vigil_forensic/gate_checks/forensic_clusters/core.py +319 -0
  48. vigil_forensic/gate_checks/forensic_clusters/data_quality.py +763 -0
  49. vigil_forensic/gate_checks/forensic_clusters/dead_code.py +480 -0
  50. vigil_forensic/gate_checks/forensic_clusters/edit_mutation.py +842 -0
  51. vigil_forensic/gate_checks/forensic_clusters/exception_boundary.py +240 -0
  52. vigil_forensic/gate_checks/forensic_clusters/legacy_debt.py +556 -0
  53. vigil_forensic/gate_checks/forensic_clusters/static_analysis.py +834 -0
  54. vigil_forensic/gate_checks/forensic_clusters/structural_quality.py +298 -0
  55. vigil_forensic/gate_checks/god_object_zones_checks.py +173 -0
  56. vigil_forensic/gate_checks/hallucination_checks.py +566 -0
  57. vigil_forensic/gate_checks/hunter_artifact_completeness_check.py +139 -0
  58. vigil_forensic/gate_checks/implementation_overfit_checks.py +380 -0
  59. vigil_forensic/gate_checks/import_integrity_checks.py +233 -0
  60. vigil_forensic/gate_checks/imports_in_function_checks.py +283 -0
  61. vigil_forensic/gate_checks/ml_checks.py +318 -0
  62. vigil_forensic/gate_checks/performance_checks.py +106 -0
  63. vigil_forensic/gate_checks/project_specific_runner.py +691 -0
  64. vigil_forensic/gate_checks/provider_capability_checks.py +73 -0
  65. vigil_forensic/gate_checks/refactor_completeness_checks.py +274 -0
  66. vigil_forensic/gate_checks/reliability_checks.py +389 -0
  67. vigil_forensic/gate_checks/reporting_checks.py +55 -0
  68. vigil_forensic/gate_checks/runtime_behavior_checks.py +220 -0
  69. vigil_forensic/gate_checks/security_injection_checks.py +332 -0
  70. vigil_forensic/gate_checks/semantic_intent_checks.py +139 -0
  71. vigil_forensic/gate_checks/size_complexity_checks.py +336 -0
  72. vigil_forensic/gate_checks/stuck_feature_flag_checks.py +354 -0
  73. vigil_forensic/gate_checks/syntax_validity_checks.py +217 -0
  74. vigil_forensic/gate_checks/temporal_freshness_checks.py +79 -0
  75. vigil_forensic/gate_checks/test_quality_checks.py +946 -0
  76. vigil_forensic/gate_checks/testing_checks.py +149 -0
  77. vigil_forensic/gate_checks/toctou_checks.py +367 -0
  78. vigil_forensic/gate_checks/type_checking_checks.py +316 -0
  79. vigil_forensic/gate_models.py +392 -0
  80. vigil_forensic/gate_packs/__init__.py +1 -0
  81. vigil_forensic/gate_packs/universal.py +179 -0
  82. vigil_forensic/gate_profile.json +31 -0
  83. vigil_forensic/gate_registry.py +21 -0
  84. vigil_forensic/language_profiles.py +219 -0
  85. vigil_forensic/meta_findings.py +207 -0
  86. vigil_forensic/self_audit.py +725 -0
  87. vigil_forensic/source_analysis.py +175 -0
  88. vigil_mapper/__init__.py +103 -0
  89. vigil_mapper/_ast_helpers_minimal.py +229 -0
  90. vigil_mapper/_extract_imports_impl.py +123 -0
  91. vigil_mapper/_file_count_guard.py +129 -0
  92. vigil_mapper/_git_utils.py +178 -0
  93. vigil_mapper/_runtime_ast.py +438 -0
  94. vigil_mapper/_runtime_dispatch.py +137 -0
  95. vigil_mapper/_seed_helpers.py +82 -0
  96. vigil_mapper/authority_builder.py +1102 -0
  97. vigil_mapper/cli_entry.py +731 -0
  98. vigil_mapper/conflict_builder.py +818 -0
  99. vigil_mapper/data_contract_builder.py +446 -0
  100. vigil_mapper/findings_builder.py +716 -0
  101. vigil_mapper/fingerprint.py +53 -0
  102. vigil_mapper/hotspot_builder.py +539 -0
  103. vigil_mapper/map_common.py +449 -0
  104. vigil_mapper/map_errors.py +55 -0
  105. vigil_mapper/map_models.py +431 -0
  106. vigil_mapper/map_models_ext.py +206 -0
  107. vigil_mapper/map_models_findings.py +130 -0
  108. vigil_mapper/map_storage.py +455 -0
  109. vigil_mapper/parse_cache.py +795 -0
  110. vigil_mapper/refactor_boundary_builder.py +266 -0
  111. vigil_mapper/runtime_builder.py +527 -0
  112. vigil_mapper/runtime_tracer.py +243 -0
  113. vigil_mapper/runtime_tracer_entry.py +199 -0
  114. vigil_mapper/semantic_diff.py +71 -0
  115. vigil_mapper/source_adapters/__init__.py +109 -0
  116. vigil_mapper/source_adapters/_base.py +264 -0
  117. vigil_mapper/source_adapters/_ir.py +156 -0
  118. vigil_mapper/source_adapters/_lexer.py +309 -0
  119. vigil_mapper/source_adapters/_patterns.py +212 -0
  120. vigil_mapper/source_adapters/_treesitter.py +182 -0
  121. vigil_mapper/source_adapters/go.py +553 -0
  122. vigil_mapper/source_adapters/java.py +541 -0
  123. vigil_mapper/source_adapters/javascript.py +626 -0
  124. vigil_mapper/source_adapters/python.py +325 -0
  125. vigil_mapper/source_adapters/typescript.py +749 -0
  126. vigil_mapper/structural_builder.py +586 -0
  127. vigil_mcp/__init__.py +1 -0
  128. vigil_mcp/_jobs.py +587 -0
  129. vigil_mcp/_paths.py +93 -0
  130. vigil_mcp/forensic_server.py +419 -0
  131. vigil_mcp/map_server.py +452 -0
@@ -0,0 +1,392 @@
1
+ """Gate models for vigil_forensic.
2
+
3
+ Re-exports shared vocabulary types from _shared (inlined from the Vigil shared_helpers.gate_models)
4
+ and defines PostExecGateContext and related dataclasses (inlined from the Vigil autoforensics.gate_models).
5
+
6
+ This module provides backward-compatible re-exports so gate_checks can use:
7
+ from vigil_forensic.gate_models import PostExecGateContext, ...
8
+ """
9
+ from __future__ import annotations
10
+
11
+ import logging
12
+ import time
13
+ from dataclasses import dataclass, field
14
+ from pathlib import Path
15
+ from typing import TYPE_CHECKING, Any, Mapping, Optional
16
+
17
+ _log = logging.getLogger(__name__)
18
+
19
+ # Import coerce_float from our inlined _shared
20
+ from vigil_forensic._shared import coerce_float as _coerce_float
21
+
22
+ # Re-export the shared vocabulary from our inlined _shared module.
23
+ from vigil_forensic._shared import ( # noqa: F401
24
+ EvidenceReference,
25
+ GateCategory,
26
+ GateCheckResult,
27
+ GateFileSnapshot,
28
+ GateFinding,
29
+ GateImpact,
30
+ GateSeverity,
31
+ GateVerdict,
32
+ RepairKind,
33
+ RepoGateProfile,
34
+ )
35
+
36
+ # Import stubs for control-plane types (replaces SYSTEM.control_plane.models
37
+ # and SYSTEM.runtime.pocketcoder_adapter imports in the original self_audit.py)
38
+ from vigil_forensic._stubs import ValidationContractProfile, PocketCoderForensicReport
39
+
40
+ if TYPE_CHECKING:
41
+ pass # No TYPE_CHECKING imports needed in the standalone package
42
+
43
+
44
+ # Default identity strings
45
+ _VERDICT_OWNER_DEFAULT: str = "orchestrator"
46
+ _PROMPT_OWNER_DEFAULT: str = "orchestrator"
47
+ _SUPERVISOR_DEFAULT: str = "orchestrator"
48
+
49
+
50
+ _HOOK_TRACE_KNOWN_KEYS: frozenset[str] = frozenset({
51
+ "ts", "tool_name", "decision", "reason", "attempt_id", "summary",
52
+ "command_scope", "is_remote_wrapper", "approval_class", "actor",
53
+ "policy_rule", "provenance", "target_path", "target_paths",
54
+ "workspace_root", "path_scope", "tool_input_digest",
55
+ })
56
+
57
+
58
+ def _now() -> float:
59
+ return time.time()
60
+
61
+
62
+ @dataclass(frozen=True)
63
+ class HookTraceEntry:
64
+ ts: float = 0.0
65
+ tool_name: str = ""
66
+ decision: str = ""
67
+ reason: str = ""
68
+ attempt_id: str = "unknown"
69
+ summary: str = ""
70
+ command_scope: str = ""
71
+ is_remote_wrapper: bool = False
72
+ approval_class: str = ""
73
+ actor: str = ""
74
+ policy_rule: str = ""
75
+ target_path: str = ""
76
+ target_paths: tuple[str, ...] = ()
77
+ workspace_root: str = ""
78
+ path_scope: str = ""
79
+ tool_input_digest: str = ""
80
+ extras: tuple[tuple[str, object], ...] = ()
81
+
82
+ @classmethod
83
+ def from_mapping(cls, data: Mapping[str, object]) -> "HookTraceEntry":
84
+ provenance_raw = data.get("provenance")
85
+ provenance: dict[str, object] = dict(provenance_raw) if isinstance(provenance_raw, dict) else {}
86
+
87
+ def _pick(name: str, default: object = "") -> object:
88
+ if name in data:
89
+ return data.get(name)
90
+ return provenance.get(name, default)
91
+
92
+ extras_raw = [(key, value) for key, value in data.items() if key not in _HOOK_TRACE_KNOWN_KEYS]
93
+ if provenance:
94
+ for prov_key, prov_val in provenance.items():
95
+ if prov_key in _HOOK_TRACE_KNOWN_KEYS:
96
+ continue
97
+ extras_raw.append((prov_key, prov_val))
98
+ extras_raw.sort(key=lambda item: item[0])
99
+
100
+ target_paths_raw = data.get("target_paths")
101
+ if isinstance(target_paths_raw, (list, tuple)):
102
+ target_paths = tuple(str(x) for x in target_paths_raw)
103
+ else:
104
+ target_paths = ()
105
+
106
+ return cls(
107
+ ts=_coerce_float(data.get("ts")),
108
+ tool_name=str(data.get("tool_name", "") or ""),
109
+ decision=str(data.get("decision", "") or ""),
110
+ reason=str(data.get("reason", "") or ""),
111
+ attempt_id=str(data.get("attempt_id", "unknown") or "unknown"),
112
+ summary=str(data.get("summary", "") or ""),
113
+ command_scope=str(data.get("command_scope", "") or ""),
114
+ is_remote_wrapper=bool(data.get("is_remote_wrapper", False)),
115
+ approval_class=str(data.get("approval_class", "") or ""),
116
+ actor=str(_pick("actor", "") or ""),
117
+ policy_rule=str(_pick("policy_rule", "") or ""),
118
+ target_path=str(data.get("target_path", "") or ""),
119
+ target_paths=target_paths,
120
+ workspace_root=str(data.get("workspace_root", "") or ""),
121
+ path_scope=str(data.get("path_scope", "") or ""),
122
+ tool_input_digest=str(data.get("tool_input_digest", "") or ""),
123
+ extras=tuple(extras_raw),
124
+ )
125
+
126
+ def to_dict(self) -> dict[str, object]:
127
+ payload: dict[str, object] = {
128
+ "ts": self.ts, "tool_name": self.tool_name, "decision": self.decision,
129
+ "reason": self.reason, "attempt_id": self.attempt_id, "summary": self.summary,
130
+ "command_scope": self.command_scope, "is_remote_wrapper": self.is_remote_wrapper,
131
+ "approval_class": self.approval_class, "actor": self.actor,
132
+ "policy_rule": self.policy_rule, "target_path": self.target_path,
133
+ "target_paths": list(self.target_paths), "workspace_root": self.workspace_root,
134
+ "path_scope": self.path_scope, "tool_input_digest": self.tool_input_digest,
135
+ }
136
+ for key, value in self.extras:
137
+ payload[key] = value
138
+ return payload
139
+
140
+
141
+ @dataclass(frozen=True)
142
+ class RuntimeState:
143
+ health: str = "healthy"
144
+ runtime_model: str = "local_workspace"
145
+ survives_console_exit: Optional[bool] = None
146
+ extras: tuple[tuple[str, object], ...] = ()
147
+
148
+ @classmethod
149
+ def from_mapping(cls, data: Mapping[str, object]) -> "RuntimeState":
150
+ known = {"health", "runtime_model", "survives_console_exit"}
151
+ extras = sorted(
152
+ ((k, v) for k, v in data.items() if k not in known),
153
+ key=lambda item: item[0],
154
+ )
155
+ raw_survives = data.get("survives_console_exit")
156
+ survives: Optional[bool] = None if raw_survives is None else bool(raw_survives)
157
+ return cls(
158
+ health=str(data.get("health", "healthy") or "healthy"),
159
+ runtime_model=str(data.get("runtime_model", "local_workspace") or "local_workspace"),
160
+ survives_console_exit=survives,
161
+ extras=tuple(extras),
162
+ )
163
+
164
+ def to_dict(self) -> dict[str, object]:
165
+ payload: dict[str, object] = {
166
+ "health": self.health, "runtime_model": self.runtime_model,
167
+ "survives_console_exit": self.survives_console_exit,
168
+ }
169
+ for key, value in self.extras:
170
+ payload[key] = value
171
+ return payload
172
+
173
+
174
+ @dataclass(frozen=True)
175
+ class VerificationSummary:
176
+ passed: bool = True
177
+ blocking_issues: tuple[str, ...] = ()
178
+ warnings: tuple[str, ...] = ()
179
+ summary: str = ""
180
+ verdict_owner: str = _VERDICT_OWNER_DEFAULT
181
+ extras: tuple[tuple[str, object], ...] = ()
182
+
183
+ @classmethod
184
+ def from_mapping(cls, data: Mapping[str, object]) -> "VerificationSummary":
185
+ known = {"passed", "blocking_issues", "warnings", "summary", "verdict_owner"}
186
+
187
+ def _str_tuple(value: object) -> tuple[str, ...]:
188
+ if value is None:
189
+ return ()
190
+ if isinstance(value, (list, tuple)):
191
+ return tuple(str(item) for item in value)
192
+ return ()
193
+
194
+ extras = sorted(
195
+ ((k, v) for k, v in data.items() if k not in known),
196
+ key=lambda item: item[0],
197
+ )
198
+ return cls(
199
+ passed=bool(data.get("passed", True)),
200
+ blocking_issues=_str_tuple(data.get("blocking_issues", ())),
201
+ warnings=_str_tuple(data.get("warnings", ())),
202
+ summary=str(data.get("summary", "") or ""),
203
+ verdict_owner=str(data.get("verdict_owner", _VERDICT_OWNER_DEFAULT) or _VERDICT_OWNER_DEFAULT),
204
+ extras=tuple(extras),
205
+ )
206
+
207
+ def to_dict(self) -> dict[str, object]:
208
+ payload: dict[str, object] = {
209
+ "passed": self.passed, "blocking_issues": list(self.blocking_issues),
210
+ "warnings": list(self.warnings), "summary": self.summary,
211
+ "verdict_owner": self.verdict_owner,
212
+ }
213
+ for key, value in self.extras:
214
+ payload[key] = value
215
+ return payload
216
+
217
+
218
+ @dataclass(frozen=True)
219
+ class HookTraceLoadProvenance:
220
+ kind: str = ""
221
+ started_at: float = 0.0
222
+ entries_considered: int = 0
223
+ entries_loaded: int = 0
224
+ extras: tuple[tuple[str, object], ...] = ()
225
+
226
+ @classmethod
227
+ def from_mapping(cls, data: Mapping[str, object]) -> "HookTraceLoadProvenance":
228
+ known = {"kind", "started_at", "entries_considered", "entries_loaded"}
229
+ extras = tuple(sorted(((k, v) for k, v in data.items() if k not in known), key=lambda item: item[0]))
230
+ return cls(
231
+ kind=str(data.get("kind", "") or ""),
232
+ started_at=_coerce_float(data.get("started_at")),
233
+ entries_considered=int(data.get("entries_considered", 0) or 0),
234
+ entries_loaded=int(data.get("entries_loaded", 0) or 0),
235
+ extras=extras,
236
+ )
237
+
238
+ def to_dict(self) -> dict[str, object]:
239
+ out: dict[str, object] = {
240
+ "kind": self.kind, "started_at": self.started_at,
241
+ "entries_considered": self.entries_considered, "entries_loaded": self.entries_loaded,
242
+ }
243
+ for k, v in self.extras:
244
+ out[k] = v
245
+ return out
246
+
247
+
248
+ @dataclass(frozen=True)
249
+ class DraftMessageEvidence:
250
+ message_id: str = ""
251
+ draft_id: str = ""
252
+ role: str = ""
253
+ created_at: float = 0.0
254
+ no_executor_started: bool = True
255
+ draft_assistant_mode: str = ""
256
+ extras: tuple[tuple[str, object], ...] = ()
257
+
258
+ @classmethod
259
+ def from_mapping(cls, data: Mapping[str, object]) -> "DraftMessageEvidence":
260
+ known = {"message_id", "draft_id", "role", "created_at", "no_executor_started", "draft_assistant_mode"}
261
+ extras = tuple((k, v) for k, v in data.items() if k not in known)
262
+ return cls(
263
+ message_id=str(data.get("message_id", "") or ""),
264
+ draft_id=str(data.get("draft_id", "") or ""),
265
+ role=str(data.get("role", "") or ""),
266
+ created_at=_coerce_float(data.get("created_at")),
267
+ no_executor_started=bool(data.get("no_executor_started", True)),
268
+ draft_assistant_mode=str(data.get("draft_assistant_mode", "") or ""),
269
+ extras=extras,
270
+ )
271
+
272
+ def to_dict(self) -> dict[str, object]:
273
+ out: dict[str, object] = {
274
+ "message_id": self.message_id, "draft_id": self.draft_id,
275
+ "role": self.role, "created_at": self.created_at,
276
+ "no_executor_started": self.no_executor_started,
277
+ "draft_assistant_mode": self.draft_assistant_mode,
278
+ }
279
+ for k, v in self.extras:
280
+ out[k] = v
281
+ return out
282
+
283
+
284
+ @dataclass(frozen=True)
285
+ class PostExecGateContext:
286
+ project_dir: Path
287
+ session_number: int
288
+ task_id: str
289
+ a1_task_id: str
290
+ validation_contract: "ValidationContractProfile"
291
+ forensic_report: "PocketCoderForensicReport"
292
+ runtime_state: RuntimeState
293
+ verification_summary: VerificationSummary
294
+ attempt_id: str = ""
295
+ gate_round: int = 1
296
+ maps: "Optional[Any]" = None
297
+ task_intent: str = ""
298
+ transport_mode: str = ""
299
+ project_mode: str = ""
300
+ original_user_request: str = ""
301
+ structured_handoff: Optional[Any] = None
302
+ self_check_summary: str = ""
303
+ changed_files_reported: tuple[str, ...] = field(default_factory=tuple)
304
+ changed_files_observed: tuple[str, ...] = field(default_factory=tuple)
305
+ touched_files: tuple[str, ...] = field(default_factory=tuple)
306
+ # True = full-project scan (standalone self-audit): clears cross_touched_duplicate
307
+ # so it does not double-count duplicate_scan. False = incremental diff (default).
308
+ is_full_scan: bool = False
309
+ artifact_refs: dict[str, str] = field(default_factory=dict)
310
+ prior_findings: tuple[str, ...] = field(default_factory=tuple)
311
+ tests_touched: tuple[str, ...] = field(default_factory=tuple)
312
+ file_snapshots: dict[str, GateFileSnapshot] = field(default_factory=dict)
313
+ source_package_roots: tuple[str, ...] = field(default_factory=tuple)
314
+ repo_profile: Optional[RepoGateProfile] = None
315
+ plan_artifact: Optional[Any] = None
316
+ execution_pack: Optional[Any] = None
317
+ codex_executor_brief: Optional[Any] = None
318
+ codex_review: Optional[Any] = None
319
+ codex_repair_brief: Optional[Any] = None
320
+ control_task_metadata: dict[str, Any] = field(default_factory=dict)
321
+ draft_metadata: Optional[Any] = None
322
+ mutable_draft_artifact: Optional[Any] = None
323
+ draft_launch_snapshot: Optional[Any] = None
324
+ session_artifacts: dict[str, str] = field(default_factory=dict)
325
+ artifact_load_errors: dict[str, str] = field(default_factory=dict)
326
+ hook_trace_entries: tuple[HookTraceEntry, ...] = field(default_factory=tuple)
327
+ hook_trace_load_provenance: HookTraceLoadProvenance = field(default_factory=HookTraceLoadProvenance)
328
+ draft_messages: tuple[DraftMessageEvidence, ...] = field(default_factory=tuple)
329
+ project_context: Optional[Any] = None
330
+ self_check_findings: tuple[str, ...] = field(default_factory=tuple)
331
+ self_check_parse_status: str = "n/a"
332
+ self_check_passed: Optional[bool] = None
333
+ foc_pre_gate_results: Optional[Mapping[str, object]] = None
334
+
335
+ def to_dict(self) -> dict[str, Any]:
336
+ return {
337
+ "session_number": self.session_number,
338
+ "task_id": self.task_id,
339
+ "a1_task_id": self.a1_task_id,
340
+ "attempt_id": self.attempt_id,
341
+ "gate_round": self.gate_round,
342
+ "task_intent": self.task_intent,
343
+ "transport_mode": self.transport_mode,
344
+ "project_mode": self.project_mode,
345
+ "original_user_request": self.original_user_request,
346
+ "self_check_summary": self.self_check_summary,
347
+ "changed_files_reported": list(self.changed_files_reported),
348
+ "changed_files_observed": list(self.changed_files_observed),
349
+ "touched_files": list(self.touched_files),
350
+ "validation_contract": self.validation_contract.to_dict(),
351
+ "forensic_report": self.forensic_report.to_dict(),
352
+ "runtime_state": self.runtime_state.to_dict(),
353
+ "artifact_refs": self.artifact_refs,
354
+ "verification_summary": self.verification_summary.to_dict(),
355
+ "prior_findings": list(self.prior_findings),
356
+ "tests_touched": list(self.tests_touched),
357
+ "file_snapshots": {k: v.to_dict() for k, v in self.file_snapshots.items()},
358
+ "repo_profile": self.repo_profile.to_dict() if self.repo_profile else {},
359
+ "control_task_metadata": self.control_task_metadata,
360
+ "session_artifacts": dict(self.session_artifacts),
361
+ "artifact_load_errors": dict(self.artifact_load_errors),
362
+ "hook_trace_entries": [entry.to_dict() for entry in self.hook_trace_entries],
363
+ "hook_trace_load_provenance": self.hook_trace_load_provenance.to_dict(),
364
+ "draft_messages": [m.to_dict() for m in self.draft_messages],
365
+ "self_check_findings": list(self.self_check_findings),
366
+ "self_check_parse_status": self.self_check_parse_status,
367
+ "self_check_passed": self.self_check_passed,
368
+ "foc_pre_gate_results": (
369
+ dict(self.foc_pre_gate_results) if self.foc_pre_gate_results is not None else None
370
+ ),
371
+ }
372
+
373
+
374
+ def detect_source_package_roots(project_dir: Path) -> tuple[str, ...]:
375
+ """Auto-detect top-level Python package roots in project_dir."""
376
+ _EXCLUDE = frozenset({
377
+ "__pycache__", ".git", ".venv", "venv", "env", "node_modules",
378
+ "dist", "build", ".tox", ".mypy_cache", ".ruff_cache", ".pytest_cache",
379
+ ".cortex", "libs", "tests", "test",
380
+ })
381
+ roots = []
382
+ try:
383
+ for item in sorted(project_dir.iterdir()):
384
+ if not item.is_dir():
385
+ continue
386
+ if item.name.startswith(".") or item.name in _EXCLUDE:
387
+ continue
388
+ if (item / "__init__.py").exists():
389
+ roots.append(item.name)
390
+ except OSError:
391
+ _log.warning("gate_models: failed to scan project roots in %s", project_dir, exc_info=True)
392
+ return tuple(roots)
@@ -0,0 +1 @@
1
+ # vigil_forensic gate_packs package
@@ -0,0 +1,179 @@
1
+ """Universal gate specifications for vigil_forensic.
2
+
3
+ Adapted from the Vigil autoforensics gate_packs.universal.
4
+ FOC gates (foc_observability_coverage, foc_secret_logging, foc_duplicate_log) are DROPPED.
5
+ All cluster imports rewritten to vigil_forensic.*.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ from typing import Any
10
+
11
+ from vigil_forensic.gate_checks.broad_except_checks import run_broad_except_checks
12
+ from vigil_forensic.gate_checks.embedded_string_checks import run_embedded_string_checks
13
+ from vigil_forensic.gate_checks.duplication_checks import run_duplication_checks
14
+ from vigil_forensic.gate_checks.file_proliferation_checks import run_file_proliferation_checks
15
+ from vigil_forensic.gate_checks.fix_without_test_checks import run_fix_without_test_checks
16
+ from vigil_forensic.gate_checks.empty_output_checks import run_empty_output_checks
17
+ from vigil_forensic.gate_checks.semantic_intent_checks import run_semantic_intent_checks
18
+ from vigil_forensic.gate_checks.temporal_freshness_checks import run_temporal_freshness_checks
19
+ from vigil_forensic.gate_checks.hallucination_checks import run_hallucination_checks
20
+ from vigil_forensic.gate_checks.encoding_checks import run_encoding_checks, run_subprocess_encoding_checks
21
+ from vigil_forensic.gate_checks.authority_checks import run_authority_checks
22
+ from vigil_forensic.gate_checks.runtime_behavior_checks import run_runtime_duplicate_side_effect_checks
23
+ from vigil_forensic.gate_checks.contract_shape_drift_checks import run_contract_shape_drift_checks
24
+ from vigil_forensic.gate_checks.toctou_checks import run_toctou_check_then_act
25
+ from vigil_forensic.gate_checks.atomic_write_checks import run_atomic_write_safety_checks
26
+ from vigil_forensic.gate_checks.context_fallback_checks import run_context_fallback_save_checks
27
+ from vigil_forensic.gate_checks.broad_except_hidden_sentinel_checks import run_broad_except_hidden_sentinel_checks
28
+ from vigil_forensic.gate_checks.god_object_zones_checks import run_god_object_zones_checks
29
+ from vigil_forensic.gate_checks.forensic_cluster_runners import run_forensic_cluster_checks
30
+ from vigil_forensic.gate_checks.project_specific_runner import run_project_specific_checks
31
+ from vigil_forensic.gate_checks.fallback_checks import run_fallback_checks
32
+ from vigil_forensic.gate_checks.config_ssot_checks import run_config_ssot_checks
33
+ from vigil_forensic.gate_checks.performance_checks import run_performance_checks
34
+ from vigil_forensic.gate_checks.size_complexity_checks import run_size_complexity_checks, run_hotspot_inflation_checks
35
+ from vigil_forensic.gate_checks.testing_checks import run_testing_checks
36
+ from vigil_forensic.gate_checks.test_quality_checks import (
37
+ run_empty_test_module_checks,
38
+ run_simulated_test_checks,
39
+ run_test_quality_checks,
40
+ run_test_suite_masking_checks,
41
+ )
42
+ from vigil_forensic.gate_checks.reporting_checks import run_reporting_checks
43
+ from vigil_forensic.gate_checks.syntax_validity_checks import run_syntax_validity_checks
44
+ from vigil_forensic.gate_checks.provider_capability_checks import check_provider_capabilities
45
+ from vigil_forensic.gate_checks.import_integrity_checks import run_import_integrity_checks, run_init_order_regression_checks
46
+ from vigil_forensic.gate_checks.boundary_breach_checks import run_boundary_breach_checks
47
+ from vigil_forensic.gate_checks.conflict_checks import run_conflict_touch_checks
48
+ from vigil_forensic.gate_checks.refactor_completeness_checks import run_refactor_completeness_checks
49
+ from vigil_forensic.gate_checks.type_checking_checks import run_type_checking_checks
50
+ from vigil_forensic.gate_checks.reliability_checks import run_reliability_checks
51
+ from vigil_forensic.gate_checks.security_injection_checks import run_security_injection_checks
52
+ from vigil_forensic.gate_checks.config_safety_checks import run_config_safety_checks
53
+ from vigil_forensic.gate_checks.implementation_overfit_checks import run_implementation_overfit_checks
54
+ from vigil_forensic.gate_checks.stuck_feature_flag_checks import run_stuck_feature_flag_checks
55
+ from vigil_forensic.gate_checks.hunter_artifact_completeness_check import run_hunter_artifact_completeness_checks
56
+ from vigil_forensic.gate_checks.export_completeness_checks import run_export_completeness_checks
57
+ from vigil_forensic.gate_checks.imports_in_function_checks import run_imports_in_function_checks
58
+ from vigil_forensic.gate_checks.ml_checks import run_ml_checks
59
+ from vigil_forensic.meta_findings import meta_runner_stub
60
+ from vigil_forensic._shared import GateCategory
61
+
62
+ # Gate metadata flags — single source of truth for gate classification.
63
+ # FOC gates DROPPED (foc.observability_coverage, foc.secret_logging, foc.duplicate_log).
64
+ GATE_FLAGS: dict[str, frozenset[str]] = {
65
+ "handoff": frozenset({"skip_in_static"}),
66
+ "artifact_completeness": frozenset({"skip_in_static"}),
67
+ "semantic_intent": frozenset({"skip_in_static"}),
68
+ # forensic_clusters is NOT skip_in_static: the pack runs in static mode but
69
+ # filters out its runtime-only sub-checks (see
70
+ # forensic_cluster_runners.core._RUNTIME_ONLY_CLUSTERS / _is_static_mode), so
71
+ # the static-safe checks (security, secrets, mutable defaults, resource
72
+ # leaks, dead code, hardcoded paths, …) still fire without runtime FPs.
73
+ "forensic_clusters": frozenset(),
74
+ "pipeline_chain": frozenset({"skip_in_static"}),
75
+ "testing": frozenset({"skip_in_static"}),
76
+ "fix_without_test": frozenset({"skip_in_static"}),
77
+ "truth_boundary": frozenset({"skip_in_static"}),
78
+ "pe_health": frozenset({"skip_in_static"}),
79
+ "hallucination": frozenset({"skip_in_static"}),
80
+ "empty_output": frozenset({"skip_in_static"}),
81
+ "reporting": frozenset({"skip_in_static"}),
82
+ "temporal_freshness": frozenset({"skip_in_static"}),
83
+ "provider_capability": frozenset({"skip_in_static"}),
84
+ "tool_hook_coverage": frozenset({"skip_in_static"}),
85
+ "policy_boundary": frozenset({"skip_in_static"}),
86
+ "draft_boundary": frozenset({"skip_in_static"}),
87
+ "authority_checks": frozenset({"requires_git"}),
88
+ "contract_shape_drift": frozenset({"requires_git"}),
89
+ "init_order_regression": frozenset({"requires_git"}),
90
+ "stuck_feature_flag": frozenset(),
91
+ "hunter_artifact_completeness": frozenset({"skip_in_static"}),
92
+ "size_complexity": frozenset({"agnostic"}),
93
+ "duplication": frozenset({"agnostic"}),
94
+ "file_proliferation": frozenset({"agnostic"}),
95
+ "syntax_validity": frozenset({"agnostic"}),
96
+ }
97
+
98
+ GATE_SPECS: tuple[tuple[str, GateCategory, Any], ...] = (
99
+ # broad_except family
100
+ ("broad_except", GateCategory.FALLBACK, run_broad_except_checks),
101
+ ("broad_except.bare", GateCategory.FALLBACK, run_broad_except_checks),
102
+ ("broad_except.base_exception", GateCategory.FALLBACK, run_broad_except_checks),
103
+ ("broad_except.return_none", GateCategory.FALLBACK, run_broad_except_checks),
104
+ ("broad_except.log_swallow", GateCategory.FALLBACK, run_broad_except_checks),
105
+ ("broad_except.hidden_sentinel", GateCategory.CONTRACT, run_broad_except_hidden_sentinel_checks),
106
+ # embedded string
107
+ ("embedded_string", GateCategory.FALLBACK, run_embedded_string_checks),
108
+ # duplication
109
+ ("duplication", GateCategory.DUPLICATION, run_duplication_checks),
110
+ ("file_proliferation", GateCategory.DUPLICATION, run_file_proliferation_checks),
111
+ # testing
112
+ ("fix_without_test", GateCategory.TESTING, run_fix_without_test_checks),
113
+ # reporting
114
+ ("empty_output", GateCategory.REPORTING, run_empty_output_checks),
115
+ # semantic / temporal
116
+ ("semantic_intent", GateCategory.SEMANTIC_INTENT, run_semantic_intent_checks),
117
+ ("temporal_freshness", GateCategory.TEMPORAL_FRESHNESS, run_temporal_freshness_checks),
118
+ # contract
119
+ ("hallucination", GateCategory.CONTRACT, run_hallucination_checks),
120
+ # runtime behavior
121
+ ("encoding_safety", GateCategory.RUNTIME_BEHAVIOR, run_encoding_checks),
122
+ ("subprocess_encoding", GateCategory.RUNTIME_BEHAVIOR, run_subprocess_encoding_checks),
123
+ ("authority_checks", GateCategory.CONTRACT, run_authority_checks),
124
+ ("runtime_duplicate_side_effect", GateCategory.RUNTIME_BEHAVIOR, run_runtime_duplicate_side_effect_checks),
125
+ ("toctou_check_then_act", GateCategory.RUNTIME_BEHAVIOR, run_toctou_check_then_act),
126
+ ("atomic_write_safety", GateCategory.DRIFT, run_atomic_write_safety_checks),
127
+ ("context_fallback_save", GateCategory.CONTRACT, run_context_fallback_save_checks),
128
+ # drift
129
+ ("contract_shape_drift", GateCategory.DRIFT, run_contract_shape_drift_checks),
130
+ # object zones
131
+ ("god_object_zones", GateCategory.DRIFT, run_god_object_zones_checks),
132
+ # cluster framework runner
133
+ ("forensic_clusters", GateCategory.CONTRACT, run_forensic_cluster_checks),
134
+ # dynamic gate loader
135
+ ("project_specific", GateCategory.CONTRACT, run_project_specific_checks),
136
+ # profile-driven gates
137
+ ("fallback", GateCategory.FALLBACK, run_fallback_checks),
138
+ ("config_ssot", GateCategory.CONFIG_SSOT, run_config_ssot_checks),
139
+ ("performance", GateCategory.PERFORMANCE, run_performance_checks),
140
+ ("size_complexity", GateCategory.SIZE_COMPLEXITY, run_size_complexity_checks),
141
+ ("testing", GateCategory.TESTING, run_testing_checks),
142
+ ("test_quality", GateCategory.TESTING, run_test_quality_checks),
143
+ ("test_suite_masking", GateCategory.TESTING, run_test_suite_masking_checks),
144
+ ("empty_test_module", GateCategory.TESTING, run_empty_test_module_checks),
145
+ ("simulated_instead_of_executed_test", GateCategory.TESTING, run_simulated_test_checks),
146
+ ("reporting", GateCategory.REPORTING, run_reporting_checks),
147
+ ("syntax_validity", GateCategory.REPORTING, run_syntax_validity_checks),
148
+ ("provider_capability", GateCategory.CONTRACT, check_provider_capabilities),
149
+ ("import_integrity", GateCategory.CONTRACT, run_import_integrity_checks),
150
+ ("init_order_regression", GateCategory.CONTRACT, run_init_order_regression_checks),
151
+ ("boundary_breach", GateCategory.CONTRACT, run_boundary_breach_checks),
152
+ ("conflict_touch", GateCategory.CONTRACT, run_conflict_touch_checks),
153
+ ("hotspot_inflation", GateCategory.SIZE_COMPLEXITY, run_hotspot_inflation_checks),
154
+ ("refactor_completeness", GateCategory.DRIFT, run_refactor_completeness_checks),
155
+ ("type_checking", GateCategory.CONTRACT, run_type_checking_checks),
156
+ ("reliability", GateCategory.RUNTIME_BEHAVIOR, run_reliability_checks),
157
+ ("security_injection", GateCategory.CONTRACT, run_security_injection_checks),
158
+ ("config_safety", GateCategory.CONFIG_SSOT, run_config_safety_checks),
159
+ ("implementation_overfit", GateCategory.DRIFT, run_implementation_overfit_checks),
160
+ ("stuck_feature_flag", GateCategory.DRIFT, run_stuck_feature_flag_checks),
161
+ ("hunter_artifact_completeness", GateCategory.META, run_hunter_artifact_completeness_checks),
162
+ ("export_completeness", GateCategory.CONTRACT, run_export_completeness_checks),
163
+ ("imports_in_function", GateCategory.DRIFT, run_imports_in_function_checks),
164
+ ("imports_in_function.stdlib", GateCategory.DRIFT, run_imports_in_function_checks),
165
+ # ML/NN correctness pack (static AST; look-ahead, leakage, seed)
166
+ ("ml_checks", GateCategory.ML, run_ml_checks),
167
+ ("ml.lookahead_negative_shift", GateCategory.ML, run_ml_checks),
168
+ ("ml.nondeterministic_split", GateCategory.ML, run_ml_checks),
169
+ ("ml.scaler_fit_on_test", GateCategory.ML, run_ml_checks),
170
+ ("ml.missing_random_seed", GateCategory.ML, run_ml_checks),
171
+ # meta stubs (FOC gates removed)
172
+ ("meta.syntax_parse_error", GateCategory.META, meta_runner_stub),
173
+ ("meta.profile_load_failed", GateCategory.META, meta_runner_stub),
174
+ ("meta.git_unavailable", GateCategory.META, meta_runner_stub),
175
+ ("meta.artifact_corrupted", GateCategory.META, meta_runner_stub),
176
+ ("meta.artifact_unreadable", GateCategory.META, meta_runner_stub),
177
+ ("meta.file_unreadable", GateCategory.META, meta_runner_stub),
178
+ ("meta.allowlist_corrupted", GateCategory.META, meta_runner_stub),
179
+ )
@@ -0,0 +1,31 @@
1
+ {
2
+ "profile_name": "vigil-default",
3
+ "version": "1.0",
4
+ "_doc": "Default forensic gate profile. Size/complexity thresholds use industry-standard linter defaults to silence size-noise false-positives on legitimately large files. JSON forbids comments; the cited justification for every value lives in README.md ('Default gate profile' section). To override for your own repo, copy this file to <your-project>/gate_profile.json (or <your-project>/.cortex/gate_profile.json) and edit size_thresholds.",
5
+ "size_thresholds": {
6
+ "file_warn": 750,
7
+ "file_revise": 1000,
8
+ "function_warn": 100,
9
+ "function_revise": 150,
10
+ "nesting_warn": 5,
11
+ "nesting_revise": 8
12
+ },
13
+ "generated_roots": [
14
+ ".git",
15
+ "__pycache__",
16
+ ".pytest_cache",
17
+ ".mypy_cache",
18
+ ".ruff_cache",
19
+ "dist",
20
+ "build",
21
+ "node_modules",
22
+ "venv",
23
+ ".venv",
24
+ ".cortex"
25
+ ],
26
+ "vendored_roots": [
27
+ ".vendor",
28
+ "vendor",
29
+ "node_modules"
30
+ ]
31
+ }
@@ -0,0 +1,21 @@
1
+ """Gate registry for vigil_forensic.
2
+
3
+ Adapted from the Vigil autoforensics gate_registry.
4
+ """
5
+ from __future__ import annotations
6
+
7
+ from vigil_forensic.gate_packs.universal import GATE_SPECS as _UNIVERSAL_SPECS
8
+ import logging
9
+ _log = logging.getLogger(__name__)
10
+
11
+ _u = {check_id: (cat, runner) for check_id, cat, runner in _UNIVERSAL_SPECS}
12
+
13
+
14
+ def _u_entry(check_id: str) -> tuple:
15
+ cat, runner = _u[check_id]
16
+ return (check_id, cat, runner)
17
+
18
+
19
+ DEFAULT_GATE_CHECKS: tuple[tuple, ...] = tuple(
20
+ _u_entry(spec[0]) for spec in _UNIVERSAL_SPECS
21
+ )