Skip to content

feat(lang): variables as a parameter; TINI for any decidable variable set - #13

Merged
hyperpolymath merged 1 commit into
mainfrom
claude/n-variables
Oct 27, 2026
Merged

hyperpolymath merged 1 commit into
mainfrom
claude/n-variables

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Summary

Closes the "multiple variables" item of PROOF-STATUS's Open list. The fragment had two variables, lo and hi, fixed in SecretTypes.Lang, so a consumer could not add one. Lintel needed exactly that: its L-7 had only the corollary half (two incomparable fields, so no typed command moves anything between them), and its coalition TINI had no variable the coalition cannot see, so it said no more than determinism. The consumer change is metadatastician/lintel#17.

The variables are now a record, like the lattice: SecretTypes.Vars (a type and decidable equality), the first module parameter of Lang, Typing.Generic, Noninterference.Statement and Noninterference.Generic.

Changes

  • src/SecretTypes/Vars.agda (new): record Vars with Var and _≟ᵥ_.
  • src/SecretTypes/Lang.agda: parameterised by 𝓥 : Vars; a store is Var → Nat; update compares each variable with the written one.
  • src/SecretTypes/Noninterference/Generic.agda: the proof changes in two lemmas only, confine-assign and tini-assign, which split on x ≟ᵥ y instead of on lo/hi. That is the only use of the variables' structure.
  • src/SecretTypes/Lang/Two.agda (new): the two-variable instance (lo, hi, ⟨_,_⟩, low, high, _≈_). Typing, Noninterference, Witness, Countermodels and the two reject fixtures import it; their content is unchanged.
  • tests/reject/ThirdVariable.agda (new): the rules at three variables refuse a flow into a third.
  • PROOF-STATUS.adoc: fragment restated, N-7 widened to every Vars, "multiple variables" removed from Open. README.adoc and docs/README-section.adoc follow.

RSR Quality Checklist

Required

  • Tests pass: scripts/check.sh → PASS: core proofs and all 3 expected rejections; scripts/minimal-laws.sh → PASS: minimal-laws certificate (3 laws, each needed) (Agda 2.6.4.3, the CI pin).
  • Code is formatted (matches the surrounding modules).
  • Linter is clean: -W error, no warnings.
  • No banned language patterns.
  • No unsafe blocks.
  • No banned functions: no postulates (the gate's trusted-base check passes).
  • SPDX headers present on the three new files.
  • No secrets.

As Applicable

  • Documentation updated: PROOF-STATUS, README.
  • CHANGELOG: not touched.

Testing

Both gates locally, as above. ThirdVariable was first refused for the wrong reason (its _≟_ clashed with the Prelude's), which the gate caught as an unexpected failure; renamed. Its corrected form (c ≔ var a) is accepted, as the negative control.

Downstream: Lintel's full gate passes against this commit fetched fresh by its pin (PASS: Lintel proofs, 5 positive control(s), 4 expected rejection(s), negative control).

Breaking for consumers: SecretTypes.Lang is now a parameterised module, so open import SecretTypes.Lang becomes SecretTypes.Lang.Two (or SecretTypes.Lang 𝓥), and Noninterference.Generic 𝓛 label becomes Noninterference.Generic 𝓥 𝓛 label. Lintel is the only consumer I know of, and it pins by commit.


Generated by Claude Code

… set

The fragment had two variables, lo and hi, fixed in SecretTypes.Lang, so a
consumer could not add a variable: Lintel's L-7 needed a client-only sink
and its coalition TINI had no variable the coalition cannot see (Lintel
README L-7, A-1; PROOF-STATUS Open, "multiple variables").

The variables are now a record, SecretTypes.Vars (a type and decidable
equality), and SecretTypes.Lang, Typing.Generic, Noninterference.Statement
and Noninterference.Generic take it as their first module parameter, as
they take the Lattice.  A store is a function Var → Nat and update compares
each variable with the written one.  The proof changes in two lemmas only,
confine-assign and tini-assign, which now split on x ≟ᵥ y instead of on
lo/hi; that is the only use of the variables' structure.

SecretTypes.Lang.Two is the two-variable instance (lo, hi, ⟨_,_⟩, low,
high, _≈_), and the two-point development (Typing, Noninterference,
Witness, Countermodels, tests/reject) is unchanged in content and now
imports it.  tests/reject/ThirdVariable checks the rules at three
variables; its corrected form is accepted (checked locally as the
negative control).

Gates, Agda 2.6.4.3:
  scripts/check.sh:        PASS: core proofs and all 3 expected rejections
  scripts/minimal-laws.sh: PASS: minimal-laws certificate (3 laws, each needed)

PROOF-STATUS: fragment restated, N-7 widened to every Vars, "multiple
variables" removed from Open.  README and its section copy follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BYbQRtNu216R13jtZLmoqs
@coderabbitai

coderabbitai Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 435fcfc5-5e35-4743-af83-e4e67466a7cf
Commits

Reviewing files that changed from the base of the PR and between 7736da2 and ee01db4.

Files selected for processing: 17
  • PROOF-STATUS.adoc
  • README.adoc
  • docs/README-section.adoc
  • src/SecretTypes/All.agda
  • src/SecretTypes/Countermodels.agda
  • src/SecretTypes/Lang.agda
  • src/SecretTypes/Lang/Two.agda
  • src/SecretTypes/Noninterference.agda
  • src/SecretTypes/Noninterference/Generic.agda
  • src/SecretTypes/Noninterference/Statement.agda
  • src/SecretTypes/Typing.agda
  • src/SecretTypes/Typing/Generic.agda
  • src/SecretTypes/Vars.agda
  • src/SecretTypes/Witness.agda
  • tests/reject/ExplicitFlow.agda
  • tests/reject/ImplicitFlow.agda
  • tests/reject/ThirdVariable.agda

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

Recent review details
Context from checks skipped due to timeout: 17
  • GitHub Check: call-estate-audit / estate-audit
  • GitHub Check: Validate K9 contracts
  • GitHub Check: 🔴 GATE: Empty-linter (invisible characters)
  • GitHub Check: Patch Bridge CVE triage
  • GitHub Check: Hypatia neurosymbolic scan
  • GitHub Check: analyze (actions, none)
  • GitHub Check: 🔴 GATE: Empty-linter (invisible characters)
  • GitHub Check: Dogfooding compliance summary
  • GitHub Check: 🟡 CHECK: Groove manifest check
  • GitHub Check: panic-attack assail
  • GitHub Check: Validate DEED manifests
  • GitHub Check: RSR oracle — dogfood this repo
  • GitHub Check: estate-rules
  • GitHub Check: 🟡 CHECK: Validate K9 contracts
  • GitHub Check: Validate DEED manifests
  • GitHub Check: openssf-compliance
  • GitHub Check: Core proofs, countermodels, expected rejections, minimal-laws certificate
CI failures not shown inline: 17

GitHub Actions: OpenSSF Compliance / 0_openssf-compliance.txt: feat(lang): variables as a parameter; TINI for any decidable variable set

Conclusion: failure

View job details

##[group]Run SECFILE=""
 �[36;1mSECFILE=""�[0m
 �[36;1m[ -f "SECURITY.md" ] && SECFILE="SECURITY.md"�[0m
 �[36;1m[ -f "SECURITY.adoc" ] && SECFILE="SECURITY.adoc"�[0m
 �[36;1m[ -f ".github/SECURITY.md" ] && SECFILE=".github/SECURITY.md"�[0m
 �[36;1m�[0m
 �[36;1mif [ -z "$SECFILE" ]; then�[0m
 �[36;1m  echo "::error::SECURITY.md (or SECURITY.adoc) is required for OpenSSF Best Practices"�[0m
 �[36;1m  exit 1�[0m
 �[36;1mfi�[0m
 �[36;1m�[0m
 �[36;1mLINES=$(wc -l < "$SECFILE")�[0m
 �[36;1mif [ "$LINES" -lt 10 ]; then�[0m
 �[36;1m  echo "::error::$SECFILE has only $LINES lines — must have >10 lines of substantive content"�[0m
...
 ##[group]Run if [ ! -f "LICENSE" ] && [ ! -f "LICENSE.txt" ] && [ ! -f "LICENSE.md" ]; then
 �[36;1mif [ ! -f "LICENSE" ] && [ ! -f "LICENSE.txt" ] && [ ! -f "LICENSE.md" ]; then�[0m
 �[36;1m  echo "::error::LICENSE file is required for OpenSSF Best Practices"�[0m
...
 ##[group]Run if [ ! -f "CONTRIBUTING.md" ] && [ ! -f "CONTRIBUTING.adoc" ] \
 �[36;1mif [ ! -f "CONTRIBUTING.md" ] && [ ! -f "CONTRIBUTING.adoc" ] \�[0m
 �[36;1m   && [ ! -f ".github/CONTRIBUTING.md" ] && [ ! -f ".github/CONTRIBUTING.adoc" ]; then�[0m
 �[36;1m  echo "::error::CONTRIBUTING file is required for OpenSSF Best Practices"�[0m
...
 ##[group]Run if [ ! -f "README.md" ] && [ ! -f "README.adoc" ] && [ ! -f "README.rst" ] && [ ! -f "README.txt" ] && [ ! -f "README" ]; then
 �[36;1mif [ ! -f "README.md" ] && [ ! -f "README.adoc" ] && [ ! -f "README.rst" ] && [ ! -f "README.txt" ] && [ ! -f "README" ]; then�[0m
 �[36;1m  echo "::error::README file is required for OpenSSF Best Practices"�[0m
...
 ##[group]Run if [ ! -d ".machine_readable" ]; then
 �[36;1mif [ ! -d ".machine_readable" ]; then�[0m
 �[36;1m  echo "::error::.machine_readable/ directory is required"�[0m
 �[36;1m  exit 1�[0m
 �[36;1mfi�[0m
 �[36;1m�[0m
 �[36;1mif [ ! -f ".machine_readable/descriptiles/STATE.a2ml" ]; then�[0m
 �[36;1m  echo "::error::.machine_readable/descriptiles/STATE.a2ml is required"�[0m
...
 ...

GitHub Actions: OpenSSF Compliance / openssf-compliance: feat(lang): variables as a parameter; TINI for any decidable variable set

Conclusion: failure

View job details

##[group]Run SECFILE=""
 �[36;1mSECFILE=""�[0m
 �[36;1m[ -f "SECURITY.md" ] && SECFILE="SECURITY.md"�[0m
 �[36;1m[ -f "SECURITY.adoc" ] && SECFILE="SECURITY.adoc"�[0m
 �[36;1m[ -f ".github/SECURITY.md" ] && SECFILE=".github/SECURITY.md"�[0m
 �[36;1m�[0m
 �[36;1mif [ -z "$SECFILE" ]; then�[0m
 �[36;1m  echo "::error::SECURITY.md (or SECURITY.adoc) is required for OpenSSF Best Practices"�[0m
 �[36;1m  exit 1�[0m
 �[36;1mfi�[0m
 �[36;1m�[0m
 �[36;1mLINES=$(wc -l < "$SECFILE")�[0m
 �[36;1mif [ "$LINES" -lt 10 ]; then�[0m
 �[36;1m  echo "::error::$SECFILE has only $LINES lines — must have >10 lines of substantive content"�[0m

GitHub Actions: OpenSSF Compliance / openssf-compliance: feat(lang): variables as a parameter; TINI for any decidable variable set

Conclusion: failure

View job details

##[group]Run if [ ! -f "LICENSE" ] && [ ! -f "LICENSE.txt" ] && [ ! -f "LICENSE.md" ]; then
 �[36;1mif [ ! -f "LICENSE" ] && [ ! -f "LICENSE.txt" ] && [ ! -f "LICENSE.md" ]; then�[0m
 �[36;1m  echo "::error::LICENSE file is required for OpenSSF Best Practices"�[0m

GitHub Actions: OpenSSF Compliance / openssf-compliance: feat(lang): variables as a parameter; TINI for any decidable variable set

Conclusion: failure

View job details

##[group]Run if [ ! -f "CONTRIBUTING.md" ] && [ ! -f "CONTRIBUTING.adoc" ] \
 �[36;1mif [ ! -f "CONTRIBUTING.md" ] && [ ! -f "CONTRIBUTING.adoc" ] \�[0m
 �[36;1m   && [ ! -f ".github/CONTRIBUTING.md" ] && [ ! -f ".github/CONTRIBUTING.adoc" ]; then�[0m
 �[36;1m  echo "::error::CONTRIBUTING file is required for OpenSSF Best Practices"�[0m

GitHub Actions: OpenSSF Compliance / openssf-compliance: feat(lang): variables as a parameter; TINI for any decidable variable set

Conclusion: failure

View job details

##[group]Run if [ ! -f "README.md" ] && [ ! -f "README.adoc" ] && [ ! -f "README.rst" ] && [ ! -f "README.txt" ] && [ ! -f "README" ]; then
 �[36;1mif [ ! -f "README.md" ] && [ ! -f "README.adoc" ] && [ ! -f "README.rst" ] && [ ! -f "README.txt" ] && [ ! -f "README" ]; then�[0m
 �[36;1m  echo "::error::README file is required for OpenSSF Best Practices"�[0m

GitHub Actions: OpenSSF Compliance / openssf-compliance: feat(lang): variables as a parameter; TINI for any decidable variable set

Conclusion: failure

View job details

##[group]Run if [ ! -d ".machine_readable" ]; then
 �[36;1mif [ ! -d ".machine_readable" ]; then�[0m
 �[36;1m  echo "::error::.machine_readable/ directory is required"�[0m
 �[36;1m  exit 1�[0m
 �[36;1mfi�[0m
 �[36;1m�[0m
 �[36;1mif [ ! -f ".machine_readable/descriptiles/STATE.a2ml" ]; then�[0m
 �[36;1m  echo "::error::.machine_readable/descriptiles/STATE.a2ml is required"�[0m

GitHub Actions: OpenSSF Compliance / openssf-compliance: feat(lang): variables as a parameter; TINI for any decidable variable set

Conclusion: failure

View job details

##[group]Run if [ ! -f "CHANGELOG.md" ] && [ ! -f "CHANGELOG.adoc" ] && [ ! -f "CHANGES.md" ]; then
 �[36;1mif [ ! -f "CHANGELOG.md" ] && [ ! -f "CHANGELOG.adoc" ] && [ ! -f "CHANGES.md" ]; then�[0m
 �[36;1m  echo "::error::CHANGELOG.md is required for OpenSSF Best Practices"�[0m

GitHub Actions: OpenSSF Compliance / openssf-compliance: feat(lang): variables as a parameter; TINI for any decidable variable set

Conclusion: failure

View job details

##[group]Run bash scripts/check-no-placeholders.sh .
 �[36;1mbash scripts/check-no-placeholders.sh .�[0m
 shell: /usr/bin/bash -e {0}
 ##[endgroup]
 FAIL: 90 file(s) contain unfilled {{PLACEHOLDER}} tokens:
   - .clinerules: {{AUTHOR_EMAIL}} {{AUTHOR}} {{CURRENT_YEAR}} {{OWNER}}
   - .cursorrules: {{AUTHOR_EMAIL}} {{AUTHOR}} {{CURRENT_YEAR}} {{OWNER}}
   - .devcontainer/Containerfile: {{AUTHOR_EMAIL}} {{AUTHOR}} {{CURRENT_YEAR}} {{OWNER}} {{PROJECT_NAME}}
   - .devcontainer/README.adoc: {{AUTHOR_EMAIL}} {{AUTHOR}} {{PROJECT_NAME}}
   - .devcontainer/devcontainer.json: {{AUTHOR_EMAIL}} {{AUTHOR}} {{CURRENT_YEAR}} {{OWNER}} {{PROJECT_NAME}}
   - .envrc: {{PROJECT_NAME}}
   - .github/CODE_OF_CONDUCT.md: {{CONDUCT_EMAIL}} {{CONDUCT_TEAM}} {{CURRENT_YEAR}} {{RESPONSE_TIME}}
   - .github/CONTRIBUTING.md: {{MAIN_BRANCH}}
   - .github/GOVERNANCE.md: {{CURRENT_YEAR}} {{OWNER}} {{PROJECT_NAME}}
   - .github/ISSUE_TEMPLATE/config.yml: {{FORGE}} {{OWNER}} {{REPO}}
   - .github/SECURITY.md: {{CURRENT_YEAR}} {{SECURITY_EMAIL}}
   - .github/SUPPORT.md: {{OWNER}} {{REPO}}
   - .github/copilot-instructions.md: {{AUTHOR_EMAIL}} {{AUTHOR}} {{CURRENT_YEAR}} {{OWNER}}
   - .machine_readable/ENSAID_CONFIG.a2ml: {{AUTHOR_EMAIL}} {{AUTHOR}} {{CURRENT_YEAR}} {{OWNER}} {{PROJECT_NAME}}
   - .machine_readable/bot_directives/coverage.a2ml: {{AUTHOR_EMAIL}} {{AUTHOR}} {{CURRENT_DATE}} {{CURRENT_YEAR}} {{OWNER}}
   - .machine_readable/bot_directives/debt.a2ml: {{AUTHOR_EMAIL}} {{AUTHOR}} {{CURRENT_DATE}} {{CURRENT_YEAR}} {{OWNER}}
   - .machine_readable/bot_directives/methodology.a2ml: {{AUTHOR_EMAIL}} {{AUTHOR}} {{CURRENT_DATE}} {{CURRENT_YEAR}} {{OWNER}} {{PROJECT_UNIQUE_STRENGTH}} {{PROJECT}}
   - .machine_readable/coaptation/witness-map.ncl: {{PROJECT_NAME}}
   - .machine_readable/compliance/reuse/dep5: {{AUTHOR_EMAIL}} {{AUTHOR}} {{CURRENT_YEAR}} {{OWNER}} {{PROJECT_NAME}} {{REPO}}
   - .machine_readable/configs/eclexiaiser.toml: {{REPO}}
   - .machine_readable/configs/git-cliff/cliff.to...

GitHub Actions: Dogfood Gate / 2_🟡 CHECK Groove manifest check.txt: feat(lang): variables as a parameter; TINI for any decidable variable set

Conclusion: failure

View job details

##[group]Run # Check for static or dynamic Groove endpoints
 �[36;1m# Check for static or dynamic Groove endpoints�[0m
 �[36;1mHAS_MANIFEST="false"�[0m
 �[36;1mHAS_GROOVE_CODE="false"�[0m
 �[36;1m�[0m
 �[36;1m# Canonical manifest location is www/.well-known/groove/ (issue #53);�[0m
 �[36;1m# the repository-root path is accepted, with a warning, during the�[0m
 �[36;1m# migration window.�[0m
 �[36;1mMANIFEST=""�[0m
 �[36;1mif [ -f "www/.well-known/groove/manifest.json" ]; then�[0m
 �[36;1m  MANIFEST="www/.well-known/groove/manifest.json"�[0m
 �[36;1melif [ -f ".well-known/groove/manifest.json" ]; then�[0m
 �[36;1m  MANIFEST=".well-known/groove/manifest.json"�[0m
 �[36;1m  echo "::warning::Groove manifest at legacy root .well-known/ — canonical location is www/.well-known/ (run scripts/migrate-wellknown-to-www.sh)"�[0m
 �[36;1mfi�[0m
 �[36;1m�[0m
 �[36;1mif [ -n "$MANIFEST" ]; then�[0m
 �[36;1m  HAS_MANIFEST="true"�[0m
 �[36;1m  # Validate the manifest JSON�[0m
 �[36;1m  if ! jq empty "$MANIFEST" 2>/dev/null; then�[0m
 �[36;1m    # Gate, don't annotate: an unparseable manifest is a real error,�[0m
 �[36;1m    # not a warning — same behaviour as the standalone�[0m
 �[36;1m    # groove-check.yml (this job had drifted to annotation-only,�[0m
 �[36;1m    # the class of "check that cannot fail" from nexia-list#49).�[0m
 �[36;1m    echo "::error file=$MANIFEST::Invalid JSON in Groove manifest"�[0m

GitHub Actions: Dogfood Gate / 🟡 CHECK Groove manifest check: feat(lang): variables as a parameter; TINI for any decidable variable set

Conclusion: failure

View job details

##[group]Run # Check for static or dynamic Groove endpoints
 �[36;1m# Check for static or dynamic Groove endpoints�[0m
 �[36;1mHAS_MANIFEST="false"�[0m
 �[36;1mHAS_GROOVE_CODE="false"�[0m
 �[36;1m�[0m
 �[36;1m# Canonical manifest location is www/.well-known/groove/ (issue #53);�[0m
 �[36;1m# the repository-root path is accepted, with a warning, during the�[0m
 �[36;1m# migration window.�[0m
 �[36;1mMANIFEST=""�[0m
 �[36;1mif [ -f "www/.well-known/groove/manifest.json" ]; then�[0m
 �[36;1m  MANIFEST="www/.well-known/groove/manifest.json"�[0m
 �[36;1melif [ -f ".well-known/groove/manifest.json" ]; then�[0m
 �[36;1m  MANIFEST=".well-known/groove/manifest.json"�[0m
 �[36;1m  echo "::warning::Groove manifest at legacy root .well-known/ — canonical location is www/.well-known/ (run scripts/migrate-wellknown-to-www.sh)"�[0m
 �[36;1mfi�[0m
 �[36;1m�[0m
 �[36;1mif [ -n "$MANIFEST" ]; then�[0m
 �[36;1m  HAS_MANIFEST="true"�[0m
 �[36;1m  # Validate the manifest JSON�[0m
 �[36;1m  if ! jq empty "$MANIFEST" 2>/dev/null; then�[0m
 �[36;1m    # Gate, don't annotate: an unparseable manifest is a real error,�[0m
 �[36;1m    # not a warning — same behaviour as the standalone�[0m
 �[36;1m    # groove-check.yml (this job had drifted to annotation-only,�[0m
 �[36;1m    # the class of "check that cannot fail" from nexia-list#49).�[0m
 �[36;1m    echo "::error file=$MANIFEST::Invalid JSON in Groove manifest"�[0m

GitHub Actions: Dogfood Gate / 3_🔴 GATE Empty-linter (invisible characters).txt: feat(lang): variables as a parameter; TINI for any decidable variable set

Conclusion: failure

View job details

##[group]Run RESULTS_FILE="$RUNNER_TEMP/empty-lint-results.bin"
 �[36;1mRESULTS_FILE="$RUNNER_TEMP/empty-lint-results.bin"�[0m
 �[36;1mBLOCKING_FILE="$RUNNER_TEMP/empty-lint-blocking-results.bin"�[0m
 �[36;1mif ! scripts/check-invisible-characters.sh \�[0m
 �[36;1m    "$GITHUB_WORKSPACE" "$RESULTS_FILE" "$BLOCKING_FILE"; then�[0m
 �[36;1m  echo "::error::Invisible-character scanner failed; refusing a partial pass"�[0m
...
 �[36;1m  SAFE_PATH="${REL_PATH//'%'/'%25'}"�[0m
 �[36;1m  SAFE_PATH="${SAFE_PATH//$'\r'/'%0D'}"�[0m
 �[36;1m  SAFE_PATH="${SAFE_PATH//$'\n'/'%0A'}"�[0m
 �[36;1m  SAFE_PATH="${SAFE_PATH//':'/'%3A'}"�[0m
 �[36;1m  SAFE_PATH="${SAFE_PATH//','/'%2C'}"�[0m
 �[36;1m  echo "::error file=${SAFE_PATH}::C0 control character or NUL byte detected"�[0m

GitHub Actions: Dogfood Gate / 🔴 GATE Empty-linter (invisible characters): feat(lang): variables as a parameter; TINI for any decidable variable set

Conclusion: failure

View job details

##[group]Run RESULTS_FILE="$RUNNER_TEMP/empty-lint-results.bin"
 �[36;1mRESULTS_FILE="$RUNNER_TEMP/empty-lint-results.bin"�[0m
 �[36;1mBLOCKING_FILE="$RUNNER_TEMP/empty-lint-blocking-results.bin"�[0m
 �[36;1mif ! scripts/check-invisible-characters.sh \�[0m
 �[36;1m    "$GITHUB_WORKSPACE" "$RESULTS_FILE" "$BLOCKING_FILE"; then�[0m
 �[36;1m  echo "::error::Invisible-character scanner failed; refusing a partial pass"�[0m
...
 �[36;1m  SAFE_PATH="${REL_PATH//'%'/'%25'}"�[0m
 �[36;1m  SAFE_PATH="${SAFE_PATH//$'\r'/'%0D'}"�[0m
 �[36;1m  SAFE_PATH="${SAFE_PATH//$'\n'/'%0A'}"�[0m
 �[36;1m  SAFE_PATH="${SAFE_PATH//':'/'%3A'}"�[0m
 �[36;1m  SAFE_PATH="${SAFE_PATH//','/'%2C'}"�[0m
 �[36;1m  echo "::error file=${SAFE_PATH}::C0 control character or NUL byte detected"�[0m

GitHub Actions: Dogfood Gate / 4_Canon lockstep.txt: feat(lang): variables as a parameter; TINI for any decidable variable set

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1mLOCK="$RUNNER_TEMP/canon.lock"�[0m
 �[36;1mURL="https://raw.githubusercontent.com/hyperpolymath/standards/main/canon.lock"�[0m
 �[36;1mif ! curl -fsSL --retry 3 --max-time 30 "$URL" -o "$LOCK"; then�[0m
 �[36;1m  echo "::error::could not fetch canon.lock from $URL"�[0m
...
 �[36;1m  END { print rec }' "$LOCK")"�[0m
 �[36;1mwant="$(printf '%s\n' "$rec" \�[0m
 �[36;1m  | grep -oE 'sha256[[:space:]]*=[[:space:]]*"[0-9a-f]{64}"' \�[0m
 �[36;1m  | grep -oE '[0-9a-f]{64}' | head -1)"�[0m
 �[36;1mif [ -z "$want" ]; then�[0m
 �[36;1m  echo "::error::canon.lock carries no criteria sha256 — malformed, or"�[0m
...
 ##[group]Run set -euo pipefail
...
 �[36;1m  if curl -fsSL --retry 3 --max-time 30 "$URL" -o "$PROFILE" 2>/dev/null; then�[0m
 �[36;1m    fetched="$p"; break�[0m
 �[36;1m  fi�[0m
 �[36;1mdone�[0m
 �[36;1mif [ -z "$fetched" ]; then�[0m
 �[36;1m  echo "::error::no rsr-profile.a2ml at ${HEAD_SHA:0:7} — this repo cannot declare a canon pin"�[0m
...
 �[36;1m# empty string, and `"" = ""` is a green build with nothing behind it —�[0m
 �[36;1m# the same class of bug as this job reading a file that was never there.�[0m
 �[36;1mfor pair in "want_crit:$want_crit" "want_gates:$want_gates" "want_ver:$want_ver" \�[0m
 �[36;1m            "got_crit:$got_crit" "got_gates:$got_gates" "got_ver:$got_ver"; do�[0m
 �[36;1m  if [ -z "${pair#*:}" ]; then�[0m
 �[36;1m    echo "::error::could not read ${pair%%:*} — refusing to compare an empty value"�[0m
...
 �[36;1m} >> "$GITHUB_STEP_SUMMARY"�[0m
 �[36;1mif [ "$ok" = "1" ]; then�[0m
 �[36;1m  echo ":white_check_mark: This template implements the canon at HEAD."�[0m
 �[36;1m  exit 0�[0m
 �[36;1mfi�[0m
 �[36;1mecho "::error::canon lockstep broken — the template does not implement the canon at HEAD"�[0m
...
 shell: /usr/bin/bash -e {0}
 env:
   WANT: ***REDACTED_HIGH_ENTROPY_STRING***
   HEAD_SHA: ee01db4dc34e457cbc32cfb1b7abd737ea8f075a
 ##[endgroup]
 ##[error]no rsr-prof...

GitHub Actions: Dogfood Gate / Canon lockstep: feat(lang): variables as a parameter; TINI for any decidable variable set

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1mLOCK="$RUNNER_TEMP/canon.lock"�[0m
 �[36;1mURL="https://raw.githubusercontent.com/hyperpolymath/standards/main/canon.lock"�[0m
 �[36;1mif ! curl -fsSL --retry 3 --max-time 30 "$URL" -o "$LOCK"; then�[0m
 �[36;1m  echo "::error::could not fetch canon.lock from $URL"�[0m
...
 �[36;1m  END { print rec }' "$LOCK")"�[0m
 �[36;1mwant="$(printf '%s\n' "$rec" \�[0m
 �[36;1m  | grep -oE 'sha256[[:space:]]*=[[:space:]]*"[0-9a-f]{64}"' \�[0m
 �[36;1m  | grep -oE '[0-9a-f]{64}' | head -1)"�[0m
 �[36;1mif [ -z "$want" ]; then�[0m
 �[36;1m  echo "::error::canon.lock carries no criteria sha256 — malformed, or"�[0m

GitHub Actions: Dogfood Gate / Canon lockstep: feat(lang): variables as a parameter; TINI for any decidable variable set

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1mPROFILE="$RUNNER_TEMP/rsr-profile.a2ml"�[0m
 �[36;1mfetched=""�[0m
 �[36;1mfor p in ".machine_readable/rsr-profile.a2ml" "machine-readable/rsr-profile.a2ml"; do�[0m
 �[36;1m  URL="https://raw.githubusercontent.com/hyperpolymath/rsr-template-repo/${HEAD_SHA}/${p}"�[0m
 �[36;1m  if curl -fsSL --retry 3 --max-time 30 "$URL" -o "$PROFILE" 2>/dev/null; then�[0m
 �[36;1m    fetched="$p"; break�[0m
 �[36;1m  fi�[0m
 �[36;1mdone�[0m
 �[36;1mif [ -z "$fetched" ]; then�[0m
 �[36;1m  echo "::error::no rsr-profile.a2ml at ${HEAD_SHA:0:7} — this repo cannot declare a canon pin"�[0m
...
 �[36;1m# empty string, and `"" = ""` is a green build with nothing behind it —�[0m
 �[36;1m# the same class of bug as this job reading a file that was never there.�[0m
 �[36;1mfor pair in "want_crit:$want_crit" "want_gates:$want_gates" "want_ver:$want_ver" \�[0m
 �[36;1m            "got_crit:$got_crit" "got_gates:$got_gates" "got_ver:$got_ver"; do�[0m
 �[36;1m  if [ -z "${pair#*:}" ]; then�[0m
 �[36;1m    echo "::error::could not read ${pair%%:*} — refusing to compare an empty value"�[0m
...
 �[36;1m} >> "$GITHUB_STEP_SUMMARY"�[0m
 �[36;1mif [ "$ok" = "1" ]; then�[0m
 �[36;1m  echo ":white_check_mark: This template implements the canon at HEAD."�[0m
 �[36;1m  exit 0�[0m
 �[36;1mfi�[0m
 �[36;1mecho "::error::canon lockstep broken — the template does not implement the canon at HEAD"�[0m
...
 shell: /usr/bin/bash -e {0}
 env:
   WANT: ***REDACTED_HIGH_ENTROPY_STRING***
   HEAD_SHA: ee01db4dc34e457cbc32cfb1b7abd737ea8f075a
 ##[endgroup]
 ##[error]no rsr-profile.a2ml at ee01db4 — this repo cannot declare a canon pin
 Looked for .machine_readable/rsr-profile.a2ml and machine-readable/rsr-profile.a2ml.
 ##[error]Process completed with exit code 1.

GitHub Actions: Dogfood Gate / 5_Validate eclexiaiser manifest.txt: feat(lang): variables as a parameter; TINI for any decidable variable set

Conclusion: failure

View job details

##[group]Run if [ ! -f "eclexiaiser.toml" ]; then
 �[36;1mif [ ! -f "eclexiaiser.toml" ]; then�[0m
 �[36;1m  # Check if repo has a Containerfile — if so, recommend eclexiaiser�[0m
 �[36;1m  if [ -f "Containerfile" ]; then�[0m
 �[36;1m    echo "::warning::Containerfile present but no eclexiaiser.toml. Run \`eclexiaiser init\` to scaffold energy/carbon budgets."�[0m
 �[36;1m  fi�[0m
 �[36;1m  echo "has_manifest=false" >> "$GITHUB_OUTPUT"�[0m
 �[36;1m  exit 0�[0m
 �[36;1mfi�[0m
 �[36;1m�[0m
 �[36;1mecho "has_manifest=true" >> "$GITHUB_OUTPUT"�[0m
 �[36;1m�[0m
 �[36;1m# Validate eclexiaiser.toml structure (bash + grep; NO Python per estate policy).�[0m
 �[36;1m# Structural presence checks only — deep schema validation is eclexiaiser's own job.�[0m
 �[36;1merr=0�[0m
 �[36;1mgrep -qE '^[[:space:]]*\[project\]'        eclexiaiser.toml || { echo "::error file=eclexiaiser.toml::[project] section is required"; err=1; }�[0m
 �[36;1mgrep -qE '^[[:space:]]*name[[:space:]]*=[[:space:]]*"[^"]+"' eclexiaiser.toml || { echo "::error file=eclexiaiser.toml::a non-empty name is required"; err=1; }�[0m
 �[36;1mgrep -qE '^[[:space:]]*\[\[functions\]\]'  eclexiaiser.toml || { echo "::error file=eclexiaiser.toml::at least one [[functions]] entry is required"; err=1; }�[0m

GitHub Actions: Dogfood Gate / Validate eclexiaiser manifest: feat(lang): variables as a parameter; TINI for any decidable variable set

Conclusion: failure

View job details

##[group]Run if [ ! -f "eclexiaiser.toml" ]; then
 �[36;1mif [ ! -f "eclexiaiser.toml" ]; then�[0m
 �[36;1m  # Check if repo has a Containerfile — if so, recommend eclexiaiser�[0m
 �[36;1m  if [ -f "Containerfile" ]; then�[0m
 �[36;1m    echo "::warning::Containerfile present but no eclexiaiser.toml. Run \`eclexiaiser init\` to scaffold energy/carbon budgets."�[0m
 �[36;1m  fi�[0m
 �[36;1m  echo "has_manifest=false" >> "$GITHUB_OUTPUT"�[0m
 �[36;1m  exit 0�[0m
 �[36;1mfi�[0m
 �[36;1m�[0m
 �[36;1mecho "has_manifest=true" >> "$GITHUB_OUTPUT"�[0m
 �[36;1m�[0m
 �[36;1m# Validate eclexiaiser.toml structure (bash + grep; NO Python per estate policy).�[0m
 �[36;1m# Structural presence checks only — deep schema validation is eclexiaiser's own job.�[0m
 �[36;1merr=0�[0m
 �[36;1mgrep -qE '^[[:space:]]*\[project\]'        eclexiaiser.toml || { echo "::error file=eclexiaiser.toml::[project] section is required"; err=1; }�[0m
 �[36;1mgrep -qE '^[[:space:]]*name[[:space:]]*=[[:space:]]*"[^"]+"' eclexiaiser.toml || { echo "::error file=eclexiaiser.toml::a non-empty name is required"; err=1; }�[0m
 �[36;1mgrep -qE '^[[:space:]]*\[\[functions\]\]'  eclexiaiser.toml || { echo "::error file=eclexiaiser.toml::at least one [[functions]] entry is required"; err=1; }�[0m
Additional context used
Code guidelines: 1
.cursorrules — auto-discovered
Path-based instructions: 1
Source excerpt:

CodeRabbit inference engine (.cursorrules)

Files:

  • README.adoc
  • docs/README-section.adoc
  • src/SecretTypes/Witness.agda
  • src/SecretTypes/All.agda
  • src/SecretTypes/Vars.agda
  • PROOF-STATUS.adoc
  • tests/reject/ExplicitFlow.agda
  • tests/reject/ImplicitFlow.agda
  • src/SecretTypes/Countermodels.agda
  • src/SecretTypes/Noninterference.agda
  • src/SecretTypes/Noninterference/Generic.agda
  • src/SecretTypes/Typing.agda
  • src/SecretTypes/Noninterference/Statement.agda
  • src/SecretTypes/Typing/Generic.agda
  • src/SecretTypes/Lang/Two.agda
  • tests/reject/ThirdVariable.agda
  • src/SecretTypes/Lang.agda
Learnings: 2
Learning: 2026-10-20T19:57:55.017Z
Learnt from: CR
Repo: hyperpolymath/secret-types PR: 0
File: .cursorrules:0-0
Timestamp: 2026-10-20T19:57:55.017Z
Learning: Source excerpt:
# Add SPDX-License-Identifier headers to every source file.

# Add SPDX-License-Identifier headers to every source file.

Applied to files:

  • src/SecretTypes/Vars.agda
  • src/SecretTypes/Lang/Two.agda
Learning: 2026-10-20T19:57:19.327Z
Learnt from: CR
Repo: hyperpolymath/secret-types PR: 0
File: .windsurfrules:0-0
Timestamp: 2026-10-20T19:57:19.327Z
Learning: Source excerpt:
# SPDX header required on every source file.

# SPDX header required on every source file.

Applied to files:

  • src/SecretTypes/Vars.agda
Additional comments: 17
src/SecretTypes/Vars.agda: 1

1-20: LGTM!

src/SecretTypes/Lang.agda: 1

5-10: LGTM!

Also applies to: 12-16, 21-23, 40-40, 48-51, 53-56

src/SecretTypes/Lang/Two.agda: 1

1-43: LGTM!

README.adoc: 1

49-51: LGTM!

docs/README-section.adoc: 1

12-14: LGTM!

src/SecretTypes/Typing/Generic.agda: 1

10-10: LGTM!

Also applies to: 13-13, 18-18, 21-22

src/SecretTypes/Noninterference/Statement.agda: 1

11-11: LGTM!

Also applies to: 14-14, 19-19, 22-23

src/SecretTypes/Noninterference/Generic.agda: 1

10-10: LGTM!

Also applies to: 12-12, 25-26, 28-28, 31-32, 35-36, 75-76, 78-80, 119-120, 123-125

tests/reject/ThirdVariable.agda: 1

1-37: LGTM!

PROOF-STATUS.adoc: 1

3-3: LGTM!

Also applies to: 15-28, 41-41, 74-74

src/SecretTypes/Typing.agda: 1

10-10: LGTM!

Also applies to: 19-19

src/SecretTypes/Noninterference.agda: 1

25-25: LGTM!

Also applies to: 27-27

src/SecretTypes/Countermodels.agda: 1

26-26: LGTM!

Also applies to: 61-61, 98-98, 131-131, 241-241

src/SecretTypes/Witness.agda: 1

9-9: LGTM!

tests/reject/ExplicitFlow.agda: 1

6-6: LGTM!

tests/reject/ImplicitFlow.agda: 1

6-6: LGTM!

src/SecretTypes/All.agda: 1

7-7: LGTM!

Also applies to: 9-9

📝 Summary

Summary by CodeRabbit

  • New Features

    • The language, typing rules and noninterference analysis now support arbitrary variable sets with decidable equality.
    • The existing two-variable example remains available as a specific instance.
    • Added a three-variable example demonstrating that an assignment with an insufficient security label is rejected.
  • Documentation

    • Updated the project overview and proof status to describe the broader variable support and clarify the scope of the existing example.

The language and generic typing and noninterference modules now accept variable sets equipped with decidable equality. Stores map variables to naturals, and the existing lo/hi development remains as a concrete instance. A three-variable rejection test exercises generic typing, and existing clients and documentation are updated.

Changes: Generic variable-set support

Layer / File(s) Summary
Variable-parameterised language
src/SecretTypes/Vars.agda, src/SecretTypes/Lang.agda, src/SecretTypes/Lang/Two.agda, README.adoc, docs/README-section.adoc
Vars pairs a variable type with decidable equality. Lang uses a function from variables to naturals as its store, and Lang.Two provides the lo/hi instance. The README descriptions now distinguish the general language from that instance.
Generic typing and noninterference rules
src/SecretTypes/Typing/Generic.agda, src/SecretTypes/Noninterference/Statement.agda, src/SecretTypes/Noninterference/Generic.agda, tests/reject/ThirdVariable.agda, PROOF-STATUS.adoc
The generic typing and noninterference modules take a variable set as a parameter. Assignment proofs use variable equality, and the new three-variable test declares an assignment expected to fail. The proof-status text updates the scope of N-7 and the fragment description.
Two-variable client updates
src/SecretTypes/Typing.agda, src/SecretTypes/Noninterference.agda, src/SecretTypes/Countermodels.agda, src/SecretTypes/Witness.agda, src/SecretTypes/All.agda, tests/reject/ExplicitFlow.agda, tests/reject/ImplicitFlow.agda
Existing modules and rejection tests use Lang.Two; generic module calls pass two as the variable-set argument. All imports Vars and Lang.Two.

Priority: Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature

Possibly related issues

Possibly related PRs

  • hyperpolymath/secret-types#10: This PR extends the generic typing and noninterference interfaces introduced there with a variable-set parameter and retains the two-variable development as an instance.
Merge Risk: Minimal · up to ee01d

No actionable issue remains identified; the change is mergeable after normal checks.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title names the main change: the language and noninterference development now take the variable set as a parameter, with the two-variable proof kept as an instance. It is specific and matches the …
Description check Passed The description follows the template. It has Summary, Changes, the RSR Quality Checklist with the required items checked, and Testing, which lists the gate results. It also includes a breaking-change …
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title names the main change: the language and noninterference development now take the variable set as a parameter, with the two-variable proof kept as an instance. It is specific and matches the summary and objectives. The title is 73 characters, which is slightly long but readable.

Full details: Description check

Explanation

The description follows the template. It has Summary, Changes, the RSR Quality Checklist with the required items checked, and Testing, which lists the gate results. It also includes a breaking-change note for consumers. The Screenshots section is absent, which is acceptable because it is marked as applicable only when relevant. The CHANGELOG item is left unchecked and the author says it was not touched. That is noted openly.

Finishing Touches
🛠️ Fix failing CI checks
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sonarqubecloud

Copy link
Copy Markdown

Copy link
Copy Markdown
Owner Author

Two checks are red on ee01db4. Neither one comes from this PR:

  • Canon lockstep (Dogfood Gate): no rsr-profile.a2ml at ee01db4 — this repo cannot declare a canon pin. The Dogfood Gate is red on main at every push since at least 2026-10-05 (7736da2, ccdcb3e, a75798a, 833715c, 2a37fe1). This diff touches no .machine_readable/ file.
  • openssf-compliance: unfilled template placeholders ({{PROJECT}}, {{AUTHOR}}, … in docs/status/PROOF-STATUS.adoc, tests/e2e.sh, www/…). This is red on main at the same pushes. This diff adds no placeholder.

Both come from secret-types never having been minted from rsr-template-repo; Lintel needed the same mint in metadatastician/lintel#3. I have no fix to port. Doing the mint here is the owner's call and a change separate from this one. I'm not re-running these checks, because they fail the same way on main.

The check this PR does own is Agda proofs. Locally both of its gates pass at Agda 2.6.4.3: PASS: core proofs and all 3 expected rejections and PASS: minimal-laws certificate (3 laws, each needed).


Generated by Claude Code

@linear-code
linear-code Bot marked this pull request as ready for review October 27, 2026 05:23
hyperpolymath added a commit to metadatastician/lintel that referenced this pull request Oct 27, 2026
…full (#17)

## Summary

Stacked on
[hyperpolymath/secret-types#13](hyperpolymath/secret-types#13),
which makes the variables a parameter. Pinned to that branch's commit
`ee01db4` for now; I re-pin to the merge commit once it lands, and this
stays a draft until then.

Lintel now names its own variables: `addr` (the address), `qn` (the
query name) and `local`, the client's local state, labelled client-only.
That closes the two scope caveats #14 recorded:

- **L-7** had only the corollary half. With two incomparable fields no
typed command moves information between them at all, so "no command
writes the link" followed from that. With a client-only variable the
informative statement holds and is not vacuous: `link-written-to-local`
(a typed write depending on both fields targets `local` and nothing
else) and `link-writable` (a typed command does write the link into
`local`).
- **A-1**: `tini-coalition proxy target` said no more than determinism,
since the coalition saw every variable. It does not see `local`
(`coalition-blind`), so it now relates stores that differ there
(`coalition-agrees`, `stores-differ`).

## Changes

- `src/Lintel/Instance.agda`: `Field`, `_≟f_`, `fields : Vars`,
`field-label local = observer client`; `coalition-blind`,
`store₀`/`store₁`, `coalition-agrees`, `stores-differ`. Re-exports
`SecretTypes.Lang fields`.
- `src/Lintel/Composition.agda`: the generic part is over any `Vars` and
labelling; `no-link-written` is replaced by `link-written-to-local` and
`link-writable`.
- `tests/accept/ProgramLinkLocal.agda` (new): the positive control for
`tests/reject/ProgramLink.agda`, the same sum written into `local`. The
four existing program fixtures move to the new names (`lo`→`addr`,
`hi`→`qn`).
- `scripts/fetch-siblings.sh`, module pin headers, README footer:
secret-types `ccdcb3e` → `ee01db4`.
- `README.adoc`: L-6, L-7 and A-1 restated; L-7's scope caveat and A-1's
determinism note removed, because what they described no longer holds.
Statuses unchanged: L-6/L-7 PROVEN, A-1 ASSUMED.

## RSR Quality Checklist

### Required

- [x] Tests pass: `bash scripts/fetch-siblings.sh && bash
scripts/check.sh` with a fresh fetch of the pin → `PASS: Lintel proofs,
5 positive control(s), 4 expected rejection(s), negative control`.
- [x] Code is formatted.
- [x] Linter is clean: `-W error`.
- [x] No banned language patterns.
- [x] No `unsafe` blocks.
- [x] No banned functions; no postulates.
- [x] SPDX headers present.
- [x] No secrets.

### As Applicable

- [x] Documentation updated (README status table).
- [ ] `CHANGELOG`: not touched.

## Testing

Gate as above. Mutation, checked locally: labelling `local` as the
address breaks `coalition-blind` and `link-writable`.
`link-written-to-local` alone would still hold under that mutation (its
`local` case is `refl`). What carries the content is the pair, and the
README says it in those terms.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01BYbQRtNu216R13jtZLmoqs)_

Co-authored-by: Claude <noreply@anthropic.com>
@hyperpolymath
hyperpolymath enabled auto-merge (squash) October 27, 2026 05:35
@hyperpolymath
hyperpolymath enabled auto-merge (squash) October 27, 2026 05:38
@coderabbitai

coderabbitai Bot commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

Add Carrot credits or activate Agent usage billing to use Autofix

@coderabbitai

coderabbitai Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

✅ Coding Agent task started: View task and status

The task will inspect the CI failures, validate its fix, and commit the fix to this branch automatically.

Note: Fixing CI failures is a beta feature and may encounter errors. Expect some limitations and changes as we gather feedback and continue to improve it.

⏭️ Checks skipped: 4 · already failing on `main` (not caused by this PR)
  • GitHub Actions: OpenSSF Compliance / 0_openssf-compliance.txt
  • GitHub Actions: Dogfood Gate / 2_🟡 CHECK Groove manifest check.txt
  • GitHub Check: Canon lockstep
  • GitHub Check: openssf-compliance

@hyperpolymath
hyperpolymath enabled auto-merge (squash) October 27, 2026 11:42
@hyperpolymath
hyperpolymath merged commit f581f82 into main Oct 27, 2026
32 of 34 checks passed
@hyperpolymath
hyperpolymath deleted the claude/n-variables branch October 27, 2026 14:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants