fable-engine 1.3.4__tar.gz → 1.3.6__tar.gz

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 (166) hide show
  1. {fable_engine-1.3.4/fable_engine.egg-info → fable_engine-1.3.6}/PKG-INFO +53 -14
  2. {fable_engine-1.3.4 → fable_engine-1.3.6}/README.md +52 -13
  3. fable_engine-1.3.6/docs/ai-evidence-adjudicator.md +119 -0
  4. fable_engine-1.3.6/docs/stop-ai-agents-writing-too-early.md +139 -0
  5. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/actions/__init__.py +4 -0
  6. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/actions/deliberation.py +48 -0
  7. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/actions/fleet.py +32 -9
  8. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/actions/lifecycle.py +14 -1
  9. fable_engine-1.3.6/fable_engine/adjudicator.py +509 -0
  10. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/fable_session.json +130 -33
  11. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/schema.py +68 -15
  12. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/scrapers/base.py +1 -1
  13. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/server.py +3 -1
  14. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/session.py +39 -2
  15. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/test_server.py +14 -0
  16. {fable_engine-1.3.4 → fable_engine-1.3.6/fable_engine.egg-info}/PKG-INFO +53 -14
  17. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine.egg-info/SOURCES.txt +6 -0
  18. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_mode/__init__.py +1 -1
  19. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_mode/manifest.py +1 -0
  20. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_mode/resources.json +1 -0
  21. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/coder_fleet/design_engine.py +153 -109
  22. fable_engine-1.3.6/fable_v2/coder_fleet/sandbox_executor.py +314 -0
  23. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/cortical/plasticity_engine.py +46 -7
  24. {fable_engine-1.3.4 → fable_engine-1.3.6}/pyproject.toml +1 -1
  25. {fable_engine-1.3.4 → fable_engine-1.3.6}/rules/AGENTS.md +1 -1
  26. {fable_engine-1.3.4 → fable_engine-1.3.6}/rules/fable-mode.md +1 -1
  27. {fable_engine-1.3.4 → fable_engine-1.3.6}/setup.py +1 -1
  28. fable_engine-1.3.6/skills/fable-mode/SKILL.md +131 -0
  29. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/cortex/frontend_design.md +28 -109
  30. fable_engine-1.3.6/skills/fable-mode/references/design-system.md +102 -0
  31. fable_engine-1.3.6/tests/test_adjudicator.py +358 -0
  32. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_design_engine.py +22 -6
  33. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_hebbian_plasticity.py +4 -1
  34. fable_engine-1.3.6/tests/test_red_team_seal_path.py +297 -0
  35. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_red_team_swarm.py +30 -14
  36. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_stealth_browser.py +20 -0
  37. fable_engine-1.3.4/docs/stop-ai-agents-writing-too-early.md +0 -80
  38. fable_engine-1.3.4/skills/fable-mode/SKILL.md +0 -142
  39. {fable_engine-1.3.4 → fable_engine-1.3.6}/LICENSE +0 -0
  40. {fable_engine-1.3.4 → fable_engine-1.3.6}/MANIFEST.in +0 -0
  41. {fable_engine-1.3.4 → fable_engine-1.3.6}/docs/fable-v1-v2-migration.md +0 -0
  42. {fable_engine-1.3.4 → fable_engine-1.3.6}/docs/fable-v2-architecture.md +0 -0
  43. {fable_engine-1.3.4 → fable_engine-1.3.6}/docs/system3-architecture.md +0 -0
  44. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_compressor.py +0 -0
  45. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/__init__.py +0 -0
  46. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/actions/cas.py +0 -0
  47. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/actions/scrapers.py +0 -0
  48. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/actions/system3.py +0 -0
  49. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/browser.py +0 -0
  50. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/cas.py +0 -0
  51. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/guards.py +0 -0
  52. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/scrapers/__init__.py +0 -0
  53. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/scrapers/arxiv.py +0 -0
  54. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/scrapers/github.py +0 -0
  55. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/scrapers/reddit.py +0 -0
  56. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/scrapers/web.py +0 -0
  57. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/scrapers/x.py +0 -0
  58. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/scrapers/youtube.py +0 -0
  59. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine/updater.py +0 -0
  60. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine.egg-info/dependency_links.txt +0 -0
  61. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine.egg-info/entry_points.txt +0 -0
  62. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_engine.egg-info/top_level.txt +0 -0
  63. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_mode/__main__.py +0 -0
  64. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_mode/adapters.py +0 -0
  65. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_mode/installer.py +0 -0
  66. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_mode/launcher.py +0 -0
  67. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_mode/safety.py +0 -0
  68. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_mode/skill_bundle.py +0 -0
  69. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_mode_entry.py +0 -0
  70. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/__init__.py +0 -0
  71. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/adapters.py +0 -0
  72. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/coder_fleet/__init__.py +0 -0
  73. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/coder_fleet/ast_tools.py +0 -0
  74. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/coder_fleet/compute.py +0 -0
  75. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/coder_fleet/diagnostics.py +0 -0
  76. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/coder_fleet/fleet_dispatcher.py +0 -0
  77. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/coder_fleet/mock_auditor.py +0 -0
  78. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/coder_fleet/mutation.py +0 -0
  79. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/coder_fleet/property_oracle.py +0 -0
  80. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/coder_fleet/receipt_attestor.py +0 -0
  81. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/coder_fleet/red_team_swarm.py +0 -0
  82. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/coder_fleet/test_harness.py +0 -0
  83. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/coder_fleet/vector_engine.py +0 -0
  84. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/coder_fleet/visual.py +0 -0
  85. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/coder_fleet/workspace.py +0 -0
  86. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/cortical/__init__.py +0 -0
  87. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/execution_broker.py +0 -0
  88. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/proof_engine.py +0 -0
  89. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/protocol.py +0 -0
  90. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/runtime.py +0 -0
  91. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/system3/__init__.py +0 -0
  92. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/system3/causal.py +0 -0
  93. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/system3/dialectical.py +0 -0
  94. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/system3/evolution.py +0 -0
  95. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/system3/executive.py +0 -0
  96. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/system3/free_energy.py +0 -0
  97. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/system3/hyperbolic.py +0 -0
  98. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/system3/induction.py +0 -0
  99. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/system3/kripke.py +0 -0
  100. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/system3/oracle.py +0 -0
  101. {fable_engine-1.3.4 → fable_engine-1.3.6}/fable_v2/verifiers.py +0 -0
  102. {fable_engine-1.3.4 → fable_engine-1.3.6}/rules/GEMINI.md +0 -0
  103. {fable_engine-1.3.4 → fable_engine-1.3.6}/setup.cfg +0 -0
  104. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/cortex/concurrency.md +0 -0
  105. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/cortex/design_3d.md +0 -0
  106. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/cortex/process.md +0 -0
  107. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/cortex/python.md +0 -0
  108. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/cortex/research.md +0 -0
  109. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/cortex/rust.md +0 -0
  110. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/cortex/security.md +0 -0
  111. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/cortex/synaptic_matrix.json +0 -0
  112. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/cortex/system.md +0 -0
  113. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/cortex/target.md +0 -0
  114. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/examples/autonomous-agentic-migration.md +0 -0
  115. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/examples/breakthrough-algorithm-synthesis.md +0 -0
  116. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/examples/deepthink-analysis-proof.md +0 -0
  117. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/examples/distributed-system-design.md +0 -0
  118. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/examples/swe-bench-pro-debugging.md +0 -0
  119. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/examples/weak_model_ollama_setup.md +0 -0
  120. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/aaa-threejs-game-engine.md +0 -0
  121. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/adversarial-code-review-swarm.md +0 -0
  122. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/agentic-execution.md +0 -0
  123. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/anti-slop-frontend-architecture.md +0 -0
  124. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/architectural-blueprinting.md +0 -0
  125. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/cinematic-design-engine.md +0 -0
  126. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/cognitive-protocol.md +0 -0
  127. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/deepthink-mode.md +0 -0
  128. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/design-tokens-and-typographies.md +0 -0
  129. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/goal-rubric-and-pipeline-automation.md +0 -0
  130. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/hebbian-cortical-plasticity.md +0 -0
  131. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/innovation-engine.md +0 -0
  132. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/interleaved-verification.md +0 -0
  133. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/model-velocity-calibration.md +0 -0
  134. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/prompt-scaffolds.md +0 -0
  135. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/proof-architecture.md +0 -0
  136. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/svg-craft-and-vector-design.md +0 -0
  137. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/system2-session-engine.md +0 -0
  138. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/system3-meta-cognition.md +0 -0
  139. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/visual-imagination-engine.md +0 -0
  140. {fable_engine-1.3.4 → fable_engine-1.3.6}/skills/fable-mode/references/weak-model-frontier-uplift.md +0 -0
  141. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/__init__.py +0 -0
  142. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_anti_loop_circuit_breaker.py +0 -0
  143. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_auto_updater.py +0 -0
  144. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_coder_fleet.py +0 -0
  145. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_delegation_compiler.py +0 -0
  146. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_descriptor_boundaries.py +0 -0
  147. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_epistemic_evidence_validator.py +0 -0
  148. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_execution_broker.py +0 -0
  149. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_fable_v2.py +0 -0
  150. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_fleet_transitions.py +0 -0
  151. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_fsm_redteam_evolution.py +0 -0
  152. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_goal_rubric_and_pipeline.py +0 -0
  153. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_packaging_runtime.py +0 -0
  154. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_proof_engine.py +0 -0
  155. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_redteam_remediation.py +0 -0
  156. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_registration_transaction.py +0 -0
  157. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_requested_regressions.py +0 -0
  158. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_scrapers.py +0 -0
  159. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_server_actions.py +0 -0
  160. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_server_frontier_actions.py +0 -0
  161. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_server_protocol.py +0 -0
  162. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_skill_distribution.py +0 -0
  163. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_system3.py +0 -0
  164. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_system3_deep_integration.py +0 -0
  165. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_system3_frontier.py +0 -0
  166. {fable_engine-1.3.4 → fable_engine-1.3.6}/tests/test_vector_engine.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: fable-engine
3
- Version: 1.3.4
3
+ Version: 1.3.6
4
4
  Summary: Independent deterministic System 2 cognitive engine and mechanical time-lock MCP server
5
5
  Author: REX-codebase
6
6
  License: MIT License
@@ -85,24 +85,49 @@ mechanical, not prompt advice: no timer, no proof, no write access.
85
85
  <img src="./assets/flow-simple.svg" width="720" alt="Think → Prove → Attack → Write"/>
86
86
  </div>
87
87
 
88
+ ### Demo
89
+
90
+ **KERR // ORRERY**
91
+
92
+ One self-contained HTML file. Raw WebGL, zero libraries, zero external assets,
93
+ and zero build step.
94
+
95
+ https://github.com/user-attachments/assets/8287bbfe-e3ee-4dcf-ba0f-f9ff22ae79bd
96
+
97
+ <sub>7 renders rejected before final · 2 bugs caught · 10/10 red-team probes passed</sub>
98
+
99
+ <br/>
100
+
101
+ **Fable Mode overview**
102
+
88
103
  https://github.com/user-attachments/assets/27f4f8a2-b1bb-4398-a08c-bc9fd93d69d7
89
104
 
90
105
  <br/>
91
106
 
92
- ### See it work
107
+ ### Quick start
93
108
 
94
109
  A session starts locked. Confidence does not unlock it.
95
110
 
96
- ```text
97
- >>> session = create_session('demo-refactor', budget='2 min')
98
- state=INIT execution_locked=True can_execute_code=False
111
+ 1. Install the MCP server using one of the options below.
112
+ 2. Add the optional Agent Skill if you want the full workflow.
113
+ 3. Ask your agent to use Fable Mode for a concrete coding task and choose a time budget.
99
114
 
100
- >>> session.unlock_execution('the plan looks fine, let me write code now')
101
- PermissionError: HARD TIME-LOCK VIOLATION: Execution unlock rejected!
102
- The immutable 2.0m authority budget has not elapsed yet
103
- (Remaining: 1m 59s / 120.0s).
115
+ A new session starts with execution locked:
116
+
117
+ ```json
118
+ {
119
+ "action": "create_session",
120
+ "session_name": "demo-refactor",
121
+ "objective": "Refactor the parser without changing public behavior",
122
+ "time_budget_minutes": 2
123
+ }
104
124
  ```
105
125
 
126
+ The agent then records evidence and an invariant. An early `unlock_execution`
127
+ request is rejected until the authority timer and proof prerequisites pass.
128
+ Use `get_status` at any point to see the active phase, remaining time, evidence
129
+ counts, and lock state.
130
+
106
131
  The same gates guard every phase: evidence receipts for claims, a five-vector
107
132
  red-team swarm for code, and a sealed record of what was verified.
108
133
 
@@ -116,7 +141,7 @@ pip install fable-engine
116
141
 
117
142
  Or install the MCP server in your editor:
118
143
 
119
- [![Install MCP server in VS Code](https://img.shields.io/badge/VS_Code-Install_MCP_server-007ACC?logo=visualstudiocode&logoColor=white)](vscode:mcp/install?%7B%22name%22%3A%22fable-engine%22%2C%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22--from%22%2C%22fable-engine%3D%3D1.3.4%22%2C%22fable-engine%22%5D%7D)
144
+ [![Install MCP server in VS Code](https://img.shields.io/badge/VS_Code-Install_MCP_server-007ACC?logo=visualstudiocode&logoColor=white)](vscode:mcp/install?%7B%22name%22%3A%22fable-engine%22%2C%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22--from%22%2C%22fable-engine%3D%3D1.3.6%22%2C%22fable-engine%22%5D%7D)
120
145
  [![Add to Cursor](https://img.shields.io/badge/Cursor-Add_MCP_server-black)](cursor://anysphere.cursor-deeplink/mcp/install?name=fable-engine&config=eyJjb21tYW5kIjoidXZ4IiwiYXJncyI6WyItLWZyb20iLCJmYWJsZS1lbmdpbmU9PTEuMy4zIiwiZmFibGUtZW5naW5lIl19)
121
146
 
122
147
  These links configure Fable Engine for AI agents in VS Code Chat or Cursor. They do not install a standalone editor extension. Both use `uvx`, which downloads and runs the pinned PyPI release in an isolated environment.
@@ -124,13 +149,13 @@ These links configure Fable Engine for AI agents in VS Code Chat or Cursor. They
124
149
  Point your agent at the MCP server manually:
125
150
 
126
151
  ```jsonc
127
- // Claude Code: claude mcp add fable-engine -- uvx --from fable-engine==1.3.4 fable-engine
152
+ // Claude Code: claude mcp add fable-engine -- uvx --from fable-engine==1.3.6 fable-engine
128
153
  // Cursor: ~/.cursor/mcp.json
129
154
  {
130
155
  "mcpServers": {
131
156
  "fable-engine": {
132
157
  "command": "uvx",
133
- "args": ["--from", "fable-engine==1.3.4", "fable-engine"]
158
+ "args": ["--from", "fable-engine==1.3.6", "fable-engine"]
134
159
  }
135
160
  }
136
161
  }
@@ -152,7 +177,7 @@ The complete skill tree ships inside the wheel. To install it into your
152
177
  project's skills directory (the cross-client `.agents/skills/` convention):
153
178
 
154
179
  ```bash
155
- uvx --from fable-engine==1.3.4 fable-mode install-skill --yes
180
+ uvx --from fable-engine==1.3.6 fable-mode install-skill --yes
156
181
  ```
157
182
 
158
183
  This copies the skill to `.agents/skills/fable-mode`. Preview first with
@@ -170,6 +195,18 @@ agent afterwards so it picks up the skill.
170
195
 
171
196
  <br/>
172
197
 
198
+ ### Optional: AI evidence adjudicator
199
+
200
+ The evidence in a session is written by an AI agent, so Fable can optionally
201
+ ask an external reviewer model to audit that evidence before the workspace
202
+ unlocks. Stdlib-only, one bounded HTTPS call, no local model, no extra RAM to
203
+ speak of. Off by default; fail-closed when enforcing. It raises the cost of
204
+ fabricated proof - it cannot guarantee deception is impossible, and the
205
+ mechanical gates stay the primary authority. Setup and honest limits:
206
+ [AI evidence adjudicator](./docs/ai-evidence-adjudicator.md).
207
+
208
+ <br/>
209
+
173
210
  ### What it is not
174
211
 
175
212
  - Not a claim of flawless code. It is a checkable workflow, not a guarantee.
@@ -180,10 +217,12 @@ agent afterwards so it picks up the skill.
180
217
 
181
218
  ### Docs
182
219
 
220
+ - [Start here: practical guide](./docs/stop-ai-agents-writing-too-early.md)
221
+ - [Agent Skill reference](./skills/fable-mode/SKILL.md)
183
222
  - [V1 → V2 migration](./docs/fable-v1-v2-migration.md)
184
223
  - [V2 architecture](./docs/fable-v2-architecture.md)
185
224
  - [System 3 (experimental)](./docs/system3-architecture.md)
186
- - [Stop AI coding agents from writing too early](./docs/stop-ai-agents-writing-too-early.md)
225
+ - [AI evidence adjudicator (optional)](./docs/ai-evidence-adjudicator.md)
187
226
 
188
227
  <br/>
189
228
 
@@ -42,24 +42,49 @@ mechanical, not prompt advice: no timer, no proof, no write access.
42
42
  <img src="./assets/flow-simple.svg" width="720" alt="Think → Prove → Attack → Write"/>
43
43
  </div>
44
44
 
45
+ ### Demo
46
+
47
+ **KERR // ORRERY**
48
+
49
+ One self-contained HTML file. Raw WebGL, zero libraries, zero external assets,
50
+ and zero build step.
51
+
52
+ https://github.com/user-attachments/assets/8287bbfe-e3ee-4dcf-ba0f-f9ff22ae79bd
53
+
54
+ <sub>7 renders rejected before final · 2 bugs caught · 10/10 red-team probes passed</sub>
55
+
56
+ <br/>
57
+
58
+ **Fable Mode overview**
59
+
45
60
  https://github.com/user-attachments/assets/27f4f8a2-b1bb-4398-a08c-bc9fd93d69d7
46
61
 
47
62
  <br/>
48
63
 
49
- ### See it work
64
+ ### Quick start
50
65
 
51
66
  A session starts locked. Confidence does not unlock it.
52
67
 
53
- ```text
54
- >>> session = create_session('demo-refactor', budget='2 min')
55
- state=INIT execution_locked=True can_execute_code=False
68
+ 1. Install the MCP server using one of the options below.
69
+ 2. Add the optional Agent Skill if you want the full workflow.
70
+ 3. Ask your agent to use Fable Mode for a concrete coding task and choose a time budget.
56
71
 
57
- >>> session.unlock_execution('the plan looks fine, let me write code now')
58
- PermissionError: HARD TIME-LOCK VIOLATION: Execution unlock rejected!
59
- The immutable 2.0m authority budget has not elapsed yet
60
- (Remaining: 1m 59s / 120.0s).
72
+ A new session starts with execution locked:
73
+
74
+ ```json
75
+ {
76
+ "action": "create_session",
77
+ "session_name": "demo-refactor",
78
+ "objective": "Refactor the parser without changing public behavior",
79
+ "time_budget_minutes": 2
80
+ }
61
81
  ```
62
82
 
83
+ The agent then records evidence and an invariant. An early `unlock_execution`
84
+ request is rejected until the authority timer and proof prerequisites pass.
85
+ Use `get_status` at any point to see the active phase, remaining time, evidence
86
+ counts, and lock state.
87
+
63
88
  The same gates guard every phase: evidence receipts for claims, a five-vector
64
89
  red-team swarm for code, and a sealed record of what was verified.
65
90
 
@@ -73,7 +98,7 @@ pip install fable-engine
73
98
 
74
99
  Or install the MCP server in your editor:
75
100
 
76
- [![Install MCP server in VS Code](https://img.shields.io/badge/VS_Code-Install_MCP_server-007ACC?logo=visualstudiocode&logoColor=white)](vscode:mcp/install?%7B%22name%22%3A%22fable-engine%22%2C%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22--from%22%2C%22fable-engine%3D%3D1.3.4%22%2C%22fable-engine%22%5D%7D)
101
+ [![Install MCP server in VS Code](https://img.shields.io/badge/VS_Code-Install_MCP_server-007ACC?logo=visualstudiocode&logoColor=white)](vscode:mcp/install?%7B%22name%22%3A%22fable-engine%22%2C%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22--from%22%2C%22fable-engine%3D%3D1.3.6%22%2C%22fable-engine%22%5D%7D)
77
102
  [![Add to Cursor](https://img.shields.io/badge/Cursor-Add_MCP_server-black)](cursor://anysphere.cursor-deeplink/mcp/install?name=fable-engine&config=eyJjb21tYW5kIjoidXZ4IiwiYXJncyI6WyItLWZyb20iLCJmYWJsZS1lbmdpbmU9PTEuMy4zIiwiZmFibGUtZW5naW5lIl19)
78
103
 
79
104
  These links configure Fable Engine for AI agents in VS Code Chat or Cursor. They do not install a standalone editor extension. Both use `uvx`, which downloads and runs the pinned PyPI release in an isolated environment.
@@ -81,13 +106,13 @@ These links configure Fable Engine for AI agents in VS Code Chat or Cursor. They
81
106
  Point your agent at the MCP server manually:
82
107
 
83
108
  ```jsonc
84
- // Claude Code: claude mcp add fable-engine -- uvx --from fable-engine==1.3.4 fable-engine
109
+ // Claude Code: claude mcp add fable-engine -- uvx --from fable-engine==1.3.6 fable-engine
85
110
  // Cursor: ~/.cursor/mcp.json
86
111
  {
87
112
  "mcpServers": {
88
113
  "fable-engine": {
89
114
  "command": "uvx",
90
- "args": ["--from", "fable-engine==1.3.4", "fable-engine"]
115
+ "args": ["--from", "fable-engine==1.3.6", "fable-engine"]
91
116
  }
92
117
  }
93
118
  }
@@ -109,7 +134,7 @@ The complete skill tree ships inside the wheel. To install it into your
109
134
  project's skills directory (the cross-client `.agents/skills/` convention):
110
135
 
111
136
  ```bash
112
- uvx --from fable-engine==1.3.4 fable-mode install-skill --yes
137
+ uvx --from fable-engine==1.3.6 fable-mode install-skill --yes
113
138
  ```
114
139
 
115
140
  This copies the skill to `.agents/skills/fable-mode`. Preview first with
@@ -127,6 +152,18 @@ agent afterwards so it picks up the skill.
127
152
 
128
153
  <br/>
129
154
 
155
+ ### Optional: AI evidence adjudicator
156
+
157
+ The evidence in a session is written by an AI agent, so Fable can optionally
158
+ ask an external reviewer model to audit that evidence before the workspace
159
+ unlocks. Stdlib-only, one bounded HTTPS call, no local model, no extra RAM to
160
+ speak of. Off by default; fail-closed when enforcing. It raises the cost of
161
+ fabricated proof - it cannot guarantee deception is impossible, and the
162
+ mechanical gates stay the primary authority. Setup and honest limits:
163
+ [AI evidence adjudicator](./docs/ai-evidence-adjudicator.md).
164
+
165
+ <br/>
166
+
130
167
  ### What it is not
131
168
 
132
169
  - Not a claim of flawless code. It is a checkable workflow, not a guarantee.
@@ -137,10 +174,12 @@ agent afterwards so it picks up the skill.
137
174
 
138
175
  ### Docs
139
176
 
177
+ - [Start here: practical guide](./docs/stop-ai-agents-writing-too-early.md)
178
+ - [Agent Skill reference](./skills/fable-mode/SKILL.md)
140
179
  - [V1 → V2 migration](./docs/fable-v1-v2-migration.md)
141
180
  - [V2 architecture](./docs/fable-v2-architecture.md)
142
181
  - [System 3 (experimental)](./docs/system3-architecture.md)
143
- - [Stop AI coding agents from writing too early](./docs/stop-ai-agents-writing-too-early.md)
182
+ - [AI evidence adjudicator (optional)](./docs/ai-evidence-adjudicator.md)
144
183
 
145
184
  <br/>
146
185
 
@@ -0,0 +1,119 @@
1
+ # AI Evidence Adjudicator (optional)
2
+
3
+ An external reviewer model that audits a session's recorded evidence before
4
+ execution unlocks. It exists because the evidence in a Fable session is itself
5
+ written by an AI agent, and an AI agent can fabricate plausible-looking proof.
6
+
7
+ The adjudicator is a second opinion, not a guarantee. See
8
+ [Honest limits](#honest-limits) before relying on it.
9
+
10
+ ## What it does
11
+
12
+ Two layers, code first:
13
+
14
+ 1. **Deterministic evidence lint** (always local, stdlib, zero network, zero
15
+ extra RAM): flags fabrication-shaped patterns by rule - placeholder text
16
+ (`lorem ipsum`, `TBD`, `TODO`), generic success claims with no artifact
17
+ ("it works", "all tests passed"), evidence that restates the claim
18
+ word-for-word (circular), the same evidence recycled across claims, empty
19
+ evidence, failed proof receipts, and padded refinement cycles.
20
+ 2. **External reviewer model** (optional, needs an API key): the engine
21
+ bundles the session's evidence into a bounded JSON snapshot and sends it,
22
+ clearly marked as untrusted data, to an external LLM API. The lint's
23
+ findings travel with it as engine-computed ground truth. The model's reply
24
+ is strictly parsed into `pass`, `fail`, or `uncertain`.
25
+
26
+ Flow at `unlock_execution`, after the mechanical gates pass:
27
+
28
+ - The lint runs always. A critical lint finding is a `fail` verdict on its
29
+ own - deterministic findings outrank any model output.
30
+ - Without an API key, the lint alone is the verdict (the receipt records
31
+ `llm_status: skipped_no_api_key`). With a key, the model review runs too,
32
+ and its reply is merged with the lint findings.
33
+ - A receipt (verdict, issues, lint summary, bundle SHA-256, latency) is
34
+ recorded in the session's proof receipts. The API key and full prompt are
35
+ never stored.
36
+ - In `enforcing` mode, anything other than `pass` blocks the unlock.
37
+ In `advisory` mode (default), the receipt is recorded but never blocks.
38
+
39
+ You can also request a review at any time with the `adjudicate_evidence`
40
+ action of `fable_session`.
41
+
42
+ ## Resource profile
43
+
44
+ - Stdlib only. No SDK, no embedded model, no GPU.
45
+ - RAM overhead is one JSON payload capped at 24 KB plus the HTTP response.
46
+ - One HTTPS request per adjudication, default 15 s timeout (clamped 3-60 s).
47
+ - Disabled by default: zero network calls and zero behavior change.
48
+ - Enforcing mode works fully offline: the deterministic lint is the gate,
49
+ the external reviewer only deepens it.
50
+
51
+ ## Setup
52
+
53
+ ```bash
54
+ export FABLE_ADJUDICATOR_ENABLED=1
55
+ export FABLE_ADJUDICATOR_API_KEY=your_key_here
56
+ # optional
57
+ export FABLE_ADJUDICATOR_STYLE=gemini # gemini (default) | openai
58
+ export FABLE_ADJUDICATOR_MODEL=gemini-2.0-flash
59
+ export FABLE_ADJUDICATOR_MODE=advisory # advisory (default) | enforcing
60
+ export FABLE_ADJUDICATOR_TIMEOUT_SECONDS=15
61
+ ```
62
+
63
+ - `gemini` style calls `https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent`.
64
+ A free AI Studio key works.
65
+ - `openai` style calls an OpenAI-compatible chat-completions endpoint
66
+ (`https://api.openai.com/v1/chat/completions` unless
67
+ `FABLE_ADJUDICATOR_ENDPOINT` overrides it).
68
+
69
+ Start with `advisory`. Read the receipts. Move to `enforcing` only when the
70
+ verdicts are consistently sensible for your workloads.
71
+
72
+ ## Failure behavior
73
+
74
+ Fail-closed. Timeouts, HTTP errors, unreachable endpoints, empty replies, and
75
+ malformed model output all resolve to `uncertain`. In enforcing mode,
76
+ `uncertain` blocks the unlock just like `fail`. If the API key is missing, no
77
+ network call is attempted; the deterministic lint still runs and its verdict
78
+ stands on its own.
79
+
80
+ ## Injection resistance
81
+
82
+ Evidence is data, not instructions. The bundle is wrapped in explicit
83
+ untrusted-data markers (and any copy of those markers inside the evidence
84
+ itself is scrubbed), the model is told to judge rather than obey, the reply
85
+ must be a strict JSON object, and verdicts outside the known set are rejected.
86
+ The bundle itself is size-capped per field and in total.
87
+
88
+ ## Measuring detection quality
89
+
90
+ `benchmarks/adversarial_evidence_benchmark.py` scores the verifier against a
91
+ labeled corpus of fabricated and legitimate evidence snapshots
92
+ (`benchmarks/fixtures/adversarial_cases.json`). Baseline on the seed corpus
93
+ (16 cases): 100% catch rate on fabricated evidence, 0% false flags on
94
+ legitimate evidence - run it yourself:
95
+
96
+ ```bash
97
+ python benchmarks/adversarial_evidence_benchmark.py
98
+ ```
99
+
100
+ A seed corpus this small proves only that the rules fire. The corpus, not the
101
+ score, is the asset: every new fooling pattern found in the wild must land as
102
+ a fixture, and detection claims are only as strong as the corpus is
103
+ adversarial. `--llm` scores the full two-layer pipeline (one API call per
104
+ case, needs a key).
105
+
106
+ ## Honest limits
107
+
108
+ - No verifier can guarantee that no AI will ever fool it. This adjudicator
109
+ raises the cost of fabricated evidence; it does not make deception
110
+ impossible.
111
+ - The reviewer model can be wrong in both directions: it can pass weak
112
+ evidence and fail good evidence.
113
+ - A submission crafted to mislead this specific reviewer can sometimes
114
+ succeed. Rotate models if you depend on this gate.
115
+ - The deterministic lint only knows the patterns it was taught; novel
116
+ fabrication styles slip past it until the benchmark corpus teaches them.
117
+ - The mechanical gates (immutable time-lock, deterministic proof receipts,
118
+ anti-idle refinement cycles) remain the primary authority. The adjudicator
119
+ is one more gate that must agree, never a replacement for the others.
@@ -0,0 +1,139 @@
1
+ # Start here: stop AI coding agents from writing too early
2
+
3
+ AI coding agents often move from a plausible plan to editing files before they have gathered enough evidence. Fable Mode adds a mechanical session gate: the agent can inspect and reason, but the Fable Engine will not report write permission until the configured authority timer and proof prerequisites pass.
4
+
5
+ Fable Mode is two separate pieces:
6
+
7
+ - **Fable Engine** is the MCP server that stores session state and enforces its gates.
8
+ - **The Fable Mode Agent Skill** is the optional workflow that tells a compatible agent how to use those gates.
9
+
10
+ Installing one does not silently activate the other.
11
+
12
+ ## Install the engine
13
+
14
+ You need Python 3.10+ and [uv](https://docs.astral.sh/uv/getting-started/installation/).
15
+
16
+ Run the pinned release without changing your global Python environment:
17
+
18
+ ```bash
19
+ uvx --from fable-engine==1.3.6 fable-engine
20
+ ```
21
+
22
+ ### Claude Code
23
+
24
+ ```bash
25
+ claude mcp add fable-engine -- uvx --from fable-engine==1.3.6 fable-engine
26
+ ```
27
+
28
+ ### Cursor or another JSON-configured MCP client
29
+
30
+ ```json
31
+ {
32
+ "mcpServers": {
33
+ "fable-engine": {
34
+ "command": "uvx",
35
+ "args": ["--from", "fable-engine==1.3.6", "fable-engine"]
36
+ }
37
+ }
38
+ }
39
+ ```
40
+
41
+ Restart or reload the client, then inspect its MCP tools. You should see `fable_session` plus the browser tools exposed by the server.
42
+
43
+ ## Install the optional Agent Skill
44
+
45
+ From the root of the project where you want the skill:
46
+
47
+ ```bash
48
+ uvx --from fable-engine==1.3.6 fable-mode install-skill --dry-run
49
+ uvx --from fable-engine==1.3.6 fable-mode install-skill --yes
50
+ ```
51
+
52
+ The default destination is `.agents/skills/fable-mode`. Use `--target <dir>` for a different skill directory. The installer refuses to overwrite local edits unless you pass `--force`.
53
+
54
+ Reload the agent after installation.
55
+
56
+ ## Run a first session
57
+
58
+ Ask your MCP client to call `fable_session` with:
59
+
60
+ ```json
61
+ {
62
+ "action": "create_session",
63
+ "session_name": "parser-refactor",
64
+ "objective": "Refactor the parser without changing its public behavior",
65
+ "time_budget_minutes": 2
66
+ }
67
+ ```
68
+
69
+ The result should show:
70
+
71
+ - `can_execute_code: False`;
72
+ - the active phase;
73
+ - the authority budget and remaining time;
74
+ - zero recorded evidence items and invariants.
75
+
76
+ Next, inspect the target repository and record real findings:
77
+
78
+ ```json
79
+ {
80
+ "action": "log_epistemic_item",
81
+ "session_name": "parser-refactor",
82
+ "tag": "PROVEN",
83
+ "claim": "The public parser entry point is parse(text)",
84
+ "evidence": "src/parser.py:18 and tests/test_parser.py"
85
+ }
86
+ ```
87
+
88
+ Record a second evidence-backed claim and a falsifiable invariant:
89
+
90
+ ```json
91
+ {
92
+ "action": "record_invariant",
93
+ "session_name": "parser-refactor",
94
+ "invariant_name": "INV-01 public behavior",
95
+ "formal_statement": "For every existing parser fixture, output before == output after",
96
+ "proof_or_rationale": "Run the existing fixture suite before and after the change",
97
+ "domain": "compatibility"
98
+ }
99
+ ```
100
+
101
+ Use `get_status` to inspect the gate. When the timer has elapsed and prerequisites are satisfied, call `unlock_execution` with an evidence-based rationale. A rejected unlock is expected when a condition is still missing.
102
+
103
+ ## What the four gates mean
104
+
105
+ 1. **Think**: inspect the system and classify claims as `PROVEN`, `HYPOTHESIS`, or `UNKNOWN`.
106
+ 2. **Prove**: attach evidence to key claims and define invariants that can fail.
107
+ 3. **Attack**: run normal tests and targeted adversarial checks against the proposed change.
108
+ 4. **Write**: edit only after the engine reports that execution is unlocked, then verify the final tree.
109
+
110
+ The minimum authority budget is two minutes. It is a floor, not a claim that two minutes is enough for every task.
111
+
112
+ ## Boundaries
113
+
114
+ Fable Mode does not guarantee correct code. It also does not replace:
115
+
116
+ - the host's filesystem permissions or sandbox;
117
+ - repository instructions and review rules;
118
+ - user approval for external side effects;
119
+ - a container or VM for hostile code;
120
+ - tests, type checks, static analysis, or human review.
121
+
122
+ The V2 broker can add a separate process and policy boundary. For hostile workloads, run it inside an OS-level sandbox or container with restricted permissions.
123
+
124
+ ## Troubleshooting
125
+
126
+ **The client cannot find `fable_session`.** Run the `uvx` command directly, check the MCP client configuration, and reload the client. MCP servers communicate over standard input and output; the client manages the process after configuration.
127
+
128
+ **`unlock_execution` is rejected.** Read the returned reason. Common causes are an active authority timer, fewer than two `PROVEN` items, or no recorded invariant. Do not relabel assumptions to satisfy the counter.
129
+
130
+ **The skill is installed but not used.** Confirm the destination matches the client's skill-discovery convention, then reload the client. The package cannot activate a host skill by itself.
131
+
132
+ **You need a different workflow.** The skill is guidance around the engine. Host permissions and the user's instructions still win.
133
+
134
+ ## Next steps
135
+
136
+ - [Agent Skill reference](../skills/fable-mode/SKILL.md)
137
+ - [V2 architecture](./fable-v2-architecture.md)
138
+ - [V1 to V2 migration](./fable-v1-v2-migration.md)
139
+ - [System 3 architecture](./system3-architecture.md)
@@ -27,6 +27,7 @@ from fable_engine.actions.deliberation import (
27
27
  _handle_get_session_lineage,
28
28
  _handle_inspect_plan,
29
29
  _handle_verify_proof,
30
+ _handle_adjudicate_evidence,
30
31
  _handle_record_visual_mockups,
31
32
  _handle_validate_event_history,
32
33
  )
@@ -186,6 +187,9 @@ ACTION_DISPATCH: Dict[str, Callable[[Dict[str, Any]], str]] = {
186
187
  "plan": _handle_inspect_plan,
187
188
  "inspect_blueprint": _handle_inspect_plan,
188
189
  "verify_proof": _handle_verify_proof,
190
+ "adjudicate_evidence": _handle_adjudicate_evidence,
191
+ "adjudicate": _handle_adjudicate_evidence,
192
+ "ai_review": _handle_adjudicate_evidence,
189
193
  "validate_proof": _handle_verify_proof,
190
194
  "check_proof": _handle_verify_proof,
191
195
  "record_visual_mockups": _handle_record_visual_mockups,
@@ -521,3 +521,51 @@ def _handle_validate_event_history(arguments: Dict[str, Any]) -> str:
521
521
  )
522
522
 
523
523
 
524
+ def _handle_adjudicate_evidence(arguments: Dict[str, Any]) -> str:
525
+ """On-demand AI adjudication of a session's recorded evidence.
526
+
527
+ Runs even in advisory mode; the env flag still gates whether any
528
+ external call happens at all.
529
+ """
530
+ session_name = arguments.get("session_name", "").strip()
531
+ if not session_name:
532
+ return "Error: 'session_name' is required for action 'adjudicate_evidence'."
533
+ try:
534
+ session = get_or_load_session(session_name)
535
+ except Exception as exc:
536
+ return f"Error: could not load session '{session_name}': {exc}"
537
+
538
+ from fable_engine.adjudicator import AdjudicatorConfig, adjudicate_session
539
+ config = AdjudicatorConfig.from_env()
540
+ if not config.enabled:
541
+ return (
542
+ "AI Evidence Adjudicator is disabled. The host must set "
543
+ "FABLE_ADJUDICATOR_ENABLED=1 and FABLE_ADJUDICATOR_API_KEY "
544
+ "(optional: FABLE_ADJUDICATOR_STYLE, FABLE_ADJUDICATOR_MODEL, "
545
+ "FABLE_ADJUDICATOR_MODE=advisory|enforcing). No evidence was sent anywhere."
546
+ )
547
+ receipt = adjudicate_session(session, config=config)
548
+ if receipt is None:
549
+ return "AI Evidence Adjudicator is disabled; no review performed."
550
+ session.proof_receipts.append(receipt)
551
+ try:
552
+ session.save()
553
+ except Exception:
554
+ pass
555
+
556
+ verdict = str(receipt.get("verdict", "uncertain")).upper()
557
+ badge = {"PASS": "✅ PASS", "FAIL": "❌ FAIL"}.get(verdict, "⚠️ UNCERTAIN")
558
+ issues = receipt.get("issues") or []
559
+ issues_md = "\n".join(f"- {i}" for i in issues) if issues else "- none reported"
560
+ blocking = "blocking (enforcing mode)" if receipt.get("mode") == "enforcing" else "advisory only"
561
+ return (
562
+ f"### 🤖 AI Evidence Adjudication\n\n"
563
+ f"- **Verdict**: `{badge}` ({blocking})\n"
564
+ f"- **Confidence**: `{receipt.get('confidence', 0.0)}`\n"
565
+ f"- **Model**: `{receipt.get('model')}` ({receipt.get('style')})\n"
566
+ f"- **Receipt ID**: `{receipt.get('receipt_id')}`\n"
567
+ f"- **Evidence Bundle SHA-256**: `{receipt.get('bundle_sha256')}`\n"
568
+ f"\n**Issues**:\n{issues_md}\n\n"
569
+ f"Note: an AI adjudication is a second opinion, not a guarantee. "
570
+ f"Mechanical gates and deterministic proof receipts remain the primary authority."
571
+ )
@@ -200,16 +200,25 @@ def _handle_red_team_code_review(arguments: Dict[str, Any]) -> str:
200
200
  code_snippet = arguments[k]
201
201
  break
202
202
 
203
+ sandbox = None
203
204
  if code_snippet is not None and not callable(code_snippet):
204
- return (
205
- "Error: Source-code strings cannot be evaluated in-process for security reasons. "
206
- "Dynamic source-code execution is disabled for public actions until an isolated sandbox executor is configured."
207
- )
205
+ from fable_v2.coder_fleet.sandbox_executor import load_sandboxed_target
206
+ entrypoint = arguments.get("entrypoint") or arguments.get("function_name") or None
207
+ try:
208
+ sandbox = load_sandboxed_target(str(code_snippet), entrypoint=entrypoint)
209
+ code_snippet = sandbox
210
+ except Exception as exc:
211
+ return f"Error: Sandboxed executor could not load the target source: {exc}"
208
212
 
209
213
  custom_hypotheses = arguments.get("custom_hypotheses") or arguments.get("hypotheses")
210
214
  output_path = arguments.get("output_path")
211
215
 
212
- session = get_or_load_session(session_name)
216
+ try:
217
+ session = get_or_load_session(session_name)
218
+ except Exception:
219
+ if sandbox is not None:
220
+ sandbox.close()
221
+ raise
213
222
  try:
214
223
  report = _get_swarm().run_full_review_cycle(
215
224
  target_callable=code_snippet,
@@ -227,9 +236,13 @@ def _handle_red_team_code_review(arguments: Dict[str, Any]) -> str:
227
236
  report_dict["red_team_receipt"] = session.issue_red_team_receipt(report_dict, change_id)
228
237
  session.record_breakage_report(report_dict)
229
238
  except (TypeError, ValueError) as exc:
239
+ if sandbox is not None:
240
+ sandbox.close()
230
241
  return f"Error: Cannot record red-team report: {exc}"
231
242
  session.save()
232
243
 
244
+ if sandbox is not None:
245
+ sandbox.close()
233
246
  md_report = _get_swarm().document_breakage(report, output_path=output_path)
234
247
  return (
235
248
  f"{md_report}\n\n"
@@ -320,11 +333,15 @@ def _handle_verify_red_team_remediation(arguments: Dict[str, Any]) -> str:
320
333
  remediated_code = arguments[k]
321
334
  break
322
335
 
336
+ sandbox = None
323
337
  if remediated_code is not None and not callable(remediated_code):
324
- return (
325
- "Error: Source-code strings cannot be evaluated in-process for security reasons. "
326
- "Dynamic source-code execution is disabled for public actions until an isolated sandbox executor is configured."
327
- )
338
+ from fable_v2.coder_fleet.sandbox_executor import load_sandboxed_target
339
+ entrypoint = arguments.get("entrypoint") or arguments.get("function_name") or None
340
+ try:
341
+ sandbox = load_sandboxed_target(str(remediated_code), entrypoint=entrypoint)
342
+ remediated_code = sandbox
343
+ except Exception as exc:
344
+ return f"Error: Sandboxed executor could not load the remediated source: {exc}"
328
345
 
329
346
  session = get_or_load_session(session_name)
330
347
 
@@ -338,6 +355,8 @@ def _handle_verify_red_team_remediation(arguments: Dict[str, Any]) -> str:
338
355
  prior_report = session.breakage_reports[-1]
339
356
 
340
357
  if not prior_report:
358
+ if sandbox is not None:
359
+ sandbox.close()
341
360
  return "Error: No prior breakage report found to verify. Provide 'report_id' or 'prior_report'."
342
361
  try:
343
362
  timeout_sec = float(arguments.get("timeout_seconds", 3.0))
@@ -369,8 +388,12 @@ def _handle_verify_red_team_remediation(arguments: Dict[str, Any]) -> str:
369
388
  report["red_team_receipt"] = session.issue_red_team_receipt(report, change_id)
370
389
  session.record_breakage_report(report)
371
390
  except (TypeError, ValueError) as exc:
391
+ if sandbox is not None:
392
+ sandbox.close()
372
393
  return f"Error: Cannot record remediation verification: {exc}"
373
394
 
395
+ if sandbox is not None:
396
+ sandbox.close()
374
397
  session.save()
375
398
  broken_count = int(report.get("broken_count", 0))
376
399
  if broken_count > 0: