opengstack 0.13.10 → 0.14.2

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 (189) hide show
  1. package/AGENTS.md +4 -4
  2. package/CLAUDE.md +127 -110
  3. package/README.md +10 -5
  4. package/SKILL.md +500 -70
  5. package/bin/opengstack.js +69 -69
  6. package/{skills/land-and-deploy/SKILL.md → commands/autoplan.md} +7 -25
  7. package/{skills/benchmark/SKILL.md → commands/benchmark.md} +84 -108
  8. package/{skills/browse/SKILL.md → commands/browse.md} +60 -81
  9. package/{skills/ship/SKILL.md → commands/canary.md} +7 -27
  10. package/{skills/careful/SKILL.md → commands/careful.md} +2 -22
  11. package/{skills/canary/SKILL.md → commands/codex.md} +7 -26
  12. package/{skills/connect-chrome/SKILL.md → commands/connect-chrome.md} +7 -24
  13. package/commands/cso.md +70 -0
  14. package/commands/design-consultation.md +70 -0
  15. package/commands/design-review.md +70 -0
  16. package/commands/design-shotgun.md +70 -0
  17. package/commands/document-release.md +70 -0
  18. package/{skills/freeze/SKILL.md → commands/freeze.md} +3 -29
  19. package/{skills/guard/SKILL.md → commands/guard.md} +4 -35
  20. package/commands/investigate.md +70 -0
  21. package/commands/land-and-deploy.md +70 -0
  22. package/commands/office-hours.md +70 -0
  23. package/{skills/gstack-upgrade/SKILL.md → commands/opengstack-upgrade.md} +64 -79
  24. package/commands/plan-ceo-review.md +70 -0
  25. package/commands/plan-design-review.md +70 -0
  26. package/commands/plan-eng-review.md +70 -0
  27. package/commands/qa-only.md +70 -0
  28. package/commands/qa.md +70 -0
  29. package/commands/retro.md +70 -0
  30. package/commands/review.md +70 -0
  31. package/{skills/setup-browser-cookies/SKILL.md → commands/setup-browser-cookies.md} +22 -40
  32. package/commands/setup-deploy.md +70 -0
  33. package/commands/ship.md +70 -0
  34. package/commands/unfreeze.md +25 -0
  35. package/docs/designs/CHROME_VS_CHROMIUM_EXPLORATION.md +9 -9
  36. package/docs/designs/CONDUCTOR_CHROME_SIDEBAR_INTEGRATION.md +2 -2
  37. package/docs/designs/CONDUCTOR_SESSION_API.md +16 -16
  38. package/docs/designs/DESIGN_SHOTGUN.md +74 -74
  39. package/docs/designs/DESIGN_TOOLS_V1.md +111 -111
  40. package/docs/skills.md +483 -202
  41. package/package.json +42 -43
  42. package/scripts/analytics.ts +188 -0
  43. package/scripts/dev-skill.ts +83 -0
  44. package/scripts/discover-skills.ts +39 -0
  45. package/scripts/eval-compare.ts +97 -0
  46. package/scripts/eval-list.ts +117 -0
  47. package/scripts/eval-select.ts +86 -0
  48. package/scripts/eval-summary.ts +188 -0
  49. package/scripts/eval-watch.ts +172 -0
  50. package/scripts/gen-skill-docs.ts +473 -0
  51. package/scripts/resolvers/browse.ts +129 -0
  52. package/scripts/resolvers/codex-helpers.ts +133 -0
  53. package/scripts/resolvers/composition.ts +48 -0
  54. package/scripts/resolvers/confidence.ts +37 -0
  55. package/scripts/resolvers/constants.ts +50 -0
  56. package/scripts/resolvers/design.ts +950 -0
  57. package/scripts/resolvers/index.ts +59 -0
  58. package/scripts/resolvers/learnings.ts +96 -0
  59. package/scripts/resolvers/preamble.ts +505 -0
  60. package/scripts/resolvers/review.ts +884 -0
  61. package/scripts/resolvers/testing.ts +573 -0
  62. package/scripts/resolvers/types.ts +45 -0
  63. package/scripts/resolvers/utility.ts +421 -0
  64. package/scripts/skill-check.ts +190 -0
  65. package/scripts/cleanup.py +0 -100
  66. package/scripts/filter-skills.sh +0 -114
  67. package/scripts/filter_skills.py +0 -164
  68. package/scripts/install-skills.js +0 -60
  69. package/skills/autoplan/SKILL.md +0 -96
  70. package/skills/autoplan/SKILL.md.tmpl +0 -694
  71. package/skills/benchmark/SKILL.md.tmpl +0 -222
  72. package/skills/browse/SKILL.md.tmpl +0 -131
  73. package/skills/browse/bin/find-browse +0 -21
  74. package/skills/browse/bin/remote-slug +0 -14
  75. package/skills/browse/scripts/build-node-server.sh +0 -48
  76. package/skills/browse/src/activity.ts +0 -208
  77. package/skills/browse/src/browser-manager.ts +0 -959
  78. package/skills/browse/src/buffers.ts +0 -137
  79. package/skills/browse/src/bun-polyfill.cjs +0 -109
  80. package/skills/browse/src/cli.ts +0 -678
  81. package/skills/browse/src/commands.ts +0 -128
  82. package/skills/browse/src/config.ts +0 -150
  83. package/skills/browse/src/cookie-import-browser.ts +0 -625
  84. package/skills/browse/src/cookie-picker-routes.ts +0 -230
  85. package/skills/browse/src/cookie-picker-ui.ts +0 -688
  86. package/skills/browse/src/find-browse.ts +0 -61
  87. package/skills/browse/src/meta-commands.ts +0 -550
  88. package/skills/browse/src/platform.ts +0 -17
  89. package/skills/browse/src/read-commands.ts +0 -358
  90. package/skills/browse/src/server.ts +0 -1192
  91. package/skills/browse/src/sidebar-agent.ts +0 -280
  92. package/skills/browse/src/sidebar-utils.ts +0 -21
  93. package/skills/browse/src/snapshot.ts +0 -407
  94. package/skills/browse/src/url-validation.ts +0 -95
  95. package/skills/browse/src/write-commands.ts +0 -364
  96. package/skills/browse/test/activity.test.ts +0 -120
  97. package/skills/browse/test/adversarial-security.test.ts +0 -32
  98. package/skills/browse/test/browser-manager-unit.test.ts +0 -17
  99. package/skills/browse/test/bun-polyfill.test.ts +0 -72
  100. package/skills/browse/test/commands.test.ts +0 -2075
  101. package/skills/browse/test/compare-board.test.ts +0 -342
  102. package/skills/browse/test/config.test.ts +0 -316
  103. package/skills/browse/test/cookie-import-browser.test.ts +0 -519
  104. package/skills/browse/test/cookie-picker-routes.test.ts +0 -260
  105. package/skills/browse/test/file-drop.test.ts +0 -271
  106. package/skills/browse/test/find-browse.test.ts +0 -50
  107. package/skills/browse/test/findport.test.ts +0 -191
  108. package/skills/browse/test/fixtures/basic.html +0 -33
  109. package/skills/browse/test/fixtures/cursor-interactive.html +0 -22
  110. package/skills/browse/test/fixtures/dialog.html +0 -15
  111. package/skills/browse/test/fixtures/empty.html +0 -2
  112. package/skills/browse/test/fixtures/forms.html +0 -55
  113. package/skills/browse/test/fixtures/iframe.html +0 -30
  114. package/skills/browse/test/fixtures/network-idle.html +0 -30
  115. package/skills/browse/test/fixtures/qa-eval-checkout.html +0 -108
  116. package/skills/browse/test/fixtures/qa-eval-spa.html +0 -98
  117. package/skills/browse/test/fixtures/qa-eval.html +0 -51
  118. package/skills/browse/test/fixtures/responsive.html +0 -49
  119. package/skills/browse/test/fixtures/snapshot.html +0 -55
  120. package/skills/browse/test/fixtures/spa.html +0 -24
  121. package/skills/browse/test/fixtures/states.html +0 -17
  122. package/skills/browse/test/fixtures/upload.html +0 -25
  123. package/skills/browse/test/gstack-config.test.ts +0 -138
  124. package/skills/browse/test/gstack-update-check.test.ts +0 -514
  125. package/skills/browse/test/handoff.test.ts +0 -235
  126. package/skills/browse/test/path-validation.test.ts +0 -91
  127. package/skills/browse/test/platform.test.ts +0 -37
  128. package/skills/browse/test/server-auth.test.ts +0 -65
  129. package/skills/browse/test/sidebar-agent-roundtrip.test.ts +0 -226
  130. package/skills/browse/test/sidebar-agent.test.ts +0 -199
  131. package/skills/browse/test/sidebar-integration.test.ts +0 -320
  132. package/skills/browse/test/sidebar-unit.test.ts +0 -96
  133. package/skills/browse/test/snapshot.test.ts +0 -467
  134. package/skills/browse/test/state-ttl.test.ts +0 -35
  135. package/skills/browse/test/test-server.ts +0 -57
  136. package/skills/browse/test/url-validation.test.ts +0 -72
  137. package/skills/browse/test/watch.test.ts +0 -129
  138. package/skills/canary/SKILL.md.tmpl +0 -212
  139. package/skills/careful/SKILL.md.tmpl +0 -56
  140. package/skills/careful/bin/check-careful.sh +0 -112
  141. package/skills/codex/SKILL.md +0 -90
  142. package/skills/codex/SKILL.md.tmpl +0 -417
  143. package/skills/connect-chrome/SKILL.md.tmpl +0 -195
  144. package/skills/cso/ACKNOWLEDGEMENTS.md +0 -14
  145. package/skills/cso/SKILL.md +0 -93
  146. package/skills/cso/SKILL.md.tmpl +0 -606
  147. package/skills/design-consultation/SKILL.md +0 -94
  148. package/skills/design-consultation/SKILL.md.tmpl +0 -415
  149. package/skills/design-review/SKILL.md +0 -94
  150. package/skills/design-review/SKILL.md.tmpl +0 -290
  151. package/skills/design-shotgun/SKILL.md +0 -91
  152. package/skills/design-shotgun/SKILL.md.tmpl +0 -285
  153. package/skills/document-release/SKILL.md +0 -91
  154. package/skills/document-release/SKILL.md.tmpl +0 -359
  155. package/skills/freeze/SKILL.md.tmpl +0 -77
  156. package/skills/freeze/bin/check-freeze.sh +0 -79
  157. package/skills/gstack-upgrade/SKILL.md.tmpl +0 -222
  158. package/skills/guard/SKILL.md.tmpl +0 -77
  159. package/skills/investigate/SKILL.md +0 -105
  160. package/skills/investigate/SKILL.md.tmpl +0 -194
  161. package/skills/land-and-deploy/SKILL.md.tmpl +0 -881
  162. package/skills/office-hours/SKILL.md +0 -96
  163. package/skills/office-hours/SKILL.md.tmpl +0 -645
  164. package/skills/plan-ceo-review/SKILL.md +0 -94
  165. package/skills/plan-ceo-review/SKILL.md.tmpl +0 -811
  166. package/skills/plan-design-review/SKILL.md +0 -92
  167. package/skills/plan-design-review/SKILL.md.tmpl +0 -446
  168. package/skills/plan-eng-review/SKILL.md +0 -93
  169. package/skills/plan-eng-review/SKILL.md.tmpl +0 -303
  170. package/skills/qa/SKILL.md +0 -95
  171. package/skills/qa/SKILL.md.tmpl +0 -316
  172. package/skills/qa/references/issue-taxonomy.md +0 -85
  173. package/skills/qa/templates/qa-report-template.md +0 -126
  174. package/skills/qa-only/SKILL.md +0 -89
  175. package/skills/qa-only/SKILL.md.tmpl +0 -101
  176. package/skills/retro/SKILL.md +0 -89
  177. package/skills/retro/SKILL.md.tmpl +0 -820
  178. package/skills/review/SKILL.md +0 -92
  179. package/skills/review/SKILL.md.tmpl +0 -281
  180. package/skills/review/TODOS-format.md +0 -62
  181. package/skills/review/checklist.md +0 -220
  182. package/skills/review/design-checklist.md +0 -132
  183. package/skills/review/greptile-triage.md +0 -220
  184. package/skills/setup-browser-cookies/SKILL.md.tmpl +0 -81
  185. package/skills/setup-deploy/SKILL.md +0 -92
  186. package/skills/setup-deploy/SKILL.md.tmpl +0 -215
  187. package/skills/ship/SKILL.md.tmpl +0 -636
  188. package/skills/unfreeze/SKILL.md +0 -37
  189. package/skills/unfreeze/SKILL.md.tmpl +0 -36
@@ -0,0 +1,133 @@
1
+ import type { Host } from './types';
2
+
3
+ const OPENAI_SHORT_DESCRIPTION_LIMIT = 120;
4
+
5
+ export function extractNameAndDescription(content: string): { name: string; description: string } {
6
+ const fmStart = content.indexOf('---\n');
7
+ if (fmStart !== 0) return { name: '', description: '' };
8
+ const fmEnd = content.indexOf('\n---', fmStart + 4);
9
+ if (fmEnd === -1) return { name: '', description: '' };
10
+
11
+ const frontmatter = content.slice(fmStart + 4, fmEnd);
12
+ const nameMatch = frontmatter.match(/^name:\s*(.+)$/m);
13
+ const name = nameMatch ? nameMatch[1].trim() : '';
14
+
15
+ let description = '';
16
+ const lines = frontmatter.split('\n');
17
+ let inDescription = false;
18
+ const descLines: string[] = [];
19
+ for (const line of lines) {
20
+ if (line.match(/^description:\s*\|?\s*$/)) {
21
+ inDescription = true;
22
+ continue;
23
+ }
24
+ if (line.match(/^description:\s*\S/)) {
25
+ description = line.replace(/^description:\s*/, '').trim();
26
+ break;
27
+ }
28
+ if (inDescription) {
29
+ if (line === '' || line.match(/^\s/)) {
30
+ descLines.push(line.replace(/^ /, ''));
31
+ } else {
32
+ break;
33
+ }
34
+ }
35
+ }
36
+ if (descLines.length > 0) {
37
+ description = descLines.join('\n').trim();
38
+ }
39
+
40
+ return { name, description };
41
+ }
42
+
43
+ export function condenseOpenAIShortDescription(description: string): string {
44
+ const firstParagraph = description.split(/\n\s*\n/)[0] || description;
45
+ const collapsed = firstParagraph.replace(/\s+/g, ' ').trim();
46
+ if (collapsed.length <= OPENAI_SHORT_DESCRIPTION_LIMIT) return collapsed;
47
+
48
+ const truncated = collapsed.slice(0, OPENAI_SHORT_DESCRIPTION_LIMIT - 3);
49
+ const lastSpace = truncated.lastIndexOf(' ');
50
+ const safe = lastSpace > 40 ? truncated.slice(0, lastSpace) : truncated;
51
+ return `${safe}...`;
52
+ }
53
+
54
+ export function generateOpenAIYaml(displayName: string, shortDescription: string): string {
55
+ return `interface:
56
+ display_name: ${JSON.stringify(displayName)}
57
+ short_description: ${JSON.stringify(shortDescription)}
58
+ default_prompt: ${JSON.stringify(`Use ${displayName} for this task.`)}
59
+ policy:
60
+ allow_implicit_invocation: true
61
+ `;
62
+ }
63
+
64
+ /** Compute skill name for external hosts (Codex, Factory, etc.) */
65
+ export function externalSkillName(skillDir: string): string {
66
+ if (skillDir === '.' || skillDir === '') return 'OpenGStack';
67
+ // Don't double-prefix: opengstack-upgrade → opengstack-upgrade (not opengstack-opengstack-upgrade)
68
+ if (skillDir.startsWith('opengstack-')) return skillDir;
69
+ return `opengstack-${skillDir}`;
70
+ }
71
+
72
+ /**
73
+ * Transform frontmatter for Codex: keep only name + description.
74
+ * Strips allowed-tools, hooks, version, and all other fields.
75
+ * Handles multiline block scalar descriptions (YAML | syntax).
76
+ */
77
+ export function transformFrontmatter(content: string, host: Host): string {
78
+ if (host === 'claude') return content;
79
+
80
+ // Find frontmatter boundaries
81
+ const fmStart = content.indexOf('---\n');
82
+ if (fmStart !== 0) return content; // frontmatter must be at the start
83
+ const fmEnd = content.indexOf('\n---', fmStart + 4);
84
+ if (fmEnd === -1) return content;
85
+
86
+ const body = content.slice(fmEnd + 4); // includes the leading \n after ---
87
+ const { name, description } = extractNameAndDescription(content);
88
+
89
+ // Codex 1024-char description limit — fail build, don't ship broken skills
90
+ const MAX_DESC = 1024;
91
+ if (description.length > MAX_DESC) {
92
+ throw new Error(
93
+ `Codex description for "${name}" is ${description.length} chars (max ${MAX_DESC}). ` +
94
+ `Compress the description in the .tmpl file.`
95
+ );
96
+ }
97
+
98
+ // Re-emit Codex frontmatter (name + description only)
99
+ const indentedDesc = description.split('\n').map(l => ` ${l}`).join('\n');
100
+ const codexFm = `---\nname: ${name}\ndescription: |\n${indentedDesc}\n---`;
101
+ return codexFm + body;
102
+ }
103
+
104
+ /**
105
+ * Extract hook descriptions from frontmatter for inline safety prose.
106
+ * Returns a description of what the hooks do, or null if no hooks.
107
+ */
108
+ export function extractHookSafetyProse(tmplContent: string): string | null {
109
+ if (!tmplContent.match(/^hooks:/m)) return null;
110
+
111
+ // Parse the hook matchers to build a human-readable safety description
112
+ const matchers: string[] = [];
113
+ const matcherRegex = /matcher:\s*"(\w+)"/g;
114
+ let m;
115
+ while ((m = matcherRegex.exec(tmplContent)) !== null) {
116
+ if (!matchers.includes(m[1])) matchers.push(m[1]);
117
+ }
118
+
119
+ if (matchers.length === 0) return null;
120
+
121
+ // Build safety prose based on what tools are hooked
122
+ const toolDescriptions: Record<string, string> = {
123
+ Bash: 'check bash commands for destructive operations (rm -rf, DROP TABLE, force-push, git reset --hard, etc.) before execution',
124
+ Edit: 'verify file edits are within the allowed scope boundary before applying',
125
+ Write: 'verify file writes are within the allowed scope boundary before applying',
126
+ };
127
+
128
+ const safetyChecks = matchers
129
+ .map(t => toolDescriptions[t] || `check ${t} operations for safety`)
130
+ .join(', and ');
131
+
132
+ return `> **Safety Advisory:** This skill includes safety checks that ${safetyChecks}. When using this skill, always pause and verify before executing potentially destructive operations. If uncertain about a command's safety, ask the user for confirmation before proceeding.`;
133
+ }
@@ -0,0 +1,48 @@
1
+ import type { TemplateContext } from './types';
2
+
3
+ /**
4
+ * {{INVOKE_SKILL:skill-name}} — emits prose instructing Claude to read
5
+ * another skill's SKILL.md and follow it, skipping preamble sections.
6
+ *
7
+ * Supports optional skip= parameter for additional sections to skip:
8
+ * {{INVOKE_SKILL:plan-ceo-review:skip=Outside Voice,Design Outside Voices}}
9
+ */
10
+ export function generateInvokeSkill(ctx: TemplateContext, args?: string[]): string {
11
+ const skillName = args?.[0];
12
+ if (!skillName || skillName === '') {
13
+ throw new Error('{{INVOKE_SKILL}} requires a skill name, e.g. {{INVOKE_SKILL:plan-ceo-review}}');
14
+ }
15
+
16
+ // Parse optional skip= parameter from args[1+]
17
+ const extraSkips = (args?.slice(1) || [])
18
+ .filter(a => a.startsWith('skip='))
19
+ .flatMap(a => a.slice(5).split(','))
20
+ .map(s => s.trim())
21
+ .filter(Boolean);
22
+
23
+ const DEFAULT_SKIPS = [
24
+ 'Preamble (run first)',
25
+ 'AskUserQuestion Format',
26
+ 'Completeness Principle — Boil the Lake',
27
+ 'Search Before Building',
28
+ 'Contributor Mode',
29
+ 'Completion Status Protocol',
30
+
31
+ 'Step 0: Detect platform and base branch',
32
+ 'Review Readiness Dashboard',
33
+ 'Plan File Review Report',
34
+ 'Prerequisite Skill Offer',
35
+ 'Plan Status Footer',
36
+ ];
37
+
38
+ const allSkips = [...DEFAULT_SKIPS, ...extraSkips];
39
+
40
+ return `Read the \`/${skillName}\` skill file at \`${ctx.paths.skillRoot}/${skillName}/SKILL.md\` using the Read tool.
41
+
42
+ **If unreadable:** Skip with "Could not load /${skillName} — skipping." and continue.
43
+
44
+ Follow its instructions from top to bottom, **skipping these sections** (already handled by the parent skill):
45
+ ${allSkips.map(s => `- ${s}`).join('\n')}
46
+
47
+ Execute every other section at full depth. When the loaded skill's instructions are complete, continue with the next step below.`;
48
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Confidence calibration resolver
3
+ *
4
+ * Adds confidence scoring rubric to review-producing skills.
5
+ * Every finding includes a 1-10 score that gates display:
6
+ * 7+: show normally
7
+ * 5-6: show with caveat
8
+ * <5: suppress from main report
9
+ */
10
+ import type { TemplateContext } from './types';
11
+
12
+ export function generateConfidenceCalibration(_ctx: TemplateContext): string {
13
+ return `## Confidence Calibration
14
+
15
+ Every finding MUST include a confidence score (1-10):
16
+
17
+ | Score | Meaning | Display rule |
18
+ |-------|---------|-------------|
19
+ | 9-10 | Verified by reading specific code. Concrete bug or exploit demonstrated. | Show normally |
20
+ | 7-8 | High confidence pattern match. Very likely correct. | Show normally |
21
+ | 5-6 | Moderate. Could be a false positive. | Show with caveat: "Medium confidence, verify this is actually an issue" |
22
+ | 3-4 | Low confidence. Pattern is suspicious but may be fine. | Suppress from main report. Include in appendix only. |
23
+ | 1-2 | Speculation. | Only report if severity would be P0. |
24
+
25
+ **Finding format:**
26
+
27
+ \\\`[SEVERITY] (confidence: N/10) file:line — description\\\`
28
+
29
+ Example:
30
+ \\\`[P1] (confidence: 9/10) app/models/user.rb:42 — SQL injection via string interpolation in where clause\\\`
31
+ \\\`[P2] (confidence: 5/10) app/controllers/api/v1/users_controller.rb:18 — Possible N+1 query, verify with production logs\\\`
32
+
33
+ **Calibration learning:** If you report a finding with confidence < 7 and the user
34
+ confirms it IS a real issue, that is a calibration event. Your initial confidence was
35
+ too low. Log the corrected pattern as a learning so future reviews catch it with
36
+ higher confidence.`;
37
+ }
@@ -0,0 +1,50 @@
1
+ // ─── Shared Design Constants ────────────────────────────────
2
+
3
+ /** OpenGStack's 10 AI slop anti-patterns — shared between DESIGN_METHODOLOGY and DESIGN_HARD_RULES */
4
+ export const AI_SLOP_BLACKLIST = [
5
+ 'Purple/violet/indigo gradient backgrounds or blue-to-purple color schemes',
6
+ '**The 3-column feature grid:** icon-in-colored-circle + bold title + 2-line description, repeated 3x symmetrically. THE most recognizable AI layout.',
7
+ 'Icons in colored circles as section decoration (SaaS starter template look)',
8
+ 'Centered everything (`text-align: center` on all headings, descriptions, cards)',
9
+ 'Uniform bubbly border-radius on every element (same large radius on everything)',
10
+ 'Decorative blobs, floating circles, wavy SVG dividers (if a section feels empty, it needs better content, not decoration)',
11
+ 'Emoji as design elements (rockets in headings, emoji as bullet points)',
12
+ 'Colored left-border on cards (`border-left: 3px solid <accent>`)',
13
+ 'Generic hero copy ("Welcome to [X]", "Unlock the power of...", "Your all-in-one solution for...")',
14
+ 'Cookie-cutter section rhythm (hero → 3 features → testimonials → pricing → CTA, every section same height)',
15
+ ];
16
+
17
+ /** OpenAI hard rejection criteria (from "Designing Delightful Frontends with GPT-5.4", Mar 2026) */
18
+ export const OPENAI_HARD_REJECTIONS = [
19
+ 'Generic SaaS card grid as first impression',
20
+ 'Beautiful image with weak brand',
21
+ 'Strong headline with no clear action',
22
+ 'Busy imagery behind text',
23
+ 'Sections repeating same mood statement',
24
+ 'Carousel with no narrative purpose',
25
+ 'App UI made of stacked cards instead of layout',
26
+ ];
27
+
28
+ /** OpenAI litmus checks — 7 yes/no tests for cross-model consensus scoring */
29
+ export const OPENAI_LITMUS_CHECKS = [
30
+ 'Brand/product unmistakable in first screen?',
31
+ 'One strong visual anchor present?',
32
+ 'Page understandable by scanning headlines only?',
33
+ 'Each section has one job?',
34
+ 'Are cards actually necessary?',
35
+ 'Does motion improve hierarchy or atmosphere?',
36
+ 'Would design feel premium with all decorative shadows removed?',
37
+ ];
38
+
39
+ /**
40
+ * Shared Codex error handling block for resolver output.
41
+ * Used by ADVERSARIAL_STEP, CODEX_PLAN_REVIEW, CODEX_SECOND_OPINION,
42
+ * DESIGN_OUTSIDE_VOICES, DESIGN_REVIEW_LITE, DESIGN_SKETCH.
43
+ */
44
+ export function codexErrorHandling(feature: string): string {
45
+ return `**Error handling:** All errors are non-blocking — the ${feature} is informational.
46
+ - Auth failure (stderr contains "auth", "login", "unauthorized"): note and skip
47
+ - Timeout: note timeout duration and skip
48
+ - Empty response: note and skip
49
+ On any error: continue — ${feature} is informational, not a gate.`;
50
+ }