@appsforgood/next-supabase-kit 0.1.5 → 0.1.7

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 (47) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/DOGFOOD.md +40 -0
  3. package/README.md +246 -43
  4. package/REPOSITORY_SETTINGS.md +7 -3
  5. package/SUPPLY_CHAIN.md +5 -5
  6. package/UPGRADE.md +2 -1
  7. package/antigravity/commands/accessibility-pass.toml +16 -0
  8. package/antigravity/commands/browser-qa.toml +18 -0
  9. package/antigravity/commands/distinctiveness-pass.toml +16 -0
  10. package/antigravity/commands/frontend.toml +5 -4
  11. package/antigravity/commands/layout-cleanup.toml +16 -0
  12. package/antigravity/commands/responsive-cleanup.toml +16 -0
  13. package/antigravity/commands/review.toml +16 -0
  14. package/antigravity/commands/screenshot-critique.toml +16 -0
  15. package/antigravity/commands/spec.toml +17 -0
  16. package/antigravity/commands/test.toml +17 -0
  17. package/antigravity/commands/ui-audit.toml +17 -0
  18. package/antigravity/commands/ui-polish.toml +17 -0
  19. package/antigravity/plugin.json +13 -1
  20. package/assistant-adapters/antigravity.md +7 -0
  21. package/checklists/ui-acceptance-rubric.md +58 -0
  22. package/checklists/ui-detectors.md +75 -0
  23. package/dist/index.js +796 -458
  24. package/dist/index.js.map +1 -1
  25. package/dist/studio/office/assets/office.css +109 -28
  26. package/dist/studio/office/assets/office.js +14 -63
  27. package/dist/studio/wizard/assets/wizard.css +105 -26
  28. package/dist/studio/wizard/assets/wizard.js +22 -85
  29. package/examples/next-supabase-installed/.agent-kit/agent-roster.json +53 -14
  30. package/examples/next-supabase-installed/.agent-kit/manifest.json +12 -12
  31. package/examples/next-supabase-installed/audit-output.json +380 -375
  32. package/package.json +21 -5
  33. package/prompts/lifecycle-command-index.md +180 -0
  34. package/prompts/ui-command-index.md +124 -0
  35. package/rosters/next-supabase-default-council.json +53 -14
  36. package/runtime-skills/ui-improvement-harness/SKILL.md +12 -0
  37. package/skills/ui-improvement-harness.md +96 -0
  38. package/templates/next-supabase/AGENT_ROSTER.md +6 -3
  39. package/templates/next-supabase/ASSISTANT_ADAPTERS.md +3 -1
  40. package/templates/next-supabase/DECISIONS.md +14 -0
  41. package/templates/next-supabase/DESIGN.md +3 -0
  42. package/templates/next-supabase/DOCS.md +5 -1
  43. package/templates/next-supabase/QUALITY_GATES.md +4 -2
  44. package/templates/next-supabase/SKILLS.md +14 -0
  45. package/templates/next-supabase/SPEC.md +5 -1
  46. package/templates/next-supabase/STYLE_GUIDE.md +3 -1
  47. package/templates/next-supabase/TESTING.md +4 -0
@@ -92,8 +92,7 @@
92
92
  els.ringPct.textContent = pct + "%";
93
93
  els.ring.style.setProperty("--pct", String(pct));
94
94
  if (els.levelPill && state.agenticLevel) {
95
- els.levelPill.textContent =
96
- "L" + state.agenticLevel.currentLevel + " → L" + state.agenticLevel.targetLevel;
95
+ els.levelPill.textContent = "L" + state.agenticLevel.currentLevel + " → L" + state.agenticLevel.targetLevel;
97
96
  els.levelPill.hidden = false;
98
97
  }
99
98
  render();
@@ -137,10 +136,8 @@
137
136
  const sections = state.progress?.sections || [];
138
137
  els.sectionNav.innerHTML = sections
139
138
  .map((s) => {
140
- const chipClass =
141
- s.status === "done" ? "done" : s.status === "in_progress" ? "progress" : s.status === "optional" ? "optional" : "";
142
- const chipLabel =
143
- 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" : "";
144
141
  return (
145
142
  '<li><button type="button" data-section="' +
146
143
  s.id +
@@ -171,14 +168,7 @@
171
168
 
172
169
  function renderTeamIntro() {
173
170
  const cards = state.agents
174
- .map(
175
- (a) =>
176
- '<li class="agent-card"><strong>' +
177
- escapeHtml(a.name) +
178
- "</strong><p>" +
179
- escapeHtml(a.roleSummary) +
180
- "</p></li>"
181
- )
171
+ .map((a) => '<li class="agent-card"><strong>' + escapeHtml(a.name) + "</strong><p>" + escapeHtml(a.roleSummary) + "</p></li>")
182
172
  .join("");
183
173
  return (
184
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>' +
@@ -211,9 +201,7 @@
211
201
  }
212
202
 
213
203
  function renderHome() {
214
- const pills = (boot.stackSignals || [])
215
- .map((s) => '<span class="pill">' + escapeHtml(s) + "</span>")
216
- .join("");
204
+ const pills = (boot.stackSignals || []).map((s) => '<span class="pill">' + escapeHtml(s) + "</span>").join("");
217
205
  const agentCount = state.agents.length || boot.agents?.length || 0;
218
206
  const officePromo =
219
207
  '<div class="office-promo">' +
@@ -243,9 +231,7 @@
243
231
  depthCard("complete", "Complete (~25 min)", "Standard plus DESIGN and MESSAGING intake drafts.") +
244
232
  "</div>" +
245
233
  (state.progress?.recommendedNext
246
- ? '<p class="why" style="margin-top:18px">Continue: <strong>' +
247
- escapeHtml(state.progress.recommendedNext) +
248
- "</strong></p>"
234
+ ? '<p class="why" style="margin-top:18px">Continue: <strong>' + escapeHtml(state.progress.recommendedNext) + "</strong></p>"
249
235
  : "")
250
236
  );
251
237
  }
@@ -259,8 +245,8 @@
259
245
  level.currentLevel +
260
246
  " → target L" +
261
247
  level.targetLevel +
262
- " <span class=\"hint-inline\">(setup progress is separate from audit readiness and visual QA tiers)</span></p>" +
263
- (level.maintainerNote ? "<p class=\"hint\">" + escapeHtml(level.maintainerNote) + "</p>" : "") +
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>" : "") +
264
250
  "</div>"
265
251
  );
266
252
  }
@@ -284,9 +270,9 @@
284
270
  const val = escapeHtml(state.form[name] || "");
285
271
  if (type === "textarea") {
286
272
  return (
287
- "<label for=\"" +
273
+ '<label for="' +
288
274
  name +
289
- "\">" +
275
+ '">' +
290
276
  escapeHtml(label) +
291
277
  (hint ? "<span>" + escapeHtml(hint) + "</span>" : "") +
292
278
  '</label><textarea id="' +
@@ -303,9 +289,9 @@
303
289
  );
304
290
  }
305
291
  return (
306
- "<label for=\"" +
292
+ '<label for="' +
307
293
  name +
308
- "\">" +
294
+ '">' +
309
295
  escapeHtml(label) +
310
296
  (hint ? "<span>" + escapeHtml(hint) + "</span>" : "") +
311
297
  '</label><input id="' +
@@ -334,25 +320,11 @@
334
320
  ),
335
321
  productCategory: () => {
336
322
  const opts = (boot.categories || [])
337
- .map(
338
- (c) =>
339
- '<option value="' +
340
- c +
341
- '"' +
342
- (state.form.productCategory === c ? " selected" : "") +
343
- ">" +
344
- c +
345
- "</option>"
346
- )
323
+ .map((c) => '<option value="' + c + '"' + (state.form.productCategory === c ? " selected" : "") + ">" + c + "</option>")
347
324
  .join("");
348
- return (
349
- '<label for="productCategory">Category</label><select id="productCategory" name="productCategory">' +
350
- opts +
351
- "</select>"
352
- );
325
+ return '<label for="productCategory">Category</label><select id="productCategory" name="productCategory">' + opts + "</select>";
353
326
  },
354
- primaryAudience: () =>
355
- 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?"),
356
328
  primaryWorkflows: () =>
357
329
  inputField(
358
330
  "primaryWorkflows",
@@ -363,16 +335,7 @@
363
335
  ),
364
336
  tenantModel: () => {
365
337
  const opts = (boot.tenantModels || [])
366
- .map(
367
- (c) =>
368
- '<option value="' +
369
- c +
370
- '"' +
371
- (state.form.tenantModel === c ? " selected" : "") +
372
- ">" +
373
- c +
374
- "</option>"
375
- )
338
+ .map((c) => '<option value="' + c + '"' + (state.form.tenantModel === c ? " selected" : "") + ">" + c + "</option>")
376
339
  .join("");
377
340
  return '<label for="tenantModel">Who uses the system?</label><select id="tenantModel" name="tenantModel">' + opts + "</select>";
378
341
  },
@@ -388,12 +351,9 @@
388
351
  "textarea",
389
352
  "Describe auth boundaries agents must not break."
390
353
  ),
391
- uiPreferred: () =>
392
- inputField("uiPreferred", "UI should feel like…", "", "textarea", "Task-first, clear hierarchy, readable typography."),
393
- uiAvoid: () =>
394
- inputField("uiAvoid", "UI should avoid…", "Optional.", "textarea", "Generic SaaS heroes, card soup, fake metrics."),
395
- valueProposition: () =>
396
- 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?"),
397
357
  proof: () => inputField("proof", "Proof points", "One per line. Real evidence only.", "textarea", ""),
398
358
  objections: () => inputField("objections", "Objections", "One per line. Optional.", "textarea", ""),
399
359
  qualityTarget: () => {
@@ -410,16 +370,7 @@
410
370
  },
411
371
  ideSurface: () => {
412
372
  const opts = state.ideSurfaces
413
- .map(
414
- (s) =>
415
- '<option value="' +
416
- s.id +
417
- '"' +
418
- (state.form.ideSurface === s.id ? " selected" : "") +
419
- ">" +
420
- escapeHtml(s.label) +
421
- "</option>"
422
- )
373
+ .map((s) => '<option value="' + s.id + '"' + (state.form.ideSurface === s.id ? " selected" : "") + ">" + escapeHtml(s.label) + "</option>")
423
374
  .join("");
424
375
  const chip = renderAdapterChip(state.lastAdapterValidation);
425
376
  return (
@@ -494,15 +445,7 @@
494
445
  : validation.warn > 0
495
446
  ? "Adapter validate: pass with warnings"
496
447
  : "Adapter validate: pass";
497
- return (
498
- '<p class="adapter-chip ' +
499
- kind +
500
- '" role="status">' +
501
- escapeHtml(label) +
502
- " (" +
503
- escapeHtml(validation.target) +
504
- ")</p>"
505
- );
448
+ return '<p class="adapter-chip ' + kind + '" role="status">' + escapeHtml(label) + " (" + escapeHtml(validation.target) + ")</p>";
506
449
  }
507
450
 
508
451
  function renderComplete() {
@@ -513,13 +456,7 @@
513
456
  .join("");
514
457
  return (
515
458
  '<div class="complete-icon" aria-hidden="true">✓</div><h2>Setup saved</h2>' +
516
- (level
517
- ? '<p class="why">Agentic level <strong>L' +
518
- level.currentLevel +
519
- "</strong> (target L" +
520
- level.targetLevel +
521
- ").</p>"
522
- : "") +
459
+ (level ? '<p class="why">Agentic level <strong>L' + level.currentLevel + "</strong> (target L" + level.targetLevel + ").</p>" : "") +
523
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>' +
524
461
  '<ol class="next-steps">' +
525
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>" +
@@ -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
  ],
@@ -95,13 +96,7 @@
95
96
  "voice-tone",
96
97
  "pricing-copy"
97
98
  ],
98
- "skills": [
99
- "positioning-messaging",
100
- "conversion-copywriting",
101
- "landing-page-copy",
102
- "product-voice-tone",
103
- "onboarding-empty-state-copy"
104
- ],
99
+ "skills": ["positioning-messaging", "conversion-copywriting", "landing-page-copy", "product-voice-tone", "onboarding-empty-state-copy"],
105
100
  "handsOffTo": ["frontend-design-lead", "nextjs-engineer", "qa-engineer", "docs-maintainer"]
106
101
  },
107
102
  {
@@ -116,7 +111,7 @@
116
111
  "id": "qa-engineer",
117
112
  "name": "QA Engineer",
118
113
  "file": ".agent-kit/agents/qa-engineer.md",
119
- "defaultFor": ["testing", "regression", "smoke", "acceptance-evidence"],
114
+ "defaultFor": ["testing", "regression", "smoke", "acceptance-evidence", "test", "review", "code-review"],
120
115
  "skills": ["testing-qa", "best-practice-maturity-review", "visual-regression-qa", "accessibility-wcag"],
121
116
  "handsOffTo": ["docs-maintainer", "deployment-observability-engineer"]
122
117
  },
@@ -140,14 +135,26 @@
140
135
  "workflows": [
141
136
  {
142
137
  "id": "planning",
143
- "triggers": ["plan", "roadmap", "phase", "scope", "what should we do", "break this down"],
138
+ "triggers": ["plan", "roadmap", "phase", "scope", "spec", "specification", "acceptance criteria", "what should we do", "break this down"],
144
139
  "sequence": ["planner", "lead-architect", "qa-engineer", "docs-maintainer"],
145
140
  "council": ["planner", "lead-architect"],
146
141
  "requiredOutputs": ["phased checklist", "maturity target", "affected layers", "preserved capabilities", "verification plan", "docs impact"]
147
142
  },
148
143
  {
149
144
  "id": "core-change",
150
- "triggers": ["schema", "auth", "rls", "api", "route handler", "server action", "dependency", "upgrade", "release workflow", "package behavior", "cross-layer"],
145
+ "triggers": [
146
+ "schema",
147
+ "auth",
148
+ "rls",
149
+ "api",
150
+ "route handler",
151
+ "server action",
152
+ "dependency",
153
+ "upgrade",
154
+ "release workflow",
155
+ "package behavior",
156
+ "cross-layer"
157
+ ],
151
158
  "sequence": [
152
159
  "planner",
153
160
  "lead-architect",
@@ -171,7 +178,7 @@
171
178
  },
172
179
  {
173
180
  "id": "frontend-change",
174
- "triggers": ["screen", "component", "layout", "design", "responsive", "accessibility", "screenshot"],
181
+ "triggers": ["screen", "component", "layout", "design", "responsive", "accessibility", "screenshot", "ui audit", "ui polish", "browser qa"],
175
182
  "sequence": ["planner", "frontend-design-lead", "marketing-copy-lead", "nextjs-engineer", "qa-engineer", "docs-maintainer"],
176
183
  "council": ["frontend-design-lead", "marketing-copy-lead", "qa-engineer"],
177
184
  "requiredOutputs": [
@@ -183,15 +190,33 @@
183
190
  "design critique verdict",
184
191
  "frontend product-quality scorecard",
185
192
  "domain-specific UI rationale",
193
+ "UI detector findings and severity",
194
+ "UI command workflow applied when polishing or auditing",
186
195
  "visual QA evidence",
187
196
  "state coverage",
188
197
  "accessibility checks",
189
- "desktop/mobile verification"
198
+ "desktop/mobile verification",
199
+ "authenticated screen evidence when applicable"
190
200
  ]
191
201
  },
192
202
  {
193
203
  "id": "marketing-copy",
194
- "triggers": ["copy", "copywriting", "marketing", "positioning", "messaging", "value prop", "value proposition", "landing page", "headline", "cta", "conversion", "onboarding", "empty state", "pricing"],
204
+ "triggers": [
205
+ "copy",
206
+ "copywriting",
207
+ "marketing",
208
+ "positioning",
209
+ "messaging",
210
+ "value prop",
211
+ "value proposition",
212
+ "landing page",
213
+ "headline",
214
+ "cta",
215
+ "conversion",
216
+ "onboarding",
217
+ "empty state",
218
+ "pricing"
219
+ ],
195
220
  "sequence": ["planner", "marketing-copy-lead", "frontend-design-lead", "qa-engineer", "docs-maintainer"],
196
221
  "council": ["marketing-copy-lead", "frontend-design-lead"],
197
222
  "requiredOutputs": [
@@ -205,6 +230,20 @@
205
230
  "handoff notes for design and implementation"
206
231
  ]
207
232
  },
233
+ {
234
+ "id": "testing",
235
+ "triggers": ["test", "tests", "unit test", "regression test", "smoke test", "playwright", "acceptance test"],
236
+ "sequence": ["qa-engineer", "docs-maintainer"],
237
+ "council": ["qa-engineer"],
238
+ "requiredOutputs": ["test plan", "commands run", "pass/fail summary", "coverage gaps", "skipped-test rationale"]
239
+ },
240
+ {
241
+ "id": "code-review",
242
+ "triggers": ["review", "code review", "pre-merge", "pr review", "merge review"],
243
+ "sequence": ["qa-engineer", "security-reviewer", "docs-maintainer"],
244
+ "council": ["qa-engineer", "security-reviewer"],
245
+ "requiredOutputs": ["reviewed scope", "findings by severity", "required fixes", "security notes when applicable", "merge recommendation"]
246
+ },
208
247
  {
209
248
  "id": "security-review",
210
249
  "triggers": ["security", "owasp", "secret", "token", "permission", "ssrf", "idor", "dependency"],
@@ -219,7 +258,7 @@
219
258
  "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
259
  "Planner starts planning and ambiguous requests by default.",
221
260
  "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.",
261
+ "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
262
  "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
263
  "Security Reviewer must review auth, data mutation, external-call, dependency, secret, and release-risk changes.",
225
264
  "QA Engineer must verify behavior changes before completion.",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "packageName": "@appsforgood/next-supabase-kit",
3
- "packageVersion": "0.1.5",
3
+ "packageVersion": "0.1.7",
4
4
  "stack": "next-supabase",
5
- "installedAt": "2026-06-17T11:49:38.732Z",
5
+ "installedAt": "2026-07-04T01:32:06.844Z",
6
6
  "docs": [
7
7
  "AGENTS.md",
8
8
  "AGENT_ROSTER.md",
@@ -40,20 +40,20 @@
40
40
  "modelRouting": ".agent-kit/model-routing.json",
41
41
  "templateHashes": {
42
42
  "AGENTS.md": "c7f3e7360938a1ed804d2110e9af96e6f09d50c49138063bef0db1642ddaf84f",
43
- "AGENT_ROSTER.md": "fb88198d0a5f911ec8cbaa2850c1a47e1dbd1fe2c8144f9ce633bbfc1ec414d3",
44
- "ASSISTANT_ADAPTERS.md": "b5fb02dbab39bab1af5122050cb86acbc726e24226e7024a3b984d5fdc12f798",
43
+ "AGENT_ROSTER.md": "40147eecf3977bf64431204b67f24eb277a834ba5b6f894c053c79c0a9dbb8f5",
44
+ "ASSISTANT_ADAPTERS.md": "4d37ba6555814cf18c6ac2a302a614af07bb33b0ac0eb5f19886c3af3328cb63",
45
45
  "COUNCIL.md": "40bec9051664c9c38b8360ee16f21b5e4716030d19c493cdec67395ab06528e1",
46
- "SKILLS.md": "3c3c2eb40438a42026479dccac7bbf084ba22e2d758c425dff59385d05eae3bd",
47
- "SPEC.md": "bb0406a141338b630a82026e4a2bb37f38448b3641d3b3ada62d146711a4fbfe",
48
- "DECISIONS.md": "0c08d1106a40f829b197d552d0397c9bcd9af7e168a55c47ff5be033c6035ec6",
49
- "DOCS.md": "da6a9006daf78bf410051153fe2838417b7f46459904582c2259ec1dba4bd29f",
50
- "DESIGN.md": "70f52e539073e7c4c1d37e63c9a21672a3221d2931d3ff284058dabf60243530",
46
+ "SKILLS.md": "320b76f37e8b509d597ba01331d3b1a4dc4f1eb68b6d2294ba4125fb2ab02970",
47
+ "SPEC.md": "30dca40819d3d204cfcb33f016e67d0d9008d0fad0907db9c93f6d32e50e057a",
48
+ "DECISIONS.md": "1374d33cc40a9f3086f57c1af885c3e4defaa67df5116168cf4872d2ae8a3628",
49
+ "DOCS.md": "c9501b68bfa97788579ddaaa4b072ca7a7c80a5890e6ec10c05901694fcdae48",
50
+ "DESIGN.md": "e464ff8d9a8e542d00a04143a51417752dc98e1afcfa7e2a5549ecfbb47a479b",
51
51
  "MESSAGING.md": "f1f7c0f11796820b60bb44e42a65749763f7167944ba6acf092a1cf7b59e50de",
52
52
  "MODEL_ROUTING.md": "f0ca3bd12872cd5f61ff4c6bef670249c0a0188f20c049cb0d09d84219b1839c",
53
- "QUALITY_GATES.md": "df9a39ad301394f7f58bc3dd5bf52f9fafeefffdc240fb7ae6a9b6a74b8da0b5",
54
- "STYLE_GUIDE.md": "dcaed2d7885e920060d74e4ba5a8d548a08a729a3efc178434a17b5a182fb628",
53
+ "QUALITY_GATES.md": "15f260c75d6180d1e583917e367ab522030e878f1a6e93ba5f18eba17fef4bb2",
54
+ "STYLE_GUIDE.md": "0fcb8e04ed3d31fa560a0165588ad56efd262463ca0f3aa26633fba955daf0db",
55
55
  "SECURITY.md": "f046e4dc794f49700ddee4cb866e2ba1983a1b71268f2e244892d615b41714f8",
56
- "TESTING.md": "2889421a1a66d5a6d910e9896a7f21fe4041aa2f6c0f52c92bac8505b66ba06a",
56
+ "TESTING.md": "59a82645445c3af0c9ccc26a9ed5154c1f710b202d3d13ffa9558a0b1d8a96de",
57
57
  "LOOP_CODING.md": "3d4719c7fc7c2e8465ee15aec27574adbbc5207d58123ecf4f88f3942c522812",
58
58
  "DEPLOYMENT.md": "c33d949c2b1850f8ee6c38e5ec565325c3d47f4daac13b81c75e1b35655ea174",
59
59
  "UPGRADE.md": "d4678475458744dee7c1f23b69c04e3cf82d9e896196e62455585aaae5d3a25a"