Commit e229268
Changed files (7)
lib
elelem
skills
builtin
spec
elelem
skills
lib/elelem/skills/builtin/rfc/draft.md
@@ -0,0 +1,51 @@
+Write an RFC (or PRD, or Implementation Plan -- see SKILL.md's altitude
+table) from source material, applying style.md throughout.
+
+# Role
+
+- Read style.md before writing anything -- it's the single source of truth
+ for structure, tone, and the required/optional sections.
+- Write the document to .agents/rfcs/NNN-short-name.md (zero-padded,
+ continuing from the highest existing number in the directory).
+- Where the audience or detail level isn't stated, assume the primary
+ audience is engineers on the team making the change, note the assumption
+ as a `<!-- REVIEW: ... -->` marker, and write at standard detail rather
+ than stalling to ask.
+
+# Process
+
+1. **Gather** - Read whatever source material exists: implementation plan,
+ PRD, prior discussion, code. Note the output path.
+2. **Pick the altitude** - Confirm this should be an RFC and not a PRD or
+ Implementation Plan (see SKILL.md). If genuinely ambiguous, write the
+ RFC and flag the choice as a REVIEW marker.
+3. **Draft** - Write the document following style.md's section table.
+ Present one solution in Proposal; move alternatives to Abandoned Ideas
+ as narrative prose, not a template.
+4. **Self-review** - Before finishing, run style.md's Review Checklist
+ against your own draft and fix what it catches. There's no second pass
+ from a fresh reviewer in this workflow, so this step is what stands in
+ for one.
+5. **Report** - State the file path and list any REVIEW markers you left,
+ so the user knows what to confirm before circulating.
+
+# Draft Status
+
+Every draft starts with this section at the top (see style.md's Draft
+Markers section for the full convention):
+
+```markdown
+## Draft Status
+
+**State:** Draft
+
+**Items for review:**
+- [ ] <!-- REVIEW: item 1 -->
+```
+
+# Guidelines
+
+- One solution in Proposal, not a menu of options.
+- Make decisions; flag them for review instead of leaving blanks or asking.
+- Abandoned Ideas needs real reasoning per alternative, not a dismissal.
+- No time estimates anywhere in the document.
lib/elelem/skills/builtin/rfc/feedback.md
@@ -0,0 +1,74 @@
+Evaluate reviewer feedback on a circulated RFC against its own constraints,
+then update it.
+
+# Role
+
+- Feedback is suggestions to evaluate, not orders to implement. The RFC
+ already documents constraints (Background), rejected alternatives
+ (Abandoned Ideas), and design rationale -- feedback that contradicts
+ those needs pushback, not silent acceptance.
+- If source material (PRD, PoC, implementation plan) is available, verify
+ against it too. The RFC is an abstraction; it can have abstracted a
+ constraint away that the source material still shows.
+
+# Process
+
+1. **Read** - Take in the full feedback before reacting to any one item.
+2. **Parse** - Break it into discrete items.
+3. **Verify** - For each item, check it against the RFC's Background,
+ Abandoned Ideas, and design rationale, and against source material if
+ available.
+4. **Evaluate** - Does it improve the document, or does it ignore a
+ documented constraint?
+5. **Decide** - Accept, push back, or flag for clarification (see below).
+ There's no live back-and-forth in this workflow, so a genuinely unclear
+ item gets listed as needing clarification rather than guessed at.
+6. **Implement** - Apply every accepted change directly to the document.
+7. **Report** - Output the summary format below.
+
+# Deciding
+
+**Accept** when the feedback raises a valid concern the RFC doesn't
+address, catches an edge case, or improves phrasing. Also accept even when
+you initially lean toward disagreeing, if multiple reviewers raise the same
+point independently, or the change is low-cost and removes reviewer doubt.
+
+**Push back** when the feedback contradicts a documented Background
+constraint, re-raises an alternative already covered in Abandoned Ideas, or
+expands scope beyond the RFC's purpose. State the reasoning and point to
+the specific section rather than just disagreeing:
+
+> We considered this -- see Abandoned Ideas. The blocker was [X]. Point to
+> [section] if there's something that changes that.
+
+**Flag for clarification** when the feedback is genuinely ambiguous. Don't
+guess at intent; list it as needing clarification and move on to the next
+item rather than partially implementing a guess.
+
+**When a reviewer asks a question** rather than making a suggestion,
+don't just fold it into the document. Note your own read on the answer,
+what the RFC and source material suggest, and what's still uncertain --
+then treat it as needing clarification if it isn't resolvable from what's
+already written down.
+
+# Forbidden
+
+- Performative agreement ("Great feedback!") -- just state what changed.
+- Implementing before checking it against Background/Abandoned Ideas.
+- Defensive pushback -- use documented reasoning, not tone.
+
+# Output Summary
+
+```markdown
+## Feedback Summary
+
+**Accepted (N items):**
+- [Item]: Updated [section] to [change]
+
+**Pushed Back (N items):**
+- [Item]: See Abandoned Ideas -- [reason]
+- [Item]: Contradicts Background constraint [X]
+
+**Needs Clarification (N items):**
+- [Item]: [what's unclear]
+```
lib/elelem/skills/builtin/rfc/finalize.md
@@ -0,0 +1,48 @@
+Prepare an approved RFC draft for circulation: resolve REVIEW markers,
+convert diagrams, drop the Draft Status section.
+
+# Role
+
+- Only run this once the draft's content is approved -- this is mechanical
+ cleanup, not another content pass.
+- Read style.md's Draft Markers and Diagrams sections before starting.
+
+# Process
+
+1. **Scan** - Find every `<!-- REVIEW: ... -->` marker in the document.
+2. **Resolve** - For each marker, decide: the decision stands (remove the
+ marker), or it should become a visible open question for reviewers
+ (convert to a callout, see below). There's no way to ask the user
+ per-marker in this workflow, so default to confirming the decision
+ stands unless the marker itself reads as genuinely unresolved -- and
+ list every resolution in your final report so the user can override
+ any of them.
+3. **Convert diagrams** - Turn each ASCII diagram into mermaid
+ (`flowchart`, `sequenceDiagram`, or `stateDiagram-v2`), dropping the
+ table container but keeping the caption underneath.
+4. **Remove Draft Status** - Delete the whole section, including any
+ trailing `---` left over from older drafts.
+5. **Validate** - Confirm: no `<!-- REVIEW:` markers remain (unless
+ deliberately converted to callouts), no Draft Status section, no ASCII
+ diagrams, no horizontal rules between sections.
+6. **Rename** - Suggest a circulation-ready filename without "Draft" or a
+ version suffix, e.g. `001-streaming-architecture.md`.
+7. **Report** - List what each marker resolved to and any diagrams
+ converted, so the user can catch a wrong call before this goes out.
+
+# Deferred Markers as Callouts
+
+If a marker should stay visible to reviewers instead of disappearing:
+
+```markdown
+| **Open Question** | Token expiration is set to 24h. Feedback requested on whether this works for long sessions. |
+| :---- |
+```
+
+# Edge Cases
+
+- No REVIEW markers found: skip straight to diagram conversion.
+- No ASCII diagrams found: skip straight to removing Draft Status.
+- A diagram is too complex to convert accurately: leave it as ASCII and
+ flag it in your report for manual recreation, rather than producing a
+ broken mermaid version.
lib/elelem/skills/builtin/rfc/SKILL.md
@@ -0,0 +1,53 @@
+---
+name: rfc
+description: Write, review, finalize, and incorporate feedback on RFC/PRD/Implementation Plan documents in .agents/rfcs/. Use when the user wants to propose an architecture decision or design in writing, not just implement one.
+---
+
+# RFC
+
+A four-phase workflow for writing technical proposals, tracked as a markdown
+file in `.agents/rfcs/`. Each phase is a separate file in this skill's
+directory -- read the one for the phase you're in.
+
+# Phases
+
+| Phase | File | When |
+|---|---|---|
+| Draft | [draft.md](draft.md) | No document exists yet, or it needs a first pass |
+| Style | [style.md](style.md) | Reference only -- draft and feedback both read this, it has no phase of its own |
+| Finalize | [finalize.md](finalize.md) | Draft content is approved, needs cleanup before circulating |
+| Feedback | [feedback.md](feedback.md) | Reviewers responded and their comments need addressing |
+
+# Document Types
+
+Not every proposal needs an RFC. Pick the altitude that matches the question:
+
+| Document | Answers | Audience |
+|---|---|---|
+| PRD | Why? Business justification, user needs | Stakeholders, product |
+| RFC | What? Architecture decisions, system design | Engineers, PMs |
+| Implementation Plan | How? Execution steps, code-level decisions | Engineers doing the work |
+
+An RFC documents a decision, not the execution of one. If the request is
+really "how do we build this," read the scrum skill's design.md instead.
+
+# Document Lifecycle
+
+Draft creates the document, applying style.md throughout. Finalize prepares
+an approved draft for circulation. Feedback processes reviewer comments
+after circulation and updates the document. There is no build phase here --
+an RFC documents a decision, it doesn't implement one.
+
+Every phase runs in a single turn with no way to pause for a live answer.
+Where the source material leaves something ambiguous, make the call, note
+it inline as `<!-- REVIEW: ... -->`, and list it in the document's Draft
+Status section -- see style.md for the exact convention. Don't leave blanks
+and don't stall waiting for clarification that can't arrive mid-turn.
+
+# Attribution
+
+The style and structure in this skill are adapted from
+[lemieux/rfc-skills](https://github.com/lemieux/rfc-skills) (MIT License,
+Copyright (c) 2026 Marc-Antoine Lemieux), trimmed to a single-agent,
+single-turn workflow: no subagents, no live back-and-forth review loop --
+decisions get made and flagged with `<!-- REVIEW: ... -->` instead.
lib/elelem/skills/builtin/rfc/style.md
@@ -0,0 +1,138 @@
+# RFC Style Guide
+
+Reference for writing and reviewing documents in this skill. Read before
+drafting or revising -- draft.md and feedback.md both point here instead
+of repeating these rules.
+
+# Constraints
+
+- Target 500-1000 lines. If it's growing past that, trim -- it's drifting
+ into implementation-plan territory.
+- Prefer pseudocode over full implementations. Code should illustrate, not
+ be copy-pasteable.
+- Present ONE solution in Proposal. Move alternatives to Abandoned Ideas.
+- Never include time estimates. Describe phases and dependencies only.
+- Write Abandoned Ideas as narrative prose, not a template.
+- No "Open Questions" section. Every question gets answered with a
+ decision, then flagged `<!-- REVIEW: ... -->` -- see Draft Markers below.
+
+# Patterns to Avoid
+
+These read as AI-generated and undermine the document:
+
+| Don't write | Write instead |
+|---|---|
+| It's worth noting that... | [state the fact directly] |
+| Let's dive into... | The X works as follows. |
+| This helps facilitate... | This enables... |
+| On one hand X, but on the other hand Y | X. However, Y. |
+| It could potentially cause... | This risks causing... |
+| In this section, we will explore... | [start the section] |
+| Em dashes for asides | Commas, periods, or parentheses |
+| "The X Trap" / "The X Problem" | A descriptive header |
+| Dramatic rhetorical questions | A direct statement |
+| "You need to..." | "We need to..." |
+
+# Writing Style
+
+- Plain vocabulary: "use" not "utilize", "help" not "facilitate".
+- Direct and confident. Explain the why behind a decision, not just the what.
+- "We", not "you" -- the document is the team thinking together.
+- Vary sentence length and connect ideas with reasoning words (because, so,
+ which means, since). Three or more short declarative sentences in a row
+ reads as a bulleted list pretending to be prose -- rewrite it as one.
+- One idea per paragraph, 3-5 sentences, first sentence states the point.
+- No numbered headers, no manual table of contents, no horizontal rules
+ (`---`) between sections -- headers already separate them.
+
+**Choppy (avoid):** Redis pub/sub is fire-and-forget. If no subscriber is
+listening, the message is lost. The buffer is authoritative. Pub/sub is an
+optimization.
+
+**Connected (better):** Redis pub/sub is fire-and-forget, meaning if no
+subscriber is listening when a message is published, it's gone. Because of
+this, we treat the buffer as the authoritative source. Pub/sub pushes
+chunks for low-latency delivery, but the buffer is what makes the system
+reliable.
+
+# Structure Rules
+
+- Code blocks only for actual code, config, commands, or data contracts --
+ never for prose or emphasis.
+- Tables for dense reference data (fields, status codes, options). Prose
+ with subheaders for anything needing explanation (risks, tradeoffs).
+- Define a component before referencing it.
+- Show real request/response JSON for API contracts, not just prose
+ describing them.
+
+# Diagrams
+
+Every diagram reference needs a real diagram, not a placeholder sentence.
+
+While drafting, use ASCII wrapped in a table with the caption as a second
+row of the same table:
+
+```markdown
+| |
+|:---:|
+| `Client -> Redis Buffer -> Delivery Pod -> Widget` |
+| *Caption: High-level data flow* |
+```
+
+During finalize, convert ASCII to mermaid (`flowchart`, `sequenceDiagram`,
+or `stateDiagram-v2`) placed directly in the document -- mermaid renders
+its own boundary, so drop the table container but keep the caption.
+
+# Draft Markers
+
+Use `<!-- REVIEW: ... -->` to flag a decision that was made but might need
+a second look, rather than leaving a blank or a live question:
+
+```markdown
+We chose Redis for the buffer because it supports pub/sub natively.
+<!-- REVIEW: Assumed a 3-node cluster. Confirm capacity with platform. -->
+```
+
+Every marker appears in two places: inline where the decision was made,
+and again in a `## Draft Status` section at the top of the document:
+
+```markdown
+## Draft Status
+
+**State:** Draft
+
+**Items for review:**
+- [ ] <!-- REVIEW: Assumed a 3-node cluster. Confirm capacity with platform. -->
+```
+
+Make the decision, then flag it. Most items should be resolved this way,
+not left as open options. For a genuinely unresolved fork where either
+choice is defensible, present both under a single marker and say so
+explicitly, rather than picking arbitrarily.
+
+# Sections
+
+| Section | Length | Notes |
+|---|---|---|
+| Abstract | 2-3 sentences | A reader with no context understands the problem and approach in 10 seconds. |
+| Background | as needed | All context needed to follow the rest. Done when a newcomer stops asking clarifying questions. |
+| Glossary | 1 line/term | Optional. Only if domain jargon exists; place near the top, not at the end. |
+| Problem Statement | as needed | Optional. Skip if Background already makes the problem obvious. |
+| Proposal | 40-60% of document | The one solution, not a menu. Sub-sections: architecture, component responsibilities, key flows (happy path and error/recovery), data model, integration points. Shorter than Background + Problem Statement combined is a sign it's too thin. |
+| Bill of Work | 50-100 words/component | Optional. Only if multiple teams/components are involved. |
+| Rollout | 200-400 words | Optional. Deployment strategy and rollback plan. Phases and dependencies only, never dates or sprint counts. |
+| Risks | 50-100 words/risk | Optional but recommended. Prose with a subheader per risk, not a table. |
+| Future Steps | 100-300 words | Optional. What this enables later, so reviewers see it's not overbuilt. |
+| Abandoned Ideas | 150-300 words/alternative | Required. Narrative prose per alternative: why it looked viable, what killed it. Not a "what/why attractive/why rejected" template. |
+
+# Review Checklist
+
+- [ ] Proposal is meatier than Background + Problem Statement combined
+- [ ] Abandoned Ideas has real reasoning, not a one-line dismissal
+- [ ] No three-plus-short-sentences-in-a-row choppiness
+- [ ] No patterns from the avoid-list above
+- [ ] "We", not "you", throughout
+- [ ] Every diagram is a real diagram (ASCII while drafting, mermaid after finalize)
+- [ ] Every REVIEW marker appears both inline and in Draft Status
+- [ ] API contracts show real JSON, not prose paraphrase
+- [ ] No Open Questions section
spec/elelem/skills/catalog_spec.rb
@@ -36,16 +36,18 @@ RSpec.describe Elelem::Skills::Catalog do
end
describe "GEM_SKILLS" do
- it "bundles the scrum skill with the gem" do
+ it "bundles the scrum and rfc skills with the gem" do
catalog = described_class.new
- expect(catalog.all.map(&:name)).to include("scrum")
+ expect(catalog.all.map(&:name)).to include("scrum", "rfc")
end
- it "does not treat the scrum skill's phase files as separate skills" do
+ it "does not treat either skill's phase files as separate skills" do
catalog = described_class.new
- expect(catalog.all.map(&:name)).not_to include("plan", "design", "build", "review", "verify")
+ names = catalog.all.map(&:name)
+ expect(names).not_to include("plan", "design", "build", "review", "verify")
+ expect(names).not_to include("draft", "style", "finalize", "feedback")
end
end
README.md
@@ -20,11 +20,16 @@ description: Test-driven development. Use when the user wants tests written firs
`elelem-skills` scans, in this order (later paths shadow earlier ones by name):
-1. `lib/elelem/skills/builtin/*/SKILL.md` bundled with this gem -- currently
- just `scrum`: a lightweight story-driven workflow (backlog files under
- `.agents/backlog/`) with five phases (plan, design, build, review, verify)
- as sibling files the model reads on demand. Used to live as five separate
- ERB system prompts before the skills standard existed.
+1. `lib/elelem/skills/builtin/*/SKILL.md` bundled with this gem:
+ - `scrum` -- a story-driven workflow (backlog files under
+ `.agents/backlog/`) with five phases (plan, design, build, review,
+ verify) as sibling files the model reads on demand. Used to live as
+ five separate ERB system prompts before the skills standard existed.
+ - `rfc` -- write/finalize/incorporate-feedback on RFC, PRD, and
+ Implementation Plan documents (`.agents/rfcs/`), adapted from
+ [lemieux/rfc-skills](https://github.com/lemieux/rfc-skills) (MIT) for
+ a single-agent, single-turn workflow -- decisions get made and
+ flagged `<!-- REVIEW: ... -->` instead of asking live.
2. `~/.agents/skills/*/SKILL.md` (user-level)
3. `.agents/skills/*/SKILL.md` (project-level)
@@ -47,6 +52,9 @@ A `/skills [name]` command is also registered for human-driven listing/reading.
policy) that some skills ship alongside `SKILL.md` -- ignored for now.
- `allowed-tools` / permission scoping from the frontmatter.
- Skill installation/updates (that's `npx skills`, a separate concern).
+- Remote discovery via `.well-known/agent-skills/` (see
+ [cloudflare/agent-skills-discovery-rfc](https://github.com/cloudflare/agent-skills-discovery-rfc))
+ -- this gem only discovers local filesystem paths.
## Setup