Add CTO Case provider admission route

This commit is contained in:
Svrnty 2026-05-31 19:26:27 -04:00
parent 6afe95f6b6
commit 81ebbc7666
5 changed files with 190 additions and 1 deletions

View File

@ -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
```

View File

@ -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

View File

@ -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 <task-file>`.
## 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 <task-file>`.
- 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.

View File

@ -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 <task-file>` or `ca session <repo-path> --task <task-file>`.
## 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 <task-file>` 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 <task-file>` 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.

View File

@ -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 <task-file>",
"ca session <repo-path> --task <task-file>",
"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 <task-file>` 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,