Repository navigation
feat(mods): add experimental fellowship-gates Claude Code mod - #113
justinjdev wants to merge 1 commit into
Conversation
Shows fellowship quest status in Claude Code's status line, toasts when a gate becomes pending, and draws a band above the prompt with Approve / Reject / Later buttons for each pending gate. Approve and Reject go through the prompt so the lead still messages the teammate to resume. Lives under plugin/mods/ and is loaded explicitly with --plugin-dir; it is not wired into the fellowship plugin yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HeW5DKghWKp8v2UYCRv5xb
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. 📝 WalkthroughWalkthroughAdds an experimental Claude Code plugin that polls fellowship quest status, displays a status line and notifications for pending gates, and provides Approve, Reject, and Later controls. ChangesFellowship Gates
Priority: ⬇️ Low Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant ClaudeCode
participant register
participant FellowshipCLI as fellowship status --json
participant AbovePrompt
participant User
participant PluginState
ClaudeCode->>register: Start session or complete turn
register->>FellowshipCLI: Request quest status
FellowshipCLI-->>register: Return status output
register->>PluginState: Update quests and status line
AbovePrompt->>User: Display pending-gate actions
User->>AbovePrompt: Select Approve, Reject, or Later
AbovePrompt->>PluginState: Record dismissal when Later is selected
AbovePrompt->>ClaudeCode: Submit approval prompt or fill rejection prompt
Merge Risk: 🔵 Low · up to Overlapping polls may briefly show outdated quest or gate status. This is a bounded risk for the experimental mod, but the refresh ordering should be fixed or accepted before merging. Security Architecture ReviewSecurity architecture risk: 🟡 Moderate · up to The feature is explicitly enabled and requires a user action before requesting approval. However, an approval request uses cached quest information without binding the user's decision to the current gate instance. Existing state checks limit the risk, but stale-request handling and the permissions of quest-data writers remain unresolved. Retained concerns
Security review detailsSecurity Blast Radius
Security Findings and Attack Paths
Trust Boundaries and Controls
Resilience and Maintainability Implications
Hardening Proposals
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 4 files. (5 skipped: 5 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
plugin/mods/fellowship-gates/tests/gates.test.tsx (1)
13-74: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAssert that Reject fills the feedback prompt.
Press Reject and assert that
prompt.fillreceives the rejection text. The current test exercises Approve and Later, but not Reject.
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Organization UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
b5b94fd4-bf7c-4801-90d5-548a1313b5da
📒 Files selected for processing (9)
plugin/mods/fellowship-gates/.claude-plugin/plugin.jsonplugin/mods/fellowship-gates/.gitignoreplugin/mods/fellowship-gates/README.mdplugin/mods/fellowship-gates/hooks/hooks.jsonplugin/mods/fellowship-gates/hooks/register.tsxplugin/mods/fellowship-gates/hooks/status.tsplugin/mods/fellowship-gates/tests/gates.test.tsxplugin/mods/fellowship-gates/tsconfig.jsonplugin/mods/fellowship-gates/types/index.d.ts
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.
| async function refresh($: EngineInterface) { | ||
| let list: Quest[] = [] | ||
| try { | ||
| const ran = await $.process.run(['sh', '-c', STATUS_CMD], { cwd, timeoutMs: 15_000 }) | ||
| if (ran.exitCode === 0) list = parseStatus(ran.stdout) | ||
| } catch { | ||
| // Binary missing or slow: show nothing rather than a stale count. | ||
| } | ||
|
|
||
| const pending = list.filter(q => q.gatePending).map(gateKey) | ||
| if (announced !== null) { | ||
| for (const key of pending) { | ||
| if (!announced.has(key)) $.ui.toast(`fellowship: ${key.replace(':', ' — ')} gate pending`) | ||
| } | ||
| } | ||
| announced = new Set(pending) | ||
|
|
||
| await update($, quests, () => list) | ||
| // Forget dismissals for gates that are no longer pending, so the same | ||
| // phase gating again after a rejection shows up again. | ||
| await update($, dismissed, keys => keys.filter(k => pending.includes(k))) | ||
| $.ui.status(statusLine(list)) | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
Add a staleness check to refresh.
refresh runs from session.start, turn.complete, and the timer. These calls can overlap, and a slow older call (up to 15 s timeout) can finish after a newer one. The older result then overwrites quests, announced, and the status line with stale data. It can also cause duplicate or missed toasts. Capture a sequence number before the await and return early after the await if a newer call has started.
Proposed fix
+let seq = 0
async function refresh($: EngineInterface) {
+ const mine = ++seq
let list: Quest[] = []
try {
const ran = await $.process.run(['sh', '-c', STATUS_CMD], { cwd, timeoutMs: 15_000 })
if (ran.exitCode === 0) list = parseStatus(ran.stdout)
} catch {
// Binary missing or slow: show nothing rather than a stale count.
}
+ if (mine !== seq) returnSource: Learnings
Summary
Adds an experimental Claude Code mod at
plugin/mods/fellowship-gates/that shows fellowship quest status inside Claude Code:⚔ 2 quests · 1 gate pending, or the quest name and phase when there's only one quest.fellowship gate approvedirectly, so the lead still messages the teammate to resume it.The data comes from
~/.claude/fellowship/bin/fellowship status --json, polled every 10 seconds and after each turn. Merged quests are left out. With no binary or no quests, the mod shows nothing.Scope
claude --plugin-dir plugin/mods/fellowship-gates. It is not wired into the fellowship plugin manifest yet..claude-plugin/types/(types Claude Code generates on load) is gitignored.Test plan
claude plugin validate plugin/mods/fellowship-gatespassesclaude plugin test plugin/mods/fellowship-gates: 3 pass (status parsing, plus the band's Approve/Later flow on the terminal and desktop surfaces)/fellowshipwith real quests and confirm the status line, the toast and the Approve button work (only tested against mockedstatus --jsonoutput so far)🤖 Generated with Claude Code
https://claude.ai/code/session_01HeW5DKghWKp8v2UYCRv5xb
Generated by Claude Code
Summary by CodeRabbit