Skip to content

docs(contracts): move plugin-author contracts out of docs/conventions - #10719

Closed
kyle-sexton wants to merge 31 commits into
mainfrom
docs/7537-contracts-split
Closed

kyle-sexton wants to merge 31 commits into
mainfrom
docs/7537-contracts-split

Conversation

@kyle-sexton

@kyle-sexton kyle-sexton commented Oct 28, 2026 •

Copy link
Copy Markdown
Member

Closes #7537

Summary

docs/conventions/ held two kinds of file: contracts for plugin authors working in this repository, and the convention and settings files a consumer repository would also have (ADR 0064). Plugins resolve a consumer's convention home to docs/conventions/ by default, so this repository's own folder now holds only what a consumer's would.

Fix

  • 48 plugin-author contract folders move from docs/conventions/<name>/ to docs/contracts/<name>/ (for example hook-budget, enforcement-ladder, mod-authoring, hook-precision, loop-lane, config-cascade).
  • Old paths that keep a stub:
    • Every moved README keeps a stub carrying each heading of the moved file, so existing links and #anchor references still resolve.
    • The 11 other moved files that something under plugins/, lib/, scripts/ or .github/ on main cites, which installed plugin versions carry:
      • check-placement/adopting-git-hooks.md, config-cascade/consumer-gotchas.md and hook-precision/guard-precision.md keep a heading and a "Moved to" link.
      • ecosystem-commands/ecosystem.schema.json, hook-telemetry/envelope.schema.json, hook-telemetry/data/{block-windows-drive-tmp,lane-stop-gate,stale-path-verify}.schema.json and standards/standards.schema.json are JSON Schemas that keep the old $id and $ref the new file's $id.
      • ecosystem-commands/examples/{dotnet,go}.yaml are comment-only pointers; no lane reads them, so scripts/affected-tests-no-suite.txt records them.
  • The other moved files (changelogs, the remaining schemas and examples, sub-docs) get no stub: nothing in those trees cites their old paths.
  • docs/conventions/ keeps the <concern>.yaml and .md settings files and pr-pipeline/, which moves later behind its own gate.
  • References across plugins, scripts, .claude/ and AGENTS.md point at docs/contracts/. The config-cascade and prerequisites readers read from docs/contracts/.
    • A few comment links in files with no test suite stay on the old README paths, where the stubs resolve them.
    • The plugin copy of hook-telemetry-sink.sh stays in step with its .claude/ copy.
  • The AGENTS.md "Team standards" paragraph now says where contracts and settings live.
  • docs/contracts/ecosystem-commands/examples.test.sh validates the moved examples against ecosystem.schema.json, with a negative case.
  • Changelog fragments for every plugin the branch touches.

Verification

  • Pre-push on head ddf6655e27, merged with main 2026-10-28:
    • check-affected passed: 12 passed, 5 skipped.
    • guardrails-remote-reference-verify passed in 150 s.
  • Main's reference-verify.sh over the whole branch range: exit 0 in 87 s.
  • examples.test.sh in the affected-tests suite: 138/138.
  • Stub commit: every old non-README path was checked with git grep -l -F <old path> origin/main -- plugins lib scripts .github; the 11 stubbed are the hits other than standards/CHANGELOG.md, which only this repository's check-standards-contract-bump scripts name and this branch repoints. The six stub schemas pass check-jsonschema --check-metaschema; check-affected passed (11 passed, 4 skipped) and check-changelog-fragments.sh --check-required passed.

Related

🤖 Generated with Claude Code

kyle-sexton and others added 22 commits October 27, 2026 20:55
Move the 48 marketplace plugin contract folders out of docs/conventions/
into docs/contracts/, per the owner decision on #7537, and rewrite every
reference outside .claude/ (paths, raw and blob URLs, relative links).
docs/conventions/ keeps this repository's <concern>.yaml and .md settings.

Per-folder calls: standards, commit-convention, loop-lane and
pr-body-convention are marketplace owner docs, so they move. pr-pipeline
stays until it moves under its own gate; source-control stays because it
holds the consumer settings file commit-convention.yml.

ADR 0064 Decision 6 is amended and AGENTS.md names the new home. The
changelog parity check also reads docs/contracts/*/CHANGELOG.md.

Refs: #7537

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0144XNKvN1T32ur41zrz3oaW
Each contract folder moved to docs/contracts/ keeps a README at its old
docs/conventions/<name>/ path pointing at the new one, so links from
installed plugin versions keep resolving.

Refs: #7537

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0144XNKvN1T32ur41zrz3oaW
…acts

validate-plugin-contracts and the prerequisites schema test built the
old path from separate segments, which the path rewrite missed. Adds the
pr-pipeline fragment for its rewritten contract links.

Refs: #7537

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0144XNKvN1T32ur41zrz3oaW
…plit

Re-ran the contract path rewrite over main's new text (babysit_risk.py,
the pr-pipeline README cost-hold link).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0144XNKvN1T32ur41zrz3oaW
Each stub at docs/conventions/<name>/README.md keeps the old README's
headings in order, each pointing at the same section of
docs/contracts/<name>/README.md, so deep links from installed plugin
versions still land on their section. Fragments are a patch only where
the shared-copy and standards-contract bump gates require one (76
plugins); the 8 path-only plugins take bump: none.

Refs: #7537

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0144XNKvN1T32ur41zrz3oaW
…plit

# Conflicts:
#	docs/conventions/commit-convention/README.md
#	docs/conventions/loop-lane/README.md
#	docs/conventions/plugin-reconfiguration/README.md
#	docs/extensibility-contract-smoke-tests.md
#	lib/resolve-convention-pattern.sh
#	plugins/guardrails/hooks/block-convention-violation.sh
#	plugins/guardrails/hooks/resolve-convention-pattern.sh
#	scripts/validate-plugin-contracts.mjs
…aths

requirements.in and the toolchain ecosystem YAMLs have no test lane, so
affected-tests fails any change to them by design
(scripts/affected-tests-no-suite.txt). Their only change here was a
comment link to the moved contract; the stub at the old path keeps every
heading, so the link still resolves. Restore them to main's text.

Refs: #7537

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…te runs as a background job

check-changed-skills.sh runs each checker with `&`, so the suite starts with
SIGINT ignored, and bash cannot trap a signal ignored on entry: case 16's
INT never reached fix-plugin-drift.sh's trap and the apply completed, failing
4 of 316 checks. Run the script under env --default-signal=INT when SIGINT
arrives ignored, and skip case 16 where env lacks that flag.

Refs: #7537

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ir schema

The contracts move renames the four examples, and affected-tests fails any
change to them because no suite read them (scripts/affected-tests-no-suite.txt
asked for a check-jsonschema lane first). examples.test.sh names each example,
validates it against ecosystem.schema.json, and checks that an example without
the required globs key is rejected; it skips when check-jsonschema is absent,
as check-convention-yaml.test.sh does.

Refs: #7537

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e .claude edit lands

.claude/hooks/hook-telemetry-sink.sh must match the harness-ops copy byte
for byte, and its pointer edit waits on the owner's review of the .claude/
edits. Keep the plugin copy's comment on the old path for now; the stub
there keeps every heading, so the pointer still resolves.

Refs: #7537

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Five .claude/ files (code-metrics.yaml, check-affected-pre-push.sh,
hook-telemetry-sink.sh, mod-authoring.md, skill-bodies-state-current-rules.md)
and the harness-ops copy of the telemetry sink now cite the moved contracts.
The owner approved these edits on 2026-10-28; the stubs at the old paths
keep every heading, so older links still resolve.

Refs: #7537

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs-hygiene already reads docs/conventions/docs-hygiene.yaml (the
row near the top of the matrix), and #5699 deleted its .claude/ JSON,
so the "listed for later adoption" row was stale. The two retirement
records name the retired files without a .claude/ path prefix, so the
reference check, which judges the moved file whole, stops reading them
as live citations; the meaning is unchanged.

Refs: #7537

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kyle-sexton
kyle-sexton marked this pull request as ready for review October 28, 2026 21:56
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-28T21:59:27.195354Z 3b34f3a Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

claude-security-review reviewed 0e0cc61b1deb7909299869c40bdfdc3207b6061a: 0 finding(s), 0 as inline comments.

No security findings.

critical-findings: 0

This is a path move: 48 contract folders go from docs/conventions/ to docs/contracts/, with stubs left at the old paths. I read the diff directly and did not dispatch hunter or verifier subagents. My shell tool was disabled, so I searched .claude-lane/pr.diff and the checkout with Grep and Read.

What I read in the trusted paths

  • .github/scripts/pr-merge/enable-auto-merge.mjs and post-unarmed-status.mjs: comment-only. They repoint a loop-lane link and change no logic.
  • .github/workflows/pr-require-checks.yml: two comment-only path edits. The ci-status hold steps are untouched.
  • babysit_risk.py and babysit_verify_evidence.py: docstring and comment URL edits only. The risk path table (babysit_risk.py:280) and docs/conventions/pr-pipeline.yaml stay where they are.
  • babysit_review_evidence.py: LANE_SOURCE_PREFIXES gains docs/contracts/instruction-exception-register/ and docs/contracts/untrusted-content/. The old docs/conventions/ prefixes stay, so editing either the stub or the moved file still marks a pull request as having changed its own review input. This widens the set of lane-source paths and weakens nothing. test_babysit_review_evidence.py covers both.
  • .github/workflows/release-publish-plugins.yml:231: the staged release commit now also stages docs/contracts. It comes from the main checkout, so no untrusted input reaches it.
  • Trust controls: none of trusted-actors, check-trusted-trigger, request-lane-token, check-kill-switch, resolve-config, CODEOWNERS, .gitmodules, merge-holds.mjs or the merge: settings in pr-pipeline.yaml changed. pr-pipeline.yaml and pr-pipeline/ stay in docs/conventions/, as the description says.
  • Plugin manifests: the diff touches no plugin.json or marketplace.json, so there are no manifest <field> lines.
  • The lib/, scripts/ and .claude/ changes are comment, link and string-literal repoints. The one functional path change is lib/hook-test-sink.sh:68, which now looks for envelope.schema.json under docs/contracts/. The schema moves in the same pull request, and the test fails closed if it is missing.

Instruction-surface check
docs/conventions/instruction-exception-register/README.md and untrusted-content/README.md become heading-only stubs that link to docs/contracts/. The full text moves intact, and docs/contracts/instruction-exception-register/README.md carries the classes. An installed older security-review skill still reads the old path. It would find the stub, which still links to the moved sections. The updated skill in this change points at the new path. No rule is deleted, so this is not a finding. The register's protected-class list was not re-read against the removed lines, because nothing in the diff deletes a rule.

No spend: this change adds no paid plan, billing setting or billed resource, and no prepaid-credit usage either.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

claude-review: 2 inline finding(s) on 3b34f3a333ea460baa0834a1ed3b56c30ed0c28f; the summary is in this lane's pull request comment.

claude-lane: claude-review

Comment thread scripts/check-changelog-parity.sh
@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

claude-review reviewed 0e0cc61b1deb7909299869c40bdfdc3207b6061a: 0 finding(s), 0 as inline comments.

No findings. I did not read the whole 1065-file diff; I sampled the files where behavior can change. I had no shell, so I ran nothing and did not run the author's checks (check-affected, reference-verify.sh, examples.test.sh).

I read:

  • the stub schemas that keep an old $id and $ref the new file;
  • the changelog-fragment helpers convention_of and root_of in scripts/lib/changelog-fragments.sh, check-changelog-fragments.sh and write-changelog-fragments.sh, with their tests;
  • the new docs/contracts/ecosystem-commands/examples.test.sh;
  • the trusted-path changes: the comment-only path edits in pr-merge/enable-auto-merge.mjs, pr-merge/post-unarmed-status.mjs, babysit_risk.py and babysit_verify_evidence.py, the pr-require-checks.yml comments, and the security-review SKILL.md path edits;
  • the babysit_review_evidence.py change, which adds docs/contracts/instruction-exception-register/ and docs/contracts/untrusted-content/ to LANE_SOURCE_PREFIXES next to the old stub paths;
  • the release-publish-plugins.yml change that adds docs/contracts to git add, the AGENTS.md edits, and the .changes fragments.

Everything I read holds:

  • Trusted-path scripts: the pr-merge and babysit edits are comment or doc-URL rewrites, plus the lane-source prefix addition above. No gate logic changed.
  • Changelog helpers: the new helpers resolve docs/contracts/<name>/ and docs/conventions/<name>/, and skip a stub left at the old path or a name a plugin owns.
  • Schemas and tests: the stub schemas keep the old $id, and the in-repo readers (hook-test-sink, standards scripts, prerequisites.test.mjs) now point at docs/contracts/.
  • Examples test: examples.test.sh has a negative case, and it skips rather than passes when check-jsonschema is missing.
  • Fragments: the fragments I read are bump: patch, which fits a path-only change.

Manifest items: the diff touches no plugin.json or marketplace.json, so the manifest checks do not apply.

Closing issue #7537: I read this against the issue's decision comments. The move, the stubs, the AGENTS.md update and the pr-pipeline/ carve-out match them. The comment says ADR 0064 Decision 6 is amended in the same change. The diff touches ADR 0064, but I did not read that edit.

Cost: no billing or paid-plan change.

kyle-sexton and others added 2 commits October 28, 2026 19:02
… root

The contracts move left fragment mode matching only docs/conventions/. A
listed contract's fragment failed as UNKNOWN PLUGIN, its README edits needed
no fragment, a non-release heading skipped FRAGMENT-MODE RELEASE, and the
release job would stage the fragment deletions but not the CHANGELOG entry.

root_of now finds docs/contracts/<name>/CHANGELOG.md, and the new
changelog_fragments::convention_of classifies a path under either home for
check-changelog-parity.sh and check-changelog-fragments.sh. The standalone
write-changelog-fragments.sh, the release workflow's git add and the error
text cover both homes. Each convention test now runs under both homes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The contracts move swapped the two docs/conventions/ lane-source prefixes
for docs/contracts/ ones, but the stubs stay at the old paths and installed
plugin versions still read them for the untrusted-content framing. Keep both
prefixes until the stubs retire, so an edit to a stub still marks the pull
request as one that may have changed its own review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@melodic-automation-lanes

melodic-automation-lanes Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

The pr-unblock lane stopped resolve-conflicts on this pull request: the lane could not resolve every conflict. The lane sets no label: the run ends in a failing pr-unblock/conflict status on the head the lane gated.

When a retry on this head can change the outcome, the lane runs one on its own, up to its per-head cap, and edits this comment if it stops again; a run that does not stop clears the status. When no retry can (a review thread the lane does not take or settle, or a failing check after the retries are spent), a person resolves the threads or gets the checks green, then dispatches the workflow below: that run finds the cause gone and clears the status. On a pull request the lanes App opened, the dispatchers start that run once per stop; on any other, a person does. A new commit to the branch starts clean.

To run it again on this head now, dispatch the pr-unblock workflow:

gh workflow run pr-unblock.yml -R melodic-software/claude-code-plugins -f pr-number=10719 -f activity=resolve-conflicts

…plit

Port #10767's three-label table (needs-human, attended, host-run) from
the old "When work stops for the owner" section into its new home in
docs/contracts/loop-lane/README.md, with links rebased to that
directory; the old location keeps its "Moved to" stub.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

claude-review: 1 inline finding(s) on ff294381e6698d2ec7e64316a431aa2b3c872fe2; the summary is in this lane's pull request comment.

claude-lane: claude-review

Comment thread docs/contracts/ecosystem-commands/ecosystem.schema.json
@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

The pr-verify verifier failed head 0e0cc61b1deb7909299869c40bdfdc3207b6061a. What it wrote, as data:

Summary: Issue #7537 asks for the plugin-author contracts in docs/conventions/ to move to docs/contracts/, with stubs at the old paths, every reference rewritten, AGENTS.md updated and ADR 0064 Decision 6 amended. The diff is about 3.4 MB. It shows each moved file in full instead of as a rename, and it runs to hundreds of files. I could not review it all with confidence. The parts I read look right: the reference rewrites in .claude/, .github/, AGENTS.md and the ADRs, the AGENTS.md "Team standards" paragraph, and the one-line release-publish-plugins.yml staging change. The parts I could not read include executable code: the changelog-fragment scripts, the config-cascade and prerequisites readers, babysit_review_evidence.py and its tests, the plugin hook scripts and the plugin skill instructions. The rules require `fail` when an unread part is executable, so this fails on size and the change needs to be split. I found no correctness or safety defect in what I read.
- pr-verify-data/diff.patch: about 3.4 MB. Moved files appear as full delete and add instead of renames, so I could not review the whole diff with confidence. Split it into: (1) a pure move PR, with the docs/conventions/<name>/ to docs/contracts/<name>/ renames and the old-path stubs only, so rename detection keeps it small; (2) a PR for the prose and comment reference rewrites in docs/, plugins/*/skills and the changelog fragments; (3) a small PR for the executable changes.
- scripts/lib/changelog-fragments.sh, scripts/check-changelog-parity.sh, scripts/check-changelog-fragments.sh, scripts/write-changelog-fragments.sh: the PR adds root_of/convention_of handling for docs/contracts/. I could not find or review these changes in the diff I read. Put them in the small executable PR so a reviewer can confirm both homes resolve, including a stub left at the old home.
- babysit_review_evidence.py and tests/test_babysit_review_evidence.py: the lane-source prefix list changes (both the docs/contracts/ and the old docs/conventions/ prefixes). I could not review this. It feeds the review and merge lanes, so put it in the executable PR.
- The config-cascade and prerequisites readers now read from docs/contracts/. I could not review the code change. Put it in the executable PR with its tests.
- plugins/**/hooks/*.sh, the plugin copy of hook-telemetry-sink.sh, and plugin SKILL.md and agent instructions: many changes, not reviewed in full. A path rewrite inside an executable hook or a lane-steering instruction must be readable on its own. Keep it in a reviewable split.
- .github/workflows/release-publish-plugins.yml:231: `git add -A -- plugins docs/contracts docs/conventions .changes` is correct for the move (read and judged).
- AGENTS.md:102-106: the Team standards paragraph now names docs/contracts/ for contracts, docs/conventions/ for settings, and pr-pipeline/ staying put until its own gate. This matches the owner's 2026-10-22 decision (read and judged).
- docs/adr/0064-*.md: the owner's decision requires amending Decision 6 in this same change. I could not confirm the amendment in the part of the diff I could read. Make sure the split PRs include it, along with the conventions index update the issue asks for (step 4).
- Issue #7537: the owner's decision says the move is built attended because it touches AGENTS.md. The PR author is the owner account, which looks consistent with that.

This pull request leaves the merge queue, and ci-status holds it out while it carries pr-verify-failed. A pr-verify pass at a new commit removes the label.

@github-actions github-actions Bot added the pr-verify-failed pr-verify failed this head; a pass at a new commit removes it. label Oct 28, 2026
kyle-sexton and others added 2 commits October 28, 2026 19:53
…l cite

Leave a pointer stub at each old docs/conventions/ path that a file under
plugins/, lib/, scripts/ or .github/ on main references: three sub-docs, six
JSON Schemas that keep their old $id and $ref the new one, and two
comment-only ecosystem-commands example stubs, recorded as no-suite paths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kyle-sexton
kyle-sexton added this pull request to the merge queue Oct 29, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 29, 2026
@kyle-sexton kyle-sexton added the do-not-merge Hard merge gate: do not merge while applied. label Oct 29, 2026
@kyle-sexton

Copy link
Copy Markdown
Member Author

Closing as superseded: pr-verify failed this head for size (about 3.5 MB), and #7537 is landing as a split. #7537 stays open.

kyle-sexton added a commit that referenced this pull request Oct 29, 2026
Drop the attended-label fragment carried over from #10719's branch (already
released), drop the stub claim from B1's fragments (B2 adds the stubs), and
restore main's wording in config-cascade/README.md so it differs only in paths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do-not-merge Hard merge gate: do not merge while applied. pr-verify-failed pr-verify failed this head; a pass at a new commit removes it.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: separate plugin-author contracts from consumer conventions in docs/conventions

1 participant