From 5dff81be3e759c3f2fdd30fa440e7f8e0ed1075a Mon Sep 17 00:00:00 2001 From: iliya Date: Mon, 7 Sep 2026 15:32:42 +0000 Subject: [PATCH 1/2] test(docs): align README contracts with authoring preview boundaries --- .../contract_clarity_integration_test.go | 123 ++++++++++-------- .../starter_template_sync_integration_test.go | 11 +- 2 files changed, 80 insertions(+), 54 deletions(-) diff --git a/repotests/contract_clarity_integration_test.go b/repotests/contract_clarity_integration_test.go index b55cd1c2..eaeb4e1c 100644 --- a/repotests/contract_clarity_integration_test.go +++ b/repotests/contract_clarity_integration_test.go @@ -218,7 +218,24 @@ func TestContractClarity_RuntimeMetadataAndDocsStayAligned(t *testing.T) { t.Fatal(err) } - mustContain(t, string(rootReadme), "Build one plugin and ship it to many AI agents was the legacy authoring goal.") + // The root README separates the installer and unreleased standard preview + // from preserved v1 capabilities. Keep legacy claims inside that boundary. + currentReadme, historicalReadme, found := strings.Cut(string(rootReadme), "### Historical authoring and development\n") + if !found { + t.Fatal("README missing historical authoring boundary") + } + mustContain(t, currentReadme, "## Use plugins") + mustContain(t, currentReadme, "## Build plugins — unreleased preview") + currentProse := strings.Join(strings.Fields(currentReadme), " ") + mustContain(t, currentProse, "root `plugin.json` with optional `skills/` and `mcp.json`") + mustContain(t, currentProse, "`agentplugins author` and `plugin-kit-ai` are the two prepared entrypoints to one standard authoring engine.") + mustContain(t, currentProse, "Public deployment remains gated on release acceptance") + mustContain(t, currentProse, "There is no implicit YAML fallback or second supported YAML engine.") + mustContain(t, historicalReadme, "[Historical plugin-kit-ai v1, baseline 1.2.4](website/source/en/legacy/v1/index.md)") + mustContain(t, historicalReadme, "Project migration is not available in v2 yet.") + mustContain(t, historicalReadme, "Maintain legacy projects using the v1 1.2.4 command set.") + mustContain(t, strings.Join(strings.Fields(historicalReadme), " "), "All commands, stability labels, and supported-output claims in this section describe the preserved v1 workflow, not the unreleased standard authoring MVP.") + mustContain(t, historicalReadme, "Build one plugin and ship it to many AI agents was the legacy authoring goal.") mustContain(t, string(sdkReadme), "`(*plugin-kit-ai.App).Gemini()`") mustContain(t, string(sdkReadme), "`github.com/777genius/plugin-kit-ai/sdk/gemini`") mustContain(t, string(sdkReadme), "## Gemini Example") @@ -264,32 +281,32 @@ func TestContractClarity_RuntimeMetadataAndDocsStayAligned(t *testing.T) { mustContain(t, string(architectureDoc), "`sdk/gemini`") mustContain(t, string(architectureDoc), "`sdk/internal/platforms/gemini`") mustContain(t, string(architectureDoc), "Gemini runtime hooks use `stdin_json`") - mustContain(t, string(rootReadme), "`plugin-kit-ai` keeps authored source under `plugin/`, generates the supported outputs you need, and helps you validate the repo before handoff.") - mustContain(t, string(rootReadme), "supported outputs for Claude, Codex, Gemini, Cursor, and OpenCode where the repo shape allows it") - mustContain(t, string(rootReadme), "The honest promise is `one repo / many supported outputs`, not fake parity everywhere") - mustContain(t, string(rootReadme), "overview: [plugin-kit-ai documentation](https://github.com/777genius/universal-agent-plugins/blob/9beca10448ac50fbe526a52101d1433a12471980/website/source/en/index.md)") - mustContain(t, string(rootReadme), "fastest start: [Quickstart](https://github.com/777genius/universal-agent-plugins/blob/9beca10448ac50fbe526a52101d1433a12471980/website/source/en/guide/quickstart.md)") - mustContain(t, string(rootReadme), "choose by job first: [Choose What You Are Building](https://github.com/777genius/universal-agent-plugins/blob/9beca10448ac50fbe526a52101d1433a12471980/website/source/en/guide/choose-what-you-are-building.md)") - mustContain(t, string(rootReadme), "one repo, many outputs: [What You Can Build](https://github.com/777genius/universal-agent-plugins/blob/9beca10448ac50fbe526a52101d1433a12471980/website/source/en/guide/what-you-can-build.md)") - mustContain(t, string(rootReadme), "honest caveat: [Support Boundary](https://github.com/777genius/universal-agent-plugins/blob/9beca10448ac50fbe526a52101d1433a12471980/website/source/en/reference/support-boundary.md)") - mustContain(t, string(rootReadme), "## Choose What You Are Building") - mustContain(t, string(rootReadme), "### Connect an online service") - mustContain(t, string(rootReadme), "### Connect a local tool") - mustContain(t, string(rootReadme), "### Build custom plugin logic") - mustContain(t, string(rootReadme), "## Quick start") - mustContain(t, string(rootReadme), "brew install 777genius/homebrew-plugin-kit-ai/plugin-kit-ai") - mustContain(t, string(rootReadme), "npm: `npm i -g plugin-kit-ai@1.2.4` or `npx plugin-kit-ai@1.2.4 ...`") - mustContain(t, string(rootReadme), "pipx (`public-beta`, only when that release is published to PyPI): `pipx install plugin-kit-ai==1.2.4`") - mustContain(t, string(rootReadme), "fallback installer: `curl -fsSL https://raw.githubusercontent.com/777genius/plugin-kit-ai/main/scripts/install.sh | sh`") - mustContain(t, string(rootReadme), "plugin-kit-ai init my-plugin --template online-service") - mustContain(t, string(rootReadme), "plugin-kit-ai init my-plugin --template local-tool") - mustContain(t, string(rootReadme), "plugin-kit-ai init my-plugin --template custom-logic") - mustContain(t, string(rootReadme), "plugin-kit-ai init my-plugin") - mustContain(t, string(rootReadme), "plugin-kit-ai generate .") - mustContain(t, string(rootReadme), "plugin-kit-ai validate . --platform codex-runtime --strict") - mustContain(t, string(rootReadme), "## Works Across Multiple Outputs") - mustContain(t, string(rootReadme), "## What To Do Next") - mustContain(t, string(rootReadme), "## Keep This Rule In Mind") + mustContain(t, historicalReadme, "`plugin-kit-ai` keeps authored source under `plugin/`, generates the supported outputs you need, and helps you validate the repo before handoff.") + mustContain(t, historicalReadme, "supported outputs for Claude, Codex, Gemini, Cursor, and OpenCode where the repo shape allows it") + mustContain(t, historicalReadme, "The honest promise is `one repo / many supported outputs`, not fake parity everywhere") + mustContain(t, historicalReadme, "overview: [plugin-kit-ai documentation](https://github.com/777genius/universal-agent-plugins/blob/9beca10448ac50fbe526a52101d1433a12471980/website/source/en/index.md)") + mustContain(t, historicalReadme, "fastest start: [Quickstart](https://github.com/777genius/universal-agent-plugins/blob/9beca10448ac50fbe526a52101d1433a12471980/website/source/en/guide/quickstart.md)") + mustContain(t, historicalReadme, "choose by job first: [Choose What You Are Building](https://github.com/777genius/universal-agent-plugins/blob/9beca10448ac50fbe526a52101d1433a12471980/website/source/en/guide/choose-what-you-are-building.md)") + mustContain(t, historicalReadme, "one repo, many outputs: [What You Can Build](https://github.com/777genius/universal-agent-plugins/blob/9beca10448ac50fbe526a52101d1433a12471980/website/source/en/guide/what-you-can-build.md)") + mustContain(t, historicalReadme, "honest caveat: [Support Boundary](https://github.com/777genius/universal-agent-plugins/blob/9beca10448ac50fbe526a52101d1433a12471980/website/source/en/reference/support-boundary.md)") + mustContain(t, historicalReadme, "## Choose What You Are Building") + mustContain(t, historicalReadme, "### Connect an online service") + mustContain(t, historicalReadme, "### Connect a local tool") + mustContain(t, historicalReadme, "### Build custom plugin logic") + mustContain(t, historicalReadme, "## Historical Quick Start") + mustContain(t, historicalReadme, "brew install 777genius/homebrew-plugin-kit-ai/plugin-kit-ai") + mustContain(t, historicalReadme, "npm: `npm i -g plugin-kit-ai@1.2.4` or `npx plugin-kit-ai@1.2.4 ...`") + mustContain(t, historicalReadme, "pipx (`public-beta`, only when that release is published to PyPI): `pipx install plugin-kit-ai==1.2.4`") + mustContain(t, historicalReadme, "fallback installer: `curl -fsSL https://raw.githubusercontent.com/777genius/plugin-kit-ai/main/scripts/install.sh | sh`") + mustContain(t, historicalReadme, "plugin-kit-ai init my-plugin --template online-service") + mustContain(t, historicalReadme, "plugin-kit-ai init my-plugin --template local-tool") + mustContain(t, historicalReadme, "plugin-kit-ai init my-plugin --template custom-logic") + mustContain(t, historicalReadme, "plugin-kit-ai init my-plugin") + mustContain(t, historicalReadme, "plugin-kit-ai generate .") + mustContain(t, historicalReadme, "plugin-kit-ai validate . --platform codex-runtime --strict") + mustContain(t, historicalReadme, "## Works Across Multiple Outputs") + mustContain(t, historicalReadme, "## What To Do Next") + mustContain(t, historicalReadme, "## Keep This Rule In Mind") mustContain(t, string(cliReadme), "How To Publish Plugins") mustContain(t, string(cliReadme), "https://777genius.github.io/plugin-kit-ai/docs/en/guide/how-to-publish-plugins.html") mustContain(t, string(publishGuideEn), "codex-marketplace") @@ -304,32 +321,32 @@ func TestContractClarity_RuntimeMetadataAndDocsStayAligned(t *testing.T) { mustContain(t, string(publishGuideRu), "Gemini в v1 использует plan-and-readiness publication, а не local apply.") mustContain(t, string(guideIndexEn), "/en/guide/how-to-publish-plugins") mustContain(t, string(guideIndexRu), "/ru/guide/how-to-publish-plugins") - mustContain(t, string(rootReadme), "## Deep Product Details") - mustContain(t, string(rootReadme), "## Go Deeper By Goal") - mustContain(t, string(rootReadme), "### Fast Local Plugin") - mustContain(t, string(rootReadme), "### Production-Ready Plugin Repo") - mustContain(t, string(rootReadme), "### Already Have Native Config") - mustContain(t, string(rootReadme), "[examples/starters/README.md](examples/starters/README.md)") - mustContain(t, string(rootReadme), "[examples/local/README.md](examples/local/README.md)") - mustContain(t, string(rootReadme), "[docs/CHOOSING_HELPER_DELIVERY_MODE.md](docs/CHOOSING_HELPER_DELIVERY_MODE.md)") - mustContain(t, string(rootReadme), "the stable local Python and Node subset on `codex-runtime` and `claude`") - mustContain(t, string(rootReadme), "`doctor`, `bootstrap`, `validate --strict`, `export`, and bundle handoff for that stable local subset") - mustContain(t, string(rootReadme), "`generate`, `import`, and `normalize` are still `public-beta`") - mustContain(t, string(rootReadme), "[docs/generated/target_support_matrix.md](docs/generated/target_support_matrix.md)") - mustContain(t, string(rootReadme), "[docs/generated/support_matrix.md](docs/generated/support_matrix.md)") - mustContain(t, string(rootReadme), "[docs/SUPPORT.md](docs/SUPPORT.md)") - mustContain(t, string(rootReadme), "## SDK And CLI") - mustContain(t, string(rootReadme), "Go SDK packages:") - mustContain(t, string(rootReadme), "`github.com/777genius/plugin-kit-ai/sdk/claude`") - mustContain(t, string(rootReadme), "`github.com/777genius/plugin-kit-ai/sdk/codex`") - mustContain(t, string(rootReadme), "`github.com/777genius/plugin-kit-ai/sdk/gemini`") - mustContain(t, string(rootReadme), "./bin/plugin-kit-ai doctor ./my-plugin") - mustContain(t, string(rootReadme), "./bin/plugin-kit-ai bootstrap ./my-plugin") - mustContain(t, string(rootReadme), "./bin/plugin-kit-ai import ./native-plugin --from codex-runtime") - mustContain(t, string(rootReadme), "./bin/plugin-kit-ai capabilities --format json") - mustContain(t, string(rootReadme), "`plugin-kit-ai validate --format json` now emits the versioned `plugin-kit-ai/validate-report` contract") - mustContain(t, string(rootReadme), "[docs/CODEX_TARGET_BOUNDARY.md](docs/CODEX_TARGET_BOUNDARY.md)") - mustContain(t, string(rootReadme), "[docs/VALIDATE_JSON_CONTRACT.md](docs/VALIDATE_JSON_CONTRACT.md)") + mustContain(t, historicalReadme, "## Deep Product Details") + mustContain(t, historicalReadme, "## Go Deeper By Goal") + mustContain(t, historicalReadme, "### Fast Local Plugin") + mustContain(t, historicalReadme, "### Production-Ready Plugin Repo") + mustContain(t, historicalReadme, "### Already Have Native Config") + mustContain(t, historicalReadme, "[examples/starters/README.md](examples/starters/README.md)") + mustContain(t, historicalReadme, "[examples/local/README.md](examples/local/README.md)") + mustContain(t, historicalReadme, "[docs/CHOOSING_HELPER_DELIVERY_MODE.md](docs/CHOOSING_HELPER_DELIVERY_MODE.md)") + mustContain(t, historicalReadme, "the stable local Python and Node subset on `codex-runtime` and `claude`") + mustContain(t, historicalReadme, "`doctor`, `bootstrap`, `validate --strict`, `export`, and bundle handoff for that stable local subset") + mustContain(t, historicalReadme, "`generate`, `import`, and `normalize` are still `public-beta`") + mustContain(t, historicalReadme, "[docs/generated/target_support_matrix.md](docs/generated/target_support_matrix.md)") + mustContain(t, historicalReadme, "[docs/generated/support_matrix.md](docs/generated/support_matrix.md)") + mustContain(t, historicalReadme, "[docs/SUPPORT.md](docs/SUPPORT.md)") + mustContain(t, historicalReadme, "## SDK And CLI") + mustContain(t, historicalReadme, "Go SDK packages:") + mustContain(t, historicalReadme, "`github.com/777genius/plugin-kit-ai/sdk/claude`") + mustContain(t, historicalReadme, "`github.com/777genius/plugin-kit-ai/sdk/codex`") + mustContain(t, historicalReadme, "`github.com/777genius/plugin-kit-ai/sdk/gemini`") + mustContain(t, historicalReadme, "./bin/plugin-kit-ai doctor ./my-plugin") + mustContain(t, historicalReadme, "./bin/plugin-kit-ai bootstrap ./my-plugin") + mustContain(t, historicalReadme, "./bin/plugin-kit-ai import ./native-plugin --from codex-runtime") + mustContain(t, historicalReadme, "./bin/plugin-kit-ai capabilities --format json") + mustContain(t, historicalReadme, "`plugin-kit-ai validate --format json` now emits the versioned `plugin-kit-ai/validate-report` contract") + mustContain(t, historicalReadme, "[docs/CODEX_TARGET_BOUNDARY.md](docs/CODEX_TARGET_BOUNDARY.md)") + mustContain(t, historicalReadme, "[docs/VALIDATE_JSON_CONTRACT.md](docs/VALIDATE_JSON_CONTRACT.md)") mustContain(t, string(cliReadme), "## Fast Local Plugin") mustContain(t, string(cliReadme), "## Production-Ready Plugin Repo") mustContain(t, string(cliReadme), "## Already Have Native Config") diff --git a/repotests/starter_template_sync_integration_test.go b/repotests/starter_template_sync_integration_test.go index f9f594aa..ddcb0f44 100644 --- a/repotests/starter_template_sync_integration_test.go +++ b/repotests/starter_template_sync_integration_test.go @@ -49,7 +49,16 @@ func TestStarterTemplateSyncContractFilesStayAligned(t *testing.T) { mustContain(t, workflow, "run: ./scripts/update-starter-template.sh") mustContain(t, workflow, "default: \"all\"") mustContain(t, workflow, "- all-runtime-package") - mustContain(t, rootReadme, "Codex and Claude starters across Go, Python, and") + // Preserved v1 starters remain discoverable without being advertised as + // root plugin.json templates for the unreleased standard authoring MVP. + _, historicalReadme, found := strings.Cut(rootReadme, "### Historical authoring and development\n") + if !found { + t.Fatal("README missing historical authoring boundary") + } + mustContain(t, strings.Join(strings.Fields(historicalReadme), " "), "The repository preserves Codex and Claude starters across Go, Python, and Node/TypeScript.") + mustContain(t, historicalReadme, "[starters](examples/starters/README.md)") + mustContain(t, startersReadme, "Historical plugin-kit-ai v1 managed examples; baseline 1.2.4.") + mustContain(t, startersReadme, "These are not root `plugin.json` starters for the standard MVP.") mustContain(t, cliReadme, "Official starter templates:") mustContain(t, startersReadme, "These starter repos are the fastest way to get one working plugin repo that can later expand to more supported outputs.") mustContain(t, startersReadme, "Use this template") From cc63ec462840ac867669603f47ce4be8953454b1 Mon Sep 17 00:00:00 2001 From: iliya Date: Mon, 7 Sep 2026 15:54:52 +0000 Subject: [PATCH 2/2] test(docs): normalize README contract line endings --- .../contract_clarity_integration_test.go | 2 +- repotests/readme_boundary_test.go | 46 +++++++++++++++++++ .../starter_template_sync_integration_test.go | 2 +- 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 repotests/readme_boundary_test.go diff --git a/repotests/contract_clarity_integration_test.go b/repotests/contract_clarity_integration_test.go index eaeb4e1c..4748e812 100644 --- a/repotests/contract_clarity_integration_test.go +++ b/repotests/contract_clarity_integration_test.go @@ -220,7 +220,7 @@ func TestContractClarity_RuntimeMetadataAndDocsStayAligned(t *testing.T) { // The root README separates the installer and unreleased standard preview // from preserved v1 capabilities. Keep legacy claims inside that boundary. - currentReadme, historicalReadme, found := strings.Cut(string(rootReadme), "### Historical authoring and development\n") + currentReadme, historicalReadme, found := cutHistoricalReadme(string(rootReadme)) if !found { t.Fatal("README missing historical authoring boundary") } diff --git a/repotests/readme_boundary_test.go b/repotests/readme_boundary_test.go new file mode 100644 index 00000000..ce61377f --- /dev/null +++ b/repotests/readme_boundary_test.go @@ -0,0 +1,46 @@ +package pluginkitairepo_test + +import ( + "strings" + "testing" +) + +// Normalize only Windows line endings; retain the exact historical heading and +// terminating newline so current and preserved-v1 assertions stay separated. +func cutHistoricalReadme(readme string) (current, historical string, found bool) { + return strings.Cut(strings.ReplaceAll(readme, "\r\n", "\n"), "### Historical authoring and development\n") +} + +func TestHistoricalReadmeBoundaryLineEndings(t *testing.T) { + const heading = "### Historical authoring and development" + for _, newline := range []struct{ name, value string }{{"LF", "\n"}, {"CRLF", "\r\n"}} { + for _, tc := range []struct { + name, boundary string + found bool + }{ + {"exact", heading + newline.value, true}, + {"missing", "", false}, + {"wrong_title", "### Historical authoring" + newline.value, false}, + {"wrong_level", "## Historical authoring and development" + newline.value, false}, + {"trailing_space", heading + " " + newline.value, false}, + {"suffix", heading + " extra" + newline.value, false}, + {"no_newline", heading, false}, + {"bare_CR", heading + "\r", false}, + } { + t.Run(newline.name+"/"+tc.name, func(t *testing.T) { + input := "current" + newline.value + tc.boundary + "historical" + newline.value + current, historical, found := cutHistoricalReadme(input) + if found != tc.found { + t.Fatalf("boundary found = %v, want %v", found, tc.found) + } + if found { + if current != "current\n" || historical != "historical\n" { + t.Fatalf("incorrect sections: current=%q historical=%q", current, historical) + } + } else if current != strings.ReplaceAll(input, "\r\n", "\n") || historical != "" { + t.Fatalf("missing boundary changed sections: current=%q historical=%q", current, historical) + } + }) + } + } +} diff --git a/repotests/starter_template_sync_integration_test.go b/repotests/starter_template_sync_integration_test.go index ddcb0f44..c9470566 100644 --- a/repotests/starter_template_sync_integration_test.go +++ b/repotests/starter_template_sync_integration_test.go @@ -51,7 +51,7 @@ func TestStarterTemplateSyncContractFilesStayAligned(t *testing.T) { mustContain(t, workflow, "- all-runtime-package") // Preserved v1 starters remain discoverable without being advertised as // root plugin.json templates for the unreleased standard authoring MVP. - _, historicalReadme, found := strings.Cut(rootReadme, "### Historical authoring and development\n") + _, historicalReadme, found := cutHistoricalReadme(rootReadme) if !found { t.Fatal("README missing historical authoring boundary") }