whale-igniter 1.3.7 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,48 @@
1
+ # Changelog
2
+
3
+ All notable changes to Whale Igniter are documented here.
4
+
5
+ ## 1.5.1 - 2026-06-03
6
+
7
+ ### Added
8
+
9
+ - `whale forge <Component>` — generates a Markdown implementation contract for a registered component, including spec table, derived design tokens, and an implementation checklist. `whale create component` now suggests running forge as a next step.
10
+ - `whale scribe readme <Component>` — uses the configured AI provider (Anthropic/OpenAI) to generate a developer-ready README for a registered component. Falls back to `--prompt-only` if no API key is set.
11
+ - `whale scribe overview` — generates a full project overview README with foundations, component catalog, and architectural decisions via AI.
12
+ - `whale atlas health` — generates an AI-powered project health report for PMs and tech leads: validation status, design system maturity, risk signals, and prioritized next steps.
13
+ - `whale atlas decisions` — lists active architectural decisions grouped by category, filterable by `--category` and `--status`.
14
+ - Block-style ASCII art title in the `whale ignite` splash screen (Larry 3D → Block font, hardcoded, no runtime dependency).
15
+ - Default header and footer in generated landing pages, with nav links to Features, Proof, and Contact.
16
+ - Hover microinteractions on buttons, cards, hero panel, and quote block, with `prefers-reduced-motion` support.
17
+ - Mobile-responsive fixes: media queries corrected to `768px` literal (not CSS vars), header/footer stack on mobile, contact grid single-column at narrow viewports.
18
+
19
+ ## 1.5.0 - 2026-06-03
20
+
21
+ ### Added
22
+
23
+ - Custom landing-page copy without AI via `whale create landing --content <path>`.
24
+ - Hero override flags for generated landing pages: `--title`, `--eyebrow`, `--tagline`, `--cta`, and `--cta-href`.
25
+ - Local onboarding helpers for landing generation: `--sample-content`, `--brief`, and role-based next-edit hints.
26
+ - Validation for local landing content JSON, with clean CLI failures for malformed content.
27
+
28
+ ## 1.4.0 - 2026-06-03
29
+
30
+ ### Added
31
+
32
+ - Local UI theme engine for generated landing pages, with Atlas, Harbor, and Aurora themes.
33
+ - `whale themes list` for browsing shipped themes.
34
+ - Capability-gated `whale ignite` splash with color, Unicode, and plain fallbacks.
35
+ - README Data & privacy section, generated-output ownership note, and font attribution.
36
+
37
+ ### Changed
38
+
39
+ - Generated landing CSS now emits theme-driven custom properties for color, typography, structure, interaction, and motion.
40
+ - Selene response cache writes now ensure `.whale/` is ignored in the target project's `.gitignore`.
41
+ - Reworded older brand-planning docs to avoid vague status language.
42
+
43
+ ### Verified
44
+
45
+ - Selene API keys are read from environment variables and used only in provider request headers.
46
+ - Selene cache stores response text under `.whale/selene/cache`; it does not store API keys.
47
+ - No font binaries are shipped.
48
+ - No telemetry or analytics code is present.
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img src="https://cdn.jsdelivr.net/npm/whale-igniter@1.3.0/brand/lockup.svg" alt="Whale Igniter" width="640">
2
+ <img src="https://cdn.jsdelivr.net/npm/whale-igniter@latest/brand/lockup.svg" alt="Whale Igniter" width="640">
3
3
  </p>
4
4
 
5
5
  <p align="center">
@@ -43,6 +43,8 @@ my-app/
43
43
 
44
44
  The agent doesn't guess anymore. It reads.
45
45
 
46
+ Generated output belongs to you. Files created by Whale Igniter, including generated HTML, CSS, CLAUDE.md, AGENTS.md, wiki pages, and copied theme files, are yours to use and modify; they are not restricted by this project's MIT license.
47
+
46
48
  ---
47
49
 
48
50
  ## What agents can read — and write
@@ -98,6 +100,55 @@ whale create landing --theme atlas # enterprise minimal, dense, neutral (de
98
100
 
99
101
  Each theme defines four tiers — Identity, Typography, Structural, Interaction — and emits a complete CSS custom property block. Swap themes; everything updates.
100
102
 
103
+ Landing copy can be customized without AI:
104
+
105
+ ```bash
106
+ whale create landing --theme harbor --title "FuelForge" --tagline "Meal planning for athletes who train hard."
107
+ whale create landing --theme aurora --content landing.json
108
+ whale create landing --brief
109
+ ```
110
+
111
+ `landing.json` can define the brand, hero copy, CTA, features, proof, and contact copy. CLI flags override the JSON, so quick edits stay fast. Use `--sample-content` to generate an editable starter file, or `--brief` for a short local questionnaire that creates the JSON and landing together.
112
+
113
+ ---
114
+
115
+ ## Implementation intelligence
116
+
117
+ Once a component exists, Whale helps you build it right and document it thoroughly. Three commands, one chain:
118
+
119
+ ```bash
120
+ # 1. Generate a typed component scaffold
121
+ whale create component Button --variants primary,secondary,ghost --states hover,focus,disabled
122
+
123
+ # 2. Generate an implementation contract — spec, tokens, checklist
124
+ whale forge Button
125
+
126
+ # 3. Generate a developer README using AI
127
+ whale scribe readme Button
128
+ ```
129
+
130
+ `whale forge` produces a Markdown contract in `docs/forge/` with the component's foundation spec (grid, radius, padding), derived design tokens, and an implementation checklist. No API key required.
131
+
132
+ `whale scribe readme` calls your configured AI provider (Anthropic or OpenAI) and writes a developer-ready README to `docs/scribe/`. Use `--prompt-only` to get the prompt without an API call.
133
+
134
+ `whale scribe overview` generates a full project README — foundations, component catalog, architectural decisions — in one pass.
135
+
136
+ ---
137
+
138
+ ## Project health (Atlas)
139
+
140
+ Atlas gives product managers and tech leads a narrative view of the project's operational health.
141
+
142
+ ```bash
143
+ whale atlas health # AI-generated health report: errors, risk areas, next steps
144
+ whale atlas decisions # list active architectural decisions by category
145
+ whale atlas decisions --category design-system
146
+ ```
147
+
148
+ `whale atlas health` scans validation issues, component coverage, and recorded decisions, then generates a prioritized health report in `docs/atlas/health.md`. Use `--prompt-only` without an API key.
149
+
150
+ `whale atlas decisions` lists active decisions inline, grouped by category, with rationale and consequences.
151
+
101
152
  ---
102
153
 
103
154
  ## Core commands
@@ -112,8 +163,12 @@ Each theme defines four tiers — Identity, Typography, Structural, Interaction
112
163
  | `whale changes --since HEAD~5` | What changed in intelligence stores since a git ref |
113
164
  | `whale themes list` | Browse available UI themes |
114
165
  | `whale create landing --theme <name>` | Generate a themed HTML/CSS landing page |
115
- | `whale create component Hero` | Generate a typed component with intelligence registration |
116
- | `whale references add --all` | Install the UI component reference library |
166
+ | `whale create component <Name>` | Generate a typed component with intelligence registration |
167
+ | `whale forge <Component>` | Generate an implementation contract for a registered component |
168
+ | `whale scribe readme <Component>` | Generate a developer README for a component using AI |
169
+ | `whale scribe overview` | Generate a full project README using AI |
170
+ | `whale atlas health` | Generate an AI-powered project health report |
171
+ | `whale atlas decisions` | List active architectural decisions |
117
172
  | `whale selene suggest` | AI-powered improvement suggestions (API key optional) |
118
173
  | `whale mcp config --client cursor` | Configure an MCP client |
119
174
 
@@ -121,14 +176,14 @@ Each theme defines four tiers — Identity, Typography, Structural, Interaction
121
176
 
122
177
  ## Operating packs
123
178
 
124
- Packs are structured roles not autonomous agents, but instructions and context that help the agent you already use work with better information.
179
+ Packs add structured operational context to your project. `forge`, `scribe`, and `atlas` are available as both standalone commands and installable packs installing a pack makes its context visible to AI agents via CLAUDE.md and the MCP server.
125
180
 
126
181
  ```bash
127
- whale team add lighthouse # quality and validation checks
128
- whale team add scribe # documentation and wiki generation
129
- whale team add forge # implementation architecture
130
- whale team add atlas # product strategy
131
- whale team add selene # AI suggestions and audits
182
+ whale team add lighthouse # quality and accessibility validation
183
+ whale team add scribe # documentation generation
184
+ whale team add forge # implementation contracts and handoff
185
+ whale team add atlas # product health and decision tracking
186
+ whale team add selene # AI suggestions and component audits
132
187
  ```
133
188
 
134
189
  ---
@@ -148,10 +203,30 @@ whale selene describe src/components/Button.tsx
148
203
 
149
204
  ---
150
205
 
206
+ ## Data & privacy
207
+
208
+ Whale Igniter runs offline by default. Core flows such as themes, drift detection, wiki generation, MCP, and local project analysis do not require an API key and do not send project data over the network.
209
+
210
+ AI features are opt-in. When you enable Selene API mode or use `whale scribe` / `whale atlas health`, Whale sends the prompt and project context to the selected provider, Anthropic or OpenAI, under that provider's terms. You are responsible for reviewing context before sending it and for keeping secrets or sensitive data out of prompts.
211
+
212
+ API keys are read from environment variables only: `ANTHROPIC_API_KEY` or `OPENAI_API_KEY`. The key is used only in request headers, and Whale does not log it, write it to config, or persist it on disk.
213
+
214
+ Selene's local cache stores response text under `.whale/selene/cache` in the target project. It does not store API keys. Whale also ensures `.whale/` is ignored by the target project's `.gitignore` when writing Selene cache entries.
215
+
216
+ Whale Igniter has no telemetry or analytics.
217
+
218
+ ---
219
+
151
220
  ## Requirements
152
221
 
153
222
  - Node ≥ 20
154
- - No API key required for any core flow — themes, drift detection, wiki generation, and MCP are fully local and deterministic
223
+ - No API key required for any core flow — themes, drift detection, wiki generation, MCP, `whale forge`, and `whale atlas decisions` are fully local and deterministic
224
+
225
+ ---
226
+
227
+ ## Credits
228
+
229
+ Brand assets reference JetBrains Mono (SIL Open Font License 1.1) and Special Elite (Apache License 2.0). No font binaries are shipped.
155
230
 
156
231
  ---
157
232
 
@@ -164,6 +239,6 @@ whale selene describe src/components/Button.tsx
164
239
  ---
165
240
 
166
241
  <p align="center">
167
- <img src="https://cdn.jsdelivr.net/npm/whale-igniter@1.3.0/brand/logo.svg" alt="" width="44"><br>
242
+ <img src="https://cdn.jsdelivr.net/npm/whale-igniter@latest/brand/logo.svg" alt="" width="44"><br>
168
243
  <sub><b>Whale Igniter</b> · map the project before the agent moves</sub>
169
244
  </p>
@@ -0,0 +1,196 @@
1
+ import path from "node:path";
2
+ import fs from "fs-extra";
3
+ import ora from "ora";
4
+ import { resolveTarget } from "../utils/paths.js";
5
+ import { loadConfig } from "../utils/config.js";
6
+ import { loadComponents } from "../utils/components.js";
7
+ import { loadDecisions } from "../utils/decisions.js";
8
+ import { loadRefinements } from "../utils/refinements.js";
9
+ import { validateCss } from "../validators/cssValidator.js";
10
+ import { resolveProvider } from "../selene/providers.js";
11
+ import { callProvider } from "../selene/apiClient.js";
12
+ import { ui } from "../ui/index.js";
13
+ // ---------------------------------------------------------------------------
14
+ // whale atlas health
15
+ // ---------------------------------------------------------------------------
16
+ export async function atlasHealthCommand(options = {}) {
17
+ const target = resolveTarget();
18
+ const config = await loadConfig(target);
19
+ const spinner = ora("Atlas · scanning project health").start();
20
+ const [components, decisions, refinements, issues] = await Promise.all([
21
+ loadComponents(target),
22
+ loadDecisions(target),
23
+ loadRefinements(target),
24
+ validateCss(target),
25
+ ]);
26
+ spinner.stop();
27
+ const errors = issues.filter((i) => i.severity === "error");
28
+ const warnings = issues.filter((i) => i.severity === "warning");
29
+ // Group issues by type to surface patterns
30
+ const issuesByType = new Map();
31
+ for (const issue of issues) {
32
+ issuesByType.set(issue.type, (issuesByType.get(issue.type) ?? 0) + 1);
33
+ }
34
+ const topIssueTypes = [...issuesByType.entries()]
35
+ .sort((a, b) => b[1] - a[1])
36
+ .slice(0, 5);
37
+ const activeDecisions = decisions.filter((d) => d.status === "active");
38
+ const outDir = options.out ?? "docs/atlas";
39
+ const fileRel = path.join(outDir, "health.md").replace(/\\/g, "/");
40
+ const fileAbs = path.join(target, fileRel);
41
+ if (await fs.pathExists(fileAbs) && !options.force) {
42
+ console.log(ui.fail(`${ui.path(fileRel)} already exists. Use --force to overwrite.`));
43
+ process.exitCode = 1;
44
+ return;
45
+ }
46
+ const prompt = buildHealthPrompt({
47
+ config,
48
+ components,
49
+ activeDecisions,
50
+ refinementsCount: refinements.length,
51
+ errorCount: errors.length,
52
+ warningCount: warnings.length,
53
+ topIssueTypes,
54
+ });
55
+ if (options.promptOnly) {
56
+ console.log(prompt);
57
+ return;
58
+ }
59
+ const resolved = resolveProvider(config);
60
+ if (!resolved) {
61
+ console.log(ui.warn("No API key found — printing prompt instead."));
62
+ console.log(ui.muted(" Set ANTHROPIC_API_KEY or OPENAI_API_KEY to use AI generation."));
63
+ console.log("\n" + prompt);
64
+ return;
65
+ }
66
+ const spinner2 = ora("Atlas · generating health report").start();
67
+ const result = await callProvider(resolved, { prompt, maxTokens: 1400, temperature: 0.3 });
68
+ if (!result.ok) {
69
+ spinner2.fail(`API error: ${result.error}`);
70
+ process.exitCode = 1;
71
+ return;
72
+ }
73
+ spinner2.succeed("Health report generated");
74
+ const content = result.text.trim();
75
+ await fs.ensureDir(path.dirname(fileAbs));
76
+ await fs.writeFile(fileAbs, content + "\n", "utf8");
77
+ console.log(ui.ok(`Atlas → ${ui.path(fileRel)}`));
78
+ console.log(ui.muted(` provider: ${resolved.provider} · ${resolved.model}`));
79
+ // Print a quick inline summary so the user sees signal immediately
80
+ console.log("");
81
+ printInlineSummary({ errorCount: errors.length, warningCount: warnings.length, activeDecisions, components });
82
+ }
83
+ // ---------------------------------------------------------------------------
84
+ // whale atlas decisions
85
+ // ---------------------------------------------------------------------------
86
+ export async function atlasDecisionsCommand(options = {}) {
87
+ const target = resolveTarget();
88
+ const decisions = await loadDecisions(target);
89
+ if (decisions.length === 0) {
90
+ console.log(ui.muted("No decisions recorded yet. Run `whale decision` to add one."));
91
+ return;
92
+ }
93
+ let filtered = decisions;
94
+ if (options.category) {
95
+ filtered = filtered.filter((d) => d.category === options.category);
96
+ }
97
+ if (options.status) {
98
+ filtered = filtered.filter((d) => d.status === options.status);
99
+ }
100
+ else {
101
+ filtered = filtered.filter((d) => d.status === "active");
102
+ }
103
+ if (filtered.length === 0) {
104
+ console.log(ui.muted("No decisions match the given filters."));
105
+ return;
106
+ }
107
+ const byCategory = new Map();
108
+ for (const d of filtered) {
109
+ const list = byCategory.get(d.category) ?? [];
110
+ list.push(d);
111
+ byCategory.set(d.category, list);
112
+ }
113
+ for (const [category, list] of byCategory) {
114
+ console.log(ui.emphasis(`\n${category.toUpperCase()}`));
115
+ for (const d of list) {
116
+ console.log(` ${ui.ok(d.title)}`);
117
+ console.log(` ${ui.muted(d.decision)}`);
118
+ if (d.consequences) {
119
+ console.log(` ${ui.muted("→ " + d.consequences)}`);
120
+ }
121
+ console.log(` ${ui.muted(d.timestamp.slice(0, 10) + " · " + d.status)}`);
122
+ }
123
+ }
124
+ console.log(`\n${ui.muted(`${filtered.length} decision(s) shown.`)}`);
125
+ }
126
+ // ---------------------------------------------------------------------------
127
+ // Prompt builder
128
+ // ---------------------------------------------------------------------------
129
+ function buildHealthPrompt(args) {
130
+ const { config, components, activeDecisions, refinementsCount, errorCount, warningCount, topIssueTypes } = args;
131
+ const decisionSummary = activeDecisions.length > 0
132
+ ? activeDecisions.map((d) => `- [${d.category}] ${d.title}: ${d.decision}${d.consequences ? ` (consequences: ${d.consequences})` : ""}`).join("\n")
133
+ : " (none recorded)";
134
+ const issueBreakdown = topIssueTypes.length > 0
135
+ ? topIssueTypes.map(([type, count]) => `- ${type}: ${count} occurrence(s)`).join("\n")
136
+ : " (no issues detected)";
137
+ const riskSignals = [];
138
+ if (errorCount > 100)
139
+ riskSignals.push("High error volume — likely systemic design-system drift");
140
+ if (errorCount > 0 && refinementsCount === 0)
141
+ riskSignals.push("Errors present but no refinements recorded — exceptions not being tracked");
142
+ if (activeDecisions.length === 0)
143
+ riskSignals.push("No architectural decisions recorded — context risk for future agents and contributors");
144
+ if (components.length === 0)
145
+ riskSignals.push("No components registered — catalog is empty");
146
+ return [
147
+ "# Atlas task — project health report",
148
+ "",
149
+ "You are a technical product advisor reviewing a frontend project's operational health.",
150
+ "Write a concise, actionable health report for a PM or tech lead.",
151
+ "",
152
+ "## Project",
153
+ `- Name: ${config.projectName ?? "unnamed"}`,
154
+ `- Type: ${config.projectType ?? "unspecified"}`,
155
+ `- Stack: ${config.stack ?? "unspecified"}`,
156
+ `- Active packs: ${(config.packs ?? []).join(", ") || "none"}`,
157
+ "",
158
+ "## Validation status",
159
+ `- Errors: ${errorCount}`,
160
+ `- Warnings: ${warningCount}`,
161
+ `- Top issue types:`,
162
+ issueBreakdown,
163
+ "",
164
+ "## Design system posture",
165
+ `- Components registered: ${components.length}`,
166
+ `- Active decisions: ${activeDecisions.length}`,
167
+ `- Refinements (approved exceptions): ${refinementsCount}`,
168
+ "",
169
+ "## Active decisions",
170
+ decisionSummary,
171
+ "",
172
+ ...(riskSignals.length > 0 ? [
173
+ "## Risk signals detected",
174
+ riskSignals.map((s) => `- ${s}`).join("\n"),
175
+ "",
176
+ ] : []),
177
+ "## Task",
178
+ "Write a health report with these sections:",
179
+ "1. **Executive summary** (2-3 sentences on overall project health)",
180
+ "2. **Validation health** (what the error/warning counts mean in practice)",
181
+ "3. **Design system maturity** (component coverage, decision hygiene)",
182
+ "4. **Risk areas** (specific things that need attention)",
183
+ "5. **Recommended next steps** (3-5 concrete actions, ordered by priority)",
184
+ "",
185
+ "Be direct and specific. No generic advice. Audience: PM or tech lead who can act on it.",
186
+ "Write in plain Markdown. No preamble or explanation outside the report.",
187
+ ].join("\n");
188
+ }
189
+ // ---------------------------------------------------------------------------
190
+ // Inline summary
191
+ // ---------------------------------------------------------------------------
192
+ function printInlineSummary(args) {
193
+ const { errorCount, warningCount, activeDecisions, components } = args;
194
+ const healthEmoji = errorCount === 0 ? "●" : errorCount < 50 ? "◐" : "○";
195
+ console.log(`${healthEmoji} ${errorCount} error(s) · ${warningCount} warning(s) · ${components.length} component(s) · ${activeDecisions.length} decision(s)`);
196
+ }
@@ -98,6 +98,9 @@ export async function createComponentCommand(name, options = {}) {
98
98
  await generateWiki(target);
99
99
  console.log(ui.muted(`${ui.glyph.check} AI context updated`));
100
100
  }
101
+ if (shouldRegister) {
102
+ console.log(ui.muted(` → run \`whale forge ${name}\` to generate an implementation contract`));
103
+ }
101
104
  }
102
105
  // ---------------------------------------------------------------------------
103
106
  // Heuristics & templates