From 167642ec9df4923150fc2c7769f36bd715a0bb97 Mon Sep 17 00:00:00 2001 From: Gergo Magyar Date: Thu, 3 Sep 2026 20:14:05 +0000 Subject: [PATCH] feat(ci): let a dispatched evolution run start from a blank slate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Seeding is unconditional today, so the next run would inherit the rejected proposal from a generation whose proposer could still read the hidden oracles. That taint propagates: each generation stages the previous proposal, so one contaminated proposal survives until the artifact expires. Scheduled runs still always seed — memoryless weekly runs would re-propose the same rejected candidate forever. Co-authored-by: Cursor --- .github/workflows/gitnexus-skill-evolution.yml | 7 +++++++ .../test/unit/skill-evolution-workflow.test.ts | 17 +++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/.github/workflows/gitnexus-skill-evolution.yml b/.github/workflows/gitnexus-skill-evolution.yml index 56429e0e2..a14dc79eb 100644 --- a/.github/workflows/gitnexus-skill-evolution.yml +++ b/.github/workflows/gitnexus-skill-evolution.yml @@ -131,6 +131,11 @@ on: required: false default: false type: boolean + seed_from_previous: + description: 'Seed the proposer with the previous run''s evidence and rejected proposal. Turn off to start from a blank slate — required when the earlier evidence is not trustworthy (e.g. produced before a harness-integrity fix), since a tainted proposal would otherwise propagate into every later generation.' + required: false + default: true + type: boolean concurrency: group: ${{ github.workflow }} @@ -336,6 +341,8 @@ jobs: - name: Seed the proposer with the previous run's evidence id: seed + # Scheduled runs always seed; a dispatch can opt out to start clean. + if: github.event_name != 'workflow_dispatch' || inputs.seed_from_previous # Best-effort seeding must not consume the benchmark's budget. This # step walks up to 10 prior runs and every iteration blocks on network # it does not control (`gh run download` of a multi-hundred-megabyte diff --git a/gitnexus/test/unit/skill-evolution-workflow.test.ts b/gitnexus/test/unit/skill-evolution-workflow.test.ts index 0fd8b898a..ccc682a18 100644 --- a/gitnexus/test/unit/skill-evolution-workflow.test.ts +++ b/gitnexus/test/unit/skill-evolution-workflow.test.ts @@ -238,6 +238,23 @@ describe('gitnexus skill-evolution workflow contract', () => { expect(seed).toContain('break'); }); + it('lets a dispatch start from a blank slate while the schedule always seeds', () => { + // Evidence from a run whose harness leaked the hidden oracles cannot be + // trusted, and the staged prior proposal is what carries that taint into + // every later generation. Without an opt-out the only remedy is waiting + // for the tainted artifact to expire. + const triggers = (workflowDocument as { on?: Record }).on; + const inputs = (triggers?.workflow_dispatch as { inputs?: Record } | undefined) + ?.inputs; + const input = inputs?.seed_from_previous as { type?: string; default?: unknown } | undefined; + expect(input?.type).toBe('boolean'); + expect(input?.default).toBe(true); + + const condition = findStep("Seed the proposer with the previous run's evidence")?.if; + expect(condition).toContain("github.event_name != 'workflow_dispatch'"); + expect(condition).toContain('inputs.seed_from_previous'); + }); + it('bounds the best-effort seed walk well inside the job budget', () => { // Every iteration blocks on a network download this job does not control, // and the job-level timeout CANCELS rather than fails — which skips the