From ba712be2beeb0ea20f606909e84ee3e95b85c1cd Mon Sep 17 00:00:00 2001 From: Svrnty Date: Sun, 31 May 2026 21:51:18 -0400 Subject: [PATCH] Admit Qwen local Case model --- .../CTO-CASE-AGENT-PROTOCOL-BLOCKER.md | 16 ++++++++ ...TO-CASE-MODEL-PROVIDER-ADMISSION-ISSUES.md | 37 ++++++++++++++++++ ...-ADMISSION.qwen-local-qwen3.6-35b-a3b.json | 10 +++++ .../CTO-CASE-PROVIDER-DECISION-RECORD.md | 10 +++++ README.md | 1 + WORKBOARD.yaml | 5 +++ tools/validate_cto_child.py | 38 +++++++++++++++++++ 7 files changed, 117 insertions(+) create mode 100644 .sot/03-PROTOCOLS/CTO-CASE-MODEL-PROVIDER-ADMISSION.qwen-local-qwen3.6-35b-a3b.json diff --git a/.sot/03-PROTOCOLS/CTO-CASE-AGENT-PROTOCOL-BLOCKER.md b/.sot/03-PROTOCOLS/CTO-CASE-AGENT-PROTOCOL-BLOCKER.md index a33bd14..8f96f0a 100644 --- a/.sot/03-PROTOCOLS/CTO-CASE-AGENT-PROTOCOL-BLOCKER.md +++ b/.sot/03-PROTOCOLS/CTO-CASE-AGENT-PROTOCOL-BLOCKER.md @@ -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, 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 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. - Add fail-closed classification in Hermes CTO harness if needed. - 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. Forbidden next actions: diff --git a/.sot/03-PROTOCOLS/CTO-CASE-MODEL-PROVIDER-ADMISSION-ISSUES.md b/.sot/03-PROTOCOLS/CTO-CASE-MODEL-PROVIDER-ADMISSION-ISSUES.md index 8c68cb2..fc748bd 100644 --- a/.sot/03-PROTOCOLS/CTO-CASE-MODEL-PROVIDER-ADMISSION-ISSUES.md +++ b/.sot/03-PROTOCOLS/CTO-CASE-MODEL-PROVIDER-ADMISSION-ISSUES.md @@ -125,3 +125,40 @@ Acceptance: - Case retry classified the failure as `agent-protocol-error`. - `CTO-WORK-020` remains blocked because no real Case Stage 2 pass report exists. - 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. diff --git a/.sot/03-PROTOCOLS/CTO-CASE-MODEL-PROVIDER-ADMISSION.qwen-local-qwen3.6-35b-a3b.json b/.sot/03-PROTOCOLS/CTO-CASE-MODEL-PROVIDER-ADMISSION.qwen-local-qwen3.6-35b-a3b.json new file mode 100644 index 0000000..1d1581d --- /dev/null +++ b/.sot/03-PROTOCOLS/CTO-CASE-MODEL-PROVIDER-ADMISSION.qwen-local-qwen3.6-35b-a3b.json @@ -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" +} diff --git a/.sot/03-PROTOCOLS/CTO-CASE-PROVIDER-DECISION-RECORD.md b/.sot/03-PROTOCOLS/CTO-CASE-PROVIDER-DECISION-RECORD.md index 42a44dd..647c5e6 100644 --- a/.sot/03-PROTOCOLS/CTO-CASE-PROVIDER-DECISION-RECORD.md +++ b/.sot/03-PROTOCOLS/CTO-CASE-PROVIDER-DECISION-RECORD.md @@ -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. - 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. + +## 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. diff --git a/README.md b/README.md index 3559815..1068c3e 100644 --- a/README.md +++ b/README.md @@ -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-RECORD.md | |-- 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 `-- tools/ `-- validate_cto_child.py diff --git a/WORKBOARD.yaml b/WORKBOARD.yaml index 6c8a908..b1f3215 100644 --- a/WORKBOARD.yaml +++ b/WORKBOARD.yaml @@ -140,3 +140,8 @@ items: status: blocked source: .sot/03-PROTOCOLS/CTO-CASE-AGENT-PROTOCOL-BLOCKER.md 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: "" diff --git a/tools/validate_cto_child.py b/tools/validate_cto_child.py index bad9732..b1130db 100644 --- a/tools/validate_cto_child.py +++ b/tools/validate_cto_child.py @@ -40,6 +40,7 @@ REQUIRED_FILES = [ ".sot/03-PROTOCOLS/CTO-CASE-PROVIDER-DECISION-PACKET-ISSUES.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.qwen-local-qwen3.6-35b-a3b.json", ".sot/03-PROTOCOLS/CTO-CASE-AGENT-PROTOCOL-BLOCKER.md", ] @@ -423,6 +424,7 @@ REQUIRED_MODEL_PROVIDER_ADMISSION_ISSUE_IDS = [ "CTO-WORK-019", "CTO-WORK-020", "CTO-WORK-027", + "CTO-WORK-029", ] REQUIRED_MODEL_PROVIDER_ADMISSION_ISSUE_PHRASES = [ @@ -480,6 +482,15 @@ REQUIRED_OPENAI_CODEX_ADMISSION_JSON = { "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 = [ "Local planning SOT only. Not a Core Protocol. Not active Core authority.", "`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"}: 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" if local_provider_route_prd.is_file(): text = local_provider_route_prd.read_text(encoding="utf-8") @@ -1017,6 +1052,7 @@ def main() -> int: "CTO-WORK-025": "validated", "CTO-WORK-026": "validated", "CTO-WORK-027": "validated", + "CTO-WORK-029": "validated", } for issue_id, expected in expected_statuses.items(): checked.append(f"workboard_status:{issue_id}:{expected}") @@ -1067,6 +1103,8 @@ def main() -> int: errors.append("workboard_missing_provider_decision_record_source") if "CTO-CASE-MODEL-PROVIDER-ADMISSION.openai-codex-gpt-5.5.json" not in text: 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 = { "ok": not errors,