Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 8 additions & 1 deletion cocoder/PRIORITIES.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ Slim index of active and archived priorities. Open a priority's folder for detai

| Slug | Description | Status | Canon | Owner | Blocked on |
|---|---|---|---|---|---|
| [`v0.1-foundation`](./priorities/v0.1-foundation/README.md) | Ship CoCoder v0.1 — extraction, Oz MVP, docs, public publish | Active | Expand — **Sub-Playbook D doc + CI-gate authoring COMPLETE on branch `v0.1-publish`** (run 1wna3uxq). Only founder release (merge → CI → `v0.1.0` tag) remains. | Bob + founder | **Next (founder):** review `v0.1-publish` → merge to `main` (CI = D-S2 Class A) → tag `v0.1.0`. B/C Refines parallel (founder). |
| [`v0.1-foundation`](./priorities/v0.1-foundation/README.md) | Ship CoCoder v0.1 — extraction, Oz MVP, docs, public publish | Shipped | **`v0.1.0` tagged + released 2026-05-27** (merged to `main`, CI green). | Bob + founder | **Archival ceremony folded into v0.5 Phase 3** (carryover: ADR-0011 + P-R1/P-R3, then archive). |
| [`v0.5-orchestration-services`](./priorities/v0.5-orchestration-services/README.md) | Cheap/fast-model admin delegation — Oscar offloads wrap/compaction/teardown to bounded services | **Active** | Adoption — engine + launch config (route + boundary) now on `main` (ADR-0009) | Bob + founder | **Sequenced before v0.4** (founder 2026-05-27). **Now launchable from Oz.** Next: Phase 2 (reconcile PR #51) + Phase 3 (adoption + v0.1 carryover/archive). |

## Draft

Expand Down Expand Up @@ -65,3 +66,9 @@ Slim index of active and archived priorities. Open a priority's folder for detai
**Summary:** Turn Oz into a real operator control plane — a per-workspace, in-dashboard headless chatbot that is the primary command interface and the primary watcher/debugger for every run.
**What:** Build the Oz UI per [ADR-0008](./decisions/0008-oz-control-plane-architecture.md) (Dashboard with Oz chat + drag-reorder priorities + ad-hoc run launcher; Workspaces with primary/writable/read-only roots; CLIs with Test; Personas with CLI/model + sub-agent hierarchy + visible/headless; Runs list+detail; Settings) plus the Oz oversight/debugger mechanism. Screen/flow brief + design prompt in `docs/oz-design-brief.md`. Root roles per ADR-0007 (revised 2026-05-27).
**Status:** Draft (stub). Founder decision on sequencing. Depends on the claude.ai/design output + ADR-0008. Authored 2026-05-27 per founder ask. See [`priorities/v0.4-oz-control-plane/README.md`](./priorities/v0.4-oz-control-plane/README.md).

### [v0.5-orchestration-services](./priorities/v0.5-orchestration-services/README.md)
**Owner:** Bob + founder
**Summary:** Let Oscar run faster/cheaper models for repeatable admin work (priority/handoff editing, run wrap-up, teardown) via bounded non-persona orchestration services, instead of spending lead-model context.
**What:** Declarative services (`packages/core/services/*.json`) + two contracts + `lib/services.mjs` (build/validate/execute packet with deterministic git write-audit) + 5 CLI commands + a headless `cursor-agent-service` adapter. 11 services shipped. Services never commit/finalize/supersede (Oscar-only route control); adapter+model configurable per service (`cursor-agent` default). Oz unchanged (ADR-0008 preserved).
**Status:** **Active — engine + launch config (route entry + boundary) landed on `main` (ADR-0009; convergence 2026-05-27). Sequenced BEFORE v0.4 (founder). Launchable from Oz now.** Next: Phase 2 (reconcile PR #51 onto main — general orchestration infra; leave v0.4 design for the v0.4 run) + Phase 3 (adoption: wire services into Oscar's live wrap/teardown flow, prove headless `cursor-agent` end-to-end, verify Oz run-detail surfacing; v0.1 carryover: ADR-0011 + P-R1/P-R3 or waive B/C refines, then archive v0.1-foundation; add ghost-priority/dangling-ADR guard). Full brief in [`priorities/v0.5-orchestration-services/README.md`](./priorities/v0.5-orchestration-services/README.md).
13 changes: 13 additions & 0 deletions cocoder/SESSION_LOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,19 @@ Append-only log of work sessions. New entries at the **top**. One entry per mean

---

## 2026-05-27 — **Orchestration-services convergence: landed orphaned PR #50 onto `main` (ADR-0009 engine + v0.5 priority + route/boundary); v0.5 now launchable**

**Persona:** Oscar (lead, founder-authorized one-time config scope) | **Priority:** v0.5-orchestration-services | **Run:** 1wna3uxq

**Outcomes:**
- **Diagnosed an orchestration failure:** parallel branches minted governance on a "reconcile at merge" plan that never merged — PR #50 (orchestration-services engine + ADR-0009 + v0.5 priority) sat orphaned off pre-v0.1 `main`; `v0.5` was a ghost (in the route's `supportedPriorityOwners` but not `PRIORITIES.md`); ADR-0009 was a dangling reference; and the launch config (route/boundary) was split from the priority. v0.5 was hard-blocked from launching on every branch.
- **Founder authorized (A): one-time config convergence onto `main`.** Merged `main` into the PR #50 branch (resolved `PRIORITIES.md`/`SESSION_LOG` to main + re-added v0.5), fixed `wrap-execution.json` (dropped `orchestrator-commit`/`finalize-run-status` from `requiredChecks` per the CoBuilder prior-fix), set `oscar-lead` route to `bounded-writers` + added v0.4/v0.5 owners, and brought the v0.5 priority-boundary. Verified `main` and `oz-control-plane-design` launcher code are **identical** — convergence stays config-only.
- **Reviewed PR #50:** engine enforces `decisionAuthority: oscar-only` + `forbiddenDecisions` + a blocking before/after git write-audit + headless argv; adapter+model configurable per service (`cursor-agent` default) — implements ADR-0008's per-call CLI+model clause (v0.4 builds the UI on top).

**Next:** Phase 2 — reconcile PR #51 (`oz-control-plane-design`) onto `main` (general infra; leave v0.4 design for the v0.4 run). Phase 3 — v0.5 adoption (wire services into live wrap/teardown, prove headless `cursor-agent` e2e, verify Oz surfacing) + v0.1 carryover (ADR-0011 + P-R1/P-R3 or waive B/C refines) + **archive v0.1-foundation** + add a ghost-priority/dangling-ADR guard. v0.5 is now launchable from Oz once PR #50 squash-merges.

---

## 2026-05-27 — **v0.1 publish surfaces complete on clean branch `v0.1-publish` (Option A disentangle); D-S1 removed; ready for founder release**

**Persona:** Oscar (lead) + Bob (builder, codex) | **Priority:** v0.1-foundation | **Plan:** [`plans/2026-05-21-docs-publish.plan.md`](./priorities/v0.1-foundation/plans/2026-05-21-docs-publish.plan.md) | **Run:** 1wna3uxq
Expand Down
45 changes: 45 additions & 0 deletions cocoder/decisions/0009-orchestration-services.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
id: ADR-0009
title: "Non-persona orchestration services (cheap-model admin delegation)"
status: accepted
date: 2026-05-27
relates-to: ADR-0002, ADR-0004, ADR-0008
---

# ADR-0009: Non-persona orchestration services

## Context

The lead orchestrator (Oscar) spends expensive lead-model context on repeatable, mechanical administrative work: wrap cleanup, handoff/priority compaction, run summaries, evidence collation, result-contract repair, commit-boundary and startup-context audits, and teardown-readiness checks. None of this needs lead-model judgment, yet today it either runs as deterministic CLI checks (a subset) or falls to Oscar directly.

CoCoder already has model-role assignment (`lib/model-roles.mjs`) for the *build* side — `orchestrator`, `builder`, `builderSubagents`, `planning`, `research` — but those are static, route-scoped lane assignments resolved at launch. There was **no** mechanism for the lead to offload its *own* admin work to a cheaper/faster model on demand, with bounded writes and verification. [ADR-0008](./0008-oz-control-plane-architecture.md) point 6 already reserved the slot ("a persona may delegate to **sub-agents/services that each independently select CLI + model**"); this ADR implements it. The pattern is ported from CoBuilder (upstream extraction reference per [ADR-0001](./0001-storage-and-license.md)).

## Decision

1. **Orchestration services are non-persona, bounded administrative execution units.** They are not agents and create no durable personas. Oscar may invoke a service when work is mechanical and scoped; Oscar retains all judgment (priority, architecture, scope, founder decisions, completion).

2. **Services are declarations, not runtime code.** Each service is a JSON file at `packages/core/services/<service-id>.json` declaring `id`, `label`, `mode` (`read-only` | `bounded-write` | `control-plane`), `purpose`, `execution` (model/executor guidance), `allowedWriteScopes`, and `requiredChecks`. Adding a service is a new declaration, **not** a runtime-code edit — `lib/services.mjs` must not become a catalog god file. Two hand-written JSON contracts validate the surface: `orchestration-service-declaration.schema.json` (registry entry) and `orchestration-service.schema.json` (the **packet**). These follow the same custom `{ contract, required, fields, rules }` shape and `lib/contracts.mjs` validator as the existing 12 core contracts; per [ADR-0004](./0004-typescript-validation-toolchain.md), the Zod→JSON-Schema rule governs `packages/schemas` config/Oz schemas, not the copy-verbatim orchestration contracts.

3. **A service packet binds one execution.** `build-service-packet` instantiates a declaration against exact run context + Oscar's decision input, narrowing the declaration's broad `allowedWriteScopes` to the exact `allowedWrites` for that run, and freezing `decisionAuthority: oscar-only`, `executionAuthority: orchestration-service`, and a fixed `forbiddenDecisions` list. The packet delegates execution only.

4. **Headless execution + deterministic write-audit.** `execute-service-packet` runs the packet headlessly (default executor `cursor-agent`, argv array — no shell interpolation), capturing a service-result JSON and transcript under `<runDir>/services/<packetId>/`. A before/after `git status --porcelain` audit blocks acceptance — forcing `BLOCK` even on a claimed `PASS` — if any write lands outside `allowedWrites` (or any write at all for a read-only service). Failures return diagnosis + proposedFix + nextAction to Oscar, who fixes in scope or recommends the Orchestrator Debugger.

5. **Eleven services ship at adoption.** `startup-context-audit`, `handoff-compaction`, `wrap-execution`, `evidence-collation`, `commit-boundary-audit`, `result-contract-repair`, `run-summary`, `next-run-packet`, `doc-hygiene`, `teardown-readiness`, `regression-triage`. Write scopes were path-scrubbed to CoCoder's layout (`cocoder/PRIORITIES.md`, `cocoder/SESSION_LOG.md`, `cocoder/plans/*.md`, `cocoder/priorities/*/plans/*.md`, `cocoder/priorities/zArchive/INDEX.md`, run results under `local/workspaces/*/runs/*/jobs/*`).

6. **The debugger recognizes the pattern.** Future debugger sessions suggest a service when an issue is recurring, mechanical, bounded, and administrative — and explicitly **not** for founder judgment, priority ordering, architecture direction, persona-dispatch judgment, or Bob/Talia/Phil/Quinn/Ian domain work ([ADR-0002](./0002-talia-quinn-boundary.md) boundaries).

7. **A dedicated `cursor-agent-service` adapter** declares the headless, write-capable executor profile (`interactive: false`, `sandboxModes: [danger-full-access]`, `resultContract: orchestration-service-packet`) as registry metadata, leaving the existing interactive `cursor-agent` adapter (resultContract `job-result`) untouched.

## Consequences

- **Oz requires no change ([ADR-0008](./0008-oz-control-plane-architecture.md) preserved).** Services run externally (Oscar / `cursor-agent`) and write artifacts under the run directory; Oz observes them as ordinary run artifacts in run detail. The capability lives entirely in the orchestration-services / `packages/core` layer.
- Complements `model-roles.mjs`: cheap models on the *build* side (subagents/planning/research) and now on the *lead/admin* side (services).
- New surface: `packages/core/services/`, two contracts, `lib/services.mjs`, 5 CLI commands (`list-orchestration-services`, `validate-orchestration-services`, `build-service-packet`, `validate-service-packet`, `execute-service-packet`), a session-wrap fragment bullet, and debugger guidance. Suite: 346/346 core, 8/8 oz-daemon, 10/10 oz-dashboard.
- **Adoption is pending** (tracked under `v0.5-orchestration-services`): wiring services into Oscar's live wrap/teardown flow, proving headless `cursor-agent` execution end-to-end against a real run, and surfacing service results in Oz run detail.

## Alternatives considered

- **Extend `model-roles.mjs` to cover admin work** — rejected; model-roles are static launch-time lane assignments, not on-demand bounded packets with write-audit. Different shape, different lifecycle.
- **Make each service a persona/sub-agent** — rejected; services must carry no judgment authority. Persona framing would invite scope creep and a durable-identity surface the pattern explicitly avoids.
- **Overwrite the interactive `cursor-agent` adapter with the headless profile** (upstream's exact shape) — rejected; it would flip `interactive`→false and `resultContract`→`orchestration-service-packet`, breaking the prior-session interactive adapter. A separate adapter id keeps both intents.
- **Write service results under `jobs/<lane>/`** — rejected; services are not personas/lanes. `<runDir>/services/<packetId>/` keeps the persona job space clean and matches upstream.
3 changes: 2 additions & 1 deletion cocoder/decisions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ Numbered, dated, single-purpose decisions. Each ADR captures **context → decis
| [ADR-0006](./0006-no-nested-workspaces-inside-install.md) | No workspaces nested inside the CoCoder install repository | accepted | 2026-05-22 |
| [ADR-0007](./0007-workspace-files-and-multiroot-description.md) | Workspace files — storage location and the multi-root description convention | accepted (revised 2026-05-27) | 2026-05-26 |
| [ADR-0008](./0008-oz-control-plane-architecture.md) | Oz control-plane architecture | accepted | 2026-05-27 |
| [ADR-0009](./0009-orchestration-services.md) | Non-persona orchestration services (cheap-model admin delegation) | accepted | 2026-05-27 |

## Pending / proposed

(None — next ADR number is 0009.)
(None — next ADR number is 0010.)

## Authoring guide

Expand Down
19 changes: 19 additions & 0 deletions cocoder/personas/PORT-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,22 @@ Paths in committed fixtures use `__REPO_ROOT__` token; tests hydrate with the ch
| Phil working example | `examples/personas/phil-primitive-builder/` | CoCoder-neutral "Workshop Toolsmith" domain; not CoBuilder primitives. |
| Public playbooks | `cocoder/personas/playbooks/{bob,talia,oscar,phil}.md` | Authored fresh; not copied from CoBuilder private playbooks. |
| Private operator pattern | `cocoder/personas/playbooks/README-private-operator-pattern.md` + template `local/README.md` | Documents `<workspace>/cocoder/local/playbooks/`. |

## Orchestration-services import (2026-05-27) — ADR-0009

Ported CoBuilder's non-persona orchestration-services pattern. Source root: `/Volumes/NAS LOCAL/CoBuilder/infrastructure/cobuilder-build/orchestration/`. This port is **runtime/contracts**, not personas, but the scrubs are recorded here as the canonical CoBuilder→CoCoder divergence log.

| Borrowed file (CoBuilder) | Target in CoCoder | Scrub / divergence |
|---|---|---|
| `core/lib/services.mjs` | `packages/core/lib/services.mjs` | **3 scrubs, logic verbatim:** (1) `DEFAULT_SERVICES_DIR` resolved module-relative (`../services` via `fileURLToPath`) instead of `repoPath('cobuilder-build/orchestration/services')` — services ship inside the package like `contracts/`+`adapters/`; (2) dropped the now-unused `repoPath` import; (3) `renderServicePrompt` "CoBuilder orchestration service packet" → "CoCoder". Reuses CoCoder's existing `lib/contracts.mjs` `loadContracts`/`validateInstance` (same names/shape upstream uses) — **no AJV introduced**. |
| `contracts/orchestration-service-declaration.schema.json` | `packages/core/contracts/orchestration-service-declaration.schema.json` | Verbatim (repo-agnostic custom `{contract,required,fields,rules}` shape; loads via existing `contracts.mjs`). |
| `contracts/orchestration-service.schema.json` | `packages/core/contracts/orchestration-service.schema.json` | Verbatim (the packet contract; `createdAt: iso-datetime` validates via the Bug-B `matchesType` fix). |
| `services/*.json` (11) | `packages/core/services/*.json` (11) | Verbatim **except `allowedWriteScopes` path scrubs** (read-only services unchanged — empty scopes): `cobuilder-build/PRIORITIES.md`→`cocoder/PRIORITIES.md`; `cobuilder-build/SESSION_LOG.md`→`cocoder/SESSION_LOG.md`; `SESSION_LOG_ARCHIVE.md` same prefix swap; `cobuilder-build/plans/*.md`→`cocoder/plans/*.md` **+ added `cocoder/priorities/*/plans/*.md`** (most CoCoder plans live under the priority folder); `cobuilder-build/PRIORITIES-ARCHIVE.md`→`cocoder/priorities/zArchive/INDEX.md` (CoCoder has no PRIORITIES-ARCHIVE.md); `cobuilder-build/orchestration/runs/*/jobs/*/result.{json,md}`→`local/workspaces/*/runs/*/jobs/*/result.{json,md}`. `requiredChecks` verbatim — all gate/command names (`check-handoff-consistency`, `check-session-log-hygiene`, `gate-result`, `orchestrator-commit`, `finalize-run-status`, `check-doc-refs`, …) already exist in CoCoder's CLI. |
| `adapters/cursor-agent.json` (repurposed headless) | `packages/core/adapters/cursor-agent-service.json` (**new id**) | Founder decision: do NOT overwrite CoCoder's interactive `cursor-agent.json` (resultContract `job-result`). New separate adapter declares the headless profile (`interactive:false`, `sandboxModes:[danger-full-access]`, `approvalModes:[never]`, `resultContract:orchestration-service-packet`). The executor hardcodes its own `cursor-agent` flags, so this adapter is registry metadata only. |
| `core/cli.mjs` service commands (5) | `packages/core/cli/registry.mjs` handlers + `commandRegistry` + `cli/help.mjs` | Same 5 commands. Added `service`/`executorCommand`/`model` to the `parseArgs` string allow-list in `cli/shared.mjs` (must not be `path.resolve`d). Added `DEFAULT_SERVICES_DIR`. Help baseline fixture `tests/fixtures/cli-help-baseline.txt` regenerated. |
| `core/lib/debugger.mjs` "Orchestration Service Pattern" section | `packages/core/lib/debugger.mjs` `renderDebuggerPrompt` | Additive prompt text only (no change to evidence APIs Oz reuses). Path scrub `cobuilder-build/orchestration/services/<id>.json`→`packages/core/services/<id>.json`. |
| `personas/prompts/shared/session-wrap.md` (item 7) | `cocoder/personas/prompts/shared/session-wrap.md` | Added the one service-delegation bullet verbatim (no CoBuilder-specific paths in it). |
| `tests/services.test.mjs` | `packages/core/tests/services.test.mjs` | Ported; dirs resolved module-relative; fixture paths `cobuilder-build/`→`cocoder/`; out-of-scope product path → `packages/core/lib/launch.mjs`; CLI entry → `packages/core/cli.mjs`. |
| `tests/debugger.test.mjs` (service-guidance asserts) | `packages/core/tests/debugger.test.mjs` | Added 4 assertions for the new guidance section (scrubbed path). |

**Layout decision (founder):** service results land at `<runDir>/services/<packetId>/` (upstream layout preserved), not `jobs/<lane>/` — services are not personas/lanes. **Oz untouched (ADR-0008):** services execute externally and surface as ordinary run artifacts.
Loading
Loading