nighthawk-python 0.15.0__tar.gz → 0.17.0__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 (314) hide show
  1. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/.github/workflows/ci.yml +14 -14
  2. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/.github/workflows/docs.yml +26 -8
  3. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/.github/workflows/publish.yml +1 -1
  4. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/CHANGELOG.md +36 -1
  5. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/PKG-INFO +1 -1
  6. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/docs/api.md +8 -2
  7. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/docs/coding-agent-backends.md +5 -0
  8. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/docs/design-drivers.md +39 -0
  9. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/docs/embedded-execution.md +60 -7
  10. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/docs/executors.md +39 -0
  11. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/docs/for-coding-agents.md +5 -5
  12. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/docs/natural-blocks.md +4 -3
  13. nighthawk_python-0.17.0/docs/operation-feedback.md +229 -0
  14. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/docs/patterns.md +14 -13
  15. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/docs/roadmap.md +1 -1
  16. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/docs/runtime-configuration.md +167 -6
  17. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/docs/specification.md +157 -69
  18. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/docs/verification.md +14 -9
  19. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/README.md +10 -12
  20. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/inspection_study.py +14 -15
  21. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/mkdocs.yml +1 -0
  22. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/pyproject.toml +1 -1
  23. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/backends/mcp_boundary.py +33 -6
  24. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/backends/mcp_server.py +4 -6
  25. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/backends/tool_bridge.py +16 -3
  26. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/composition.py +6 -2
  27. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/configuration.py +5 -4
  28. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/function_call.py +16 -4
  29. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/lifecycle.py +2 -2
  30. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/oversight.py +36 -10
  31. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/__init__.py +14 -1
  32. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/environment.py +50 -29
  33. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/expression.py +1 -1
  34. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/model_candidate.py +12 -4
  35. nighthawk_python-0.17.0/src/nighthawk/runtime/model_response.py +43 -0
  36. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/operation_contract.py +33 -2
  37. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/operations.py +49 -19
  38. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/preparation.py +1 -4
  39. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/prompt.py +3 -17
  40. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/runner.py +31 -26
  41. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/scoping.py +13 -7
  42. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/step_context.py +4 -5
  43. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/step_executor.py +68 -33
  44. nighthawk_python-0.17.0/src/nighthawk/runtime/step_request.py +99 -0
  45. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/testing.py +25 -23
  46. nighthawk_python-0.17.0/src/nighthawk/tools/_ordering.py +252 -0
  47. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/tools/contracts.py +6 -0
  48. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/tools/execution.py +31 -3
  49. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/backends/test_mcp_boundary.py +114 -90
  50. nighthawk_python-0.17.0/tests/backends/test_rejection_feedback.py +126 -0
  51. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/backends/test_tool_bridge.py +7 -7
  52. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/docs/test_coding_agent_examples.py +1 -1
  53. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/docs/test_error_examples.py +1 -1
  54. nighthawk_python-0.17.0/tests/docs/test_operation_feedback.py +15 -0
  55. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/docs/test_readme_example.py +1 -1
  56. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/docs/test_runtime_examples.py +3 -0
  57. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/integration/test_natural_composition.py +19 -17
  58. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/lifecycle/test_embedded.py +8 -4
  59. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/lifecycle/test_step_completion.py +6 -6
  60. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/lifecycle/test_step_ledger.py +3 -3
  61. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/natural/test_runtime_name_hygiene.py +7 -6
  62. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/oversight/test_embedded_commit.py +4 -4
  63. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/oversight/test_return_expression.py +8 -8
  64. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/oversight/test_step_commit.py +15 -18
  65. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/resilience/test_composition.py +2 -2
  66. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/resilience/test_retry.py +1 -1
  67. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_discovery.py +7 -7
  68. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_embedded.py +37 -4
  69. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_environment.py +32 -14
  70. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_executor_contract.py +6 -1
  71. nighthawk_python-0.17.0/tests/runtime/test_explicit_sharing.py +317 -0
  72. nighthawk_python-0.17.0/tests/runtime/test_input_patterns.py +151 -0
  73. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_managed_model.py +5 -4
  74. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_model_selection.py +2 -2
  75. nighthawk_python-0.17.0/tests/runtime/test_operation_recovery.py +700 -0
  76. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_operations.py +8 -8
  77. nighthawk_python-0.17.0/tests/runtime/test_output_selection.py +135 -0
  78. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_preparation.py +1 -1
  79. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_runner.py +10 -5
  80. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_step_executor.py +5 -1
  81. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_workflows.py +5 -5
  82. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/support/executors.py +4 -3
  83. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/test_testing.py +28 -26
  84. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/tools/test_coroutine_ownership.py +2 -1
  85. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/tools/test_execution.py +8 -8
  86. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/tools/test_ordering.py +5 -5
  87. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/uv.lock +47 -47
  88. nighthawk_python-0.15.0/src/nighthawk/runtime/step_request.py +0 -61
  89. nighthawk_python-0.15.0/src/nighthawk/tools/_ordering.py +0 -88
  90. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/.claude/rules/docs.md +0 -0
  91. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/.claude/rules/evals.md +0 -0
  92. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/.claude/rules/promptfoo.md +0 -0
  93. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/.claude/rules/python.md +0 -0
  94. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/.claude/rules/src.md +0 -0
  95. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/.claude/rules/tests.md +0 -0
  96. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/.claude/settings.json +0 -0
  97. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/.claude/unset_envs.sh +0 -0
  98. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/.devcontainer/devcontainer-lock.json +0 -0
  99. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/.devcontainer/devcontainer.json +0 -0
  100. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/.devcontainer/postCreateCommand.sh +0 -0
  101. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/.github/dependabot.yml +0 -0
  102. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/.gitignore +0 -0
  103. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/.python-version +0 -0
  104. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/AGENTS.md +0 -0
  105. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/CLAUDE.md +0 -0
  106. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/CONTRIBUTING.md +0 -0
  107. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/LICENSE +0 -0
  108. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/README.md +0 -0
  109. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/docs/AGENTS.md +0 -0
  110. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/docs/assets/nighthawk_logo-128x128.png +0 -0
  111. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/docs/index.md +0 -0
  112. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/docs/philosophy.md +0 -0
  113. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/docs/pydantic-ai-providers.md +0 -0
  114. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/docs/quickstart.md +0 -0
  115. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/AGENTS.md +0 -0
  116. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/coding_agents/evidence/20260914-guide-assessment.md +0 -0
  117. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/__init__.py +0 -0
  118. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/cases.py +0 -0
  119. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260908-tool-design-review.md +0 -0
  120. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260909-assessment.md +0 -0
  121. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260909-configurations.json +0 -0
  122. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260909-gpt56-assessment.md +0 -0
  123. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260909-gpt56-configurations.json +0 -0
  124. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260909-gpt56-guidance.md +0 -0
  125. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260909-gpt56-main.md +0 -0
  126. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260909-gpt56-selected-traces.json +0 -0
  127. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260909-gpt56-trials.csv +0 -0
  128. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260909-guidance.md +0 -0
  129. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260909-main.md +0 -0
  130. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260909-selected-traces.json +0 -0
  131. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260909-trials.csv +0 -0
  132. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260910-natural-composition.md +0 -0
  133. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260910-python-boundaries.md +0 -0
  134. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260911-ideal-state-audit.md +0 -0
  135. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260911-inspection-artifact-manifest.json +0 -0
  136. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260911-inspection-assessment.md +0 -0
  137. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260911-inspection-failure-traces.jsonl +0 -0
  138. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260911-inspection-study-protocol.md +0 -0
  139. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/evidence/20260911-inspection-trial-metrics.csv +0 -0
  140. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/prototype.py +0 -0
  141. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/report.py +0 -0
  142. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/model_tools/run.py +0 -0
  143. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/AGENTS.md +0 -0
  144. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/assertions/__init__.py +0 -0
  145. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/assertions/binding_value.py +0 -0
  146. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/assertions/outcome_kind.py +0 -0
  147. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/assertions/raise_message.py +0 -0
  148. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/evidence/2026-03-26-baseline-prompt-ab.md +0 -0
  149. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/evidence/2026-03-26-baseline-regression.md +0 -0
  150. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/evidence/2026-03-26-baseline-suffix-ab.md +0 -0
  151. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/evidence/2026-04-27-runtime-prompt-optimization.md +0 -0
  152. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/promptfooconfig-agents.yaml +0 -0
  153. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/promptfooconfig-luna-sanity.yaml +0 -0
  154. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/promptfooconfig-prompt-ab.yaml +0 -0
  155. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/promptfooconfig-suffix-ab.yaml +0 -0
  156. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/promptfooconfig.yaml +0 -0
  157. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/prompts/eval_coding_agent.txt +0 -0
  158. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/prompts/eval_default.txt +0 -0
  159. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/prompts/eval_legacy_default.txt +0 -0
  160. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/prompts/eval_mutation_aware.txt +0 -0
  161. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/prompts/eval_sequenced.txt +0 -0
  162. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/provider.py +0 -0
  163. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/research-result.md +0 -0
  164. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/test_cases/binding_operations.yaml +0 -0
  165. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/test_cases/edge_cases.yaml +0 -0
  166. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/test_cases/loop_outcomes.yaml +0 -0
  167. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/test_cases/loop_outcomes_ja.yaml +0 -0
  168. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/test_cases/multi_step.yaml +0 -0
  169. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/test_cases/null_handling.yaml +0 -0
  170. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/test_cases/outcome_kinds.yaml +0 -0
  171. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/evals/promptfoo/test_cases/tool_selection.yaml +0 -0
  172. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/pyrightconfig.json +0 -0
  173. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/AGENTS.md +0 -0
  174. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/__init__.py +0 -0
  175. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/backends/__init__.py +0 -0
  176. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/backends/_text_fallback.py +0 -0
  177. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/backends/base.py +0 -0
  178. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/backends/claude_code_cli.py +0 -0
  179. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/backends/claude_code_sdk.py +0 -0
  180. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/backends/claude_code_settings.py +0 -0
  181. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/backends/codex.py +0 -0
  182. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/backends/process_management.py +0 -0
  183. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/backends/text_projection.py +0 -0
  184. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/backends/tool_transport.py +0 -0
  185. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/errors.py +0 -0
  186. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/identifier_path.py +0 -0
  187. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/json_renderer.py +0 -0
  188. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/natural/__init__.py +0 -0
  189. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/natural/_names.py +0 -0
  190. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/natural/blocks.py +0 -0
  191. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/natural/decorator.py +0 -0
  192. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/natural/definition.py +0 -0
  193. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/natural/transform.py +0 -0
  194. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/resilience/__init__.py +0 -0
  195. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/resilience/_budget.py +0 -0
  196. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/resilience/_circuit_breaker.py +0 -0
  197. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/resilience/_fallback.py +0 -0
  198. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/resilience/_retry.py +0 -0
  199. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/resilience/_timeout.py +0 -0
  200. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/resilience/_vote.py +0 -0
  201. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/_user_content.py +0 -0
  202. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/annotations.py +0 -0
  203. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/assignment.py +0 -0
  204. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/async_bridge.py +0 -0
  205. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/bindings.py +0 -0
  206. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/context.py +0 -0
  207. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/description.py +0 -0
  208. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/discovery.py +0 -0
  209. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/embedded.py +0 -0
  210. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/execution_reference.py +0 -0
  211. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/inspection.py +0 -0
  212. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/interruption.py +0 -0
  213. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/notifications.py +0 -0
  214. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/step_contract.py +0 -0
  215. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/step_definition.py +0 -0
  216. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/step_result.py +0 -0
  217. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/runtime/tool_calls.py +0 -0
  218. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/tools/__init__.py +0 -0
  219. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/tools/_admission.py +0 -0
  220. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/tools/_tool_return_content.py +0 -0
  221. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/tools/assignment.py +0 -0
  222. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/tools/declarations.py +0 -0
  223. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/tools/provided.py +0 -0
  224. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/src/nighthawk/ulid.py +0 -0
  225. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/AGENTS.md +0 -0
  226. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/README.md +0 -0
  227. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/__init__.py +0 -0
  228. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/backends/__init__.py +0 -0
  229. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/backends/test_base.py +0 -0
  230. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/backends/test_claude_code_cli.py +0 -0
  231. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/backends/test_claude_code_sdk.py +0 -0
  232. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/backends/test_codex.py +0 -0
  233. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/backends/test_process_management.py +0 -0
  234. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/backends/test_text_fallback.py +0 -0
  235. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/backends/test_text_projection.py +0 -0
  236. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/backends/test_tool_transport.py +0 -0
  237. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/conftest.py +0 -0
  238. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/docs/__init__.py +0 -0
  239. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/docs/test_integrity.py +0 -0
  240. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/docs/test_links.py +0 -0
  241. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/docs/test_prompt_examples.py +0 -0
  242. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/evals/__init__.py +0 -0
  243. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/evals/model_tools/__init__.py +0 -0
  244. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/evals/model_tools/test_inspection_study.py +0 -0
  245. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/evals/model_tools/test_prototype.py +0 -0
  246. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/integration/__init__.py +0 -0
  247. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/integration/skip_helpers.py +0 -0
  248. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/integration/test_carry_pattern.py +0 -0
  249. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/integration/test_claude_code_cli.py +0 -0
  250. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/integration/test_claude_code_sdk.py +0 -0
  251. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/integration/test_codex.py +0 -0
  252. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/integration/test_openai.py +0 -0
  253. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/integration/test_openai_multimodal.py +0 -0
  254. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/lifecycle/__init__.py +0 -0
  255. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/lifecycle/test_notifications.py +0 -0
  256. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/natural/__init__.py +0 -0
  257. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/natural/test_block_ordering.py +0 -0
  258. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/natural/test_blocks.py +0 -0
  259. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/natural/test_decorator_globals.py +0 -0
  260. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/natural/test_deferred_annotations.py +0 -0
  261. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/natural/test_function_definition.py +0 -0
  262. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/natural/test_introspection.py +0 -0
  263. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/natural/test_lexical_contract.py +0 -0
  264. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/natural/test_methods.py +0 -0
  265. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/natural/test_traceback.py +0 -0
  266. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/natural/test_variadic_contracts.py +0 -0
  267. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/oversight/__init__.py +0 -0
  268. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/resilience/__init__.py +0 -0
  269. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/resilience/test_budget.py +0 -0
  270. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/resilience/test_circuit_breaker.py +0 -0
  271. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/resilience/test_fallback.py +0 -0
  272. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/resilience/test_timeout.py +0 -0
  273. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/resilience/test_vote.py +0 -0
  274. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/__init__.py +0 -0
  275. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_assignment.py +0 -0
  276. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_async_bridge.py +0 -0
  277. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_bindings.py +0 -0
  278. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_capabilities.py +0 -0
  279. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_context.py +0 -0
  280. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_description.py +0 -0
  281. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_expression.py +0 -0
  282. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_model_candidate.py +0 -0
  283. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_model_operation_failures.py +0 -0
  284. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_prompt_globals.py +0 -0
  285. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_prompt_multimodal.py +0 -0
  286. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_prompt_system.py +0 -0
  287. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_prompt_values.py +0 -0
  288. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_request_observation.py +0 -0
  289. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_scope_composition.py +0 -0
  290. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_scoping.py +0 -0
  291. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_step_contract.py +0 -0
  292. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_step_definition.py +0 -0
  293. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_tracing.py +0 -0
  294. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/runtime/test_usage_meter.py +0 -0
  295. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/support/__init__.py +0 -0
  296. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/support/codex.py +0 -0
  297. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/support/contexts.py +0 -0
  298. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/support/host_controls.py +0 -0
  299. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/support/prompts.py +0 -0
  300. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/support/tools.py +0 -0
  301. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/support/values.py +0 -0
  302. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/test_composition.py +0 -0
  303. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/test_configuration.py +0 -0
  304. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/test_function_call.py +0 -0
  305. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/test_json_renderer.py +0 -0
  306. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/test_public_api.py +0 -0
  307. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/tools/__init__.py +0 -0
  308. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/tools/test_admission.py +0 -0
  309. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/tools/test_assignment_async.py +0 -0
  310. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/tools/test_contracts.py +0 -0
  311. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/tools/test_declarations.py +0 -0
  312. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/tools/test_discovery_content.py +0 -0
  313. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/tools/test_provided_async.py +0 -0
  314. {nighthawk_python-0.15.0 → nighthawk_python-0.17.0}/tests/tools/test_tool_return_content.py +0 -0
@@ -24,7 +24,7 @@ jobs:
24
24
  persist-credentials: false
25
25
 
26
26
  # setup-uv publishes no floating major tag since v8, so pin an exact release.
27
- - uses: astral-sh/setup-uv@v10.0.1
27
+ - uses: astral-sh/setup-uv@v10.3.0
28
28
  with:
29
29
  python-version: "3.13"
30
30
  # Same dependency set and cache key as "test (3.13)". Only that job
@@ -32,16 +32,16 @@ jobs:
32
32
  save-cache: false
33
33
 
34
34
  - name: Install dependencies
35
- run: uv sync --all-extras --all-groups
35
+ run: uv sync --locked --all-extras --all-groups
36
36
 
37
37
  - name: Format check
38
- run: uv run ruff format --check .
38
+ run: uv run --no-sync ruff format --check .
39
39
 
40
40
  - name: Lint
41
- run: uv run ruff check .
41
+ run: uv run --no-sync ruff check .
42
42
 
43
43
  - name: Type check
44
- run: uv run pyright
44
+ run: uv run --no-sync pyright
45
45
 
46
46
  test:
47
47
  name: Test (Python ${{ matrix.python-version }})
@@ -49,23 +49,22 @@ jobs:
49
49
  strategy:
50
50
  fail-fast: false
51
51
  matrix:
52
- python-version: ["3.13", "3.14"]
53
- continue-on-error: ${{ matrix.python-version != '3.13' }}
52
+ python-version: ["3.13", "3.14", "3.15"]
54
53
  steps:
55
54
  - uses: actions/checkout@v7
56
55
  with:
57
56
  persist-credentials: false
58
57
 
59
58
  # Sole writer of the per-Python-version dependency cache.
60
- - uses: astral-sh/setup-uv@v10.0.1
59
+ - uses: astral-sh/setup-uv@v10.3.0
61
60
  with:
62
61
  python-version: ${{ matrix.python-version }}
63
62
 
64
63
  - name: Install dependencies
65
- run: uv sync --all-extras --all-groups
64
+ run: uv sync --locked --all-extras --all-groups
66
65
 
67
66
  - name: Run tests
68
- run: uv run pytest -q
67
+ run: uv run --no-sync pytest -q
69
68
 
70
69
  build:
71
70
  name: Build distribution
@@ -78,7 +77,7 @@ jobs:
78
77
 
79
78
  # Keep packaging and its fresh installation check independent of the
80
79
  # source test job's dependency cache.
81
- - uses: astral-sh/setup-uv@v10.0.1
80
+ - uses: astral-sh/setup-uv@v10.3.0
82
81
  with:
83
82
  enable-cache: false
84
83
 
@@ -87,14 +86,15 @@ jobs:
87
86
 
88
87
  - name: Verify documented examples against the installed wheel
89
88
  run: |
90
- uv sync --all-groups
89
+ uv sync --locked --all-groups
91
90
  uv venv "$RUNNER_TEMP/nighthawk-distribution"
92
91
  uv pip install --python "$RUNNER_TEMP/nighthawk-distribution/bin/python" dist/*.whl
93
92
  NIGHTHAWK_DISTRIBUTION_PYTHON="$RUNNER_TEMP/nighthawk-distribution/bin/python" \
94
- uv run pytest -q tests/docs/test_runtime_examples.py
93
+ uv run --no-sync pytest -q tests/docs/test_runtime_examples.py
95
94
 
96
95
  - name: Upload distribution artifacts
97
- uses: actions/upload-artifact@v6
96
+ uses: actions/upload-artifact@v7
98
97
  with:
99
98
  name: python-package-distributions
100
99
  path: dist/
100
+ if-no-files-found: error
@@ -1,4 +1,4 @@
1
- name: Deploy docs to GitHub Pages
1
+ name: Build and deploy docs to GitHub Pages
2
2
 
3
3
  on:
4
4
  push:
@@ -8,26 +8,38 @@ on:
8
8
  - "src/nighthawk/**"
9
9
  - "mkdocs.yml"
10
10
  - "pyproject.toml"
11
+ - "uv.lock"
12
+ - ".python-version"
13
+ - ".github/workflows/docs.yml"
14
+ pull_request:
15
+ branches: [main]
16
+ paths:
17
+ - "docs/**"
18
+ - "src/nighthawk/**"
19
+ - "mkdocs.yml"
20
+ - "pyproject.toml"
21
+ - "uv.lock"
22
+ - ".python-version"
11
23
  - ".github/workflows/docs.yml"
12
24
  workflow_dispatch:
13
25
 
14
26
  permissions:
15
27
  contents: read
16
- pages: write
17
- id-token: write
18
28
 
19
29
  concurrency:
20
- group: pages
21
- cancel-in-progress: false
30
+ group: pages-${{ github.event_name == 'pull_request' && github.ref || 'deployment' }}
31
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
22
32
 
23
33
  jobs:
24
34
  build:
25
35
  runs-on: ubuntu-latest
26
36
  steps:
27
37
  - uses: actions/checkout@v7
38
+ with:
39
+ persist-credentials: false
28
40
 
29
41
  # setup-uv publishes no floating major tag since v8, so pin an exact release.
30
- - uses: astral-sh/setup-uv@v10.0.1
42
+ - uses: astral-sh/setup-uv@v10.3.0
31
43
  with:
32
44
  python-version: "3.13"
33
45
  # The docs group is a subset of the cache "test (3.13)" saves under
@@ -35,18 +47,24 @@ jobs:
35
47
  save-cache: false
36
48
 
37
49
  - name: Install dependencies
38
- run: uv sync --group docs
50
+ # The default dev group supplies Ruff for API signature formatting.
51
+ run: uv sync --locked --group docs
39
52
 
40
53
  - name: Build docs
41
- run: uv run mkdocs build
54
+ run: uv run --no-sync mkdocs build
42
55
 
43
56
  - uses: actions/upload-pages-artifact@v5
57
+ if: github.event_name != 'pull_request'
44
58
  with:
45
59
  path: site
46
60
 
47
61
  deploy:
62
+ if: github.event_name != 'pull_request'
48
63
  needs: build
49
64
  runs-on: ubuntu-latest
65
+ permissions:
66
+ pages: write
67
+ id-token: write
50
68
  environment:
51
69
  name: github-pages
52
70
  url: ${{ steps.deployment.outputs.page_url }}
@@ -24,7 +24,7 @@ jobs:
24
24
  id-token: write
25
25
  steps:
26
26
  - name: Download distribution artifacts
27
- uses: actions/download-artifact@v7
27
+ uses: actions/download-artifact@v8
28
28
  with:
29
29
  name: python-package-distributions
30
30
  path: dist/
@@ -7,6 +7,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.17.0]
11
+
12
+ ### Changed
13
+
14
+ - Breaking: operation inspection now returns `Accept`, `RejectOperation`, or `AbortStep`. Commit inspection accepts `Accept`, `Rewrite`, or `AbortStep`. Replace terminal `Reject(reason)` decisions with `AbortStep(reason)`; there is no legacy alias or implicit change to recoverable behavior.
15
+ - Breaking: `StepAbortedError` replaces `OversightRejectedError`. Terminal records use `failure_stage="oversight_abort"` and `abort_reason` instead of `oversight_rejection` and `rejection_reason`. Aborted operation records use status `"aborted"`; recoverable refusals use `"rejected"`.
16
+ - Breaking: explicit commit `AbortStep` decisions also propagate `StepAbortedError` instead of an `ExecutionError` wrapper, matching operation inspection; terminal delivery may still supply a host exception.
17
+ - Standard agent output processing resolves candidate expressions before leaving its model loop. Rejected return expressions can be corrected without recreating the step or replaying prior operations.
18
+ - Rejection stops the remaining calls in the same visible model response before argument validation, records them as `"skipped"`, and discards that response's final candidates. Nighthawk makes `early` dispatch follow emission order; ordinary Pydantic AI runs retain their own strategies.
19
+ - MCP/SDK tool responses carry error indicators and structured refusal information. Coding-agent internal batches and inference requests remain outside Core's visible response/request boundaries.
20
+
21
+ ### Added
22
+
23
+ - `OperationRejection`, `OperationRejectedError`, and exported `OperationDeliveryError` support direct executor recovery and correlated failure diagnostics. Refusals retain live state, earlier effects, request accounting, and ordinary finalization.
24
+ - Deterministic model, executor, lifecycle, ordering, and backend tests cover refusal feedback, skipped calls, cancellation, notification failures, limits, and nested execution. See [operation feedback](docs/operation-feedback.md) for examples and migration details.
25
+
26
+ ## [0.16.0]
27
+
28
+ ### Changed
29
+
30
+ - Breaking: `StepCandidate` and testing responses distinguish omitted output selection (`UNSET`, select initialized declared outputs) from an explicit complete mapping (`{}`, no writes). Added `StepRequest.snapshot_output_bindings()` for explicit Python composition. `StepResponse` and response factories use `binding_name_to_value`; keyword-expanded output arguments are removed.
31
+ - Breaking: `Raise` rejects explicit nonempty output mappings in candidates and rewrites. Standard agent executors retain automatic output selection and final validation.
32
+ - Breaking: optional executor configuration and run identifiers use `UNSET`; invalid `None`, raw configuration dictionaries, and empty run identifiers fail at entry. Environment mappings reject `None`, and `StepExecutorConfiguration.model_settings` defaults to an empty dictionary.
33
+ - `function_call_scope` now supports omission or `UNSET` for inheritance, `None` for clearing, and validated handler replacement.
34
+ - Breaking: Natural functions no longer copy parent working values into their environment. Share values through Python arguments, globals, closures, or explicit `scope(task_references=...)`; ordinary Python helpers can select references from the active environment. Removed the `parent` name source and `parent_name_to_value` from `StepEnvironment` and test-call records.
35
+ - Documented explicit working-state snapshots, scoped reference replacement and clearing, and synchronous/asynchronous host sharing examples. Updated composition examples to declare their dependencies.
36
+
37
+ ### Fixed
38
+
39
+ - Falsey nonempty mappings and configuration objects retain their explicit values; invalid scope arguments fail before model resolution.
40
+ - Nested configuration and sharing scopes preserve the active step identity so child executions retain their parent-step correlation.
41
+
10
42
  ## [0.15.0]
11
43
 
12
44
  ### Added
@@ -43,6 +75,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
43
75
 
44
76
  ### Fixed
45
77
 
78
+ - Embedded step type annotations resolve explicit and scoped names on Python 3.14, including nested forward references and names that shadow builtins.
46
79
  - Dynamic annotation validation uses explicit `TypeForm[object]` casts at Pydantic `TypeAdapter` boundaries, restoring type-checking compatibility with Pydantic 2.14 without changing runtime validation. Declared `typing-extensions` as a direct dependency.
47
80
  - Error-handling guides distinguish Natural-selected exceptions, recoverable tool errors, and finalization failures. Published handlers are executed against deterministic runtime responses.
48
81
  - Tests follow environment, prompt, executor, and model-selection ownership; scope tests use current composition terminology and avoid duplicate replacement checks or fixed instrumentation names.
@@ -347,7 +380,9 @@ Invalid initial results fail before oversight; use resilience retries to recover
347
380
  - Step executor abstraction and provider integration foundation.
348
381
  - Core documentation and project scaffolding.
349
382
 
350
- [Unreleased]: https://github.com/kurusugawa-computer/nighthawk-python/compare/v0.15.0...HEAD
383
+ [Unreleased]: https://github.com/kurusugawa-computer/nighthawk-python/compare/v0.17.0...HEAD
384
+ [0.17.0]: https://github.com/kurusugawa-computer/nighthawk-python/compare/v0.15.0...v0.17.0
385
+ [0.16.0]: https://github.com/kurusugawa-computer/nighthawk-python/compare/v0.15.0...v0.16.0
351
386
  [0.15.0]: https://github.com/kurusugawa-computer/nighthawk-python/compare/v0.14.0...v0.15.0
352
387
  [0.14.0]: https://github.com/kurusugawa-computer/nighthawk-python/compare/v0.13.0...v0.14.0
353
388
  [0.13.0]: https://github.com/kurusugawa-computer/nighthawk-python/compare/v0.12.0...v0.13.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: nighthawk-python
3
- Version: 0.15.0
3
+ Version: 0.17.0
4
4
  Summary: A Python library where Python controls flow and LLMs or coding agents reason within constrained Natural blocks.
5
5
  Project-URL: Repository, https://github.com/kurusugawa-computer/nighthawk-python
6
6
  Project-URL: Documentation, https://kurusugawa-computer.github.io/nighthawk-python/
@@ -181,9 +181,11 @@
181
181
  - StepCommit
182
182
  - Rewrite
183
183
  - Accept
184
- - Reject
184
+ - RejectOperation
185
+ - AbortStep
185
186
  - Oversight
186
- - OversightRejectedError
187
+ - StepAbortedError
188
+ - OperationDecision
187
189
  - StepCommitDecision
188
190
 
189
191
  ## Lifecycle
@@ -257,6 +259,10 @@ See [Embedded execution](embedded-execution.md) for executable synchronous and a
257
259
  - OperationRequest
258
260
  - OperationFinished
259
261
  - OperationError
262
+ - OperationRejection
263
+ - OperationRejectedError
264
+ - OperationDeliveryError
265
+ - OperationStatus
260
266
 
261
267
  ::: nighthawk.runtime.expression
262
268
  options:
@@ -60,6 +60,11 @@ All three backends accept `working_directory` in their model settings. This abso
60
60
 
61
61
  If a backend CLI process fails (e.g., crashes, times out, or returns an invalid response), Nighthawk surfaces the failure as an `ExecutionError`. See [Patterns](patterns.md#error-handling) for error handling patterns.
62
62
 
63
+ Operation inspection can return `RejectOperation` to deliver structured refusal through MCP/SDK error results while keeping the transport available for another inspected request.
64
+ `AbortStep`, inspection failures, and operation notification failures terminate the step even if the coding agent catches a tool error.
65
+ Core cannot identify a coding agent's invisible response batches or individually gate its internal inference requests.
66
+ The [operation feedback support matrix](operation-feedback.md#ordering-and-backend-boundaries) describes these limits and the distinct behavior of directly visible Pydantic AI responses.
67
+
63
68
  ### Allowed tool names
64
69
 
65
70
  Use `allowed_tool_names` to restrict which Nighthawk tools are exposed to the backend via MCP. When `None` (default), all tools visible in the current scope are exposed.
@@ -168,6 +168,45 @@ The expected benefit is less custom host integration for dynamic declarations an
168
168
  Success requires correct per-invocation value contracts and completion records that reflect writeback failures.
169
169
  Compare the effort and complexity of constructing and changing this integration with an ordinary Python implementation providing the same guarantees.
170
170
 
171
+ ## Explicit sharing across nested Natural calls
172
+
173
+ **Status:** The name-resolution contract is covered by deterministic tests in `tests/runtime/test_explicit_sharing.py`, with executable synchronous and asynchronous [sharing examples](runtime-configuration.md#selecting-shared-values-with-python).
174
+ The originating evidence is one embedded conversation host's v0.15.0 reproduction; independent application evidence and model-quality improvements remain unevaluated.
175
+
176
+ The host calls reusable Natural functions from a step containing conversation input and temporary working values.
177
+ Automatically copying those working names into children creates dependencies beyond the child's arguments, Python lexical environment, and deliberately shared references.
178
+ A context builder can omit prompt content but cannot change preparation-time binding resolution or runtime name lookup.
179
+ Requiring host executors to reconstruct Core preparation would move execution complexity into applications.
180
+
181
+ Core therefore constructs each child's own Python environment and supplies only the active scope's explicit task references as additional names.
182
+ Applications select values using ordinary Python helpers and pass dictionaries through `scope(task_references=...)`; no inheritance mode or environment-construction callback is required.
183
+ Scopes preserve execution parentage and existing management contracts while replacing or clearing shared references.
184
+ This simplifies an existing execution semantic; it does not establish a general object-isolation facility.
185
+
186
+ The deterministic evidence covers absent parent bindings, preparation failures, real context construction, expression and discovery access, object identity, nested execution, and scoped asynchronous behavior.
187
+ It does not establish that separating names prevents repeated model calls or improves judgments.
188
+ Assess those hypotheses through application evaluations, including independent reuse and the effort needed to declare shared dependencies.
189
+
190
+ ## Correcting refused operations within a Natural step
191
+
192
+ **Status:** Execution contracts have deterministic coverage in `tests/runtime/test_operation_recovery.py` and `tests/backends/test_rejection_feedback.py`, with executable [model and custom-executor examples](operation-feedback.md).
193
+ No independent application case or comparative model-quality evaluation is recorded.
194
+
195
+ A host may refuse a proposed operation while still permitting a different way to complete the task.
196
+ Previously every operation-inspection rejection ended the step, even if an executor caught the exception.
197
+ Ordinary helper return values can communicate expected domain findings, but cannot change that Core-owned inspection and finalization contract.
198
+ Reimplementing the operation pipeline in application executors would duplicate state, notification, and termination responsibilities.
199
+
200
+ Core therefore separates `RejectOperation`, which refuses one body and exposes deliberate feedback, from `AbortStep`, which ends the inspected step.
201
+ The same step retains its live environment, prior effects, model history, and request controls while the model or custom executor chooses another operation.
202
+ Refusal records survive successful finalization; failed notifications and terminal stops cannot become ordinary feedback.
203
+ Visible model batches stop at refusal, while provider-internal batches remain a documented backend boundary.
204
+
205
+ Applications own the policy, alternative operations, acceptance criteria, and any durable evidence or improvement process.
206
+ Core does not infer that a later accepted output means the task was completed, automatically retry an operation, or add a separate repair agent or policy engine.
207
+ The deterministic tests establish execution behavior, not improved judgment, accumulated capability, or comparative advantage.
208
+ Further application evidence should compare successful corrections, unacceptable effects, authoring and maintenance burden, and inference cost against ordinary Python/model-library compositions.
209
+
171
210
  ## Using Nighthawk to develop Nighthawk
172
211
 
173
212
  **Status:** Conceptual application direction.
@@ -36,7 +36,10 @@ Caller locals, globals, closure cells, and inherited parent working state are no
36
36
  Scoped configuration, execution identity, oversight, capabilities, and lifecycle retain their usual inheritance rules.
37
37
 
38
38
  Called Python functions retain their own closures and globals.
39
- Nested Natural functions use their own Python frames and the usual parent working-state inheritance; the explicit namespace is not installed as their local environment.
39
+ Nested Natural functions use their own Python frames and the active scope's explicit task references.
40
+ The explicit namespace and later parent temporaries do not become implicit inputs to those functions or their descendants.
41
+ Pass values as arguments, or use a Python helper to select references for `nh.scope(task_references=...)` before calling the child.
42
+ See the [synchronous and asynchronous sharing examples](runtime-configuration.md#selecting-shared-values-with-python).
40
43
  This selects an execution environment without isolating Python objects or restricting the authority of called functions.
41
44
 
42
45
  Omitting an output annotation selects the ordinary initial-value inference rule.
@@ -52,10 +55,13 @@ It returns `None` or an awaitable completing that assignment.
52
55
  Callbacks run sequentially in output declaration order; Core records a successful assignment only after its callback returns normally.
53
56
  Both entry points accept synchronous or asynchronous writers; the synchronous entry point uses the ordinary bridge for awaitables.
54
57
 
55
- Normal finalization includes initialized declared outputs, even if the executor does not propose them.
56
- Tracked working values take precedence over initial values, and explicit executor proposals take precedence over both.
57
- Uninitialized outputs without proposals remain absent.
58
- An initial `Raise` discards outputs before value validation while still rejecting undeclared names.
58
+ When `StepCandidate.binding_name_to_value` is omitted or `nh.UNSET`, finalization selects initialized declared outputs.
59
+ Tracked working values take precedence over current Python values; uninitialized outputs and task-only references remain absent.
60
+ A supplied mapping selects exactly those outputs, including when it is empty; omitted names are neither supplemented nor validated for writeback.
61
+ Selected values must satisfy their output contracts before commit inspection.
62
+ Use `request.snapshot_output_bindings()` and ordinary Python dictionary composition to explicitly combine current output values with replacements.
63
+ An initial `Raise` selects no outputs and skips validation of pending working values.
64
+ Pairing `Raise` with an explicitly supplied nonempty output mapping is invalid for both `StepCandidate` and `Rewrite`.
59
65
  A commit `Rewrite` with an explicitly supplied mapping replaces the selected outputs completely; rewriting to `{}` does not restore initial values.
60
66
 
61
67
  These are separate facts:
@@ -71,6 +77,53 @@ An interrupted writer must finish its cancellation handling before control can r
71
77
  If a writer mutates storage and then raises, Core cannot infer whether the assignment completed; that writer owns diagnosis and recovery for its partial effects.
72
78
  This interface does not promise database transactions, rollback, retries, or durable storage.
73
79
 
80
+ This example uses the same executor with synchronous and asynchronous entry points to distinguish automatic, empty, explicit, and composed output selections.
81
+
82
+ <!-- runnable-example:output_selection -->
83
+ ```py
84
+ import asyncio
85
+
86
+ import nighthawk as nh
87
+ from nighthawk.runtime import Pass, StepCandidate, StepDefinition, StepRequest, execute_step, execute_step_async
88
+
89
+
90
+ class Executor:
91
+ def run_step(self, *, request: StepRequest) -> StepCandidate:
92
+ selection = request.processed_natural_program
93
+ if selection == "automatic":
94
+ return StepCandidate(outcome=Pass())
95
+ if selection == "empty":
96
+ return StepCandidate(outcome=Pass(), binding_name_to_value={})
97
+ if selection == "explicit":
98
+ return StepCandidate(outcome=Pass(), binding_name_to_value={"first": 7})
99
+ return StepCandidate(outcome=Pass(), binding_name_to_value={**request.snapshot_output_bindings(), "first": 7})
100
+
101
+
102
+ async def main() -> None:
103
+ selection_to_binding_name_to_value = {
104
+ "automatic": {"first": 1, "second": 2},
105
+ "empty": {},
106
+ "explicit": {"first": 7},
107
+ "composed": {"first": 7, "second": 2},
108
+ }
109
+ with nh.run(Executor()):
110
+ for asynchronous in (False, True):
111
+ for selection, expected_binding_name_to_value in selection_to_binding_name_to_value.items():
112
+ saved_name_to_value: dict[str, object] = {}
113
+ definition = StepDefinition(selection, output_binding_names=("first", "second"))
114
+ initial_name_to_value = {"first": 1, "second": 2}
115
+ if asynchronous:
116
+ await execute_step_async(definition, name_to_value=initial_name_to_value, write_binding=saved_name_to_value.__setitem__)
117
+ else:
118
+ execute_step(definition, name_to_value=initial_name_to_value, write_binding=saved_name_to_value.__setitem__)
119
+ assert saved_name_to_value == expected_binding_name_to_value
120
+
121
+
122
+ asyncio.run(main())
123
+ print("automatic=2; empty=0; explicit=1; composed=2; sync_and_async=True")
124
+ ```
125
+ <!-- /runnable-example:output_selection -->
126
+
74
127
  Terminal delivery happens after writeback or failure, with the usual `StepCompleted`, `StepRaised`, `StepFailed`, or `StepInterrupted` record.
75
128
  Notification failure propagates without replaying execution or notification and without undoing completed writes.
76
129
  The optional `source_location` labels the trusted program for diagnostics; its default is `<embedded>:0`.
@@ -107,7 +160,7 @@ definition = StepDefinition(
107
160
  binding_name_to_type={"summary": str},
108
161
  source_location="trusted_summary:1",
109
162
  )
110
- executor = ScriptedExecutor([pass_response(summary="The trial passed.")])
163
+ executor = ScriptedExecutor([pass_response(binding_name_to_value={"summary": "The trial passed."})])
111
164
  with nh.run(executor), nh.scope(lifecycle=StepLifecycle(finished)):
112
165
  outcome = execute_step(definition, name_to_value=name_to_value, write_binding=name_to_value.__setitem__)
113
166
 
@@ -159,7 +212,7 @@ async def main() -> None:
159
212
  binding_name_to_type={"selected": "Selection"},
160
213
  source_location="trusted_selection:1",
161
214
  )
162
- executor = ScriptedExecutor([pass_response(selected={"label": "alpha"})])
215
+ executor = ScriptedExecutor([pass_response(binding_name_to_value={"selected": {"label": "alpha"}})])
163
216
  with nh.run(executor), nh.scope(lifecycle=StepLifecycle(finished)):
164
217
  outcome = await execute_step_async(definition, name_to_value={"candidates": ["alpha", "beta"], "Selection": Selection}, write_binding=write)
165
218
  assert outcome == Pass()
@@ -30,6 +30,9 @@ step_executor = nh.AgentStepExecutor.from_configuration(configuration=configurat
30
30
 
31
31
  The `model` field accepts a `provider:model` identifier or a borrowed Pydantic AI `Model` instance whose client lifetime remains with the host.
32
32
  The default model is `openai-responses:gpt-5.6-luna`.
33
+ `model_settings` defaults to an empty dictionary; `None` and `UNSET` are invalid field values.
34
+ Optional executor configuration arguments use omission or `nh.UNSET` to create a fresh default configuration.
35
+ An explicit configuration replaces the complete value; raw dictionaries and `None` are rejected before constructing an agent.
33
36
 
34
37
  Use [Runtime configuration](runtime-configuration.md) to establish a run, select child models, or mix executors.
35
38
  Host wrappers can support model selection through the [configuration resolution protocol](specification.md#model-declarations-and-observation).
@@ -49,6 +52,42 @@ executor = nh.AgentStepExecutor.from_agent(agent=agent)
49
52
 
50
53
  For full control, implement `AsyncStepExecutor` directly. See [Specification Section 14.3](specification.md#143-custom-backends) for semantics and [API reference](api.md#runtime-executor-boundary) for the protocol.
51
54
 
55
+ ## Output selection
56
+
57
+ Executors return `StepCandidate(outcome=..., binding_name_to_value=...)`.
58
+ The output mapping selects the complete set of values to validate and consider for writeback.
59
+
60
+ | Selection | Meaning |
61
+ |---|---|
62
+ | Omitted or `nh.UNSET` | Select initialized declared outputs from the working environment at finalization. |
63
+ | `{}` | Select no writes, even when declared outputs already have values. |
64
+ | `{"result": value}` | Select only `result`; do not supplement other initialized outputs. |
65
+ | `None` | Invalid. |
66
+
67
+ The standard agent executor omits the selection, so its tracked assignments and other initialized declared outputs receive final validation.
68
+ An explicit selection validates only its entries; output names must still be declared, and commit inspection still applies.
69
+ Neither an empty selection nor a later rejection undoes earlier calls or in-place object mutations.
70
+ `Raise` permits only omitted or empty output selections.
71
+
72
+ For an explicit combination of current outputs and replacements, use ordinary Python:
73
+
74
+ ```py
75
+ from nighthawk.runtime import Pass, StepCandidate, StepRequest
76
+
77
+
78
+ def select_result(request: StepRequest, result: object) -> StepCandidate:
79
+ return StepCandidate(
80
+ outcome=Pass(),
81
+ binding_name_to_value={**request.snapshot_output_bindings(), "result": result},
82
+ )
83
+ ```
84
+
85
+ `snapshot_output_bindings()` returns a fresh dictionary in declaration order, preferring tracked assignments over current Python values, including live globals and cells.
86
+ Unbound outputs, temporaries, and task-only references are excluded.
87
+ The method preserves value identity and performs no validation or writes.
88
+ A snapshot fixes associations at the time it is taken; omission selects them later, during finalization.
89
+ `Rewrite` uses the same complete-mapping semantics after initial validation, with omission retaining the current commit field.
90
+
52
91
  ## Next steps
53
92
 
54
93
  - **[Pydantic AI providers](pydantic-ai-providers.md)** -- Installation, model identifiers, credentials, and model settings for each Pydantic AI provider.
@@ -89,7 +89,7 @@ Read [Quickstart](https://kurusugawa-computer.github.io/nighthawk-python/quickst
89
89
  - Use `deny` frontmatter to prohibit outcomes that would bypass required Python work. The template denies `return` to preserve the Python return path and denies the explicit `raise` outcome; runtime and helper failures can still raise.
90
90
  - Denying outcomes does not require a fresh assignment. A permitted `pass` can retain an output's initial value. Use a deliberate default or an unbound annotated output, and validate the result before dependent work.
91
91
  - Each block starts a fresh model interaction without implicit message history. Carry essential inputs and results through Python parameters and return values.
92
- - Lexical values, inherited parent working state, and scoped task references can supply context. Prefer explicit arguments for essential dependencies and inheritance for intentionally shared policy. Child name rebinding stays local; mutable objects can remain shared.
92
+ - Python lexical values and scoped task references supply context. Prefer explicit arguments for essential dependencies and `scope(task_references=...)` for intentionally shared policy. Parent working values are not copied into children. Child name rebinding stays local; explicitly shared mutable objects retain identity.
93
93
 
94
94
  The type boundary may sit inside a function: accept text that needs interpretation, then commit a typed result before deterministic work begins.
95
95
  Types constrain the result's shape and range; they do not prove that its meaning is correct.
@@ -189,8 +189,8 @@ def test_quote_batch_processes_each_message_and_uses_host_price():
189
189
  messages = ["A dozen, please.", "Please send three."]
190
190
  executor = ScriptedExecutor(
191
191
  responses=[
192
- pass_response(order={"quantity": 12}),
193
- pass_response(order={"quantity": 3}),
192
+ pass_response(binding_name_to_value={"order": {"quantity": 12}}),
193
+ pass_response(binding_name_to_value={"order": {"quantity": 3}}),
194
194
  ],
195
195
  )
196
196
  with nh.run(executor):
@@ -199,14 +199,14 @@ def test_quote_batch_processes_each_message_and_uses_host_price():
199
199
 
200
200
 
201
201
  def test_quote_batch_stops_when_quantity_is_unclear():
202
- executor = ScriptedExecutor(responses=[pass_response(order={"quantity": None})])
202
+ executor = ScriptedExecutor(responses=[pass_response(binding_name_to_value={"order": {"quantity": None}})])
203
203
  with nh.run(executor), pytest.raises(ValueError, match="Quantity needs clarification"):
204
204
  quote_batch(["A few, please.", "Then three more."], unit_price_cents=250)
205
205
  assert len(executor.calls) == 1
206
206
 
207
207
 
208
208
  def test_quote_batch_rejects_invalid_model_output():
209
- executor = ScriptedExecutor(responses=[pass_response(order={"quantity": 0})])
209
+ executor = ScriptedExecutor(responses=[pass_response(binding_name_to_value={"order": {"quantity": 0}})])
210
210
  with nh.run(executor), pytest.raises(nh.ExecutionError):
211
211
  quote_batch(["One, please."], unit_price_cents=250)
212
212
  ```
@@ -81,7 +81,7 @@ Presentation is a view of accessible state, not its authority or a replacement f
81
81
 
82
82
  Each Natural block performs one task with declared output bindings and one outcome.
83
83
  There is no implicit model message history between blocks.
84
- Python values, inherited parent working state, and scoped task references supply context to each fresh interaction (see [Patterns: cross-block composition](patterns.md#cross-block-composition)).
84
+ Python lexical values and explicitly scoped task references supply context to each fresh interaction (see [Patterns: cross-block composition](patterns.md#cross-block-composition)).
85
85
 
86
86
  ## Providing data to a block
87
87
 
@@ -150,7 +150,8 @@ An explicit output annotation determines its validation contract at block entry.
150
150
  Without one, the runtime infers the initialized value's type, except for `None` and a plain `object()`; otherwise the output is unconstrained.
151
151
  Annotate collections explicitly when element types matter: `findings: list[Finding] = []` retains its element contract, while `findings = []` selects only `list`.
152
152
  An unresolved explicit annotation fails preparation instead of silently falling back to inference.
153
- All bound declared outputs receive final validation even if the model never assigns them; an initial Raise discards pending outputs.
153
+ The standard executor selects all bound declared outputs for final validation even if the model never assigns them; an initial Raise discards pending outputs.
154
+ Custom executors may supply an explicit complete output selection; see [output selection](executors.md#output-selection).
154
155
  Output contracts constrain values, not the factual correctness of a judgment.
155
156
  See [binding contracts](specification.md#7-natural-dsl-bindings) for annotation acquisition and global/nonlocal writeback.
156
157
 
@@ -401,7 +402,7 @@ Function parameters and working locals are candidates for LOCALS, and explicit m
401
402
 
402
403
  Keep fewer incidental locals alive when they do not help the judgment. A callable passed through a parameter retains its live callable metadata even when the parameter annotation is `object`, `Any`, or absent. Signature and documentation acquisition are best-effort and do not execute application properties or annotation expressions.
403
404
 
404
- Use explicit parameters for essential inputs and independent reuse. Module globals and task injection can supply shared capabilities; inherited working state supplies deliberately shared parent context. These layers preserve their provenance and remain available beyond the initial presentation budget.
405
+ Use explicit parameters for essential inputs and independent reuse. Module globals and task references can supply shared capabilities and context. Parent working values are not copied into children; select values in ordinary Python and supply them through arguments or `nh.scope(task_references=...)`. These layers preserve their provenance and remain available beyond the initial presentation budget.
405
406
 
406
407
  **Note:** Nighthawk also accepts native tools through `nh.scope(tools=[...])`, which exposes functions via the model's native tool-calling interface for the duration of the scope. This path is reserved for cases that need native tool calling, such as strict argument schemas or Pydantic AI tool features. Binding functions are preferred for all other uses because they incur no per-definition token overhead beyond a signature line in the prompt context. See [Runtime configuration](runtime-configuration.md#scoped-tools) and [Specification Section 8.3](specification.md#83-tools-available-to-the-llm).
407
408