-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathbuild.sh
More file actions
executable file
·271 lines (228 loc) · 11.2 KB
/
Copy pathbuild.sh
File metadata and controls
executable file
·271 lines (228 loc) · 11.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
#!/bin/bash
# Design with Intent
# Build script: generates platform-specific distributions from source skills.
#
# Claude Code reads source skills/ and agents/ directly — no generation step.
# This script only produces the distributions other platforms need.
#
# Platforms:
# .cursor/rules/ — Cursor (.mdc files, simplified frontmatter)
# .github/ — VS Code Copilot (copilot-instructions.md + skill files)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SKILLS_DIR="$SCRIPT_DIR/skills"
# Colors for output
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo -e "${BLUE}Design with Intent${NC}"
echo "Building platform distributions..."
echo ""
skill_count=$(ls -d "$SKILLS_DIR"/*/ 2>/dev/null | wc -l | tr -d ' ')
agent_count=$(ls "$SCRIPT_DIR"/agents/*.md 2>/dev/null | wc -l | tr -d ' ')
# =============================================================================
# CURSOR — .cursor/rules/
# .mdc files with simplified frontmatter (description, alwaysApply)
# Each skill becomes a flat .mdc file. Reference docs are appended to their
# parent skill's .mdc file.
# =============================================================================
echo -e "${GREEN}[1/2] Cursor (.cursor/rules/)${NC}"
CURSOR_DIR="$SCRIPT_DIR/.cursor/rules"
rm -rf "$CURSOR_DIR"
mkdir -p "$CURSOR_DIR"
for skill_dir in "$SKILLS_DIR"/*/; do
skill_name=$(basename "$skill_dir")
skill_file="$skill_dir/SKILL.md"
if [ ! -f "$skill_file" ]; then
continue
fi
# Extract description from YAML frontmatter
# Read everything between first --- and second ---, grab description field
description=$(awk '
/^---$/ { count++; next }
count == 1 && /^description:/ {
# Get the description value (may be multi-line with >)
sub(/^description: *>? */, "")
desc = $0
# Read continuation lines (indented)
while ((getline line) > 0) {
if (line ~ /^ /) {
sub(/^ +/, "", line)
desc = desc " " line
} else {
break
}
}
print desc
exit
}
' "$skill_file")
# Get content after frontmatter (skip YAML block)
content=$(awk '
BEGIN { count = 0; printing = 0 }
/^---$/ { count++; if (count == 2) { printing = 1; next } }
printing { print }
' "$skill_file")
# If this skill has reference docs, emit each as its own .mdc file
# instead of inlining them (prevents context bloat in Cursor)
if [ -d "$skill_dir/references" ]; then
for ref_file in "$skill_dir/references"/*.md; do
if [ -f "$ref_file" ]; then
ref_name=$(basename "$ref_file" .md)
ref_content=$(cat "$ref_file")
# Generate a trigger description from the reference name
case "$ref_name" in
accessibility-foundations)
ref_desc="Intent reference: WCAG 2.2 for designers, screen reader design, keyboard navigation, cognitive and motor accessibility, inclusive design principles and testing methodology. Load when working on accessibility, a11y audits, inclusive design, or assistive technology." ;;
content-strategy)
ref_desc="Intent reference: voice framework methodology, tone matrices, content modeling, microcopy patterns, terminology governance, readability scoring. Load when working on UX writing, voice and tone, content models, or copy strategy." ;;
ethical-design)
ref_desc="Intent reference: anti-pattern remediation, dark pattern alternatives, consent design, design ethics frameworks, regulatory compliance patterns. Load when fixing dark patterns, designing consent flows, or reviewing ethical concerns." ;;
information-architecture)
ref_desc="Intent reference: navigation patterns and trade-offs, taxonomy design, mental model theory, wayfinding principles, search behavior models. Load when designing navigation, site structure, taxonomy, or information hierarchy." ;;
interaction-patterns)
ref_desc="Intent reference: form design, state management, validation patterns, feedback loops, progressive disclosure, error recovery, undo/redo. Load when designing forms, interactions, input validation, or state transitions." ;;
measurement-frameworks)
ref_desc="Intent reference: HEART framework, Goal-Signal-Metric mapping, A/B test design, statistical literacy for designers, ethical measurement. Load when defining metrics, designing experiments, or building measurement plans." ;;
research-methods)
ref_desc="Intent reference: method selection matrix, sample size guidance, interview techniques, usability testing, survey design, synthesis frameworks. Load when planning or conducting user research." ;;
service-design)
ref_desc="Intent reference: service blueprinting methodology, frontstage/backstage mapping, touchpoint analysis, moment-of-truth design, channel orchestration. Load when mapping services, systems, or cross-channel experiences." ;;
*)
ref_desc="Intent reference document: $ref_name" ;;
esac
cat > "$CURSOR_DIR/intent-ref-$ref_name.mdc" << ENDOFREF
---
description: $ref_desc
alwaysApply: false
---
$ref_content
ENDOFREF
fi
done
fi
# Determine if this should always apply
# Only the intent (master) skill should always apply
always_apply="false"
if [ "$skill_name" = "intent" ]; then
always_apply="true"
fi
# Write .mdc file
cat > "$CURSOR_DIR/$skill_name.mdc" << ENDOFMDC
---
description: $description
alwaysApply: $always_apply
---
$content
ENDOFMDC
done
mdc_count=$(ls "$CURSOR_DIR"/*.mdc 2>/dev/null | wc -l | tr -d ' ')
echo " Generated $mdc_count .mdc rule files"
# =============================================================================
# VS CODE COPILOT — .github/
# copilot-instructions.md with core Intent principles
# Individual skills as .instructions.md files in .github/copilot/skills/
# =============================================================================
echo -e "${GREEN}[2/2] VS Code Copilot (.github/)${NC}"
GITHUB_DIR="$SCRIPT_DIR/.github"
COPILOT_SKILLS_DIR="$GITHUB_DIR/copilot/skills"
# Preserve workflows directory during rebuild
WORKFLOWS_BACKUP=""
if [ -d "$GITHUB_DIR/workflows" ]; then
WORKFLOWS_BACKUP=$(mktemp -d)
cp -r "$GITHUB_DIR/workflows" "$WORKFLOWS_BACKUP/workflows"
# Safety net: if the script dies between the rm and the restore mv below
# (signal, disk error, set -e tripping on a downstream command), this
# trap recreates .github/workflows from the backup so the source repo
# is never left in a corrupt state.
trap '[ -n "${WORKFLOWS_BACKUP:-}" ] && [ -d "$WORKFLOWS_BACKUP/workflows" ] && [ ! -d "$GITHUB_DIR/workflows" ] && { mkdir -p "$GITHUB_DIR" 2>/dev/null; mv "$WORKFLOWS_BACKUP/workflows" "$GITHUB_DIR/workflows" 2>/dev/null; } || true' EXIT
fi
rm -rf "$GITHUB_DIR"
mkdir -p "$COPILOT_SKILLS_DIR"
if [ -n "$WORKFLOWS_BACKUP" ] && [ -d "$WORKFLOWS_BACKUP/workflows" ]; then
mv "$WORKFLOWS_BACKUP/workflows" "$GITHUB_DIR/workflows"
rmdir "$WORKFLOWS_BACKUP"
fi
# Generate the main copilot-instructions.md from the intent skill
# This is the always-loaded file — contains core principles and routing
intent_content=$(awk '
BEGIN { count = 0; printing = 0 }
/^---$/ { count++; if (count == 2) { printing = 1; next } }
printing { print }
' "$SKILLS_DIR/intent/SKILL.md")
cat > "$GITHUB_DIR/copilot-instructions.md" << ENDOFCOPILOT
# Design with Intent
This project uses the Intent UX design strategy system. When working on design decisions, UX strategy, user research, information architecture, content strategy, accessibility, or engineering handoff, follow these principles and use the specialized skill files in .github/copilot/skills/.
$intent_content
ENDOFCOPILOT
# Copy each skill (except intent, which is in the main file) as a separate file
for skill_dir in "$SKILLS_DIR"/*/; do
skill_name=$(basename "$skill_dir")
skill_file="$skill_dir/SKILL.md"
if [ ! -f "$skill_file" ] || [ "$skill_name" = "intent" ]; then
continue
fi
# Copy skill file
cp "$skill_file" "$COPILOT_SKILLS_DIR/$skill_name.md"
# Copy reference docs if they exist
if [ -d "$skill_dir/references" ]; then
mkdir -p "$COPILOT_SKILLS_DIR/$skill_name"
cp "$skill_dir/references"/*.md "$COPILOT_SKILLS_DIR/$skill_name/"
fi
done
# Also generate AGENTS.md for Copilot agent mode
cat > "$GITHUB_DIR/AGENTS.md" << ENDOFAGENTS
# Design with Intent
This project uses the Intent UX design strategy system.
## Skills
Specialized design skills are available in .github/copilot/skills/:
$(for skill_dir in "$SKILLS_DIR"/*/; do
skill_name=$(basename "$skill_dir")
# Extract full description (handles multi-line YAML > format)
desc=$(awk '
/^---$/ { count++; next }
count == 1 && /^description:/ {
sub(/^description: *>? */, "")
desc = $0
while ((getline line) > 0) {
if (line ~ /^ /) {
sub(/^ +/, "", line)
desc = desc " " line
} else {
break
}
}
# Truncate to first sentence for AGENTS.md brevity
match(desc, /\. /)
if (RSTART > 0) desc = substr(desc, 1, RSTART)
print desc
exit
}
' "$skill_dir/SKILL.md" 2>/dev/null)
echo "- **$skill_name** — $desc"
done)
## Core Principles
- Respect user autonomy — no manipulation, clear choices, easy reversal
- Design for real conditions — slow networks, distraction, disability, stress
- Make intent visible — every screen should answer: what can I do, why should I, what happens next
- Evidence over intuition — research, test, measure
- Systems over screens — a flow is part of a system is part of a user's life
- Ethical defaults — opt-in over opt-out, privacy by default, honest over persuasive
See .github/copilot-instructions.md for the full Intent system and anti-pattern catalog.
ENDOFAGENTS
copilot_count=$(ls "$COPILOT_SKILLS_DIR"/*.md 2>/dev/null | wc -l | tr -d ' ')
echo " Generated copilot-instructions.md + AGENTS.md + $copilot_count skill files"
# =============================================================================
# Summary
# =============================================================================
echo ""
echo -e "${BLUE}Build complete.${NC}"
echo ""
echo " skills/ — $skill_count skills (source, read by Claude Code directly)"
echo " agents/ — $agent_count agents (source, read by Claude Code directly)"
echo " .cursor/rules/ — $mdc_count rules (.mdc format)"
echo " .github/ — copilot-instructions.md + AGENTS.md + $copilot_count skills"
echo ""
echo -e "${YELLOW}Note:${NC} Commit the generated .cursor/ and .github/ directories to make"
echo "Intent available in Cursor and Copilot. Claude Code uses the source files directly."