From 212f95f79d81b73c6f3381542069ab8f111e6fea Mon Sep 17 00:00:00 2001 From: Simone Carolini Date: Thu, 22 Oct 2026 23:04:46 +0200 Subject: [PATCH] docs(boundary): the executor sets TASK_ATTEMPT on every production Job The python-node env contract lists TASK_ATTEMPT, the 0-based number of the task's attempt (0 on the first run, 1 on the first retry). The executor sets it on dbt and python Jobs alike; the harness does not read it, a node script may. Co-Authored-By: Claude Opus 5.5 Signed-off-by: Simone Carolini --- CHANGELOG.md | 7 +++++++ docs/boundary-contract.md | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9758e5a..1d060db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [Unreleased] +### Changed + +- The python-node env contract in `docs/boundary-contract.md` lists + `TASK_ATTEMPT`, the 0-based number of the task's attempt, which the executor + sets on every production Job. The harness does not read it; a node script + may. Documentation only: no package changes. + ## [0.10.0] - 2026-10-22 ### Added diff --git a/docs/boundary-contract.md b/docs/boundary-contract.md index cce1fd9..74eb205 100644 --- a/docs/boundary-contract.md +++ b/docs/boundary-contract.md @@ -425,6 +425,7 @@ inject the names below instead: | `NODE_ID` | **required** | Any identifier whose trailing two dot-separated segments MUST be `.` of the declared node (e.g. `python-node...
`); the harness splits on `.` and matches the last two segments against the merged contract's nodes. | | `TABLE_NAME` | **required** | The target table name; must match the `table` of the node selected via `NODE_ID`. | | `TARGET_SCHEMA` | **required** | The target schema name; must match the `schema` of the node selected via `NODE_ID`. There is no fallback — `SCHEMA` and `DBT_TARGET_SCHEMA` are **not** recognized. | +| `TASK_ATTEMPT` | set by the executor, not read by the harness | The 0-based number of the task's attempt: `0` on a task's first run, `1` on its first retry, and so on. The executor sets it on every production Job, dbt and python alike, so a node script can read it; the harness neither requires nor interprets it. | | `CONTRACT_DIR` | optional | Path to the directory of merged contract YAML files baked into the image. Defaults to `/app/contracts`. | | `APP_ROOT` | optional | Repository root the node's `script:` path is resolved against. Defaults to `CONTRACT_DIR`'s parent directory. | | engine-native vars | **required**, per adapter | Whatever the installed `WarehouseAdapter.required_env()` declares (e.g. `POSTGRES_HOST`/`POSTGRES_DB`/`POSTGRES_USER`, optionally `POSTGRES_PORT`/`POSTGRES_PASSWORD`) — missing any of these is a `LoadError`. | @@ -433,7 +434,8 @@ The executor's python-kind dispatch (continuo PR 8) **must** inject `NODE_ID`/`TABLE_NAME`/`TARGET_SCHEMA` under exactly these names; they intentionally differ from the dbt job env (`SCHEMA`/`DBT_TARGET_SCHEMA`/dbt `UniqueID`) because the python-node harness has a different selection model -(a merged contract keyed by `schema.table`, not a dbt manifest node). +(a merged contract keyed by `schema.table`, not a dbt manifest node). It also +sets `TASK_ATTEMPT` on the same Jobs, under the same name as on a dbt Job. ## 13.5 Surface 5 — what the domain repo's CI/CD does per merge