whale-igniter 1.2.2 → 1.3.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.
@@ -0,0 +1,82 @@
1
+ export function renderProject(config, errors, warnings, refinementCount, decisionCount) {
2
+ return `# Project Context
3
+
4
+ - **Project name:** ${config.projectName ?? "(unset)"}
5
+ - **Project type:** ${config.projectType ?? "unspecified"}
6
+ - **Stack:** ${config.stack ?? "css"}
7
+ - **AI targets:** ${(config.aiTargets ?? []).join(", ") || "(none)"}
8
+ - **Active packs:** ${(config.packs ?? []).join(", ") || "(none)"}
9
+ - **Ignited:** ${config.ignited?.at ?? "(not yet)"} (${config.ignited?.mode ?? "—"})
10
+
11
+ ## Current status
12
+
13
+ - Validation errors: ${errors}
14
+ - Validation warnings: ${warnings}
15
+ - Decisions logged: ${decisionCount}
16
+ - Active refinements: ${refinementCount}
17
+
18
+ _Generated by Whale Igniter._
19
+ `;
20
+ }
21
+ export function renderWikiReadme(_config) {
22
+ return `# LLM Wiki
23
+
24
+ This directory is generated by Whale Igniter. It contains a human-and-AI
25
+ readable view of the project's operational context.
26
+
27
+ **Do not edit these files directly** — they are regenerated from
28
+ \`intelligence/*.json\` and \`whale.config.json\` whenever you run
29
+ \`whale sync\`.
30
+
31
+ ## Files
32
+
33
+ - \`PROJECT.md\` — high-level project facts
34
+ - \`FOUNDATIONS.md\` — grid, radius, tokens
35
+ - \`CONVENTIONS.md\` — active conventions and refinements
36
+ - \`DECISIONS.md\` — decision log
37
+ - \`COMPONENTS.md\` — component catalog
38
+ - \`WORKFLOWS.md\` — recommended usage flow
39
+
40
+ ## For AI agents
41
+
42
+ The canonical entry point for AI agents is \`/CLAUDE.md\` at the project root.
43
+ This wiki is the detailed view — start with the root file, drill in here.
44
+
45
+ _Generated by Whale Igniter._
46
+ `;
47
+ }
48
+ export function renderWorkflows(_config) {
49
+ return `# Workflows
50
+
51
+ ## Daily flow
52
+
53
+ \`\`\`
54
+ whale validate # see what's drifting
55
+ whale refine "<note>" # accept an intentional exception
56
+ whale decision # record a non-obvious choice
57
+ whale component add <name> # register a new component
58
+ whale sync # regenerate AI context
59
+ \`\`\`
60
+
61
+ ## When to use what
62
+
63
+ | You want to... | Command |
64
+ | --------------------------------------------- | ----------------------------- |
65
+ | See what's broken | \`whale validate\` |
66
+ | Accept an exception ("we use radius 0 here") | \`whale refine "..."\` |
67
+ | Log an architecture/product choice | \`whale decision\` |
68
+ | Track a new component | \`whale component add\` |
69
+ | Refresh AI context after manual edits | \`whale sync\` |
70
+ | Produce human reports | \`whale docs\` |
71
+ | Review style drift interactively | \`whale insights drift <cat>\`|
72
+
73
+ ## Recommended cadence
74
+
75
+ - **Per change:** run \`validate\` before commit.
76
+ - **Per significant choice:** record a \`decision\` or \`refinement\`.
77
+ - **Per session:** run \`sync\` before handing off to an AI agent.
78
+ - **Per sprint:** review \`whale insights drift spacing\` for accumulated drift.
79
+
80
+ _Generated by Whale Igniter._
81
+ `;
82
+ }
@@ -0,0 +1,25 @@
1
+ import { loadConfig } from "./config.js";
2
+ import { resolveTarget } from "./paths.js";
3
+ export async function getAiAvailability(target) {
4
+ if (process.env.ANTHROPIC_API_KEY) {
5
+ return { available: true, source: "env-anthropic" };
6
+ }
7
+ if (process.env.OPENAI_API_KEY) {
8
+ return { available: true, source: "env-openai" };
9
+ }
10
+ try {
11
+ const ws = resolveTarget(target);
12
+ const config = await loadConfig(ws);
13
+ const provider = config.selene?.provider;
14
+ if (provider === "anthropic" && process.env.ANTHROPIC_API_KEY) {
15
+ return { available: true, source: "config" };
16
+ }
17
+ if (provider === "openai" && process.env.OPENAI_API_KEY) {
18
+ return { available: true, source: "config" };
19
+ }
20
+ }
21
+ catch {
22
+ // config unreadable — no AI
23
+ }
24
+ return { available: false, source: "none" };
25
+ }
@@ -0,0 +1,54 @@
1
+ const PROJECT_TYPE_MAP = {
2
+ "web-app": "web-app",
3
+ "marketing-site": "landing-page",
4
+ "portfolio": "landing-page",
5
+ "internal-tool": "web-app",
6
+ "prototype": "web-app",
7
+ "other": "other"
8
+ };
9
+ const STACK_MAP = {
10
+ "react-ts": "tailwind",
11
+ "vue-ts": "css",
12
+ "svelte-ts": "css",
13
+ "html-css-js": "css",
14
+ "other": "css"
15
+ };
16
+ const AI_TARGETS_MAP = {
17
+ solo: ["claude"],
18
+ small: ["claude", "codex"],
19
+ large: ["claude", "codex", "cursor"]
20
+ };
21
+ export function suggestUiCategories(projectType) {
22
+ const map = {
23
+ "web-app": ["forms", "navigation", "feedback"],
24
+ "marketing-site": ["surface", "layout"],
25
+ "portfolio": ["surface", "layout"],
26
+ "internal-tool": ["forms", "navigation", "feedback", "data-display"],
27
+ "prototype": ["forms", "feedback"],
28
+ "other": ["forms"]
29
+ };
30
+ return map[projectType] ?? ["forms"];
31
+ }
32
+ export function mapWizardAnswers(answers) {
33
+ const projectType = PROJECT_TYPE_MAP[answers.projectType];
34
+ const stack = STACK_MAP[answers.stack];
35
+ const aiTargets = AI_TARGETS_MAP[answers.teamSize];
36
+ const packs = answers.agentPacks && answers.agentPacks.length > 0
37
+ ? answers.agentPacks
38
+ : ["selene"];
39
+ const uiReferences = answers.uiCategories ?? [];
40
+ const config = {
41
+ projectType,
42
+ stack,
43
+ aiTargets: aiTargets,
44
+ packs,
45
+ uiReferences,
46
+ foundations: { grid: 8, radius: { control: 2, container: 4 } },
47
+ branding: { tone: "enterprise-minimal", accent: "cyan" },
48
+ intelligence: { trackPreferences: true, trackRefinements: true, decisionLogging: true }
49
+ };
50
+ const projectIntentNote = answers.projectType === "other" && answers.projectTypeOther
51
+ ? answers.projectTypeOther
52
+ : undefined;
53
+ return { config, projectIntentNote };
54
+ }
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const PACKAGE_VERSION = "1.2.2";
1
+ export const PACKAGE_VERSION = "1.3.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "whale-igniter",
3
- "version": "1.2.2",
3
+ "version": "1.3.0",
4
4
  "description": "CLI-first operational intelligence. Bootstraps and adopts AI-readable project context so agents like Claude Code, Codex and Cursor understand your design system from the first commit. Includes an MCP server, a file watcher, deterministic insights, and an opt-in AI bridge (Selene).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -18,7 +18,7 @@
18
18
  "dev": "tsx src/index.ts",
19
19
  "build": "tsc",
20
20
  "start": "node dist/index.js",
21
- "test": "tsx tests/run.ts && tsx tests/mcp-smoke.ts",
21
+ "test": "tsx tests/run.ts && tsx tests/mcp-smoke.ts && tsx tests/extractors.ts && tsx tests/driftAnalyzers.ts",
22
22
  "prepublishOnly": "npm run build && npm test"
23
23
  },
24
24
  "engines": {