pdl-taskmaster 2.5.0__tar.gz → 2.5.1__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 (208) hide show
  1. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/PKG-INFO +1 -1
  2. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/docs/adr/README.md +1 -0
  3. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/__init__.py +1 -1
  4. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/host/app.py +2 -0
  5. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/host/cli.py +8 -0
  6. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/host/repl.py +81 -16
  7. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/api_worker.py +174 -30
  8. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/client.py +1 -1
  9. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/recipes/problem_class.py +3 -2
  10. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/operation_bridge.py +18 -9
  11. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/result_ir.py +14 -6
  12. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/session_engine.py +108 -49
  13. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/wire_payloads.py +4 -1
  14. pdl_taskmaster-2.5.1/src/pdl_taskmaster/tools/repl_viewer.html +276 -0
  15. pdl_taskmaster-2.5.1/src/pdl_taskmaster/tools/viewer_server.py +272 -0
  16. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/verification/checkers/partition_sum_triples.py +12 -4
  17. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/verification/output_verifier.py +1 -1
  18. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/verification/plan_soundness.py +35 -1
  19. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/verification/sandbox.py +70 -2
  20. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_plan_soundness.py +23 -0
  21. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_sys1_foundation.py +1 -1
  22. pdl_taskmaster-2.5.1/tests/test_sys1_worker_wiring.py +215 -0
  23. pdl_taskmaster-2.5.1/tests/test_viewer_command.py +51 -0
  24. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/.gitignore +0 -0
  25. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/LICENSE +0 -0
  26. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/NOTICE.md +0 -0
  27. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/README.md +0 -0
  28. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/AUTHORITY_MAP.json +0 -0
  29. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/CALIBRATION.json +0 -0
  30. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/CONTRACT_MANIFEST.json +0 -0
  31. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/EXECUTION_CONTRACT.json +0 -0
  32. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/IMPLEMENTATION_BOUNDARY.json +0 -0
  33. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/VERIFICATION_CONTRACT.json +0 -0
  34. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/ARTIFACT_STANDARD.md +0 -0
  35. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/AUTHORITY_STANDARD.md +0 -0
  36. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/CONFORMANCE_STANDARD.md +0 -0
  37. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/CONTEXT_STANDARD.md +0 -0
  38. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/EXECUTION_STANDARD.md +0 -0
  39. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/HANDOFF_STANDARD.md +0 -0
  40. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/INSTALLATION_STANDARD.md +0 -0
  41. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/PDL_STANDARD.md +0 -0
  42. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/PROMPT_STANDARD.md +0 -0
  43. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/PROTOCOL_STANDARD.md +0 -0
  44. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/RESPONSE_PLAN_STANDARD.md +0 -0
  45. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/RESULT_STANDARD.md +0 -0
  46. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/REVIEW_STANDARD.md +0 -0
  47. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/SEMANTIC_INPUT_STANDARD.md +0 -0
  48. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/TASK_SEMANTICS_STANDARD.md +0 -0
  49. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/pyproject.toml +0 -0
  50. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/AUTHORITY_MAP.json +0 -0
  51. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/CALIBRATION.json +0 -0
  52. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/CONTRACT_MANIFEST.json +0 -0
  53. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/EXECUTION_CONTRACT.json +0 -0
  54. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/IMPLEMENTATION_BOUNDARY.json +0 -0
  55. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/VERIFICATION_CONTRACT.json +0 -0
  56. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/ARTIFACT_STANDARD.md +0 -0
  57. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/AUTHORITY_STANDARD.md +0 -0
  58. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/CONFORMANCE_STANDARD.md +0 -0
  59. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/CONTEXT_STANDARD.md +0 -0
  60. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/EXECUTION_STANDARD.md +0 -0
  61. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/HANDOFF_STANDARD.md +0 -0
  62. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/INSTALLATION_STANDARD.md +0 -0
  63. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/PDL_STANDARD.md +0 -0
  64. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/PROMPT_STANDARD.md +0 -0
  65. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/PROTOCOL_STANDARD.md +0 -0
  66. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/RESPONSE_PLAN_STANDARD.md +0 -0
  67. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/RESULT_STANDARD.md +0 -0
  68. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/REVIEW_STANDARD.md +0 -0
  69. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/SEMANTIC_INPUT_STANDARD.md +0 -0
  70. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/TASK_SEMANTICS_STANDARD.md +0 -0
  71. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/__init__.py +0 -0
  72. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/mechanical_controller.py +0 -0
  73. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/activation_decision.schema.json +0 -0
  74. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/artifact_body.schema.json +0 -0
  75. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/artifact_review_facts.schema.json +0 -0
  76. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/bootstrap_analysis.schema.json +0 -0
  77. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/execution_draft.schema.json +0 -0
  78. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/execution_input_decision.schema.json +0 -0
  79. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/execution_outcome.schema.json +0 -0
  80. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/plan_artifact.schema.json +0 -0
  81. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/prompt_artifact.schema.json +0 -0
  82. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/protocol_discussion.schema.json +0 -0
  83. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/result_ir_repair.schema.json +0 -0
  84. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/__init__.py +0 -0
  85. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/build_adversarial_battery.py +0 -0
  86. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/compare_eval_runs.py +0 -0
  87. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/control_api_call.py +0 -0
  88. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/export_rlcd_dataset.py +0 -0
  89. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/fidelity_scan.py +0 -0
  90. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/gen_fidelity_battery.py +0 -0
  91. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/leak_scan.py +0 -0
  92. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/rerecord_fixtures.py +0 -0
  93. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/run_canary_shape_probe.py +0 -0
  94. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/run_dual_gate_probe.py +0 -0
  95. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/run_qualified_batch.py +0 -0
  96. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/summarize_run.py +0 -0
  97. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/host/__init__.py +0 -0
  98. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/observation/__init__.py +0 -0
  99. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/observation/cli.py +0 -0
  100. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/observation/observed_session.py +0 -0
  101. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/observation/parsers.py +0 -0
  102. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/observation/records.py +0 -0
  103. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/observation/session.py +0 -0
  104. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/observation/sink.py +0 -0
  105. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/observation/sinks.py +0 -0
  106. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/README.md +0 -0
  107. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/__init__.py +0 -0
  108. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/base.py +0 -0
  109. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/codex_worker.py +0 -0
  110. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/fixtures.py +0 -0
  111. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/live_stub.py +0 -0
  112. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/recorded.py +0 -0
  113. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/__init__.py +0 -0
  114. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/gating.py +0 -0
  115. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/recipes/__init__.py +0 -0
  116. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/recipes/activation_route.py +0 -0
  117. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/recipes/base.py +0 -0
  118. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/recipes/confirmation_match.py +0 -0
  119. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/recipes/review_facets.py +0 -0
  120. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/schema.py +0 -0
  121. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys2/__init__.py +0 -0
  122. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys2/client.py +0 -0
  123. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/py.typed +0 -0
  124. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/__init__.py +0 -0
  125. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/context_compiler.py +0 -0
  126. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/model_classification.py +0 -0
  127. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/normative_store.py +0 -0
  128. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/presentation.py +0 -0
  129. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/quarantine.py +0 -0
  130. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/semantic_observer.py +0 -0
  131. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/standard_registry.py +0 -0
  132. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/worker-bootstrap.txt +0 -0
  133. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/workspace.py +0 -0
  134. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/tracking/__init__.py +0 -0
  135. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/tracking/log_live_session.py +0 -0
  136. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/tracking/mlflow_sink.py +0 -0
  137. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/verification/__init__.py +0 -0
  138. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/verification/checkers/__init__.py +0 -0
  139. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/verification/checkers/base.py +0 -0
  140. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/verification/checkers/fallback.py +0 -0
  141. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/verify/verify_repl_baseline.py +0 -0
  142. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/FIXTURE_MANIFEST.json +0 -0
  143. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/BND-00/turns.json +0 -0
  144. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-01/turns.json +0 -0
  145. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-02/turns.json +0 -0
  146. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-03/turns.json +0 -0
  147. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-04/turns.json +0 -0
  148. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-05/turns.json +0 -0
  149. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-06/turns.json +0 -0
  150. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-07/turns.json +0 -0
  151. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-08/turns.json +0 -0
  152. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-09/turns.json +0 -0
  153. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-10/turns.json +0 -0
  154. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-01/turns.json +0 -0
  155. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-02/turns.json +0 -0
  156. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-03/turns.json +0 -0
  157. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-04/turns.json +0 -0
  158. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-05/turns.json +0 -0
  159. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-06/turns.json +0 -0
  160. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-07/turns.json +0 -0
  161. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-08/turns.json +0 -0
  162. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-09/turns.json +0 -0
  163. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-10/turns.json +0 -0
  164. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/F4-CONTRADICTION/turns.json +0 -0
  165. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/MANIFEST.json +0 -0
  166. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/STACK-01/turns.json +0 -0
  167. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/STACK-02/turns.json +0 -0
  168. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/STACK-03/turns.json +0 -0
  169. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/STACK-04/turns.json +0 -0
  170. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/STACK-05/turns.json +0 -0
  171. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/ACTOR-01/turns.json +0 -0
  172. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/ACTOR-02/turns.json +0 -0
  173. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/ACTOR-03/turns.json +0 -0
  174. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/DISAMB-01/turns.json +0 -0
  175. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/DISAMB-02/turns.json +0 -0
  176. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/DISAMB-03/turns.json +0 -0
  177. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/DISAMB-04/turns.json +0 -0
  178. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/MANIFEST.json +0 -0
  179. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/MC-01/turns.json +0 -0
  180. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/MC-02/turns.json +0 -0
  181. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/MC-03/turns.json +0 -0
  182. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/MC-04/turns.json +0 -0
  183. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/MC-05/turns.json +0 -0
  184. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/MC-06/turns.json +0 -0
  185. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/recorded-cases.json +0 -0
  186. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_adversarial_battery.py +0 -0
  187. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_bump_version.py +0 -0
  188. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_codex_decoupling.py +0 -0
  189. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_dev_mode.py +0 -0
  190. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_evidence_sink.py +0 -0
  191. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_fidelity_scan.py +0 -0
  192. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_harness_baseline.py +0 -0
  193. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_mlflow_logger.py +0 -0
  194. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_output_verifier.py +0 -0
  195. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_phase9_turns.py +0 -0
  196. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_pydantic_wire.py +0 -0
  197. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_quarantine.py +0 -0
  198. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_quarantine_generalized.py +0 -0
  199. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_repl_integration.py +0 -0
  200. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_repl_paste.py +0 -0
  201. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_rlcd_dataset.py +0 -0
  202. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_sandbox.py +0 -0
  203. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_sem05_wiring.py +0 -0
  204. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_sys1_recipes.py +0 -0
  205. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_task_entities.py +0 -0
  206. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_v230_features.py +0 -0
  207. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_wire_repairs.py +0 -0
  208. {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_witness_projection.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pdl-taskmaster
3
- Version: 2.5.0
3
+ Version: 2.5.1
4
4
  Summary: Deterministic protocol governance and bounded AI agent harness
5
5
  Author: PDL-Standard Contributors
6
6
  License: MIT
@@ -18,6 +18,7 @@
18
18
  | [ADR-0014](0014-dual-plane-boundary-and-wire-conformance.md) | Accepted | Dual-plane boundary architecture: positive structural guidance, wire-level Pydantic contract enforcement, and tripartite clause governance. |
19
19
  | [ADR-0015](0015-model-synthesized-verification-and-confinement-boundaries.md) | Proposed | Model-synthesized verification and confinement boundaries in ephemeral sandboxes. |
20
20
  | [ADR-0016](0016-pydantic-ssot-wire-and-deliverable-boundary-enforcement.md) | Accepted | Pydantic Single Source of Truth (SSOT) for wire and deliverable boundary enforcement. |
21
+ | [ADR-0017](0017-dual-plane-runtime-realignment-and-mrv-solver-governance.md) | Accepted | Dual-Plane Runtime Realignment: System 1 (Jev) Baseline & Constraint-Ordered Solver Governance. |
21
22
 
22
23
  The records are intentionally separated so UI, context construction, execution
23
24
  isolation, output representation, and reasoning policy can evolve without
@@ -1,6 +1,6 @@
1
1
  """PDL-Taskmaster: Deterministic protocol governance and bounded AI agent harnesses."""
2
2
 
3
- __version__ = "2.5.0"
3
+ __version__ = "2.5.1"
4
4
  __protocol_version__ = "v2"
5
5
 
6
6
  __all__ = ["__version__", "__protocol_version__"]
@@ -84,6 +84,7 @@ class PDLtHost:
84
84
  higher_priority_constraints=self.higher_priority_constraints,
85
85
  available_execution_tools=[],
86
86
  render_compact=self.render_compact,
87
+ sys1_client=getattr(self.worker, "sys1_client", None),
87
88
  )
88
89
  except Exception as exc:
89
90
  # Graceful degradation: a session with no committed protocol
@@ -99,6 +100,7 @@ class PDLtHost:
99
100
  available_execution_tools=[],
100
101
  workspace_root=self.workspace_root,
101
102
  render_compact=self.render_compact,
103
+ sys1_client=getattr(self.worker, "sys1_client", None),
102
104
  )
103
105
  self.engine = engine
104
106
  if self.observation_dir is not None:
@@ -73,6 +73,12 @@ def _cmd_verify(argv: list[str]) -> int:
73
73
  return verify_main()
74
74
 
75
75
 
76
+ def _cmd_viewer(argv: list[str]) -> int:
77
+ from pdl_taskmaster.tools.viewer_server import main as viewer_main
78
+
79
+ return viewer_main(argv)
80
+
81
+
76
82
  def _main_impl(argv: list[str] | None = None) -> int:
77
83
  if argv is None:
78
84
  argv = sys.argv[1:]
@@ -89,6 +95,8 @@ def _main_impl(argv: list[str] | None = None) -> int:
89
95
  return _cmd_init(argv[1:])
90
96
  if subcmd == "verify":
91
97
  return _cmd_verify(argv[1:])
98
+ if subcmd in {"viewer", "ui", "dashboard"}:
99
+ return _cmd_viewer(argv[1:])
92
100
 
93
101
  # Default: route all other invocations to REPL
94
102
  from pdl_taskmaster.host.repl import main as repl_main
@@ -13,9 +13,36 @@ from typing import Any, TextIO
13
13
  import sys
14
14
 
15
15
 
16
- ROOT = Path(__file__).resolve().parents[3]
17
- if str(ROOT) not in sys.path:
18
- sys.path.insert(0, str(ROOT))
16
+ def _resolve_repo_root() -> Path | None:
17
+ """Resolve the repository root when running from a dev/editable install.
18
+
19
+ Returns None when running from a wheel-installed site-packages layout
20
+ where the repo root cannot be meaningfully derived from __file__.
21
+ """
22
+ candidate = Path(__file__).resolve().parents[3]
23
+ # A dev-install lives under the repo; site-packages does not.
24
+ if (candidate / "pyproject.toml").is_file() or (candidate / "setup.py").is_file():
25
+ return candidate
26
+ return None
27
+
28
+
29
+ _REPO_ROOT = _resolve_repo_root()
30
+
31
+ # Dev-install sys.path shim — harmless no-op for wheel installs.
32
+ if _REPO_ROOT is not None and str(_REPO_ROOT) not in sys.path:
33
+ sys.path.insert(0, str(_REPO_ROOT))
34
+
35
+
36
+ def _default_session_base() -> Path:
37
+ """Default live-session storage root.
38
+
39
+ Dev-install: <repo>/runs/live-sessions (preserves existing sessions)
40
+ Wheel-install: ~/.pdlt/runs/live-sessions (user-writable, consistent
41
+ with NormativeStore.user_dir())
42
+ """
43
+ if _REPO_ROOT is not None:
44
+ return _REPO_ROOT / "runs" / "live-sessions"
45
+ return Path.home() / ".pdlt" / "runs" / "live-sessions"
19
46
 
20
47
  from pdl_taskmaster.host.app import PDLtHost
21
48
  from pdl_taskmaster.providers.api_worker import ApiWorker
@@ -165,14 +192,17 @@ def _select_session(session_base: Path, args) -> str:
165
192
  return sanitize_session_name(args.session_id)
166
193
  if args.new_session or not _is_interactive(args):
167
194
  return _new_session_name()
195
+ # Ensure session root exists on first run (e.g. fresh wheel install).
196
+ session_base.mkdir(parents=True, exist_ok=True)
168
197
  sessions = sorted(
169
198
  (path for path in session_base.iterdir() if path.is_dir()),
170
199
  key=lambda path: path.stat().st_mtime,
171
200
  reverse=True,
172
201
  )
173
- if sessions:
174
- print("Existing sessions:", flush=True)
175
- for index, path in enumerate(sessions, 1):
202
+ displayed = sessions[:10]
203
+ if displayed:
204
+ print("Existing sessions (10 most recent):", flush=True)
205
+ for index, path in enumerate(displayed, 1):
176
206
  print(f" {index}) {path.name}", flush=True)
177
207
  print(" n) Start a new session", flush=True)
178
208
  else:
@@ -181,8 +211,8 @@ def _select_session(session_base: Path, args) -> str:
181
211
  choice = input("Select session: ").strip()
182
212
  except EOFError:
183
213
  return _new_session_name()
184
- if choice.isdigit() and 1 <= int(choice) <= len(sessions):
185
- return sessions[int(choice) - 1].name
214
+ if choice.isdigit() and 1 <= int(choice) <= len(displayed):
215
+ return displayed[int(choice) - 1].name
186
216
  if choice.lower() == "n" or not choice:
187
217
  return _new_session_name()
188
218
  return sanitize_session_name(choice)
@@ -273,7 +303,7 @@ def switch_session(
273
303
  try:
274
304
  subprocess.run(
275
305
  [sys.executable, "-m", "pdl_taskmaster.tracking.log_live_session", "--session-dir", str(runtime.session_dir), "--worker-profile", _worker_profile(worker)],
276
- cwd=ROOT,
306
+ cwd=(_REPO_ROOT or Path.cwd()),
277
307
  check=False,
278
308
  )
279
309
  except KeyboardInterrupt:
@@ -794,9 +824,16 @@ def main() -> int:
794
824
  )
795
825
  parser.add_argument(
796
826
  "--api-structured-output",
797
- action="store_true",
827
+ action=argparse.BooleanOptionalAction,
828
+ default=True,
798
829
  help="api worker only: pass the compiled output schema as a real JSON-schema "
799
- "decoding constraint (opt-in; backend must support structured output)",
830
+ "decoding constraint (default ON; use --no-api-structured-output or --no-structured-output to disable)",
831
+ )
832
+ parser.add_argument(
833
+ "--no-structured-output",
834
+ action="store_false",
835
+ dest="api_structured_output",
836
+ help="api worker only: disable JSON-schema decoding constraints (alias for --no-api-structured-output)",
800
837
  )
801
838
  parser.add_argument(
802
839
  "--worker-sandbox",
@@ -829,7 +866,7 @@ def main() -> int:
829
866
  if args.allow_bypass:
830
867
  print(f"[note: --allow-bypass is specific to the codex worker and is ignored for worker '{args.worker}']", flush=True)
831
868
 
832
- session_base = args.workspace_root or ROOT / "runs" / "live-sessions"
869
+ session_base = args.workspace_root or _default_session_base()
833
870
  try:
834
871
  session_id = _select_session(session_base, args)
835
872
  except ValueError as exc:
@@ -882,7 +919,7 @@ def main() -> int:
882
919
  reasoning_by_operation=_parse_reasoning_operations(args.api_reasoning_operation),
883
920
  model_by_operation=_parse_model_operations(args.api_model_operation),
884
921
  reorder_keys_for_cache=bool(getattr(args, "cache_order_render", False)),
885
- structured_output=bool(getattr(args, "api_structured_output", False)),
922
+ structured_output=bool(getattr(args, "api_structured_output", True)),
886
923
  max_tokens=getattr(args, "max_tokens", 4096),
887
924
  on_progress=lambda line: print(f"[api] {line}", flush=True) if line.strip() else None,
888
925
  )
@@ -950,6 +987,7 @@ def main() -> int:
950
987
  "/sandbox [read-only|workspace-write] -> show/set worker sandbox mode (codex worker only)\n"
951
988
  "/workdir [path] -> show/set worker workdir\n"
952
989
  "/transcript [path] -> show/set transcript file\n"
990
+ "/viewer -> launch and open live telemetry & verifier browser dashboard\n"
953
991
  "/dev [on|off|status|diagnose|set|get] -> Dev Mode diagnostic and mutation control plane\n"
954
992
  "/new -> start a new session\n"
955
993
  "/resume <session-id> -> resume a session\n"
@@ -964,6 +1002,26 @@ def main() -> int:
964
1002
  parts = line.split(maxsplit=1)
965
1003
  cmd = parts[0].lower()
966
1004
  arg = parts[1].strip() if len(parts) > 1 else ""
1005
+ if cmd in {"/viewer", "/ui", "/dashboard"}:
1006
+ import webbrowser
1007
+ from pdl_taskmaster.tools.viewer_server import start_server
1008
+
1009
+ global _viewer_server_state
1010
+ if "_viewer_server_state" not in globals() or _viewer_server_state is None:
1011
+ try:
1012
+ _viewer_server_state = start_server(8090)
1013
+ except OSError as exc:
1014
+ print(f"[viewer error] Could not start server: {exc}", flush=True)
1015
+ continue
1016
+
1017
+ _, _, bound_port = _viewer_server_state
1018
+ url = f"http://localhost:{bound_port}"
1019
+ print(f"[viewer] Live REPL dashboard running on {url}", flush=True)
1020
+ try:
1021
+ webbrowser.open(url)
1022
+ except Exception:
1023
+ pass
1024
+ continue
967
1025
  if cmd == "/dev":
968
1026
  handled, dev_mode = _handle_dev_command(line, dev_mode, runtime, worker, session_base)
969
1027
  continue
@@ -1133,7 +1191,7 @@ def main() -> int:
1133
1191
  reasoning_effort=args.api_reasoning_effort,
1134
1192
  reasoning_by_operation=_parse_reasoning_operations(args.api_reasoning_operation),
1135
1193
  model_by_operation=_parse_model_operations(args.api_model_operation),
1136
- structured_output=bool(getattr(args, "api_structured_output", False)),
1194
+ structured_output=bool(getattr(args, "api_structured_output", True)),
1137
1195
  on_progress=lambda line: print(f"[api] {line}", flush=True) if line.strip() else None,
1138
1196
  )
1139
1197
  else:
@@ -1253,7 +1311,7 @@ def main() -> int:
1253
1311
  "--worker-profile",
1254
1312
  _worker_profile(worker),
1255
1313
  ],
1256
- cwd=ROOT,
1314
+ cwd=(_REPO_ROOT or Path.cwd()),
1257
1315
  check=False,
1258
1316
  )
1259
1317
  except KeyboardInterrupt:
@@ -1266,7 +1324,14 @@ def main() -> int:
1266
1324
  ctrl = status.get("controller_state")
1267
1325
  if ctrl is not None:
1268
1326
  final_stage = ctrl.get("stage")
1269
- if final_stage not in {"CLOSED_SUCCESS", "CLOSED_CANCELLED"}:
1327
+ if final_stage == "CLOSED_CANCELLED":
1328
+ print(
1329
+ f"[headless halt] Session ended with stage '{final_stage}'. Exiting fail-closed (code 1).",
1330
+ file=sys.stderr,
1331
+ flush=True,
1332
+ )
1333
+ return 1
1334
+ if final_stage != "CLOSED_SUCCESS":
1270
1335
  print(
1271
1336
  f"[headless halt] Session ended at non-terminal stage '{final_stage}'. Exiting fail-closed (code 2).",
1272
1337
  file=sys.stderr,
@@ -79,7 +79,7 @@ class ApiWorker:
79
79
  reasoning_by_operation: dict[str, str] | None = None,
80
80
  model_by_operation: dict[str, str] | None = None,
81
81
  reorder_keys_for_cache: bool = False,
82
- structured_output: bool = False,
82
+ structured_output: bool = True,
83
83
  provider_pinning: dict[str, Any] | None = None,
84
84
  safety_settings: list[dict[str, str]] | None = None,
85
85
  max_tokens: int = 4096,
@@ -111,8 +111,17 @@ class ApiWorker:
111
111
  bootstrap_path = Path(repo_root) / "src" / "pdl_taskmaster" / "runtime" / "worker-bootstrap.txt"
112
112
  if not bootstrap_path.is_file():
113
113
  bootstrap_path = Path(repo_root) / "scripts" / "runtime" / "worker-bootstrap.txt"
114
+ self.repo_root = Path(repo_root)
114
115
  self._bootstrap = bootstrap_path.read_text(encoding="utf-8")
115
116
  self._bootstrap_prefix = self._bootstrap.rstrip() + "\n\n"
117
+ from pdl_taskmaster.providers.sys1.client import Sys1Client
118
+ self.sys1_client = Sys1Client(api_key=self._resolve_api_key_safe())
119
+
120
+ def _resolve_api_key_safe(self) -> str:
121
+ try:
122
+ return self._resolve_api_key()
123
+ except Exception:
124
+ return (os.environ.get("SYS1_API_KEY") or os.environ.get(self.api_key_env) or "").strip()
116
125
 
117
126
  @staticmethod
118
127
  def _default_api_key_command(env_name: str) -> list[str] | None:
@@ -215,42 +224,66 @@ class ApiWorker:
215
224
 
216
225
  @staticmethod
217
226
  def _sanitize_schema_for_grammar(schema: Any) -> Any:
218
- """Sanitize schema for grammar engines (Vertex, Venice, Outlines, vLLM).
227
+ """Sanitize schema for strict grammar engines (Groq, Vertex, Venice, Outlines, vLLM).
219
228
 
220
- Cleans unsupported keywords like $schema, minLength, etc., converts 'const'
221
- to single-item 'enum', while strictly preserving oneOf branch structures
222
- and required field invariants.
229
+ Inlines $defs/$ref pointers recursively, cleans unsupported keywords like
230
+ $schema, title, description, minLength, converts 'const' to single-item 'enum',
231
+ and enforces object constraints.
223
232
  """
224
233
  if not isinstance(schema, dict):
225
234
  return schema
226
235
 
236
+ defs = schema.get("$defs", {}) or schema.get("definitions", {}) or {}
237
+
227
238
  def _clean_node(node: Any) -> Any:
228
239
  if not isinstance(node, dict):
229
240
  return node
230
- res = dict(node)
231
- for key_to_drop in ("$schema", "minLength", "maxLength", "minItems", "maxItems", "uniqueItems"):
232
- res.pop(key_to_drop, None)
241
+ if "$ref" in node:
242
+ ref_path = str(node["$ref"])
243
+ if ref_path.startswith("#/$defs/") or ref_path.startswith("#/definitions/"):
244
+ def_name = ref_path.split("/")[-1]
245
+ if def_name in defs:
246
+ inlined = dict(defs[def_name])
247
+ for k, v in node.items():
248
+ if k != "$ref":
249
+ inlined[k] = v
250
+ return _clean_node(inlined)
251
+ res: dict[str, Any] = {}
252
+ for k, v in node.items():
253
+ if k in (
254
+ "$defs",
255
+ "definitions",
256
+ "$schema",
257
+ "title",
258
+ "description",
259
+ "minLength",
260
+ "maxLength",
261
+ "minItems",
262
+ "maxItems",
263
+ "uniqueItems",
264
+ ):
265
+ continue
266
+ if isinstance(v, dict):
267
+ res[k] = _clean_node(v)
268
+ elif isinstance(v, list):
269
+ res[k] = [_clean_node(item) for item in v]
270
+ else:
271
+ res[k] = v
233
272
  if "const" in res:
234
273
  res["enum"] = [res.pop("const")]
235
274
  if "type" not in res:
236
275
  res["type"] = "string"
237
- if "properties" in res and isinstance(res["properties"], dict):
238
- clean_props: dict[str, Any] = {}
239
- for k, v in res["properties"].items():
240
- clean_props[k] = _clean_node(v)
241
- res["properties"] = clean_props
242
- if "items" in res:
243
- res["items"] = _clean_node(res["items"])
244
276
  if "oneOf" in res and isinstance(res["oneOf"], list):
245
- # Vertex/Gemini grammar enforcement accepts anyOf but rejects
246
- # oneOf; all oneOf branches here are distinguished by a const
247
- # 'kind' discriminator, so anyOf is semantically equivalent.
248
- res.pop("oneOf", None)
249
- res["anyOf"] = [_clean_node(b) for b in node["oneOf"]]
277
+ res["anyOf"] = [_clean_node(b) for b in res.pop("oneOf")]
250
278
  if "anyOf" in res and isinstance(res["anyOf"], list):
251
279
  res["anyOf"] = [_clean_node(b) for b in res["anyOf"]]
252
280
  if "allOf" in res and isinstance(res["allOf"], list):
253
281
  res["allOf"] = [_clean_node(b) for b in res["allOf"]]
282
+ if "properties" in res and isinstance(res["properties"], dict):
283
+ if "required" not in res or not res["required"]:
284
+ res["required"] = list(res["properties"].keys())
285
+ if "additionalProperties" not in res:
286
+ res["additionalProperties"] = False
254
287
  return res
255
288
 
256
289
  return _clean_node(schema)
@@ -331,6 +364,116 @@ class ApiWorker:
331
364
  raise TransportError(f"api worker returned non-JSON response: {raw[:500]}") from exc
332
365
 
333
366
  def call(self, request: Any) -> WorkerResult:
367
+ operation_name = getattr(request, "operation", None)
368
+
369
+ # ADR-0017 Pillar 1: Wire System 1 (Jev / ModernBERT) for fast classification and review interpretation
370
+ if operation_name == "INTERPRET_ACTIVATION":
371
+ if not self.sys1_client.is_configured:
372
+ safe_k = self._resolve_api_key_safe()
373
+ if safe_k:
374
+ self.sys1_client.api_key = safe_k
375
+ if self.sys1_client.is_configured:
376
+ try:
377
+ user_msg = ""
378
+ proj = getattr(request, "projection", None)
379
+ if proj and isinstance(getattr(proj, "document", None), dict):
380
+ user_msg = proj.document.get("operation_inputs", {}).get("RAW_USER_MESSAGE", "")
381
+ if not user_msg:
382
+ try:
383
+ parsed_in = json.loads(request.prompt.split("\n\n", 1)[-1])
384
+ user_msg = parsed_in.get("operation_inputs", {}).get("RAW_USER_MESSAGE", "")
385
+ except Exception:
386
+ pass
387
+ if user_msg:
388
+ from pdl_taskmaster.providers.sys1.recipes.activation_route import ActivationRouteRecipe
389
+ recipe = ActivationRouteRecipe()
390
+ sys1_req = recipe.build_request({"request": user_msg})
391
+ resp_body, duration_ms = self.sys1_client.call(sys1_req)
392
+ result = recipe.parse_response(resp_body, duration_ms=duration_ms)
393
+ if result.passed_gating:
394
+ wire_payload = recipe.map_to_wire(result)
395
+ metadata = {
396
+ "worker": "sys1",
397
+ "model": self.sys1_client.model,
398
+ "observed_model": self.sys1_client.model,
399
+ "recipe": recipe.name,
400
+ "confidence": result.confidence,
401
+ "latency_ms": round(duration_ms, 3),
402
+ "operation": operation_name,
403
+ }
404
+ return WorkerResult(json.dumps(wire_payload), metadata)
405
+ except Exception:
406
+ pass
407
+
408
+ elif operation_name in ("INTERPRET_PROMPT_REVIEW", "INTERPRET_PLAN_REVIEW"):
409
+ if not self.sys1_client.is_configured:
410
+ safe_k = self._resolve_api_key_safe()
411
+ if safe_k:
412
+ self.sys1_client.api_key = safe_k
413
+ if self.sys1_client.is_configured:
414
+ try:
415
+ proj = getattr(request, "projection", None)
416
+ doc = proj.document if proj and isinstance(getattr(proj, "document", None), dict) else {}
417
+ op_inputs = doc.get("operation_inputs", {})
418
+ subject_body = op_inputs.get("BOUND_REVIEW_SUBJECT_BODY", "")
419
+ user_msg = op_inputs.get("RAW_USER_REVIEW_MESSAGE", "")
420
+ artifact_kind = "plan" if operation_name == "INTERPRET_PLAN_REVIEW" else "prompt"
421
+
422
+ if not (subject_body and user_msg):
423
+ try:
424
+ parsed_in = json.loads(request.prompt.split("\n\n", 1)[-1])
425
+ op_inputs = parsed_in.get("operation_inputs", {})
426
+ subject_body = op_inputs.get("BOUND_REVIEW_SUBJECT_BODY", "")
427
+ user_msg = op_inputs.get("RAW_USER_REVIEW_MESSAGE", "")
428
+ except Exception:
429
+ pass
430
+
431
+ if subject_body and user_msg:
432
+ from pdl_taskmaster.providers.sys1.recipes.confirmation_match import ConfirmationMatchRecipe
433
+ from pdl_taskmaster.providers.sys1.recipes.review_facets import ReviewFacetsRecipe
434
+
435
+ conf_recipe = ConfirmationMatchRecipe()
436
+ conf_req = conf_recipe.build_request({"proposal": subject_body, "response": user_msg})
437
+ conf_body, duration_ms = self.sys1_client.call(conf_req)
438
+ conf_res = conf_recipe.parse_response(conf_body, duration_ms=duration_ms)
439
+
440
+ if conf_res.passed_gating and conf_res.verdict in ("agrees", "rejects"):
441
+ wire_payload = conf_recipe.map_to_wire(conf_res)
442
+ metadata = {
443
+ "worker": "sys1",
444
+ "model": self.sys1_client.model,
445
+ "observed_model": self.sys1_client.model,
446
+ "recipe": conf_recipe.name,
447
+ "confidence": conf_res.confidence,
448
+ "latency_ms": round(duration_ms, 3),
449
+ "operation": operation_name,
450
+ }
451
+ return WorkerResult(json.dumps(wire_payload), metadata)
452
+
453
+ # Evaluate multi-label review facets
454
+ facets_recipe = ReviewFacetsRecipe()
455
+ facets_req = facets_recipe.build_request({
456
+ "artifact_kind": artifact_kind,
457
+ "content": subject_body,
458
+ "feedback": user_msg,
459
+ })
460
+ facets_body, duration_ms2 = self.sys1_client.call(facets_req)
461
+ facets_res = facets_recipe.parse_response(facets_body, duration_ms=duration_ms2)
462
+ if facets_res.passed_gating:
463
+ wire_payload = facets_recipe.map_to_wire(facets_res)
464
+ metadata = {
465
+ "worker": "sys1",
466
+ "model": self.sys1_client.model,
467
+ "observed_model": self.sys1_client.model,
468
+ "recipe": facets_recipe.name,
469
+ "confidence": facets_res.confidence,
470
+ "latency_ms": round(duration_ms + duration_ms2, 3),
471
+ "operation": operation_name,
472
+ }
473
+ return WorkerResult(json.dumps(wire_payload), metadata)
474
+ except Exception:
475
+ pass
476
+
334
477
  instructions, input_text = self._split_prompt(request.prompt)
335
478
  if self.reorder_keys_for_cache:
336
479
  input_text = self._reorder_for_cache(input_text.lstrip())
@@ -347,7 +490,6 @@ class ApiWorker:
347
490
  # losing the entire task upstream of every gate. Structured output is
348
491
  # for ops whose SHAPE is the contract (drafts, executions, reviews);
349
492
  # the semantic read must stay free-text.
350
- operation_name = getattr(request, "operation", None)
351
493
  schema_enforced = self.structured_output and operation_name not in _SEMANTIC_READ_OPERATIONS
352
494
 
353
495
  extra_guidance = ""
@@ -374,13 +516,15 @@ class ApiWorker:
374
516
  " EMIT the resulting partition and count\n"
375
517
  "2. Layout: Each step MUST appear on its own line (PDL-02). DO NOT invent prefixes like 'STEP 1:', 'ACTION:', 'RESULT:' (PDL-05).\n"
376
518
  "3. Procedure to Deliverable: Specify the high-level procedural steps to execute and compute the concrete deliverable (PLAN-01, PLAN-02).\n"
377
- "4. Neutrality & No Placeholders: Do not leak substantive answers into the plan (PLAN-04), and NEVER insert placeholder steps or meta-prohibitions like 'insert placeholders without performing computation' (PLAN-10)."
519
+ "4. Neutrality & No Placeholders: Do not leak substantive answers into the plan (PLAN-04), and NEVER insert placeholder steps or meta-prohibitions like 'insert placeholders without performing computation' (PLAN-10).\n"
520
+ "5. Verified Execution & MRV Search: For combinatorial, partition, or search tasks, commit to running an executable Python solver script using constraint ordering or Minimum Remaining Values (MRV) heuristic (e.g. branch on elements with fewest candidates first)."
378
521
  )
379
- elif operation_name == "EXECUTE":
522
+ elif operation_name in ("EXECUTE", "DRAFT_EXECUTE", "DRAFT_EXECUTION", "EMIT_RESULT_IR"):
380
523
  extra_guidance = (
381
- "\n\nNORMATIVE GUIDELINES FOR EXECUTE:\n"
524
+ "\n\nNORMATIVE GUIDELINES FOR EXECUTE & DRAFT_EXECUTE:\n"
382
525
  "- This is the substantive execution stage: You MUST solve the problem, perform any required computation, and output the concrete final deliverable/result (e.g. concrete answers, solutions, code, or partitions), not an algorithmic description or meta-summary.\n"
383
- "- If SUPPLIED_EXECUTION_INPUT_SOURCE is provided, use it as the operative input data for your computation."
526
+ "- If SUPPLIED_EXECUTION_INPUT_SOURCE is provided, use it as the operative input data for your computation.\n"
527
+ "- MANDATORY FOR VERIFIED / ALGORITHMIC TASKS: The deliverable 'body' MUST contain the complete, executable Python solver script inside a ```python ... ``` block. Implement an efficient constraint-ordered search (MRV) so the script runs in <1s in the sandbox and prints the witness. Never output fabricated or guessed solutions in prose without code."
384
528
  )
385
529
 
386
530
  if instructions:
@@ -414,11 +558,11 @@ class ApiWorker:
414
558
  schema = manifest["output_schema"]
415
559
  elif not isinstance(schema, dict) and isinstance(manifest.get("output_schema"), str):
416
560
  schema_path = self.repo_root / manifest["output_schema"]
417
- if schema_path.is_file():
418
- try:
419
- schema = json.loads(schema_path.read_text(encoding="utf-8"))
420
- except Exception:
421
- schema = None
561
+ if schema_path.is_file():
562
+ try:
563
+ schema = json.loads(schema_path.read_text(encoding="utf-8"))
564
+ except Exception:
565
+ schema = None
422
566
  if schema and isinstance(schema, dict):
423
567
  body["text"] = {
424
568
  "format": {
@@ -19,7 +19,7 @@ from pdl_taskmaster.providers.sys1.schema import Sys1Request
19
19
  logger = logging.getLogger(__name__)
20
20
 
21
21
  DEFAULT_SYS1_ENDPOINT = "https://openrouter.ai/api/alpha/decisions"
22
- DEFAULT_SYS1_MODEL = os.environ.get("SYS1_MODEL", "typesafe/sys1-latest")
22
+ DEFAULT_SYS1_MODEL = os.environ.get("SYS1_MODEL", "typesafe/jev-1.13")
23
23
 
24
24
 
25
25
  class Sys1Client:
@@ -15,11 +15,12 @@ from pdl_taskmaster.providers.sys1.schema import RecipeResult, Sys1Question, Sys
15
15
 
16
16
  # Deterministic regex patterns for combinatorial existence and exact witness problems
17
17
  _COMBINATORIAL_PATTERNS = re.compile(
18
- r"(?i)\b(?:schur\s+triples?|partition\b[^.\n]*\btriples?|sum\s+triples?|"
18
+ r"(?i)\b(?:schur\s+triples?|partitioned?\b[^.\n]*\btriples?|sum\s+triples?|"
19
19
  r"subset\s*sum|exact\s+cover|(?:graph\s+)?(?:\d+-)?coloring|graph\s+color|clique\b|hamiltonian\b|"
20
20
  r"boolean\s+satisfiability|\bsat\s+solver|combinatorial\s+(?:existence|structure|optimization)|"
21
21
  r"minimal\s+(?:cut|partition)\s+palindrome|palindrome\s+partitioning|"
22
- r"does\s+(?:there\s+exist|a\s+valid\s+partition\s+exist)|is\s+it\s+possible\s+to\s+partition)\b"
22
+ r"does\s+(?:there\s+exist|a\s+valid\s+partition\s+exist)|is\s+it\s+possible\s+to\s+partition|"
23
+ r"sisters?|brothers?|how\s+many\s+sisters|family\s+relationship|logic\s+puzzle|riddle)\b"
23
24
  )
24
25
 
25
26
 
@@ -103,19 +103,23 @@ def _normalize_body_newlines(body: str) -> str:
103
103
 
104
104
  _META_RULE_PATTERNS = [
105
105
  # Prohibitions on computation/execution/solving/partitioning + describing only:
106
- # e.g. "DO NOT perform the partitioning; only describe the required result."
106
+ # e.g. "DO NOT perform the actual partitioning or verification at this stage; only specify the required result."
107
107
  # e.g. "Do not perform any computation; only describe the required task."
108
- # e.g. "Do not compute; describe only."
108
+ # e.g. "DO NOT perform any calculations or produce the actual partition in this step."
109
109
  re.compile(
110
- r"(?i)\b(?:do not|never)\s+(?:perform|execute|calculate|compute|solve|partition|do)\s+(?:any\s+|the\s+)?(?:computation|work|calculation|partitioning|task)\b[^.\n]*[.!]?",
110
+ r"(?i)\b(?:do not|never)\s+(?:perform|execute|calculate|compute|solve|partition|do|produce)\s+(?:any\s+|the\s+|actual\s+|the\s+actual\s+)?(?:computation|work|calculation|calculations|partitioning|partition|verification|task|search)\b[^.\n]*[.!]?",
111
111
  ),
112
- # Standalone "only describe / describe only the required task/result/output":
112
+ # Standalone "only describe / only specify / describe only the required task/result/output":
113
113
  re.compile(
114
- r"(?i)\b(?:only\s+describe|describe\s+only)\s+(?:the\s+)?(?:required\s+)?(?:task|result|output|deliverable)\b[^.\n]*[.!]?",
114
+ r"(?i)\b(?:only\s+(?:describe|specify)|(?:describe|specify)\s+only)\s+(?:the\s+)?(?:required\s+)?(?:task|result|output|deliverable)\b[^.\n]*[.!]?",
115
115
  ),
116
- # "without performing any computation/work/calculation/selection/partitioning"
116
+ # "without performing any / the actual computation/work/calculation/selection/partitioning/search"
117
117
  re.compile(
118
- r"(?i)\bwithout\s+performing\s+any\s+(?:computation|work|calculation|selection|partitioning)\b[^.\n]*[.!]?",
118
+ r"(?i)\bwithout\s+performing\s+(?:any\s+|the\s+|actual\s+|the\s+actual\s+)?(?:computation|work|calculation|selection|partitioning|search)\b[^.\n]*[.!]?",
119
+ ),
120
+ # "at this stage / in this step ... only specify / describe"
121
+ re.compile(
122
+ r"(?i)\b(?:at\s+this\s+stage|in\s+this\s+step)[;,]?\s*only\s+(?:specify|describe|state)\b[^.\n]*[.!]?",
119
123
  ),
120
124
  # "no actual/algorithmic/substantive computation/work is performed"
121
125
  re.compile(
@@ -268,8 +272,11 @@ class OperationBridge:
268
272
  def _validate(self, operation: str, model_type: Any, model_text: str) -> Any:
269
273
  value = self._object(model_text)
270
274
  if operation == "EXECUTE" and isinstance(value, dict) and "kind" not in value:
271
- # ADR-0016: Root Result IR wire normalization.
272
- # If the model emits a bare Result IR object at top level, wrap it as a RESULT outcome.
275
+ # ADR-0016 / ADR-0017: Root Result IR and model synonym wire normalization.
276
+ for alt in ("deliverable", "text", "output", "code", "solution", "content", "response", "answer"):
277
+ if alt in value and isinstance(value[alt], str) and value[alt].strip() and "body" not in value:
278
+ value["body"] = value[alt]
279
+ break
273
280
  if "files" in value or "reconciliation" in value or "witness" in value:
274
281
  body_candidate = value.get("body")
275
282
  if not body_candidate and value.get("files") and isinstance(value["files"], list):
@@ -287,6 +294,8 @@ class OperationBridge:
287
294
  "body": body_candidate,
288
295
  "result_ir": value,
289
296
  }
297
+ elif "body" in value and isinstance(value["body"], str) and value["body"].strip():
298
+ value["kind"] = "RESULT"
290
299
  try:
291
300
  adapter = TypeAdapter(model_type)
292
301
  return adapter.validate_python(value)
@@ -82,7 +82,7 @@ def render_instructions(
82
82
  "\n\nWITNESS REQUIREMENT (ADR-0013 / ADR-0015): Because this task requires verified execution, your Result IR MUST include a 'witness' field certifying substantive correctness:\n"
83
83
  "- If a partition exists: {\"polarity\": \"positive\", \"evidence\": {\"path\": \"execution://witness\"}, \"data\": {\"triples\": [[a1, b1, c1], [a2, b2, c2], ...]}} where each triple satisfies a + b = c and all input integers are partitioned without duplicates.\n"
84
84
  "- If no partition exists: {\"polarity\": \"negative\", \"evidence\": {\"path\": \"execution://witness\"}, \"search_exhausted\": true, \"nodes_explored\": <integer count of search states explored, > 1>, \"method\": \"<search algorithm name>\"}\n\n"
85
- "COMPUTATIONAL SEARCH & SYNTHESIS: To solve and verify large inputs, include an executable Python solver script in a ```python ... ``` block that searches for the partition and prints the resulting triples or witness object. The host executes your script in an isolated sandbox to certify the witness."
85
+ "COMPUTATIONAL SEARCH & SYNTHESIS (ADR-0017): To solve and verify large inputs within the sandbox time ceiling, implement an efficient constraint-ordered backtracking search in a ```python ... ``` block. Crucial for combinatorial partitioning: always pick the unused element with the minimum remaining candidate triples (MRV / most constrained element first) to prune the search space to sub-second runtime. Print the resulting triples in format: print(solution) or WITNESS: {...}. The host executes your script in an isolated sandbox to certify the witness."
86
86
  )
87
87
  return base
88
88
 
@@ -199,13 +199,21 @@ def _resolve_evidence(
199
199
  return
200
200
  content = candidate.read_text(encoding="utf-8", errors="replace")
201
201
  section = ev.get("section")
202
- if section and str(section) not in content:
202
+ if section and str(section).lower() not in ("body", "execution_body", "default", "code", "solution", "script", "main", "") and str(section) not in content:
203
203
  errors.append(f"{where}: cited section marker not found in artifact: {section!r}")
204
204
  observed = ev.get("observed")
205
- if observed and str(observed).strip() not in content:
206
- errors.append(
207
- f"{where}: cited observation is not a verbatim substring of the artifact: {str(observed)[:80]!r}"
208
- )
205
+ if observed and str(observed).strip():
206
+ obs_s = str(observed).strip()
207
+ if obs_s not in content:
208
+ content_norm = " ".join(content.lower().split())
209
+ obs_norm = " ".join(obs_s.lower().split())
210
+ if obs_norm not in content_norm:
211
+ import re
212
+ obs_words = [w for w in re.findall(r"\w+", obs_norm) if len(w) > 3]
213
+ if obs_words and not any(w in content_norm for w in obs_words):
214
+ errors.append(
215
+ f"{where}: cited observation is not a verbatim substring of the artifact: {obs_s[:80]!r}"
216
+ )
209
217
 
210
218
 
211
219
  def validate_result_ir(