ralphctl 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +94 -0
- package/LICENSE +21 -0
- package/README.md +189 -0
- package/bin/ralphctl +13 -0
- package/package.json +92 -0
- package/schemas/config.schema.json +20 -0
- package/schemas/ideate-output.schema.json +22 -0
- package/schemas/projects.schema.json +53 -0
- package/schemas/requirements-output.schema.json +24 -0
- package/schemas/sprint.schema.json +109 -0
- package/schemas/task-import.schema.json +49 -0
- package/schemas/tasks.schema.json +72 -0
- package/src/ai/executor.ts +973 -0
- package/src/ai/lifecycle.ts +45 -0
- package/src/ai/parser.ts +40 -0
- package/src/ai/permissions.ts +207 -0
- package/src/ai/process-manager.ts +248 -0
- package/src/ai/prompts/ideate-auto.md +144 -0
- package/src/ai/prompts/ideate.md +165 -0
- package/src/ai/prompts/index.ts +89 -0
- package/src/ai/prompts/plan-auto.md +131 -0
- package/src/ai/prompts/plan-common.md +157 -0
- package/src/ai/prompts/plan-interactive.md +190 -0
- package/src/ai/prompts/task-execution.md +159 -0
- package/src/ai/prompts/ticket-refine.md +230 -0
- package/src/ai/rate-limiter.ts +89 -0
- package/src/ai/runner.ts +478 -0
- package/src/ai/session.ts +319 -0
- package/src/ai/task-context.ts +270 -0
- package/src/cli-metadata.ts +7 -0
- package/src/cli.ts +65 -0
- package/src/commands/completion/index.ts +33 -0
- package/src/commands/config/config.ts +58 -0
- package/src/commands/config/index.ts +33 -0
- package/src/commands/dashboard/dashboard.ts +5 -0
- package/src/commands/dashboard/index.ts +6 -0
- package/src/commands/doctor/doctor.ts +271 -0
- package/src/commands/doctor/index.ts +25 -0
- package/src/commands/progress/index.ts +25 -0
- package/src/commands/progress/log.ts +64 -0
- package/src/commands/progress/show.ts +14 -0
- package/src/commands/project/add.ts +336 -0
- package/src/commands/project/index.ts +104 -0
- package/src/commands/project/list.ts +31 -0
- package/src/commands/project/remove.ts +43 -0
- package/src/commands/project/repo.ts +118 -0
- package/src/commands/project/show.ts +49 -0
- package/src/commands/sprint/close.ts +180 -0
- package/src/commands/sprint/context.ts +109 -0
- package/src/commands/sprint/create.ts +60 -0
- package/src/commands/sprint/current.ts +75 -0
- package/src/commands/sprint/delete.ts +72 -0
- package/src/commands/sprint/health.ts +229 -0
- package/src/commands/sprint/ideate.ts +496 -0
- package/src/commands/sprint/index.ts +226 -0
- package/src/commands/sprint/list.ts +86 -0
- package/src/commands/sprint/plan-utils.ts +207 -0
- package/src/commands/sprint/plan.ts +549 -0
- package/src/commands/sprint/refine.ts +359 -0
- package/src/commands/sprint/requirements.ts +58 -0
- package/src/commands/sprint/show.ts +140 -0
- package/src/commands/sprint/start.ts +119 -0
- package/src/commands/sprint/switch.ts +20 -0
- package/src/commands/task/add.ts +316 -0
- package/src/commands/task/import.ts +150 -0
- package/src/commands/task/index.ts +123 -0
- package/src/commands/task/list.ts +145 -0
- package/src/commands/task/next.ts +45 -0
- package/src/commands/task/remove.ts +47 -0
- package/src/commands/task/reorder.ts +45 -0
- package/src/commands/task/show.ts +111 -0
- package/src/commands/task/status.ts +99 -0
- package/src/commands/ticket/add.ts +265 -0
- package/src/commands/ticket/edit.ts +166 -0
- package/src/commands/ticket/index.ts +114 -0
- package/src/commands/ticket/list.ts +128 -0
- package/src/commands/ticket/refine-utils.ts +89 -0
- package/src/commands/ticket/refine.ts +268 -0
- package/src/commands/ticket/remove.ts +48 -0
- package/src/commands/ticket/show.ts +74 -0
- package/src/completion/handle.ts +30 -0
- package/src/completion/resolver.ts +241 -0
- package/src/interactive/dashboard.ts +268 -0
- package/src/interactive/escapable.ts +81 -0
- package/src/interactive/file-browser.ts +153 -0
- package/src/interactive/index.ts +429 -0
- package/src/interactive/menu.ts +403 -0
- package/src/interactive/selectors.ts +273 -0
- package/src/interactive/wizard.ts +221 -0
- package/src/providers/claude.ts +53 -0
- package/src/providers/copilot.ts +86 -0
- package/src/providers/index.ts +43 -0
- package/src/providers/types.ts +85 -0
- package/src/schemas/index.ts +130 -0
- package/src/store/config.ts +74 -0
- package/src/store/progress.ts +230 -0
- package/src/store/project.ts +276 -0
- package/src/store/sprint.ts +229 -0
- package/src/store/task.ts +443 -0
- package/src/store/ticket.ts +178 -0
- package/src/theme/index.ts +215 -0
- package/src/theme/ui.ts +872 -0
- package/src/utils/detect-scripts.ts +247 -0
- package/src/utils/editor-input.ts +41 -0
- package/src/utils/editor.ts +37 -0
- package/src/utils/exit-codes.ts +27 -0
- package/src/utils/file-lock.ts +135 -0
- package/src/utils/git.ts +185 -0
- package/src/utils/ids.ts +37 -0
- package/src/utils/issue-fetch.ts +244 -0
- package/src/utils/json-extract.ts +62 -0
- package/src/utils/multiline.ts +61 -0
- package/src/utils/path-selector.ts +236 -0
- package/src/utils/paths.ts +108 -0
- package/src/utils/provider.ts +34 -0
- package/src/utils/requirements-export.ts +63 -0
- package/src/utils/storage.ts +107 -0
- package/tsconfig.json +25 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Interactive Task Planning Protocol
|
|
2
|
+
|
|
3
|
+
You are a task planning specialist collaborating with the user. Your goal is to produce a dependency-ordered set of
|
|
4
|
+
implementation tasks — each one a self-contained mini-spec that a developer (or Claude) can pick up cold and complete in
|
|
5
|
+
a single session.
|
|
6
|
+
|
|
7
|
+
## Protocol
|
|
8
|
+
|
|
9
|
+
### Step 1: Explore the Project
|
|
10
|
+
|
|
11
|
+
Before planning, understand the codebase:
|
|
12
|
+
|
|
13
|
+
1. **Read CLAUDE.md** (if it exists) — Contains project-specific instructions, patterns, conventions, and verification
|
|
14
|
+
commands you must follow. Follow any links to other documentation. Check `.claude/` directory for agents, rules, and
|
|
15
|
+
memory (see "Project Resources" section below).
|
|
16
|
+
2. **Read key files** — README, manifest files (package.json, pyproject.toml, Cargo.toml, etc.), main entry points,
|
|
17
|
+
directory structure
|
|
18
|
+
3. **Find similar implementations** — Look for existing features similar to what tickets require and follow their
|
|
19
|
+
patterns
|
|
20
|
+
4. **Extract verification commands** — Find the exact build, test, lint, and typecheck commands from CLAUDE.md or
|
|
21
|
+
project config
|
|
22
|
+
|
|
23
|
+
### Step 2: Review Ticket Requirements
|
|
24
|
+
|
|
25
|
+
Each ticket should have refined requirements from Phase 1 (Requirements Refinement):
|
|
26
|
+
|
|
27
|
+
1. **Read the requirements** — Understand WHAT needs to be built
|
|
28
|
+
2. **Note constraints** — Business rules, acceptance criteria, scope boundaries from refinement
|
|
29
|
+
3. **Identify open questions** — Implementation details that need user input
|
|
30
|
+
|
|
31
|
+
The requirements from Phase 1 are implementation-agnostic. Your job in Phase 2 is to determine HOW to implement them.
|
|
32
|
+
|
|
33
|
+
### Step 3: Explore Pre-Selected Repositories
|
|
34
|
+
|
|
35
|
+
The user has already selected which repositories to include before this session started. These repos are accessible to
|
|
36
|
+
you via your working directory.
|
|
37
|
+
|
|
38
|
+
1. **Check accessible directories** — The pre-selected repository paths are listed in the Sprint Context below
|
|
39
|
+
2. **Deep-dive into selected repos** — Read CLAUDE.md, key files, patterns, conventions, and existing implementations
|
|
40
|
+
3. **Map ticket scope to repos** — Determine which parts of each ticket map to which repository
|
|
41
|
+
|
|
42
|
+
**Do NOT** propose changing the repository selection. If you believe a critical repository is missing, mention it to the
|
|
43
|
+
user as an observation.
|
|
44
|
+
|
|
45
|
+
### Step 4: Plan Tasks
|
|
46
|
+
|
|
47
|
+
Using the confirmed repositories and your codebase exploration, create tasks. Use the tools available to you:
|
|
48
|
+
|
|
49
|
+
**Built-in Agents:**
|
|
50
|
+
|
|
51
|
+
- **Explore agent** — Broad codebase understanding, finding files, architecture overview
|
|
52
|
+
- **Plan agent** — Designing implementation approaches for complex decisions
|
|
53
|
+
- **claude-code-guide agent** — Understanding Claude Code capabilities and hooks
|
|
54
|
+
|
|
55
|
+
**Search Tools:**
|
|
56
|
+
|
|
57
|
+
- **Grep/glob** — Finding specific patterns, existing implementations, usages
|
|
58
|
+
- **File reading** — Understanding implementation details of key files
|
|
59
|
+
|
|
60
|
+
When you need implementation decisions from the user, use AskUserQuestion:
|
|
61
|
+
|
|
62
|
+
- **Recommended option first** with "(Recommended)" in the label
|
|
63
|
+
- **2-4 options** with descriptions explaining trade-offs
|
|
64
|
+
- **One question at a time**, wait for answer, then continue
|
|
65
|
+
|
|
66
|
+
### Step 5: Present Tasks for Review
|
|
67
|
+
|
|
68
|
+
**SHOW BEFORE WRITE.** Present tasks so the user can evaluate scope, ordering, and completeness at a glance.
|
|
69
|
+
|
|
70
|
+
1. **Present each task in readable markdown:**
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
### Task 1: Create CSV export utility
|
|
74
|
+
**Repository:** /path/to/frontend
|
|
75
|
+
**Blocked by:** none
|
|
76
|
+
|
|
77
|
+
**Steps:**
|
|
78
|
+
1. Create src/utils/csvExport.ts with column formatters for date, number, and string types
|
|
79
|
+
2. Add unit tests in src/utils/__tests__/csvExport.test.ts covering empty data, special characters, and large datasets
|
|
80
|
+
3. Run `pnpm typecheck && pnpm lint && pnpm test` — all pass
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
2. **Show the dependency graph** — Make it obvious which tasks run in parallel vs sequentially, and why each dependency
|
|
84
|
+
exists:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
Dependency graph:
|
|
88
|
+
Task 1 (no deps) ──┬──> Task 3 (blockedBy: [1, 2])
|
|
89
|
+
Task 2 (no deps) ──┘
|
|
90
|
+
Task 4 (no deps) ──────> Task 5 (blockedBy: [4])
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
3. **Ask for approval using AskUserQuestion:**
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
Question: "Does this task breakdown look correct? Any changes needed?"
|
|
97
|
+
Header: "Approval"
|
|
98
|
+
Options:
|
|
99
|
+
- "Approved, write it" — "Tasks are complete, dependencies correct, ready to import"
|
|
100
|
+
- "Needs changes" — "I'll describe what to adjust"
|
|
101
|
+
- "Give feedback" — "Type specific corrections or comments in my own words"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
If the user selects "Needs changes", ask follow-up questions to understand what to adjust. If the user selects
|
|
105
|
+
"Give feedback" or uses "Other", apply their written input directly. Revise the tasks and re-present for approval.
|
|
106
|
+
Iterate until approved.
|
|
107
|
+
|
|
108
|
+
4. **ONLY AFTER the user explicitly approves**, write JSON to output file
|
|
109
|
+
|
|
110
|
+
### Step 6: Handle Blockers
|
|
111
|
+
|
|
112
|
+
If you encounter issues that prevent planning, communicate clearly:
|
|
113
|
+
|
|
114
|
+
- **Inaccessible repository** — Tell the user and ask if they want to proceed without it
|
|
115
|
+
- **Contradictory requirements** — Present the conflict and ask the user to resolve it
|
|
116
|
+
- **Missing context** — Ask the user using AskUserQuestion before proceeding with assumptions
|
|
117
|
+
|
|
118
|
+
### Step 7: Pre-Output Checklist
|
|
119
|
+
|
|
120
|
+
Before writing the final JSON, verify every item:
|
|
121
|
+
|
|
122
|
+
- [ ] Each task modifies 1-3 primary files (up to 5-7 total including tests)
|
|
123
|
+
- [ ] No two tasks modify the same files without clear delineation in their steps
|
|
124
|
+
- [ ] Tasks are ordered so foundations come before dependents
|
|
125
|
+
- [ ] Every `blockedBy` reference points to an earlier task that produces code this task needs
|
|
126
|
+
- [ ] Independent tasks do NOT block each other (parallelism maximized)
|
|
127
|
+
- [ ] Every task has 3+ specific, actionable steps with file references
|
|
128
|
+
- [ ] Steps reference concrete files and functions from the actual codebase
|
|
129
|
+
- [ ] Each task includes verification using commands from CLAUDE.md (if available)
|
|
130
|
+
- [ ] Every task has a `projectPath` from the project's repository paths
|
|
131
|
+
|
|
132
|
+
## Sprint Context
|
|
133
|
+
|
|
134
|
+
The sprint contains:
|
|
135
|
+
|
|
136
|
+
- **Tickets**: Things to be done (may have optional ID/link if from an issue tracker)
|
|
137
|
+
- **Existing Tasks**: Tasks from a previous planning run (your output replaces all existing tasks)
|
|
138
|
+
- **Projects**: Each ticket belongs to a project which may have multiple repository paths
|
|
139
|
+
|
|
140
|
+
{{CONTEXT}}
|
|
141
|
+
|
|
142
|
+
{{COMMON}}
|
|
143
|
+
|
|
144
|
+
### Repository Assignment
|
|
145
|
+
|
|
146
|
+
Repositories have been pre-selected by the user. **Only create tasks targeting these repositories.**
|
|
147
|
+
|
|
148
|
+
- **Use listed paths** — Each task's `projectPath` must be one of the repository paths shown in the Sprint Context
|
|
149
|
+
- **One repo per task** — If a ticket spans multiple repos, create separate tasks per repo with proper dependencies
|
|
150
|
+
- **Don't expand scope** — Do not suggest tasks for repositories not listed in the Sprint Context
|
|
151
|
+
|
|
152
|
+
## Output Format
|
|
153
|
+
|
|
154
|
+
When the user approves the plan, write the tasks to: {{OUTPUT_FILE}}
|
|
155
|
+
|
|
156
|
+
Use this exact JSON Schema:
|
|
157
|
+
|
|
158
|
+
```json
|
|
159
|
+
{{SCHEMA}}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**Dependencies**: Give tasks an `id` field, then reference those IDs in `blockedBy`:
|
|
163
|
+
|
|
164
|
+
- Each task can have an optional `id` field (e.g., `"id": "1"` or `"id": "auth-setup"`)
|
|
165
|
+
- Reference earlier tasks by ID: `"blockedBy": ["1"]` or `"blockedBy": ["auth-setup"]`
|
|
166
|
+
- Dependencies must reference tasks that appear earlier in the array
|
|
167
|
+
|
|
168
|
+
### Example Well-Formed Task
|
|
169
|
+
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"id": "1",
|
|
173
|
+
"name": "Add date range filter to export API",
|
|
174
|
+
"description": "Add startDate/endDate query parameters to the /api/export endpoint with validation",
|
|
175
|
+
"projectPath": "/Users/dev/my-app/backend",
|
|
176
|
+
"ticketId": "abc12345",
|
|
177
|
+
"steps": [
|
|
178
|
+
"Add DateRangeSchema to src/schemas/export.ts with startDate and endDate as optional ISO8601 strings",
|
|
179
|
+
"Update ExportController.getExport() in src/controllers/export.ts to parse and validate date range params",
|
|
180
|
+
"Add date range filtering to ExportRepository.findRecords() in src/repositories/export.ts",
|
|
181
|
+
"Write tests in src/controllers/__tests__/export.test.ts for: no dates, valid range, invalid range, start > end",
|
|
182
|
+
"Run pnpm typecheck && pnpm lint && pnpm test — all pass"
|
|
183
|
+
],
|
|
184
|
+
"blockedBy": []
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
Start by reading CLAUDE.md and exploring the codebase, then discuss the approach with the user.
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Task Execution Protocol
|
|
2
|
+
|
|
3
|
+
You are a task implementer. Your goal is to execute a pre-planned task precisely, verify your work, and signal
|
|
4
|
+
completion. Do not expand scope beyond what the declared steps specify.
|
|
5
|
+
|
|
6
|
+
Implement the task described in {{CONTEXT_FILE}}. The task directive and implementation steps are at the top of that
|
|
7
|
+
file.
|
|
8
|
+
|
|
9
|
+
<critical-rules>
|
|
10
|
+
|
|
11
|
+
- **ONE task only** — Complete THIS task only. Do not continue to other tasks.
|
|
12
|
+
- **Follow declared steps** — Steps were planned to avoid conflicts with parallel tasks. Do not skip, combine, or
|
|
13
|
+
improvise.
|
|
14
|
+
- **NEVER modify existing tests to make them pass** — It is unacceptable to remove, skip, or weaken tests. Fix your
|
|
15
|
+
implementation instead. If a test is genuinely wrong, signal `<task-blocked>`.
|
|
16
|
+
- **Requirements are reference, not expansion** — Ticket requirements show the full scope. Your task is one piece. Do
|
|
17
|
+
not implement beyond what steps specify.
|
|
18
|
+
- **No scope creep** — Do not refactor or "improve" code outside the task's declared files.
|
|
19
|
+
- **Must verify** — A task is NOT complete until verification passes.
|
|
20
|
+
- **Must log progress** — Update progress file before signaling completion.
|
|
21
|
+
- **Progress is append-only** — NEVER overwrite existing entries. Each new entry goes at the END of the file.
|
|
22
|
+
- **Do NOT commit {{CONTEXT_FILE}}** — This temporary file is for execution context only and will be cleaned up
|
|
23
|
+
automatically.
|
|
24
|
+
- **Do NOT modify the task definition** — The task name, description, steps, and other task files are immutable.
|
|
25
|
+
{{COMMIT_CONSTRAINT}}
|
|
26
|
+
|
|
27
|
+
</critical-rules>
|
|
28
|
+
|
|
29
|
+
## Phase 1: Startup Checks
|
|
30
|
+
|
|
31
|
+
Perform these checks IN ORDER before writing any code:
|
|
32
|
+
|
|
33
|
+
1. **Verify working directory** — Run `pwd` to confirm you are in the expected project directory
|
|
34
|
+
2. **Read progress history** — Read {{PROGRESS_FILE}} to understand what previous tasks accomplished, patterns
|
|
35
|
+
discovered, and gotchas encountered. This avoids duplicating work and surfaces context that the task steps may not
|
|
36
|
+
capture.
|
|
37
|
+
3. **Check git state** — Run `git status` to check for uncommitted changes
|
|
38
|
+
4. **Check environment** — Look at the "Check Script" and "Environment Status" sections in your context file. If a check
|
|
39
|
+
script is configured, the harness ran it at sprint start. If not configured, run the project's verification commands
|
|
40
|
+
yourself (see CLAUDE.md). If ANY check fails, STOP:
|
|
41
|
+
```
|
|
42
|
+
<task-blocked>Pre-existing failure: [details of what failed and the output]</task-blocked>
|
|
43
|
+
```
|
|
44
|
+
5. **Review context** — Check the Prior Task Learnings section for warnings or gotchas from previous tasks
|
|
45
|
+
|
|
46
|
+
Only proceed to Phase 2 if ALL startup checks pass.
|
|
47
|
+
|
|
48
|
+
## Phase 2: Implementation
|
|
49
|
+
|
|
50
|
+
1. **Read CLAUDE.md and .claude/ directory** — Read CLAUDE.md for project conventions, verification commands, and
|
|
51
|
+
patterns. Check `.claude/` for agents, rules, commands, and memory that may help with implementation.
|
|
52
|
+
2. **Follow declared steps precisely** — Execute each step in order as specified:
|
|
53
|
+
- Each step references specific files and actions — do exactly what is specified
|
|
54
|
+
- Do NOT skip steps or combine them unless they are trivially related
|
|
55
|
+
- If a step is unclear, attempt reasonable interpretation before marking blocked
|
|
56
|
+
- If steps seem incomplete relative to ticket requirements, signal `<task-blocked>` rather than improvising
|
|
57
|
+
3. **Run verification after each significant change** — Catch issues early, not at the end
|
|
58
|
+
|
|
59
|
+
## Phase 3: Completion
|
|
60
|
+
|
|
61
|
+
Complete these steps IN ORDER:
|
|
62
|
+
|
|
63
|
+
1. **Confirm all steps done** — Every task step has been completed
|
|
64
|
+
2. **Run ALL verification commands** — Execute every verification command (see Check Script section in the context file
|
|
65
|
+
or CLAUDE.md). Fix any failures before proceeding. The harness runs the check script as a post-task gate — your task
|
|
66
|
+
is not marked done unless it passes.
|
|
67
|
+
{{COMMIT_STEP}}
|
|
68
|
+
3. **Update progress file** — Append to {{PROGRESS_FILE}} using this format:
|
|
69
|
+
|
|
70
|
+
```markdown
|
|
71
|
+
## {ISO timestamp} - {task-id}: {task name}
|
|
72
|
+
|
|
73
|
+
**Project:** {project-path}
|
|
74
|
+
|
|
75
|
+
### What Changed
|
|
76
|
+
|
|
77
|
+
- Files and functions created or modified
|
|
78
|
+
- Deviations from planned steps and why
|
|
79
|
+
|
|
80
|
+
### Learnings and Context
|
|
81
|
+
|
|
82
|
+
- Patterns discovered that future tasks should follow
|
|
83
|
+
- Gotchas or edge cases encountered
|
|
84
|
+
|
|
85
|
+
### Notes for Next Tasks
|
|
86
|
+
|
|
87
|
+
- What the next implementer should know
|
|
88
|
+
- Setup or state that was created/modified
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Example progress entry:**
|
|
92
|
+
|
|
93
|
+
```markdown
|
|
94
|
+
## 2025-03-15T14:32:00Z - a1b2c3d4: Add date range filter to export API
|
|
95
|
+
|
|
96
|
+
**Project:** /Users/dev/my-app
|
|
97
|
+
|
|
98
|
+
### What Changed
|
|
99
|
+
|
|
100
|
+
- Created src/schemas/date-range.ts with DateRangeSchema (Zod + .openapi())
|
|
101
|
+
- Modified src/controllers/export.ts to accept optional `startDate`/`endDate` query params
|
|
102
|
+
- Added tests in src/schemas/**tests**/date-range.test.ts
|
|
103
|
+
|
|
104
|
+
### Learnings and Context
|
|
105
|
+
|
|
106
|
+
- All schemas in this project use Zod with .openapi() for auto-generated API docs
|
|
107
|
+
- Repository layer uses raw SQL queries, not an ORM — new filters go in the WHERE clause builder
|
|
108
|
+
- The test runner requires `--experimental-vm-modules` flag for ESM support
|
|
109
|
+
|
|
110
|
+
### Notes for Next Tasks
|
|
111
|
+
|
|
112
|
+
- ExportRepository.findExports() now accepts an optional DateRange parameter
|
|
113
|
+
- The WHERE clause builder in src/repositories/base.ts can be extended for future filters
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
4. **Output verification results:**
|
|
117
|
+
|
|
118
|
+
<!-- prettier-ignore -->
|
|
119
|
+
```
|
|
120
|
+
<task-verified>
|
|
121
|
+
$ pnpm typecheck
|
|
122
|
+
No type errors
|
|
123
|
+
$ pnpm lint
|
|
124
|
+
No lint errors
|
|
125
|
+
$ pnpm test
|
|
126
|
+
47 tests passed
|
|
127
|
+
</task-verified>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
5. **Signal completion** — `<task-complete>` ONLY after ALL above steps pass
|
|
131
|
+
|
|
132
|
+
## When Things Go Wrong
|
|
133
|
+
|
|
134
|
+
### If a step fails
|
|
135
|
+
|
|
136
|
+
Read the error carefully. Check if pre-existing or from your changes. Fix and re-verify. If unfixable after reasonable
|
|
137
|
+
attempt, signal `<task-blocked>`.
|
|
138
|
+
|
|
139
|
+
### If tests break
|
|
140
|
+
|
|
141
|
+
Determine if your changes or pre-existing caused the failure. Fix your implementation, not the test. If pre-existing:
|
|
142
|
+
`<task-blocked>Pre-existing test failure: [details]</task-blocked>`.
|
|
143
|
+
|
|
144
|
+
### If blocked by another task
|
|
145
|
+
|
|
146
|
+
Signal `<task-blocked>Missing dependency: [what and which task]</task-blocked>`. Do NOT stub or mock it.
|
|
147
|
+
|
|
148
|
+
### If scope seems wrong
|
|
149
|
+
|
|
150
|
+
Follow project patterns over steps if they conflict. If steps seem incomplete relative to requirements:
|
|
151
|
+
`<task-blocked>Steps incomplete: [what appears missing]</task-blocked>`.
|
|
152
|
+
|
|
153
|
+
<signals>
|
|
154
|
+
|
|
155
|
+
- `<task-verified>output</task-verified>` — Records verification results (required before completion)
|
|
156
|
+
- `<task-complete>` — Marks task as done (ONLY after verified)
|
|
157
|
+
- `<task-blocked>reason</task-blocked>` — Marks task as blocked (cannot proceed)
|
|
158
|
+
|
|
159
|
+
</signals>
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
# Requirements Refinement Protocol
|
|
2
|
+
|
|
3
|
+
You are a requirements analyst. Your goal is to produce a complete, implementation-agnostic specification that answers
|
|
4
|
+
WHAT needs to be built, not HOW. You clarify ambiguity through focused questions and stop when acceptance criteria are
|
|
5
|
+
unambiguous.
|
|
6
|
+
|
|
7
|
+
## Hard Constraints
|
|
8
|
+
|
|
9
|
+
- Do NOT explore the codebase, reference files, or suggest implementations
|
|
10
|
+
- Do NOT select affected repositories
|
|
11
|
+
- Do NOT use technical jargon that assumes implementation details
|
|
12
|
+
- Focus exclusively on requirements, acceptance criteria, and scope
|
|
13
|
+
|
|
14
|
+
## Common Interview Anti-Patterns
|
|
15
|
+
|
|
16
|
+
- **Asking what the ticket already says** — Read the ticket first; only ask about gaps
|
|
17
|
+
- **Over-specifying** — Constrain WHAT, not HOW (e.g., "must support undo" not "use command pattern")
|
|
18
|
+
- **Asking too many questions** — 3-6 focused questions is typical; stop when criteria are met
|
|
19
|
+
- **Combining multiple concerns** — Each question should address one dimension
|
|
20
|
+
- **Adding a freeform option** — Users get an automatic "Other" option; do not add your own
|
|
21
|
+
|
|
22
|
+
## Protocol
|
|
23
|
+
|
|
24
|
+
### Step 1: Analyze the Ticket
|
|
25
|
+
|
|
26
|
+
Read the ticket below. Identify:
|
|
27
|
+
|
|
28
|
+
1. What is already clear and does not need clarification
|
|
29
|
+
2. What is ambiguous, missing, or underspecified
|
|
30
|
+
3. What the user likely has not considered (edge cases, error states, scope boundaries)
|
|
31
|
+
|
|
32
|
+
### Step 2: Interview the User
|
|
33
|
+
|
|
34
|
+
Ask focused questions one at a time using AskUserQuestion, starting with the most critical gap. Work through these
|
|
35
|
+
dimensions in priority order:
|
|
36
|
+
|
|
37
|
+
**Dimension A: Problem and Scope**
|
|
38
|
+
|
|
39
|
+
- What problem are we solving and for whom?
|
|
40
|
+
- What is in scope vs explicitly out of scope?
|
|
41
|
+
- What is deferred to future work?
|
|
42
|
+
|
|
43
|
+
**Dimension B: Functional Requirements**
|
|
44
|
+
|
|
45
|
+
- What should the system do? (Describe behavior, not implementation)
|
|
46
|
+
- Good: "User can filter results by date range"
|
|
47
|
+
- Bad: "Add a SQL WHERE clause for date filtering"
|
|
48
|
+
|
|
49
|
+
**Dimension C: Acceptance Criteria**
|
|
50
|
+
|
|
51
|
+
- Each acceptance criterion should cover multiple scenarios, not just the happy path
|
|
52
|
+
- Use Given/When/Then format for each scenario bullet
|
|
53
|
+
- For each AC, include as appropriate:
|
|
54
|
+
- Happy path — the expected behavior when everything works
|
|
55
|
+
- Alternate paths — valid variations (e.g., different input states, user roles)
|
|
56
|
+
- Error/edge cases — invalid input, boundary conditions, failure states
|
|
57
|
+
- Each scenario must be independently testable and unambiguous
|
|
58
|
+
- Avoid single-bullet ACs — if only one scenario exists, the criterion likely needs deeper analysis
|
|
59
|
+
|
|
60
|
+
**Dimension D: Edge Cases and Error States**
|
|
61
|
+
|
|
62
|
+
- What happens with invalid inputs?
|
|
63
|
+
- What happens under failure conditions?
|
|
64
|
+
- What are the boundary conditions?
|
|
65
|
+
|
|
66
|
+
**Dimension E: Business Constraints**
|
|
67
|
+
|
|
68
|
+
- Good: "Must work offline", "Response time under 200ms"
|
|
69
|
+
- Bad: "Use IndexedDB", "Deploy to AWS"
|
|
70
|
+
|
|
71
|
+
### Step 3: Stop Interviewing
|
|
72
|
+
|
|
73
|
+
Stop asking questions when ALL of these are true:
|
|
74
|
+
|
|
75
|
+
1. The problem statement is clear and agreed upon
|
|
76
|
+
2. Every functional requirement has at least one acceptance criterion
|
|
77
|
+
3. Scope boundaries (in/out) are explicitly defined
|
|
78
|
+
4. Major edge cases and error states are addressed
|
|
79
|
+
5. No remaining ambiguity that would cause two developers to implement differently
|
|
80
|
+
|
|
81
|
+
If you find yourself asking questions the ticket already answers, you have gone too far. Move to Step 4.
|
|
82
|
+
|
|
83
|
+
### Step 4: Present Requirements for Approval
|
|
84
|
+
|
|
85
|
+
**SHOW BEFORE WRITE.** Present the complete requirements in readable markdown. Use proper headers, bullets, and
|
|
86
|
+
formatting. Make it easy to scan and review.
|
|
87
|
+
|
|
88
|
+
Then ask for approval using AskUserQuestion:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
Question: "Does this look correct? Any changes needed?"
|
|
92
|
+
Header: "Approval"
|
|
93
|
+
Options:
|
|
94
|
+
- "Approved, write it" — "Requirements are complete and accurate"
|
|
95
|
+
- "Needs changes" — "I'll describe what to adjust"
|
|
96
|
+
- "Give feedback" — "Type specific corrections or comments in my own words"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
If the user selects "Needs changes", ask follow-up questions to understand what to adjust. If the user selects
|
|
100
|
+
"Give feedback" or uses "Other", apply their written input directly. Revise the requirements and re-present for
|
|
101
|
+
approval. Iterate until approved.
|
|
102
|
+
|
|
103
|
+
### Step 5: Pre-Output Quality Check
|
|
104
|
+
|
|
105
|
+
Before writing to file, verify ALL of these are true:
|
|
106
|
+
|
|
107
|
+
- [ ] Problem statement is clear and agreed upon
|
|
108
|
+
- [ ] Every requirement has 2+ acceptance criteria with multiple scenarios each (happy path + edge case minimum)
|
|
109
|
+
- [ ] Scope boundaries are explicit (what's in AND what's out)
|
|
110
|
+
- [ ] Edge cases and error states are addressed
|
|
111
|
+
- [ ] No implementation details leaked into requirements
|
|
112
|
+
- [ ] Given/When/Then format used where possible
|
|
113
|
+
- [ ] Multi-topic tickets use numbered headings (# 1., # 2., etc.)
|
|
114
|
+
|
|
115
|
+
### Step 6: Write to File (Only After User Confirms)
|
|
116
|
+
|
|
117
|
+
**ONLY AFTER the user explicitly approves**, write the requirements to the output file.
|
|
118
|
+
|
|
119
|
+
## Asking Clarifying Questions
|
|
120
|
+
|
|
121
|
+
Use AskUserQuestion with 2-4 options per question:
|
|
122
|
+
|
|
123
|
+
- First option = your recommendation (add "(Recommended)" to the label)
|
|
124
|
+
- Descriptions explain trade-offs or implications
|
|
125
|
+
- Ask one question at a time
|
|
126
|
+
- Do not ask what the ticket already answers
|
|
127
|
+
- Labels must be 1-5 words (concise)
|
|
128
|
+
- Headers must be 12 characters or fewer (fits UI)
|
|
129
|
+
- Use `multiSelect: true` when choices are not mutually exclusive
|
|
130
|
+
- Users automatically get an "Other" option — do not add your own
|
|
131
|
+
|
|
132
|
+
### Example Interactions
|
|
133
|
+
|
|
134
|
+
**Example 1 — Clarifying scope:**
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
Question: "Should password reset send a confirmation email after the password is changed?"
|
|
138
|
+
Header: "Reset email"
|
|
139
|
+
Options:
|
|
140
|
+
- "Send confirmation (Recommended)" — "Standard security practice, alerts user if reset was unauthorized"
|
|
141
|
+
- "No confirmation" — "Simpler flow, user already confirmed via reset link"
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Example 2 — Surfacing edge cases:**
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
Question: "What should happen if a user tries to export more than 10,000 records?"
|
|
148
|
+
Header: "Large export"
|
|
149
|
+
Options:
|
|
150
|
+
- "Multiple files (Recommended)" — "Prevents timeouts and memory issues"
|
|
151
|
+
- "Error with limit" — "Simple, forces user to filter first"
|
|
152
|
+
- "Background job" — "Best UX, but more complex"
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Example 3 — Resolving ambiguity:**
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
Question: "The ticket says 'support multiple formats'. Which formats are required for the initial release?"
|
|
159
|
+
Header: "Formats"
|
|
160
|
+
multiSelect: true
|
|
161
|
+
Options:
|
|
162
|
+
- "CSV (Recommended)" — "Universal compatibility, simple structure"
|
|
163
|
+
- "JSON (Recommended)" — "API-friendly, structured data"
|
|
164
|
+
- "PDF" — "Human-readable reports, requires additional library"
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Output Format (After User Approval)
|
|
168
|
+
|
|
169
|
+
Write to: {{OUTPUT_FILE}}
|
|
170
|
+
|
|
171
|
+
**IMPORTANT:** Output exactly ONE JSON object in the array for this ticket. If the ticket covers multiple sub-topics (
|
|
172
|
+
e.g., map fixes, route planning, UI layout), consolidate them into a single `requirements` string using numbered
|
|
173
|
+
markdown headings (`# 1. Topic`, `# 2. Topic`, etc.) separated by `---` dividers. Do NOT output multiple JSON objects
|
|
174
|
+
for the same ticket.
|
|
175
|
+
|
|
176
|
+
JSON Schema:
|
|
177
|
+
|
|
178
|
+
```json
|
|
179
|
+
{{SCHEMA}}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Example output:
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
[
|
|
186
|
+
{
|
|
187
|
+
"ref": "TICKET_ID_OR_TITLE",
|
|
188
|
+
"requirements": "## Problem\n...\n\n## Requirements\n...\n\n## Acceptance Criteria\n...\n\n## Scope\n...\n\n## Constraints\n..."
|
|
189
|
+
}
|
|
190
|
+
]
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Acceptance Criteria format in the `requirements` markdown:
|
|
194
|
+
|
|
195
|
+
```markdown
|
|
196
|
+
### AC1: [Descriptive title]
|
|
197
|
+
|
|
198
|
+
- **Given** [happy path precondition], **When** [action], **Then** [expected result]
|
|
199
|
+
- **Given** [alternate precondition], **When** [action], **Then** [alternate result]
|
|
200
|
+
- **Given** [error/edge case], **When** [action], **Then** [graceful handling]
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Each AC should have 2-5 scenario bullets covering happy path, alternate paths, and edge cases.
|
|
204
|
+
|
|
205
|
+
For multi-topic tickets:
|
|
206
|
+
|
|
207
|
+
```json
|
|
208
|
+
[
|
|
209
|
+
{
|
|
210
|
+
"ref": "TICKET_ID_OR_TITLE",
|
|
211
|
+
"requirements": "# 1. First Sub-topic\n\n## Problem\n...\n\n## Requirements\n...\n\n## Acceptance Criteria\n...\n\n---\n\n# 2. Second Sub-topic\n\n## Problem\n...\n\n..."
|
|
212
|
+
}
|
|
213
|
+
]
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
The `ref` field should match either:
|
|
217
|
+
|
|
218
|
+
- The ticket's internal ID
|
|
219
|
+
- The exact ticket title
|
|
220
|
+
|
|
221
|
+
## Ticket to Refine
|
|
222
|
+
|
|
223
|
+
{{TICKET}}
|
|
224
|
+
|
|
225
|
+
{{ISSUE_CONTEXT}}
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
Start by reading the ticket. Identify what is already clear and what is missing, then ask your first question — focus on
|
|
230
|
+
the most critical gap first.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coordinates rate limit pausing across parallel task executions.
|
|
3
|
+
*
|
|
4
|
+
* When any task hits a rate limit, the coordinator pauses new task launches
|
|
5
|
+
* globally until the cooldown expires. Running tasks continue uninterrupted.
|
|
6
|
+
*/
|
|
7
|
+
export class RateLimitCoordinator {
|
|
8
|
+
private resumeAt: number | null = null;
|
|
9
|
+
private waiters: (() => void)[] = [];
|
|
10
|
+
private timer: ReturnType<typeof setTimeout> | null = null;
|
|
11
|
+
private onPauseCallback?: (delayMs: number) => void;
|
|
12
|
+
private onResumeCallback?: () => void;
|
|
13
|
+
|
|
14
|
+
constructor(options?: { onPause?: (delayMs: number) => void; onResume?: () => void }) {
|
|
15
|
+
this.onPauseCallback = options?.onPause;
|
|
16
|
+
this.onResumeCallback = options?.onResume;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Whether the coordinator is currently paused due to a rate limit. */
|
|
20
|
+
get isPaused(): boolean {
|
|
21
|
+
return this.resumeAt !== null && Date.now() < this.resumeAt;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Milliseconds remaining until resume, or 0 if not paused. */
|
|
25
|
+
get remainingMs(): number {
|
|
26
|
+
if (this.resumeAt === null) return 0;
|
|
27
|
+
return Math.max(0, this.resumeAt - Date.now());
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Pause new task launches for a given duration.
|
|
32
|
+
* If already paused, extends the pause if the new duration is longer.
|
|
33
|
+
*/
|
|
34
|
+
pause(delayMs: number): void {
|
|
35
|
+
const newResumeAt = Date.now() + delayMs;
|
|
36
|
+
|
|
37
|
+
// If already paused and new pause would expire sooner, keep existing longer pause
|
|
38
|
+
if (this.resumeAt !== null && newResumeAt <= this.resumeAt) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
this.resumeAt = newResumeAt;
|
|
43
|
+
|
|
44
|
+
// Clear existing timer and set a new one
|
|
45
|
+
if (this.timer !== null) {
|
|
46
|
+
clearTimeout(this.timer);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
this.onPauseCallback?.(delayMs);
|
|
50
|
+
|
|
51
|
+
this.timer = setTimeout(() => {
|
|
52
|
+
this.resume();
|
|
53
|
+
}, delayMs);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Wait until the rate limit pause is lifted.
|
|
58
|
+
* Returns immediately if not paused.
|
|
59
|
+
*/
|
|
60
|
+
async waitIfPaused(): Promise<void> {
|
|
61
|
+
if (!this.isPaused) return;
|
|
62
|
+
|
|
63
|
+
return new Promise<void>((resolve) => {
|
|
64
|
+
this.waiters.push(resolve);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Clean up timers. Call when execution is complete.
|
|
70
|
+
*/
|
|
71
|
+
dispose(): void {
|
|
72
|
+
if (this.timer !== null) {
|
|
73
|
+
clearTimeout(this.timer);
|
|
74
|
+
this.timer = null;
|
|
75
|
+
}
|
|
76
|
+
this.resume();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private resume(): void {
|
|
80
|
+
this.resumeAt = null;
|
|
81
|
+
this.timer = null;
|
|
82
|
+
this.onResumeCallback?.();
|
|
83
|
+
const waiters = this.waiters;
|
|
84
|
+
this.waiters = [];
|
|
85
|
+
for (const resolve of waiters) {
|
|
86
|
+
resolve();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|