@appsforgood/next-supabase-kit 0.1.4 → 0.1.6

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/DOGFOOD.md +24 -0
  3. package/LOOP_CODING.md +107 -0
  4. package/MAINTAINER_RELEASE.md +100 -0
  5. package/README.md +40 -4
  6. package/REPOSITORY_SETTINGS.md +7 -3
  7. package/SUPPLY_CHAIN.md +5 -5
  8. package/UPGRADE.md +2 -1
  9. package/antigravity/commands/accessibility-pass.toml +16 -0
  10. package/antigravity/commands/browser-qa.toml +18 -0
  11. package/antigravity/commands/distinctiveness-pass.toml +16 -0
  12. package/antigravity/commands/frontend.toml +5 -4
  13. package/antigravity/commands/layout-cleanup.toml +16 -0
  14. package/antigravity/commands/responsive-cleanup.toml +16 -0
  15. package/antigravity/commands/screenshot-critique.toml +16 -0
  16. package/antigravity/commands/ui-audit.toml +17 -0
  17. package/antigravity/commands/ui-polish.toml +17 -0
  18. package/antigravity/plugin.json +9 -0
  19. package/checklists/ui-acceptance-rubric.md +58 -0
  20. package/checklists/ui-detectors.md +75 -0
  21. package/dist/index.js +1090 -411
  22. package/dist/index.js.map +1 -1
  23. package/dist/studio/office/assets/office.css +188 -29
  24. package/dist/studio/office/assets/office.js +72 -50
  25. package/dist/studio/wizard/assets/wizard.css +157 -26
  26. package/dist/studio/wizard/assets/wizard.js +78 -70
  27. package/examples/next-supabase-installed/.agent-kit/agent-roster.json +7 -3
  28. package/examples/next-supabase-installed/.agent-kit/manifest.json +13 -11
  29. package/examples/next-supabase-installed/audit-output.json +22 -2
  30. package/examples/next-supabase-installed/tree.txt +1 -0
  31. package/package.json +28 -7
  32. package/prompts/ui-command-index.md +124 -0
  33. package/research/summaries/agentic-engineering-maturity-levels.md +54 -0
  34. package/rosters/next-supabase-default-council.json +37 -12
  35. package/runtime-skills/ui-improvement-harness/SKILL.md +12 -0
  36. package/schemas/agentic-level.schema.json +47 -0
  37. package/schemas/onboarding-state.schema.json +4 -1
  38. package/skills/ui-improvement-harness.md +96 -0
  39. package/templates/next-supabase/AGENT_ROSTER.md +6 -3
  40. package/templates/next-supabase/ASSISTANT_ADAPTERS.md +3 -1
  41. package/templates/next-supabase/DECISIONS.md +14 -0
  42. package/templates/next-supabase/DESIGN.md +3 -0
  43. package/templates/next-supabase/DOCS.md +7 -1
  44. package/templates/next-supabase/LOOP_CODING.md +98 -0
  45. package/templates/next-supabase/QUALITY_GATES.md +4 -2
  46. package/templates/next-supabase/SKILLS.md +14 -0
  47. package/templates/next-supabase/SPEC.md +5 -1
  48. package/templates/next-supabase/STYLE_GUIDE.md +3 -1
  49. package/templates/next-supabase/TESTING.md +14 -0
@@ -15,17 +15,28 @@
15
15
  }
16
16
 
17
17
  @media (prefers-reduced-motion: reduce) {
18
- *, *::before, *::after {
18
+ *,
19
+ *::before,
20
+ *::after {
19
21
  animation-duration: 0.01ms !important;
20
22
  transition-duration: 0.01ms !important;
21
23
  }
22
24
  }
23
25
 
24
- * { box-sizing: border-box; }
26
+ * {
27
+ box-sizing: border-box;
28
+ }
25
29
 
26
30
  body {
27
31
  margin: 0;
28
- font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
32
+ font-family:
33
+ Inter,
34
+ ui-sans-serif,
35
+ system-ui,
36
+ -apple-system,
37
+ BlinkMacSystemFont,
38
+ "Segoe UI",
39
+ sans-serif;
29
40
  color: var(--ink);
30
41
  background: var(--bg);
31
42
  line-height: 1.55;
@@ -131,6 +142,58 @@ body {
131
142
  color: var(--muted);
132
143
  }
133
144
 
145
+ .office-promo .btn:hover {
146
+ filter: brightness(1.05);
147
+ }
148
+
149
+ .wizard-level-pill {
150
+ margin-top: 8px;
151
+ display: inline-block;
152
+ font-size: 12px;
153
+ padding: 4px 10px;
154
+ border-radius: 999px;
155
+ background: rgba(15, 118, 110, 0.25);
156
+ border: 1px solid rgba(153, 246, 228, 0.35);
157
+ color: #99f6e4;
158
+ }
159
+
160
+ .agentic-level-card {
161
+ margin: 12px 0 16px;
162
+ padding: 12px 14px;
163
+ border-radius: 10px;
164
+ border: 1px solid #d9e2ec;
165
+ background: #f8fafc;
166
+ font-size: 14px;
167
+ }
168
+
169
+ .agentic-level-card .hint-inline {
170
+ font-size: 12px;
171
+ color: #64748b;
172
+ }
173
+
174
+ .adapter-chip {
175
+ margin-top: 10px;
176
+ padding: 8px 10px;
177
+ border-radius: 8px;
178
+ font-size: 13px;
179
+ border: 1px solid #d9e2ec;
180
+ }
181
+
182
+ .adapter-chip.ok {
183
+ background: #ecfdf5;
184
+ border-color: #6ee7b7;
185
+ }
186
+
187
+ .adapter-chip.warn {
188
+ background: #fffbeb;
189
+ border-color: #fcd34d;
190
+ }
191
+
192
+ .adapter-chip.error {
193
+ background: #fef2f2;
194
+ border-color: #fca5a5;
195
+ }
196
+
134
197
  .office-promo .btn {
135
198
  display: inline-block;
136
199
  background: var(--accent);
@@ -152,8 +215,13 @@ body {
152
215
  }
153
216
 
154
217
  @media (max-width: 860px) {
155
- .shell { grid-template-columns: 1fr; }
156
- .rail { border-right: 0; border-bottom: 1px solid var(--line); }
218
+ .shell {
219
+ grid-template-columns: 1fr;
220
+ }
221
+ .rail {
222
+ border-right: 0;
223
+ border-bottom: 1px solid var(--line);
224
+ }
157
225
  }
158
226
 
159
227
  .rail {
@@ -188,7 +256,7 @@ body {
188
256
  width: 56px;
189
257
  height: 56px;
190
258
  border-radius: 50%;
191
- background: conic-gradient(var(--accent) calc(var(--pct) * 1%), rgba(255,255,255,0.12) 0);
259
+ background: conic-gradient(var(--accent) calc(var(--pct) * 1%), rgba(255, 255, 255, 0.12) 0);
192
260
  display: grid;
193
261
  place-items: center;
194
262
  position: relative;
@@ -253,12 +321,21 @@ body {
253
321
  letter-spacing: 0.04em;
254
322
  padding: 2px 7px;
255
323
  border-radius: 999px;
256
- border: 1px solid rgba(255,255,255,0.15);
324
+ border: 1px solid rgba(255, 255, 255, 0.15);
257
325
  }
258
326
 
259
- .chip.done { background: rgba(22, 101, 52, 0.35); color: #bbf7d0; }
260
- .chip.progress { background: rgba(180, 83, 9, 0.35); color: #fde68a; }
261
- .chip.optional { background: rgba(100, 116, 139, 0.35); color: #e2e8f0; }
327
+ .chip.done {
328
+ background: rgba(22, 101, 52, 0.35);
329
+ color: #bbf7d0;
330
+ }
331
+ .chip.progress {
332
+ background: rgba(180, 83, 9, 0.35);
333
+ color: #fde68a;
334
+ }
335
+ .chip.optional {
336
+ background: rgba(100, 116, 139, 0.35);
337
+ color: #e2e8f0;
338
+ }
262
339
 
263
340
  .main {
264
341
  padding: clamp(20px, 4vw, 40px);
@@ -274,8 +351,18 @@ body {
274
351
  font-size: 14px;
275
352
  }
276
353
 
277
- .status.ok { display: block; background: #ecfdf5; border: 1px solid #86efac; color: var(--ok); }
278
- .status.error { display: block; background: #fef2f2; border: 1px solid #fca5a5; color: #991b1b; }
354
+ .status.ok {
355
+ display: block;
356
+ background: #ecfdf5;
357
+ border: 1px solid #86efac;
358
+ color: var(--ok);
359
+ }
360
+ .status.error {
361
+ display: block;
362
+ background: #fef2f2;
363
+ border: 1px solid #fca5a5;
364
+ color: #991b1b;
365
+ }
279
366
 
280
367
  .card {
281
368
  background: var(--panel);
@@ -322,7 +409,9 @@ label span {
322
409
  margin-top: 3px;
323
410
  }
324
411
 
325
- input, select, textarea {
412
+ input,
413
+ select,
414
+ textarea {
326
415
  width: 100%;
327
416
  border: 1px solid var(--line);
328
417
  border-radius: 10px;
@@ -332,14 +421,23 @@ input, select, textarea {
332
421
  background: #fff;
333
422
  }
334
423
 
335
- input:focus, select:focus, textarea:focus {
424
+ input:focus,
425
+ select:focus,
426
+ textarea:focus {
336
427
  outline: 2px solid var(--accent-soft);
337
428
  border-color: var(--accent);
338
429
  }
339
430
 
340
- textarea { min-height: 120px; resize: vertical; }
431
+ textarea {
432
+ min-height: 120px;
433
+ resize: vertical;
434
+ }
341
435
 
342
- .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; }
436
+ .grid {
437
+ display: grid;
438
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
439
+ gap: 12px;
440
+ }
343
441
 
344
442
  .hint {
345
443
  background: #f0fdfa;
@@ -370,7 +468,9 @@ textarea { min-height: 120px; resize: vertical; }
370
468
  display: none;
371
469
  }
372
470
 
373
- .field-error.show { display: block; }
471
+ .field-error.show {
472
+ display: block;
473
+ }
374
474
 
375
475
  .depth-grid {
376
476
  display: grid;
@@ -395,8 +495,15 @@ textarea { min-height: 120px; resize: vertical; }
395
495
  background: #f0fdfa;
396
496
  }
397
497
 
398
- .depth-card strong { display: block; margin-bottom: 6px; }
399
- .depth-card p { margin: 0; font-size: 13px; color: var(--muted); }
498
+ .depth-card strong {
499
+ display: block;
500
+ margin-bottom: 6px;
501
+ }
502
+ .depth-card p {
503
+ margin: 0;
504
+ font-size: 13px;
505
+ color: var(--muted);
506
+ }
400
507
 
401
508
  .stack-pills {
402
509
  display: flex;
@@ -414,9 +521,22 @@ textarea { min-height: 120px; resize: vertical; }
414
521
  border: 1px solid var(--line);
415
522
  }
416
523
 
417
- .review dl { margin: 0; display: grid; gap: 14px; }
418
- .review dt { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); font-weight: 700; }
419
- .review dd { margin: 4px 0 0; white-space: pre-wrap; }
524
+ .review dl {
525
+ margin: 0;
526
+ display: grid;
527
+ gap: 14px;
528
+ }
529
+ .review dt {
530
+ font-size: 11px;
531
+ text-transform: uppercase;
532
+ letter-spacing: 0.06em;
533
+ color: var(--muted);
534
+ font-weight: 700;
535
+ }
536
+ .review dd {
537
+ margin: 4px 0 0;
538
+ white-space: pre-wrap;
539
+ }
420
540
 
421
541
  .preview {
422
542
  background: #f8fafc;
@@ -455,9 +575,18 @@ button.btn {
455
575
  cursor: pointer;
456
576
  }
457
577
 
458
- button.btn.primary { background: var(--accent); color: #fff; }
459
- button.btn.secondary { background: #edf2f7; color: var(--ink); }
460
- button.btn:disabled { opacity: 0.5; cursor: not-allowed; }
578
+ button.btn.primary {
579
+ background: var(--accent);
580
+ color: #fff;
581
+ }
582
+ button.btn.secondary {
583
+ background: #edf2f7;
584
+ color: var(--ink);
585
+ }
586
+ button.btn:disabled {
587
+ opacity: 0.5;
588
+ cursor: not-allowed;
589
+ }
461
590
 
462
591
  .complete-icon {
463
592
  font-size: 48px;
@@ -480,7 +609,9 @@ code {
480
609
  border-radius: 4px;
481
610
  }
482
611
 
483
- .hidden { display: none !important; }
612
+ .hidden {
613
+ display: none !important;
614
+ }
484
615
 
485
616
  .agent-roster {
486
617
  list-style: none;
@@ -14,7 +14,9 @@
14
14
  designDraft: null,
15
15
  messagingDraft: null,
16
16
  ideSurfaces: boot.ideSurfaces || [],
17
- agents: boot.agents || []
17
+ agents: boot.agents || [],
18
+ agenticLevel: null,
19
+ lastAdapterValidation: null
18
20
  };
19
21
 
20
22
  const els = {
@@ -22,6 +24,7 @@
22
24
  projectName: document.getElementById("project-name"),
23
25
  ringPct: document.getElementById("ring-pct"),
24
26
  ring: document.getElementById("progress-ring"),
27
+ levelPill: document.getElementById("wizard-level-pill"),
25
28
  sectionNav: document.getElementById("section-nav"),
26
29
  card: document.getElementById("wizard-card"),
27
30
  footer: document.getElementById("wizard-footer"),
@@ -83,10 +86,15 @@
83
86
  state.designDraft = data.designDraft;
84
87
  state.messagingDraft = data.messagingDraft;
85
88
  if (Array.isArray(data.agents) && data.agents.length) state.agents = data.agents;
89
+ state.agenticLevel = data.agenticLevel || null;
86
90
  els.projectName.textContent = data.projectName || "your project";
87
91
  const pct = data.progress?.percent ?? 0;
88
92
  els.ringPct.textContent = pct + "%";
89
93
  els.ring.style.setProperty("--pct", String(pct));
94
+ if (els.levelPill && state.agenticLevel) {
95
+ els.levelPill.textContent = "L" + state.agenticLevel.currentLevel + " → L" + state.agenticLevel.targetLevel;
96
+ els.levelPill.hidden = false;
97
+ }
90
98
  render();
91
99
  }
92
100
 
@@ -128,10 +136,8 @@
128
136
  const sections = state.progress?.sections || [];
129
137
  els.sectionNav.innerHTML = sections
130
138
  .map((s) => {
131
- const chipClass =
132
- s.status === "done" ? "done" : s.status === "in_progress" ? "progress" : s.status === "optional" ? "optional" : "";
133
- const chipLabel =
134
- s.status === "done" ? "Done" : s.status === "in_progress" ? "Now" : s.status === "optional" ? "Optional" : "—";
139
+ const chipClass = s.status === "done" ? "done" : s.status === "in_progress" ? "progress" : s.status === "optional" ? "optional" : "";
140
+ const chipLabel = s.status === "done" ? "Done" : s.status === "in_progress" ? "Now" : s.status === "optional" ? "Optional" : "";
135
141
  return (
136
142
  '<li><button type="button" data-section="' +
137
143
  s.id +
@@ -162,14 +168,7 @@
162
168
 
163
169
  function renderTeamIntro() {
164
170
  const cards = state.agents
165
- .map(
166
- (a) =>
167
- '<li class="agent-card"><strong>' +
168
- escapeHtml(a.name) +
169
- "</strong><p>" +
170
- escapeHtml(a.roleSummary) +
171
- "</p></li>"
172
- )
171
+ .map((a) => '<li class="agent-card"><strong>' + escapeHtml(a.name) + "</strong><p>" + escapeHtml(a.roleSummary) + "</p></li>")
173
172
  .join("");
174
173
  return (
175
174
  '<p class="why">Next you will brief each specialist — one step per agent. Skip any you are not ready to answer; you can return later.</p>' +
@@ -202,9 +201,7 @@
202
201
  }
203
202
 
204
203
  function renderHome() {
205
- const pills = (boot.stackSignals || [])
206
- .map((s) => '<span class="pill">' + escapeHtml(s) + "</span>")
207
- .join("");
204
+ const pills = (boot.stackSignals || []).map((s) => '<span class="pill">' + escapeHtml(s) + "</span>").join("");
208
205
  const agentCount = state.agents.length || boot.agents?.length || 0;
209
206
  const officePromo =
210
207
  '<div class="office-promo">' +
@@ -227,19 +224,33 @@
227
224
  pills +
228
225
  "</div>" +
229
226
  '<p class="why" style="margin-top:20px"><strong>Choose your path</strong></p>' +
227
+ agenticLevelHomeBlock() +
230
228
  '<div class="depth-grid">' +
231
229
  depthCard("quick", "Quick (~10 min)", "IDE setup, agent briefings, and product essentials.") +
232
230
  depthCard("standard", "Standard (~15 min)", "Quick plus visual QA tier for UI changes.") +
233
231
  depthCard("complete", "Complete (~25 min)", "Standard plus DESIGN and MESSAGING intake drafts.") +
234
232
  "</div>" +
235
233
  (state.progress?.recommendedNext
236
- ? '<p class="why" style="margin-top:18px">Continue: <strong>' +
237
- escapeHtml(state.progress.recommendedNext) +
238
- "</strong></p>"
234
+ ? '<p class="why" style="margin-top:18px">Continue: <strong>' + escapeHtml(state.progress.recommendedNext) + "</strong></p>"
239
235
  : "")
240
236
  );
241
237
  }
242
238
 
239
+ function agenticLevelHomeBlock() {
240
+ const level = state.agenticLevel;
241
+ if (!level) return "";
242
+ return (
243
+ '<div class="agentic-level-card">' +
244
+ "<p><strong>Agentic level</strong> L" +
245
+ level.currentLevel +
246
+ " → target L" +
247
+ level.targetLevel +
248
+ ' <span class="hint-inline">(setup progress is separate from audit readiness and visual QA tiers)</span></p>' +
249
+ (level.maintainerNote ? '<p class="hint">' + escapeHtml(level.maintainerNote) + "</p>" : "") +
250
+ "</div>"
251
+ );
252
+ }
253
+
243
254
  function depthCard(id, title, desc) {
244
255
  const sel = state.depth === id ? " selected" : "";
245
256
  return (
@@ -259,9 +270,9 @@
259
270
  const val = escapeHtml(state.form[name] || "");
260
271
  if (type === "textarea") {
261
272
  return (
262
- "<label for=\"" +
273
+ '<label for="' +
263
274
  name +
264
- "\">" +
275
+ '">' +
265
276
  escapeHtml(label) +
266
277
  (hint ? "<span>" + escapeHtml(hint) + "</span>" : "") +
267
278
  '</label><textarea id="' +
@@ -278,9 +289,9 @@
278
289
  );
279
290
  }
280
291
  return (
281
- "<label for=\"" +
292
+ '<label for="' +
282
293
  name +
283
- "\">" +
294
+ '">' +
284
295
  escapeHtml(label) +
285
296
  (hint ? "<span>" + escapeHtml(hint) + "</span>" : "") +
286
297
  '</label><input id="' +
@@ -309,25 +320,11 @@
309
320
  ),
310
321
  productCategory: () => {
311
322
  const opts = (boot.categories || [])
312
- .map(
313
- (c) =>
314
- '<option value="' +
315
- c +
316
- '"' +
317
- (state.form.productCategory === c ? " selected" : "") +
318
- ">" +
319
- c +
320
- "</option>"
321
- )
323
+ .map((c) => '<option value="' + c + '"' + (state.form.productCategory === c ? " selected" : "") + ">" + c + "</option>")
322
324
  .join("");
323
- return (
324
- '<label for="productCategory">Category</label><select id="productCategory" name="productCategory">' +
325
- opts +
326
- "</select>"
327
- );
325
+ return '<label for="productCategory">Category</label><select id="productCategory" name="productCategory">' + opts + "</select>";
328
326
  },
329
- primaryAudience: () =>
330
- inputField("primaryAudience", "Primary user or buyer", "", "text", "Who uses or pays for this product?"),
327
+ primaryAudience: () => inputField("primaryAudience", "Primary user or buyer", "", "text", "Who uses or pays for this product?"),
331
328
  primaryWorkflows: () =>
332
329
  inputField(
333
330
  "primaryWorkflows",
@@ -338,16 +335,7 @@
338
335
  ),
339
336
  tenantModel: () => {
340
337
  const opts = (boot.tenantModels || [])
341
- .map(
342
- (c) =>
343
- '<option value="' +
344
- c +
345
- '"' +
346
- (state.form.tenantModel === c ? " selected" : "") +
347
- ">" +
348
- c +
349
- "</option>"
350
- )
338
+ .map((c) => '<option value="' + c + '"' + (state.form.tenantModel === c ? " selected" : "") + ">" + c + "</option>")
351
339
  .join("");
352
340
  return '<label for="tenantModel">Who uses the system?</label><select id="tenantModel" name="tenantModel">' + opts + "</select>";
353
341
  },
@@ -363,18 +351,17 @@
363
351
  "textarea",
364
352
  "Describe auth boundaries agents must not break."
365
353
  ),
366
- uiPreferred: () =>
367
- inputField("uiPreferred", "UI should feel like…", "", "textarea", "Task-first, clear hierarchy, readable typography."),
368
- uiAvoid: () =>
369
- inputField("uiAvoid", "UI should avoid…", "Optional.", "textarea", "Generic SaaS heroes, card soup, fake metrics."),
370
- valueProposition: () =>
371
- inputField("valueProposition", "Value proposition", "", "textarea", "What outcome do users get?"),
354
+ uiPreferred: () => inputField("uiPreferred", "UI should feel like…", "", "textarea", "Task-first, clear hierarchy, readable typography."),
355
+ uiAvoid: () => inputField("uiAvoid", "UI should avoid…", "Optional.", "textarea", "Generic SaaS heroes, card soup, fake metrics."),
356
+ valueProposition: () => inputField("valueProposition", "Value proposition", "", "textarea", "What outcome do users get?"),
372
357
  proof: () => inputField("proof", "Proof points", "One per line. Real evidence only.", "textarea", ""),
373
358
  objections: () => inputField("objections", "Objections", "One per line. Optional.", "textarea", ""),
374
359
  qualityTarget: () => {
375
360
  const q = state.form.qualityTarget || "baseline-setup";
376
361
  return (
377
- '<label for="qualityTarget">Quality target</label><select id="qualityTarget" name="qualityTarget">' +
362
+ '<label for="qualityTarget">Audit readiness target</label>' +
363
+ '<p class="hint">This is your <strong>audit readiness</strong> goal (agent-kit audit), not Agentic L5/L6 or visual QA tier.</p>' +
364
+ '<select id="qualityTarget" name="qualityTarget">' +
378
365
  optionQuality("baseline-setup", "baseline-setup — kit installed, filling evidence", q) +
379
366
  optionQuality("needs-improvement", "needs-improvement — active delivery", q) +
380
367
  optionQuality("best-practice-candidate", "best-practice-candidate — clean audit goal", q) +
@@ -383,22 +370,15 @@
383
370
  },
384
371
  ideSurface: () => {
385
372
  const opts = state.ideSurfaces
386
- .map(
387
- (s) =>
388
- '<option value="' +
389
- s.id +
390
- '"' +
391
- (state.form.ideSurface === s.id ? " selected" : "") +
392
- ">" +
393
- escapeHtml(s.label) +
394
- "</option>"
395
- )
373
+ .map((s) => '<option value="' + s.id + '"' + (state.form.ideSurface === s.id ? " selected" : "") + ">" + escapeHtml(s.label) + "</option>")
396
374
  .join("");
375
+ const chip = renderAdapterChip(state.lastAdapterValidation);
397
376
  return (
398
377
  '<label for="ideSurface">Primary AI coding tool</label><select id="ideSurface" name="ideSurface" required>' +
399
378
  '<option value="">Choose your IDE…</option>' +
400
379
  opts +
401
- '</select><p class="why">We configure instructions for this path: <code id="ide-path"></code></p>'
380
+ '</select><p class="why">We configure instructions for this path: <code id="ide-path"></code></p>' +
381
+ chip
402
382
  );
403
383
  },
404
384
  visualQaTier: () => {
@@ -456,9 +436,35 @@
456
436
  );
457
437
  }
458
438
 
439
+ function renderAdapterChip(validation) {
440
+ if (!validation || !validation.target) return "";
441
+ const kind = validation.fail > 0 ? "error" : validation.warn > 0 ? "warn" : "ok";
442
+ const label =
443
+ validation.fail > 0
444
+ ? "Adapter validate: " + validation.fail + " fail"
445
+ : validation.warn > 0
446
+ ? "Adapter validate: pass with warnings"
447
+ : "Adapter validate: pass";
448
+ return '<p class="adapter-chip ' + kind + '" role="status">' + escapeHtml(label) + " (" + escapeHtml(validation.target) + ")</p>";
449
+ }
450
+
459
451
  function renderComplete() {
452
+ const level = state.agenticLevel;
453
+ const climb = (level?.climbSteps || [])
454
+ .slice(0, 3)
455
+ .map((step) => "<li>" + escapeHtml(step.remediation) + "</li>")
456
+ .join("");
460
457
  return (
461
- '<div class="complete-icon" aria-hidden="true">✓</div><h2>Setup saved</h2><p class="why">Agents read <code>.agent-kit/project-context.md</code> and <code>.agent-kit/agent-briefs.md</code> before meaningful work.</p><ol class="next-steps"><li>Run <code>agent-kit audit</code></li><li>Reload your IDE so it picks up instructions for your chosen tool</li><li>Return anytime with <code>agent-kit setup</code></li></ol>'
458
+ '<div class="complete-icon" aria-hidden="true">✓</div><h2>Setup saved</h2>' +
459
+ (level ? '<p class="why">Agentic level <strong>L' + level.currentLevel + "</strong> (target L" + level.targetLevel + ").</p>" : "") +
460
+ '<p class="why">Agents read <code>.agent-kit/project-context.md</code> and <code>.agent-kit/agent-briefs.md</code> before meaningful work.</p>' +
461
+ '<ol class="next-steps">' +
462
+ "<li>Run eval loop from <code>LOOP_CODING.md</code>: <code>npm test</code>, <code>agent-kit audit --min-readiness baseline-setup</code></li>" +
463
+ "<li>Validate IDE adapters: <code>agent-kit adapter validate cursor|codex|all</code></li>" +
464
+ "<li>Reload your IDE so it picks up council subagents and rules</li>" +
465
+ "<li>Return anytime with <code>agent-kit setup</code></li>" +
466
+ "</ol>" +
467
+ (climb ? '<h3>Next climb steps</h3><ol class="next-steps">' + climb + "</ol>" : "")
462
468
  );
463
469
  }
464
470
 
@@ -619,11 +625,13 @@
619
625
  await patchState({ currentSection: step.section, currentStep: state.stepIndex });
620
626
  }
621
627
  if (step?.section === "ide" && fieldValue("ideSurface")) {
622
- await api("/api/checklist/ide", {
628
+ const ideResult = await api("/api/checklist/ide", {
623
629
  method: "POST",
624
630
  headers: { "Content-Type": "application/json" },
625
631
  body: JSON.stringify({ ideSurface: fieldValue("ideSurface") })
626
632
  });
633
+ state.lastAdapterValidation = ideResult.adapterValidation || null;
634
+ state.agenticLevel = ideResult.agenticLevel || state.agenticLevel;
627
635
  }
628
636
  if (step?.section === "visualQa" && fieldValue("visualQaTier")) {
629
637
  await api("/api/checklist/visual-qa", {
@@ -70,6 +70,7 @@
70
70
  "frontend-distinctiveness-benchmark",
71
71
  "frontend-product-quality-rubric",
72
72
  "frontend-design-system",
73
+ "ui-improvement-harness",
73
74
  "visual-regression-qa",
74
75
  "accessibility-wcag"
75
76
  ],
@@ -171,7 +172,7 @@
171
172
  },
172
173
  {
173
174
  "id": "frontend-change",
174
- "triggers": ["screen", "component", "layout", "design", "responsive", "accessibility", "screenshot"],
175
+ "triggers": ["screen", "component", "layout", "design", "responsive", "accessibility", "screenshot", "ui audit", "ui polish", "browser qa"],
175
176
  "sequence": ["planner", "frontend-design-lead", "marketing-copy-lead", "nextjs-engineer", "qa-engineer", "docs-maintainer"],
176
177
  "council": ["frontend-design-lead", "marketing-copy-lead", "qa-engineer"],
177
178
  "requiredOutputs": [
@@ -183,10 +184,13 @@
183
184
  "design critique verdict",
184
185
  "frontend product-quality scorecard",
185
186
  "domain-specific UI rationale",
187
+ "UI detector findings and severity",
188
+ "UI command workflow applied when polishing or auditing",
186
189
  "visual QA evidence",
187
190
  "state coverage",
188
191
  "accessibility checks",
189
- "desktop/mobile verification"
192
+ "desktop/mobile verification",
193
+ "authenticated screen evidence when applicable"
190
194
  ]
191
195
  },
192
196
  {
@@ -219,7 +223,7 @@
219
223
  "Meaningful multi-agent work must record council-session evidence in COUNCIL.md or a structured record that follows .agent-kit/schemas/council-session.schema.json.",
220
224
  "Planner starts planning and ambiguous requests by default.",
221
225
  "Lead Architect must review core changes before implementation.",
222
- "Frontend Design Lead must record reference-set evidence, anti-references, a design critique verdict, a distinctiveness benchmark, and a frontend product-quality scorecard before accepting significant frontend work.",
226
+ "Frontend Design Lead must record reference-set evidence, anti-references, a design critique verdict, a distinctiveness benchmark, a frontend product-quality scorecard, UI detector severity findings, and desktop/mobile screenshot evidence before accepting significant frontend work.",
223
227
  "Marketing Copy Lead must ask discovery questions and record audience, pain, outcome, value proposition, proof, objections, voice/tone, and conversion goal before accepting public-facing or conversion-facing copy.",
224
228
  "Security Reviewer must review auth, data mutation, external-call, dependency, secret, and release-risk changes.",
225
229
  "QA Engineer must verify behavior changes before completion.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "packageName": "@appsforgood/next-supabase-kit",
3
- "packageVersion": "0.1.4",
3
+ "packageVersion": "0.1.6",
4
4
  "stack": "next-supabase",
5
5
  "installedAt": "2026-06-17T11:49:38.732Z",
6
6
  "docs": [
@@ -19,6 +19,7 @@
19
19
  "STYLE_GUIDE.md",
20
20
  "SECURITY.md",
21
21
  "TESTING.md",
22
+ "LOOP_CODING.md",
22
23
  "DEPLOYMENT.md",
23
24
  "UPGRADE.md"
24
25
  ],
@@ -39,20 +40,21 @@
39
40
  "modelRouting": ".agent-kit/model-routing.json",
40
41
  "templateHashes": {
41
42
  "AGENTS.md": "c7f3e7360938a1ed804d2110e9af96e6f09d50c49138063bef0db1642ddaf84f",
42
- "AGENT_ROSTER.md": "fb88198d0a5f911ec8cbaa2850c1a47e1dbd1fe2c8144f9ce633bbfc1ec414d3",
43
- "ASSISTANT_ADAPTERS.md": "b5fb02dbab39bab1af5122050cb86acbc726e24226e7024a3b984d5fdc12f798",
43
+ "AGENT_ROSTER.md": "40147eecf3977bf64431204b67f24eb277a834ba5b6f894c053c79c0a9dbb8f5",
44
+ "ASSISTANT_ADAPTERS.md": "4d37ba6555814cf18c6ac2a302a614af07bb33b0ac0eb5f19886c3af3328cb63",
44
45
  "COUNCIL.md": "40bec9051664c9c38b8360ee16f21b5e4716030d19c493cdec67395ab06528e1",
45
- "SKILLS.md": "3c3c2eb40438a42026479dccac7bbf084ba22e2d758c425dff59385d05eae3bd",
46
- "SPEC.md": "bb0406a141338b630a82026e4a2bb37f38448b3641d3b3ada62d146711a4fbfe",
47
- "DECISIONS.md": "0c08d1106a40f829b197d552d0397c9bcd9af7e168a55c47ff5be033c6035ec6",
48
- "DOCS.md": "4a2940e8d2526d4ad8f481c82451dd65d62f0420638795580a5f04dacec237de",
49
- "DESIGN.md": "70f52e539073e7c4c1d37e63c9a21672a3221d2931d3ff284058dabf60243530",
46
+ "SKILLS.md": "320b76f37e8b509d597ba01331d3b1a4dc4f1eb68b6d2294ba4125fb2ab02970",
47
+ "SPEC.md": "30dca40819d3d204cfcb33f016e67d0d9008d0fad0907db9c93f6d32e50e057a",
48
+ "DECISIONS.md": "1374d33cc40a9f3086f57c1af885c3e4defaa67df5116168cf4872d2ae8a3628",
49
+ "DOCS.md": "c9501b68bfa97788579ddaaa4b072ca7a7c80a5890e6ec10c05901694fcdae48",
50
+ "DESIGN.md": "e464ff8d9a8e542d00a04143a51417752dc98e1afcfa7e2a5549ecfbb47a479b",
50
51
  "MESSAGING.md": "f1f7c0f11796820b60bb44e42a65749763f7167944ba6acf092a1cf7b59e50de",
51
52
  "MODEL_ROUTING.md": "f0ca3bd12872cd5f61ff4c6bef670249c0a0188f20c049cb0d09d84219b1839c",
52
- "QUALITY_GATES.md": "df9a39ad301394f7f58bc3dd5bf52f9fafeefffdc240fb7ae6a9b6a74b8da0b5",
53
- "STYLE_GUIDE.md": "dcaed2d7885e920060d74e4ba5a8d548a08a729a3efc178434a17b5a182fb628",
53
+ "QUALITY_GATES.md": "15f260c75d6180d1e583917e367ab522030e878f1a6e93ba5f18eba17fef4bb2",
54
+ "STYLE_GUIDE.md": "0fcb8e04ed3d31fa560a0165588ad56efd262463ca0f3aa26633fba955daf0db",
54
55
  "SECURITY.md": "f046e4dc794f49700ddee4cb866e2ba1983a1b71268f2e244892d615b41714f8",
55
- "TESTING.md": "30ef3fa51a6b8e0b5ef608d7b7c448d6a7958bc87c27e15786a54f361fc7ef23",
56
+ "TESTING.md": "59a82645445c3af0c9ccc26a9ed5154c1f710b202d3d13ffa9558a0b1d8a96de",
57
+ "LOOP_CODING.md": "3d4719c7fc7c2e8465ee15aec27574adbbc5207d58123ecf4f88f3942c522812",
56
58
  "DEPLOYMENT.md": "c33d949c2b1850f8ee6c38e5ec565325c3d47f4daac13b81c75e1b35655ea174",
57
59
  "UPGRADE.md": "d4678475458744dee7c1f23b69c04e3cf82d9e896196e62455585aaae5d3a25a"
58
60
  }