@oisincoveney/pipeline 3.0.1 → 3.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.
Files changed (85) hide show
  1. package/dist/commands/ticket-command.js +4 -1
  2. package/dist/config/lint.js +0 -1
  3. package/dist/config/schemas.d.ts +4 -4
  4. package/dist/config/validate.js +0 -1
  5. package/dist/planning/generate.js +4 -8
  6. package/dist/runtime/agent-node/agent-node.js +6 -1
  7. package/dist/schedule/passes/drain-merge.js +58 -0
  8. package/dist/schedule/passes/index.js +1 -0
  9. package/dist/schedule/prompts.js +1 -0
  10. package/dist/schedule/scheduling-roles.js +18 -1
  11. package/dist/tickets/ticket-graph.js +3 -4
  12. package/package.json +1 -2
  13. package/.agents/skills/add-dark-mode/SKILL.md +0 -79
  14. package/.agents/skills/brand-kit/SKILL.md +0 -61
  15. package/.agents/skills/brand-kit/brand-kit-prompt.md +0 -158
  16. package/.agents/skills/canonicalize-tailwind/SKILL.md +0 -86
  17. package/.agents/skills/componentize/SKILL.md +0 -60
  18. package/.agents/skills/critique/SKILL.md +0 -374
  19. package/.agents/skills/dark-mode-image/SKILL.md +0 -64
  20. package/.agents/skills/design/SKILL.md +0 -58
  21. package/.agents/skills/design/design-guidelines.md +0 -74
  22. package/.agents/skills/design/guidelines/assets-api.md +0 -196
  23. package/.agents/skills/design/guidelines/avatars.md +0 -8
  24. package/.agents/skills/design/guidelines/badges.md +0 -5
  25. package/.agents/skills/design/guidelines/border-radius.md +0 -6
  26. package/.agents/skills/design/guidelines/buttons.md +0 -27
  27. package/.agents/skills/design/guidelines/colors.md +0 -6
  28. package/.agents/skills/design/guidelines/copywriting.md +0 -9
  29. package/.agents/skills/design/guidelines/custom-fonts.md +0 -7
  30. package/.agents/skills/design/guidelines/dark-mode.md +0 -29
  31. package/.agents/skills/design/guidelines/dashboards.md +0 -12
  32. package/.agents/skills/design/guidelines/description-lists.md +0 -5
  33. package/.agents/skills/design/guidelines/feature-lists.md +0 -5
  34. package/.agents/skills/design/guidelines/flexbox-layout.md +0 -6
  35. package/.agents/skills/design/guidelines/font-recommendations.md +0 -175
  36. package/.agents/skills/design/guidelines/footers.md +0 -13
  37. package/.agents/skills/design/guidelines/form-controls.md +0 -139
  38. package/.agents/skills/design/guidelines/general.md +0 -47
  39. package/.agents/skills/design/guidelines/headers.md +0 -8
  40. package/.agents/skills/design/guidelines/heading-groups.md +0 -19
  41. package/.agents/skills/design/guidelines/icons.md +0 -18
  42. package/.agents/skills/design/guidelines/images.md +0 -12
  43. package/.agents/skills/design/guidelines/interactivity.md +0 -6
  44. package/.agents/skills/design/guidelines/landing-pages.md +0 -11
  45. package/.agents/skills/design/guidelines/login-pages.md +0 -5
  46. package/.agents/skills/design/guidelines/logo-clouds.md +0 -6
  47. package/.agents/skills/design/guidelines/navigation.md +0 -10
  48. package/.agents/skills/design/guidelines/pagination.md +0 -5
  49. package/.agents/skills/design/guidelines/placeholder-content.md +0 -23
  50. package/.agents/skills/design/guidelines/pricing-cards.md +0 -42
  51. package/.agents/skills/design/guidelines/prose-content.md +0 -11
  52. package/.agents/skills/design/guidelines/responsive-design.md +0 -15
  53. package/.agents/skills/design/guidelines/section-layout.md +0 -23
  54. package/.agents/skills/design/guidelines/shadows.md +0 -6
  55. package/.agents/skills/design/guidelines/surfaces.md +0 -13
  56. package/.agents/skills/design/guidelines/svg.md +0 -7
  57. package/.agents/skills/design/guidelines/tables.md +0 -27
  58. package/.agents/skills/design/guidelines/team-sections.md +0 -13
  59. package/.agents/skills/design/guidelines/testimonials.md +0 -11
  60. package/.agents/skills/design/guidelines/typography.md +0 -18
  61. package/.agents/skills/diagnose/SKILL.md +0 -68
  62. package/.agents/skills/doubt/SKILL.md +0 -243
  63. package/.agents/skills/execute/SKILL.md +0 -211
  64. package/.agents/skills/fix/SKILL.md +0 -64
  65. package/.agents/skills/grill/SKILL.md +0 -43
  66. package/.agents/skills/ideas/SKILL.md +0 -161
  67. package/.agents/skills/imagegen/SKILL.md +0 -24
  68. package/.agents/skills/improve/SKILL.md +0 -51
  69. package/.agents/skills/inspect/SKILL.md +0 -19
  70. package/.agents/skills/library-first-development/SKILL.md +0 -108
  71. package/.agents/skills/make-responsive/SKILL.md +0 -91
  72. package/.agents/skills/markup-from-image/SKILL.md +0 -88
  73. package/.agents/skills/migrate/SKILL.md +0 -213
  74. package/.agents/skills/optimize/SKILL.md +0 -352
  75. package/.agents/skills/orchestrate/SKILL.md +0 -108
  76. package/.agents/skills/quality-gate/SKILL.md +0 -92
  77. package/.agents/skills/quick/SKILL.md +0 -20
  78. package/.agents/skills/research/SKILL.md +0 -71
  79. package/.agents/skills/schedule-graph-shaping/SKILL.md +0 -24
  80. package/.agents/skills/scope/SKILL.md +0 -130
  81. package/.agents/skills/secure/SKILL.md +0 -351
  82. package/.agents/skills/spec/SKILL.md +0 -221
  83. package/.agents/skills/test/SKILL.md +0 -70
  84. package/.agents/skills/trace/SKILL.md +0 -137
  85. package/.agents/skills/verify/SKILL.md +0 -125
@@ -157,7 +157,10 @@ function runTicketScoperEffect(launchPlan, executor) {
157
157
  }
158
158
  function checkTicketGraphEffect(worktreePath, flags) {
159
159
  return Effect.gen(function* () {
160
- yield* writeLineEffect(`OK: ticket graph valid (${(yield* loadTicketGraphEffect(worktreePath, flags.root)).scopedIds.length} tickets)`);
160
+ const loaded = yield* loadTicketGraphEffect(worktreePath, flags.root);
161
+ const dangling = loaded.graph.danglingDependencies;
162
+ yield* writeLineEffect(`OK: ticket graph valid (${loaded.scopedIds.length} tickets)`);
163
+ if (dangling.length > 0) yield* writeLineEffect(`WARN: ${dangling.length} dependency reference(s) point to tasks absent from this backlog (treated as non-blocking): ${dangling.join("; ")}`);
161
164
  });
162
165
  }
163
166
  function printTicketSequenceEffect(worktreePath, flags) {
@@ -34,7 +34,6 @@ function lintMissingFileReferencesEffect(config, projectRoot) {
34
34
  }
35
35
  function lintFileReferences(config) {
36
36
  const refs = [];
37
- for (const [skillId, skill] of Object.entries(config.skills)) pushLintPathRef(refs, `skills.${skillId}.path`, skill);
38
37
  for (const [profileId, profile] of Object.entries(config.profiles)) {
39
38
  pushLintPathRef(refs, `profiles.${profileId}.instructions.path`, { path: profile.instructions.path });
40
39
  pushLintPathRef(refs, `profiles.${profileId}.output.schema_path`, { path: profile.output?.schema_path });
@@ -226,8 +226,8 @@ declare const configSchema: z.ZodObject<{
226
226
  policy: z.ZodOptional<z.ZodObject<{
227
227
  commands: z.ZodOptional<z.ZodEnum<{
228
228
  allow: "allow";
229
- deny: "deny";
230
229
  "trusted-only": "trusted-only";
230
+ deny: "deny";
231
231
  }>>;
232
232
  modules: z.ZodOptional<z.ZodEnum<{
233
233
  allow: "allow";
@@ -255,8 +255,8 @@ declare const configSchema: z.ZodObject<{
255
255
  global: "global";
256
256
  }>>;
257
257
  mode: z.ZodEnum<{
258
- local: "local";
259
258
  hosted: "hosted";
259
+ local: "local";
260
260
  }>;
261
261
  provider: z.ZodLiteral<"toolhive">;
262
262
  authorization_env: z.ZodDefault<z.ZodString>;
@@ -299,10 +299,10 @@ declare const configSchema: z.ZodObject<{
299
299
  }, z.core.$strict>>;
300
300
  output: z.ZodOptional<z.ZodObject<{
301
301
  format: z.ZodEnum<{
302
- json_schema: "json_schema";
303
302
  text: "text";
304
303
  json: "json";
305
304
  jsonl: "jsonl";
305
+ json_schema: "json_schema";
306
306
  }>;
307
307
  repair: z.ZodOptional<z.ZodObject<{
308
308
  enabled: z.ZodOptional<z.ZodBoolean>;
@@ -371,10 +371,10 @@ declare const configSchema: z.ZodObject<{
371
371
  disabled: "disabled";
372
372
  }>>>;
373
373
  output_formats: z.ZodOptional<z.ZodArray<z.ZodEnum<{
374
- json_schema: "json_schema";
375
374
  text: "text";
376
375
  json: "json";
377
376
  jsonl: "jsonl";
377
+ json_schema: "json_schema";
378
378
  }>>>;
379
379
  rules: z.ZodOptional<z.ZodBoolean>;
380
380
  skills: z.ZodOptional<z.ZodBoolean>;
@@ -37,7 +37,6 @@ function validatePipelineConfig(rawConfig, projectRoot, options = {}) {
37
37
  validateHookConfig(config, issues, projectRoot, options);
38
38
  validateTokenBudget(config, issues);
39
39
  for (const [ruleId, rule] of Object.entries(config.rules)) validatePath(`rules.${ruleId}.path`, rule, projectRoot, issues, options);
40
- for (const [skillId, skill] of Object.entries(config.skills)) validatePath(`skills.${skillId}.path`, skill, projectRoot, issues, options);
41
40
  for (const [workflowId, workflow] of Object.entries(config.workflows)) validateWorkflow(workflowId, workflow, config, issues, projectRoot, options);
42
41
  if (issues.length > 0) throw validationError(issues);
43
42
  return config;
@@ -7,8 +7,9 @@ import { normalizeRunnerOutput } from "../runner-output.js";
7
7
  import { compileWorkflowPlan } from "./compile.js";
8
8
  import { loadBacklogPlanningContext } from "../schedule/backlog-context.js";
9
9
  import { baselineScheduleArtifact } from "../schedule/baseline.js";
10
- import { isCoverageNode, isImplementationNode } from "../schedule/scheduling-roles.js";
10
+ import { isCoverageNode, isImplementationNode, isWriteCapableParallelChild } from "../schedule/scheduling-roles.js";
11
11
  import { addGeneratedImplementationCoverage } from "../schedule/passes/coverage.js";
12
+ import { integrateParallelWriteFanout } from "../schedule/passes/drain-merge.js";
12
13
  import { canonicalizeGeneratedScheduleIds } from "../schedule/passes/ids.js";
13
14
  import { SCHEDULE_PASS_ORDER } from "../schedule/passes/index.js";
14
15
  import { applyNodeCatalogModelFallbacks } from "../schedule/passes/models.js";
@@ -92,7 +93,7 @@ async function generateScheduleArtifact(options) {
92
93
  const planningContext = { ...loadBacklogPlanningContext(options.task, options.worktreePath) };
93
94
  const generatedArtifact = await planScheduleArtifact(baseline, policy.planner_profile, options, planningContext);
94
95
  assertSchedulePassOrder();
95
- const artifact = hydrateScheduleTaskContexts(canonicalizeGeneratedScheduleIds(applyNodeCatalogModelFallbacks(options.config, policy.node_catalog, addGeneratedImplementationCoverage(options.config, generatedArtifact))), planningContext);
96
+ const artifact = hydrateScheduleTaskContexts(canonicalizeGeneratedScheduleIds(applyNodeCatalogModelFallbacks(options.config, policy.node_catalog, integrateParallelWriteFanout(options.config, addGeneratedImplementationCoverage(options.config, generatedArtifact)))), planningContext);
96
97
  validateScheduleArtifact(options.config, artifact, planningContext);
97
98
  compileScheduleArtifact(options.config, artifact, options.worktreePath);
98
99
  return {
@@ -103,6 +104,7 @@ async function generateScheduleArtifact(options) {
103
104
  function assertSchedulePassOrder() {
104
105
  if (SCHEDULE_PASS_ORDER.join("\0") !== [
105
106
  "coverage",
107
+ "drain-merge",
106
108
  "models",
107
109
  "ids",
108
110
  "references"
@@ -281,12 +283,6 @@ function workflowNodeIssues(artifact, collectIssues) {
281
283
  });
282
284
  });
283
285
  }
284
- function isWriteCapableParallelChild(config, node) {
285
- if (node.kind === "agent") return config.profiles[node.profile]?.filesystem?.mode === "workspace-write";
286
- if (node.kind === "command") return true;
287
- if (node.kind === "parallel") return node.nodes.some((child) => isWriteCapableParallelChild(config, child));
288
- return false;
289
- }
290
286
  function hasDownstreamDrainMerge(nodeId, index) {
291
287
  return hasReachableDependent(nodeId, index, (node) => node.kind === "builtin" && PARALLEL_MERGE_BUILTINS.has(node.builtin));
292
288
  }
@@ -482,7 +482,12 @@ function renderPathReferenceEffect(id, registry, worktreePath) {
482
482
  `Path: ${path}`,
483
483
  "",
484
484
  content.trimEnd()
485
- ].join("\n")));
485
+ ].join("\n")), Effect.catchAllCause(() => Effect.succeed([
486
+ `## ${id}`,
487
+ `Path: ${path}`,
488
+ "",
489
+ "(install-managed harness asset; loaded by the host agent runtime)"
490
+ ].join("\n"))));
486
491
  }
487
492
  function resolveRuntimePathReference(worktreePath, ref) {
488
493
  if (ref?.source_root === "package") return resolvePackageAssetPath(ref.path ?? "");
@@ -0,0 +1,58 @@
1
+ import { uniqueGeneratedId } from "../../strings.js";
2
+ import { dependentsByNeed, hasReachableDependent } from "../../planning/graph.js";
3
+ import { isWriteCapableParallelChild } from "../scheduling-roles.js";
4
+ //#region src/schedule/passes/drain-merge.ts
5
+ const DRAIN_MERGE_BUILTIN = "drain-merge";
6
+ /**
7
+ * A parallel node whose children mutate a shared worktree must hand its results
8
+ * to a downstream `drain-merge` builtin (the schedule validator rejects it
9
+ * otherwise). The planner is instructed to emit one, but the integration cannot
10
+ * depend on planner cooperation: this pass deterministically inserts the missing
11
+ * `drain-merge` after any parallel node with more than one write-capable child
12
+ * that lacks one, and reroutes the parallel's existing dependents through it so
13
+ * the merge is a true join point. Single-writer or already-integrated parallels
14
+ * are left untouched.
15
+ */
16
+ function integrateParallelWriteFanout(config, artifact) {
17
+ return {
18
+ ...artifact,
19
+ workflows: Object.fromEntries(Object.entries(artifact.workflows).map(([id, workflow]) => [id, {
20
+ ...workflow,
21
+ nodes: integrateNodeList(config, workflow.nodes)
22
+ }]))
23
+ };
24
+ }
25
+ function integrateNodeList(config, nodes) {
26
+ const index = dependentsByNeed(nodes);
27
+ const unintegrated = nodes.filter((node) => isUnintegratedWriteFanout(config, node) && !hasDrainMerge(node.id, index));
28
+ if (unintegrated.length === 0) return nodes;
29
+ const usedIds = new Set(nodes.map((node) => node.id));
30
+ return unintegrated.reduce((current, parallel) => insertDrainMerge(current, parallel.id, usedIds), nodes);
31
+ }
32
+ function isUnintegratedWriteFanout(config, node) {
33
+ return node.kind === "parallel" && node.nodes.filter((child) => isWriteCapableParallelChild(config, child)).length > 1;
34
+ }
35
+ function hasDrainMerge(parallelId, index) {
36
+ return hasReachableDependent(parallelId, index, (node) => node.kind === "builtin" && node.builtin === DRAIN_MERGE_BUILTIN);
37
+ }
38
+ function insertDrainMerge(nodes, parallelId, usedIds) {
39
+ const mergeId = uniqueGeneratedId(`generated-drain-merge-${parallelId}`, usedIds, "generated-drain-merge");
40
+ const rerouted = nodes.map((node) => rerouteNeed(node, parallelId, mergeId));
41
+ const mergeNode = {
42
+ builtin: DRAIN_MERGE_BUILTIN,
43
+ id: mergeId,
44
+ kind: "builtin",
45
+ needs: [parallelId]
46
+ };
47
+ return [...rerouted, mergeNode];
48
+ }
49
+ function rerouteNeed(node, from, to) {
50
+ if (!node.needs?.includes(from)) return node;
51
+ const needs = node.needs.map((need) => need === from ? to : need);
52
+ return {
53
+ ...node,
54
+ needs: [...new Set(needs)]
55
+ };
56
+ }
57
+ //#endregion
58
+ export { integrateParallelWriteFanout };
@@ -1,6 +1,7 @@
1
1
  //#region src/schedule/passes/index.ts
2
2
  const SCHEDULE_PASS_ORDER = [
3
3
  "coverage",
4
+ "drain-merge",
4
5
  "models",
5
6
  "ids",
6
7
  "references"
@@ -35,6 +35,7 @@ function plannerPrompt(entrypointId, task, baseline, config, planningContext) {
35
35
  "Shape the graph by intent, not by ticket count. Do not create a full RED/GREEN/ACCEPTANCE/VERIFY chain for each backlog ticket unless each step needs ticket-specific evidence.",
36
36
  "Only add needs edges for real dependencies, shared constraints, or verification/review fan-in.",
37
37
  "Use one RED node for a group of tickets when they share a test strategy, then fan out to parallel GREEN implementation nodes where the work can be implemented independently.",
38
+ "When a parallel node contains more than one write-capable (implementation/GREEN) child, it MUST be followed by a builtin drain-merge node that needs the parallel node, and the parallel's downstream consumers must depend on that drain-merge. The drain-merge integrates the concurrent children; a parallel of multiple writers without one is rejected.",
38
39
  "Use one acceptance or verifier node for multiple GREEN nodes when the same acceptance checklist or real repository commands prove the group.",
39
40
  "Only serialize ticket nodes when the backlog, a shared migration/schema/API dependency, or implementation risk requires it.",
40
41
  "",
@@ -15,5 +15,22 @@ function isImplementationNode(config, node) {
15
15
  function isCoverageNode(config, node) {
16
16
  return hasSchedulingRole(config, node, "coverage");
17
17
  }
18
+ /**
19
+ * Whether a parallel child mutates the workspace, and therefore must not share a
20
+ * worktree with sibling writers unless their results are integrated downstream
21
+ * (a `drain-merge` builtin). Agent nodes are write-capable when their profile is
22
+ * workspace-write; command nodes always are; a nested parallel is write-capable
23
+ * when any descendant is. Single source of truth for both schedule normalization
24
+ * (the drain-merge integration pass) and validation.
25
+ */
26
+ function isWriteCapableParallelChild(config, node) {
27
+ if (node.kind === "command") return true;
28
+ if (node.kind === "parallel") return node.nodes.some((child) => isWriteCapableParallelChild(config, child));
29
+ if (node.kind === "agent") return isWorkspaceWriteProfile(config, node.profile);
30
+ return false;
31
+ }
32
+ function isWorkspaceWriteProfile(config, profileId) {
33
+ return config.profiles[profileId]?.filesystem?.mode === "workspace-write";
34
+ }
18
35
  //#endregion
19
- export { isCoverageNode, isImplementationNode };
36
+ export { isCoverageNode, isImplementationNode, isWriteCapableParallelChild };
@@ -6,8 +6,6 @@ var TicketGraphError = class extends Data.TaggedError("TicketGraphError") {};
6
6
  function buildTicketGraphEffect(tasks) {
7
7
  return Effect.gen(function* () {
8
8
  const graph = buildUncheckedTicketGraph(tasks);
9
- const missingDependencies = missingDependencyMessages(graph);
10
- if (missingDependencies.length > 0) return yield* Effect.fail(new TicketGraphError({ message: `Backlog dependency graph has missing references: ${missingDependencies.join("; ")}` }));
11
9
  const cycles = alg.findCycles(graph.dependencyGraph);
12
10
  if (cycles.length > 0) return yield* Effect.fail(new TicketGraphError({ message: `Backlog dependency graph contains cycle: ${cycles.map((cycle) => cycle.sort(compareTaskIds).join(" -> ")).join("; ")}` }));
13
11
  return graph;
@@ -45,6 +43,7 @@ function buildUncheckedTicketGraph(tasks) {
45
43
  const dependencyGraph = buildDependencyGraph(sortedTasks, tasksById);
46
44
  return {
47
45
  childrenByParentId: indexChildrenByParentId(sortedTasks),
46
+ danglingDependencies: missingDependencyMessages(sortedTasks, tasksById),
48
47
  dependencyGraph,
49
48
  tasksById
50
49
  };
@@ -69,9 +68,9 @@ function addDependencyEdges(dependencyGraph, tasks, tasksById) {
69
68
  function addTaskDependencyEdges(dependencyGraph, task, tasksById) {
70
69
  for (const dependency of task.dependencies) if (tasksById.has(dependency)) dependencyGraph.setEdge(dependency, task.id);
71
70
  }
72
- function missingDependencyMessages(graph) {
71
+ function missingDependencyMessages(tasks, tasksById) {
73
72
  const messages = [];
74
- for (const task of graph.tasksById.values()) for (const dependency of task.dependencies) if (!graph.tasksById.has(dependency)) messages.push(`${task.id} depends on missing ${dependency}`);
73
+ for (const task of tasks) for (const dependency of task.dependencies) if (!tasksById.has(dependency)) messages.push(`${task.id} depends on missing ${dependency}`);
75
74
  return messages;
76
75
  }
77
76
  function sequenceUncheckedTicketBatches(graph, ticketIds) {
package/package.json CHANGED
@@ -108,7 +108,6 @@
108
108
  }
109
109
  },
110
110
  "files": [
111
- ".agents/skills",
112
111
  "defaults",
113
112
  "dist",
114
113
  "docs",
@@ -127,7 +126,7 @@
127
126
  "prepack": "bun run build:cli"
128
127
  },
129
128
  "type": "module",
130
- "version": "3.0.1",
129
+ "version": "3.1.0",
131
130
  "description": "Config-driven multi-agent pipeline runner for repository work",
132
131
  "main": "./dist/index.js",
133
132
  "types": "./dist/index.d.ts",
@@ -1,79 +0,0 @@
1
- ---
2
- name: add-dark-mode
3
- description: Add dark mode with colors, shadows, and surfaces handled the way a designer would.
4
- ---
5
-
6
- # Add Dark Mode
7
-
8
- Use this when the user wants to add dark mode support to an existing UI.
9
-
10
- ## Activation
11
-
12
- ### Use For
13
-
14
- - adding dark mode to a page, section, component, or site
15
- - improving an existing dark mode treatment
16
- - converting a light-mode-only UI to support dark mode
17
-
18
- ### Do Not Use For
19
-
20
- - brand-new design or layout work
21
- - standalone image dark-mode conversion
22
- - responsive behavior, component organization, or general visual polish without dark mode
23
-
24
- ## Load First
25
-
26
- - No companion files are required.
27
- - Dark-mode design guidance is inline below.
28
-
29
- ## Progress Updates
30
-
31
- Keep the user informed so longer runs do not look stuck.
32
-
33
- - One-line status update before each major phase.
34
- - Concrete and lightweight: what you are doing now, not verbose logs.
35
-
36
- ## Workflow
37
-
38
- 1. Inspect the existing UI and project Tailwind conventions.
39
- 2. Convert markup to include appropriate dark-mode classes.
40
- 3. Audit rasterized images for dark-mode variants.
41
- 4. For each rasterized image that needs a dark-mode variant, hand off to `dark-mode-image`, which MUST load and use the `imagegen` skill before creating or editing image assets.
42
- 5. Save generated dark-mode images alongside the originals and wire them into the dark-mode UI.
43
-
44
- ## Dark Mode Rules
45
-
46
- ### Design Rules
47
-
48
- - Dark mode is about maintaining the same contrast ratios as light mode, not simply inverting colors
49
- - Dark mode doesn't need to preserve every detail of the light mode design — it just needs to look good
50
- - Default dark mode to follow the operating system's `prefers-color-scheme` setting (Tailwind's built-in `dark:` behavior); only add a manual toggle when the user explicitly asks for one
51
- - Remove all shadows in dark mode — use `dark:shadow-none`
52
- - On dark-mode-only sites, add the `scheme-only-dark` class to `<html>` or the top-level element — ensures native elements like scrollbars, form controls, and `color-scheme` render in dark mode
53
-
54
- ### Component Rules
55
-
56
- - Never keep large branded/colored panels in dark mode; instead use the same background color and add a light divider between sections
57
- - Style cards only slightly lighter than the page background (e.g. `dark:bg-gray-900` on a `dark:bg-gray-950` page); add a `dark:inset-ring dark:inset-ring-white/5` for definition
58
- - Make decorative quote marks in testimonials very faint (e.g. `dark:text-white/5`)
59
- - Never use multiple heading text colors in dark mode (e.g. dark gray + brand color); use a single light color like `white` or `gray-100` for all heading text
60
-
61
- ### Raster Image Rules
62
-
63
- - When adding or improving dark mode, audit the page for rasterized images that need dark-mode versions: photos, screenshots, product mockups, decorative backgrounds, textures, and rasterized illustrations
64
- - Never use CSS filters (`invert`, `brightness`, `contrast`, `opacity`) as the final dark-mode treatment for raster images; always create real dark-mode image files
65
- - Generate dark-mode raster image variants with the `dark-mode-image` skill, which MUST load and use the `imagegen` skill before creating or editing any raster image assets
66
-
67
- ### SVG Rules
68
-
69
- - For inline `<svg>` elements, style dark mode with Tailwind `dark:*` classes (e.g. `dark:fill-*`, `dark:stroke-*`, `dark:text-*`)
70
- - For external SVG files referenced via `<img>`, always create a dark-mode version alongside the original (e.g. `logo.svg` and `logo-dark.svg`); never substitute CSS filters (`invert`, `brightness`) or opacity adjustments for a true dark variant
71
-
72
- ## Guardrails
73
-
74
- - Do not generate, edit, or replace raster image assets directly from this skill; `dark-mode-image` owns that work and MUST use the `imagegen` skill.
75
- - Require the `dark-mode-image` + `imagegen` handoff even when the image change seems simple, decorative, or incidental.
76
-
77
- ## Verify
78
-
79
- - Check light and dark modes for contrast, missing variants, and images that still assume a light background.
@@ -1,61 +0,0 @@
1
- ---
2
- name: brand-kit
3
- description: Generate a complete visual identity and marketing-site mockup board from a product idea.
4
- ---
5
-
6
- # Brand Kit
7
-
8
- ## Overview
9
-
10
- Run the brand kit workflow from concept to one finished 3840 x 2160 image. This skill wraps [Brand Kit Prompt](./brand-kit-prompt.md) and then renders the generated prompt directly through the `imagegen` skill.
11
-
12
- Use this workflow when the output should emphasize memorable frontend art direction, distinctive website composition, production-grade public-facing marketing pages, and avoidance of generic AI aesthetics. The final image should follow the fixed structure defined by [Brand Kit Prompt](./brand-kit-prompt.md): two large website page mockups plus a narrow design-system rail that documents only typography and hierarchical color values.
13
-
14
- ## Load First
15
-
16
- - Read [Brand Kit Prompt](./brand-kit-prompt.md) before generating the intermediate image prompt.
17
- - Load and follow the `imagegen` skill before rendering the final image.
18
-
19
- ## Workflow
20
-
21
- 1. Treat the user's concept, brief, notes, constraints, references, audience, tone, avoid-list items, and attached images as the source input.
22
- 2. Use [Brand Kit Prompt](./brand-kit-prompt.md) with the source input to generate one production-ready mockup-first image prompt. If images are attached, describe them as visual inspiration only using the rules in `Attached Images`.
23
- 3. Capture the full prompt text from step 2 as intermediate working content. Do not present it as the final answer unless the user explicitly asks to see it.
24
- 4. Use `$imagegen` with the full generated prompt from step 2 as its input, including any attached images as visual references when the imagegen interface supports reference images.
25
- 5. Generate exactly one high-quality 3840 x 2160 px 16:9 landscape image: a fixed three-column marketing-site case-study board with page mockup 1 in the left 40%, page mockup 2 in the middle 40%, and a right-side design-system details rail in the final 20%.
26
- 6. Return the rendered image. Keep final commentary minimal.
27
-
28
- ## Attached Images
29
-
30
- If the user attaches images, use them as design inspiration only:
31
-
32
- - Use attached images to infer aesthetic direction, composition style, visual density, color atmosphere, type mood, spacing feel, texture, lighting, layout rhythm, and interaction/presentation patterns.
33
- - Do not copy or recreate attached-image content, logos, wordmarks, brand marks, icons, mascots, characters, product names, readable text, photography subjects, proprietary UI, exact layouts, or distinctive artwork.
34
- - Do not treat attached images as mandatory content for the generated brand kit unless the user explicitly says the image is their own brand asset and asks to use it.
35
- - When passing the generated prompt to `$imagegen`, explicitly state that attached images are style references only and must not be replicated.
36
- - If attached images conflict with the user's written concept, preserve the written concept and use the images only for visual direction.
37
-
38
- ## Routing Rules
39
-
40
- - If the user provides only a thin but usable concept, make careful creative inferences in the prompt-generation step.
41
- - Ask a follow-up only when there is no usable brand, product, company, idea, or concept information.
42
- - Preserve all user-supplied constraints through both steps, especially names, audience, positioning, tone, visual references, attached-image inspiration, required deliverables, and avoid-list items.
43
- - If the user asks for the image plus the generated prompt, render the image first, then include the prompt text afterward.
44
- - If the prompt-generation step produces multiple boards, extra alternatives, a flexible metadata placement, or any output shape other than the fixed structure, normalize the result to match `brand-kit-prompt` before passing it to `imagegen`.
45
- - Do not route this workflow through `brand-kit-images`.
46
-
47
- ## Output Discipline
48
-
49
- - Do not stop after producing the intermediate prompt.
50
- - Do not summarize or rewrite the intermediate prompt so heavily that brand details are lost.
51
- - Treat [Brand Kit Prompt](./brand-kit-prompt.md) as the source of truth for image structure and content. If this wrapper conflicts with that file, follow [Brand Kit Prompt](./brand-kit-prompt.md).
52
- - Do not generate a separate design-system board.
53
- - Do not generate multiple images, a contact sheet, or a two-board split.
54
- - Do not copy attached images or import their content, logos, text, brand marks, exact layouts, or proprietary UI into the generated image.
55
- - Do not generate a 2:1 board, a 4096 x 2048 board, or a flexible metadata strip/sidebar/footer/overlay layout.
56
- - Make the final image exactly two large public-facing website page mockups plus the right-side design-system rail.
57
- - Include a consistent logo, wordmark, or brand mark inside the page mockups where a production website would naturally show one.
58
- - Keep the design-system rail compact but legible at full 4K size, preserving only font names/typeface directions, dominant color values, supporting color values, palette hierarchy, and short color role labels.
59
- - In the rail, distinguish dominant/load-bearing colors from infrequent supporting accents. Dominant colors should appear larger, grouped as the main palette, and labeled by role; supporting/accent/signal colors should appear as smaller chips.
60
- - Do not put logo notes, spacing scales, border radius, grid specs, motion notes, component inventories, component state details, icon notes, elevation/shadow specs, or arbitrary brand copy in the design-system rail.
61
- - Do not create extra files or resource directories for this wrapper skill.
@@ -1,158 +0,0 @@
1
- ---
2
- name: brand-kit-prompt
3
- description: Generate an image prompt for one fixed-structure 4K marketing-site brand case-study board with two large page mockups and a narrow design-system rail documenting typography and hierarchical colors. Use when Codex is asked to write a brand kit prompt, website mockup prompt, marketing site prompt, landing page prompt, product mockup prompt, or image-generation prompt for a visual brand identity.
4
- ---
5
-
6
- # Brand Kit Prompt
7
-
8
- ## Purpose
9
-
10
- Generate one complete, production-ready image prompt for a fixed-structure 4K marketing-site brand case-study image. Output prompt text only; do not generate images.
11
-
12
- This skill prioritizes distinctive frontend art direction, production-grade public-facing marketing website mockups, generous whitespace, and consistent side-by-side comparison. Even when the concept is a web app, desktop app, mobile app, SaaS product, or other software interface, the board should show the public marketing site for that product. The final image must feel like two real, spacious website surfaces plus a concise typography/color rail, not a cramped moodboard, component inventory, app UI board, or traditional brand-system sheet.
13
-
14
- ## Source Handling
15
-
16
- - Use only the user's concept, brief, notes, constraints, references, attached images, audience, tone, required pages, and avoid-list items.
17
- - If the input is thin but usable, make careful creative inferences.
18
- - Ask a question only when there is no usable brand, product, company, idea, or concept.
19
- - Preserve user-supplied vocabulary, constraints, page requests, examples, references, attached-image inspiration, and avoid-list items.
20
- - Output only the final prompt, with no preamble, rationale, commentary, follow-up, or setup text.
21
-
22
- ## Attached Images
23
-
24
- If the user attaches images, inspect them and translate their visual qualities into prompt language. Use them as design inspiration only:
25
-
26
- - Extract aesthetic direction, composition style, visual density, color atmosphere, type mood, spacing feel, texture, lighting, layout rhythm, and interaction/presentation patterns.
27
- - Do not copy or recreate attached-image content, logos, wordmarks, brand marks, icons, mascots, characters, product names, readable text, photography subjects, proprietary UI, exact layouts, or distinctive artwork.
28
- - Do not treat attached images as mandatory content for the generated brand kit unless the user explicitly says the image is their own brand asset and asks to use it.
29
- - If attached images conflict with the written concept, preserve the written concept and use the images only for visual direction.
30
- - In the final prompt, include a short "Reference Image Use" note when images are attached: describe the style inspiration to borrow and explicitly state that attached images are style references only, not content or logo sources.
31
-
32
- ## Workflow
33
-
34
- 1. Infer the purpose, audience, positioning, product context, and brand personality.
35
- 2. Choose one clear, memorable aesthetic direction that fits the concept.
36
- 3. Choose the two public marketing-site page examples:
37
- - Page mockup 1 defaults to the homepage.
38
- - Page mockup 2 defaults to a concept-appropriate supporting page with a different content pattern from the homepage.
39
- - If the user asks for specific pages, use those instead.
40
- - If the concept is an app or software product, choose pages that can naturally show product screenshots inside the marketing site.
41
- 4. If images are attached, summarize their reusable visual qualities using `Attached Images`.
42
- 5. Assemble one internally consistent image-generation prompt using the structure in `Final Prompt Structure`.
43
-
44
- ## Canonical Board Spec
45
-
46
- The generated prompt must request this exact image structure unless the user explicitly asks for a different structure:
47
-
48
- - Canvas: one single 3840 x 2160 px, 16:9 landscape, high-quality 4K image.
49
- - Layout: three full-height vertical columns with clean gutters.
50
- - Widths: page mockup 1 = 40%, page mockup 2 = 40%, design-system rail = 20%; equivalent ratio 2 : 2 : 1.
51
- - Left column: page mockup 1.
52
- - Middle column: page mockup 2.
53
- - Right column: design-system details rail.
54
- - The two page mockups must dominate and read as large, inspectable website pages.
55
- - The rail must be quieter than the mockups but legible at full 4K size.
56
- - Keep the page mockups spacious and breathable, with clear margins, open section rhythm, and enough negative space that the design does not feel busy.
57
- - Do not add extra panels, page thumbnails, floating device mockups, moodboard imagery, standalone logo explorations, component inventories, callout overlays, or decorative filler.
58
- - Do not generate a separate design-system board, a two-board split, multiple images, unreadably tiny UI fragments, or a dashboard/workspace/app UI board unless the user explicitly requests an interface-only board instead of a marketing site.
59
-
60
- ## Page Mockups
61
-
62
- The two mockups should be substantial public-facing marketing website pages with generous spacing, strong breathing room, and restrained content density. Treat an app concept as a product that needs a marketing site, not as permission to make the board an app UI study. Product/app UI may appear only as supporting content embedded inside a page mockup.
63
-
64
- If the concept is a web app, desktop app, mobile app, SaaS product, marketplace, creator tool, productivity tool, or other software product, include at least one realistic screenshot or framed view of the app inside the marketing pages. These screenshots should help explain the product and provide brand inspiration, while the surrounding page remains the main subject.
65
-
66
- Page mockup 1:
67
-
68
- - Default to the homepage.
69
- - Make it the clearest expression of the marketing promise.
70
- - Include primary navigation with an appropriate logo, wordmark, or brand mark; a strong hero system; primary CTA; and enough below-the-fold content to show section pacing.
71
- - For app/software concepts, include a prominent but embedded product screenshot, device frame, desktop/webapp frame, mobile screen, or interface crop.
72
-
73
- Page mockup 2:
74
-
75
- - Default to a supporting page that reveals a different side of the system.
76
- - Prefer pages that add new content patterns: pricing, booking, signup, product/service detail, collection/category, editorial/content, comparison, case study, lead-capture, checkout, account creation, search/results, commerce, structured data, forms, tables, cards, proof blocks, dense typography, or screenshot-led feature explanation.
77
- - Reuse the same logo, wordmark, or mark from the homepage in realistic page chrome when appropriate.
78
-
79
- For each page, define:
80
-
81
- - Page type and purpose.
82
- - Layout structure, hierarchy, key components, and copy tone.
83
- - Logo/wordmark/mark placement when a real site would include one.
84
- - Product screenshot placement when the concept is an app/software product.
85
- - Visible design behavior: grid/composition, generous spacing feel, low-to-moderate density, type scale, navigation, CTAs, forms, cards, pricing tables, proof blocks, product tiles, filters, commerce modules, editorial modules, or other relevant components.
86
- - Whitespace strategy: wide margins, clear gutters, open hero composition, fewer simultaneous content blocks, and section pacing that feels calm rather than crowded.
87
- - Distinctive frontend composition: asymmetry, overlap, strict grid, dense utility, editorial pacing, diagonal flow, immersive media, tactile states, active/hover states, scroll moments, or another concept-appropriate idea.
88
-
89
- ## Design-System Rail
90
-
91
- The right rail documents only values that are hard to recover from the mockups without OCR.
92
-
93
- Include:
94
-
95
- - Typography: display/headline, body, and UI/label/numeric/mono typeface names or typeface directions; include brief hierarchy, casing, weight, tracking, or pairing notes only when useful.
96
- - Color: dominant/core colors separated from supporting/accent colors; approximate hex-style values; short role labels such as background, foreground, primary, surface, border, signal, accent, semantic, or category.
97
- - Color hierarchy: dominant/load-bearing colors shown as larger swatches or bars; supporting/accent/signal colors shown as smaller grouped chips.
98
- - Rail text optimized for full-4K readability: short labels, large enough type, clear spacing, no dense captions.
99
-
100
- Do not include in the rail:
101
-
102
- - Logo, wordmark, mark construction, lockups, logo notes, logo variations, or logo-spec content.
103
- - Spacing scales, border radius, grid specs, motion notes, component inventories, component states, icon notes, elevation/shadow specs, or arbitrary brand copy.
104
- - Slogans, positioning paragraphs, mood words, or any text that does not directly document typography or color values used in the page mockups.
105
-
106
- ## Creative Direction
107
-
108
- Choose a bold but concept-appropriate aesthetic direction, such as brutally minimal, maximalist, retro-futuristic, organic, luxury, playful, editorial, brutalist, art deco, soft, industrial, utilitarian, or another direction inferred from the brief.
109
-
110
- Define:
111
-
112
- - Purpose: what visitors should understand, trust, and do.
113
- - Marketing focus: how the site introduces, explains, proves, and sells the brand.
114
- - Tone: 3-5 strong adjectives, not a neutral default.
115
- - Differentiation: the one visual, typographic, interaction, material, motif, or page-structure idea someone would remember.
116
- - Constraints: production-grade, functional, accessible, plausible for a real frontend.
117
- - Intensity: maximalist systems may be rich; refined systems should rely on restraint, proportion, and precision.
118
- - Spacing: preserve generous whitespace even for expressive or maximalist concepts; use scale, contrast, and composition for impact instead of cramming in more modules.
119
-
120
- Avoid:
121
-
122
- - Defaulting to Inter, Roboto, Arial, system fonts, or overused neutral typography unless requested.
123
- - Cliche purple-blue gradients on white, generic glassmorphism, bland SaaS dashboards, default rounded cards, cookie-cutter component layouts, unrelated gradient blobs, or decorative effects unrelated to the brand.
124
- - Cramped layouts, busy collages, overfilled sections, dense rows of tiny cards, excessive annotations, or too many simultaneous UI fragments.
125
- - Reusing the same trendy typefaces or color systems across concepts.
126
-
127
- ## Final Prompt Structure
128
-
129
- Assemble the final answer as the image prompt itself, using these sections:
130
-
131
- 1. Brand Positioning
132
- - Target audience, market positioning, 3-5 tone adjectives, brand personality, relevant comparables/references, and avoid list.
133
- 2. Aesthetic Concept
134
- - Core frontend art direction in one vivid phrase, why it fits, memorable design idea, intensity/restraint, and what makes it specific to this brand.
135
- 3. Reference Image Use
136
- - Include only when images are attached. Summarize reusable visual qualities and state that references are for style inspiration only, not for copied content, logos, text, exact layouts, or proprietary UI.
137
- 4. Board Layout
138
- - Restate the canonical 3840 x 2160, 40% / 40% / 20%, three-column layout and the prohibition on extra panels or alternate layouts.
139
- 5. Page Mockups
140
- - Define the homepage and supporting page using the `Page Mockups` requirements, or use the user's requested pages.
141
- 6. Design-System Rail
142
- - Define only the typography block and hierarchical color block using the `Design-System Rail` requirements.
143
- 7. Visual Style Constraints
144
- - State what to avoid, what to emphasize, anti-generic constraints, generous whitespace requirements, and that the fixed layout still applies even when the aesthetic is expressive.
145
- 8. Rendering / Style Hints
146
- - End with one concise rendering line: one 3840 x 2160 px 16:9 high-quality 4K presentation image; fixed 40% page mockup 1 / 40% page mockup 2 / 20% typography-and-color rail; crisp readable UI and rail text; production-grade marketing website mockups; bold concept-specific art direction; generous margins, open section rhythm, and calm whitespace; realistic polished visual design.
147
-
148
- ## Rules
149
-
150
- - Be specific and concrete; maintain internal consistency across all sections.
151
- - Make the aesthetic direction memorable and concept-specific.
152
- - Keep the website mockups spacious; do not trade readability and whitespace for extra content.
153
- - Use specific typeface names or precise typeface directions and approximate color values.
154
- - Specify which colors are dominant/load-bearing and which are supporting/rare accents, and require that hierarchy to be visible.
155
- - Keep all visible rail text short enough for image generation to render legibly.
156
- - Do not hardcode examples from one concept into another concept.
157
- - Do not ask for a separate design-system board or two images.
158
- - Do not explain your reasoning.