@jahanxu/trellis 0.4.1 → 0.5.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/dist/configurators/workflow.d.ts.map +1 -1
- package/dist/configurators/workflow.js +58 -1
- package/dist/configurators/workflow.js.map +1 -1
- package/dist/constants/paths.d.ts +17 -0
- package/dist/constants/paths.d.ts.map +1 -1
- package/dist/constants/paths.js +19 -0
- package/dist/constants/paths.js.map +1 -1
- package/dist/templates/claude/commands/trellis/handoff.md +90 -387
- package/dist/templates/claude/commands/trellis/pick-task.md +74 -444
- package/dist/templates/claude/hooks/inject-subagent-context.py +17 -101
- package/dist/templates/claude/hooks/ralph-loop.py +1 -0
- package/dist/templates/claude/hooks/session-start.py +170 -54
- package/dist/templates/iflow/commands/trellis/handoff.md +148 -0
- package/dist/templates/iflow/commands/trellis/pick-task.md +145 -0
- package/dist/templates/iflow/hooks/inject-subagent-context.py +1 -0
- package/dist/templates/iflow/hooks/ralph-loop.py +1 -0
- package/dist/templates/iflow/hooks/session-start.py +171 -0
- package/dist/templates/markdown/index.d.ts +9 -0
- package/dist/templates/markdown/index.d.ts.map +1 -1
- package/dist/templates/markdown/index.js +10 -0
- package/dist/templates/markdown/index.js.map +1 -1
- package/dist/templates/markdown/spec/roles/designer/index.md.txt +57 -0
- package/dist/templates/markdown/spec/roles/designer/mock-data-standards.md.txt +63 -0
- package/dist/templates/markdown/spec/roles/designer/prototype-guidelines.md.txt +49 -0
- package/dist/templates/markdown/spec/roles/frontend-impl/api-integration.md.txt +63 -0
- package/dist/templates/markdown/spec/roles/frontend-impl/index.md.txt +57 -0
- package/dist/templates/markdown/spec/roles/frontend-impl/prototype-to-production.md.txt +57 -0
- package/dist/templates/markdown/spec/roles/pm/index.md.txt +45 -0
- package/dist/templates/markdown/spec/roles/pm/prd-template.md.txt +64 -0
- package/dist/templates/markdown/spec/roles/pm/requirement-checklist.md.txt +43 -0
- package/dist/templates/trellis/index.d.ts +1 -0
- package/dist/templates/trellis/index.d.ts.map +1 -1
- package/dist/templates/trellis/index.js +2 -0
- package/dist/templates/trellis/index.js.map +1 -1
- package/dist/templates/trellis/scripts/add_session.py +3 -2
- package/dist/templates/trellis/scripts/common/cli_adapter.py +4 -3
- package/dist/templates/trellis/scripts/common/developer.py +4 -3
- package/dist/templates/trellis/scripts/common/git_context.py +7 -7
- package/dist/templates/trellis/scripts/common/paths.py +64 -14
- package/dist/templates/trellis/scripts/common/phase.py +2 -2
- package/dist/templates/trellis/scripts/common/registry.py +16 -15
- package/dist/templates/trellis/scripts/common/task_queue.py +10 -10
- package/dist/templates/trellis/scripts/common/task_utils.py +5 -4
- package/dist/templates/trellis/scripts/common/worktree.py +8 -7
- package/dist/templates/trellis/scripts/pool.py +214 -265
- package/dist/templates/trellis/scripts/task.py +3 -116
- package/package.json +3 -3
- package/dist/templates/claude/commands/trellis/before-role-work.md +0 -364
- package/dist/templates/trellis/VERSION +0 -1
- package/dist/templates/trellis/deliverables/README.md +0 -51
- package/dist/templates/trellis/paths.README.md +0 -277
- package/dist/templates/trellis/paths.yaml +0 -41
- package/dist/templates/trellis/pool/implementations.json +0 -5
- package/dist/templates/trellis/pool/prototypes.json +0 -5
- package/dist/templates/trellis/pool/requirements.json +0 -5
- package/dist/templates/trellis/scripts/common/project_paths.py +0 -189
- package/dist/templates/trellis/scripts/handoff_generator.py +0 -380
- package/dist/templates/trellis/spec/roles/designer/index.md +0 -243
- package/dist/templates/trellis/spec/roles/designer/mock-data-standards.md +0 -481
- package/dist/templates/trellis/spec/roles/designer/prototype-guidelines.md +0 -429
- package/dist/templates/trellis/spec/roles/frontend-impl/api-integration.md +0 -565
- package/dist/templates/trellis/spec/roles/frontend-impl/index.md +0 -321
- package/dist/templates/trellis/spec/roles/frontend-impl/state-management.md +0 -599
- package/dist/templates/trellis/spec/roles/pm/index.md +0 -112
- package/dist/templates/trellis/spec/roles/pm/prd-template.md +0 -124
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Pick Task - Select Upstream Deliverable and Start Working
|
|
2
|
+
|
|
3
|
+
Pick a deliverable from an upstream pool, create a task directory, and inject upstream context.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
/trellis:pick-task <pool> <id>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
- `<pool>`: `requirements` (for Designers) or `prototypes` (for Frontend)
|
|
14
|
+
- `<id>`: deliverable ID to pick (e.g., `user-login`)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Process `[AI]`
|
|
19
|
+
|
|
20
|
+
### Step 1: Validate Role
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
python3 ./.trellis/scripts/get_context.py
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Read the developer name from `.developer` file. Parse role from `{role}-{name}` convention.
|
|
27
|
+
|
|
28
|
+
Validate role-pool match:
|
|
29
|
+
- `designer` can pick from `requirements`
|
|
30
|
+
- `frontend` / `frontend-impl` can pick from `prototypes`
|
|
31
|
+
- `pm` should NOT pick from pools (PMs create tasks directly)
|
|
32
|
+
|
|
33
|
+
If role cannot be parsed, warn but continue (soft detection).
|
|
34
|
+
|
|
35
|
+
### Step 2: Check Pool Availability
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
python3 ./.trellis/scripts/pool.py status <pool> <id>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Verify the item:
|
|
42
|
+
- Exists in the pool
|
|
43
|
+
- Status is `available` (not `consumed`)
|
|
44
|
+
|
|
45
|
+
If not available, list what IS available:
|
|
46
|
+
```bash
|
|
47
|
+
python3 ./.trellis/scripts/pool.py list <pool>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Step 3: Check Current Task
|
|
51
|
+
|
|
52
|
+
If there is already a current task set, ask:
|
|
53
|
+
> "You have an active task: `<current-task>`. Would you like to finish it first, or switch to the new task?"
|
|
54
|
+
|
|
55
|
+
If user wants to continue, proceed.
|
|
56
|
+
|
|
57
|
+
### Step 4: Create Task Directory
|
|
58
|
+
|
|
59
|
+
Determine task suffix based on pool:
|
|
60
|
+
- `requirements` pool -> `{id}-prototype`
|
|
61
|
+
- `prototypes` pool -> `{id}-impl`
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
TASK_DIR=$(python3 ./.trellis/scripts/task.py create "<title>" --slug <id>-<suffix>)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Step 5: Write source.json
|
|
68
|
+
|
|
69
|
+
Create `source.json` in the task directory to reference upstream:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"based_on": {
|
|
74
|
+
"type": "<requirement|prototype>",
|
|
75
|
+
"id": "<id>",
|
|
76
|
+
"path": "<deliverable path>",
|
|
77
|
+
"handoff_doc": "<path>/HANDOFF.md"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Write this file:
|
|
83
|
+
```bash
|
|
84
|
+
cat > "$TASK_DIR/source.json" << 'EOF'
|
|
85
|
+
{content}
|
|
86
|
+
EOF
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Step 6: Configure Context (JSONL)
|
|
90
|
+
|
|
91
|
+
Initialize context files for the task:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
python3 ./.trellis/scripts/task.py init-context "$TASK_DIR" frontend
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Add upstream deliverable files and role specs to context:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Add role spec
|
|
101
|
+
python3 ./.trellis/scripts/task.py add-context "$TASK_DIR" implement ".trellis/spec/roles/<role>/index.md" "Role guidelines"
|
|
102
|
+
|
|
103
|
+
# Add upstream HANDOFF doc
|
|
104
|
+
python3 ./.trellis/scripts/task.py add-context "$TASK_DIR" implement "<handoff_doc>" "Upstream handoff document"
|
|
105
|
+
|
|
106
|
+
# Add upstream deliverable directory files
|
|
107
|
+
# (add each significant file from the upstream output)
|
|
108
|
+
python3 ./.trellis/scripts/task.py add-context "$TASK_DIR" implement "<upstream_file>" "Upstream deliverable"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Step 7: Consume from Pool
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
python3 ./.trellis/scripts/pool.py consume <pool> <id> <developer>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Step 8: Activate Task
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
python3 ./.trellis/scripts/task.py start "$TASK_DIR"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Step 9: Read Upstream Context
|
|
124
|
+
|
|
125
|
+
Read and summarize the upstream deliverables for the user:
|
|
126
|
+
|
|
127
|
+
1. Read the HANDOFF.md document
|
|
128
|
+
2. List all upstream files
|
|
129
|
+
3. Summarize key points the user should know
|
|
130
|
+
|
|
131
|
+
### Step 10: Report
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
Task picked and ready!
|
|
135
|
+
- Task: <task-dir>
|
|
136
|
+
- Based on: <pool>/<id>
|
|
137
|
+
- Upstream: <deliverable-path>
|
|
138
|
+
- Role specs loaded: .trellis/spec/roles/<role>/
|
|
139
|
+
|
|
140
|
+
Key points from upstream HANDOFF:
|
|
141
|
+
- (summary point 1)
|
|
142
|
+
- (summary point 2)
|
|
143
|
+
|
|
144
|
+
What would you like to work on first?
|
|
145
|
+
```
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"""
|
|
4
4
|
Session Start Hook - Inject structured context
|
|
5
5
|
"""
|
|
6
|
+
from __future__ import annotations
|
|
6
7
|
|
|
7
8
|
# IMPORTANT: Suppress all warnings FIRST
|
|
8
9
|
import warnings
|
|
@@ -65,6 +66,166 @@ def run_script(script_path: Path) -> str:
|
|
|
65
66
|
return "No context available"
|
|
66
67
|
|
|
67
68
|
|
|
69
|
+
def detect_role(trellis_dir: Path) -> str | None:
|
|
70
|
+
"""Detect role from developer name ({role}-{name} convention)."""
|
|
71
|
+
dev_file = trellis_dir / ".developer"
|
|
72
|
+
if not dev_file.is_file():
|
|
73
|
+
return None
|
|
74
|
+
try:
|
|
75
|
+
content = dev_file.read_text(encoding="utf-8")
|
|
76
|
+
for line in content.splitlines():
|
|
77
|
+
if line.startswith("name="):
|
|
78
|
+
name = line.split("=", 1)[1].strip()
|
|
79
|
+
if "-" in name:
|
|
80
|
+
role = name.split("-", 1)[0]
|
|
81
|
+
if role in ("pm", "designer", "frontend", "frontend-impl"):
|
|
82
|
+
return role
|
|
83
|
+
except (OSError, IOError):
|
|
84
|
+
pass
|
|
85
|
+
return None
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def inject_upstream_context(trellis_dir: Path, project_dir: Path, output: StringIO) -> None:
|
|
89
|
+
"""Inject upstream context when source.json exists in current task."""
|
|
90
|
+
current_task_file = trellis_dir / ".current-task"
|
|
91
|
+
if not current_task_file.is_file():
|
|
92
|
+
return
|
|
93
|
+
|
|
94
|
+
try:
|
|
95
|
+
task_rel = current_task_file.read_text(encoding="utf-8").strip()
|
|
96
|
+
except (OSError, IOError):
|
|
97
|
+
return
|
|
98
|
+
|
|
99
|
+
if not task_rel:
|
|
100
|
+
return
|
|
101
|
+
|
|
102
|
+
task_dir = project_dir / task_rel
|
|
103
|
+
source_file = task_dir / "source.json"
|
|
104
|
+
if not source_file.is_file():
|
|
105
|
+
return
|
|
106
|
+
|
|
107
|
+
try:
|
|
108
|
+
source = json.loads(source_file.read_text(encoding="utf-8"))
|
|
109
|
+
except (json.JSONDecodeError, OSError):
|
|
110
|
+
return
|
|
111
|
+
|
|
112
|
+
based_on = source.get("based_on")
|
|
113
|
+
if not based_on:
|
|
114
|
+
return
|
|
115
|
+
|
|
116
|
+
output.write("<upstream-context>\n")
|
|
117
|
+
output.write("## Based on Upstream Deliverable\n")
|
|
118
|
+
output.write(f"- Type: {based_on.get('type', '?')}\n")
|
|
119
|
+
output.write(f"- ID: {based_on.get('id', '?')}\n")
|
|
120
|
+
output.write(f"- Path: {based_on.get('path', '?')}\n\n")
|
|
121
|
+
|
|
122
|
+
handoff_path = project_dir / based_on.get("handoff_doc", "")
|
|
123
|
+
if handoff_path.is_file():
|
|
124
|
+
output.write("### Handoff Document\n")
|
|
125
|
+
handoff_content = read_file(handoff_path)
|
|
126
|
+
if len(handoff_content) > 3000:
|
|
127
|
+
handoff_content = handoff_content[:3000] + "\n... (truncated)"
|
|
128
|
+
output.write(handoff_content)
|
|
129
|
+
output.write("\n\n")
|
|
130
|
+
|
|
131
|
+
source_path = project_dir / based_on.get("path", "")
|
|
132
|
+
if source_path.is_dir():
|
|
133
|
+
output.write("### Upstream Deliverable Files\n")
|
|
134
|
+
total_size = 0
|
|
135
|
+
text_exts = {".md", ".txt", ".tsx", ".ts", ".jsx", ".js", ".vue", ".css", ".json", ".yaml", ".yml", ".html"}
|
|
136
|
+
for fpath in sorted(source_path.rglob("*")):
|
|
137
|
+
if not fpath.is_file():
|
|
138
|
+
continue
|
|
139
|
+
if fpath.name == "HANDOFF.md":
|
|
140
|
+
continue
|
|
141
|
+
if fpath.suffix not in text_exts:
|
|
142
|
+
continue
|
|
143
|
+
if total_size >= 50000:
|
|
144
|
+
output.write("\n(total size cap reached, remaining files omitted)\n")
|
|
145
|
+
break
|
|
146
|
+
try:
|
|
147
|
+
content = fpath.read_text(encoding="utf-8")
|
|
148
|
+
except (OSError, UnicodeDecodeError):
|
|
149
|
+
continue
|
|
150
|
+
rel = fpath.relative_to(source_path)
|
|
151
|
+
output.write(f"\n#### {rel}\n")
|
|
152
|
+
ext = fpath.suffix[1:] if fpath.suffix else ""
|
|
153
|
+
if len(content) > 3000:
|
|
154
|
+
content = content[:3000] + "\n... (truncated)"
|
|
155
|
+
output.write(f"```{ext}\n{content}\n```\n")
|
|
156
|
+
total_size += len(content)
|
|
157
|
+
|
|
158
|
+
output.write("</upstream-context>\n\n")
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def inject_pool_summary(trellis_dir: Path, output: StringIO) -> None:
|
|
162
|
+
"""Inject available tasks summary from pool files."""
|
|
163
|
+
pool_dir = trellis_dir / "pool"
|
|
164
|
+
if not pool_dir.is_dir():
|
|
165
|
+
return
|
|
166
|
+
|
|
167
|
+
pool_files = sorted(pool_dir.glob("*.json"))
|
|
168
|
+
if not pool_files:
|
|
169
|
+
return
|
|
170
|
+
|
|
171
|
+
has_available = False
|
|
172
|
+
pool_output = StringIO()
|
|
173
|
+
|
|
174
|
+
for pool_file in pool_files:
|
|
175
|
+
try:
|
|
176
|
+
data = json.loads(pool_file.read_text(encoding="utf-8"))
|
|
177
|
+
except (json.JSONDecodeError, OSError):
|
|
178
|
+
continue
|
|
179
|
+
|
|
180
|
+
available = [
|
|
181
|
+
i for i in data.get("available", [])
|
|
182
|
+
if i.get("status") == "available"
|
|
183
|
+
]
|
|
184
|
+
if not available:
|
|
185
|
+
continue
|
|
186
|
+
|
|
187
|
+
has_available = True
|
|
188
|
+
pool_name = pool_file.stem
|
|
189
|
+
pool_output.write(f"## Available in {pool_name} ({len(available)})\n")
|
|
190
|
+
for item in available:
|
|
191
|
+
completed_by = item.get("completed_by", "?")
|
|
192
|
+
completed_at = item.get("completed_at", "?")
|
|
193
|
+
pool_output.write(
|
|
194
|
+
f"- {item.get('id', '?')}: {item.get('title', '?')} "
|
|
195
|
+
f"(by {completed_by}, {completed_at})\n"
|
|
196
|
+
)
|
|
197
|
+
pool_output.write("\n")
|
|
198
|
+
|
|
199
|
+
if has_available:
|
|
200
|
+
output.write("<available-tasks>\n")
|
|
201
|
+
output.write(pool_output.getvalue())
|
|
202
|
+
output.write("Use `/trellis:pick-task <pool> <id>` to start working on an available item.\n")
|
|
203
|
+
output.write("</available-tasks>\n\n")
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def inject_role_guidelines(trellis_dir: Path, role: str | None, output: StringIO) -> None:
|
|
207
|
+
"""Inject role-specific guidelines if role is detected."""
|
|
208
|
+
if not role:
|
|
209
|
+
return
|
|
210
|
+
|
|
211
|
+
role_dir_map = {
|
|
212
|
+
"pm": "pm",
|
|
213
|
+
"designer": "designer",
|
|
214
|
+
"frontend": "frontend-impl",
|
|
215
|
+
"frontend-impl": "frontend-impl",
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
role_dir = role_dir_map.get(role)
|
|
219
|
+
if not role_dir:
|
|
220
|
+
return
|
|
221
|
+
|
|
222
|
+
role_index = trellis_dir / "spec" / "roles" / role_dir / "index.md"
|
|
223
|
+
if role_index.is_file():
|
|
224
|
+
output.write(f"## Role: {role}\n")
|
|
225
|
+
output.write(read_file(role_index))
|
|
226
|
+
output.write("\n\n")
|
|
227
|
+
|
|
228
|
+
|
|
68
229
|
def main():
|
|
69
230
|
if should_skip_injection():
|
|
70
231
|
sys.exit(0)
|
|
@@ -95,6 +256,10 @@ Read and follow all instructions below carefully.
|
|
|
95
256
|
|
|
96
257
|
output.write("<guidelines>\n")
|
|
97
258
|
|
|
259
|
+
# Detect role and inject role-specific guidelines
|
|
260
|
+
role = detect_role(trellis_dir)
|
|
261
|
+
inject_role_guidelines(trellis_dir, role, output)
|
|
262
|
+
|
|
98
263
|
output.write("## Frontend\n")
|
|
99
264
|
frontend_index = read_file(
|
|
100
265
|
trellis_dir / "spec" / "frontend" / "index.md", "Not configured"
|
|
@@ -117,6 +282,12 @@ Read and follow all instructions below carefully.
|
|
|
117
282
|
|
|
118
283
|
output.write("\n</guidelines>\n\n")
|
|
119
284
|
|
|
285
|
+
# Inject upstream context (from source.json in current task)
|
|
286
|
+
inject_upstream_context(trellis_dir, project_dir, output)
|
|
287
|
+
|
|
288
|
+
# Inject pool summary (available tasks)
|
|
289
|
+
inject_pool_summary(trellis_dir, output)
|
|
290
|
+
|
|
120
291
|
output.write("<instructions>\n")
|
|
121
292
|
start_md = read_file(
|
|
122
293
|
iflow_dir / "commands" / "trellis" / "start.md", "No start.md found"
|
|
@@ -24,4 +24,13 @@ export declare const frontendStateManagementContent: string;
|
|
|
24
24
|
export declare const guidesIndexContent: string;
|
|
25
25
|
export declare const guidesCrossLayerThinkingGuideContent: string;
|
|
26
26
|
export declare const guidesCodeReuseThinkingGuideContent: string;
|
|
27
|
+
export declare const rolePmIndexContent: string;
|
|
28
|
+
export declare const rolePmPrdTemplateContent: string;
|
|
29
|
+
export declare const rolePmRequirementChecklistContent: string;
|
|
30
|
+
export declare const roleDesignerIndexContent: string;
|
|
31
|
+
export declare const roleDesignerPrototypeGuidelinesContent: string;
|
|
32
|
+
export declare const roleDesignerMockDataStandardsContent: string;
|
|
33
|
+
export declare const roleFrontendImplIndexContent: string;
|
|
34
|
+
export declare const roleFrontendImplApiIntegrationContent: string;
|
|
35
|
+
export declare const roleFrontendImplPrototypeToProductionContent: string;
|
|
27
36
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/markdown/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAqBH,eAAO,MAAM,eAAe,EAAE,MAAuC,CAAC;AAGtE,eAAO,MAAM,qBAAqB,EAAE,MACK,CAAC;AAG1C,eAAO,MAAM,yBAAyB,QAAwB,CAAC;AAG/D,eAAO,MAAM,wBAAwB,EAAE,MACH,CAAC;AAQrC,eAAO,MAAM,mBAAmB,EAAE,MAEjC,CAAC;AACF,eAAO,MAAM,gCAAgC,EAAE,MAE9C,CAAC;AACF,eAAO,MAAM,gCAAgC,EAAE,MAE9C,CAAC;AACF,eAAO,MAAM,+BAA+B,EAAE,MAE7C,CAAC;AACF,eAAO,MAAM,+BAA+B,EAAE,MAE7C,CAAC;AACF,eAAO,MAAM,2BAA2B,EAAE,MAEzC,CAAC;AAGF,eAAO,MAAM,oBAAoB,EAAE,MAElC,CAAC;AACF,eAAO,MAAM,iCAAiC,EAAE,MAE/C,CAAC;AACF,eAAO,MAAM,yBAAyB,EAAE,MAEvC,CAAC;AACF,eAAO,MAAM,6BAA6B,EAAE,MAE3C,CAAC;AACF,eAAO,MAAM,kCAAkC,EAAE,MAEhD,CAAC;AACF,eAAO,MAAM,gCAAgC,EAAE,MAE9C,CAAC;AACF,eAAO,MAAM,8BAA8B,EAAE,MAE5C,CAAC;AAGF,eAAO,MAAM,kBAAkB,EAAE,MAEhC,CAAC;AACF,eAAO,MAAM,oCAAoC,EAAE,MAElD,CAAC;AACF,eAAO,MAAM,mCAAmC,EAAE,MAEjD,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/markdown/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAqBH,eAAO,MAAM,eAAe,EAAE,MAAuC,CAAC;AAGtE,eAAO,MAAM,qBAAqB,EAAE,MACK,CAAC;AAG1C,eAAO,MAAM,yBAAyB,QAAwB,CAAC;AAG/D,eAAO,MAAM,wBAAwB,EAAE,MACH,CAAC;AAQrC,eAAO,MAAM,mBAAmB,EAAE,MAEjC,CAAC;AACF,eAAO,MAAM,gCAAgC,EAAE,MAE9C,CAAC;AACF,eAAO,MAAM,gCAAgC,EAAE,MAE9C,CAAC;AACF,eAAO,MAAM,+BAA+B,EAAE,MAE7C,CAAC;AACF,eAAO,MAAM,+BAA+B,EAAE,MAE7C,CAAC;AACF,eAAO,MAAM,2BAA2B,EAAE,MAEzC,CAAC;AAGF,eAAO,MAAM,oBAAoB,EAAE,MAElC,CAAC;AACF,eAAO,MAAM,iCAAiC,EAAE,MAE/C,CAAC;AACF,eAAO,MAAM,yBAAyB,EAAE,MAEvC,CAAC;AACF,eAAO,MAAM,6BAA6B,EAAE,MAE3C,CAAC;AACF,eAAO,MAAM,kCAAkC,EAAE,MAEhD,CAAC;AACF,eAAO,MAAM,gCAAgC,EAAE,MAE9C,CAAC;AACF,eAAO,MAAM,8BAA8B,EAAE,MAE5C,CAAC;AAGF,eAAO,MAAM,kBAAkB,EAAE,MAEhC,CAAC;AACF,eAAO,MAAM,oCAAoC,EAAE,MAElD,CAAC;AACF,eAAO,MAAM,mCAAmC,EAAE,MAEjD,CAAC;AAGF,eAAO,MAAM,kBAAkB,EAAE,MAEhC,CAAC;AACF,eAAO,MAAM,wBAAwB,EAAE,MAEtC,CAAC;AACF,eAAO,MAAM,iCAAiC,EAAE,MAE/C,CAAC;AACF,eAAO,MAAM,wBAAwB,EAAE,MAEtC,CAAC;AACF,eAAO,MAAM,sCAAsC,EAAE,MAEpD,CAAC;AACF,eAAO,MAAM,oCAAoC,EAAE,MAElD,CAAC;AACF,eAAO,MAAM,4BAA4B,EAAE,MAE1C,CAAC;AACF,eAAO,MAAM,qCAAqC,EAAE,MAEnD,CAAC;AACF,eAAO,MAAM,4CAA4C,EAAE,MACmB,CAAC"}
|
|
@@ -49,4 +49,14 @@ export const frontendStateManagementContent = readLocalTemplate("spec/frontend/s
|
|
|
49
49
|
export const guidesIndexContent = readLocalTemplate("spec/guides/index.md.txt");
|
|
50
50
|
export const guidesCrossLayerThinkingGuideContent = readLocalTemplate("spec/guides/cross-layer-thinking-guide.md.txt");
|
|
51
51
|
export const guidesCodeReuseThinkingGuideContent = readLocalTemplate("spec/guides/code-reuse-thinking-guide.md.txt");
|
|
52
|
+
// Role spec templates (three-role collaboration pipeline)
|
|
53
|
+
export const rolePmIndexContent = readLocalTemplate("spec/roles/pm/index.md.txt");
|
|
54
|
+
export const rolePmPrdTemplateContent = readLocalTemplate("spec/roles/pm/prd-template.md.txt");
|
|
55
|
+
export const rolePmRequirementChecklistContent = readLocalTemplate("spec/roles/pm/requirement-checklist.md.txt");
|
|
56
|
+
export const roleDesignerIndexContent = readLocalTemplate("spec/roles/designer/index.md.txt");
|
|
57
|
+
export const roleDesignerPrototypeGuidelinesContent = readLocalTemplate("spec/roles/designer/prototype-guidelines.md.txt");
|
|
58
|
+
export const roleDesignerMockDataStandardsContent = readLocalTemplate("spec/roles/designer/mock-data-standards.md.txt");
|
|
59
|
+
export const roleFrontendImplIndexContent = readLocalTemplate("spec/roles/frontend-impl/index.md.txt");
|
|
60
|
+
export const roleFrontendImplApiIntegrationContent = readLocalTemplate("spec/roles/frontend-impl/api-integration.md.txt");
|
|
61
|
+
export const roleFrontendImplPrototypeToProductionContent = readLocalTemplate("spec/roles/frontend-impl/prototype-to-production.md.txt");
|
|
52
62
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/markdown/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC;;GAEG;AACH,SAAS,iBAAiB,CAAC,QAAgB;IACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC3C,OAAO,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AACzC,CAAC;AAED,gFAAgF;AAChF,8BAA8B;AAC9B,gFAAgF;AAEhF,MAAM,CAAC,MAAM,eAAe,GAAW,iBAAiB,CAAC,WAAW,CAAC,CAAC;AAEtE,oDAAoD;AACpD,MAAM,CAAC,MAAM,qBAAqB,GAChC,iBAAiB,CAAC,oBAAoB,CAAC,CAAC;AAE1C,gCAAgC;AAChC,MAAM,CAAC,MAAM,yBAAyB,GAAG,qBAAqB,CAAC;AAE/D,2DAA2D;AAC3D,MAAM,CAAC,MAAM,wBAAwB,GACnC,iBAAiB,CAAC,eAAe,CAAC,CAAC;AAErC,gFAAgF;AAChF,0DAA0D;AAC1D,wEAAwE;AACxE,gFAAgF;AAEhF,uCAAuC;AACvC,MAAM,CAAC,MAAM,mBAAmB,GAAW,iBAAiB,CAC1D,2BAA2B,CAC5B,CAAC;AACF,MAAM,CAAC,MAAM,gCAAgC,GAAW,iBAAiB,CACvE,yCAAyC,CAC1C,CAAC;AACF,MAAM,CAAC,MAAM,gCAAgC,GAAW,iBAAiB,CACvE,yCAAyC,CAC1C,CAAC;AACF,MAAM,CAAC,MAAM,+BAA+B,GAAW,iBAAiB,CACtE,wCAAwC,CACzC,CAAC;AACF,MAAM,CAAC,MAAM,+BAA+B,GAAW,iBAAiB,CACtE,wCAAwC,CACzC,CAAC;AACF,MAAM,CAAC,MAAM,2BAA2B,GAAW,iBAAiB,CAClE,oCAAoC,CACrC,CAAC;AAEF,wCAAwC;AACxC,MAAM,CAAC,MAAM,oBAAoB,GAAW,iBAAiB,CAC3D,4BAA4B,CAC7B,CAAC;AACF,MAAM,CAAC,MAAM,iCAAiC,GAAW,iBAAiB,CACxE,0CAA0C,CAC3C,CAAC;AACF,MAAM,CAAC,MAAM,yBAAyB,GAAW,iBAAiB,CAChE,kCAAkC,CACnC,CAAC;AACF,MAAM,CAAC,MAAM,6BAA6B,GAAW,iBAAiB,CACpE,sCAAsC,CACvC,CAAC;AACF,MAAM,CAAC,MAAM,kCAAkC,GAAW,iBAAiB,CACzE,2CAA2C,CAC5C,CAAC;AACF,MAAM,CAAC,MAAM,gCAAgC,GAAW,iBAAiB,CACvE,yCAAyC,CAC1C,CAAC;AACF,MAAM,CAAC,MAAM,8BAA8B,GAAW,iBAAiB,CACrE,uCAAuC,CACxC,CAAC;AAEF,mBAAmB;AACnB,MAAM,CAAC,MAAM,kBAAkB,GAAW,iBAAiB,CACzD,0BAA0B,CAC3B,CAAC;AACF,MAAM,CAAC,MAAM,oCAAoC,GAAW,iBAAiB,CAC3E,+CAA+C,CAChD,CAAC;AACF,MAAM,CAAC,MAAM,mCAAmC,GAAW,iBAAiB,CAC1E,8CAA8C,CAC/C,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/markdown/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Designer Role Guidelines
|
|
2
|
+
|
|
3
|
+
> Standards for interactive prototyping and mock data design.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
This directory contains guidelines for the Designer role in the three-role collaboration pipeline. Fill in each file with your project's specific conventions.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Guidelines Index
|
|
14
|
+
|
|
15
|
+
| Guide | Description | Status |
|
|
16
|
+
|-------|-------------|--------|
|
|
17
|
+
| [Prototype Guidelines](./prototype-guidelines.md) | Component structure and interaction patterns | To fill |
|
|
18
|
+
| [Mock Data Standards](./mock-data-standards.md) | How to create and document mock data | To fill |
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Workflow
|
|
23
|
+
|
|
24
|
+
1. Pick a requirement from the pool: `/trellis:pick-task requirements <id>`
|
|
25
|
+
2. Read the upstream HANDOFF.md and PRD carefully
|
|
26
|
+
3. Create runnable prototype code in `deliverables/prototypes/<feature-id>/`
|
|
27
|
+
4. Run `/trellis:handoff` to generate HANDOFF.md and add to pool
|
|
28
|
+
5. Downstream Frontend developer picks from the `prototypes` pool
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Output Directory
|
|
33
|
+
|
|
34
|
+
All Designer deliverables go to: `deliverables/prototypes/<feature-id>/`
|
|
35
|
+
|
|
36
|
+
Required files:
|
|
37
|
+
- Component files (`.tsx`, `.vue`, etc.) - runnable prototype code
|
|
38
|
+
- Mock data inline or in separate files
|
|
39
|
+
|
|
40
|
+
The prototype should:
|
|
41
|
+
- Be runnable (renders correctly with mock data)
|
|
42
|
+
- Follow the project's component conventions (see `spec/frontend/`)
|
|
43
|
+
- Use clear `// TODO:` comments where real logic needs to be added
|
|
44
|
+
- Document all mock data locations
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Key Principle
|
|
49
|
+
|
|
50
|
+
> **The prototype IS the spec for Frontend.**
|
|
51
|
+
>
|
|
52
|
+
> Frontend developers should be able to run your prototype and understand
|
|
53
|
+
> exactly what the final product should look like and behave like.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
**Language**: All documentation should be written in **English**.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Mock Data Standards
|
|
2
|
+
|
|
3
|
+
> How to create, document, and organize mock data in prototypes.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Principles
|
|
8
|
+
|
|
9
|
+
1. **Realistic**: Mock data should look like real data (realistic names, dates, amounts)
|
|
10
|
+
2. **Documented**: Every mock data location must be clearly marked
|
|
11
|
+
3. **Replaceable**: Mock data should be easy to find and replace with real API calls
|
|
12
|
+
4. **Complete**: Cover all data states (populated, empty, error, boundary values)
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Mock Data Location
|
|
17
|
+
|
|
18
|
+
Place mock data at the top of the component file or in a separate `__mocks__/` directory:
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
// === MOCK DATA (start) ===
|
|
22
|
+
const mockUser = {
|
|
23
|
+
id: "1",
|
|
24
|
+
name: "Alice Johnson",
|
|
25
|
+
email: "alice@example.com",
|
|
26
|
+
avatar: "https://i.pravatar.cc/150?u=alice",
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const mockProducts = [
|
|
30
|
+
{ id: "p1", name: "Widget A", price: 29.99, stock: 150 },
|
|
31
|
+
{ id: "p2", name: "Widget B", price: 49.99, stock: 0 },
|
|
32
|
+
];
|
|
33
|
+
// === MOCK DATA (end) ===
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Mock Handler Pattern
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
// TODO: Replace with real API call - see api-integration.md
|
|
42
|
+
const handleSubmit = async (formData: FormData) => {
|
|
43
|
+
// Mock: simulate network delay
|
|
44
|
+
await new Promise(resolve => setTimeout(resolve, 800));
|
|
45
|
+
// Mock: simulate success response
|
|
46
|
+
return { success: true, data: mockResponse };
|
|
47
|
+
};
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Edge Case Data
|
|
53
|
+
|
|
54
|
+
Always include mock data for edge cases:
|
|
55
|
+
- Empty list / no results
|
|
56
|
+
- Single item
|
|
57
|
+
- Maximum items (test scrolling/pagination)
|
|
58
|
+
- Long text (test text overflow)
|
|
59
|
+
- Missing optional fields
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
**Language**: All documentation should be written in **English**.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Prototype Guidelines
|
|
2
|
+
|
|
3
|
+
> Standards for creating interactive prototypes.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Component Structure
|
|
8
|
+
|
|
9
|
+
1. **One feature per directory**: Each feature prototype lives in its own directory
|
|
10
|
+
2. **Entry point**: Always have a clear entry component (e.g., `FeaturePage.tsx`)
|
|
11
|
+
3. **Component hierarchy**: Break down into logical sub-components
|
|
12
|
+
4. **Shared components**: Use project's existing shared components when possible
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Interaction Patterns
|
|
17
|
+
|
|
18
|
+
1. **All states**: Implement all UI states (loading, empty, error, success)
|
|
19
|
+
2. **Animations**: Include transition animations if specified in PRD
|
|
20
|
+
3. **Responsive**: Build mobile-first if the PRD requires responsive design
|
|
21
|
+
4. **Accessibility**: Use semantic HTML, ARIA labels, keyboard navigation
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Code Conventions
|
|
26
|
+
|
|
27
|
+
1. Follow the project's existing component patterns (see `spec/frontend/component-guidelines.md`)
|
|
28
|
+
2. Use the project's styling approach (Tailwind, CSS modules, etc.)
|
|
29
|
+
3. Keep components focused and single-purpose
|
|
30
|
+
4. Add clear comments for complex interactions
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## TODO Markers
|
|
35
|
+
|
|
36
|
+
Mark all places where real implementation is needed:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
// TODO: Replace with real API call
|
|
40
|
+
const data = mockData;
|
|
41
|
+
|
|
42
|
+
// TODO: Add error handling
|
|
43
|
+
// TODO: Implement loading state with skeleton
|
|
44
|
+
// TODO: Connect to auth context
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
**Language**: All documentation should be written in **English**.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# API Integration Guide
|
|
2
|
+
|
|
3
|
+
> How to replace mock data and handlers with real API calls.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Process
|
|
8
|
+
|
|
9
|
+
### 1. Identify All Mock Points
|
|
10
|
+
|
|
11
|
+
Search the prototype for:
|
|
12
|
+
- `// TODO:` comments
|
|
13
|
+
- `// Mock:` comments
|
|
14
|
+
- `mock` variables and functions
|
|
15
|
+
- `setTimeout` simulating API latency
|
|
16
|
+
- Hardcoded data arrays/objects
|
|
17
|
+
|
|
18
|
+
### 2. Map Mock to API
|
|
19
|
+
|
|
20
|
+
For each mock point, determine:
|
|
21
|
+
- Which API endpoint to call
|
|
22
|
+
- Request format (method, headers, body)
|
|
23
|
+
- Response format and how it maps to the component's expected data shape
|
|
24
|
+
- Error responses and how to handle them
|
|
25
|
+
|
|
26
|
+
### 3. Replace Pattern
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
// BEFORE (mock):
|
|
30
|
+
const handleLogin = async (email: string, password: string) => {
|
|
31
|
+
await new Promise(r => setTimeout(r, 800));
|
|
32
|
+
return { success: true, user: mockUser };
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// AFTER (real):
|
|
36
|
+
const handleLogin = async (email: string, password: string) => {
|
|
37
|
+
const response = await api.post('/auth/login', { email, password });
|
|
38
|
+
return response.data;
|
|
39
|
+
};
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Error Handling
|
|
45
|
+
|
|
46
|
+
Every API call must handle:
|
|
47
|
+
1. **Network errors**: Connection timeout, server unreachable
|
|
48
|
+
2. **HTTP errors**: 4xx (client error), 5xx (server error)
|
|
49
|
+
3. **Business errors**: Invalid credentials, insufficient permissions
|
|
50
|
+
4. **Loading states**: Show loading indicator during request
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Testing
|
|
55
|
+
|
|
56
|
+
- Test with real API responses
|
|
57
|
+
- Test with simulated error responses
|
|
58
|
+
- Test loading state transitions
|
|
59
|
+
- Test retry behavior (if implemented)
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
**Language**: All documentation should be written in **English**.
|