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.
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/PKG-INFO +1 -1
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/docs/adr/README.md +1 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/__init__.py +1 -1
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/host/app.py +2 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/host/cli.py +8 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/host/repl.py +81 -16
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/api_worker.py +174 -30
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/client.py +1 -1
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/recipes/problem_class.py +3 -2
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/operation_bridge.py +18 -9
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/result_ir.py +14 -6
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/session_engine.py +108 -49
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/wire_payloads.py +4 -1
- pdl_taskmaster-2.5.1/src/pdl_taskmaster/tools/repl_viewer.html +276 -0
- pdl_taskmaster-2.5.1/src/pdl_taskmaster/tools/viewer_server.py +272 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/verification/checkers/partition_sum_triples.py +12 -4
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/verification/output_verifier.py +1 -1
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/verification/plan_soundness.py +35 -1
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/verification/sandbox.py +70 -2
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_plan_soundness.py +23 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_sys1_foundation.py +1 -1
- pdl_taskmaster-2.5.1/tests/test_sys1_worker_wiring.py +215 -0
- pdl_taskmaster-2.5.1/tests/test_viewer_command.py +51 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/.gitignore +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/LICENSE +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/NOTICE.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/README.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/AUTHORITY_MAP.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/CALIBRATION.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/CONTRACT_MANIFEST.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/EXECUTION_CONTRACT.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/IMPLEMENTATION_BOUNDARY.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/VERIFICATION_CONTRACT.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/ARTIFACT_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/AUTHORITY_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/CONFORMANCE_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/CONTEXT_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/EXECUTION_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/HANDOFF_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/INSTALLATION_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/PDL_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/PROMPT_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/PROTOCOL_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/RESPONSE_PLAN_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/RESULT_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/REVIEW_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/SEMANTIC_INPUT_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/contracts/standards/TASK_SEMANTICS_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/pyproject.toml +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/AUTHORITY_MAP.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/CALIBRATION.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/CONTRACT_MANIFEST.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/EXECUTION_CONTRACT.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/IMPLEMENTATION_BOUNDARY.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/VERIFICATION_CONTRACT.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/ARTIFACT_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/AUTHORITY_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/CONFORMANCE_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/CONTEXT_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/EXECUTION_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/HANDOFF_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/INSTALLATION_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/PDL_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/PROMPT_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/PROTOCOL_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/RESPONSE_PLAN_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/RESULT_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/REVIEW_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/SEMANTIC_INPUT_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/contracts/standards/TASK_SEMANTICS_STANDARD.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/__init__.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/mechanical_controller.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/activation_decision.schema.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/artifact_body.schema.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/artifact_review_facts.schema.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/bootstrap_analysis.schema.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/execution_draft.schema.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/execution_input_decision.schema.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/execution_outcome.schema.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/plan_artifact.schema.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/prompt_artifact.schema.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/protocol_discussion.schema.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/controller/schemas/result_ir_repair.schema.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/__init__.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/build_adversarial_battery.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/compare_eval_runs.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/control_api_call.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/export_rlcd_dataset.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/fidelity_scan.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/gen_fidelity_battery.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/leak_scan.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/rerecord_fixtures.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/run_canary_shape_probe.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/run_dual_gate_probe.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/run_qualified_batch.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/eval/summarize_run.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/host/__init__.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/observation/__init__.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/observation/cli.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/observation/observed_session.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/observation/parsers.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/observation/records.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/observation/session.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/observation/sink.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/observation/sinks.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/README.md +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/__init__.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/base.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/codex_worker.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/fixtures.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/live_stub.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/recorded.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/__init__.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/gating.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/recipes/__init__.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/recipes/activation_route.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/recipes/base.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/recipes/confirmation_match.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/recipes/review_facets.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys1/schema.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys2/__init__.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/providers/sys2/client.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/py.typed +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/__init__.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/context_compiler.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/model_classification.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/normative_store.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/presentation.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/quarantine.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/semantic_observer.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/standard_registry.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/worker-bootstrap.txt +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/workspace.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/tracking/__init__.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/tracking/log_live_session.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/tracking/mlflow_sink.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/verification/__init__.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/verification/checkers/__init__.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/verification/checkers/base.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/verification/checkers/fallback.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/verify/verify_repl_baseline.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/FIXTURE_MANIFEST.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/BND-00/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-01/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-02/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-03/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-04/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-05/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-06/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-07/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-08/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-09/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/DRIP-10/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-01/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-02/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-03/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-04/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-05/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-06/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-07/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-08/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-09/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/ENC-10/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/F4-CONTRADICTION/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/MANIFEST.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/STACK-01/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/STACK-02/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/STACK-03/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/STACK-04/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/adversarial/STACK-05/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/ACTOR-01/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/ACTOR-02/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/ACTOR-03/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/DISAMB-01/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/DISAMB-02/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/DISAMB-03/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/DISAMB-04/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/MANIFEST.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/MC-01/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/MC-02/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/MC-03/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/MC-04/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/MC-05/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/fidelity/MC-06/turns.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/fixtures/recorded-cases.json +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_adversarial_battery.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_bump_version.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_codex_decoupling.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_dev_mode.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_evidence_sink.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_fidelity_scan.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_harness_baseline.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_mlflow_logger.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_output_verifier.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_phase9_turns.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_pydantic_wire.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_quarantine.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_quarantine_generalized.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_repl_integration.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_repl_paste.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_rlcd_dataset.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_sandbox.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_sem05_wiring.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_sys1_recipes.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_task_entities.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_v230_features.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_wire_repairs.py +0 -0
- {pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/tests/test_witness_projection.py +0 -0
|
@@ -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
|
|
@@ -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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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(
|
|
185
|
-
return
|
|
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=
|
|
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=
|
|
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 (
|
|
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
|
|
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",
|
|
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",
|
|
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=
|
|
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
|
|
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 =
|
|
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
|
-
|
|
221
|
-
to single-item 'enum',
|
|
222
|
-
and
|
|
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
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
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/
|
|
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?|
|
|
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
|
|
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
|
|
{pdl_taskmaster-2.5.0 → pdl_taskmaster-2.5.1}/src/pdl_taskmaster/runtime/operation_bridge.py
RENAMED
|
@@ -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
|
|
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. "
|
|
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
|
-
|
|
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,
|
|
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()
|
|
206
|
-
|
|
207
|
-
|
|
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(
|