name: CFC Property Suite # The deterministic CFC property suite, and the audit read over what it just # wrote. # # Nightly rather than per-PR on purpose. The suite stands up real runtimes and # real prompt loops, and the point of it is to produce evidence deliberately # rather than to gate a diff; the CI workflow's lanes already run the same # tests on a pull request, as the cf-harness part of the `workspace-unit` # suite, where they are fast because each one audits only its own run. # # What this job adds is the second step. A lane's run audits each property's # own artifacts; here the whole suite writes into one root and the corpus # checks read that root as a population โ€” AUD-16's refusal count and AUD-18's # posture uniformity are corpus questions, and a single run cannot answer # either. `--expect-refusals` declares the corpus adversarial, which turns "no # release refusal anywhere" from a warning into a failure: a suite that stopped # producing its refusal would otherwise go quiet rather than red. # # `--expected-failures` is why the threshold stays at `warn` rather than being # lowered to make the job green. Every finding the suite is known to produce is # named in that file with the issue tracking it; anything else fails the run, # and so does an entry that stopped matching. A job that cannot be green trains # everyone to ignore it, and a job whose bar was lowered is not a signal โ€” the # list is the third option, and it shrinking is the progress to watch. # # The corpus this writes is fresh every night, which is the whole value. The # historic session corpus cannot be re-run, so a check can only ever report # what those runs happened to record; this one reports what the current code # does. # # The job takes no part in test records: no spool directory, no # `run-recorded` wrapper, no ship step. `docs/specs/test-records.md` # under "Recording" holds why, and the two steps get there differently. # The suite step runs `deno test` directly, and a bare run records # nothing: records for such a suite come from a JUnit report ingested at # shipping time, which the workspace runner arranges by appending # `--junit-path` and the registration preload, and neither is here. Its # tests are units of `workspace-unit` and record when CI runs them. So a # wrapper here files one line summarizing the invocation and nothing # else, which is not one execution of one test. The audit step reads the # corpus the step before it wrote, so no lane can be asked to run it. The # audit's verdict is the job's own conclusion, and the findings behind a # red one are in the uploaded artifacts and in # `audit/expected-failures.json`. on: schedule: - cron: "0 5 * * *" # Nightly, 05:00 UTC workflow_dispatch: {} # Allow manual trigger jobs: cfc-properties: name: "CFC properties and the audit over them" runs-on: ubuntu-latest steps: - name: ๐Ÿ“ฅ Checkout repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: ๐Ÿฆ• Setup Deno uses: ./.github/actions/deno-setup - name: ๐Ÿ” Verify lock file & install dependencies uses: ./.github/actions/deno-install # One root for every property, so the corpus checks have a population. - name: ๐Ÿงช Run the CFC property suite working-directory: packages/cf-harness env: CF_HARNESS_PROPERTY_ARTIFACT_ROOT: ${{ runner.temp }}/cfc-properties run: deno test --shuffle=$(deno task -q test-seed) --no-check -A test/cfc-properties/ - name: ๐Ÿ”Ž Audit the artifacts the suite just wrote working-directory: packages/cf-harness run: | deno task cfc-audit "${{ runner.temp }}/cfc-properties" \ --corpus \ --expect-refusals \ --expected-posture audit/profiles/max-enforcement.json \ --fail-on warn \ --expected-failures audit/expected-failures.json # Kept whether or not the audit passed: a red run's findings are the # reason to look, so the evidence behind them has to outlive the job. - name: ๐Ÿ“ค Upload the audited artifacts if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: cfc-property-artifacts path: ${{ runner.temp }}/cfc-properties retention-days: 14