Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0b5175f
test(v21): establish fresh Learned Policy V3 causal RED
laiqian0239-glitch Aug 14, 2026
125eb50
feat(v21): root-fix Learned Policy production consumption
laiqian0239-glitch Aug 14, 2026
9f191f7
feat(v21): seal Learned Policy Windows runtime
laiqian0239-glitch Aug 15, 2026
ea0bf76
fix(v21): repair Learned Policy Windows argv boundary
laiqian0239-glitch Aug 15, 2026
0d3ca73
fix(v21): use native stdin for sealed policy contract
laiqian0239-glitch Aug 15, 2026
96b67e6
fix(v21): delimit Learned Policy Windows exit code
laiqian0239-glitch Aug 15, 2026
486c8b5
fix(v21): use file-backed stdin for sealed policy contract
laiqian0239-glitch Aug 15, 2026
6af68ac
fix(v21): use file-backed stdin for sealed VW training
laiqian0239-glitch Aug 15, 2026
54264f2
fix(v21): run production closure as desktop host
laiqian0239-glitch Aug 15, 2026
7064bf0
fix(v21): keep sealed Learning runtime immutable
laiqian0239-glitch Aug 15, 2026
fd4e90f
fix(v21): harden Learned Policy production authority
laiqian0239-glitch Aug 15, 2026
c719a17
test(v21): make Learned Policy UAT behavioral
laiqian0239-glitch Aug 15, 2026
fc20f3f
test(v21): cover nested Learning runtime seal inventory
laiqian0239-glitch Aug 15, 2026
e5e4786
fix(v21): isolate injected Learned Policy runtime seam
laiqian0239-glitch Aug 15, 2026
55de3a9
test(v21): require observable LKG degradation fallback
laiqian0239-glitch Aug 15, 2026
f9fa314
fix(v21): preserve degraded LKG policy fallback
laiqian0239-glitch Aug 15, 2026
15ffdbd
fix(v21): scope Learning runtime seal exclusion to root
laiqian0239-glitch Aug 15, 2026
b6474fa
fix(v21): restore WP7 bytes around Learning seal repair
laiqian0239-glitch Aug 15, 2026
9b5921b
test(v21): prove native promotion consumption in UAT
laiqian0239-glitch Aug 15, 2026
155eb1c
test(v21): make explicit resolver absence authoritative
laiqian0239-glitch Aug 15, 2026
b445355
fix(v21): honor explicit no-active policy resolution
laiqian0239-glitch Aug 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
225 changes: 225 additions & 0 deletions .github/workflows/v21-learning-policy-p1-windows.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
name: V2.1 Learned Policy P1 Windows Runtime

on:
pull_request:
paths:
- '.github/workflows/v21-learning-policy-p1-windows.yml'
- 'backend/services/contextAwareReplyBrain.js'
- 'backend/services/learningDeepTrainingContract.js'
- 'backend/services/learningOutcomeAttributionService.js'
- 'backend/services/learningPolicyDecisionContract.js'
- 'backend/services/learningPolicyRuntimeAdapter.js'
- 'backend/services/learningPromotionAdapter.js'
- 'backend/services/replyFeedbackLearningService.js'
- 'backend/services/storeManagerService.js'
- 'config/upstreams/v21-learning-growth-brain-p0.json'
- 'runtime/learning-growth/python/**'
- 'tools/learning-growth/build-windows-runtime.ps1'
- 'tools/uat/v21LearningPolicyClosedLoopEvidence.js'
- 'tools/wp7/lib.js'
- 'tools/wp7/packaged-product-trust.js'
- 'tools/wp7/create-pre-review-trusted-product.js'
- 'THIRD_PARTY_NOTICES.md'
- 'third_party/licenses/vowpal-wabbit-BSD-3-Clause.txt'
- 'tests/wp0/v21-learning-policy-p1-*.test.js'
workflow_dispatch:

permissions:
contents: read

jobs:
seal-promote-and-consume:
runs-on: windows-latest
timeout-minutes: 45
steps:
- name: Checkout exact candidate
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
with:
fetch-depth: 0
fetch-tags: false
lfs: false
persist-credentials: false

- name: Set up Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e
with:
node-version: '22'
package-manager-cache: false

- name: Install locked Node production authority dependencies
shell: powershell
run: |
$ErrorActionPreference = 'Stop'
npm.cmd ci --ignore-scripts --no-audit --no-fund
if ($LASTEXITCODE -ne 0) { throw 'locked Node dependency installation failed' }

- name: Seal Learned Policy Windows runtime from pinned OSS inputs
shell: powershell
run: |
$ErrorActionPreference = 'Stop'
.\tools\learning-growth\build-windows-runtime.ps1 -OutputRoot "$env:RUNNER_TEMP\learning-runtime"

- name: Verify sealed runtime excludes build resolver and VCS state
shell: powershell
run: |
$ErrorActionPreference = 'Stop'
$root = "$env:RUNNER_TEMP\learning-runtime"
foreach ($forbidden in @('uv.exe', '.git', 'uv.lock')) {
$found = @(Get-ChildItem -LiteralPath $root -Recurse -Force | Where-Object { $_.Name -eq $forbidden })
if ($found.Count -ne 0) { throw "forbidden build-time artifact shipped: $forbidden" }
}
foreach ($required in @('venv\Scripts\python.exe','python\python.exe','learning_entrypoint.py','runtime-sbom.cdx.json','runtime-seal.json')) {
if (-not (Test-Path -LiteralPath (Join-Path $root $required) -PathType Leaf)) { throw "sealed Learning runtime missing: $required" }
}
$seal = Get-Content (Join-Path $root 'runtime-seal.json') -Raw | ConvertFrom-Json
if ($seal.documentType -ne 'YANCE_LEARNING_WINDOWS_RUNTIME_SEAL') { throw 'Learning runtime seal identity mismatch' }
if ($seal.learningPolicy.learner -ne 'Vowpal Wabbit' -or $seal.learningPolicy.version -ne '9.11.2') { throw 'Learning runtime Vowpal Wabbit identity mismatch' }
if ($seal.learningPolicy.exploration -ne $false -or $seal.learningPolicy.textGeneration -ne $false) { throw 'Learning runtime exceeded deterministic action-head boundary' }
if ($seal.runtime.dependencyResolution -ne 'build-time-only' -or $seal.runtime.networkResolutionAtRuntime -ne $false -or $seal.runtime.buildToolsShipped -ne $false) { throw 'Learning runtime seal violates offline packaging boundary' }

- name: Train deterministic content-addressed VW candidate
shell: powershell
env:
HTTP_PROXY: 'http://127.0.0.1:9'
HTTPS_PROXY: 'http://127.0.0.1:9'
ALL_PROXY: 'http://127.0.0.1:9'
NO_PROXY: '127.0.0.1,localhost'
run: |
$ErrorActionPreference = 'Stop'
$root = "$env:RUNNER_TEMP\learning-runtime"
$python = Join-Path $root 'venv\Scripts\python.exe'
$entrypoint = Join-Path $root 'learning_entrypoint.py'
$artifact = Join-Path $env:RUNNER_TEMP 'learned-policy-candidate.vw'
$actions = @('natural_hook','playful_attraction','direct_advance','screen_and_advance','leave_aftertaste')
$rows = @(
@{
featureBundle = @{ interactionBand = 'warm'; performanceMode = 'balanced'; questionPolicy = 'light'; relationshipStage = 'early'; targetLanguage = 'en' }
decision = @{ allowedActionSet = $actions; candidateStrategyBranch = 'natural_hook'; actionProbability = 1.0 }
approvedScore = @{ approvedByLearning = $true; value = 1.0 }
},
@{
featureBundle = @{ interactionBand = 'warm'; performanceMode = 'balanced'; questionPolicy = 'light'; relationshipStage = 'early'; targetLanguage = 'en' }
decision = @{ allowedActionSet = $actions; candidateStrategyBranch = 'natural_hook'; actionProbability = 1.0 }
approvedScore = @{ approvedByLearning = $true; value = 1.0 }
}
)
$request = @{ operation = 'policy_train'; rows = $rows; artifactPath = $artifact } | ConvertTo-Json -Depth 12 -Compress
$requestPath = [IO.Path]::GetTempFileName()
$stdoutPath = [IO.Path]::GetTempFileName()
$stderrPath = [IO.Path]::GetTempFileName()
try {
$utf8NoBom = New-Object Text.UTF8Encoding($false)
[IO.File]::WriteAllText($requestPath, ($request + "`n"), $utf8NoBom)
$argumentList = @('-B', '-I', ('"' + $entrypoint + '"'))
$process = Start-Process -FilePath $python -ArgumentList $argumentList -RedirectStandardInput $requestPath -RedirectStandardOutput $stdoutPath -RedirectStandardError $stderrPath -NoNewWindow -Wait -PassThru
$output = [IO.File]::ReadAllText($stdoutPath)
$stderr = [IO.File]::ReadAllText($stderrPath)
if ($process.ExitCode -ne 0) { throw "sealed VW training failed with exit $($process.ExitCode): $stderr $output" }
} finally {
Remove-Item -LiteralPath $requestPath, $stdoutPath, $stderrPath -Force -ErrorAction SilentlyContinue
}
$result = $output | ConvertFrom-Json
if ($result.status -ne 'READY' -or $result.probability -ne 1 -or $result.exploration -ne $false) { throw "sealed VW training contract mismatch: $output" }
$digest = (Get-FileHash -LiteralPath $artifact -Algorithm SHA256).Hash.ToLowerInvariant()
if ($result.policyArtifactVersion -ne $digest -or $result.policyArtifactId -ne $digest) { throw 'trained VW artifact content identity mismatch' }
$dataRoot = Join-Path $env:RUNNER_TEMP 'learned-policy-production-data'
$candidateRoot = Join-Path $dataRoot 'learning\learned-policy\candidates'
New-Item -ItemType Directory -Force -Path $candidateRoot | Out-Null
Copy-Item -LiteralPath $artifact -Destination (Join-Path $candidateRoot "$digest.vw")
"YANCE_DATA_DIR=$dataRoot" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
"LEARNED_POLICY_DIGEST=$digest" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append

- name: Production-default native promotion and packaged consumption closure
shell: powershell
env:
HTTP_PROXY: 'http://127.0.0.1:9'
HTTPS_PROXY: 'http://127.0.0.1:9'
ALL_PROXY: 'http://127.0.0.1:9'
NO_PROXY: '127.0.0.1,localhost'
run: |
$ErrorActionPreference = 'Stop'
$resources = Join-Path $env:RUNNER_TEMP 'learned-policy-product-resources'
New-Item -ItemType Directory -Force -Path $resources | Out-Null
@'
const fs = require('node:fs');
const path = require('node:path');
const assert = require('node:assert/strict');
const { OpenFeature } = require('@openfeature/server-sdk');
process.env.YANCE_PROCESS_ROLE = 'desktop-host';
const { copyPresealedLearningRuntime, validatePresealedLearningRuntime } = require('./tools/wp7/lib');
const { createLearningPromotionAdapter } = require('./backend/services/learningPromotionAdapter');
const { createLearningPolicyRuntimeAdapter } = require('./backend/services/learningPolicyRuntimeAdapter');

(async () => {
try {
const sourceRuntime = path.join(process.env.RUNNER_TEMP, 'learning-runtime');
const resourcesRoot = path.join(process.env.RUNNER_TEMP, 'learned-policy-product-resources');
const digest = process.env.LEARNED_POLICY_DIGEST;
const actions = ['natural_hook','playful_attraction','direct_advance','screen_and_advance','leave_aftertaste'];
const sealed = validatePresealedLearningRuntime(sourceRuntime);
assert.equal(sealed.seal.learningPolicy.learner, 'Vowpal Wabbit');
assert.equal(sealed.seal.learningPolicy.version, '9.11.2');
const copied = copyPresealedLearningRuntime(sourceRuntime, resourcesRoot);
assert.equal(copied.relativeRoot, 'resources/learning-runtime');
assert.equal(copied.treeSha256, sealed.treeSha256);
Object.defineProperty(process, 'resourcesPath', { value: resourcesRoot, configurable: true });

const proposal = {
status: 'READY_FOR_REVIEW',
Regression: { passed: true },
Shadow: { passed: true },
Candidate: { id: `policy:${digest}`, version: digest, policyVersion: 'vw-p1-v1' }
};
const promotion = createLearningPromotionAdapter();
const rollout = await promotion.promote(proposal, { approved: true, evidence: { id: 'windows-production-closure' } });
assert.equal(rollout.kind, 'LEARNING_ROLLOUT');
assert.equal(rollout.candidate.version, digest);
assert.equal(rollout.OpenFeature, true);
assert.equal(rollout.flagd, 'in-process-offline');

const runtime = createLearningPolicyRuntimeAdapter();
const featureBundle = {
interactionBand: 'warm',
performanceMode: 'balanced',
questionPolicy: 'light',
relationshipStage: 'early',
targetLanguage: 'en'
};
const selected = await runtime.selectLearnedPolicyAction({ featureBundle, allowedActions: actions, baselineAction: 'natural_hook' });
assert.equal(selected.executedPolicy, 'vowpalwabbit');
assert.equal(selected.policyArtifactId, digest);
assert.equal(selected.actionProbability, 1);
assert.equal(selected.exploration, false);
assert.ok(actions.includes(selected.candidateStrategyBranch));

const promotedArtifact = path.join(process.env.YANCE_DATA_DIR, 'learning', 'learned-policy', 'artifacts', `${digest}.vw`);
fs.appendFileSync(promotedArtifact, Buffer.from('\ncorrupt-for-fail-safe-proof\n', 'utf8'));
const degraded = await runtime.selectLearnedPolicyAction({ featureBundle, allowedActions: actions, baselineAction: 'natural_hook' });
assert.equal(degraded.executedPolicy, 'baseline');
assert.equal(degraded.actionProbability, 1);
assert.equal(degraded.exploration, false);
assert.ok(degraded.degradation && degraded.degradation.reasonCode === 'LEARNING_POLICY_ARTIFACT_IDENTITY_MISMATCH');

process.stdout.write(JSON.stringify({ status: 'PASS', digest, selected, degraded, sealedTreeSha256: sealed.treeSha256 }) + '\n');
} finally {
await OpenFeature.close();
}
})().catch((error) => {
console.error(error && error.stack || error);
process.exit(1);
});
'@ | node
if ($LASTEXITCODE -ne 0) { throw 'production-default Learning promotion/runtime/WP7 closure failed' }

- name: Re-run frozen Learned Policy P1 contracts
shell: powershell
run: |
node --test tests/wp0/v21-learning-policy-p1-decision-record.test.js tests/wp0/v21-learning-policy-p1-outcome-binding.test.js tests/wp0/v21-learning-policy-p1-projection.test.js tests/wp0/v21-learning-policy-p1-supply-chain.test.js tests/wp0/v21-learning-policy-p1-vw-runtime.test.js tests/wp0/v21-learning-policy-p1-production-consumption.test.js
if ($LASTEXITCODE -ne 0) { throw 'frozen Learned Policy P1 contracts failed' }

- name: Upload sealed Learned Policy runtime
uses: actions/upload-artifact@v4
with:
name: yance-learned-policy-windows-x64
path: ${{ runner.temp }}/learning-runtime
if-no-files-found: error
9 changes: 9 additions & 0 deletions THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,3 +295,12 @@ Exact Voice Brain source, model and build-tool pins are recorded in `config/upst
- License copy: `third_party/licenses/agent-lightning-MIT.txt`
- Upstream dependency lock: exact `uv.lock` Git blob `5a98a2ac121b050b0a82f6ac8dc207577ce3af4e`
- Yance integration: source-module CORE + APO only, downstream of Learning and Model Brain authority, returning `CANDIDATE_ONLY`.
## Vowpal Wabbit

- Project: Vowpal Wabbit
- Upstream: `VowpalWabbit/vowpal_wabbit`
- Version: `9.11.2`
- Frozen commit: `122bae254a5b8bc2b774d13b33d53e6dbc2cfba7`
- License: `BSD-3-Clause`
- License copy: `third_party/licenses/vowpal-wabbit-BSD-3-Clause.txt`
- Yance integration: sealed Learning runtime contextual-bandit ADF policy head only. P1 is deterministic (`actionProbability=1.0`, `exploration=false`); Model Brain/LiteLLM remains the final reply-generation authority.
Loading
Loading