Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
{
"name": "ralph-specum",
"description": "Spec-driven development with research, requirements, design, tasks, and autonomous execution. Fresh context per task.",
"version": "4.1.2",
"version": "4.2.0",
"author": {
"name": "tzachbon"
},
Expand Down
2 changes: 1 addition & 1 deletion plugins/ralph-specum/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ralph-specum",
"version": "4.1.2",
"version": "4.2.0",
"description": "Spec-driven development with task-by-task execution. Research, requirements, design, tasks, and autonomous implementation with fresh context per task.",
"author": {
"name": "tzachbon"
Expand Down
79 changes: 73 additions & 6 deletions plugins/ralph-specum/commands/start.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,42 @@ Read `${CLAUDE_PLUGIN_ROOT}/references/intent-classification.md` and follow the

### Quick Mode Check

If `--quick` flag detected in $ARGUMENTS, skip to **Step 5: Quick Mode Flow**.
If `--quick` flag detected in $ARGUMENTS, skip to **Step 6: Quick Mode Flow**.

## Step 3: Skill Discovery Pass 1

> **Normal mode only** -- quick mode skips to Step 6 and never reaches this step. Quick mode gets its own Pass 1 in quick-mode.md.

Scan all skill files and match against the goal text:

1. Read each `${CLAUDE_PLUGIN_ROOT}/skills/*/SKILL.md` file's YAML frontmatter (`name`, `description` fields)
- If a SKILL.md is unreadable (file error, permissions): skip that skill, log warning
- If a SKILL.md has no `description` field in frontmatter: skip that skill, log "no description"
2. Determine **context text**: the goal text only (from Step 2)
3. Tokenize both context text and each skill's `description` using these rules:
a. Lowercase the entire string
b. Replace hyphens with spaces ("brainstorming-style" -> "brainstorming style")
c. Strip all punctuation (parentheses, commas, periods, colons, quotes, brackets, etc.)
d. Split on whitespace into word tokens
e. Remove stopwords: a, an, the, to, for, with, and, or, in, on, by, is, be, that, this, of, it, should, used, when, asks, needs, about
4. Count word overlap between context tokens and description tokens
5. If overlap >= 2 AND skill not already in `discoveredSkills` with `invoked: true`:
- Invoke: `Skill({ skill: "ralph-specum:<name>" })`
- On success: add `{ name, matchedAt: "start", invoked: true }` to `discoveredSkills`
- On failure: set `invoked: false` -- add `{ name, matchedAt: "start", invoked: false }`, log warning, continue
6. If no skills match across all scanned skills: log `- No skills matched`
7. Update `.ralph-state.json` with updated `discoveredSkills` array
8. Append a `## Skill Discovery` section to `.progress.md` with match details per skill:
```markdown
## Skill Discovery
- **<skill-name>**: matched (keywords: <overlapping words>)
- **<skill-name>**: no match
- **<skill-name>**: skipped (unreadable)
- **<skill-name>**: skipped (no description)
```
If no skills match: `- No skills matched`
Comment on lines +41 to +72
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Pass 1 discoveries are overwritten by state initialization in the normal-mode New Flow.

The execution order is:

  1. Step 3 (Pass 1) — invokes skills, then tries to write discoveredSkills to .ralph-state.json (Step 3.7), but .ralph-state.json doesn't exist yet for a brand-new spec.
  2. New Flow step 7 — initializes .ralph-state.json from scratch with "discoveredSkills": [], silently discarding whatever Pass 1 recorded.
  3. New Flow step 12 (Pass 2) — reads discoveredSkills: [] (no Pass 1 records), bypassing deduplication and potentially re-invoking the same skills a second time.

This is in contrast to Quick Mode (quick-mode.md) which correctly initializes state before running Pass 1 (Step 5 → Step 9).

The root fix is to move Pass 1 to inside the New Flow, after state initialization (i.e., between current New Flow steps 7 and 8), matching the Quick Mode pattern. Alternatively, New Flow step 7 should explicitly merge rather than reset discoveredSkills if any were already accumulated.

Note: This bug only affects normal mode + new spec. Resume flow is unaffected since state already exists and is updated correctly at Step 3.7.

🛠️ Sketch of the fix (New Flow reordering)

Move the discovery block out of Step 3 and into the New Flow section:

-## Step 3: Skill Discovery Pass 1
-
-> **Normal mode only** -- quick mode skips to Step 6 and never reaches this step. Quick mode gets its own Pass 1 in quick-mode.md.
-
-[full Pass 1 instructions...]
-
 ## Step 4: Scan Existing Specs

Then inside "### New Flow", after the current step 7 (state init) and before step 8 (create .progress.md):

 7. Initialize `.ralph-state.json`:
    { ..., "discoveredSkills": [] }
+7a. **Skill Discovery Pass 1** -- scan skills, match against goal text, invoke matches
+    [full Pass 1 instructions, state write now safe since file was just created]
 8. Create `.progress.md` with goal

Also update the Quick Mode Check note in Step 2 accordingly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/ralph-specum/commands/start.md` around lines 41 - 72, Pass 1
discovery results are being overwritten because New Flow initializes
.ralph-state.json after Step 3 writes discoveredSkills; move the Pass 1
discovery block so it runs after state initialization in the "New Flow" (i.e.,
run the skill discovery once the .ralph-state.json exists) or change the state
init to merge existing discoveredSkills instead of resetting them. Specifically,
relocate the Step 3 "Skill Discovery Pass 1" logic into the New Flow between
current step 7 (state init) and step 8 (create .progress.md) or modify the state
initialization to merge rather than replace discoveredSkills; ensure references
to .ralph-state.json and the discoveredSkills array are preserved and that
deduplication logic (checking invoked:true) still runs before invoking Skill({
skill: "ralph-specum:<name>" }).


## Step 3: Scan Existing Specs
## Step 4: Scan Existing Specs

Read `${CLAUDE_PLUGIN_ROOT}/references/spec-scanner.md` and follow the scanning algorithm and index hint logic.

Expand All @@ -48,7 +81,7 @@ Read `${CLAUDE_PLUGIN_ROOT}/references/spec-scanner.md` and follow the scanning

**Summary**: Scans ./specs/ directory (and all configured specs_dirs) for related specs using keyword matching. Displays related specs with relevance scores. Shows index hint if codebase indexing not yet done. Stores relatedSpecs in .ralph-state.json for use during interview.

## Step 4: Route to Action
## Step 5: Route to Action

Based on detection logic from Step 2:

Expand Down Expand Up @@ -97,14 +130,48 @@ Continuing...
"phase": "research", "taskIndex": 0, "totalTasks": 0,
"taskIteration": 1, "maxTaskIterations": 5,
"globalIteration": 1, "maxGlobalIterations": 100,
"commitSpec": true, "quickMode": false
"commitSpec": true, "quickMode": false,
"discoveredSkills": []
}
```
8. Create `.progress.md` with goal
9. Update Spec Index: `./plugins/ralph-specum/hooks/scripts/update-spec-index.sh --quiet`
10. **Goal Interview** -- Read `${CLAUDE_PLUGIN_ROOT}/references/goal-interview.md` and follow brainstorming dialogue
11. **Team Research Phase** -- Read `${CLAUDE_PLUGIN_ROOT}/references/parallel-research.md` and follow the dispatch pattern
12. **STOP** -- After merge and state update (awaitingApproval=true), display walkthrough and wait for user
12. **Skill Discovery Pass 2 (Post-Research Retry)** -- Re-scan skills with enriched context after research completes:

### Skill Discovery Pass 2

Scan all skill files and match against goal + research context:

1. Read each `${CLAUDE_PLUGIN_ROOT}/skills/*/SKILL.md` file's YAML frontmatter (`name`, `description` fields)
- If a SKILL.md is unreadable (file error, permissions): skip that skill, log warning
- If a SKILL.md has no `description` field in frontmatter: skip that skill, log "no description"
2. Determine **context text**: goal text + the **Executive Summary** section from `research.md`
3. Tokenize both context text and each skill's `description` using these rules:
a. Lowercase the entire string
b. Replace hyphens with spaces ("brainstorming-style" -> "brainstorming style")
c. Strip all punctuation (parentheses, commas, periods, colons, quotes, brackets, etc.)
d. Split on whitespace into word tokens
e. Remove stopwords: a, an, the, to, for, with, and, or, in, on, by, is, be, that, this, of, it, should, used, when, asks, needs, about
4. Count word overlap between context tokens and description tokens
5. If overlap >= 2 AND skill not already in `discoveredSkills` with `invoked: true`:
- Invoke: `Skill({ skill: "ralph-specum:<name>" })`
- On success: add `{ name, matchedAt: "post-research", invoked: true }` to `discoveredSkills`
- On failure: set `invoked: false` -- add `{ name, matchedAt: "post-research", invoked: false }`, log warning, continue
6. If no skills match across all scanned skills: log `- No skills matched`
7. Update `.ralph-state.json` with updated `discoveredSkills` array
8. Append a `### Post-Research Retry` subsection to `.progress.md` under `## Skill Discovery`:
```markdown
### Post-Research Retry
- **<skill-name>**: matched (keywords: <overlapping words>)
- **<skill-name>**: no match (already invoked)
- **<skill-name>**: skipped (unreadable)
- **<skill-name>**: skipped (no description)
```
If no new skills match: `- No new skills matched`
Comment on lines +162 to +172
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Pass 2 "no match" log instruction disagrees with the template.

Line 162 instructs to log - No skills matched, but the progress template at line 172 shows - No new skills matched. The template wording is more appropriate for a second pass. Fix the inline instruction to match (same issue exists in quick-mode.md Step 12.6).

🛠️ Proposed fix
-    6. If no skills match across all scanned skills: log `- No skills matched`
+    6. If no new skills match across all scanned skills: log `- No new skills matched`
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
6. If no skills match across all scanned skills: log `- No skills matched`
7. Update `.ralph-state.json` with updated `discoveredSkills` array
8. Append a `### Post-Research Retry` subsection to `.progress.md` under `## Skill Discovery`:
```markdown
### Post-Research Retry
- **<skill-name>**: matched (keywords: <overlapping words>)
- **<skill-name>**: no match (already invoked)
- **<skill-name>**: skipped (unreadable)
- **<skill-name>**: skipped (no description)
```
If no new skills match: `- No new skills matched`
6. If no new skills match across all scanned skills: log `- No new skills matched`
7. Update `.ralph-state.json` with updated `discoveredSkills` array
8. Append a `### Post-Research Retry` subsection to `.progress.md` under `## Skill Discovery`:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/ralph-specum/commands/start.md` around lines 162 - 172, Update the
second-pass logging instruction so the wording matches the progress template:
change the inline log text `- No skills matched` to `- No new skills matched` in
plugins/ralph-specum/commands/start.md (the step describing Pass 2 and the
Appendix "Post-Research Retry") and apply the same change in quick-mode.md Step
12.6 so both the instruction and the `### Post-Research Retry` template use the
exact phrase `- No new skills matched`.


13. **STOP** -- After merge and state update (awaitingApproval=true), display walkthrough and wait for user

### Research Walkthrough (Normal Mode Only)

Expand Down Expand Up @@ -133,7 +200,7 @@ Then STOP. Output: `-> Next: Run /ralph-specum:requirements`
End response immediately.
</mandatory>

## Step 5: Quick Mode Flow
## Step 6: Quick Mode Flow

Read `${CLAUDE_PLUGIN_ROOT}/references/quick-mode.md` and follow the full quick mode execution sequence.

Expand Down
92 changes: 78 additions & 14 deletions plugins/ralph-specum/references/quick-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,29 +72,93 @@ Validation Sequence:
taskIndex: 0, totalTasks: 0, taskIteration: 1,
maxTaskIterations: 5, globalIteration: 1,
maxGlobalIterations: 100, commitSpec: $commitSpec,
quickMode: true }
quickMode: true, discoveredSkills: [] }
6. Write .progress.md with original goal
7. Update .current-spec (bare name or full path)
8. Update Spec Index: ./plugins/ralph-specum/hooks/scripts/update-spec-index.sh --quiet
9. Goal Type Detection:
- Classify as "fix" or "add" using regex indicators
- Fix: fix|resolve|debug|broken|failing|error|bug|crash|issue|not working
- Add: add|create|build|implement|new|enable|introduce (default)
- For fix goals: run reproduction, document BEFORE state
10. Research Phase: run Team Research flow (skip walkthrough), clear awaitingApproval
11. Requirements Phase: delegate to product-manager with Quick Mode Directive, review loop
12. Design Phase: delegate to architect-reviewer with Quick Mode Directive, review loop
13. Tasks Phase: delegate to task-planner with Quick Mode Directive, review loop
14. Transition to Execution:
9. Skill Discovery Pass 1: scan skills, match against goal text, invoke matches
10. Goal Type Detection:
- Classify as "fix" or "add" using regex indicators
- Fix: fix|resolve|debug|broken|failing|error|bug|crash|issue|not working
- Add: add|create|build|implement|new|enable|introduce (default)
- For fix goals: run reproduction, document BEFORE state
11. Research Phase: run Team Research flow (skip walkthrough), clear awaitingApproval
12. Skill Discovery Pass 2: re-scan skills using goal + research Executive Summary, invoke new matches
13. Requirements Phase: delegate to product-manager with Quick Mode Directive, review loop
14. Design Phase: delegate to architect-reviewer with Quick Mode Directive, review loop
15. Tasks Phase: delegate to task-planner with Quick Mode Directive, review loop
16. Transition to Execution:
- Count total tasks (number of `- [ ]` checkboxes)
- Update state: phase="execution", totalTasks=<count>, taskIndex=0
- If commitSpec: stage, commit, push spec files
15. Invoke spec-executor for task 1
17. Invoke spec-executor for task 1
```

## Step 9: Skill Discovery Pass 1

Scan all skill files and match against the goal text:

1. Read each `${CLAUDE_PLUGIN_ROOT}/skills/*/SKILL.md` file's YAML frontmatter (`name`, `description` fields)
- If a SKILL.md is unreadable (file error, permissions): skip that skill, log warning
- If a SKILL.md has no `description` field in frontmatter: skip that skill, log "no description"
2. Determine **context text**: the goal text only (from step 1)
3. Tokenize both context text and each skill's `description` using these rules:
a. Lowercase the entire string
b. Replace hyphens with spaces ("brainstorming-style" -> "brainstorming style")
c. Strip all punctuation (parentheses, commas, periods, colons, quotes, brackets, etc.)
d. Split on whitespace into word tokens
e. Remove stopwords: a, an, the, to, for, with, and, or, in, on, by, is, be, that, this, of, it, should, used, when, asks, needs, about
4. Count word overlap between context tokens and description tokens
5. If overlap >= 2 AND skill not already in `discoveredSkills` with `invoked: true`:
- Invoke: `Skill({ skill: "ralph-specum:<name>" })`
- On success: add `{ name, matchedAt: "start", invoked: true }` to `discoveredSkills`
- On failure: set `invoked: false` -- add `{ name, matchedAt: "start", invoked: false }`, log warning, continue
6. If no skills match across all scanned skills: log `- No skills matched`
7. Update `.ralph-state.json` with updated `discoveredSkills` array
8. Append a `## Skill Discovery` section to `.progress.md` with match details per skill:
```markdown
## Skill Discovery
- **<skill-name>**: matched (keywords: <overlapping words>)
- **<skill-name>**: no match
- **<skill-name>**: skipped (unreadable)
- **<skill-name>**: skipped (no description)
```
If no skills match: `- No skills matched`

## Step 12: Skill Discovery Pass 2 (Post-Research Retry)

Re-scan skills with enriched context after research completes:

1. Read each `${CLAUDE_PLUGIN_ROOT}/skills/*/SKILL.md` file's YAML frontmatter (`name`, `description` fields)
- If a SKILL.md is unreadable (file error, permissions): skip that skill, log warning
- If a SKILL.md has no `description` field in frontmatter: skip that skill, log "no description"
2. Determine **context text**: goal text + the **Executive Summary** section from `research.md`
3. Tokenize both context text and each skill's `description` using these rules:
a. Lowercase the entire string
b. Replace hyphens with spaces ("brainstorming-style" -> "brainstorming style")
c. Strip all punctuation (parentheses, commas, periods, colons, quotes, brackets, etc.)
d. Split on whitespace into word tokens
e. Remove stopwords: a, an, the, to, for, with, and, or, in, on, by, is, be, that, this, of, it, should, used, when, asks, needs, about
4. Count word overlap between context tokens and description tokens
5. If overlap >= 2 AND skill not already in `discoveredSkills` with `invoked: true`:
- Invoke: `Skill({ skill: "ralph-specum:<name>" })`
- On success: add `{ name, matchedAt: "post-research", invoked: true }` to `discoveredSkills`
- On failure: set `invoked: false` -- add `{ name, matchedAt: "post-research", invoked: false }`, log warning, continue
6. If no skills match across all scanned skills: log `- No skills matched`
7. Update `.ralph-state.json` with updated `discoveredSkills` array
8. Append a `### Post-Research Retry` subsection to `.progress.md` under `## Skill Discovery`:
```markdown
### Post-Research Retry
- **<skill-name>**: matched (keywords: <overlapping words>)
- **<skill-name>**: no match (already invoked)
- **<skill-name>**: skipped (unreadable)
- **<skill-name>**: skipped (no description)
```
If no new skills match: `- No new skills matched`
Comment on lines +147 to +157
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Pass 2 "no match" log message is inconsistent between the instruction and the template.

Line 147 says to log - No skills matched, but the markdown template at line 157 shows - No new skills matched. For Pass 2, the template wording is more accurate since skills may have matched in Pass 1. The same inconsistency exists in start.md Pass 2 (lines 162/172).

🛠️ Proposed fix
-6. If no skills match across all scanned skills: log `- No skills matched`
+6. If no new skills match across all scanned skills: log `- No new skills matched`
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
6. If no skills match across all scanned skills: log `- No skills matched`
7. Update `.ralph-state.json` with updated `discoveredSkills` array
8. Append a `### Post-Research Retry` subsection to `.progress.md` under `## Skill Discovery`:
```markdown
### Post-Research Retry
- **<skill-name>**: matched (keywords: <overlapping words>)
- **<skill-name>**: no match (already invoked)
- **<skill-name>**: skipped (unreadable)
- **<skill-name>**: skipped (no description)
```
If no new skills match: `- No new skills matched`
6. If no new skills match across all scanned skills: log `- No new skills matched`
7. Update `.ralph-state.json` with updated `discoveredSkills` array
8. Append a `### Post-Research Retry` subsection to `.progress.md` under `## Skill Discovery`:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/ralph-specum/references/quick-mode.md` around lines 147 - 157,
Summary: The "Pass 2" no-match log wording is inconsistent between the
instruction and the Post-Research Retry template; standardize on "No new skills
matched". Fix: update the Pass 2 log instruction that currently says "- No
skills matched" to read "- No new skills matched" wherever it appears in
quick-mode.md and start.md, and ensure the "### Post-Research Retry" subsection
template under "## Skill Discovery" uses the same phrase; verify any references
to the Pass 2 message in related docs/templates are updated to keep wording
consistent.


## Quick Mode Directive

Each agent delegation in steps 10-13 includes this directive in the Task prompt:
Each agent delegation in steps 11-15 includes this directive in the Task prompt:

```text
Quick Mode Context:
Expand All @@ -109,7 +173,7 @@ Running in quick mode with no user feedback. You MUST:

## Quick Mode Review Loop (Per Artifact)

After each phase agent returns in steps 11-13, run spec-reviewer to validate:
After each phase agent returns in steps 13-15, run spec-reviewer to validate:

```text
Set iteration = 1
Expand Down
Loading