viepilot 1.9.11 β 2.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 +175 -2
- package/README.md +3 -3
- package/bin/viepilot.cjs +7 -5
- package/bin/vp-tools.cjs +193 -0
- package/dev-install.sh +34 -13
- package/docs/user/features/architect-design-mode.md +170 -0
- package/docs/user/features/hooks.md +93 -0
- package/docs/user/features/ui-direction.md +79 -3
- package/lib/adapters/claude-code.cjs +42 -0
- package/lib/adapters/cursor.cjs +31 -0
- package/lib/adapters/index.cjs +26 -0
- package/lib/hooks/brainstorm-staleness.cjs +231 -0
- package/lib/viepilot-config.cjs +103 -0
- package/lib/viepilot-install.cjs +128 -153
- package/package.json +1 -1
- package/skills/vp-audit/SKILL.md +21 -21
- package/skills/vp-auto/SKILL.md +21 -7
- package/skills/vp-brainstorm/SKILL.md +46 -35
- package/skills/vp-crystallize/SKILL.md +37 -25
- package/skills/vp-debug/SKILL.md +2 -2
- package/skills/vp-docs/SKILL.md +7 -7
- package/skills/vp-evolve/SKILL.md +25 -12
- package/skills/vp-info/SKILL.md +23 -23
- package/skills/vp-pause/SKILL.md +5 -5
- package/skills/vp-request/SKILL.md +12 -12
- package/skills/vp-resume/SKILL.md +4 -4
- package/skills/vp-rollback/SKILL.md +3 -3
- package/skills/vp-status/SKILL.md +4 -4
- package/skills/vp-task/SKILL.md +3 -3
- package/skills/vp-ui-components/SKILL.md +12 -12
- package/skills/vp-update/SKILL.md +17 -17
- package/templates/architect/apis.html +159 -0
- package/templates/architect/architect-actions.js +217 -0
- package/templates/architect/architecture.html +160 -0
- package/templates/architect/data-flow.html +109 -0
- package/templates/architect/decisions.html +96 -0
- package/templates/architect/deployment.html +184 -0
- package/templates/architect/erd.html +154 -0
- package/templates/architect/feature-map.html +113 -0
- package/templates/architect/index.html +108 -0
- package/templates/architect/sequence-diagram.html +133 -0
- package/templates/architect/style.css +365 -0
- package/templates/architect/tech-notes.html +89 -0
- package/templates/architect/tech-stack.html +114 -0
- package/templates/architect/user-use-cases.html +154 -0
- package/templates/project/AI-GUIDE.md +53 -54
- package/templates/project/PROJECT-CONTEXT.md +7 -11
- package/templates/project/README.md +43 -0
- package/templates/project/ROADMAP.md +1 -27
- package/workflows/audit.md +3 -3
- package/workflows/autonomous.md +38 -5
- package/workflows/brainstorm.md +575 -191
- package/workflows/crystallize.md +168 -58
- package/workflows/debug.md +9 -9
- package/workflows/documentation.md +5 -5
- package/workflows/evolve.md +44 -12
- package/workflows/pause-work.md +2 -2
- package/workflows/request.md +8 -8
- package/workflows/resume-work.md +1 -1
- package/workflows/rollback.md +1 -1
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="vi">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Sequence Diagram β {project}</title>
|
|
7
|
+
<link rel="stylesheet" href="style.css" />
|
|
8
|
+
</head>
|
|
9
|
+
<body data-arch-slug="sequence">
|
|
10
|
+
<nav class="nav-sidebar">
|
|
11
|
+
<div class="logo">
|
|
12
|
+
<span>ViePilot Architect Mode</span>
|
|
13
|
+
<strong>{project}</strong>
|
|
14
|
+
</div>
|
|
15
|
+
<ul>
|
|
16
|
+
<li><a href="index.html">π Hub</a></li>
|
|
17
|
+
<li><a href="architecture.html">ποΈ Architecture</a></li>
|
|
18
|
+
<li><a href="sequence-diagram.html" class="active">π¬ Sequence</a></li>
|
|
19
|
+
<li><a href="data-flow.html">π Data Flow</a></li>
|
|
20
|
+
<li><a href="decisions.html">π Decisions (ADR)</a></li>
|
|
21
|
+
<li><a href="tech-stack.html">π οΈ Tech Stack</a></li>
|
|
22
|
+
<li><a href="tech-notes.html">π Tech Notes</a></li>
|
|
23
|
+
<li><a href="feature-map.html">πΊοΈ Feature Map</a></li>
|
|
24
|
+
<li><a href="erd.html">ποΈ ERD</a></li>
|
|
25
|
+
<li><a href="user-use-cases.html">π€ Use Cases</a></li>
|
|
26
|
+
<li><a href="deployment.html">π Deployment</a></li>
|
|
27
|
+
<li><a href="apis.html">π APIs</a></li>
|
|
28
|
+
</ul>
|
|
29
|
+
</nav>
|
|
30
|
+
|
|
31
|
+
<main class="main-content">
|
|
32
|
+
<div class="page-header">
|
|
33
|
+
<div>
|
|
34
|
+
<h1>π¬ Sequence Diagrams</h1>
|
|
35
|
+
<p>Per-scenario step-by-step interactions</p>
|
|
36
|
+
</div>
|
|
37
|
+
<button id="theme-toggle" onclick="toggleTheme()">βοΈ Light</button>
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
<div class="card" style="border-left: 3px solid var(--accent); background: var(--surface-alt);">
|
|
41
|
+
<p style="color:var(--text-muted);font-size:13px;">
|
|
42
|
+
<strong>Note:</strong> Per-scenario detail. High-level service/event flows β <a href="data-flow.html">data-flow.html</a>
|
|
43
|
+
</p>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<div class="card">
|
|
47
|
+
<h2>Scenario Index</h2>
|
|
48
|
+
<table>
|
|
49
|
+
<thead>
|
|
50
|
+
<tr>
|
|
51
|
+
<th>ID</th>
|
|
52
|
+
<th>Scenario</th>
|
|
53
|
+
<th>Actors</th>
|
|
54
|
+
<th>Trigger</th>
|
|
55
|
+
<th>Related use case</th>
|
|
56
|
+
<th>Notes</th>
|
|
57
|
+
</tr>
|
|
58
|
+
</thead>
|
|
59
|
+
<tbody>
|
|
60
|
+
<tr data-arch-id="SEQ1">
|
|
61
|
+
<td>SEQ-01</td>
|
|
62
|
+
<td>{Scenario name}</td>
|
|
63
|
+
<td>{Actor A, Actor B}</td>
|
|
64
|
+
<td>{User action / Event}</td>
|
|
65
|
+
<td>{UC-ID}</td>
|
|
66
|
+
<td>{Notes}</td>
|
|
67
|
+
</tr>
|
|
68
|
+
<tr data-arch-id="SEQ2">
|
|
69
|
+
<td>SEQ-02</td>
|
|
70
|
+
<td>{Scenario name}</td>
|
|
71
|
+
<td>{Actor A, Actor B}</td>
|
|
72
|
+
<td>{User action / Event}</td>
|
|
73
|
+
<td>{UC-ID}</td>
|
|
74
|
+
<td>{Notes}</td>
|
|
75
|
+
</tr>
|
|
76
|
+
</tbody>
|
|
77
|
+
</table>
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
<div class="card" data-arch-id="SEQ-DIAG1" data-arch-title="SEQ-01: {Scenario 1 Name}">
|
|
81
|
+
<h2>SEQ-01: {Scenario 1 Name}</h2>
|
|
82
|
+
<div class="mermaid-wrap">
|
|
83
|
+
<div class="mermaid">
|
|
84
|
+
sequenceDiagram
|
|
85
|
+
actor User
|
|
86
|
+
participant Frontend
|
|
87
|
+
participant API
|
|
88
|
+
participant DB
|
|
89
|
+
|
|
90
|
+
User->>Frontend: {Action}
|
|
91
|
+
Frontend->>API: POST /resource
|
|
92
|
+
API->>DB: INSERT
|
|
93
|
+
DB-->>API: OK
|
|
94
|
+
API-->>Frontend: 200 {data}
|
|
95
|
+
Frontend-->>User: {Response}
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
<div class="card" data-arch-id="SEQ-DIAG2" data-arch-title="SEQ-02: {Scenario 2 Name}">
|
|
101
|
+
<h2>SEQ-02: {Scenario 2 Name}</h2>
|
|
102
|
+
<div class="mermaid-wrap">
|
|
103
|
+
<div class="mermaid">
|
|
104
|
+
sequenceDiagram
|
|
105
|
+
actor User
|
|
106
|
+
participant Frontend
|
|
107
|
+
participant API
|
|
108
|
+
participant Service
|
|
109
|
+
|
|
110
|
+
User->>Frontend: {Action}
|
|
111
|
+
Frontend->>API: GET /resource
|
|
112
|
+
API->>Service: fetch({params})
|
|
113
|
+
Service-->>API: {result}
|
|
114
|
+
API-->>Frontend: 200 {data}
|
|
115
|
+
Frontend-->>User: {Display}
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
</main>
|
|
120
|
+
|
|
121
|
+
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
|
|
122
|
+
<script>
|
|
123
|
+
mermaid.initialize({ startOnLoad: true, theme: 'dark' });
|
|
124
|
+
function toggleTheme() {
|
|
125
|
+
const html = document.documentElement;
|
|
126
|
+
const isLight = html.classList.toggle('light');
|
|
127
|
+
document.getElementById('theme-toggle').textContent = isLight ? 'π Dark' : 'βοΈ Light';
|
|
128
|
+
mermaid.initialize({ startOnLoad: false, theme: isLight ? 'default' : 'dark' });
|
|
129
|
+
}
|
|
130
|
+
</script>
|
|
131
|
+
<script src="architect-actions.js"></script>
|
|
132
|
+
</body>
|
|
133
|
+
</html>
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
/* ViePilot Architect Design Mode β Shared Styles (FEAT-011) */
|
|
2
|
+
|
|
3
|
+
/* ββ CSS Variables ββ */
|
|
4
|
+
:root {
|
|
5
|
+
--bg: #0f1117;
|
|
6
|
+
--surface: #1a1d27;
|
|
7
|
+
--surface-alt: #22263a;
|
|
8
|
+
--border: #2e3248;
|
|
9
|
+
--text: #e2e8f0;
|
|
10
|
+
--text-muted: #94a3b8;
|
|
11
|
+
--accent: #6366f1;
|
|
12
|
+
--accent-hover: #818cf8;
|
|
13
|
+
--updated-bg: #fef3c720;
|
|
14
|
+
--updated-border: #f59e0b;
|
|
15
|
+
--badge-bg: #f59e0b;
|
|
16
|
+
--badge-text: #1a1d27;
|
|
17
|
+
--link: #818cf8;
|
|
18
|
+
--nav-width: 220px;
|
|
19
|
+
--radius: 8px;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
html.light {
|
|
23
|
+
--bg: #f8fafc;
|
|
24
|
+
--surface: #ffffff;
|
|
25
|
+
--surface-alt: #f1f5f9;
|
|
26
|
+
--border: #e2e8f0;
|
|
27
|
+
--text: #1e293b;
|
|
28
|
+
--text-muted: #64748b;
|
|
29
|
+
--accent: #4f46e5;
|
|
30
|
+
--accent-hover: #4338ca;
|
|
31
|
+
--updated-bg: #fef9c3;
|
|
32
|
+
--updated-border: #d97706;
|
|
33
|
+
--badge-bg: #d97706;
|
|
34
|
+
--badge-text: #ffffff;
|
|
35
|
+
--link: #4f46e5;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* ββ Reset & Base ββ */
|
|
39
|
+
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
40
|
+
|
|
41
|
+
body {
|
|
42
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
43
|
+
font-size: 14px;
|
|
44
|
+
line-height: 1.6;
|
|
45
|
+
background: var(--bg);
|
|
46
|
+
color: var(--text);
|
|
47
|
+
display: flex;
|
|
48
|
+
min-height: 100vh;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
a { color: var(--link); text-decoration: none; }
|
|
52
|
+
a:hover { text-decoration: underline; }
|
|
53
|
+
|
|
54
|
+
/* ββ Layout ββ */
|
|
55
|
+
.nav-sidebar {
|
|
56
|
+
width: var(--nav-width);
|
|
57
|
+
min-height: 100vh;
|
|
58
|
+
background: var(--surface);
|
|
59
|
+
border-right: 1px solid var(--border);
|
|
60
|
+
padding: 20px 0;
|
|
61
|
+
flex-shrink: 0;
|
|
62
|
+
position: sticky;
|
|
63
|
+
top: 0;
|
|
64
|
+
align-self: flex-start;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.nav-sidebar .logo {
|
|
68
|
+
padding: 0 20px 16px;
|
|
69
|
+
border-bottom: 1px solid var(--border);
|
|
70
|
+
margin-bottom: 12px;
|
|
71
|
+
}
|
|
72
|
+
.nav-sidebar .logo span { font-size: 12px; color: var(--text-muted); display: block; }
|
|
73
|
+
.nav-sidebar .logo strong { font-size: 14px; color: var(--text); }
|
|
74
|
+
|
|
75
|
+
.nav-sidebar ul { list-style: none; }
|
|
76
|
+
.nav-sidebar li a {
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
gap: 8px;
|
|
80
|
+
padding: 8px 20px;
|
|
81
|
+
color: var(--text-muted);
|
|
82
|
+
font-size: 13px;
|
|
83
|
+
transition: background 0.15s, color 0.15s;
|
|
84
|
+
border-left: 3px solid transparent;
|
|
85
|
+
}
|
|
86
|
+
.nav-sidebar li a:hover,
|
|
87
|
+
.nav-sidebar li a.active {
|
|
88
|
+
background: var(--surface-alt);
|
|
89
|
+
color: var(--text);
|
|
90
|
+
border-left-color: var(--accent);
|
|
91
|
+
text-decoration: none;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.main-content {
|
|
95
|
+
flex: 1;
|
|
96
|
+
padding: 32px 40px;
|
|
97
|
+
min-width: 0;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.page-header {
|
|
101
|
+
margin-bottom: 28px;
|
|
102
|
+
padding-bottom: 16px;
|
|
103
|
+
border-bottom: 1px solid var(--border);
|
|
104
|
+
display: flex;
|
|
105
|
+
align-items: center;
|
|
106
|
+
justify-content: space-between;
|
|
107
|
+
}
|
|
108
|
+
.page-header h1 { font-size: 22px; font-weight: 600; }
|
|
109
|
+
.page-header p { font-size: 13px; color: var(--text-muted); margin-top: 4px; }
|
|
110
|
+
|
|
111
|
+
/* ββ Dark/Light Toggle ββ */
|
|
112
|
+
#theme-toggle {
|
|
113
|
+
background: var(--surface-alt);
|
|
114
|
+
border: 1px solid var(--border);
|
|
115
|
+
color: var(--text-muted);
|
|
116
|
+
padding: 5px 12px;
|
|
117
|
+
border-radius: var(--radius);
|
|
118
|
+
cursor: pointer;
|
|
119
|
+
font-size: 12px;
|
|
120
|
+
transition: border-color 0.15s;
|
|
121
|
+
flex-shrink: 0;
|
|
122
|
+
}
|
|
123
|
+
#theme-toggle:hover { border-color: var(--accent); color: var(--text); }
|
|
124
|
+
|
|
125
|
+
/* ββ Cards & Tables ββ */
|
|
126
|
+
.card {
|
|
127
|
+
background: var(--surface);
|
|
128
|
+
border: 1px solid var(--border);
|
|
129
|
+
border-radius: var(--radius);
|
|
130
|
+
padding: 20px;
|
|
131
|
+
margin-bottom: 20px;
|
|
132
|
+
}
|
|
133
|
+
.card h2 { font-size: 15px; font-weight: 600; margin-bottom: 12px; }
|
|
134
|
+
|
|
135
|
+
table {
|
|
136
|
+
width: 100%;
|
|
137
|
+
border-collapse: collapse;
|
|
138
|
+
font-size: 13px;
|
|
139
|
+
}
|
|
140
|
+
th {
|
|
141
|
+
background: var(--surface-alt);
|
|
142
|
+
padding: 8px 12px;
|
|
143
|
+
text-align: left;
|
|
144
|
+
font-weight: 600;
|
|
145
|
+
border-bottom: 1px solid var(--border);
|
|
146
|
+
color: var(--text-muted);
|
|
147
|
+
font-size: 12px;
|
|
148
|
+
text-transform: uppercase;
|
|
149
|
+
letter-spacing: 0.04em;
|
|
150
|
+
}
|
|
151
|
+
td {
|
|
152
|
+
padding: 9px 12px;
|
|
153
|
+
border-bottom: 1px solid var(--border);
|
|
154
|
+
vertical-align: top;
|
|
155
|
+
}
|
|
156
|
+
tr:last-child td { border-bottom: none; }
|
|
157
|
+
tr:hover td { background: var(--surface-alt); }
|
|
158
|
+
|
|
159
|
+
/* ββ Updated Diff Indicator ββ */
|
|
160
|
+
.updated {
|
|
161
|
+
border-left: 3px solid var(--updated-border) !important;
|
|
162
|
+
background: var(--updated-bg) !important;
|
|
163
|
+
position: relative;
|
|
164
|
+
}
|
|
165
|
+
.updated::after {
|
|
166
|
+
content: "updated";
|
|
167
|
+
position: absolute;
|
|
168
|
+
top: 6px;
|
|
169
|
+
right: 8px;
|
|
170
|
+
background: var(--badge-bg);
|
|
171
|
+
color: var(--badge-text);
|
|
172
|
+
font-size: 10px;
|
|
173
|
+
font-weight: 700;
|
|
174
|
+
padding: 1px 6px;
|
|
175
|
+
border-radius: 4px;
|
|
176
|
+
text-transform: uppercase;
|
|
177
|
+
letter-spacing: 0.05em;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/* ββ Mermaid Container ββ */
|
|
181
|
+
.mermaid-wrap {
|
|
182
|
+
background: var(--surface-alt);
|
|
183
|
+
border: 1px solid var(--border);
|
|
184
|
+
border-radius: var(--radius);
|
|
185
|
+
padding: 20px;
|
|
186
|
+
margin: 12px 0;
|
|
187
|
+
overflow-x: auto;
|
|
188
|
+
}
|
|
189
|
+
.mermaid { font-size: 13px; }
|
|
190
|
+
|
|
191
|
+
/* ββ Status Badges ββ */
|
|
192
|
+
.badge {
|
|
193
|
+
display: inline-block;
|
|
194
|
+
padding: 2px 8px;
|
|
195
|
+
border-radius: 4px;
|
|
196
|
+
font-size: 11px;
|
|
197
|
+
font-weight: 600;
|
|
198
|
+
text-transform: uppercase;
|
|
199
|
+
letter-spacing: 0.04em;
|
|
200
|
+
}
|
|
201
|
+
.badge-decided { background: #16a34a20; color: #4ade80; }
|
|
202
|
+
.badge-open { background: #f59e0b20; color: #fbbf24; }
|
|
203
|
+
.badge-deferred { background: #6366f120; color: #a5b4fc; }
|
|
204
|
+
.badge-phase-1 { background: #0ea5e920; color: #38bdf8; }
|
|
205
|
+
.badge-phase-2 { background: #8b5cf620; color: #c4b5fd; }
|
|
206
|
+
.badge-phase-3 { background: #64748b20; color: #94a3b8; }
|
|
207
|
+
.method-get { background: #16a34a20; color: #4ade80; }
|
|
208
|
+
.method-post { background: #3b82f620; color: #93c5fd; }
|
|
209
|
+
.method-put { background: #d9770630; color: #fcd34d; }
|
|
210
|
+
.method-delete { background: #ef444420; color: #fca5a5; }
|
|
211
|
+
.method-patch { background: #f9731620; color: #fed7aa; }
|
|
212
|
+
|
|
213
|
+
/* ββ Columns layout ββ */
|
|
214
|
+
.cols-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
|
|
215
|
+
.cols-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }
|
|
216
|
+
@media (max-width: 768px) {
|
|
217
|
+
.cols-3, .cols-2 { grid-template-columns: 1fr; }
|
|
218
|
+
.nav-sidebar { display: none; }
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/* ββ Architect Item Actions (ENH-033) ββ */
|
|
222
|
+
/* Item ID badge */
|
|
223
|
+
.arch-id-badge {
|
|
224
|
+
display: inline-block;
|
|
225
|
+
font-family: "SF Mono", "Fira Code", ui-monospace, monospace;
|
|
226
|
+
font-size: 10px;
|
|
227
|
+
padding: 1px 5px;
|
|
228
|
+
border-radius: 3px;
|
|
229
|
+
background: var(--surface-alt);
|
|
230
|
+
color: var(--text-muted);
|
|
231
|
+
border: 1px solid var(--border);
|
|
232
|
+
letter-spacing: 0.03em;
|
|
233
|
+
user-select: none;
|
|
234
|
+
white-space: nowrap;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/* Action buttons container */
|
|
238
|
+
.arch-item-actions {
|
|
239
|
+
display: inline-flex;
|
|
240
|
+
align-items: center;
|
|
241
|
+
gap: 5px;
|
|
242
|
+
opacity: 0;
|
|
243
|
+
transition: opacity 0.15s ease;
|
|
244
|
+
white-space: nowrap;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/* Reveal on row/card hover */
|
|
248
|
+
tr:hover .arch-item-actions,
|
|
249
|
+
.card:hover > .arch-item-actions,
|
|
250
|
+
[data-arch-id]:hover > .arch-item-actions {
|
|
251
|
+
opacity: 1;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/* Always visible in actions cell */
|
|
255
|
+
.arch-actions-cell .arch-item-actions {
|
|
256
|
+
opacity: 0;
|
|
257
|
+
}
|
|
258
|
+
tr:hover .arch-actions-cell .arch-item-actions {
|
|
259
|
+
opacity: 1;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/* Actions column header β minimal width, no label */
|
|
263
|
+
.arch-actions-th {
|
|
264
|
+
width: 140px;
|
|
265
|
+
min-width: 140px;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/* Actions column cell */
|
|
269
|
+
.arch-actions-cell {
|
|
270
|
+
white-space: nowrap;
|
|
271
|
+
vertical-align: middle;
|
|
272
|
+
padding: 4px 8px !important;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/* Base button */
|
|
276
|
+
.arch-btn {
|
|
277
|
+
display: inline-flex;
|
|
278
|
+
align-items: center;
|
|
279
|
+
gap: 3px;
|
|
280
|
+
padding: 2px 8px;
|
|
281
|
+
border-radius: 4px;
|
|
282
|
+
border: 1px solid transparent;
|
|
283
|
+
font-size: 11px;
|
|
284
|
+
font-weight: 500;
|
|
285
|
+
cursor: pointer;
|
|
286
|
+
transition: background 0.12s, color 0.12s, border-color 0.12s;
|
|
287
|
+
line-height: 1.6;
|
|
288
|
+
user-select: none;
|
|
289
|
+
}
|
|
290
|
+
.arch-btn:focus-visible {
|
|
291
|
+
outline: 2px solid var(--accent);
|
|
292
|
+
outline-offset: 2px;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/* Approve button β green tint */
|
|
296
|
+
.arch-btn-approve {
|
|
297
|
+
background: #16a34a18;
|
|
298
|
+
color: #4ade80;
|
|
299
|
+
border-color: #16a34a40;
|
|
300
|
+
}
|
|
301
|
+
.arch-btn-approve:hover {
|
|
302
|
+
background: #16a34a30;
|
|
303
|
+
border-color: #16a34a70;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/* Edit button β accent tint */
|
|
307
|
+
.arch-btn-edit {
|
|
308
|
+
background: #6366f118;
|
|
309
|
+
color: #a5b4fc;
|
|
310
|
+
border-color: #6366f140;
|
|
311
|
+
}
|
|
312
|
+
.arch-btn-edit:hover {
|
|
313
|
+
background: #6366f130;
|
|
314
|
+
border-color: #6366f170;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/* "Copied!" feedback state */
|
|
318
|
+
.arch-btn.copied {
|
|
319
|
+
background: #f59e0b20;
|
|
320
|
+
color: #fbbf24;
|
|
321
|
+
border-color: #f59e0b50;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/* Light-mode overrides */
|
|
325
|
+
html.light .arch-btn-approve { background: #dcfce7; color: #16a34a; border-color: #bbf7d0; }
|
|
326
|
+
html.light .arch-btn-approve:hover { background: #bbf7d0; }
|
|
327
|
+
html.light .arch-btn-edit { background: #ede9fe; color: #4f46e5; border-color: #c4b5fd; }
|
|
328
|
+
html.light .arch-btn-edit:hover { background: #c4b5fd; }
|
|
329
|
+
html.light .arch-btn.copied { background: #fef9c3; color: #b45309; border-color: #fde68a; }
|
|
330
|
+
html.light .arch-id-badge { background: #f1f5f9; color: #64748b; border-color: #e2e8f0; }
|
|
331
|
+
|
|
332
|
+
/* ββ Architect Gap / Stale Indicators (ENH-034) ββ */
|
|
333
|
+
/* Amber β "brainstorm detected a gap, HTML not synced yet"
|
|
334
|
+
Distinct from .updated (yellow = recently changed by architect session) */
|
|
335
|
+
|
|
336
|
+
.arch-gap-badge {
|
|
337
|
+
display: inline-block;
|
|
338
|
+
font-size: 10px;
|
|
339
|
+
font-weight: 600;
|
|
340
|
+
padding: 1px 5px;
|
|
341
|
+
border-radius: 3px;
|
|
342
|
+
background: rgba(245, 158, 11, 0.15);
|
|
343
|
+
color: #f59e0b;
|
|
344
|
+
border: 1px solid rgba(245, 158, 11, 0.3);
|
|
345
|
+
margin-left: 6px;
|
|
346
|
+
vertical-align: middle;
|
|
347
|
+
letter-spacing: 0.3px;
|
|
348
|
+
cursor: default;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
[data-arch-stale="true"] {
|
|
352
|
+
border-left: 3px solid #f59e0b !important;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
tr[data-arch-stale="true"] td:first-child .arch-gap-badge,
|
|
356
|
+
.card[data-arch-stale="true"] h2 .arch-gap-badge {
|
|
357
|
+
display: inline-block;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/* Light mode overrides */
|
|
361
|
+
html.light .arch-gap-badge {
|
|
362
|
+
background: rgba(217, 119, 6, 0.1);
|
|
363
|
+
color: #d97706;
|
|
364
|
+
border-color: rgba(217, 119, 6, 0.3);
|
|
365
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="vi">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Tech Notes β {project}</title>
|
|
7
|
+
<link rel="stylesheet" href="style.css" />
|
|
8
|
+
</head>
|
|
9
|
+
<body data-arch-slug="tech-notes">
|
|
10
|
+
<nav class="nav-sidebar">
|
|
11
|
+
<div class="logo">
|
|
12
|
+
<span>ViePilot Architect Mode</span>
|
|
13
|
+
<strong>{project}</strong>
|
|
14
|
+
</div>
|
|
15
|
+
<ul>
|
|
16
|
+
<li><a href="index.html">π Hub</a></li>
|
|
17
|
+
<li><a href="architecture.html">ποΈ Architecture</a></li>
|
|
18
|
+
<li><a href="sequence-diagram.html">π¬ Sequence</a></li>
|
|
19
|
+
<li><a href="data-flow.html">π Data Flow</a></li>
|
|
20
|
+
<li><a href="decisions.html">π Decisions (ADR)</a></li>
|
|
21
|
+
<li><a href="tech-stack.html">π οΈ Tech Stack</a></li>
|
|
22
|
+
<li><a href="tech-notes.html" class="active">π Tech Notes</a></li>
|
|
23
|
+
<li><a href="feature-map.html">πΊοΈ Feature Map</a></li>
|
|
24
|
+
<li><a href="erd.html">ποΈ ERD</a></li>
|
|
25
|
+
<li><a href="user-use-cases.html">π€ Use Cases</a></li>
|
|
26
|
+
<li><a href="deployment.html">π Deployment</a></li>
|
|
27
|
+
<li><a href="apis.html">π APIs</a></li>
|
|
28
|
+
</ul>
|
|
29
|
+
</nav>
|
|
30
|
+
|
|
31
|
+
<main class="main-content">
|
|
32
|
+
<div class="page-header">
|
|
33
|
+
<div>
|
|
34
|
+
<h1>π Tech Notes</h1>
|
|
35
|
+
<p>Assumptions, risks, and open questions</p>
|
|
36
|
+
</div>
|
|
37
|
+
<button id="theme-toggle" onclick="toggleTheme()">βοΈ Light</button>
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
<div class="cols-3">
|
|
41
|
+
<div class="card">
|
|
42
|
+
<h2>π· Assumptions</h2>
|
|
43
|
+
<ul style="list-style:none;padding:0;">
|
|
44
|
+
<li style="padding:6px 0;border-bottom:1px solid var(--border);font-size:13px;">{Assumption 1}</li>
|
|
45
|
+
<li style="padding:6px 0;border-bottom:1px solid var(--border);font-size:13px;">{Assumption 2}</li>
|
|
46
|
+
<li style="padding:6px 0;font-size:13px;">{Assumption 3}</li>
|
|
47
|
+
</ul>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<div class="card">
|
|
51
|
+
<h2>β οΈ Risks</h2>
|
|
52
|
+
<ul style="list-style:none;padding:0;">
|
|
53
|
+
<li style="padding:6px 0;border-bottom:1px solid var(--border);font-size:13px;">{Risk 1} β <span style="color:var(--text-muted)">High/Med/Low</span></li>
|
|
54
|
+
<li style="padding:6px 0;border-bottom:1px solid var(--border);font-size:13px;">{Risk 2} β <span style="color:var(--text-muted)">High/Med/Low</span></li>
|
|
55
|
+
<li style="padding:6px 0;font-size:13px;">{Risk 3} β <span style="color:var(--text-muted)">High/Med/Low</span></li>
|
|
56
|
+
</ul>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<div class="card">
|
|
60
|
+
<h2>β Open Questions</h2>
|
|
61
|
+
<ul style="list-style:none;padding:0;">
|
|
62
|
+
<li style="padding:6px 0;border-bottom:1px solid var(--border);font-size:13px;">
|
|
63
|
+
<strong>Q001</strong>: {Question?}
|
|
64
|
+
<span class="badge badge-open" style="margin-left:4px;">open</span>
|
|
65
|
+
</li>
|
|
66
|
+
<li style="padding:6px 0;font-size:13px;">
|
|
67
|
+
<strong>Q002</strong>: {Question?}
|
|
68
|
+
<span class="badge badge-deferred" style="margin-left:4px;">deferred</span>
|
|
69
|
+
</li>
|
|
70
|
+
</ul>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<div class="card" data-arch-id="TN1">
|
|
75
|
+
<h2>Additional Notes</h2>
|
|
76
|
+
<p style="color:var(--text-muted);font-size:13px;">{Additional context, constraints, or design notes that don't fit in other sections}</p>
|
|
77
|
+
</div>
|
|
78
|
+
</main>
|
|
79
|
+
|
|
80
|
+
<script>
|
|
81
|
+
function toggleTheme() {
|
|
82
|
+
const html = document.documentElement;
|
|
83
|
+
const isLight = html.classList.toggle('light');
|
|
84
|
+
document.getElementById('theme-toggle').textContent = isLight ? 'π Dark' : 'βοΈ Light';
|
|
85
|
+
}
|
|
86
|
+
</script>
|
|
87
|
+
<script src="architect-actions.js"></script>
|
|
88
|
+
</body>
|
|
89
|
+
</html>
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="vi">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Tech Stack β {project}</title>
|
|
7
|
+
<link rel="stylesheet" href="style.css" />
|
|
8
|
+
</head>
|
|
9
|
+
<body data-arch-slug="tech-stack">
|
|
10
|
+
<nav class="nav-sidebar">
|
|
11
|
+
<div class="logo">
|
|
12
|
+
<span>ViePilot Architect Mode</span>
|
|
13
|
+
<strong>{project}</strong>
|
|
14
|
+
</div>
|
|
15
|
+
<ul>
|
|
16
|
+
<li><a href="index.html">π Hub</a></li>
|
|
17
|
+
<li><a href="architecture.html">ποΈ Architecture</a></li>
|
|
18
|
+
<li><a href="sequence-diagram.html">π¬ Sequence</a></li>
|
|
19
|
+
<li><a href="data-flow.html">π Data Flow</a></li>
|
|
20
|
+
<li><a href="decisions.html">π Decisions (ADR)</a></li>
|
|
21
|
+
<li><a href="tech-stack.html" class="active">π οΈ Tech Stack</a></li>
|
|
22
|
+
<li><a href="tech-notes.html">π Tech Notes</a></li>
|
|
23
|
+
<li><a href="feature-map.html">πΊοΈ Feature Map</a></li>
|
|
24
|
+
<li><a href="erd.html">ποΈ ERD</a></li>
|
|
25
|
+
<li><a href="user-use-cases.html">π€ Use Cases</a></li>
|
|
26
|
+
<li><a href="deployment.html">π Deployment</a></li>
|
|
27
|
+
<li><a href="apis.html">π APIs</a></li>
|
|
28
|
+
</ul>
|
|
29
|
+
</nav>
|
|
30
|
+
|
|
31
|
+
<main class="main-content">
|
|
32
|
+
<div class="page-header">
|
|
33
|
+
<div>
|
|
34
|
+
<h1>π οΈ Tech Stack</h1>
|
|
35
|
+
<p>Layer-by-layer technology choices and alternatives</p>
|
|
36
|
+
</div>
|
|
37
|
+
<button id="theme-toggle" onclick="toggleTheme()">βοΈ Light</button>
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
<div class="card">
|
|
41
|
+
<h2>Stack Layers</h2>
|
|
42
|
+
<table>
|
|
43
|
+
<thead>
|
|
44
|
+
<tr>
|
|
45
|
+
<th>Layer</th>
|
|
46
|
+
<th>Technology</th>
|
|
47
|
+
<th>Version</th>
|
|
48
|
+
<th>Why Chosen</th>
|
|
49
|
+
<th>Alternatives</th>
|
|
50
|
+
</tr>
|
|
51
|
+
</thead>
|
|
52
|
+
<tbody>
|
|
53
|
+
<tr data-arch-id="TS1">
|
|
54
|
+
<td><strong>Frontend</strong></td>
|
|
55
|
+
<td>{e.g. React + TypeScript}</td>
|
|
56
|
+
<td>{version}</td>
|
|
57
|
+
<td>{rationale}</td>
|
|
58
|
+
<td>{alternatives}</td>
|
|
59
|
+
</tr>
|
|
60
|
+
<tr data-arch-id="TS2">
|
|
61
|
+
<td><strong>Backend</strong></td>
|
|
62
|
+
<td>{e.g. Node.js + Express}</td>
|
|
63
|
+
<td>{version}</td>
|
|
64
|
+
<td>{rationale}</td>
|
|
65
|
+
<td>{alternatives}</td>
|
|
66
|
+
</tr>
|
|
67
|
+
<tr data-arch-id="TS3">
|
|
68
|
+
<td><strong>Database</strong></td>
|
|
69
|
+
<td>{e.g. PostgreSQL}</td>
|
|
70
|
+
<td>{version}</td>
|
|
71
|
+
<td>{rationale}</td>
|
|
72
|
+
<td>{alternatives}</td>
|
|
73
|
+
</tr>
|
|
74
|
+
<tr data-arch-id="TS4">
|
|
75
|
+
<td><strong>Cache</strong></td>
|
|
76
|
+
<td>{e.g. Redis}</td>
|
|
77
|
+
<td>{version}</td>
|
|
78
|
+
<td>{rationale}</td>
|
|
79
|
+
<td>{alternatives}</td>
|
|
80
|
+
</tr>
|
|
81
|
+
<tr data-arch-id="TS5">
|
|
82
|
+
<td><strong>Infrastructure</strong></td>
|
|
83
|
+
<td>{e.g. AWS ECS + RDS}</td>
|
|
84
|
+
<td>β</td>
|
|
85
|
+
<td>{rationale}</td>
|
|
86
|
+
<td>{alternatives}</td>
|
|
87
|
+
</tr>
|
|
88
|
+
<tr data-arch-id="TS6">
|
|
89
|
+
<td><strong>DevOps</strong></td>
|
|
90
|
+
<td>{e.g. GitHub Actions + Terraform}</td>
|
|
91
|
+
<td>β</td>
|
|
92
|
+
<td>{rationale}</td>
|
|
93
|
+
<td>{alternatives}</td>
|
|
94
|
+
</tr>
|
|
95
|
+
</tbody>
|
|
96
|
+
</table>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
<div class="card">
|
|
100
|
+
<h2>Stack Summary</h2>
|
|
101
|
+
<p style="color:var(--text-muted);font-size:13px;">{High-level summary of technology choices and their coherence as a system}</p>
|
|
102
|
+
</div>
|
|
103
|
+
</main>
|
|
104
|
+
|
|
105
|
+
<script>
|
|
106
|
+
function toggleTheme() {
|
|
107
|
+
const html = document.documentElement;
|
|
108
|
+
const isLight = html.classList.toggle('light');
|
|
109
|
+
document.getElementById('theme-toggle').textContent = isLight ? 'π Dark' : 'βοΈ Light';
|
|
110
|
+
}
|
|
111
|
+
</script>
|
|
112
|
+
<script src="architect-actions.js"></script>
|
|
113
|
+
</body>
|
|
114
|
+
</html>
|