Skip to content

chore(conventions): add ecosystem-commands contract; record concern-named config seam - #96

Merged
kyle-sexton merged 4 commits into
mainfrom
chore/amend-ecosystem-commands
Jul 12, 2026
Merged

kyle-sexton merged 4 commits into
mainfrom
chore/amend-ecosystem-commands

Conversation

@kyle-sexton

@kyle-sexton kyle-sexton commented Jul 12, 2026 •

Copy link
Copy Markdown
Contributor

Codifies the ecosystem-commands design gate (interview-resolved 2026-07-12; consensus of 3 independent design reviews).

What

  • docs/conventions/ecosystem-commands/ — versioned cross-plugin contract: consumers declare per-ecosystem build/test/lint command surfaces in .claude/ecosystems/<eco>.yaml (drop-in folder, *.local.yaml overlays, user-global → team → local additive resolution); JSON Schema; worked examples; CHANGELOG.
  • Canonical-verb vs context-binding boundary: the contract owns the verb; lefthook/CI keep their own staged/full-scope bindings and cite the ecosystem file.
  • Task-runner verb SSOT deferred with recorded revisit triggers; command values are opaque strings so a later runner-pointer migration is a value swap.
  • docs/MIGRATION-PLAYBOOK.md seam 2 — new rule: multi-plugin-consumed tracked config uses a concern-named folder (.claude/<concern>/**) with its contract recorded under docs/conventions/<concern>/ (hook-telemetry template).

Why

Three divergent encodings of the same command surface exist today (implementation /build table, /lint table, review-toolkit ecosystem-specialist inline defaults) with no consumer-declared source to defer to. Follow-up retrofit/cutover issues land in the medley tracker.

Refs melodic-software/medley#1390


Note

Low Risk
Documentation and schema only; execution behavior is unchanged until plugins adopt the contract in follow-up work.

Overview
Introduces a versioned cross-plugin contract so consumer repos declare per-ecosystem build/test/lint commands in .claude/ecosystems/<eco>.yaml instead of each plugin keeping its own tables.

docs/conventions/ecosystem-commands/ documents the contract: JSON Schema (ecosystem.schema.json), layered resolution (user-global → team → *.local.yaml), the canonical verb vs context-binding split (verbs live here; lefthook/CI keep staged/full-scope bindings and reference these files), plugin resolution ladder behavior, tolerant reading / optional strict validation, and deferred task-runner SSOT with revisit triggers. Worked examples cover bash, dotnet, and python.

docs/MIGRATION-PLAYBOOK.md extends extensibility seam 2: when tracked config is consumed by more than one plugin, use a concern-named folder (.claude/<concern>/**) and record the contract under docs/conventions/<concern>/, with ecosystem-commands as the first instance.

No plugin or consumer code changes in this PR—follow-up retrofit/cutover is tracked separately.

Reviewed by Cursor Bugbot for commit db9eb2d. Bugbot is set up for automated code reviews on this repo. Configure here.

…amed config seam

Versioned cross-plugin contract for consumer-declared per-ecosystem
build/test/lint command surfaces (.claude/ecosystems/<eco>.yaml):
schema, resolution ladder application, canonical-verb vs
context-binding boundary, task-runner deferral with revisit triggers.
Playbook seam 2 gains the concern-named folder rule for
multi-plugin-consumed config.

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

cursor Bot commented Jul 12, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_8813cd49-be75-48bb-9835-202165202822)

@claude

claude Bot commented Jul 12, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 2m 32s —— View job


PR Review

  • Gather context
  • Read changed files
  • Review for correctness, security, and CLAUDE.md alignment
  • Post findings

This is a clean documentation-only PR introducing a versioned cross-plugin contract. The architecture decisions are sound and well-motivated. Two correctness issues and two minor gaps are below.


Medium: $id points to a rendered HTML page, not raw JSON

ecosystem.schema.json L4:

"$id": "https://github.com/melodic-software/claude-code-plugins/blob/main/docs/conventions/ecosystem-commands/ecosystem.schema.json"

The github.com/.../blob/... URL serves an HTML page. A JSON Schema validator that dereferences $id to verify schema identity will receive HTML, not JSON. Every sibling schema in hook-telemetry/ uses raw.githubusercontent.com instead (e.g. the envelope schema). The fix is a one-word change:

"$id": "https://raw.githubusercontent.com/melodic-software/claude-code-plugins/main/docs/conventions/ecosystem-commands/ecosystem.schema.json"

Fix this →


Medium: Array merge semantics are unspecified for overlay resolution

README.md "File layout and resolution":

Resolution per ecosystem, additive per key: user-global → team file → local overlay. A later layer overrides earlier layers key-by-key…

"Additive per key" and "overrides key-by-key" are in tension for array fields (globs, gates, project-discovery). If a local overlay adds globs: ["*.pyi"] to a team file that already has globs: ["*.py"], does the resolver produce ["*.py", "*.pyi"] (append) or ["*.pyi"] (replace)? The prose doesn't say. The MIGRATION-PLAYBOOK's "additive-preferred" rule implies append, but a plugin author implementing the resolver could reasonably read "key-by-key" as replacement.

This needs one clarifying sentence (e.g. "For array fields, a later layer's items are appended; to replace an array, set the full list in the override layer") or a short overlay example in examples/ showing a dotnet.local.yaml that adds a gate without repeating the base globs.


Low: <files> placeholder has no example

README.md placeholder table documents <files> (the changed-files list), but neither example uses it — only <solution-or-project-file> and <project-dir> appear in the fixtures. A plugin author implementing the substitution step has no concrete reference for what <files> expands to or how it should be passed to the command. Worth adding one command that uses it (e.g. a hypothetical check-cmd: 'uv run ruff check <files> --no-fix') or noting that it is intended for future use.


Low: additionalProperties: true silently passes key-name typos

ecosystem.schema.json L8:

The "tolerant reader" design is explicitly called out in the README and is intentional. Worth a one-line doc note that the recommended check-jsonschema consumer gate will also accept check_cmd (underscore) as an unknown key, not an error — so a field-name typo silently produces a file where the intended command is never found. Consumers who want stricter validation can run check-jsonschema --no-additional-properties locally.


Observations (no action required)

  • The concern-named folder addition to MIGRATION-PLAYBOOK.md seam 2 integrates cleanly. The cross-reference to docs/conventions/hook-telemetry/ as the template directory is valid — that directory exists.
  • Resolution ladder in README matches the convention-resolution ladder in MIGRATION-PLAYBOOK.md exactly.
  • CHANGELOG accurately enumerates every schema key.
  • Both YAML examples are valid against the schema, and the null build-cmd in python.yaml correctly exercises the nullable type.
  • No security surface introduced — pure documentation with no code execution, no external calls, no secrets.

…po-tolerance note

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

cursor Bot commented Jul 12, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_b0a54d7d-9c13-4671-92bd-a06203ee75d1)

@claude

claude Bot commented Jul 12, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 2m 7s —— View job


PR Review

  • Gather context and diff
  • Read changed files
  • Review for correctness, security, and CLAUDE.md alignment
  • Post findings

This amendment commit addresses three of the four findings from the initial review. Notes on what landed and what remains:


Fixed: $id raw URL

ecosystem.schema.json L3 — correctly changed to raw.githubusercontent.com. Matches the sibling hook-telemetry schemas.


Fixed: <files> placeholder example

examples/bash.yaml demonstrates both check-cmd and fix-cmd using <files> with realistic shellcheck/shfmt invocations. The inline comment noting shellcheck has no fix mode is accurate.


Fixed: Typo-tolerance note

README.md L116–118 — the check_cmd misspelling example and the --no-additional-properties escape hatch are now documented. Clear and actionable.


Still open (Medium): Array merge semantics for overlay resolution

README.md L54–55:

Resolution per ecosystem, additive per key: … A later layer overrides earlier layers key-by-key…

"Additive per key" and "overrides key-by-key" still say different things for array-typed fields (globs, gates[], project-discovery). The MIGRATION-PLAYBOOK seam 2 entry (line 141) says "additive-preferred: a later layer adds to or refines earlier layers rather than silently replacing them", which implies append — but the README doesn't surface this for arrays.

A plugin author implementing the resolver could reasonably read "key-by-key override" as a full replacement of the array. A single clarifying sentence would close the gap, e.g.:

For scalar fields a later layer replaces the value; for array fields (globs, gates, project-discovery) a later layer appends its items — to replace an array entirely, restate it in full in the override layer.

Fix this →


Observations (no action required)

  • bash.yaml install-hint uses | to separate Windows/macOS commands — consistent with python.yaml's established style in the same directory.
  • MIGRATION-PLAYBOOK seam 2 concern-named folder rule (lines 132–139) cross-references correctly; the docs/conventions/hook-telemetry/ template directory exists.
  • All four examples (bash, dotnet, python) are valid against the schema; null in python.yaml's build-cmd and bash.yaml's build-cmd/test-cmd correctly exercises the nullable type.
  • No security surface introduced — pure documentation with no code execution, no external calls, no secrets.

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale comment

Risk: low. Not approving: Cursor Bugbot completed with a skip (usage limit reached) and did not produce a clean automated review. Human review is needed before merge; no reviewers were assigned because no suitable reviewers were identified outside the PR author.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@cursor

cursor Bot commented Jul 12, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_85aefcb7-42cf-4054-96e3-6bde96521af3)

@claude

claude Bot commented Jul 12, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 1m 49s —— View job


PR Review

  • Gather context
  • Read changed files (HEAD a70f764 — merge from main, no new content changes)
  • Review for correctness, CLAUDE.md alignment, and open findings
  • Post findings

The latest push is a merge-from-main commit (a70f764) with no modifications to the ecosystem-commands files themselves. Three of the four findings from prior review rounds have been addressed; one medium finding remains open.


Still open (Medium): Array merge semantics for overlay resolution

README.md L54–55:

Resolution per ecosystem, additive per key: … A later layer overrides earlier layers key-by-key and never replaces the base file wholesale…

"Additive per key" and "overrides key-by-key" remain in tension for array-typed fields (globs, gates[], project-discovery). If a local overlay specifies globs: ["*.pyi"] over a team file with globs: ["*.py"], a resolver reading "key-by-key" could reasonably produce ["*.pyi"] (replace) while one reading "additive" produces ["*.py", "*.pyi"] (append). Two plugin authors will implement this differently without a clarifying sentence.

MIGRATION-PLAYBOOK.md line 141 says "additive-preferred: a later layer adds to or refines earlier layers rather than silently replacing them" — but that prose lives in the playbook, not here, and doesn't surface for someone reading only the convention README. One sentence resolves the ambiguity:

For scalar fields, a later layer's value replaces the earlier one; for array fields (globs, gates, project-discovery), a later layer's items are appended — to replace an array entirely, restate it in full in the override layer.

Fix this →


Confirmed fixed (from prior rounds)

  • $id raw URL — ecosystem.schema.json L3 correctly uses raw.githubusercontent.com. Matches sibling hook-telemetry schemas.
  • <files> placeholder example — bash.yaml demonstrates <files> in both check-cmd and fix-cmd with realistic shellcheck/shfmt invocations. The comment noting shellcheck has no fix mode is accurate.
  • Typo-tolerance note — README.md L116–118 documents the check_cmd misspelling pitfall and the --no-additional-properties escape hatch. Clear and actionable.

Observations (no action required)

  • All three example fixtures (bash, dotnet, python) are valid against the schema; null in build-cmd/test-cmd correctly exercises the nullable type.
  • The dotnet.yaml gates[] array is a good test of the one data type the resolution ambiguity most affects — a consumer adding a local overlay gate benefits from the clarifying sentence above.
  • CHANGELOG 1.0.0 entry is accurate and complete against the schema keys.
  • Concern-named folder addition to MIGRATION-PLAYBOOK.md seam 2 integrates cleanly; the cross-reference to docs/conventions/hook-telemetry/ as template is valid.
  • No security surface introduced — documentation only, no code execution, no external calls, no secrets.

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale comment

Risk: low. Not approving because Cursor Bugbot completed with skip status and did not provide a clean automated review signal. Human review is needed before merge; no reviewers were assigned because no suitable reviewers outside the PR author were identified.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@cursor

cursor Bot commented Jul 12, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_a733a01c-3c4f-404f-a7c9-ba7a5fe8cd03)

@claude

claude Bot commented Jul 12, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 2m 7s —— View job


PR Review

  • Gather context
  • Read changed files
  • Review for correctness, security, and CLAUDE.md alignment
  • Post findings

This is the fourth review cycle. The HEAD (db9eb2d) is a merge-from-main commit with no modifications to any ecosystem-commands files. Three of four prior findings are confirmed fixed; one medium finding remains open.


Still open (Medium): Array merge semantics unspecified for overlay resolution

README.md L54–55:

Resolution per ecosystem, additive per key: … A later layer overrides earlier layers key-by-key and never replaces the base file wholesale…

"Additive per key" and "overrides key-by-key" still describe incompatible behaviors for array-typed fields (globs, gates, project-discovery). Two plugin authors independently implementing the resolver can reach opposite semantics without a single clarifying sentence. MIGRATION-PLAYBOOK.md line 141 says "additive-preferred: a later layer adds to or refines earlier layers" — but that line lives in the playbook, not in the convention README. Someone reading only the README (the more likely path for a plugin author) gets no resolution.

Proposed fix — one sentence after line 55:

For scalar fields, a later layer's value replaces the earlier one; for array fields (globs, gates, project-discovery), a later layer's items are appended — to replace an array entirely, restate it in full in the override layer.

Fix this →


Confirmed fixed (from prior rounds)

  • $id raw URL — ecosystem.schema.json L3 correctly uses raw.githubusercontent.com. Matches sibling hook-telemetry schemas.
  • <files> placeholder example — bash.yaml demonstrates <files> in both check-cmd and fix-cmd with realistic shellcheck/shfmt invocations. The comment noting shellcheck has no fix mode is accurate.
  • Typo-tolerance note — README.md L116–118 documents the check_cmd misspelling pitfall and the --no-additional-properties escape hatch. Clear and actionable.

Observations (no action required)

  • All three example fixtures (bash, dotnet, python) are valid against the schema. null in build-cmd / test-cmd exercises the nullable type correctly.
  • dotnet.yaml gates[] array is the field most likely to be extended via a local overlay — it's also the field most affected by the unresolved semantics above.
  • The relative link in MIGRATION-PLAYBOOK.md L136 — (conventions/ecosystem-commands/README.md) — resolves correctly from docs/ root in GitHub's renderer.
  • CHANGELOG 1.0.0 entry is accurate and complete against all schema keys.
  • Concern-named folder addition to seam 2 integrates cleanly; the docs/conventions/hook-telemetry/ template cross-reference is valid.
  • No security surface — documentation only, no code execution, no external calls, no secrets.

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale comment

Risk: low. Not approving because Cursor Bugbot completed with skip status and did not provide a clean automated review signal. Human review is needed before merge; no reviewers were assigned because no suitable reviewers were identified outside the PR author.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@kyle-sexton
kyle-sexton merged commit 1ad5f31 into main Jul 12, 2026
22 checks passed
@kyle-sexton
kyle-sexton deleted the chore/amend-ecosystem-commands branch July 12, 2026 07:13

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Risk: low. Not approving because Cursor Bugbot completed with skip status (usage limit reached) and did not provide a clean automated review signal. Human review is needed before merge; no reviewers were assigned because no appropriate reviewers were found outside the PR author.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

kyle-sexton added a commit that referenced this pull request Sep 23, 2026
…#4364)

## Summary

`/gaming:dlss5 assess` only refused on anti-cheat, so a game the mod
cannot change (a 2D title such as Stardew Valley) still came back
`eligible`. This adds a `not-a-candidate` verdict for a game tree with
no DLSS, FSR 2+ or XeSS DLL, and `apply` refuses it before any write.
There is no override flag.

## Fix

- `Invoke-Dlss5Mod.ps1`: one `Find-Upscalers` finder, used by `assess`
and by `apply`'s pre-write refusal gates. It matches exact names from
upstream OptiScaler's `OptiScaler/DllNames.h` (commit `3bae321`,
2026-06-11):
  - DLSS: `nvngx_dlss.dll`.
- FSR: `ffx_fsr2_api_x64.dll`, `ffx_fsr2_api_dx12_x64.dll`,
`ffx_fsr3upscaler_x64.dll`, `amd_fidelityfx_dx12.dll`,
`amd_fidelityfx_loader_dx12.dll`, `amd_fidelityfx_upscaler_dx12.dll`,
`amd_fidelityfx_vk.dll`.
  - XeSS: `libxess.dll`, `libxess_dx11.dll`.
- Frame generation, ray reconstruction and `nvngx_dlssnr.dll` do not
count. The old `nvngx_dlss*.dll` glob matched the NR runtime itself.
- The scan root is the Steam `common` folder. For a non-Steam Unreal
game it is the install root above `<Project>\Binaries\Win64`, where
`Engine\Plugins` holds the upscaler plugins.
- The `assess` JSON field `dlss` is replaced by `upscalers` (`family`,
`file`, `version`).
- Verdict order: `refused`, then `unknown` (no exe), then
`not-a-candidate`, then `unknown` (no free proxy), then `eligible`.
- The 32-bit check is left out on purpose. Only wilsjo2's README states
a 64-bit requirement, so it appears as a labeled single-source note and
never as a refusal.
- `SKILL.md`: the router explains the verdict in plain words, using
Stardew Valley as the example. `not-a-candidate` is added to the apply
stop list and the refusal list. The static-link gap is listed under
Gotchas.
- New `reference/candidate-selection.md` covers:
  - requirements
  - detected names and the known gaps
  - non-candidates and the user-driven upscaler-mod path
- engine notes: verifier-confirmed items, plus labeled single-source or
conditional items
- trusted and untrusted config sources: guide issues authored by
FlashAust are untrusted, and #85 records a failed attempt to bypass the
NGX registry signature check
  - why the Cyberpunk proxy stays `dxgi.dll` rather than `dbghelp.dll`
- `tuning-guide.md`: a row for NR that looks inert. It says to try the
other White point source and cites both conflicting reports (wilsjo2 #34
and #96).
- `upstream-watch.md` and `fork-comparison.md`:
  - wilsjo2's newest prerelease is `v0.8.91`.
  - Releases from `v0.8.5` ship `SHA256SUMS.txt`.
  - #56 is open with no maintainer reply.
  - The pins are unchanged.
- No safety gate was weakened: the anti-cheat refusal, per-game
confirmation, the no-overwrite rule, `setup_windows.bat` never running,
`AutoCapture=false`, and the provider-neutral runtime source are all
unchanged. Version 0.1.1 -> 0.2.0.

## Verification

- `Invoke-Dlss5Mod.test.sh`: `SELFTEST OK`. New assertions:
- A fixture holding only non-upscaler DLLs (`nvngx_dlssnr`,
`nvngx_dlssg`, `nvngx_dlssd`, `libxess_fg`,
`amd_fidelityfx_framegeneration_dx12`) gets `not-a-candidate`, and
`apply` refuses it with the tree byte-identical and no state dir.
  - FSR-only and XeSS-only fixtures are `eligible`.
  - A non-Steam Unreal fixture finds DLSS under `Engine\Plugins`.
- `scripts/check-changed-skills.sh origin/main`: dlss5 PASS, 0 errors, 0
warnings.
- The following all pass or report clean on the changed files:
markdownlint-cli2, typos, `check-changelog-parity.sh --check-bump` and
`--check-preserved`, `check-shell-portability.sh`, and an em-dash grep.

## Related

Closes #4361

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant