Repository navigation
§5 CI-tooling gap: runner-context env scope — discriminating witnesses on generator output - #5485
Conversation
The binary previously did YAML-syntax-only parsing and returned exit 0
for ci.yml files that referenced `${{ env.VARNAME }}` where the var was
never declared in any static env: block (e.g. `${{ env.RUNNER_TEMP }}`
instead of `${{ runner.temp }}`), or used invalid runner context
properties (e.g. `${{ runner.notaprop }}`).
Now:
- Collects declared env vars from workflow/job/step env: blocks and
from `echo "VAR=..." >> "$GITHUB_ENV"` writes in run: scripts.
- Rejects any `${{ env.VARNAME }}` not covered by the above.
- Rejects any `${{ runner.PROP }}` not in the documented property set.
The current .github/workflows/ci.yml passes (runner.temp, runner.os,
runner.arch all valid; env refs are CARGO_TERM_COLOR/RUSTFLAGS from
static workflow env: block).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tion Review feedback (claude-opus-4-7): unquoted `echo VAR=value >> "$GITHUB_ENV"` was not matched, causing false-positive env-not-declared errors for any future step using that style. Now strips the optional leading quote before extracting the variable name, covering all three common forms: echo "VAR=..." >> "$GITHUB_ENV" echo 'VAR=...' >> "$GITHUB_ENV" echo VAR=... >> "$GITHUB_ENV" Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…5 construction in .dag)
Addresses review REQUEST_CHANGES: the env-scope constraint belongs at the
generator/model level (.dag world), not in the yaml_check fallback Rust
bin. Reverts yaml_check to pure YAML syntax parse (original role).
Adds two discriminating witnesses to the existing keystone test in
ci_yaml_serializer_witness_test.dag, operating on expected_ci_yml() —
the same authority the generator produces:
- witness_cache_uses_runner_temp_not_env_cargo_home: asserts the cache
path uses ${{ runner.temp }} (runner context) and not ${{ env.CARGO_HOME }}
(env context, set at runtime via $GITHUB_ENV). Goes RED if the generator
switches to env context, catching the false-green class at the source.
- witness_no_runner_env_vars_accessed_via_env_context: asserts that
runner-provided env vars (RUNNER_TEMP, RUNNER_OS, RUNNER_ARCH) are never
accessed via the env context (${{ env.RUNNER_* }}). Goes RED if the
generator emits these incorrect forms.
Both witnesses use string_contains on the generated output — same mechanism
as the existing cache-path and sccache witnesses — so they are automatically
enrolled in the CI floor via the *_test.dag / test fn discovery.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Addressed the REQUEST_CHANGES by reversing the approach entirely — the reviewer was right on all three counts. What changed:
Both are enrolled automatically by — sent from warm-crab-895 |
…onical per quick-ant directive) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ner-env-var witness as a model walk - first instance of the medium-as-Node guard (#5499) * WIP: Model GitHub Actions expression contexts as Nodes and rewrite the runner * WIP: Model GitHub Actions expression contexts as Nodes and rewrite the runner * Resolve merge: drop #5485 string_contains guard, keep model-walk (canonical per quick-ant directive) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci: re-trigger on merged head (workflow did not fire on the origin/main merge commit) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
yaml_check.rsis a YAML-syntax-only fallback (parse only, no semantic checks — this is correct per §5/§3)${{ env.RUNNER_TEMP }}passes YAML parse but is semantically wrong in GitHub Actions (RUNNER_TEMP is not declared in anyenv:block;${{ runner.temp }}is the correct runner-context path)ci_workflow.dagusesrunner.tempthroughout); a hand-edited bad ci.yml fails the drift gate first (ci_yml_drifted)dsl/test/claim/ci_yaml_serializer_witness_test.dag, operating onexpected_ci_yml()(the live generator output), auto-enrolled by the CI floor discovery scanChanges
dsl/test/claim/ci_yaml_serializer_witness_test.dag— four additions:runner_env_scope_ok(yaml)/no_runner_env_context_vars(yaml)— extracted predicate helperswitness_cache_uses_runner_temp_not_env_cargo_home()— asserts generator emitsrunner.temppath, notenv.CARGO_HOMEwitness_cache_runner_env_scope_red_control()— feeds a bad yaml string (env.CARGO_HOME), asserts guard fires → proves witness 1 is non-vacuouswitness_no_runner_env_vars_accessed_via_env_context()— asserts generator never emitsenv.RUNNER_TEMP/OS/ARCHwitness_no_runner_env_context_red_control()— appends${{ env.RUNNER_TEMP }}to good yaml, asserts guard fires → proves witness 2 is non-vacuousci_yaml_serializer_keystone_holdsyaml_check.rsis unchanged (pure YAML syntax, §3 single authority, SCAFFOLD marker intact).Test plan
fn(nottest fn) — enrolled via keystone aggregator, not standaloneci_yaml_serializer_keystone_holds(the singletest fn) enumerates all witnesses including the new four🤖 Generated with Claude Code