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
21 changes: 21 additions & 0 deletions .github/workflows/yield-lab.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,22 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: "24"
- name: Build and smoke-test the packed TypeScript SDK
working-directory: labs/22-yield/yield/sdk/typescript
run: |
npm run build
tarball="$RUNNER_TEMP/$(npm pack --silent --pack-destination "$RUNNER_TEMP")"
smoke_dir="$(mktemp -d)"
cd "$smoke_dir"
npm init -y >/dev/null
npm install "$tarball" >/dev/null
node --input-type=module -e 'import { defineSkill } from "@operatorstack/yield"; if (typeof defineSkill !== "function") process.exit(1)'
- uses: Swatinem/rust-cache@v2
with:
workspaces: |
labs/22-yield/yield/sdk/rust
labs/22-yield/yield/examples/data-migration
labs/22-yield/yield/examples/library/rust
labs/22-yield/yield/internal/conformance/testdata/skill-rs
- name: Vet and test (includes subprocess e2e + 4-language conformance)
working-directory: labs/22-yield/yield
Expand All @@ -42,6 +53,7 @@ jobs:
/tmp/yskill test examples/env-doctor
/tmp/yskill test examples/data-migration
YSKILL=/tmp/yskill /tmp/yskill test examples/convert-skill
YSKILL=/tmp/yskill bash ./examples/library/test-all.sh

# Shift-left projection gate: materialize the public surface exactly as
# operatorstack/yield would receive it and compile+test it, so a broken
Expand All @@ -68,6 +80,15 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: "24"
- name: Build and smoke-test the projected TypeScript package
working-directory: ${{ runner.temp }}/yield-projected/sdk/typescript
run: |
tarball="$RUNNER_TEMP/$(npm pack --silent --pack-destination "$RUNNER_TEMP")"
smoke_dir="$(mktemp -d)"
cd "$smoke_dir"
npm init -y >/dev/null
npm install "$tarball" >/dev/null
node --input-type=module -e 'import { defineSkill } from "@operatorstack/yield"; if (typeof defineSkill !== "function") process.exit(1)'
- name: Build and test the projected module (incl. 4-language conformance)
working-directory: ${{ runner.temp }}/yield-projected
env:
Expand Down
7 changes: 7 additions & 0 deletions labs/22-yield/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ yield/
├── sdk/typescript/ TypeScript SDK — examples/release-checklist (node main.ts)
├── sdk/python/ Python SDK — examples/env-doctor (import yieldskill)
├── sdk/rust/ Rust SDK — examples/data-migration (crate yieldskill)
├── examples/library/ 10 workflows × 4 languages, all fixture-tested
└── docs/locus* certified lifecycle + SDK-contract models, verdicts, discharge
```

Expand All @@ -63,9 +64,15 @@ divergence check is a *decided* design comparison, not a convention
```
go build -o /tmp/yskill ./yield/cmd/yskill
/tmp/yskill test yield/examples/investigate # scripted fixture run to completion
/tmp/yskill test yield/examples/library/typescript/review-branch
YSKILL=/tmp/yskill bash yield/examples/library/test-all.sh # all 40 language/workflow pairs
/tmp/yskill run yield/examples/investigate # prints the first operation envelope
```

The public documentation starts at [`yield/docs/README.md`](yield/docs/README.md).
It leads with a clean-install TypeScript quickstart, then separates primitive
guides, complete tutorials, executable examples, conversion, and reference.

## Formal grounding

The run lifecycle was designed against Locus verdicts
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Yield documentation and runnable TypeScript package

- Add a programmer-first documentation path: clean install, first workflow,
primitive guides, tutorials, examples, conversion, and runtime reference.
- Compile the TypeScript SDK before packing so Node loads JavaScript from
`node_modules` instead of refusing runtime type stripping there.
- Smoke-test both the source and projected npm tarballs in clean temporary
projects before publication.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Yield example library

- Add ten common coding-agent workflow examples in TypeScript, Python, Go,
and Rust.
- Add fixture-backed validation for all forty language/workflow pairs.
- Add a generated catalog so documentation can route visitors to their
preferred language without maintaining four separate lists.
- Reframe the public entry point around starting from useful workflows.
42 changes: 34 additions & 8 deletions labs/22-yield/public-readme/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ resumable programs.**
> The skill yields the next typed operation. The coding agent performs it
> and resumes the skill.

Write control flow in Go. Yield user questions, agent tasks, and commands
to the coding agent. Resume from the result. No custom agent runtime
required — the agent only runs a CLI and follows envelopes.
Write control flow in TypeScript, Python, Go, or Rust. Yield user
questions, agent tasks, and commands to the coding agent. Resume from the
result. No custom agent runtime required — the agent only runs a CLI and
follows envelopes.

A skill keeps its thin `SKILL.md` (so it works wherever skills work today)
and moves the part prose loses under context pressure — order, branching,
Expand Down Expand Up @@ -59,16 +60,41 @@ four languages and asserts identical observable protocol behavior.
Non-Go skills declare their runner in `skill.json`:
`{"run": ["node", "main.ts"]}`.

Already have prose skills? `examples/convert-skill` is a converter —
itself a Yield skill — that extracts the implicit flow from an existing
`SKILL.md`, asks you which language you want, has the model write the
program, and completes only when the generated skill passes its own
fixture run. A conversion that was never executed is never "done".
## Ten workflows, every language

The [example library](examples/library/) recreates ten common coding-agent
workflows independently in all four SDKs: branch review, failure
investigation, web QA, package release, issue triage, CI repair, dependency
upgrade, database migration, security audit, and iOS publishing.

Each language has the same workflow, a thin `SKILL.md`, and a scripted
fixture. Start from the work you already do instead of starting from a
framework tutorial.

## Documentation

Start with the [ten-minute TypeScript quickstart](docs/quickstart.md), then
use the documentation by job:

- [primitive guides](docs/primitives/README.md) — commands, model work,
human input, evidence gates, and outcomes;
- [tutorials](docs/tutorials/README.md) — review, approval, environment
repair, bounded debugging, and migration;
- [examples](docs/examples.md) — working programs in all four languages;
- [convert an existing skill](docs/convert-existing-skill.md) — move
control flow into code without claiming that fixture execution proves
every reading of the original prose;
- [CLI and runtime reference](docs/reference/cli.md).

## Try it

```
go build -o yskill ./cmd/yskill
./yskill test examples/library/typescript/review-branch
./yskill test examples/library/python/review-branch
./yskill test examples/library/go/review-branch
./yskill test examples/library/rust/review-branch
YSKILL="$PWD/yskill" bash ./examples/library/test-all.sh
./yskill test examples/investigate # Go: scripted fixture run to completion
./yskill test examples/release-checklist # TypeScript (Node >= 23.6)
./yskill test examples/env-doctor # Python 3.10+
Expand Down
46 changes: 46 additions & 0 deletions labs/22-yield/yield/docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Yield documentation

You already know the workflow. You may be repeating it in a prompt:

> Run the checks. Review the diff. Stop if anything critical remains. Ask me
> before publishing. If the session ends, start again without losing our place.

Yield lets you keep the useful words and put the order in normal code. The
coding agent still investigates, reviews, edits, and explains. Your program
decides which operation comes next, what evidence must exist, and when the run
is finished.

## Start here

1. [Build and run your first skill](quickstart.md) — a TypeScript workflow you
can test in about ten minutes.
2. [Learn the primitives](primitives/README.md) — commands, model work, human
input, gates, and honest outcomes.
3. [Follow a complete tutorial](tutorials/README.md) — review, approval,
environment repair, bounded debugging, and migration.
4. [Browse the examples](examples.md) — working programs in Go, TypeScript,
Python, and Rust.
5. [Convert an existing prose skill](convert-existing-skill.md) — use Yield's
verified converter after you understand one ordinary workflow.

## The split to remember

| Put in code | Leave with the model |
|---|---|
| order and branching | investigation and judgment |
| retry limits | reading unfamiliar code |
| commands that must really run | proposing changes |
| approval points | writing explanations |
| evidence required to finish | interpreting evidence |

This is not a new agent runtime. A thin `SKILL.md` starts the program, the
program emits one typed operation, and the coding agent performs that operation
through its normal interface. Yield records the response and resumes from the
next unanswered operation.

## Reference

- [CLI commands](reference/cli.md)
- [Run, pause, resume, and replay](reference/execution-model.md)
- [The four SDKs](reference/sdk-parity.md)
- [Guarantees and limits](reference/guarantees.md)
66 changes: 66 additions & 0 deletions labs/22-yield/yield/docs/convert-existing-skill.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Convert an existing prose skill

Use conversion after you have run one ordinary Yield workflow. Conversion is a
separate job from the runtime itself: the converter helps extract and encode a
policy; Yield then executes and verifies the resulting program.

The repository includes [`examples/convert-skill`](../examples/convert-skill/),
a converter that is itself a Yield skill.

## What moves, and what stays

Keep these in the thin `SKILL.md`:

- the goal and when the skill should be used;
- domain context the model needs;
- judgment criteria and useful examples;
- the instruction to start and resume the Yield program.

Move these into the program:

- required order;
- branches and retry limits;
- commands whose output must be observed;
- approval points;
- claims required for completion;
- `Blocked` and `Refused` outcomes.

## Run the converter

From a checkout of the public repository:

```bash
go build -o /tmp/yskill ./cmd/yskill
cd examples/convert-skill
YSKILL=/tmp/yskill /tmp/yskill run .
```

The workflow asks for:

1. the source directory containing `SKILL.md`;
2. a target language;
3. a destination directory.

The coding agent extracts the implicit flow and writes the generated files. The
converter then runs the generated skill's own fixtures under `yskill test`. It
allows two bounded repair attempts and returns `Blocked` if the fixture run
still fails.

## What “verified” means here

The converter verifies that the generated program executes its declared fixture
path. It does **not** prove that the extracted policy is behaviorally equivalent
to every reading of the original prose.

Review the conversion as a policy change:

- map every load-bearing source instruction to code, retained model judgment,
or an explicit exclusion;
- add a positive fixture and at least one negative or refusal path;
- test bypass attempts and failure states;
- replay a completed run to check determinism;
- keep performance or token-reduction claims separate from runtime correctness.

The implemented safety comparison is documented in
[`locus-converter.md`](locus-converter.md). Its narrow conclusion is that the
converter cannot report success before the generated fixture run passes.
62 changes: 62 additions & 0 deletions labs/22-yield/yield/docs/examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Example library

The library contains ten common coding-agent workflows. Every workflow is
implemented in TypeScript, Python, Go, and Rust, so the first choice is your
repository's language—not which example happens to exist.

| Workflow | Control flow moved into code |
|---|---|
| [Review a branch](../examples/library/typescript/review-branch/) | checks, review, zero-critical gate |
| [Investigate a failure](../examples/library/typescript/investigate-failure/) | evidence, diagnosis, supported cause |
| [QA a web change](../examples/library/typescript/qa-web-change/) | build, changed-route QA, no-blocker gate |
| [Release a package](../examples/library/typescript/release-package/) | tests, review, approval, publish, verify |
| [Triage an issue](../examples/library/typescript/triage-issue/) | read, classify, one next action |
| [Repair CI](../examples/library/typescript/repair-ci/) | failed log, supported repair, rerun |
| [Upgrade a dependency](../examples/library/typescript/upgrade-dependency/) | baseline, compatibility review, approval, update, tests |
| [Run a database migration](../examples/library/typescript/migrate-database/) | dry-run, risk review, approval, apply, verify |
| [Audit security](../examples/library/typescript/audit-security/) | mechanical scans, trust-boundary review, zero-critical gate |
| [Publish an iOS build](../examples/library/typescript/publish-ios/) | archive, metadata review, approval, upload, processing check |

Change the language segment in any link to python, go, or rust. Source files
are grouped separately for fast browsing:

- [TypeScript](../examples/library/typescript/src/)
- [Python](../examples/library/python/src/)
- [Go](../examples/library/go/src/)
- [Rust](../examples/library/rust/src/bin/)

Run all forty fixtures:

go build -o /tmp/yskill ./cmd/yskill
YSKILL=/tmp/yskill bash ./examples/library/test-all.sh

The included commands produce harmless evidence so the examples run in this
repository. Replace them with project commands before adopting a workflow.

## Complete walkthroughs

These examples show longer programs with a thin `SKILL.md` and scripted
responses under `fixtures/responses.json`.

| Example | Language | Pattern |
|---|---|---|
| [`release-checklist`](../examples/release-checklist/) | TypeScript | approval, build, model-authored notes, publish, verify |
| [`env-doctor`](../examples/env-doctor/) | Python | probe, diagnose, wait for a person, recheck |
| [`investigate`](../examples/investigate/) | Go | structured hypotheses, real probes, bounded attempts |
| [`data-migration`](../examples/data-migration/) | Rust | dry-run, approval, apply, verify |
| [`convert-skill`](../examples/convert-skill/) | Go | extract a prose workflow, generate code, execute its fixtures |

From the repository root:

```bash
go build -o /tmp/yskill ./cmd/yskill
/tmp/yskill test examples/release-checklist
/tmp/yskill test examples/env-doctor
/tmp/yskill test examples/investigate
/tmp/yskill test examples/data-migration
YSKILL=/tmp/yskill /tmp/yskill test examples/convert-skill
```

When adapting an example, change the repository-specific commands and model
instructions. Keep stable operation IDs for existing steps so saved runs can
replay them.
13 changes: 13 additions & 0 deletions labs/22-yield/yield/docs/locus-conformance.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ discharges the whole program's obligations. Models and derivations live in
| `sdk-contract.json` | control.nonblockingness | **nonblocking** — every SDK execution reaches an emit |
| `divergence-in-sdk.json` vs `divergence-supervisor-only.json` | verification.safety-reachability (rival designs, `drv-ad50b13e…`) | **decided** — in-SDK per-step checking satisfies `forbidden-unreachable`; supervisor-only is rejected with the verbatim trace `op_drifts → consume_unchecked → CONSUMED_MISMATCHED` |

The feature-extension boundary also passed
`practice.boundary-conformance`. Its control law is deliberately small:
SDK stdout becomes engine authority only after the protocol package admits
exactly one complete `request`, `terminal`, or `diverged` variant. Unknown
fields and malformed, missing, or ambiguous variants fail before dispatch.
The canonical IR uses the same exact-one shape, while TypeScript and Rust
encode it with closed surface types.

The decided comparison is why per-step digest comparison is a MANDATORY
part of the SDK contract in every language, not an optional nicety: without
it, a drifted operation silently consumes a recorded response meant for a
Expand Down Expand Up @@ -42,6 +50,11 @@ scenario matrix and what each observes:
| `TestGuardRefusals` | schema-invalid, duplicate-rewrite, wrong-run refusals through the live engine |
| `TestDivergenceFailsLoudlyEverywhere` | the decided design: a tampered recorded operation is detected by every SDK at replay |

`internal/protocol/ir_test.go` adds the feature-upgrade gate: positive and
negative outputs must receive the same decision from protocol admission and
the canonical schema. `internal/engine/engine_test.go` proves ambiguous SDK
output is refused at the real subprocess boundary.

Languages whose toolchain is missing are skipped locally; CI provides all
four (`.github/workflows/yield-lab.yml`).

Expand Down
6 changes: 3 additions & 3 deletions labs/22-yield/yield/docs/locus/sdk-contract.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"evidence": [
{
"path": "labs/22-yield/yield/sdk/yield/yield.go",
"note": "Go SDK: step() replay/compare/emit, Main() terminal emission \u2014 the behavior TS/Python SDKs must refine"
"note": "Go SDK: step() replay/compare/emit and Main() terminal emission \u2014 the reference behavior all four SDKs refine"
},
{
"path": "labs/22-yield/yield/internal/engine/engine.go",
Expand Down Expand Up @@ -225,7 +225,7 @@
"selector": "marked"
},
"unknowns": [
"The TS and Python SDKs are not yet implemented; this contract is what they must exhibit, discharged by running each example skill through yskill test.",
"A future output variant must be added coherently to every SDK surface, the canonical IR, protocol admission, engine dispatch, and conformance fixtures.",
"Determinism between yields is the program author's obligation in every language; the contract detects divergence, it cannot prevent nondeterminism."
]
}
}
Loading
Loading