Admit Qwen local Case model

This commit is contained in:
Svrnty 2026-05-31 21:51:18 -04:00
parent bd195071a9
commit ba712be2be
7 changed files with 117 additions and 0 deletions

View File

@ -72,6 +72,21 @@ agent did not return output framed by the Case `AGENT_RESULT` delimiter contract
The evidence does not prove whether the defect is Case provider configuration, The evidence does not prove whether the defect is Case provider configuration,
provider adapter behavior, Codex output framing, or harness invocation shape. provider adapter behavior, Codex output framing, or harness invocation shape.
## Narrowed Interpretation - 2026-06-01
Hermes commit `5db23c7 Fail closed on Case Codex auth gap` narrows the current
OpenAI Codex path blocker.
The current known OpenAI Codex blocker is an auth-bridge gap:
- Case's pipeline SDK path constructs its Pi Agent runtime directly.
- That path does not pass Pi AuthStorage OAuth headers into `streamSimple`.
- Pi env API-key lookup does not map `openai-codex` to an environment API key.
- Hermes now blocks `openai-codex` before `case_process_started` unless an explicit non-vendor auth bridge is proven.
This does not prove that any local provider path passes Stage 2. It only prevents
repeating the misleading malformed-output run for the `openai-codex` path.
## Required Next Route ## Required Next Route
The next useful route is a small Case agent protocol compatibility investigation. The next useful route is a small Case agent protocol compatibility investigation.
@ -88,6 +103,7 @@ Allowed next actions:
- Inspect Hermes CTO Case invocation behavior. - Inspect Hermes CTO Case invocation behavior.
- Add fail-closed classification in Hermes CTO harness if needed. - Add fail-closed classification in Hermes CTO harness if needed.
- Add a compatibility shim only outside vendor Case source. - Add a compatibility shim only outside vendor Case source.
- Admit and test the existing Pi local provider id `qwen-local` only through the Harness Evidence Interface.
- Re-run real Case Stage 2 only after a specific protocol compatibility change exists. - Re-run real Case Stage 2 only after a specific protocol compatibility change exists.
Forbidden next actions: Forbidden next actions:

View File

@ -125,3 +125,40 @@ Acceptance:
- Case retry classified the failure as `agent-protocol-error`. - Case retry classified the failure as `agent-protocol-error`.
- `CTO-WORK-020` remains blocked because no real Case Stage 2 pass report exists. - `CTO-WORK-020` remains blocked because no real Case Stage 2 pass report exists.
- Current downstream blocker is tracked by `CTO-WORK-028`. - Current downstream blocker is tracked by `CTO-WORK-028`.
## Hermes Auth Preflight Evidence - 2026-06-01
- Hermes commit: `5db23c7 Fail closed on Case Codex auth gap`.
- `5db23c7` proves fail-closed classification only; it is not a real Case Stage 2 pass.
- The Hermes adapter now blocks `openai-codex` before `case_process_started` unless `CTO_HARNESS_CASE_OPENAI_CODEX_AUTH_BRIDGE=1`.
- The block writes `backend/provider-auth-unavailable.txt`.
- The reason is specific: Case's pipeline SDK path constructs its Pi Agent runtime directly and does not pass Pi AuthStorage OAuth headers into `streamSimple`.
- Pi env API-key lookup does not map `openai-codex` to an environment API key.
- Focused validator passed: `python3 harness/runner/validate-case-provider-adapter.py --harness-root harness --json`.
- Aggregate validator passed: `harness/evals/health.sh --json`.
- Focused validator artifact: `/home/svrnty/.hermes/profiles/cto-planb/harness-runs/20260601T014803Z-r1-string-slugify-2448172`.
- Aggregate validator artifact: `/home/svrnty/.hermes/profiles/cto-planb/harness-runs/20260601T014805Z-r1-string-slugify-2449212`.
- `CTO-WORK-020` remains blocked because no real Case Stage 2 pass report exists.
## CTO-WORK-029 - Qwen Local Case Model Admission JSON
Status: validated.
Record the exact non-secret admission JSON required by `CTO_HARNESS_CASE_MODEL_ADMISSION_FILE` for the existing Pi local provider path `qwen-local` / `qwen3.6-35b-a3b`.
Acceptance:
- Admission file path is `.sot/03-PROTOCOLS/CTO-CASE-MODEL-PROVIDER-ADMISSION.qwen-local-qwen3.6-35b-a3b.json`.
- Admission JSON has `status`: `admitted`.
- Admission JSON has `provider`: `qwen-local`.
- Admission JSON has `model`: `qwen3.6-35b-a3b`.
- Admission JSON has `credential_source_class`: `pi-models-json-local-provider-no-secret`.
- Admission JSON has `allowed_network_class`: `local-tailscale-vllm-spark1`.
- Admission JSON has `approval_source`: `JP chat approval on 2026-05-31`.
- Admission JSON has `admission_timestamp`.
- Admission JSON has `review_trigger`.
- Admission JSON contains no secret keys or secret values.
- This admission does not change Hermes primary model policy.
- This admission does not approve real-repo, copied-repo, sandbox-repo, owned-repo, default-candidate, or Core promotion stages.
- `CTO-WORK-020` remains blocked until real Case Stage 2 produces a Harness Evidence Interface pass report using this admission file.
- Real Case Stage 2 command must set `CTO_HARNESS_CASE_MODEL_ADMISSION_FILE` to this admission JSON path.

View File

@ -0,0 +1,10 @@
{
"admission_timestamp": "2026-06-01T00:00:00-04:00",
"allowed_network_class": "local-tailscale-vllm-spark1",
"approval_source": "JP chat approval on 2026-05-31",
"credential_source_class": "pi-models-json-local-provider-no-secret",
"model": "qwen3.6-35b-a3b",
"provider": "qwen-local",
"review_trigger": "Before real Case Stage 2 admission JSON path changes, before local provider endpoint changes, before default/fallback model changes, or before promotion beyond copied artificial fixture.",
"status": "admitted"
}

View File

@ -60,3 +60,13 @@ Any future state must include exact non-secret fields required by `CTO-WORK-020`
- Real Case Stage 2 remains blocked until admitted provider/model and Harness Evidence Interface pass report exist. - Real Case Stage 2 remains blocked until admitted provider/model and Harness Evidence Interface pass report exist.
- Fallback to `vllm` with `qwen3.6-35b-a3b` must be explicit in admission evidence before it may count as a Case provider/model path. - Fallback to `vllm` with `qwen3.6-35b-a3b` must be explicit in admission evidence before it may count as a Case provider/model path.
- Existing evidence paths and commits are referenced only; runtime evidence is not copied into this record. - Existing evidence paths and commits are referenced only; runtime evidence is not copied into this record.
## Runtime Compatibility Finding - 2026-06-01
- Hermes commit `5db23c7 Fail closed on Case Codex auth gap` blocks the admitted `openai-codex` / `gpt-5.5` Case path before `case_process_started` unless a non-vendor auth bridge is proven.
- The block exists because Case's pipeline SDK path constructs its Pi Agent runtime directly and does not pass Pi AuthStorage OAuth headers into `streamSimple`.
- Pi env API-key lookup does not map `openai-codex` to an environment API key.
- The Case-compatible local provider id for the current local Spark fallback path is `qwen-local`, model `qwen3.6-35b-a3b`.
- The non-secret admission JSON for that local Case path is `.sot/03-PROTOCOLS/CTO-CASE-MODEL-PROVIDER-ADMISSION.qwen-local-qwen3.6-35b-a3b.json`.
- This finding does not change Hermes primary model policy.
- This finding does not mark `CTO-WORK-020`, `CTO-WORK-016`, or Stage 2 as validated.

View File

@ -54,6 +54,7 @@ This workspace is registered as a child-local planning workspace. Registration d
| |-- CTO-CASE-PROVIDER-DECISION-PACKET-ISSUES.md | |-- CTO-CASE-PROVIDER-DECISION-PACKET-ISSUES.md
| |-- CTO-CASE-PROVIDER-DECISION-RECORD.md | |-- CTO-CASE-PROVIDER-DECISION-RECORD.md
| |-- CTO-CASE-MODEL-PROVIDER-ADMISSION.openai-codex-gpt-5.5.json | |-- CTO-CASE-MODEL-PROVIDER-ADMISSION.openai-codex-gpt-5.5.json
| |-- CTO-CASE-MODEL-PROVIDER-ADMISSION.qwen-local-qwen3.6-35b-a3b.json
| `-- CTO-CASE-AGENT-PROTOCOL-BLOCKER.md | `-- CTO-CASE-AGENT-PROTOCOL-BLOCKER.md
`-- tools/ `-- tools/
`-- validate_cto_child.py `-- validate_cto_child.py

View File

@ -140,3 +140,8 @@ items:
status: blocked status: blocked
source: .sot/03-PROTOCOLS/CTO-CASE-AGENT-PROTOCOL-BLOCKER.md source: .sot/03-PROTOCOLS/CTO-CASE-AGENT-PROTOCOL-BLOCKER.md
owner: jp owner: jp
- id: CTO-WORK-029
title: Qwen Local Case Model Admission JSON
status: validated
source: .sot/03-PROTOCOLS/CTO-CASE-MODEL-PROVIDER-ADMISSION.qwen-local-qwen3.6-35b-a3b.json
owner: ""

View File

@ -40,6 +40,7 @@ REQUIRED_FILES = [
".sot/03-PROTOCOLS/CTO-CASE-PROVIDER-DECISION-PACKET-ISSUES.md", ".sot/03-PROTOCOLS/CTO-CASE-PROVIDER-DECISION-PACKET-ISSUES.md",
".sot/03-PROTOCOLS/CTO-CASE-PROVIDER-DECISION-RECORD.md", ".sot/03-PROTOCOLS/CTO-CASE-PROVIDER-DECISION-RECORD.md",
".sot/03-PROTOCOLS/CTO-CASE-MODEL-PROVIDER-ADMISSION.openai-codex-gpt-5.5.json", ".sot/03-PROTOCOLS/CTO-CASE-MODEL-PROVIDER-ADMISSION.openai-codex-gpt-5.5.json",
".sot/03-PROTOCOLS/CTO-CASE-MODEL-PROVIDER-ADMISSION.qwen-local-qwen3.6-35b-a3b.json",
".sot/03-PROTOCOLS/CTO-CASE-AGENT-PROTOCOL-BLOCKER.md", ".sot/03-PROTOCOLS/CTO-CASE-AGENT-PROTOCOL-BLOCKER.md",
] ]
@ -423,6 +424,7 @@ REQUIRED_MODEL_PROVIDER_ADMISSION_ISSUE_IDS = [
"CTO-WORK-019", "CTO-WORK-019",
"CTO-WORK-020", "CTO-WORK-020",
"CTO-WORK-027", "CTO-WORK-027",
"CTO-WORK-029",
] ]
REQUIRED_MODEL_PROVIDER_ADMISSION_ISSUE_PHRASES = [ REQUIRED_MODEL_PROVIDER_ADMISSION_ISSUE_PHRASES = [
@ -480,6 +482,15 @@ REQUIRED_OPENAI_CODEX_ADMISSION_JSON = {
"approval_source": "JP chat approval on 2026-05-31", "approval_source": "JP chat approval on 2026-05-31",
} }
REQUIRED_QWEN_LOCAL_ADMISSION_JSON = {
"status": "admitted",
"provider": "qwen-local",
"model": "qwen3.6-35b-a3b",
"credential_source_class": "pi-models-json-local-provider-no-secret",
"allowed_network_class": "local-tailscale-vllm-spark1",
"approval_source": "JP chat approval on 2026-05-31",
}
REQUIRED_LOCAL_PROVIDER_ROUTE_PRD_PHRASES = [ REQUIRED_LOCAL_PROVIDER_ROUTE_PRD_PHRASES = [
"Local planning SOT only. Not a Core Protocol. Not active Core authority.", "Local planning SOT only. Not a Core Protocol. Not active Core authority.",
"`CTO-WORK-020` remains blocked until a provider policy decision exists.", "`CTO-WORK-020` remains blocked until a provider policy decision exists.",
@ -893,6 +904,30 @@ def main() -> int:
if key.lower() in {"api_key", "apikey", "access_token", "token", "secret", "password", "credential_value"}: if key.lower() in {"api_key", "apikey", "access_token", "token", "secret", "password", "credential_value"}:
errors.append(f"openai_codex_admission_forbidden_secret_key:{key}") errors.append(f"openai_codex_admission_forbidden_secret_key:{key}")
qwen_local_admission = ROOT / ".sot/03-PROTOCOLS/CTO-CASE-MODEL-PROVIDER-ADMISSION.qwen-local-qwen3.6-35b-a3b.json"
if qwen_local_admission.is_file():
checked.append("qwen_local_admission_json:parse")
try:
payload = json.loads(qwen_local_admission.read_text(encoding="utf-8"))
except json.JSONDecodeError as exc:
errors.append(f"qwen_local_admission_invalid_json:{exc}")
payload = {}
if not isinstance(payload, dict):
errors.append("qwen_local_admission_must_be_object")
payload = {}
for key, expected in REQUIRED_QWEN_LOCAL_ADMISSION_JSON.items():
checked.append(f"qwen_local_admission_json:{key}")
if payload.get(key) != expected:
errors.append(f"qwen_local_admission_mismatch:{key}:expected_{expected}:actual_{payload.get(key)}")
for key in ["admission_timestamp", "review_trigger"]:
checked.append(f"qwen_local_admission_json:{key}")
if not isinstance(payload.get(key), str) or not payload.get(key):
errors.append(f"qwen_local_admission_missing:{key}")
for key in payload:
checked.append(f"qwen_local_admission_json_secret_key:{key}")
if key.lower() in {"api_key", "apikey", "access_token", "token", "secret", "password", "credential_value"}:
errors.append(f"qwen_local_admission_forbidden_secret_key:{key}")
local_provider_route_prd = ROOT / ".sot/03-PROTOCOLS/CTO-CASE-LOCAL-PROVIDER-ROUTE-PRD.md" local_provider_route_prd = ROOT / ".sot/03-PROTOCOLS/CTO-CASE-LOCAL-PROVIDER-ROUTE-PRD.md"
if local_provider_route_prd.is_file(): if local_provider_route_prd.is_file():
text = local_provider_route_prd.read_text(encoding="utf-8") text = local_provider_route_prd.read_text(encoding="utf-8")
@ -1017,6 +1052,7 @@ def main() -> int:
"CTO-WORK-025": "validated", "CTO-WORK-025": "validated",
"CTO-WORK-026": "validated", "CTO-WORK-026": "validated",
"CTO-WORK-027": "validated", "CTO-WORK-027": "validated",
"CTO-WORK-029": "validated",
} }
for issue_id, expected in expected_statuses.items(): for issue_id, expected in expected_statuses.items():
checked.append(f"workboard_status:{issue_id}:{expected}") checked.append(f"workboard_status:{issue_id}:{expected}")
@ -1067,6 +1103,8 @@ def main() -> int:
errors.append("workboard_missing_provider_decision_record_source") errors.append("workboard_missing_provider_decision_record_source")
if "CTO-CASE-MODEL-PROVIDER-ADMISSION.openai-codex-gpt-5.5.json" not in text: if "CTO-CASE-MODEL-PROVIDER-ADMISSION.openai-codex-gpt-5.5.json" not in text:
errors.append("workboard_missing_openai_codex_admission_json_source") errors.append("workboard_missing_openai_codex_admission_json_source")
if "CTO-CASE-MODEL-PROVIDER-ADMISSION.qwen-local-qwen3.6-35b-a3b.json" not in text:
errors.append("workboard_missing_qwen_local_admission_json_source")
payload = { payload = {
"ok": not errors, "ok": not errors,