Files
openprose__prose/packages/std/composites/ensemble-synthesizer.md
irl-dan 63c8ce4b23 Migrate std and co into packages/ monorepo layout
Move the standard library (previously `github.com/openprose/std`) and
the company-as-prose library (previously local dir
`/Users/sl/code/openprose/company-as-prose`) into this repository
under `packages/std/` and `packages/co/` respectively.

Motivation: concentrate attention on one repository so stars,
discussions, and issues aggregate. `openprose/std` was a genuinely
useful asset nobody could find because ~50 stars on its own repo
told a much worse story than 1,106 stars on `openprose/prose`
would have. Same logic applies to co.

Layout choice: `packages/{std,co}/` rather than `std/` + `co/` at
the repo root. Root siblings accumulate over time, and a flat
top-level made future libraries (hub, kit, dev, etc.) compete with
spec infrastructure. `packages/` is bounded — new libraries land
there without cluttering root. Matches pnpm/Deno/monorepo tooling
conventions.

Changes:

- New: `packages/std/` (copied from openprose/std, `.git` excluded)
- New: `packages/co/` (copied from company-as-prose, README updated
  for new name and location)
- `packages/std/README.md`: updated shorthand expansion reference
- `packages/co/README.md`: renamed "company-as-prose" to "co" in
  self-references, added std-vs-co split heuristic, updated
  `prose run` examples to use `co/` shorthand
- `skills/open-prose/deps.md`:
  - `std/` shorthand now expands to
    `github.com/openprose/prose/packages/std/`
  - `co/` shorthand added, expands to
    `github.com/openprose/prose/packages/co/`
  - Both shorthands resolve into the same clone of
    `openprose/prose` under `.deps/github.com/openprose/prose/`;
    `packages/std/` and `packages/co/` are sibling subdirectories
  - `prose.lock` format row updated to `host/owner/repo sha`
    (matches the explicit-host resolution that landed in #35)
  - `.deps/` directory structure example redrawn to show the
    `{host}/{owner}/{repo}/packages/{std,co}/...` shape
  - Error message and Interaction tables refreshed accordingly
  - Resolution Algorithm step 1 now documents both shorthands
- `skills/open-prose/forme.md`: Step 2 resolution list updated to
  include co/ shorthand and the host-keyed `.deps/` layout
- `skills/open-prose/help.md`: Q&A "How do dependencies work?"
  rewritten to name both shorthands and the new explicit-host model
- `skills/open-prose/state/filesystem.md`: `.deps/` directory
  tree re-drawn to include the `{host}/` layer with std/co as
  sibling packages inside the clone
- `skills/open-prose/guidance/patterns.md`,
  `skills/open-prose/guidance/antipatterns.md`: examples now use
  the `std/` shorthand or explicit `github.com/...` rather than
  the deprecated bare `openprose/std/` form
- `skills/open-prose/examples/registry-import/index.md`: sample
  service reference switched to `std/evals/inspector`
- `README.md`: Stdlib badge replaced with internal `packages/std/`
  link plus new `packages/co/` link; "Standard Library" section
  rewritten as "Libraries" with both packages described

Out of scope for this PR (deliberately):
- Tooling changes to `prose install` and Forme's `.deps/` writer
  to adopt the `{host}/{owner}/{repo}/` layout in practice — this
  PR is spec-only. Existing tooling continues to work against
  whatever layout it currently implements; the spec now describes
  the target.
- Retiring the `openprose/std` GitHub repo. Delete that repo
  separately after this merges.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 14:14:31 -07:00

3.0 KiB

name, kind
name kind
ensemble-synthesizer composite

Ensemble-Synthesizer

K agents work independently on the same task. A synthesizer merges by reasoning about disagreements.

Description

Fans out the same task to K independent agents and synthesizes their results by reasoning about disagreements.

Metadata

  • version: 0.1.0

Slots

  • ensemble_member (primary)
    • requires: task_brief
    • ensures: result text
  • synthesizer
    • requires: K member results, original task_brief
    • ensures: synthesized result with confidence assessment

Config

  • task_brief (string, default: none): The task sent identically to every ensemble member
  • ensemble_size (integer, default: 3): Number of independent ensemble members to run

Invariants

  • All ensemble members receive the identical brief
  • Synthesizer reasons about disagreements — it does not majority-vote
  • Ensemble members are unaware of each other

Shape

  • self: fan out to K ensemble members, collect results, delegate to synthesizer
  • delegates:
    • ensemble_member: produce a result given the brief — run K times
    • synthesizer: merge K results by reasoning about disagreements
  • prohibited: none

Requires

  • &compositeState exists at __compositeState with: ensemble_member: string -- component name for each ensemble member synthesizer: string -- component name for the synthesizer task_brief: string -- the task (same brief goes to all members) ensemble_size: number -- (optional, default 3)

Ensures

  • All K members receive the SAME brief independently
  • Synthesizer receives all K results — its job is NOT majority voting
  • Synthesizer reasons about WHY results differ — disagreements are signal about ambiguity or difficulty
  • Returns the synthesized result plus a confidence assessment
  • &compositeState.result contains the synthesis
  • &compositeState.member_results contains the K individual results

Delegation

const { ensemble_member, synthesizer, task_brief, ensemble_size = 3 } = __compositeState;

// Fan out to K members — each works independently
const memberResults = [];
for (let i = 0; i < ensemble_size; i++) {
  const result = await rlm(task_brief, null, { use: ensemble_member });
  memberResults.push(result);
}

// Synthesizer merges
const synthBrief = `${ensemble_size} independent agents worked on the same task. Reason about their results — where they agree, where they disagree, and why.\n\nOriginal task: ${task_brief}\n\nResults:\n${memberResults.map((r, i) => `--- Agent ${i + 1} ---\n${r}`).join("\n\n")}`;
const synthesis = await rlm(synthBrief, null, { use: synthesizer });

__compositeState.result = synthesis;
__compositeState.member_results = memberResults;
return(synthesis);

Notes

This is a seed pattern. Ensemble members do not know other agents are working on the same task. The synthesizer does not know it is part of an ensemble composite. Disagreement between members is the primary signal — it reveals ambiguity in the task, not errors in individual agents.