Skip to content

[dotnet-ai] Plugin scaffold + MEAI chat integration#237

Open
luisquintanilla wants to merge 4 commits into
dotnet:mainfrom
luisquintanilla:dotnet-ai/scaffold
Open

[dotnet-ai] Plugin scaffold + MEAI chat integration#237
luisquintanilla wants to merge 4 commits into
dotnet:mainfrom
luisquintanilla:dotnet-ai/scaffold

Conversation

@luisquintanilla

@luisquintanilla luisquintanilla commented Mar 5, 2026

Copy link
Copy Markdown
Contributor

Fixes #226
Fixes #227
Part of #225

Dependencies

Merge order: This is the first PR in the dotnet-ai plugin series. It must merge before all other dotnet-ai PRs.

Summary

Adds the dotnet-ai plugin scaffold and the first skill (meai-chat-integration) bundled together a blank plugin definition should not merge without content.

Plugin scaffold

Creates the plugin directory structure, manifest, ownership, and marketplace registration.

meai-chat-integration skill

The foundation layer that most other dotnet-ai skills build upon. Guides developers through integrating LLM chat capabilities using Microsoft.Extensions.AI and the IChatClient abstraction.

Includes references/tokenizers.md a comprehensive reference for Microsoft.ML.Tokenizers covering all 8 tokenizer types (Tiktoken, BPE, SentencePiece, Llama, BERT, WordPiece, CodeGen, Phi2).

Changes

File Description
plugins/dotnet-ai/plugin.json Plugin manifest: name, version, description, skills and agents directory references
plugins/dotnet-ai/agents/.gitkeep Placeholder for future agent definitions
plugins/dotnet-ai/skills/meai-chat-integration/SKILL.md IChatClient setup, ChatClientBuilder middleware pipeline, streaming, structured output, retry/resilience, model pinning, token counting, output validation
plugins/dotnet-ai/skills/meai-chat-integration/references/tokenizers.md Microsoft.ML.Tokenizers API reference token counting, truncation, encoding/decoding, cross-skill usage table
tests/dotnet-ai/meai-chat-integration/eval.yaml Eval: ASP.NET Core chat endpoint scenario
.github/CODEOWNERS Adds @luisquintanilla and @JeremyLikness as owners for plugins/dotnet-ai/ and tests/dotnet-ai/
.github/plugin/marketplace.json Registers dotnet-ai alongside existing dotnet and dotnet-msbuild plugins

Key Packages

  • Microsoft.Extensions.AI (core)
  • Microsoft.ML.Tokenizers (token counting and context window management)
  • Provider: OpenAI, Azure.AI.OpenAI, or OllamaSharp

Validation

  • plugin.json follows the same structure as existing plugins
  • CODEOWNERS has 2 FTE GitHub aliases per CONTRIBUTING.md requirements
  • marketplace.json is valid JSON with the new plugin entry
  • SKILL.md has valid YAML frontmatter (name, description)
  • Covers IChatClient setup, streaming, structured output, middleware, resilience
  • references/tokenizers.md covers all 8 tokenizer types and core operations
  • eval.yaml has at least one scenario

Adds the plugin directory structure, plugin.json manifest, CODEOWNERS
entries, and marketplace.json registration for the new dotnet-ai plugin.

Fixes dotnet#226
Part of dotnet#225

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI 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.

Pull request overview

Adds the initial scaffold for a new dotnet-ai plugin so future PRs can land skills/evals under a consistent plugin boundary (plugins/dotnet-ai/) with ownership and marketplace registration.

Changes:

  • Introduces plugins/dotnet-ai/plugin.json and an agents/ placeholder.
  • Adds CODEOWNERS entries for plugins/dotnet-ai/ and tests/dotnet-ai/.
  • Registers the new plugin in .github/plugin/marketplace.json.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 3 comments.

File Description
plugins/dotnet-ai/plugin.json Adds the plugin manifest for the new dotnet-ai plugin.
plugins/dotnet-ai/agents/.gitkeep Creates the agents/ directory placeholder for future agent definitions.
.github/CODEOWNERS Assigns code ownership for the new plugin and its test area.
.github/plugin/marketplace.json Registers dotnet-ai in the GitHub plugin marketplace registry.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

"name": "dotnet-ai",
"version": "0.1.0",
"description": "AI and ML skills for .NET: technology selection, LLM integration, ML.NET, vector search, RAG, ONNX inference, and agentic workflows.",
"skills": "./skills/",

Copilot AI Mar 5, 2026

Copy link

Choose a reason for hiding this comment

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

plugin.json declares a "skills": "./skills/" directory, but plugins/dotnet-ai/skills/ is not present in this PR. This makes the plugin scaffold incomplete and forces later PRs to introduce the directory structure that this PR is supposed to establish. Add plugins/dotnet-ai/skills/ (e.g., with a .gitkeep) in this PR so the manifest references an existing path.

Suggested change
"skills": "./skills/",
"skills": "./",

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Concern accepted, code suggestion rejected.

The concern is valid the skills/ directory should exist in the scaffold PR. Added plugins/dotnet-ai/skills/.gitkeep in 6e13c50.

However, the code suggestion to change "skills": "./skills/" to "skills": "./" is incorrect. Both existing plugins (dotnet and dotnet-msbuild) use "skills": "./skills/" changing to "./" would break the convention and make the plugin look for skills in the root directory instead of the skills/ subdirectory.

Comment thread .github/CODEOWNERS Outdated
Comment on lines +54 to +55
/plugins/dotnet-ai/ @luisquintanilla @JeremyLikness
/tests/dotnet-ai/ @luisquintanilla @JeremyLikness No newline at end of file

Copilot AI Mar 5, 2026

Copy link

Choose a reason for hiding this comment

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

These CODEOWNERS entries add ownership for /tests/dotnet-ai/, but the tests/dotnet-ai/ directory does not exist in the repo after this change. Since evaluation workflows key off the presence of tests/<plugin>/, the scaffold PR should create tests/dotnet-ai/ (e.g., with a .gitkeep) so later skill PRs will be evaluated as expected.

Suggested change
/plugins/dotnet-ai/ @luisquintanilla @JeremyLikness
/tests/dotnet-ai/ @luisquintanilla @JeremyLikness
/plugins/dotnet-ai/ @luisquintanilla @JeremyLikness

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Concern accepted, code suggestion rejected.

The concern is valid tests/dotnet-ai/ should exist in the scaffold PR. Added tests/dotnet-ai/.gitkeep in 6e13c50.

However, the code suggestion to remove the /tests/dotnet-ai/ CODEOWNERS entry is wrong we need ownership coverage for the test directory so that when eval files land in subsequent PRs, they require review from the plugin owners. Removing the entry would leave test files unprotected.

Comment thread .github/plugin/marketplace.json Outdated
Comment on lines +18 to +19
"source": "./plugins/dotnet-ai",
"name": "dotnet-ai",

Copilot AI Mar 5, 2026

Copy link

Choose a reason for hiding this comment

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

In this file, the existing plugin entries use the key order name, source, description, but the new dotnet-ai entry uses source before name. JSON object key order is semantically irrelevant, but keeping a consistent ordering across entries makes diffs and manual maintenance easier; consider matching the existing order here.

Suggested change
"source": "./plugins/dotnet-ai",
"name": "dotnet-ai",
"name": "dotnet-ai",
"source": "./plugins/dotnet-ai",

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Accepted. Good catch fixed the key ordering to match existing entries (name, source, description) in 6e13c50.

- Add plugins/dotnet-ai/skills/.gitkeep so the manifest path exists
- Add tests/dotnet-ai/.gitkeep so CODEOWNERS entry has a target
- Fix marketplace.json key ordering to match existing entries (name, source, description)
- Fix missing trailing newline in CODEOWNERS

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI 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.

Pull request overview

Copilot reviewed 3 out of 6 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

@timheuer

timheuer commented Mar 5, 2026

Copy link
Copy Markdown
Member

Understood on the plugin definition -- but I don't think we should merge without content...blank plugin definition doesn't make sense -- so I would bundle this with at least the first skill rather than ensure we don't just have a stub, even if for a minute ;-)

@luisquintanilla

Copy link
Copy Markdown
Contributor Author

Understood on the plugin definition -- but I don't think we should merge without content...blank plugin definition doesn't make sense -- so I would bundle this with at least the first skill rather than ensure we don't just have a stub, even if for a minute ;-)

Sounds good. I'll bring that skill in and close that PR.

Bundles the first skill (meai-chat-integration) with the plugin scaffold
per reviewer feedback  a blank plugin definition should not merge without
content.

Adds:
- skills/meai-chat-integration/SKILL.md  IChatClient setup, middleware,
  streaming, structured output, resilience, token counting
- skills/meai-chat-integration/references/tokenizers.md  full
  Microsoft.ML.Tokenizers API reference (8 tokenizer types)
- tests/dotnet-ai/meai-chat-integration/eval.yaml

Removes .gitkeep stubs (real files now exist in both directories).

Fixes dotnet#227
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@luisquintanilla luisquintanilla requested a review from a team March 6, 2026 16:25
@luisquintanilla luisquintanilla changed the title [dotnet-ai] Plugin scaffold [dotnet-ai] Plugin scaffold + MEAI chat integration Mar 6, 2026
.NET 10 is the current LTS (released Nov 2025). .NET 8 reaches
end-of-support Nov 2026.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Apr 6, 2026

Copy link
Copy Markdown
Contributor

This PR has been automatically marked as stale because it has no activity for 30 days. It will be closed if no further activity occurs within another 7 days of this comment. If it is closed, you may reopen it anytime when you're ready again.

Generated by Close Stale Pull Requests ·

@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

✅ Automated diff scan completed for 2cdadc7 — no security concerns flagged.

This is an automated static analysis of the PR diff.

Note

🔒 Integrity filter blocked 14 items

The following items were blocked because they don't meet the GitHub integrity level.

  • #237 pull_request_read: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #237 search_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #240 search_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #245 search_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #242 search_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #244 search_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #246 search_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #243 search_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #241 search_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #239 search_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #613 search_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • 2cdadc7 list_commits: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • [dotnet-ai] Plugin scaffold + MEAI chat integration #237 pull_request_read: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • 2cdadc7 get_commit: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".

To allow these resources, lower min-integrity in your GitHub frontmatter:

tools:
  github:
    min-integrity: approved  # merged | approved | unapproved | none

Generated by PR Malicious Code Scan · ● 397.2K ·

@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

✅ Automated diff scan completed for 2cdadc7 — no security concerns flagged.

This is an automated static analysis of the PR diff.

Note

🔒 Integrity filter blocked 77 items

The following items were blocked because they don't meet the GitHub integrity level.

  • #237 pull_request_read: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #694 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #686 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #682 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #609 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #607 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #601 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #598 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #502 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #486 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #376 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #329 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #303 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #269 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #267 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #266 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • ... and 61 more items

To allow these resources, lower min-integrity in your GitHub frontmatter:

tools:
  github:
    min-integrity: approved  # merged | approved | unapproved | none

Generated by PR Malicious Code Scan · ● 799.8K ·

@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

✅ Automated diff scan completed for 2cdadc7 — no security concerns flagged.

This is an automated static analysis of the PR diff.

Note

🔒 Integrity filter blocked 7 items

The following items were blocked because they don't meet the GitHub integrity level.

  • #237 pull_request_read: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • [dotnet-ai] Plugin scaffold + MEAI chat integration #237 pull_request_read: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • 2cdadc7 list_commits: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • 8557701 list_commits: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • 6e13c50 list_commits: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • 821cce5 list_commits: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • 54e6fe8 list_commits: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".

To allow these resources, lower min-integrity in your GitHub frontmatter:

tools:
  github:
    min-integrity: approved  # merged | approved | unapproved | none

Generated by PR Malicious Code Scan · ● 251K ·

@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

✅ Automated diff scan completed for 2cdadc7 — no security concerns flagged.

This is an automated static analysis of the PR diff.

Note

🔒 Integrity filter blocked 51 items

The following items were blocked because they don't meet the GitHub integrity level.

  • #237 pull_request_read: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #694 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #686 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #682 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #609 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #607 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #601 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #598 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #502 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #486 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #376 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #329 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #303 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #269 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #267 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • #266 list_pull_requests: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".
  • ... and 35 more items

To allow these resources, lower min-integrity in your GitHub frontmatter:

tools:
  github:
    min-integrity: approved  # merged | approved | unapproved | none

Generated by PR Malicious Code Scan · ● 859.4K ·

JanKrivanek added a commit that referenced this pull request Jun 4, 2026
* Fix malicious-scan repeat-spam + integrity-filter blocks

Root causes (observed on PR #237):
1. Agent's emitted add_comment body did not include the HTML marker line
   (<!-- pr-malicious-scan:fingerprint=... -->), so both the orchestrator's
   pre-dispatch check and the agent's own Step 1 idempotency lookup failed
   to find a prior scan for the same head SHA. Result: hourly re-dispatch.
2. The github MCP tools (pull_request_read, list_pull_requests,
   search_pull_requests) are blocked by the gh-aw integrity filter on PRs
   from non-approved authors -- exactly the population this scanner targets.
   Result: 'Integrity filter blocked N items' notes in every comment.

Fixes:
- pr-malicious-scan.agent.md: drop the github MCP toolset, add 'gh' to the
  bash allowlist, and instruct the agent to use 'gh api' for all PR data
  reads (PAT-authenticated, not subject to the integrity filter).
- Strengthen Step 5: the HTML marker MUST be the first line of the comment
  body. Add a defense-in-depth note that the orchestrator also accepts the
  visible-body sentinel.
- pr-triage-batch.yml + pr-triage-act.sh: match prior scans by EITHER the
  HTML marker OR the visible-body sentinel ('Automated diff scan' + backticked
  sha7), so a missing marker on a previously-emitted comment no longer
  triggers re-dispatch.

Workflow disabled remotely while this lands.

* Orchestrator-only dispatch + integrity-filter opt-out

Replace the per-push pull_request_target trigger and the gh-api workaround
with the documented gh-aw pattern:

- pr-malicious-scan.agent.md: drop pull_request_target; trigger only via
  workflow_dispatch from the orchestrator. Restore the github MCP toolset
  with min-integrity: none (the documented level for spam-detection /
  analytics workflows; safe-outputs still gates every mutation). Drop the
  'gh' bash hack and visible-body sentinel requirements.

- pr-triage-batch.yml: orchestrator now posts a deterministic
  '<!-- pr-malicious-scan:dispatched=SHORT --> ' comment BEFORE calling
  gh workflow run. That comment is the source of truth for 'a scan has
  been initiated for this head SHA' and survives every agent-side failure
  mode (PAT outage, integrity block, dropped HTML marker). Dedup matches
  either that orchestrator marker OR the agent's own fingerprint marker.

- pr-triage-act.sh: drop the visible-body-sentinel fallback; match the
  orchestrator dispatched marker plus the agent fingerprint marker.

Validated: gh aw compile clean; bash -n clean for both worker script and
orchestrator embedded script; markdownlint clean; dedup query and POST
api tested live against PR #713.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[dotnet-ai] MEAI chat integration [dotnet-ai] Plugin scaffold

4 participants