From d13fab9fa5df639442a0e9cc25acb20c265a0c9c Mon Sep 17 00:00:00 2001
From: bigboateng
Date: Sat, 8 Aug 2026 02:16:03 +0100
Subject: [PATCH 1/2] Add public Go onboarding and release proof
---
.changeset/go-public-onboarding.md | 5 +
.github/workflows/release-finalize.yml | 9 +
README.md | 4 +-
examples/investigate/main.go | 3 +
packaging/go-release.mjs | 100 ++++++++
packaging/go-release.test.mjs | 65 ++++++
scripts/check-release-control.mjs | 2 +
scripts/readme.test.mjs | 56 ++++-
sdk/yield/README.md | 309 +++++++++++++++++++++++++
9 files changed, 551 insertions(+), 2 deletions(-)
create mode 100644 .changeset/go-public-onboarding.md
create mode 100644 packaging/go-release.mjs
create mode 100644 packaging/go-release.test.mjs
create mode 100644 sdk/yield/README.md
diff --git a/.changeset/go-public-onboarding.md b/.changeset/go-public-onboarding.md
new file mode 100644
index 0000000..f5f168b
--- /dev/null
+++ b/.changeset/go-public-onboarding.md
@@ -0,0 +1,5 @@
+---
+"@operatorstack/yield": patch
+---
+
+Add a Go-first onboarding guide, pkg.go.dev discovery links, and release-time verification through the public Go module proxy.
diff --git a/.github/workflows/release-finalize.yml b/.github/workflows/release-finalize.yml
index f62d4f5..09da042 100644
--- a/.github/workflows/release-finalize.yml
+++ b/.github/workflows/release-finalize.yml
@@ -78,6 +78,10 @@ jobs:
node-version: "24"
registry-url: https://registry.npmjs.org
package-manager-cache: false
+ - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
+ with:
+ go-version-file: go.mod
+ cache: false
- name: Require matching successful publisher receipts
env:
GH_TOKEN: ${{ github.token }}
@@ -113,5 +117,10 @@ jobs:
--archives "$RUNNER_TEMP/crates-receipt" \
--attempts 3 \
--delay-ms 10000
+ node packaging/go-release.mjs \
+ --version "$version" \
+ --source-sha "$SOURCE_SHA" \
+ --attempts 3 \
+ --delay-ms 10000
test "$(git rev-list -n 1 "$TAG")" = "$SOURCE_SHA"
gh release edit "$TAG" --repo "$GITHUB_REPOSITORY" --draft=false
diff --git a/README.md b/README.md
index a48e6bb..15a9bb6 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,7 @@
+
@@ -29,6 +30,7 @@
PyPI ·
crates.io ·
+ pkg.go.dev ·
GitHub
@@ -231,7 +233,7 @@ the same program in every language and compares observable behavior.
|---|---|---|
| TypeScript | [`@operatorstack/yield`](https://github.com/operatorstack/yield/tree/main/sdk/typescript/) | [`release-checklist`](https://github.com/operatorstack/yield/tree/main/examples/release-checklist/) |
| Python | [`yieldskill`](https://github.com/operatorstack/yield/tree/main/sdk/python/) | [`env-doctor`](https://github.com/operatorstack/yield/tree/main/examples/env-doctor/) |
-| Go | [`sdk/yield`](https://github.com/operatorstack/yield/tree/main/sdk/yield/) | [`investigate`](https://github.com/operatorstack/yield/tree/main/examples/investigate/) |
+| Go | [`github.com/operatorstack/yield/sdk/yield`](https://pkg.go.dev/github.com/operatorstack/yield/sdk/yield) | [`investigate`](https://github.com/operatorstack/yield/tree/main/examples/investigate/) |
| Rust | [`yieldskill`](https://github.com/operatorstack/yield/tree/main/sdk/rust/) | [`data-migration`](https://github.com/operatorstack/yield/tree/main/examples/data-migration/) |
Cursor, Codex, and Claude Code are verified integrations. Yield also includes
diff --git a/examples/investigate/main.go b/examples/investigate/main.go
index 3abfabe..e970d69 100644
--- a/examples/investigate/main.go
+++ b/examples/investigate/main.go
@@ -5,6 +5,7 @@
// Judgment — forming and assessing hypotheses — stays with the model.
package main
+// README_EXAMPLE_START
import (
"encoding/json"
"fmt"
@@ -97,3 +98,5 @@ func main() {
fmt.Sprintf("frontier reached: %d hypotheses refuted with %d failed attempts and none surviving — new evidence is needed, not more guessing", len(hs.Hypotheses), failures))
})
}
+
+// README_EXAMPLE_END
diff --git a/packaging/go-release.mjs b/packaging/go-release.mjs
new file mode 100644
index 0000000..8b48d3f
--- /dev/null
+++ b/packaging/go-release.mjs
@@ -0,0 +1,100 @@
+#!/usr/bin/env node
+import { execFile as execFileCallback } from "node:child_process";
+import { mkdtemp, rm } from "node:fs/promises";
+import { tmpdir } from "node:os";
+import { join, resolve } from "node:path";
+import process from "node:process";
+import { promisify } from "node:util";
+import { pathToFileURL } from "node:url";
+
+export const modulePath = "github.com/operatorstack/yield";
+const stableVersion = /^\d+\.\d+\.\d+$/;
+const commit = /^[0-9a-f]{40}$/;
+const execFile = promisify(execFileCallback);
+
+function goPlatform() {
+ const operatingSystem = process.platform === "win32" ? "windows" : process.platform;
+ const architecture = process.arch === "x64" ? "amd64" : process.arch;
+ return `${operatingSystem}/${architecture}`;
+}
+
+function expect(condition, message) {
+ if (!condition) throw new Error(message);
+}
+
+export function validateModuleReceipt(receipt, { version, sourceSha }) {
+ expect(stableVersion.test(version), `invalid stable version ${version}`);
+ expect(commit.test(sourceSha), `invalid source SHA ${sourceSha}`);
+ expect(receipt?.Path === modulePath, `unexpected Go module ${receipt?.Path ?? "missing"}`);
+ expect(receipt?.Version === `v${version}`, `unexpected Go module version ${receipt?.Version ?? "missing"}`);
+ expect(receipt?.Origin?.VCS === "git", "Go module origin must use git");
+ expect(receipt?.Origin?.URL === `https://${modulePath}`, `unexpected Go module origin ${receipt?.Origin?.URL ?? "missing"}`);
+ expect(receipt?.Origin?.Hash === sourceSha, "Go module source does not match the release tag");
+ return receipt;
+}
+
+export async function verifyGoRelease({
+ version,
+ sourceSha,
+ attempts = 1,
+ delayMs = 0,
+ execImpl = execFile,
+ delay = (milliseconds) => new Promise((resolveDelay) => setTimeout(resolveDelay, milliseconds)),
+}) {
+ expect(Number.isInteger(attempts) && attempts > 0, "attempts must be a positive integer");
+ const bin = await mkdtemp(join(tmpdir(), "yield-go-release-"));
+ const environment = {
+ ...process.env,
+ GOBIN: bin,
+ GOSUMDB: "sum.golang.org",
+ GOPROXY: "https://proxy.golang.org",
+ GOWORK: "off",
+ };
+ let lastError;
+ try {
+ for (let attempt = 1; attempt <= attempts; attempt += 1) {
+ try {
+ const listed = await execImpl("go", ["list", "-m", "-json", `${modulePath}@v${version}`], { env: environment });
+ validateModuleReceipt(JSON.parse(listed.stdout), { version, sourceSha });
+ await execImpl("go", ["install", `${modulePath}/cmd/yskill@v${version}`], { env: environment });
+ const executable = join(bin, process.platform === "win32" ? "yskill.exe" : "yskill");
+ const installed = await execImpl(executable, ["--version"], { env: environment });
+ expect(installed.stdout.trim() === `yskill ${version} ${goPlatform()}`, `unexpected yskill version: ${installed.stdout.trim()}`);
+ return { module: modulePath, version, sourceSha };
+ } catch (error) {
+ lastError = error;
+ if (attempt < attempts) await delay(delayMs);
+ }
+ }
+ } finally {
+ await rm(bin, { recursive: true, force: true });
+ }
+ throw lastError;
+}
+
+function parseArgs(argv) {
+ const values = {};
+ for (let index = 0; index < argv.length; index += 2) {
+ const key = argv[index];
+ if (!key?.startsWith("--") || argv[index + 1] === undefined) throw new Error(`invalid argument ${key ?? ""}`);
+ values[key.slice(2)] = argv[index + 1];
+ }
+ expect(stableVersion.test(values.version ?? ""), "--version must be stable semver");
+ expect(commit.test(values["source-sha"] ?? ""), "--source-sha must be a full commit SHA");
+ return values;
+}
+
+async function main() {
+ const values = parseArgs(process.argv.slice(2));
+ const result = await verifyGoRelease({
+ version: values.version,
+ sourceSha: values["source-sha"],
+ attempts: Number(values.attempts ?? "1"),
+ delayMs: Number(values["delay-ms"] ?? "0"),
+ });
+ process.stdout.write(`${JSON.stringify({ ...result, verified: true })}\n`);
+}
+
+if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
+ main().catch((error) => { console.error(`go-release: ${error.message}`); process.exit(1); });
+}
diff --git a/packaging/go-release.test.mjs b/packaging/go-release.test.mjs
new file mode 100644
index 0000000..4748321
--- /dev/null
+++ b/packaging/go-release.test.mjs
@@ -0,0 +1,65 @@
+import test from "node:test";
+import assert from "node:assert/strict";
+import { modulePath, validateModuleReceipt, verifyGoRelease } from "./go-release.mjs";
+
+const sourceSha = "a".repeat(40);
+const goPlatform = `${process.platform === "win32" ? "windows" : process.platform}/${process.arch === "x64" ? "amd64" : process.arch}`;
+
+function receipt(version = "1.2.3") {
+ return {
+ Path: modulePath,
+ Version: `v${version}`,
+ Origin: { VCS: "git", URL: `https://${modulePath}`, Hash: sourceSha },
+ };
+}
+
+test("binds the public Go module to its immutable tag source", () => {
+ assert.equal(validateModuleReceipt(receipt(), { version: "1.2.3", sourceSha }).Version, "v1.2.3");
+ assert.throws(
+ () => validateModuleReceipt({ ...receipt(), Origin: { ...receipt().Origin, Hash: "b".repeat(40) } }, { version: "1.2.3", sourceSha }),
+ /does not match the release tag/,
+ );
+});
+
+test("verifies proxy discovery and a fresh command install", async () => {
+ const calls = [];
+ const result = await verifyGoRelease({
+ version: "1.2.3",
+ sourceSha,
+ execImpl: async (file, args, options) => {
+ calls.push({ file, args, options });
+ if (args[0] === "list") return { stdout: JSON.stringify(receipt()) };
+ if (file === "go") return { stdout: "" };
+ return { stdout: `yskill 1.2.3 ${goPlatform}\n` };
+ },
+ });
+ assert.equal(result.module, modulePath);
+ assert.deepEqual(calls[0].args, ["list", "-m", "-json", `${modulePath}@v1.2.3`]);
+ assert.deepEqual(calls[1].args, ["install", `${modulePath}/cmd/yskill@v1.2.3`]);
+ assert.equal(calls[0].options.env.GOPROXY, "https://proxy.golang.org");
+ assert.equal(calls[0].options.env.GOSUMDB, "sum.golang.org");
+ assert.equal(calls[0].options.env.GOWORK, "off");
+});
+
+test("retries a proxy miss without accepting a partial release", async () => {
+ let lists = 0;
+ let delays = 0;
+ await verifyGoRelease({
+ version: "1.2.3",
+ sourceSha,
+ attempts: 2,
+ delayMs: 1,
+ delay: async () => { delays += 1; },
+ execImpl: async (file, args) => {
+ if (args[0] === "list") {
+ lists += 1;
+ if (lists === 1) throw new Error("module not found");
+ return { stdout: JSON.stringify(receipt()) };
+ }
+ if (file === "go") return { stdout: "" };
+ return { stdout: `yskill 1.2.3 ${goPlatform}\n` };
+ },
+ });
+ assert.equal(lists, 2);
+ assert.equal(delays, 1);
+});
diff --git a/scripts/check-release-control.mjs b/scripts/check-release-control.mjs
index 29f73b0..21caf52 100644
--- a/scripts/check-release-control.mjs
+++ b/scripts/check-release-control.mjs
@@ -99,6 +99,8 @@ export async function checkReleaseControl(root = resolve(import.meta.dirname, ".
expect(raw["release-finalize.yml"].includes("npm-publish.yml"), "finalization must bind the combined publisher receipt");
expect(raw["release-finalize.yml"].includes("pypi-release.mjs verify"), "finalization must verify the PyPI wheel hashes");
expect(raw["release-finalize.yml"].includes("crates-release.mjs verify"), "finalization must verify the crates.io package hashes");
+ expect(raw["release-finalize.yml"].includes("go-release.mjs"), "finalization must verify the public Go module and command install");
+ expect(raw["release-finalize.yml"].includes("--source-sha \"$SOURCE_SHA\""), "Go finalization must bind the module to the release source");
expect(raw["release-finalize.yml"].includes("--name \"crates-${version}-${SOURCE_SHA}\""), "finalization must consume the publisher-produced crates receipt");
expect(raw["release.yml"].includes("gh workflow run npm-publish.yml"), "the release controller must dispatch the trusted-publishing event after tagging");
expect(!Object.values(raw).some((text) => text.includes("CRATES_BOOTSTRAP_TOKEN")), "crates.io publishing must not use a bootstrap token");
diff --git a/scripts/readme.test.mjs b/scripts/readme.test.mjs
index 33591cd..7dc0662 100644
--- a/scripts/readme.test.mjs
+++ b/scripts/readme.test.mjs
@@ -78,6 +78,57 @@ test("Rust README example matches the tested data migration", async () => {
assert.deepEqual(JSON.parse(fixtureMatch[1]), JSON.parse(fixture));
});
+test("Go README example matches the tested investigation workflow", async () => {
+ const [readme, source, fixture] = await Promise.all([
+ text("sdk/yield/README.md"),
+ text("examples/investigate/main.go"),
+ text("examples/investigate/fixtures/responses.json"),
+ ]);
+
+ const readmeMatch = readme.match(
+ /\s*```go\n([\s\S]*?)\n```\s*/,
+ );
+ assert.ok(readmeMatch, "Go README example markers are missing");
+ const sourceMatch = source.match(
+ /\/\/ README_EXAMPLE_START\n([\s\S]*?)\n\/\/ README_EXAMPLE_END/,
+ );
+ assert.ok(sourceMatch, "Go source example markers are missing");
+ const readmeProgram = readmeMatch[1].replace(/^package main\n+/, "").trim();
+ assert.equal(readmeProgram, sourceMatch[1].trim());
+
+ const fixtureMatch = readme.match(
+ /\s*```json\n([\s\S]*?)\n```\s*/,
+ );
+ assert.ok(fixtureMatch, "Go README fixture markers are missing");
+ assert.deepEqual(JSON.parse(fixtureMatch[1]), JSON.parse(fixture));
+});
+
+test("Go README presents a public five-step workflow", async () => {
+ const readme = await text("sdk/yield/README.md");
+ const headings = [
+ "### 1. Install Yield",
+ "### 2. Create the workflow",
+ "### 3. Test the workflow",
+ "### 4. Register the skill",
+ "### 5. Run the skill",
+ ];
+ let previous = -1;
+ for (const heading of headings) {
+ const current = readme.indexOf(heading);
+ assert.ok(current > previous, `${heading} is missing or out of order`);
+ previous = current;
+ }
+ assert.match(readme, /go install github\.com\/operatorstack\/yield\/cmd\/yskill@latest/);
+ assert.match(readme, /yskill init skills\/investigate/);
+ assert.match(readme, /yskill doctor skills\/investigate --test/);
+ assert.match(readme, /yskill register skills\/investigate/);
+ assert.match(readme, /^\/investigate$/m);
+ assert.match(readme, /https:\/\/pkg\.go\.dev\/github\.com\/operatorstack\/yield\/sdk\/yield/);
+ assert.match(readme, /https:\/\/proxy\.golang\.org/);
+ assert.doesNotMatch(readme, /npmjs\.com|pypi\.org|crates\.io/);
+ assert.doesNotMatch(readme, /(?:href|src)="(?!https:\/\/)/);
+});
+
test("Rust README presents a public five-step workflow", async () => {
const readme = await text("sdk/rust/README.md");
const headings = [
@@ -215,10 +266,11 @@ test("README uses the borderless Yield mark", async () => {
});
test("README and quickstart use the public documentation and package registries", async () => {
- const [readme, pythonReadme, rustReadme, docsIndex, quickstart, agentSetup] = await Promise.all([
+ const [readme, pythonReadme, rustReadme, goReadme, docsIndex, quickstart, agentSetup] = await Promise.all([
text("README.md"),
text("sdk/python/README.md"),
text("sdk/rust/README.md"),
+ text("sdk/yield/README.md"),
text("docs/README.md"),
text("docs/quickstart.md"),
text("docs/agent-setup.md"),
@@ -227,11 +279,13 @@ test("README and quickstart use the public documentation and package registries"
assert.match(readme, /href="https:\/\/yield\.operatorstack\.systems\/docs\/">Documentation<\/a>/);
assert.match(readme, /href="https:\/\/pypi\.org\/project\/yieldskill\/">PyPI<\/a>/);
assert.match(readme, /href="https:\/\/crates\.io\/crates\/yieldskill">crates\.io<\/a>/);
+ assert.match(readme, /href="https:\/\/pkg\.go\.dev\/github\.com\/operatorstack\/yield\/sdk\/yield">pkg\.go\.dev<\/a>/);
assert.match(pythonReadme, /python -m pip install yieldskill/);
assert.match(pythonReadme, /https:\/\/pypi\.org\/project\/yieldskill\//);
assert.doesNotMatch(pythonReadme, /get\.operatorstack\.systems\/pip/);
assert.match(rustReadme, /cargo install yieldskill --locked/);
assert.doesNotMatch(rustReadme, /get\.operatorstack\.systems\/cargo/);
+ assert.match(goReadme, /go install github\.com\/operatorstack\/yield\/cmd\/yskill@latest/);
assert.match(docsIndex, /\[public documentation\]\(https:\/\/yield\.operatorstack\.systems\/docs\/\)/);
assert.match(quickstart, /npm install --save-exact @operatorstack\/yield/);
assert.doesNotMatch(quickstart, /get\.operatorstack\.systems\/npm|@operatorstack\/yield@0\./);
diff --git a/sdk/yield/README.md b/sdk/yield/README.md
new file mode 100644
index 0000000..3946705
--- /dev/null
+++ b/sdk/yield/README.md
@@ -0,0 +1,309 @@
+
+
+
+
+
+
+Yield for Go
+
+Move repeatable coding-agent instructions from words into Go.
+
+
+ Build typed, resumable workflows that stay beside the code they operate on.
+
+
+
+
+
+
+
+
+
+
+ Website ·
+ Documentation ·
+ pkg.go.dev ·
+ GitHub
+
+
+The Go module is `github.com/operatorstack/yield`. Import the SDK as
+`github.com/operatorstack/yield/sdk/yield`. The installed command is `yskill`.
+
+## Build a Go skill in five steps
+
+### 1. Install Yield
+
+Yield supports Go on macOS, Linux, and Windows. Install the public command:
+
+```bash
+go install github.com/operatorstack/yield/cmd/yskill@latest
+yskill --version
+```
+
+Go downloads the tagged module through
+[`proxy.golang.org`](https://proxy.golang.org/). You do not need a separate
+registry account or private package source.
+
+### 2. Create the workflow
+
+Create a Go workflow inside your repository:
+
+```bash
+yskill init skills/investigate \
+ --language go \
+ --description "Collect failure evidence, test hypotheses, and report the cause."
+```
+
+Replace `skills/investigate/main.go` with this tested workflow:
+
+
+```go
+package main
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "github.com/operatorstack/yield/sdk/yield"
+)
+
+type hypothesis struct {
+ ID string `json:"id"`
+ Statement string `json:"statement"`
+ DisproveCommand string `json:"disprove_command"`
+}
+
+type assessment struct {
+ Refuted bool `json:"refuted"`
+ CausalChain string `json:"causal_chain"`
+}
+
+const hypothesesSchema = `{
+ "type": "object",
+ "required": ["hypotheses"],
+ "properties": {
+ "hypotheses": {
+ "type": "array",
+ "minItems": 3,
+ "items": {
+ "type": "object",
+ "required": ["id", "statement", "disprove_command"],
+ "properties": {
+ "id": {"type": "string"},
+ "statement": {"type": "string"},
+ "disprove_command": {"type": "string"}
+ }
+ }
+ }
+ }
+}`
+
+const assessmentSchema = `{
+ "type": "object",
+ "required": ["refuted"],
+ "properties": {
+ "refuted": {"type": "boolean"},
+ "causal_chain": {"type": "string"}
+ }
+}`
+
+func main() {
+ yield.Main(func(ctx *yield.Context) (yield.Outcome, error) {
+ evidence := ctx.AgentTask("collect-evidence",
+ "Collect the observable evidence for the failure under investigation: error output, logs, recent changes. Return {\"observations\": [string]}.",
+ nil, json.RawMessage(`{"type":"object","required":["observations"],"properties":{"observations":{"type":"array","items":{"type":"string"}}}}`))
+
+ raw := ctx.AgentTask("form-hypotheses",
+ "Produce at least three hypotheses explaining the evidence, ordered cheapest-to-disprove first. Each carries a shell command whose failure would disprove it.",
+ json.RawMessage(evidence), json.RawMessage(hypothesesSchema))
+ var hs struct {
+ Hypotheses []hypothesis `json:"hypotheses"`
+ }
+ if err := json.Unmarshal(raw, &hs); err != nil {
+ return yield.Outcome{}, err
+ }
+
+ failures := 0
+ for _, h := range hs.Hypotheses {
+ if failures >= 3 {
+ break
+ }
+ result := ctx.RunCommand("probe-"+h.ID, h.DisproveCommand, 300)
+ assessRaw := ctx.AgentTask("assess-"+h.ID,
+ fmt.Sprintf("Hypothesis %q: %s. Given the probe result, is it refuted? If it survives, state the causal chain from root cause to observed failure.", h.ID, h.Statement),
+ map[string]any{"hypothesis": h, "probe": result},
+ json.RawMessage(assessmentSchema))
+ var a assessment
+ if err := json.Unmarshal(assessRaw, &a); err != nil {
+ return yield.Outcome{}, err
+ }
+ if a.Refuted {
+ failures++
+ continue
+ }
+ ctx.Require(a.CausalChain != "", "the surviving hypothesis states a causal chain", a)
+ return ctx.Complete(map[string]any{
+ "hypothesis": h,
+ "causal_chain": a.CausalChain,
+ "probe_exit": result.ExitCode,
+ })
+ }
+ return yield.Outcome{}, ctx.Blocked(
+ fmt.Sprintf("frontier reached: %d hypotheses refuted with %d failed attempts and none surviving — new evidence is needed, not more guessing", len(hs.Hypotheses), failures))
+ })
+}
+```
+
+
+The generated `go.mod` pins the public Yield module to the installed CLI
+version. The generated `skill.json` runs the Go program.
+
+### 3. Test the workflow
+
+Use deterministic responses during tests. Save this as
+`skills/investigate/fixtures/responses.json`:
+
+
+```json
+{
+ "collect-evidence": {
+ "observations": [
+ "CI fails on ubuntu only with 'Text file busy' (exit 126)",
+ "failure started after the hydrate step became concurrent",
+ "macOS and windows runners are green"
+ ]
+ },
+ "form-hypotheses": {
+ "hypotheses": [
+ {
+ "id": "h1",
+ "statement": "The runner image is missing the binary entirely",
+ "disprove_command": "exit 1"
+ },
+ {
+ "id": "h2",
+ "statement": "Concurrent hydrate writes the binary while another process execs it (ETXTBSY)",
+ "disprove_command": "true"
+ },
+ {
+ "id": "h3",
+ "statement": "A permissions regression strips the execute bit",
+ "disprove_command": "true"
+ }
+ ]
+ },
+ "assess-h1": {
+ "refuted": true
+ },
+ "assess-h2": {
+ "refuted": false,
+ "causal_chain": "concurrent hydrate holds the binary open for write -> exec of the same inode returns ETXTBSY -> shell reports exit 126 -> job fails only where hydrate and exec overlap (ubuntu)"
+ }
+}
+```
+
+
+Then test the workflow:
+
+```bash
+yskill doctor skills/investigate --test
+```
+
+Yield runs commands for real and supplies agent responses from the fixture. A
+successful test reaches `completed` without leaving a run journal.
+
+### 4. Register the skill
+
+Registration lets installed coding agents discover the workflow:
+
+```bash
+yskill register skills/investigate
+```
+
+Select the verified agents explicitly when you do not want automatic
+detection:
+
+```bash
+yskill register skills/investigate \
+ --agent cursor,codex,claude-code
+```
+
+The generated adapters point back to `skills/investigate`. They do not copy the
+workflow or install its dependencies again.
+
+### 5. Run the skill
+
+Start a new coding-agent session so it discovers the registered skill. Where
+slash skills are supported, run:
+
+```text
+/investigate
+```
+
+Otherwise, ask the agent in plain language:
+
+```text
+Use the investigate skill to diagnose this failure.
+```
+
+The agent follows the adapter, starts the canonical Go workflow, and supplies
+each required agent response.
+
+## How Yield runs and resumes
+
+1. Your Go function emits one typed operation.
+2. Yield records the request and exits. It does not run a daemon.
+3. The coding agent, user, or CLI supplies the result.
+4. Yield replays the function from its journal until it reaches the next
+ operation.
+
+Replay must produce the same operation sequence. Yield reports divergence
+instead of giving a recorded response to a different operation.
+
+| Go primitive | Purpose |
+|---|---|
+| `ctx.RunCommand()` | Execute a command and record its exit code and output. |
+| `ctx.AgentTask()` | Ask the coding agent for schema-valid JSON. |
+| `ctx.AskUser()` | Request an explicit human decision. |
+| `ctx.Require()` | Bind a required claim to recorded evidence. |
+| `ctx.Blocked()` / `ctx.Refused()` | Stop honestly when work cannot or must not continue. |
+
+See the [Go reference](https://pkg.go.dev/github.com/operatorstack/yield/sdk/yield),
+[primitive guides](https://yield.operatorstack.systems/docs/primitives/), and
+[CLI reference](https://github.com/operatorstack/yield/blob/main/docs/reference/cli.md)
+for the complete contract.
+
+## Guarantees and limits
+
+Yield provides deterministic control flow, typed requests and responses,
+persistent run state, replay with divergence detection, stale and duplicate
+response rejection, and evidence-bound completion.
+
+Schema validity is not truth. Yield cannot prove that a coding agent performed
+only the requested work. `RunCommand` is different: the Yield CLI executes the
+command, so its recorded exit code and output are observed facts.
+
+Programs must remain deterministic between operations. Do not read clocks,
+random values, environment variables, or changing files to choose the next
+operation. Cross those boundaries through a Yield operation instead.
+
+Yield is not a daemon, hosted runtime, workflow DSL, marketplace, coding-agent
+replacement, or permission sandbox. Your operating system, repository, and
+coding-agent permissions remain the security boundary.
+
+## Coding-agent support
+
+Yield verifies adapters for Cursor, Codex, and Claude Code. Registry-backed
+project paths are available for other coding agents. See the
+[agent setup guide](https://yield.operatorstack.systems/docs/agent-setup/).
+
+## Source and support
+
+- [Go API reference](https://pkg.go.dev/github.com/operatorstack/yield/sdk/yield)
+- [Public documentation](https://yield.operatorstack.systems/docs/)
+- [Go source](https://github.com/operatorstack/yield/tree/main/sdk/yield)
+- [Working examples](https://github.com/operatorstack/yield/tree/main/examples)
+- [Issues](https://github.com/operatorstack/yield/issues)
+- [Security policy](https://github.com/operatorstack/yield/blob/main/SECURITY.md)
+
+Yield is available under the [MIT License](https://github.com/operatorstack/yield/blob/main/LICENSE).
From af22cd89ff8adcb54f6da2295bc44eb6969ad73c Mon Sep 17 00:00:00 2001
From: bigboateng
Date: Sat, 8 Aug 2026 02:21:06 +0100
Subject: [PATCH 2/2] Keep Go example receipt synchronized
---
evals/results/latest.json | 4 ++--
examples/investigate/main.go | 3 ---
scripts/readme.test.mjs | 9 +++------
3 files changed, 5 insertions(+), 11 deletions(-)
diff --git a/evals/results/latest.json b/evals/results/latest.json
index f0bf2f0..e03bef0 100644
--- a/evals/results/latest.json
+++ b/evals/results/latest.json
@@ -1,8 +1,8 @@
{
"schema_version": 2,
"methodology_version": "1.1",
- "generated_at": "2026-08-07T22:52:34.977Z",
- "source_digest": "b5c66a96530cc9d100c388a4df9bbbc8d0aea6e78ef0fe2cfa0009b8aa1da778",
+ "generated_at": "2026-08-08T01:20:38.016Z",
+ "source_digest": "eb20ae102ae5de056d91ad3a9b8cbfc77284185050c3e3639d93c111b78ed6db",
"status": "passed",
"workflow_conformance": {
"passed": 40,
diff --git a/examples/investigate/main.go b/examples/investigate/main.go
index e970d69..3abfabe 100644
--- a/examples/investigate/main.go
+++ b/examples/investigate/main.go
@@ -5,7 +5,6 @@
// Judgment — forming and assessing hypotheses — stays with the model.
package main
-// README_EXAMPLE_START
import (
"encoding/json"
"fmt"
@@ -98,5 +97,3 @@ func main() {
fmt.Sprintf("frontier reached: %d hypotheses refuted with %d failed attempts and none surviving — new evidence is needed, not more guessing", len(hs.Hypotheses), failures))
})
}
-
-// README_EXAMPLE_END
diff --git a/scripts/readme.test.mjs b/scripts/readme.test.mjs
index 7dc0662..59f4552 100644
--- a/scripts/readme.test.mjs
+++ b/scripts/readme.test.mjs
@@ -89,12 +89,9 @@ test("Go README example matches the tested investigation workflow", async () =>
/\s*```go\n([\s\S]*?)\n```\s*/,
);
assert.ok(readmeMatch, "Go README example markers are missing");
- const sourceMatch = source.match(
- /\/\/ README_EXAMPLE_START\n([\s\S]*?)\n\/\/ README_EXAMPLE_END/,
- );
- assert.ok(sourceMatch, "Go source example markers are missing");
- const readmeProgram = readmeMatch[1].replace(/^package main\n+/, "").trim();
- assert.equal(readmeProgram, sourceMatch[1].trim());
+ const sourceMatch = source.match(/^(package main[\s\S]*)$/m);
+ assert.ok(sourceMatch, "Go source program is missing");
+ assert.equal(readmeMatch[1].trim(), sourceMatch[1].trim());
const fixtureMatch = readme.match(
/\s*```json\n([\s\S]*?)\n```\s*/,