nighthawk-python 0.13.0__tar.gz → 0.14.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.
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/.github/workflows/ci.yml +15 -6
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/.github/workflows/docs.yml +8 -2
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/.github/workflows/publish.yml +1 -1
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/CHANGELOG.md +26 -1
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/PKG-INFO +1 -1
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/docs/api.md +48 -4
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/docs/for-coding-agents.md +4 -4
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/docs/patterns.md +4 -4
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/docs/runtime-configuration.md +49 -14
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/docs/specification.md +74 -34
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/docs/verification.md +3 -2
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/pyproject.toml +1 -1
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/__init__.py +8 -5
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/errors.py +15 -1
- nighthawk_python-0.14.0/src/nighthawk/lifecycle.py +129 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/natural/decorator.py +33 -42
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/natural/transform.py +20 -5
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/oversight.py +37 -10
- nighthawk_python-0.14.0/src/nighthawk/runtime/execution_reference.py +13 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/runtime/prompt.py +6 -6
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/runtime/runner.py +285 -187
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/runtime/scoping.py +48 -34
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/runtime/step_context.py +2 -1
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/testing.py +4 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/tools/execution.py +6 -11
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/backends/test_codex.py +15 -3
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/docs/test_docs_architecture.py +32 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/docs/test_prompt_examples.py +2 -1
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/execution/prompt_test_helpers.py +1 -1
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/execution/test_globals_prompt.py +1 -1
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/execution/test_managed_model.py +6 -1
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/execution/test_natural_block_ordering.py +12 -11
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/execution/test_natural_traceback.py +3 -3
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/execution/test_runtime.py +14 -14
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/governance/test_governance.py +5 -5
- nighthawk_python-0.14.0/tests/governance/test_return_expression_policy.py +172 -0
- nighthawk_python-0.14.0/tests/governance/test_step_completion.py +630 -0
- nighthawk_python-0.14.0/tests/governance/test_step_ledger.py +462 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/governance/test_step_results.py +1 -1
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/public/test_composition.py +2 -2
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/public/test_public_api.py +13 -12
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/tools/test_assignment_async.py +7 -6
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/tools/test_declarations.py +10 -10
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/tools/test_provided_async.py +2 -1
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/tools/test_tool_boundary.py +3 -3
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/uv.lock +1 -1
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/.claude/rules/docs.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/.claude/rules/promptfoo.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/.claude/rules/src.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/.claude/rules/tests.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/.claude/settings.json +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/.claude/unset_envs.sh +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/.devcontainer/devcontainer-lock.json +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/.devcontainer/devcontainer.json +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/.devcontainer/postCreateCommand.sh +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/.github/dependabot.yml +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/.gitignore +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/.python-version +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/AGENTS.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/CLAUDE.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/CONTRIBUTING.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/LICENSE +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/README.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/docs/AGENTS.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/docs/assets/nighthawk_logo-128x128.png +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/docs/coding-agent-backends.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/docs/executors.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/docs/index.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/docs/natural-blocks.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/docs/philosophy.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/docs/pydantic-ai-providers.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/docs/quickstart.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/docs/roadmap.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/assertions/__init__.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/assertions/binding_value.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/assertions/outcome_kind.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/assertions/raise_message.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/evidence/2026-03-26-baseline-prompt-ab.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/evidence/2026-03-26-baseline-regression.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/evidence/2026-03-26-baseline-suffix-ab.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/evidence/2026-04-27-runtime-prompt-optimization.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/promptfooconfig-agents.yaml +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/promptfooconfig-luna-sanity.yaml +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/promptfooconfig-prompt-ab.yaml +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/promptfooconfig-suffix-ab.yaml +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/promptfooconfig.yaml +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/prompts/eval_coding_agent.txt +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/prompts/eval_default.txt +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/prompts/eval_legacy_default.txt +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/prompts/eval_mutation_aware.txt +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/prompts/eval_sequenced.txt +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/provider.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/research-result.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/test_cases/binding_operations.yaml +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/test_cases/edge_cases.yaml +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/test_cases/loop_outcomes.yaml +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/test_cases/loop_outcomes_ja.yaml +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/test_cases/multi_step.yaml +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/test_cases/null_handling.yaml +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/test_cases/outcome_kinds.yaml +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/evals/promptfoo/test_cases/tool_selection.yaml +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/mkdocs.yml +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/pyrightconfig.json +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/AGENTS.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/backends/__init__.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/backends/_text_fallback.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/backends/base.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/backends/claude_code_cli.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/backends/claude_code_sdk.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/backends/claude_code_settings.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/backends/codex.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/backends/mcp_boundary.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/backends/mcp_server.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/backends/text_projection.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/backends/tool_bridge.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/composition.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/configuration.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/identifier_path.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/json_renderer.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/natural/__init__.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/natural/blocks.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/resilience/__init__.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/resilience/_budget.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/resilience/_circuit_breaker.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/resilience/_fallback.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/resilience/_retry.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/resilience/_timeout.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/resilience/_vote.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/runtime/__init__.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/runtime/_user_content.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/runtime/async_bridge.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/runtime/step_contract.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/runtime/step_executor.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/runtime/step_result.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/runtime/tool_calls.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/tools/__init__.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/tools/_tool_return_content.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/tools/assignment.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/tools/contracts.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/tools/declarations.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/tools/provided.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/src/nighthawk/ulid.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/AGENTS.md +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/__init__.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/backends/__init__.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/backends/test_claude_code_cli.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/backends/test_claude_code_sdk.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/conftest.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/docs/__init__.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/docs/test_coding_agent_examples.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/execution/__init__.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/execution/stub_executor.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/execution/test_capabilities.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/execution/test_execution_outcome_prompt_fragment.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/execution/test_infer_binding_types.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/execution/test_variables_prompt.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/integration/__init__.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/integration/skip_helpers.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/integration/test_carry_pattern.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/integration/test_claude_code_cli_integration.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/integration/test_claude_code_sdk_integration.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/integration/test_codex_integration.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/integration/test_llm_integration.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/natural/__init__.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/natural/test_blocks.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/natural/test_decorator_globals.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/natural/test_introspection.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/public/__init__.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/public/test_model_configuration.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/public/test_readme_example.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/public/test_usage_meter.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/resilience/__init__.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/resilience/test_budget.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/resilience/test_circuit_breaker.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/resilience/test_composition.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/resilience/test_fallback.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/resilience/test_retry.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/resilience/test_timeout.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/resilience/test_vote.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/test_renderer.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/test_testing.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/tools/__init__.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/tools/test_contracts.py +0 -0
- {nighthawk_python-0.13.0 → nighthawk_python-0.14.0}/tests/tools/test_multimodal_helpers.py +0 -0
|
@@ -19,13 +19,17 @@ jobs:
|
|
|
19
19
|
name: Lint and type check
|
|
20
20
|
runs-on: ubuntu-latest
|
|
21
21
|
steps:
|
|
22
|
-
- uses: actions/checkout@
|
|
22
|
+
- uses: actions/checkout@v7
|
|
23
23
|
with:
|
|
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
28
|
with:
|
|
28
29
|
python-version: "3.13"
|
|
30
|
+
# Same dependency set and cache key as "test (3.13)". Only that job
|
|
31
|
+
# saves the entry; concurrent writers race to reserve the same key.
|
|
32
|
+
save-cache: false
|
|
29
33
|
|
|
30
34
|
- name: Install dependencies
|
|
31
35
|
run: uv sync --all-extras --all-groups
|
|
@@ -48,11 +52,12 @@ jobs:
|
|
|
48
52
|
python-version: ["3.13", "3.14"]
|
|
49
53
|
continue-on-error: ${{ matrix.python-version != '3.13' }}
|
|
50
54
|
steps:
|
|
51
|
-
- uses: actions/checkout@
|
|
55
|
+
- uses: actions/checkout@v7
|
|
52
56
|
with:
|
|
53
57
|
persist-credentials: false
|
|
54
58
|
|
|
55
|
-
|
|
59
|
+
# Sole writer of the per-Python-version dependency cache.
|
|
60
|
+
- uses: astral-sh/setup-uv@v10.0.1
|
|
56
61
|
with:
|
|
57
62
|
python-version: ${{ matrix.python-version }}
|
|
58
63
|
|
|
@@ -67,11 +72,15 @@ jobs:
|
|
|
67
72
|
needs: [lint, test]
|
|
68
73
|
runs-on: ubuntu-latest
|
|
69
74
|
steps:
|
|
70
|
-
- uses: actions/checkout@
|
|
75
|
+
- uses: actions/checkout@v7
|
|
71
76
|
with:
|
|
72
77
|
persist-credentials: false
|
|
73
78
|
|
|
74
|
-
|
|
79
|
+
# "uv build" only resolves the build backend, so a cache entry would add
|
|
80
|
+
# no measurable benefit while colliding with the docs workflow key.
|
|
81
|
+
- uses: astral-sh/setup-uv@v10.0.1
|
|
82
|
+
with:
|
|
83
|
+
enable-cache: false
|
|
75
84
|
|
|
76
85
|
- name: Build sdist and wheel
|
|
77
86
|
run: uv build
|
|
@@ -24,9 +24,15 @@ jobs:
|
|
|
24
24
|
build:
|
|
25
25
|
runs-on: ubuntu-latest
|
|
26
26
|
steps:
|
|
27
|
-
- uses: actions/checkout@
|
|
27
|
+
- uses: actions/checkout@v7
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
# setup-uv publishes no floating major tag since v8, so pin an exact release.
|
|
30
|
+
- uses: astral-sh/setup-uv@v10.0.1
|
|
31
|
+
with:
|
|
32
|
+
python-version: "3.13"
|
|
33
|
+
# The docs group is a subset of the cache "test (3.13)" saves under
|
|
34
|
+
# this key, so restore it here but never overwrite it.
|
|
35
|
+
save-cache: false
|
|
30
36
|
|
|
31
37
|
- name: Install dependencies
|
|
32
38
|
run: uv sync --group docs
|
|
@@ -7,6 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.14.0]
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Scoped `nh.lifecycle.StepLifecycle` delivers typed completion, DSL raise, failure, or interruption records after generated caller assignments. Hosts can record one terminal event and translate failures with explicit exception chaining.
|
|
15
|
+
- `Oversight.inspect_return_expression` approves expressions before core evaluation, await, and return validation.
|
|
16
|
+
- `StepDeliveryError` supports host storage adapters without claiming persistence succeeded.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- `ExecutionReference` and `get_execution_reference` replace the abbreviated identity API. `step_execution_id` identifies each invocation; `source_location` identifies its source. StepContext, inspection, testing observations, terminal records, and spans share this identity.
|
|
21
|
+
- Runtime internal exceptions, including preparation and await failures, now propagate through `ExecutionError.step_failed` with the original exception as cause. Rejection is a classified failure. DSL exceptions remain distinct.
|
|
22
|
+
- Completion tracing follows actual caller assignments. Cancellation retains priority if terminal delivery fails. Delivery errors never retry execution or undo effects.
|
|
23
|
+
- Natural functions preserve original closure cells for nonlocal assignments and source locations for generated execution.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- Lifecycle handlers can rethrow an already-recorded host exception or interruption without replacing its original cause with a self-reference.
|
|
28
|
+
- Host integration guidance distinguishes one delivery attempt from ledger deduplication and explains the validation, await, and rewrite limits of name-only return approval.
|
|
29
|
+
|
|
30
|
+
### Removed
|
|
31
|
+
|
|
32
|
+
- `ExecutionRef`, `get_execution_ref`, and `step_id`, without compatibility aliases. Span attributes use `step.execution.id` and `step.source_location`.
|
|
33
|
+
|
|
10
34
|
## [0.13.0]
|
|
11
35
|
|
|
12
36
|
### Added
|
|
@@ -240,7 +264,8 @@ Invalid initial results fail before oversight; use resilience retries to recover
|
|
|
240
264
|
- Step executor abstraction and provider integration foundation.
|
|
241
265
|
- Core documentation and project scaffolding.
|
|
242
266
|
|
|
243
|
-
[Unreleased]: https://github.com/kurusugawa-computer/nighthawk-python/compare/v0.
|
|
267
|
+
[Unreleased]: https://github.com/kurusugawa-computer/nighthawk-python/compare/v0.14.0...HEAD
|
|
268
|
+
[0.14.0]: https://github.com/kurusugawa-computer/nighthawk-python/compare/v0.13.0...v0.14.0
|
|
244
269
|
[0.13.0]: https://github.com/kurusugawa-computer/nighthawk-python/compare/v0.12.0...v0.13.0
|
|
245
270
|
[0.12.0]: https://github.com/kurusugawa-computer/nighthawk-python/compare/v0.11.0...v0.12.0
|
|
246
271
|
[0.11.0]: https://github.com/kurusugawa-computer/nighthawk-python/compare/v0.10.0...v0.11.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: nighthawk-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.14.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/
|
|
@@ -23,13 +23,14 @@
|
|
|
23
23
|
- StepContextLimits
|
|
24
24
|
- JsonableValue
|
|
25
25
|
- to_jsonable_value
|
|
26
|
-
-
|
|
26
|
+
- ExecutionReference
|
|
27
27
|
- get_capabilities
|
|
28
28
|
- get_step_context
|
|
29
29
|
- get_usage_meter
|
|
30
|
-
-
|
|
30
|
+
- get_execution_reference
|
|
31
31
|
- get_implicit_references
|
|
32
32
|
- get_oversight
|
|
33
|
+
- get_lifecycle
|
|
33
34
|
- get_step_executor
|
|
34
35
|
- get_system_prompt_suffix_fragments
|
|
35
36
|
- get_tools
|
|
@@ -37,6 +38,7 @@
|
|
|
37
38
|
- resilience
|
|
38
39
|
- UsageMeter
|
|
39
40
|
- oversight
|
|
41
|
+
- lifecycle
|
|
40
42
|
|
|
41
43
|
## Errors
|
|
42
44
|
|
|
@@ -104,15 +106,42 @@
|
|
|
104
106
|
- get_step_context
|
|
105
107
|
- step_context_scope
|
|
106
108
|
|
|
109
|
+
## Step Contracts
|
|
110
|
+
|
|
111
|
+
Import these types from `nighthawk.runtime.step_contract` when implementing a custom
|
|
112
|
+
`StepExecutor` or constructing a `nighthawk.testing.StepResponse`.
|
|
113
|
+
`StepKind` describes the allowed outcome kinds, and `StepOutcome` is the union of
|
|
114
|
+
the five outcome models, discriminated by their `kind` field.
|
|
115
|
+
|
|
116
|
+
These models describe executor results before the runner resolves them for
|
|
117
|
+
oversight. In particular, `ReturnStepOutcome.return_expression` holds a Python
|
|
118
|
+
expression that the runner evaluates, whereas `nighthawk.oversight.Return.value`
|
|
119
|
+
holds the evaluated value. Oversight hooks use `nighthawk.oversight.StepResult`.
|
|
120
|
+
|
|
121
|
+
::: nighthawk.runtime.step_contract
|
|
122
|
+
options:
|
|
123
|
+
members:
|
|
124
|
+
- StepKind
|
|
125
|
+
- StepOutcome
|
|
126
|
+
- PassStepOutcome
|
|
127
|
+
- ReturnStepOutcome
|
|
128
|
+
- BreakStepOutcome
|
|
129
|
+
- ContinueStepOutcome
|
|
130
|
+
- RaiseStepOutcome
|
|
131
|
+
|
|
107
132
|
## Tool Contracts
|
|
108
133
|
|
|
109
134
|
::: nighthawk.tools.contracts
|
|
110
135
|
options:
|
|
111
136
|
members:
|
|
112
|
-
-
|
|
137
|
+
- ToolOutcome
|
|
113
138
|
- ToolBoundaryError
|
|
114
|
-
-
|
|
139
|
+
- ToolError
|
|
115
140
|
- ErrorKind
|
|
141
|
+
|
|
142
|
+
::: nighthawk.tools.execution
|
|
143
|
+
options:
|
|
144
|
+
members:
|
|
116
145
|
- ToolResultWrapperToolset
|
|
117
146
|
|
|
118
147
|
## Resilience
|
|
@@ -147,6 +176,7 @@
|
|
|
147
176
|
- Raise
|
|
148
177
|
- StepResult
|
|
149
178
|
- StepCommit
|
|
179
|
+
- ReturnExpression
|
|
150
180
|
- Rewrite
|
|
151
181
|
- Accept
|
|
152
182
|
- Reject
|
|
@@ -155,3 +185,17 @@
|
|
|
155
185
|
- OversightRejectedError
|
|
156
186
|
- StepCommitDecision
|
|
157
187
|
- ToolCallDecision
|
|
188
|
+
|
|
189
|
+
## Lifecycle
|
|
190
|
+
|
|
191
|
+
::: nighthawk.lifecycle
|
|
192
|
+
options:
|
|
193
|
+
members:
|
|
194
|
+
- StepLifecycle
|
|
195
|
+
- StepFinished
|
|
196
|
+
- StepCompleted
|
|
197
|
+
- StepRaised
|
|
198
|
+
- StepFailed
|
|
199
|
+
- StepInterrupted
|
|
200
|
+
- FailureStage
|
|
201
|
+
- StepDeliveryError
|
|
@@ -151,7 +151,7 @@ with nh.run(fast_executor):
|
|
|
151
151
|
- `nh.scope()` must run inside `nh.run()`; it keeps `run_id` and creates a new `scope_id`.
|
|
152
152
|
- Omission or `nh.UNSET` inherits; ordinary values replace and `[]`/`{}` clear collections.
|
|
153
153
|
- Use `nh.Extend([...])` to append suffix fragments and `nh.Merge({...})` to merge implicit references by identity.
|
|
154
|
-
-
|
|
154
|
+
- `oversight` and `lifecycle` accept `None` to clear their hooks; other scope fields reject it.
|
|
155
155
|
- Executor replacement precedes full configuration replacement. Managed Model instances retain identity; external agents own their model selection.
|
|
156
156
|
|
|
157
157
|
## 4. The standard contract shape
|
|
@@ -321,9 +321,9 @@ Error-handling rule:
|
|
|
321
321
|
|
|
322
322
|
Async rule:
|
|
323
323
|
|
|
324
|
-
-
|
|
325
|
-
-
|
|
326
|
-
-
|
|
324
|
+
- Both sync and async Natural functions can call async binding functions through tools; tool expressions await their results.
|
|
325
|
+
- Only an async Natural function may have a final return expression that produces an awaitable. A sync Natural function rejects that final result with `ExecutionError`.
|
|
326
|
+
- Make the Natural function `async` when it needs an awaitable final return expression, not merely because it uses an async binding function.
|
|
327
327
|
|
|
328
328
|
Resilience rule:
|
|
329
329
|
|
|
@@ -224,12 +224,12 @@ Each concurrent Natural block executes independently -- there is no shared messa
|
|
|
224
224
|
|
|
225
225
|
Async natural functions can call sync binding functions, and sync natural functions can reference async binding functions. Nighthawk detects awaitable return values and handles them automatically:
|
|
226
226
|
|
|
227
|
-
-
|
|
228
|
-
-
|
|
227
|
+
- Tool expressions await async binding function results in both sync and async Natural functions before returning them to the LLM.
|
|
228
|
+
- A final return expression may produce an awaitable only in an async Natural function. A sync Natural function rejects an awaitable final return value.
|
|
229
229
|
|
|
230
|
-
|
|
230
|
+
You can therefore use async binding functions through tools without changing a synchronous Natural function into an async function.
|
|
231
231
|
|
|
232
|
-
**Failure mode:** if a sync
|
|
232
|
+
**Failure mode:** if a sync Natural function selects a return expression such as `fetch_result()` and that expression produces an awaitable, Nighthawk raises `ExecutionError`. Make the Natural function `async` to permit an awaitable final return expression. This restriction does not apply when the model calls `fetch_result()` through a tool and writes its resolved result to a binding. See [async execution semantics](specification.md#85-async-execution-model).
|
|
233
233
|
|
|
234
234
|
## Cross-block composition
|
|
235
235
|
|
|
@@ -10,7 +10,8 @@ Use `nh.scope()` to override execution settings within an existing run. Each sco
|
|
|
10
10
|
|
|
11
11
|
```py
|
|
12
12
|
with nh.run(step_executor):
|
|
13
|
-
# Replace the full executor configuration
|
|
13
|
+
# Replace the full executor configuration, including defaults for its omitted fields.
|
|
14
|
+
# Other omitted scope arguments inherit the parent scope values.
|
|
14
15
|
with nh.scope(
|
|
15
16
|
step_executor_configuration=nh.StepExecutorConfiguration(
|
|
16
17
|
model="openai-responses:gpt-5.6-luna",
|
|
@@ -48,7 +49,8 @@ Parameters:
|
|
|
48
49
|
- `step_executor_configuration`: replace the entire configuration.
|
|
49
50
|
- `step_executor`: replace the step executor entirely.
|
|
50
51
|
- `usage_meter`: replace the `UsageMeter` that steps in this scope record into. See [Usage metering](#usage-metering).
|
|
51
|
-
- `oversight`: scope-level synchronous tool-call
|
|
52
|
+
- `oversight`: scope-level synchronous tool-call, return-expression, and resolved step-commit inspection hooks.
|
|
53
|
+
- `lifecycle`: synchronous terminal delivery after caller assignments.
|
|
52
54
|
- `system_prompt_suffix_fragments`: scope-level system suffix fragments.
|
|
53
55
|
- `user_prompt_suffix_fragments`: scope-level user suffix fragments.
|
|
54
56
|
- `implicit_references`: scope-level implicit global references.
|
|
@@ -62,7 +64,7 @@ Composition is selected by each supplied value:
|
|
|
62
64
|
- `nh.Extend(sequence)` appends prompt fragments, tools, or capabilities.
|
|
63
65
|
- `nh.Merge(mapping)` merges implicit references, rejecting a same-name value unless it is the identical Python object.
|
|
64
66
|
|
|
65
|
-
|
|
67
|
+
`oversight` and `lifecycle` accept `None`, which clears their hooks. Other scope fields reject it. `usage_meter` replaces the enclosing meter without forwarding totals. Resolution errors leave the parent context intact.
|
|
66
68
|
|
|
67
69
|
The context manager yields the resolved `StepExecutor` for the scope.
|
|
68
70
|
|
|
@@ -118,13 +120,13 @@ from pydantic_ai import RunContext
|
|
|
118
120
|
from pydantic_ai.tools import Tool
|
|
119
121
|
|
|
120
122
|
|
|
121
|
-
def
|
|
123
|
+
def read_step_execution_id(run_context: RunContext[nh.StepContext]) -> str:
|
|
122
124
|
"""Return the current step Id."""
|
|
123
|
-
return run_context.deps.
|
|
125
|
+
return run_context.deps.execution_reference.step_execution_id or ""
|
|
124
126
|
|
|
125
127
|
|
|
126
128
|
with nh.run(step_executor):
|
|
127
|
-
with nh.scope(tools=[
|
|
129
|
+
with nh.scope(tools=[read_step_execution_id, Tool(lookup_user, name="find_user")]):
|
|
128
130
|
triage_issue(ticket_text)
|
|
129
131
|
```
|
|
130
132
|
|
|
@@ -152,7 +154,7 @@ with nh.run(step_executor):
|
|
|
152
154
|
triage_issue(ticket_text)
|
|
153
155
|
```
|
|
154
156
|
|
|
155
|
-
Use capabilities to observe, gate, or instrument model requests with Pydantic AI's own hook vocabulary (`before_model_request`, `after_model_request`, `wrap_model_request`, and the rest of `AbstractCapability`). Nighthawk's `oversight` covers
|
|
157
|
+
Use capabilities to observe, gate, or instrument model requests with Pydantic AI's own hook vocabulary (`before_model_request`, `after_model_request`, `wrap_model_request`, and the rest of `AbstractCapability`). Nighthawk's `oversight` covers tool calls, return-expression approval, and resolved step commits; the model request boundary belongs to Pydantic AI. Use `nh.Extend([capability])` to append capabilities; a plain list replaces them. Repeated capability entries are preserved.
|
|
156
158
|
|
|
157
159
|
## Prompt suffix fragments in scopes
|
|
158
160
|
|
|
@@ -204,6 +206,7 @@ Within an active `nh.run()` context, snapshot getters expose the current scope's
|
|
|
204
206
|
- `nh.get_user_prompt_suffix_fragments()` returns the user prompt suffix fragments as a `tuple[str, ...]`.
|
|
205
207
|
- `nh.get_tools()` returns the scoped native tools as a `tuple[Tool[StepContext], ...]`, excluding built-in tools.
|
|
206
208
|
- `nh.get_capabilities()` returns the scoped Pydantic AI capabilities as a tuple.
|
|
209
|
+
- `nh.get_lifecycle()` returns the active `StepLifecycle`, or `None`.
|
|
207
210
|
- `nh.get_oversight()` returns the active `Oversight`, or `None` when none is installed.
|
|
208
211
|
|
|
209
212
|
The prompt suffix getters return only fragments accumulated via `nh.scope(...)`; configuration-level baseline fragments from `StepExecutorConfiguration` are not included.
|
|
@@ -219,7 +222,36 @@ with nh.run(step_executor):
|
|
|
219
222
|
triage_issue(ticket_text)
|
|
220
223
|
```
|
|
221
224
|
|
|
222
|
-
|
|
225
|
+
All getters listed above, including `nh.get_oversight()`, require an active run context. Outside `nh.run()` they raise `NighthawkError`, matching `nh.get_step_executor()` semantics. Catch `NighthawkError` if a helper needs to detect the absence of a run.
|
|
226
|
+
|
|
227
|
+
## Record completed executions
|
|
228
|
+
|
|
229
|
+
Install `nh.lifecycle.StepLifecycle` to record actual execution endings, including preparation, validation, and return-await failures. The callback runs after generated assignments and can raise a host exception referring to its stored record. Return-expression approval is available separately through `Oversight.inspect_return_expression`; core retains evaluation and validation.
|
|
230
|
+
|
|
231
|
+
```python
|
|
232
|
+
import nighthawk as nh
|
|
233
|
+
|
|
234
|
+
execution_id_to_event: dict[str, nh.lifecycle.StepFinished] = {}
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def record_finished(event: nh.lifecycle.StepFinished) -> None:
|
|
238
|
+
execution_id = event.execution_reference.step_execution_id
|
|
239
|
+
assert execution_id is not None
|
|
240
|
+
execution_id_to_event[execution_id] = event
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
# Inside an active nh.run(executor):
|
|
244
|
+
with nh.scope(lifecycle=nh.lifecycle.StepLifecycle(record_finished)):
|
|
245
|
+
result = my_natural_function()
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
This example is an in-memory history. Durable storage, serialization, and deduplication belong to the host. Callback failures do not roll back assignments or retry execution. See [terminal delivery semantics](specification.md#104-terminal-delivery-and-host-ledgers) for exception chaining, cancellation, and storage failure handling.
|
|
249
|
+
|
|
250
|
+
For a host ledger, use the executor boundary for admission and execution accounting, `inspect_step_commit` for approval before assignment, and StepLifecycle for terminal recording and exception translation. Correlate them with `execution_reference.step_execution_id`, which is unique per invocation; `source_location` only groups executions of the same source block. Preparation failures may have no admission record.
|
|
251
|
+
|
|
252
|
+
If an earlier host boundary already stored a failure and raised its public exception, the lifecycle handler still receives StepFailed. Skip a duplicate append only after verifying that exception refers to the stored event for this same execution, then rethrow the same exception. Core preserves its original cause. Merely returning from the handler results in an ExecutionError wrapper; suppressing all exceptions of the host type would incorrectly omit parent events for failed nested executions.
|
|
253
|
+
|
|
254
|
+
At a host-controlled admission boundary, `nh.get_lifecycle() is expected_lifecycle` can verify that the required callback is configured. If it has been cleared, record the bypass through that still-active boundary: the missing lifecycle cannot record its own absence. Delivery is one in-process attempt with a configured handler, not guaranteed persistence. A callback exception after successful assignment propagates without undoing writes; host delivery-failure and anomaly records are separate from the completed core record. The full rules are in [terminal delivery semantics](specification.md#104-terminal-delivery-and-host-ledgers).
|
|
223
255
|
|
|
224
256
|
## Synchronous oversight in scopes
|
|
225
257
|
|
|
@@ -256,7 +288,9 @@ Acceptance preserves validated values without repeating validators. Replacements
|
|
|
256
288
|
|
|
257
289
|
Inspection mappings are shallow read-only reference views: their entries retain Python types and identity. Trusted hooks must not mutate referenced objects; use `Rewrite`. Copy or serialize explicitly for durable history. Rejection cannot roll back effects of tools, validators, or return expressions. See [Specification](specification.md#102-host-commit-boundary) for the complete contract.
|
|
258
290
|
|
|
259
|
-
Tool rejections are returned to the model as a recoverable observation. On preview-based paths this appears with `error.kind == "oversight"` in the projected preview; provider-backed paths that use Pydantic AI's standard retry loop may instead surface the same structured details as a retry prompt whose final line is compact JSON. Step rejections raise `nh.oversight.OversightRejectedError
|
|
291
|
+
Tool rejections are returned to the model as a recoverable observation. On preview-based paths this appears with `error.kind == "oversight"` in the projected preview; provider-backed paths that use Pydantic AI's standard retry loop may instead surface the same structured details as a retry prompt whose final line is compact JSON. Step rejections produce a failed terminal record and raise `nh.ExecutionError` chained from `nh.oversight.OversightRejectedError`, unless the lifecycle callback supplies a host exception. For the normative boundary rule on which tool-call failures are projected back to the model versus propagated as host exceptions, see [Specification Section 8.3](specification.md#83-tools-available-to-the-llm).
|
|
292
|
+
|
|
293
|
+
For return approval, a host may parse `ReturnExpression.expression` and permit only a bare name present in `validated_binding_name_to_value`. Declaration alone does not prove that this candidate supplied a validated value. This policy does not skip return validation, prevent awaiting an awaitable binding, or keep the return synchronized with later binding rewrites. Arbitrary constants also bypass write bindings. Keep `deny: [return]` if the host's value policy has not admitted these behaviors; see [return approval semantics](specification.md#103-return-expression-approval).
|
|
260
294
|
|
|
261
295
|
## Caller-authenticated models
|
|
262
296
|
|
|
@@ -326,13 +360,14 @@ See [Specification Section 8.2](specification.md#82-prompt-context) for the full
|
|
|
326
360
|
|
|
327
361
|
## Runtime execution identity
|
|
328
362
|
|
|
329
|
-
Each `nh.run()` generates an `
|
|
363
|
+
Each `nh.run()` generates an `ExecutionReference` with a unique `run_id` (trace root) and `scope_id`. Nested `nh.scope()` calls generate new `scope_id` values while keeping the same `run_id`.
|
|
330
364
|
|
|
331
365
|
```py
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
366
|
+
execution_reference = nh.get_execution_reference()
|
|
367
|
+
execution_reference.run_id # trace root -- stable across nested scopes
|
|
368
|
+
execution_reference.scope_id # current scope -- changes with each nh.scope()
|
|
369
|
+
execution_reference.step_execution_id # Unique per invocation; None outside a step
|
|
370
|
+
execution_reference.source_location # Source module and line; None outside a step
|
|
336
371
|
```
|
|
337
372
|
|
|
338
373
|
Use `run_id` to correlate distributed agent processes in logs and traces. Use `scope_id` to identify the current logical execution context. See [Specification Section 10](specification.md#10-runtime-scoping) for the full specification and [Verification: observability](verification.md#observability) for tracing integration.
|