feat: code-review-tea — Gitea/tea fork of Anthropic's code-review plugin #10
@@ -44,14 +44,16 @@ These were confirmed by probing the live `tea` 0.14.1 binary during planning —
|
||||
```
|
||||
.claude/plugins/code-review-tea/
|
||||
├── .claude-plugin/
|
||||
│ ├── plugin.json # the manifest (credits Anthropic/Boris Cherny)
|
||||
│ └── commands/
|
||||
│ ├── code-review.md # the forked, tea-rewritten command
|
||||
│ └── RESOLVED_INVOCATION.md # verified tea call notes (from Task 2)
|
||||
│ └── plugin.json # the manifest (credits Anthropic/Boris Cherny) — ONLY file in .claude-plugin/
|
||||
├── commands/
|
||||
│ ├── code-review.md # the forked, tea-rewritten command (plugin root, NOT in .claude-plugin/)
|
||||
│ └── RESOLVED_INVOCATION.md # verified tea call notes (from Task 2)
|
||||
└── README.md # what this fork is, why, how it differs
|
||||
```
|
||||
|
||||
Rationale: a project-local plugin under `.claude/plugins/` is version-controlled with the repo and applies only here (this is a Gitea-only repo; a global install would mis-fire on the user's GitHub-hosted repos). The name `code-review-tea` is distinct from the upstream `code-review` so it never shadows or confuses the GitHub plugin if that ever gets enabled elsewhere.
|
||||
Rationale: per Claude Code's plugin spec, only `plugin.json` lives in `.claude-plugin/`; `commands/`, `skills/`, `agents/` live at the plugin root (verified against the upstream `code-review` and `superpowers` plugins). A project-local plugin under `.claude/plugins/` is version-controlled with the repo and applies only here. The name `code-review-tea` is distinct from the upstream `code-review` so it never shadows or confuses the GitHub plugin if that ever gets enabled elsewhere.
|
||||
|
||||
**Discovery note (verified via docs):** a plugin placed in `<repo>/.claude/plugins/<name>/` is NOT auto-discovered by Claude Code. It loads explicitly via `claude --plugin-dir .claude/plugins/code-review-tea` (per-session) or by `claude plugin init` installing into `~/.claude/skills/code-review-tea/` (auto-loads as `code-review-tea@skills-dir`). plugin commands are namespaced, so the command is invoked as **`/code-review-tea:code-review`**, not `/code-review-tea`.
|
||||
|
||||
We create **no** Python source changes and **no** test files — this is a tooling-only change. The `allowed-tools` substitution and command-file rewrite are the entire substance.
|
||||
|
||||
@@ -61,7 +63,7 @@ We create **no** Python source changes and **no** test files — this is a tooli
|
||||
|
||||
**Files:**
|
||||
- Create: `.claude/plugins/code-review-tea/.claude-plugin/plugin.json`
|
||||
- Create: `.claude/plugins/code-review-tea/.claude-plugin/commands/.gitkeep`
|
||||
- Create: `.claude/plugins/code-review-tea/commands/.gitkeep`
|
||||
|
||||
- [ ] **Step 1: Create the plugin manifest**
|
||||
|
||||
@@ -91,7 +93,7 @@ Create `.claude/plugins/code-review-tea/.claude-plugin/plugin.json`:
|
||||
|
||||
- [ ] **Step 2: Create the commands directory placeholder**
|
||||
|
||||
Create `.claude/plugins/code-review-tea/.claude-plugin/commands/.gitkeep` as an empty file so the directory is tracked by git.
|
||||
Create `.claude/plugins/code-review-tea/commands/.gitkeep` as an empty file so the directory is tracked by git.
|
||||
|
||||
- [ ] **Step 3: Verify the directory tree**
|
||||
|
||||
@@ -173,7 +175,7 @@ Make a mental/scratch note of: (a) which login-context flag worked (`--remote or
|
||||
The substantive change. Fork the upstream command, substitute the five `gh` contact points and the link format, keep the parallel-agent + confidence-score + 80-threshold logic identical, and add a header crediting the original.
|
||||
|
||||
**Files:**
|
||||
- Create: `.claude/plugins/code-review-tea/.claude-plugin/commands/code-review.md`
|
||||
- Create: `.claude/plugins/code-review-tea/commands/code-review.md`
|
||||
|
||||
- [ ] **Step 1: Read the upstream command file for reference**
|
||||
|
||||
@@ -185,7 +187,7 @@ Expected: the 93-line original. Keep it open; this is the template to fork.
|
||||
|
||||
- [ ] **Step 2: Write the command file**
|
||||
|
||||
Create `.claude/plugins/code-review-tea/.claude-plugin/commands/code-review.md`. The full content:
|
||||
Create `.claude/plugins/code-review-tea/commands/code-review.md`. The full content:
|
||||
|
||||
````markdown
|
||||
---
|
||||
@@ -305,7 +307,7 @@ No issues found. Checked for bugs and CLAUDE.md compliance.
|
||||
|
||||
Run:
|
||||
```bash
|
||||
head -6 .claude/plugins/code-review-tea/.claude-plugin/commands/code-review.md
|
||||
head -6 .claude/plugins/code-review-tea/commands/code-review.md
|
||||
```
|
||||
Expected: the `---` fence, `allowed-tools:` line containing only `Bash(tea ...:*), Bash(git ...:*)` entries (NO `gh`), then `description:` and `disable-model-invocation: false`, then closing `---`.
|
||||
|
||||
@@ -313,70 +315,75 @@ Expected: the `---` fence, `allowed-tools:` line containing only `Bash(tea ...:*
|
||||
|
||||
Run:
|
||||
```bash
|
||||
grep -nE '\bgh\b|github\.com|/blob/' .claude/plugins/code-review-tea/.claude-plugin/commands/code-review.md || echo "clean: no gh/github/blob references"
|
||||
grep -nE '\bgh\b|github\.com|/blob/' .claude/plugins/code-review-tea/commands/code-review.md || echo "clean: no gh/github/blob references"
|
||||
```
|
||||
Expected: `clean: no gh/github/blob references`. If anything matches, fix it before committing. (Note: the credit comment intentionally mentions "GitHub/gh-only" to describe the upstream — that line references `gh` as a word, so adjust the grep if it fires on the credit line; the credit line is correct and should stay. The grep is meant to catch *operational* `gh` calls, which would look like `gh pr` or `gh issue`.)
|
||||
|
||||
A more precise check:
|
||||
```bash
|
||||
grep -nE 'gh pr|gh issue|gh search|gh api|github\.com/alee/vigilar/blob|/blob/<' .claude/plugins/code-review-tea/.claude-plugin/commands/code-review.md || echo "clean: no operational gh calls or blob links"
|
||||
grep -nE 'gh pr|gh issue|gh search|gh api|github\.com/alee/vigilar/blob|/blob/<' .claude/plugins/code-review-tea/commands/code-review.md || echo "clean: no operational gh calls or blob links"
|
||||
```
|
||||
Expected: `clean: no operational gh calls or blob links`.
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add .claude/plugins/code-review-tea/.claude-plugin/commands/code-review.md
|
||||
git add .claude/plugins/code-review-tea/commands/code-review.md
|
||||
git commit -m "feat(plugin): gitea/tea port of code-review command"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Task 4: Enable the plugin in this project's settings
|
||||
## Task 4: Load and verify the plugin
|
||||
|
||||
**Files:**
|
||||
- Modify: `.claude/settings.json`
|
||||
- No file changes in this task (the plugin files from Tasks 1 & 3 are already in place; `.claude/settings.json` is NOT modified — repo-local `.claude/plugins/<name>/` dirs are not auto-discovered, so an `enabledPlugins` entry would not load it). This task is about confirming the plugin loads and its command resolves.
|
||||
|
||||
- [ ] **Step 1: Read the current settings**
|
||||
**Discovery model (verified via docs at https://code.claude.com/docs/en/plugins):** a plugin placed at `<repo>/.claude/plugins/<name>/` is NOT auto-discovered by Claude Code. Two ways to load it:
|
||||
- **`--plugin-dir`** (per-session, recommended for this fork): launch Claude Code as `claude --plugin-dir .claude/plugins/code-review-tea`. The plugin loads for that session; its command is `/code-review-tea:code-review`.
|
||||
- **`claude plugin init`** (persistent, user-scope): installs into `~/.claude/skills/code-review-tea/`, auto-loads on subsequent sessions as `code-review-tea@skills-dir` (no marketplace needed). This makes it available across all your projects, not just Vigilar — pick this only if you want that.
|
||||
|
||||
plugin commands are namespaced, so the invocation is `/code-review-tea:code-review` (plugin name `:` command file name), NOT `/code-review-tea`.
|
||||
|
||||
- [ ] **Step 1: Validate the plugin structure with the official validator**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
cat .claude/settings.json
|
||||
```
|
||||
Expected:
|
||||
```json
|
||||
{
|
||||
"enabledPlugins": {
|
||||
"superpowers@claude-plugins-official": true
|
||||
}
|
||||
}
|
||||
claude plugin validate .claude/plugins/code-review-tea 2>&1
|
||||
```
|
||||
Expected: a success/valid report. If it reports a structural error (e.g. "commands/ must be at plugin root, not in .claude-plugin/"), fix the layout before proceeding. This catches exactly the nesting mistake that was corrected earlier (commands/ now at plugin root). If `claude plugin validate` is unavailable in your version, skip to Step 2 (the layout was already verified against the upstream `code-review` plugin in planning).
|
||||
|
||||
- [ ] **Step 2: Add the new plugin to enabledPlugins**
|
||||
|
||||
Change `.claude/settings.json` to:
|
||||
|
||||
```json
|
||||
{
|
||||
"enabledPlugins": {
|
||||
"superpowers@claude-plugins-official": true,
|
||||
"code-review-tea@vigilar": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `@vigilar` suffix denotes a project-local (non-marketplace) plugin discovered from `.claude/plugins/code-review-tea/`. If Claude Code resolves local plugins by bare directory name (no `@source` suffix), drop it to `"code-review-tea": true`. Step 3 verifies which form is accepted.
|
||||
|
||||
- [ ] **Step 3: Verify the plugin is discoverable**
|
||||
|
||||
Restart/reload Claude Code for this project and run `/code-review-tea`. If the command is not found, Claude Code's local-plugin resolution may need the bare plugin name — change settings to `"code-review-tea": true` and re-verify. If still not found, confirm the plugin is discovered at all by checking whether `/code-review-tea` appears in the command list (if not, the loader may not scan `.claude/plugins/` — in that case, the plugin can still be invoked by directly reading the command file; document this fallback in the README).
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
- [ ] **Step 2: Load the plugin for a session and confirm the command is registered**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
git add .claude/settings.json
|
||||
git commit -m "chore(plugin): enable project-local code-review-tea plugin"
|
||||
claude --plugin-dir .claude/plugins/code-review-tea
|
||||
```
|
||||
Then, inside that Claude Code session, run `/help` (or check the command list) and confirm `/code-review-tea:code-review` appears. Do NOT attempt to run the full review here — the smoke test (Task 6) does the end-to-end run. This step only confirms the command is registered and discoverable.
|
||||
|
||||
If `/code-review-tea:code-review` does NOT appear: run `claude --plugin-dir .claude/plugins/code-review-tea --debug` (or whatever the version's verbose flag is) and read the plugin-load errors. Most likely cause at this point would be malformed `plugin.json` or `commands/code-review.md` frontmatter — re-validate in Step 1.
|
||||
|
||||
- [ ] **Step 3: (Optional) Make it persistent via claude plugin init**
|
||||
|
||||
If you want the plugin available in every session (not just when you remember `--plugin-dir`), install it to your skills directory:
|
||||
```bash
|
||||
claude plugin init code-review-tea
|
||||
```
|
||||
This creates `~/.claude/skills/code-review-tea/` and loads it as `code-review-tea@skills-dir` on subsequent sessions. Only do this if you want Vigilar's review command available outside this repo too; otherwise rely on `--plugin-dir` and skip this step.
|
||||
|
||||
- [ ] **Step 4: Commit the corrected layout (if not already committed)**
|
||||
|
||||
The Tasks 1 & 3 commits placed `commands/` in the wrong nested location; the restructure moved it to plugin root via `git mv`. Commit that move if it's still staged:
|
||||
```bash
|
||||
git status --short
|
||||
git add .claude/plugins/code-review-tea
|
||||
git commit -m "fix(plugin): move commands/ to plugin root (correct structure)"
|
||||
```
|
||||
Append the coauthor trailer (after a blank line):
|
||||
```
|
||||
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||||
```
|
||||
If `git status` shows nothing to commit (already committed), skip.
|
||||
|
||||
---
|
||||
|
||||
@@ -384,31 +391,40 @@ git commit -m "chore(plugin): enable project-local code-review-tea plugin"
|
||||
|
||||
**Files:**
|
||||
- Create: `.claude/plugins/code-review-tea/README.md`
|
||||
- Create: `.claude/plugins/code-review-tea/.claude-plugin/commands/RESOLVED_INVOCATION.md`
|
||||
- Create: `.claude/plugins/code-review-tea/commands/RESOLVED_INVOCATION.md`
|
||||
- Modify: `CLAUDE.md` — append a short "## Code Review" subsection
|
||||
|
||||
- [ ] **Step 1: Write the verified invocation notes**
|
||||
|
||||
Create `.claude/plugins/code-review-tea/.claude-plugin/commands/RESOLVED_INVOCATION.md`. Fill in with the variants verified in Task 2 (replace `<verified>` placeholders with the actually-confirmed values):
|
||||
Create `.claude/plugins/code-review-tea/commands/RESOLVED_INVOCATION.md`. Fill in with the variants verified in Task 2 (replace `<verified>` placeholders with the actually-confirmed values):
|
||||
|
||||
```markdown
|
||||
# Resolved tea post-back invocation (verified via Task 2 smoke run)
|
||||
|
||||
Gitea comment posting that survives large multi-line Markdown bodies:
|
||||
|
||||
tea api --remote origin "{owner}/{repo}/issues/<PR_INDEX>/comments" -f body=@- # body via stdin <verify: confirmed/rejected>
|
||||
# fallback: -f body=@/tmp/review-tea-body.md # body via file <verify: confirmed/rejected>
|
||||
tea api --remote origin "/repos/{owner}/{repo}/issues/<PR_INDEX>/comments" -F body=@- # body via stdin [VERIFIED]
|
||||
# fallback: -F body=@/tmp/review-tea-body.md # body via file [VERIFIED]
|
||||
|
||||
Code link format (verify it renders in Gitea web):
|
||||
https://git.adlee.work/alee/vigilar/src/commit/<FULL-SHA>/<path>#L<start>-L<end> # path segment confirms src/commit <verify>
|
||||
CRITICAL: use `-F` (typed field), NOT `-f`. `-f key=@file` posts the literal string `@file`;
|
||||
only `-F key=@file` / `-F key=@-` reads the file/stdin. The endpoint MUST include the `/repos/`
|
||||
prefix: `/repos/{owner}/{repo}/issues/<idx>/comments` (without /repos/ it 404s). `tea api` already
|
||||
prints JSON to stdout — do NOT pass `-o json` (that writes the body to a file named `json`).
|
||||
|
||||
Code link format (verified to render / resolve to HTTP 200 when SHA is remote-present):
|
||||
https://git.adlee.work/alee/vigilar/src/commit/<FULL-SHA>/<path>#L<start>-L<end> # path segment src/commit [VERIFIED]
|
||||
|
||||
Eligibility metadata fetch:
|
||||
tea pulls <PR_INDEX> --remote origin --fields state,draft,title,mergeable,base,head,body,diff -o json
|
||||
tea pulls <PR_INDEX> --remote origin --fields index,state,draft,title,mergeable,base,head,body -o json
|
||||
# NOTE: tea v0.14.1 returns empty `diff`/`patch` fields even when requested — do not rely on them.
|
||||
|
||||
Diff source (preferred, local):
|
||||
git diff origin/<base>...origin/<head>
|
||||
Diff source (preferred, local — the reliable source in this tea build):
|
||||
git diff origin/<base>...origin/<head> # base/head come from the PR JSON's base/head fields
|
||||
|
||||
Login context: the `alee` tea login is NOT default (tea login list shows default=false). <verify: --remote origin resolves / --login alee required>
|
||||
Already-reviewed check:
|
||||
tea pulls review-comments <PR_INDEX> --remote origin -o json # scan body for "### Code review" marker
|
||||
|
||||
Login context: the `alee` tea login is NOT default (tea login list shows default=false). [VERIFIED: --remote origin resolves context; --login alee fallback not needed]
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Write the plugin README**
|
||||
@@ -432,7 +448,7 @@ Vigilar is hosted on a self-hosted Gitea instance (`git.adlee.work`), not GitHub
|
||||
|
||||
On a branch with an open Gitea pull request against `main`:
|
||||
|
||||
/code-review-tea
|
||||
/code-review-tea:code-review
|
||||
|
||||
Claude will:
|
||||
- Verify the PR is reviewable (skip closed/draft/trivial/already-reviewed)
|
||||
@@ -449,18 +465,28 @@ Claude will:
|
||||
- The `alee` login need NOT be the default — the command passes `--remote origin` to resolve context
|
||||
- An open Gitea pull request to review
|
||||
|
||||
## Load (this plugin is NOT auto-discovered)
|
||||
|
||||
A plugin placed in `<repo>/.claude/plugins/<name>/` is not auto-discovered by Claude Code. Load it explicitly:
|
||||
|
||||
# per-session (recommended):
|
||||
claude --plugin-dir .claude/plugins/code-review-tea
|
||||
|
||||
# persistent, user-scope (across all your projects):
|
||||
claude plugin init code-review-tea # installs to ~/.claude/skills/code-review-tea/
|
||||
|
||||
## Differences from upstream
|
||||
|
||||
| Area | Upstream (GitHub) | This fork (Gitea) |
|
||||
|---|---|---|
|
||||
| CLI | `gh` | `tea` |
|
||||
| PR metadata | `gh pr view` | `tea pulls <idx> --fields ... -o json` |
|
||||
| Diff | `gh pr diff` | `git diff origin/<base>...origin/<head>` (local) |
|
||||
| Comment post | `gh pr comment --body` | `tea api {owner}/{repo}/issues/<idx>/comments -f body=@-` |
|
||||
| Code link | `github.com/o/r/blob/SHA/path#L` | `git.adlee.work/alee/vigilar/src/commit/SHA/path#L` |
|
||||
| Diff | `gh pr diff` | `git diff origin/<base>...origin/<head>` (local; `tea pulls --fields diff` returns empty in 0.14.1) |
|
||||
| Comment post | `gh pr comment --body` | `tea api /repos/{owner}/{repo}/issues/<idx>/comments -F body=@-` (`-F` typed field reads stdin; `/repos/` prefix required) |
|
||||
| Code link | `github.com/o/r/blob/SHA/path#L` | `git.adlee.work/alee/vigilar/src/commit/SHA/path#L` (SHA must be remote-present) |
|
||||
| Inline line comments | (upstream posts one summary comment) | NOT attempted — single summary comment only (Gitea inline-comment API needs `tea api` review endpoints; out of scope) |
|
||||
|
||||
See `.claude-plugin/commands/RESOLVED_INVOCATION.md` for the verified `tea` calls.
|
||||
See `commands/RESOLVED_INVOCATION.md` for the verified `tea` calls.
|
||||
````
|
||||
|
||||
- [ ] **Step 3: Append a Code Review subsection to CLAUDE.md**
|
||||
@@ -469,13 +495,13 @@ Append to `CLAUDE.md`, as a new `## Code Review` section near the existing `## C
|
||||
|
||||
```markdown
|
||||
## Code Review
|
||||
- `/code-review-tea` — review the current Gitea PR (project-local fork of Anthropic's code-review plugin, adapted from `gh` to `tea`; credit: Boris Cherny). See `.claude/plugins/code-review-tea/README.md`.
|
||||
- `/code-review-tea:code-review` — review the current Gitea PR (project-local fork of Anthropic's code-review plugin, adapted from `gh` to `tea`; credit: Boris Cherny). Load via `claude --plugin-dir .claude/plugins/code-review-tea`. See `.claude/plugins/code-review-tea/README.md`.
|
||||
```
|
||||
|
||||
- [ ] **Step 4: Commit**
|
||||
|
||||
```bash
|
||||
git add .claude/plugins/code-review-tea/README.md .claude/plugins/code-review-tea/.claude-plugin/commands/RESOLVED_INVOCATION.md CLAUDE.md
|
||||
git add .claude/plugins/code-review-tea/README.md .claude/plugins/code-review-tea/commands/RESOLVED_INVOCATION.md CLAUDE.md
|
||||
git commit -m "docs(plugin): document code-review-tea fork and CLAUDE.md note"
|
||||
```
|
||||
|
||||
@@ -517,7 +543,7 @@ Expected: a new PR index. Record it as `$SMOKE`.
|
||||
|
||||
- [ ] **Step 3: Run the adapted command against the scratch PR**
|
||||
|
||||
Run `/code-review-tea` and provide `$SMOKE` as the PR index. Watch for each stage:
|
||||
Run `/code-review-tea:code-review` and provide `$SMOKE` as the PR index. Watch for each stage:
|
||||
- eligibility fetch via `tea pulls` ✓
|
||||
- CLAUDE.md gather ✓
|
||||
- summary ✓
|
||||
@@ -553,9 +579,9 @@ git rm vigilar/_scratch_review.py 2>/dev/null && git commit -m "chore: remove re
|
||||
|
||||
- [ ] **Step 7: Update RESOLVED_INVOCATION.md with the end-to-end confirmation**
|
||||
|
||||
Edit `.claude/plugins/code-review-tea/.claude-plugin/commands/RESOLVED_INVOCATION.md` to replace each `<verify: ...>` placeholder with the actual confirmed result from this smoke run (stdin worked vs file fallback, `--remote origin` resolved, `src/commit` rendered). Commit:
|
||||
Edit `.claude/plugins/code-review-tea/commands/RESOLVED_INVOCATION.md` to replace each `<verify: ...>` placeholder with the actual confirmed result from this smoke run (stdin worked vs file fallback, `--remote origin` resolved, `src/commit` rendered). Commit:
|
||||
```bash
|
||||
git add .claude/plugins/code-review-tea/.claude-plugin/commands/RESOLVED_INVOCATION.md
|
||||
git add .claude/plugins/code-review-tea/commands/RESOLVED_INVOCATION.md
|
||||
git commit -m "docs(plugin): confirm resolved tea invocation from smoke test"
|
||||
```
|
||||
|
||||
@@ -565,7 +591,7 @@ git commit -m "docs(plugin): confirm resolved tea invocation from smoke test"
|
||||
|
||||
1. **Spec coverage** — The user asked: make the `code-review` plugin work on Gitea (`tea`), name it `code-review-tea`, give credit to the original. → Tasks 1–6: scaffold, resolve invocation, write command, enable, document, smoke-test. Credit appears in `plugin.json` (contributors), command file header comment, and README. ✓ No hot-path review (dropped per revised scope). ✓
|
||||
2. **Placeholder scan** — Command file content is verbatim in Task 3 (full file with 4-backtick fence preserving inner 3-backtick fences). Test bodies are concrete (`is_armed` scratch bug). The only "verify which form" items (Task 4 Step 3 plugin discovery; Task 5 RESOLVED_INVOCATION `<verify>` placeholders) are real, intentional verifications — each has a concrete fallback and a step that resolves it, not an unfilled "TBD".
|
||||
3. **Name consistency** — `code-review-tea` used consistently in directory, `plugin.json` `name`, settings key, README title, CLAUDE.md note, and `/code-review-tea` invocation. No leftover `supertea` or `code-review-gitea`.
|
||||
3. **Name consistency** — `code-review-tea` used consistently in directory, `plugin.json` `name`, README title, and CLAUDE.md note. Command invoked as `/code-review-tea:code-review` (namespaced). No leftover `supertea` or `code-review-gitea`. No stale `.claude-plugin/commands/` nested paths.
|
||||
4. **Credit correctness** — Original author Boris Cherny / Anthropic credited in `plugin.json` contributors, command file header comment, and README "Credit" section. Fork relationship stated (upstream = GitHub/gh-only).
|
||||
5. **Uncertainty surfaced honestly** — `tea comment` vs `tea api` posting (Task 2 verifies, fallback documented); local-plugin `enabledPlugins` key form (Task 4 Step 3 verifies); Gitea `src/commit` path segment (Task 2/6 verifies render); `plugin.json` unknown-key tolerance (Task 1 Step 1 note + Task 6 smoke exercises loading). None silently assumed.
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user