From 81ebbc7666830cd80c17c44eca50e8943c3e89a8 Mon Sep 17 00:00:00 2001 From: Svrnty Date: Sun, 31 May 2026 19:26:27 -0400 Subject: [PATCH] Add CTO Case provider admission route --- README.md | 4 +- WORKBOARD.yaml | 10 +++ .../CTO-CASE-PROVIDER-ADMISSION-ISSUES.md | 45 +++++++++++++ .../CTO-CASE-PROVIDER-ADMISSION-PRD.md | 67 +++++++++++++++++++ tools/validate_cto_child.py | 65 ++++++++++++++++++ 5 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 sot/03-PROTOCOLS/CTO-CASE-PROVIDER-ADMISSION-ISSUES.md create mode 100644 sot/03-PROTOCOLS/CTO-CASE-PROVIDER-ADMISSION-PRD.md diff --git a/README.md b/README.md index 1a41b69..a55e1a9 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,9 @@ This workspace is registered as a child-local planning workspace. Registration d | |-- CTO-CASE-STAGE1-GATED-ENGINE-PRD.md | |-- CTO-CASE-STAGE1-GATED-ENGINE-ISSUES.md | |-- CTO-CASE-STAGE2-ARTIFICIAL-FIXTURE-PRD.md -| `-- CTO-CASE-STAGE2-ARTIFICIAL-FIXTURE-ISSUES.md +| |-- CTO-CASE-STAGE2-ARTIFICIAL-FIXTURE-ISSUES.md +| |-- CTO-CASE-PROVIDER-ADMISSION-PRD.md +| `-- CTO-CASE-PROVIDER-ADMISSION-ISSUES.md `-- tools/ `-- validate_cto_child.py ``` diff --git a/WORKBOARD.yaml b/WORKBOARD.yaml index 9461c70..ebc3608 100644 --- a/WORKBOARD.yaml +++ b/WORKBOARD.yaml @@ -60,3 +60,13 @@ items: status: blocked source: sot/03-PROTOCOLS/CTO-CASE-STAGE2-ARTIFICIAL-FIXTURE-ISSUES.md owner: jp + - id: CTO-WORK-013 + title: Case Provider Admission PRD + status: validated + source: sot/03-PROTOCOLS/CTO-CASE-PROVIDER-ADMISSION-PRD.md + owner: jp + - id: CTO-WORK-014 + title: Hermes Case CLI Task Adapter Route + status: candidate + source: sot/03-PROTOCOLS/CTO-CASE-PROVIDER-ADMISSION-ISSUES.md + owner: jp diff --git a/sot/03-PROTOCOLS/CTO-CASE-PROVIDER-ADMISSION-ISSUES.md b/sot/03-PROTOCOLS/CTO-CASE-PROVIDER-ADMISSION-ISSUES.md new file mode 100644 index 0000000..da27eaf --- /dev/null +++ b/sot/03-PROTOCOLS/CTO-CASE-PROVIDER-ADMISSION-ISSUES.md @@ -0,0 +1,45 @@ +--- +title: CTO Case Provider Admission Issues +status: draft +lifecycle_classification: sot +owner: jp +created: 2026-05-31 +last_reviewed: 2026-05-31 +core_promotion_status: not-promoted +route: cto +--- + +# CTO Case Provider Admission Issues + +Local planning SOT only. Not a Core Protocol. Not active Core authority. + +## CTO-WORK-013 - Case Provider Admission PRD + +Status: validated. + +Register the provider-admission product requirement that separates discovery evidence from executable admission. + +Acceptance: + +- Records WorkOS Case source as `https://github.com/workos/case.git`. +- Records pinned commit `7959ac917cdeb0983b4aaa20bb9f42021747fed8`. +- Records that the CLI binary is `ca`. +- Records that `case` on public npm is not WorkOS Case. +- Records that Bun and `bun run build:binary` are required for `dist/ca`. +- Records that Stage 2 must use `ca run --task `. + +## CTO-WORK-014 - Hermes Case CLI Task Adapter Route + +Status: candidate. + +Implement the smallest Hermes CTO harness change that converts the Stage 2 artificial fixture contract into a Case task file and invokes the admitted Case provider with the correct command shape. + +Acceptance: + +- `CTO_HARNESS_CASE_BIN` points to an admitted `ca` executable. +- Stage 2 invokes `ca run --task `. +- The adapter does not pass a raw prompt as argv. +- Missing provider, wrong provider, wrong command shape, or wrong task contract blocks. +- The Stage 2 pass report is produced only by real Case execution. +- Provider-unavailable fail-closed behavior remains tested. +- No Target Repository path is inspected or copied. diff --git a/sot/03-PROTOCOLS/CTO-CASE-PROVIDER-ADMISSION-PRD.md b/sot/03-PROTOCOLS/CTO-CASE-PROVIDER-ADMISSION-PRD.md new file mode 100644 index 0000000..1b44bc5 --- /dev/null +++ b/sot/03-PROTOCOLS/CTO-CASE-PROVIDER-ADMISSION-PRD.md @@ -0,0 +1,67 @@ +--- +title: CTO Case Provider Admission PRD +status: draft +lifecycle_classification: sot +owner: jp +created: 2026-05-31 +last_reviewed: 2026-05-31 +core_promotion_status: not-promoted +route: cto +--- + +# CTO Case Provider Admission PRD + +Local planning SOT only. Not a Core Protocol. Not active Core authority. + +## Purpose + +Unblock Stage 2 by admitting a real WorkOS Case executable through a governed provider route, without treating Case as Cortex authority and without mutating any target repository. + +## Current Evidence + +- Source repo: `https://github.com/workos/case.git`. +- Pinned source commit: `7959ac917cdeb0983b4aaa20bb9f42021747fed8`. +- Package name: `case`. +- Package status: `private: true`. +- Public npm package `case` is not WorkOS Case. +- Case CLI binary name is `ca`, because `case` is a shell reserved word. +- Case setup requires Bun. +- Case standalone executable is produced by `bun run build:binary` as `dist/ca`. +- Case task execution uses `ca run --task ` or `ca session --task `. + +## Problem + +The Hermes CTO harness has a provider-unavailable failure path, but it does not yet have an admitted durable Case provider. `CTO_HARNESS_CASE_BIN` alone is insufficient if the adapter passes a raw prompt as argv. WorkOS Case expects a task file and a Case command shape, not an arbitrary prompt string. + +## Product Requirement + +Create a provider admission route that proves the exact executable, command contract, and task contract before Stage 2 can pass. + +## Required Contract + +- The provider path must be explicit and durable; `/tmp` clones are discovery evidence only. +- The provider must be pinned to `7959ac917cdeb0983b4aaa20bb9f42021747fed8` or a later recorded pin. +- The provider must identify itself as WorkOS Case, not the unrelated npm package. +- The adapter must call `ca run --task ` for Stage 2 artificial fixture work. +- The adapter must not pass the task brief as a raw positional prompt. +- The task file must contain no Target Repository path for Stage 2. +- The run must preserve `Stage 2 allowed mutation scope is copied artificial case only`. +- Missing Bun, missing `dist/ca`, wrong commit, wrong command shape, or wrong task file means blocked. +- Case may execute only inside the Harness Evidence Interface. +- Case may recommend. Case must not approve itself. + +## Acceptance Evidence + +- Provider admission report records executable path, source URL, pinned commit, build command, binary digest, and command shape. +- Stage 2 pass report exists only after a real `ca run --task ` execution. +- Provider-unavailable report remains available and fail-closed. +- Fake remains the default validation lane. +- No Cortex Core, Case source, vendor source, or Target Repository file is mutated. + +## Explicit Non-Goals + +- Do not vendor Case source into Cortex OS Core. +- Do not install or use the unrelated npm `case` package. +- Do not skip Stage 2. +- Do not authorize copied repo, sandbox repo, owned repo, default backend, WebUI product, or Core promotion behavior. +- Do not treat Case as CTO authority. diff --git a/tools/validate_cto_child.py b/tools/validate_cto_child.py index 485dbab..a5112a5 100644 --- a/tools/validate_cto_child.py +++ b/tools/validate_cto_child.py @@ -28,6 +28,8 @@ REQUIRED_FILES = [ "sot/03-PROTOCOLS/CTO-CASE-STAGE1-GATED-ENGINE-ISSUES.md", "sot/03-PROTOCOLS/CTO-CASE-STAGE2-ARTIFICIAL-FIXTURE-PRD.md", "sot/03-PROTOCOLS/CTO-CASE-STAGE2-ARTIFICIAL-FIXTURE-ISSUES.md", + "sot/03-PROTOCOLS/CTO-CASE-PROVIDER-ADMISSION-PRD.md", + "sot/03-PROTOCOLS/CTO-CASE-PROVIDER-ADMISSION-ISSUES.md", ] REQUIRED_BRIEF_PHRASES = [ @@ -252,6 +254,37 @@ REQUIRED_STAGE2_ISSUE_IDS = [ "CTO-WORK-012", ] +REQUIRED_PROVIDER_ADMISSION_PRD_PHRASES = [ + "Local planning SOT only. Not a Core Protocol. Not active Core authority.", + "https://github.com/workos/case.git", + "7959ac917cdeb0983b4aaa20bb9f42021747fed8", + "Package status: `private: true`.", + "Public npm package `case` is not WorkOS Case.", + "Case CLI binary name is `ca`", + "Case setup requires Bun.", + "bun run build:binary", + "dist/ca", + "ca run --task ", + "ca session --task ", + "CTO_HARNESS_CASE_BIN", + "WorkOS Case expects a task file and a Case command shape, not an arbitrary prompt string.", + "The provider path must be explicit and durable", + "The adapter must not pass the task brief as a raw positional prompt.", + "The task file must contain no Target Repository path for Stage 2.", + "Missing Bun, missing `dist/ca`, wrong commit, wrong command shape, or wrong task file means blocked.", + "Case may execute only inside the Harness Evidence Interface.", + "Case may recommend. Case must not approve itself.", + "Stage 2 pass report exists only after a real `ca run --task ` execution.", + "Fake remains the default validation lane.", + "Do not install or use the unrelated npm `case` package.", + "Do not treat Case as CTO authority.", +] + +REQUIRED_PROVIDER_ADMISSION_ISSUE_IDS = [ + "CTO-WORK-013", + "CTO-WORK-014", +] + def workboard_status(text: str, issue_id: str) -> str | None: pattern = rf"- id: {re.escape(issue_id)}\n(?: .+\n)*? status: ([^\n]+)" @@ -399,6 +432,28 @@ def main() -> int: if issue_id not in text: errors.append(f"missing_stage2_issue_id:{issue_id}") + provider_admission_prd = ROOT / "sot/03-PROTOCOLS/CTO-CASE-PROVIDER-ADMISSION-PRD.md" + if provider_admission_prd.is_file(): + text = provider_admission_prd.read_text(encoding="utf-8") + if "core_promotion_status: not-promoted" not in text: + errors.append("provider_admission_prd_missing_not_promoted_frontmatter") + for phrase in REQUIRED_PROVIDER_ADMISSION_PRD_PHRASES: + checked.append(f"provider_admission_prd_phrase:{phrase}") + if phrase not in text: + errors.append(f"missing_provider_admission_prd_phrase:{phrase}") + + provider_admission_issues = ROOT / "sot/03-PROTOCOLS/CTO-CASE-PROVIDER-ADMISSION-ISSUES.md" + if provider_admission_issues.is_file(): + text = provider_admission_issues.read_text(encoding="utf-8") + if "core_promotion_status: not-promoted" not in text: + errors.append("provider_admission_issues_missing_not_promoted_frontmatter") + if "Local planning SOT only. Not a Core Protocol. Not active Core authority." not in text: + errors.append("provider_admission_issues_missing_local_planning_notice") + for issue_id in REQUIRED_PROVIDER_ADMISSION_ISSUE_IDS: + checked.append(f"provider_admission_issue_id:{issue_id}") + if issue_id not in text: + errors.append(f"missing_provider_admission_issue_id:{issue_id}") + board = ROOT / "WORKBOARD.yaml" if board.is_file(): text = board.read_text(encoding="utf-8") @@ -414,6 +469,10 @@ def main() -> int: checked.append(f"workboard_id:{issue_id}") if issue_id not in text: errors.append(f"missing_workboard_id:{issue_id}") + for issue_id in REQUIRED_PROVIDER_ADMISSION_ISSUE_IDS: + checked.append(f"workboard_id:{issue_id}") + if issue_id not in text: + errors.append(f"missing_workboard_id:{issue_id}") expected_statuses = { "CTO-WORK-002": "validated", "CTO-WORK-003": "validated", @@ -426,6 +485,8 @@ def main() -> int: "CTO-WORK-010": "validated", "CTO-WORK-011": "validated", "CTO-WORK-012": "blocked", + "CTO-WORK-013": "validated", + "CTO-WORK-014": "candidate", } for issue_id, expected in expected_statuses.items(): checked.append(f"workboard_status:{issue_id}:{expected}") @@ -452,6 +513,10 @@ def main() -> int: errors.append("workboard_missing_stage2_prd_source") if "CTO-CASE-STAGE2-ARTIFICIAL-FIXTURE-ISSUES.md" not in text: errors.append("workboard_missing_stage2_issues_source") + if "CTO-CASE-PROVIDER-ADMISSION-PRD.md" not in text: + errors.append("workboard_missing_provider_admission_prd_source") + if "CTO-CASE-PROVIDER-ADMISSION-ISSUES.md" not in text: + errors.append("workboard_missing_provider_admission_issues_source") payload = { "ok": not errors,