whale-igniter 1.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.
- package/LICENSE +21 -0
- package/README.md +275 -0
- package/dist/analyzer/imports.js +88 -0
- package/dist/analyzer/insights.js +276 -0
- package/dist/commands/add.js +36 -0
- package/dist/commands/adopt.js +180 -0
- package/dist/commands/adoptReview.js +267 -0
- package/dist/commands/component.js +93 -0
- package/dist/commands/createComponent.js +207 -0
- package/dist/commands/decision.js +98 -0
- package/dist/commands/docs.js +34 -0
- package/dist/commands/ignite.js +212 -0
- package/dist/commands/init.js +66 -0
- package/dist/commands/insights.js +123 -0
- package/dist/commands/mcp.js +106 -0
- package/dist/commands/refine.js +36 -0
- package/dist/commands/selene.js +516 -0
- package/dist/commands/sync.js +43 -0
- package/dist/commands/validate.js +48 -0
- package/dist/commands/watch.js +150 -0
- package/dist/commands/wiki.js +21 -0
- package/dist/generators/markdownGenerator.js +112 -0
- package/dist/generators/reportGenerator.js +50 -0
- package/dist/generators/wikiGenerator.js +365 -0
- package/dist/index.js +213 -0
- package/dist/mcp/server.js +404 -0
- package/dist/scanner/componentScanner.js +522 -0
- package/dist/scanner/foundationInferrer.js +174 -0
- package/dist/scanner/tailwindMapper.js +58 -0
- package/dist/scanner/tailwindScanner.js +186 -0
- package/dist/selene/apiClient.js +168 -0
- package/dist/selene/cache.js +68 -0
- package/dist/selene/clipboard.js +56 -0
- package/dist/selene/promptBuilder.js +229 -0
- package/dist/selene/providers.js +67 -0
- package/dist/selene/responseParser.js +149 -0
- package/dist/ui/atoms.js +30 -0
- package/dist/ui/blocks.js +208 -0
- package/dist/ui/capabilities.js +64 -0
- package/dist/ui/index.js +13 -0
- package/dist/ui/symbols.js +41 -0
- package/dist/ui/theme.js +78 -0
- package/dist/utils/components.js +40 -0
- package/dist/utils/config.js +31 -0
- package/dist/utils/decisions.js +32 -0
- package/dist/utils/paths.js +4 -0
- package/dist/utils/proposals.js +61 -0
- package/dist/utils/refinements.js +81 -0
- package/dist/utils/registry.js +45 -0
- package/dist/utils/writeJson.js +6 -0
- package/dist/validators/cssValidator.js +204 -0
- package/dist/version.js +1 -0
- package/docs/ROADMAP.md +206 -0
- package/package.json +76 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import { glob } from "glob";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import postcss from "postcss";
|
|
5
|
+
import { loadConfig } from "../utils/config.js";
|
|
6
|
+
import { loadRefinements, isSuppressed } from "../utils/refinements.js";
|
|
7
|
+
// Properties that take spacing values (length-based, grid-relevant).
|
|
8
|
+
const SPACING_PROPS = new Set([
|
|
9
|
+
"margin", "margin-top", "margin-right", "margin-bottom", "margin-left",
|
|
10
|
+
"padding", "padding-top", "padding-right", "padding-bottom", "padding-left",
|
|
11
|
+
"gap", "row-gap", "column-gap",
|
|
12
|
+
"top", "right", "bottom", "left",
|
|
13
|
+
"width", "height", "min-width", "min-height", "max-width", "max-height"
|
|
14
|
+
]);
|
|
15
|
+
// Heuristic: a stylesheet is "interactive" if it styles something that needs focus.
|
|
16
|
+
// Token sheets typically just declare custom properties; they don't need :focus-visible.
|
|
17
|
+
function hasInteractiveTargets(root) {
|
|
18
|
+
let found = false;
|
|
19
|
+
root.walkRules((rule) => {
|
|
20
|
+
const sel = rule.selector;
|
|
21
|
+
if (sel.includes("button") ||
|
|
22
|
+
sel.includes("input") ||
|
|
23
|
+
sel.includes("select") ||
|
|
24
|
+
sel.includes("textarea") ||
|
|
25
|
+
sel.includes("a[") ||
|
|
26
|
+
/\ba\b/.test(sel) ||
|
|
27
|
+
sel.includes("[role=") ||
|
|
28
|
+
sel.includes("[tabindex")) {
|
|
29
|
+
found = true;
|
|
30
|
+
return false; // stop walking
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
return found;
|
|
34
|
+
}
|
|
35
|
+
// A token sheet is one that mostly declares CSS custom properties at :root.
|
|
36
|
+
// We don't expect focus styles or grid compliance from these.
|
|
37
|
+
function isTokenSheet(root) {
|
|
38
|
+
let customProps = 0;
|
|
39
|
+
let otherDecls = 0;
|
|
40
|
+
root.walkDecls((decl) => {
|
|
41
|
+
if (decl.prop.startsWith("--"))
|
|
42
|
+
customProps++;
|
|
43
|
+
else
|
|
44
|
+
otherDecls++;
|
|
45
|
+
});
|
|
46
|
+
return customProps > 0 && customProps >= otherDecls * 2;
|
|
47
|
+
}
|
|
48
|
+
// Parse a CSS value into individual length tokens. Ignores function calls
|
|
49
|
+
// like url(...), var(...), calc(...) — those are handled separately.
|
|
50
|
+
function extractPxValues(value) {
|
|
51
|
+
// Strip function calls so we don't pick up px inside url("foo.png?w=10px").
|
|
52
|
+
const stripped = value.replace(/\b\w+\s*\([^)]*\)/g, "");
|
|
53
|
+
const matches = stripped.matchAll(/(-?\d+(?:\.\d+)?)px\b/g);
|
|
54
|
+
const out = [];
|
|
55
|
+
for (const m of matches) {
|
|
56
|
+
out.push({ raw: m[0], px: parseFloat(m[1]) });
|
|
57
|
+
}
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
// Extract hex colors from a value, but ignore those inside url() or var()
|
|
61
|
+
// (var() shouldn't contain hex but be safe). Also ignore inside strings.
|
|
62
|
+
function extractHexColors(value) {
|
|
63
|
+
// Remove function-call contents and quoted strings first.
|
|
64
|
+
const cleaned = value
|
|
65
|
+
.replace(/"[^"]*"/g, "")
|
|
66
|
+
.replace(/'[^']*'/g, "")
|
|
67
|
+
.replace(/\b\w+\s*\([^)]*\)/g, "");
|
|
68
|
+
const matches = cleaned.matchAll(/#[0-9a-fA-F]{3,8}\b/g);
|
|
69
|
+
return Array.from(matches, (m) => m[0]);
|
|
70
|
+
}
|
|
71
|
+
function getSelectorFor(node) {
|
|
72
|
+
let parent = node.parent;
|
|
73
|
+
while (parent) {
|
|
74
|
+
if (parent.type === "rule")
|
|
75
|
+
return parent.selector;
|
|
76
|
+
parent = parent.parent;
|
|
77
|
+
}
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
export async function validateCss(target, options = {}) {
|
|
81
|
+
const config = options.configOverride ?? await loadConfig(target);
|
|
82
|
+
const refinements = await loadRefinements(target);
|
|
83
|
+
const grid = config.foundations?.grid ?? 8;
|
|
84
|
+
const allowedRadii = [
|
|
85
|
+
0,
|
|
86
|
+
config.foundations?.radius?.control ?? 2,
|
|
87
|
+
config.foundations?.radius?.container ?? 4
|
|
88
|
+
];
|
|
89
|
+
const files = await glob("**/*.css", {
|
|
90
|
+
cwd: target,
|
|
91
|
+
absolute: true,
|
|
92
|
+
ignore: ["node_modules/**", "dist/**", ".git/**"]
|
|
93
|
+
});
|
|
94
|
+
const issues = [];
|
|
95
|
+
for (const file of files) {
|
|
96
|
+
const content = await fs.readFile(file, "utf8");
|
|
97
|
+
const relativeFile = path.relative(target, file);
|
|
98
|
+
let root;
|
|
99
|
+
try {
|
|
100
|
+
root = postcss.parse(content, { from: file });
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
issues.push({
|
|
104
|
+
severity: "error",
|
|
105
|
+
type: "parse-error",
|
|
106
|
+
file: relativeFile,
|
|
107
|
+
line: 1,
|
|
108
|
+
column: 1,
|
|
109
|
+
message: `CSS parse failed: ${err.message}`,
|
|
110
|
+
suggestion: "Fix the CSS syntax."
|
|
111
|
+
});
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
const tokenSheet = isTokenSheet(root);
|
|
115
|
+
root.walkDecls((decl) => {
|
|
116
|
+
const line = decl.source?.start?.line ?? 1;
|
|
117
|
+
const column = decl.source?.start?.column ?? 1;
|
|
118
|
+
const selector = getSelectorFor(decl);
|
|
119
|
+
// Skip declarations inside custom-property definitions —
|
|
120
|
+
// token sheets are allowed to declare raw values.
|
|
121
|
+
const isCustomPropDef = decl.prop.startsWith("--");
|
|
122
|
+
// --- Raw hex colors ---
|
|
123
|
+
if (!isCustomPropDef) {
|
|
124
|
+
const hexes = extractHexColors(decl.value);
|
|
125
|
+
for (const hex of hexes) {
|
|
126
|
+
const issue = {
|
|
127
|
+
severity: "warning",
|
|
128
|
+
type: "raw-hex-color",
|
|
129
|
+
file: relativeFile,
|
|
130
|
+
line,
|
|
131
|
+
column,
|
|
132
|
+
message: `Raw hex color detected: ${hex}`,
|
|
133
|
+
suggestion: "Use a semantic CSS token (var(--color-...)) instead.",
|
|
134
|
+
selector
|
|
135
|
+
};
|
|
136
|
+
if (!isSuppressed(issue, refinements))
|
|
137
|
+
issues.push(issue);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// --- Spacing grid compliance ---
|
|
141
|
+
if (SPACING_PROPS.has(decl.prop) && !isCustomPropDef) {
|
|
142
|
+
const pxValues = extractPxValues(decl.value);
|
|
143
|
+
for (const { raw, px } of pxValues) {
|
|
144
|
+
if (px === 0)
|
|
145
|
+
continue;
|
|
146
|
+
if (px % grid !== 0) {
|
|
147
|
+
const nearest = Math.round(px / grid) * grid;
|
|
148
|
+
const issue = {
|
|
149
|
+
severity: "error",
|
|
150
|
+
type: "spacing-scale",
|
|
151
|
+
file: relativeFile,
|
|
152
|
+
line,
|
|
153
|
+
column,
|
|
154
|
+
message: `${decl.prop}: ${raw} does not follow the ${grid}px grid.`,
|
|
155
|
+
suggestion: `Use ${nearest}px or a spacing token.`,
|
|
156
|
+
selector
|
|
157
|
+
};
|
|
158
|
+
if (!isSuppressed(issue, refinements))
|
|
159
|
+
issues.push(issue);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// --- Border radius consistency ---
|
|
164
|
+
if (decl.prop === "border-radius" && !isCustomPropDef) {
|
|
165
|
+
const pxValues = extractPxValues(decl.value);
|
|
166
|
+
for (const { raw, px } of pxValues) {
|
|
167
|
+
if (!allowedRadii.includes(px)) {
|
|
168
|
+
const issue = {
|
|
169
|
+
severity: "error",
|
|
170
|
+
type: "radius-consistency",
|
|
171
|
+
file: relativeFile,
|
|
172
|
+
line,
|
|
173
|
+
column,
|
|
174
|
+
message: `Invalid border-radius: ${raw}.`,
|
|
175
|
+
suggestion: `Use ${allowedRadii.filter((r) => r > 0).join("px or ")}px (controls vs. containers).`,
|
|
176
|
+
selector
|
|
177
|
+
};
|
|
178
|
+
if (!isSuppressed(issue, refinements))
|
|
179
|
+
issues.push(issue);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
// --- Focus-visible: only required on sheets with interactive targets,
|
|
185
|
+
// and only flagged once per sheet, not once per declaration. ---
|
|
186
|
+
if (!tokenSheet && hasInteractiveTargets(root) && !content.includes(":focus-visible")) {
|
|
187
|
+
const issue = {
|
|
188
|
+
severity: "warning",
|
|
189
|
+
type: "focus-visible",
|
|
190
|
+
file: relativeFile,
|
|
191
|
+
line: 1,
|
|
192
|
+
column: 1,
|
|
193
|
+
message: "Stylesheet has interactive elements but no :focus-visible state.",
|
|
194
|
+
suggestion: "Add visible keyboard focus styles for buttons/inputs/links."
|
|
195
|
+
};
|
|
196
|
+
if (!isSuppressed(issue, refinements))
|
|
197
|
+
issues.push(issue);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return issues;
|
|
201
|
+
}
|
|
202
|
+
export function hasErrors(issues) {
|
|
203
|
+
return issues.some((i) => i.severity === "error");
|
|
204
|
+
}
|
package/dist/version.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const PACKAGE_VERSION = "1.1.0";
|
package/docs/ROADMAP.md
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# Whale Igniter — Roadmap
|
|
2
|
+
|
|
3
|
+
The path from "a CLI that bootstraps AI context" to "the operating
|
|
4
|
+
system for AI-assisted product work."
|
|
5
|
+
|
|
6
|
+
This roadmap is followed in order. We don't skip versions; if a step
|
|
7
|
+
reveals that the next plan needs revising, we revise it before shipping.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Shipped
|
|
12
|
+
|
|
13
|
+
### v0.6 — Real validation + closed refinement loop
|
|
14
|
+
|
|
15
|
+
- PostCSS-based CSS validator (no regex, AST-correct).
|
|
16
|
+
- Foundations driven by `whale.config.json`.
|
|
17
|
+
- Scope-inferred refinements suppress matching issues automatically.
|
|
18
|
+
- Pack taxonomy: executable vs. generator.
|
|
19
|
+
|
|
20
|
+
### v0.7 — AI context bootstrapper
|
|
21
|
+
|
|
22
|
+
- `whale ignite` in three modes (opinionated, minimal, interactive wizard).
|
|
23
|
+
- `CLAUDE.md` at project root + optional `AGENTS.md`, `.cursorrules`,
|
|
24
|
+
`.github/copilot-instructions.md`.
|
|
25
|
+
- Structured stores: `decisions.json`, `components.json`,
|
|
26
|
+
`refinements.json`.
|
|
27
|
+
- Auto-sync on every recorded change.
|
|
28
|
+
|
|
29
|
+
### v0.8 — Brownfield adoption
|
|
30
|
+
|
|
31
|
+
- `whale adopt` scans React + Tailwind projects with a real AST.
|
|
32
|
+
- Component detection across function / arrow / forwardRef / memo /
|
|
33
|
+
class patterns. Entry-point names excluded.
|
|
34
|
+
- Tailwind class observation pipeline with variant stripping, arbitrary
|
|
35
|
+
values, font-size vs color disambiguation, ring-width handling.
|
|
36
|
+
- Foundation inference: grid via weighted coverage, radii with single
|
|
37
|
+
vs split detection, color palette.
|
|
38
|
+
- Staged proposals in `intelligence/proposed.json` with idempotent
|
|
39
|
+
fingerprints; interactive `adopt review` with accept/reject/edit.
|
|
40
|
+
|
|
41
|
+
### v0.9 — Insights + generation
|
|
42
|
+
|
|
43
|
+
- `whale insights` analyzer with 7+ deterministic checks: refinement
|
|
44
|
+
clusters, scopeless refinements, catalog coverage, orphan
|
|
45
|
+
components, decision tension, token drift, grid drift.
|
|
46
|
+
- `whale create component <Name>` generates typed React scaffolds
|
|
47
|
+
respecting current foundations (control or container template).
|
|
48
|
+
- `--json`, `--category`, `--min-severity` for scripting / CI.
|
|
49
|
+
|
|
50
|
+
### v0.10 — Selene MVP (prompt mode)
|
|
51
|
+
|
|
52
|
+
- `whale selene describe / audit / suggest / apply`.
|
|
53
|
+
- Prompt builder composes self-contained prompts with project context,
|
|
54
|
+
task, input, and strict output schemas.
|
|
55
|
+
- Robust response parser handles preambles, multiple fenced blocks,
|
|
56
|
+
bare JSON. Type-guarded schemas.
|
|
57
|
+
- Clipboard helper with cross-platform cascade (pbcopy / clip.exe /
|
|
58
|
+
wl-copy / xclip / xsel) and zero npm dependencies.
|
|
59
|
+
- Works fully offline.
|
|
60
|
+
|
|
61
|
+
### v0.11 — Selene API mode
|
|
62
|
+
|
|
63
|
+
- Auto-detect `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` and call directly.
|
|
64
|
+
- Bloque `selene` en `whale.config.json` para model, temperature,
|
|
65
|
+
autoCall, confirmCost, noCache.
|
|
66
|
+
- Pre-flight cost estimation, opt-in via `--confirm-cost`.
|
|
67
|
+
- On-disk response cache (sha256, 7-day TTL).
|
|
68
|
+
- Transparent fallback to prompt mode on any API failure.
|
|
69
|
+
|
|
70
|
+
### v1.0 — Production
|
|
71
|
+
|
|
72
|
+
- **MCP server.** Ten tools exposed over stdio: `whale_project_overview`,
|
|
73
|
+
`whale_list_components`, `whale_list_decisions`,
|
|
74
|
+
`whale_list_refinements`, `whale_validate`, `whale_insights`,
|
|
75
|
+
`whale_register_component`, `whale_record_decision`,
|
|
76
|
+
`whale_record_refinement`, `whale_sync`. Configurable for Claude Code,
|
|
77
|
+
Cursor, Zed, or any MCP client via `whale mcp config`.
|
|
78
|
+
- **File watcher.** `whale watch` regenerates CLAUDE.md and wiki on
|
|
79
|
+
changes to foundations or intelligence stores. Debounced, with
|
|
80
|
+
in-flight coalescing.
|
|
81
|
+
- **npm distribution.** Published as `whale-igniter`. Works with
|
|
82
|
+
`npx whale-igniter` or global install.
|
|
83
|
+
- **Production package.** Engines, license, files, .npmignore,
|
|
84
|
+
prepublishOnly script. README and ROADMAP refreshed.
|
|
85
|
+
- **Test coverage.** 44 unit tests + MCP smoke test that spawns the
|
|
86
|
+
server and exercises real protocol calls end-to-end.
|
|
87
|
+
|
|
88
|
+
### v1.1 — Premium runtime UI
|
|
89
|
+
|
|
90
|
+
The terminal output became the product surface. Commands stopped reaching
|
|
91
|
+
for chalk directly; every command now consumes a semantic UI layer where
|
|
92
|
+
output describes *intent* (success, warning, section header, key/value
|
|
93
|
+
pair) and the active theme decides what each intent looks like.
|
|
94
|
+
|
|
95
|
+
- **Semantic UI layer in `src/ui/`.** Atoms (color roles), symbols (glyphs
|
|
96
|
+
with ASCII fallbacks), blocks (header, section, kv, panel, summary,
|
|
97
|
+
next, ok/fail/warn/note), theme dispatcher. Commands import from `ui/`
|
|
98
|
+
rather than chalk; chalk is now confined to the theme module.
|
|
99
|
+
- **Single premium theme — graphite.** Cyan accent, charcoal grays, three
|
|
100
|
+
text-hierarchy levels. Structure ready for v1.2's multi-theme without
|
|
101
|
+
touching any command.
|
|
102
|
+
- **Capability detection.** Auto-detects color and Unicode support; falls
|
|
103
|
+
back to ASCII glyphs (`*`, `v`, `x`, `->`) and plain output without a
|
|
104
|
+
TTY. Three env overrides — `WHALE_PLAIN`, `WHALE_UNICODE`, `NO_COLOR` —
|
|
105
|
+
let users force a mode in CI logs or in legacy terminals.
|
|
106
|
+
- **All 12 commands migrated.** ignite, adopt, adopt review, init, sync,
|
|
107
|
+
wiki, validate, refine, decision, component (add/list), create
|
|
108
|
+
component, add, docs, watch, mcp (serve/config), selene (describe /
|
|
109
|
+
audit / suggest / apply / status / cache). Zero `chalk` imports outside
|
|
110
|
+
`src/ui/theme.ts`.
|
|
111
|
+
- **Tests.** 14 new UI tests on top of the v1.0 suite: capability
|
|
112
|
+
detection, theme structure, block formatting, alignment, glyph fallback.
|
|
113
|
+
Total: 61 unit tests + 6 MCP smoke checks, all green.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Next
|
|
118
|
+
|
|
119
|
+
The post-v1.1 plan is shaped by what actual users hit first. The list
|
|
120
|
+
below is in rough priority order, but every item will be re-evaluated
|
|
121
|
+
once real usage produces feedback.
|
|
122
|
+
|
|
123
|
+
### v1.2 — Hardening from real-world usage
|
|
124
|
+
|
|
125
|
+
Now that the surface area is feature-complete, the next version should
|
|
126
|
+
be small and reactive. Expected items:
|
|
127
|
+
|
|
128
|
+
- Edge cases in the scanner discovered against larger repos (10k+ LOC
|
|
129
|
+
Next.js apps, monorepos).
|
|
130
|
+
- MCP server polishing: better error messages, validation of inputs
|
|
131
|
+
the agents pass, telemetry helpers for the user to debug.
|
|
132
|
+
- Pre-commit hook helper: `whale hook install` to wire up
|
|
133
|
+
`whale validate && whale sync` automatically.
|
|
134
|
+
- Selene prompt caching at the Anthropic API level (split the context
|
|
135
|
+
prefix as a separate system message so caching can hit).
|
|
136
|
+
- Optional second theme once real users have asked for it. The
|
|
137
|
+
architecture is ready; we're deliberately waiting for demand before
|
|
138
|
+
shipping more themes.
|
|
139
|
+
|
|
140
|
+
### v1.3 — Multi-framework parsing
|
|
141
|
+
|
|
142
|
+
The Vue + Svelte parser is the largest stretch from current code. The
|
|
143
|
+
rest of the pipeline (foundation inference, insights, generators) is
|
|
144
|
+
already framework-agnostic; only the scanner needs new dialects.
|
|
145
|
+
|
|
146
|
+
### v1.4 — Style-system breadth
|
|
147
|
+
|
|
148
|
+
CSS-in-JS (vanilla-extract, Panda CSS, styled-components), plus
|
|
149
|
+
Tailwind config resolution that actually evaluates the user's
|
|
150
|
+
`tailwind.config.{js,ts}` for accurate scales. Style Dictionary /
|
|
151
|
+
Figma Tokens import would slot in here too.
|
|
152
|
+
|
|
153
|
+
### v2.0 — Team layer (uncommitted)
|
|
154
|
+
|
|
155
|
+
The decision we keep deferring: how teams collaborate around
|
|
156
|
+
`intelligence/`. Today it's local + git, and PRs are the workflow. At
|
|
157
|
+
some scale that breaks down — multiple writers, conflicting
|
|
158
|
+
decisions, no review surface. Possibilities:
|
|
159
|
+
|
|
160
|
+
- A "shared inbox" of proposed decisions/refinements that need
|
|
161
|
+
approval, separate from accepted ones.
|
|
162
|
+
- A web viewer for the wiki that's read-only and link-shareable.
|
|
163
|
+
- A schema lock that prevents PRs from contradicting active decisions
|
|
164
|
+
without an explicit `supersedes`.
|
|
165
|
+
|
|
166
|
+
We won't pick one until we have multiple teams telling us which one
|
|
167
|
+
they need most.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## What we will NOT do
|
|
172
|
+
|
|
173
|
+
These are listed explicitly to defend focus over time.
|
|
174
|
+
|
|
175
|
+
- **A web dashboard.** Whale is CLI-first. Forever.
|
|
176
|
+
- **A hosted SaaS.** Intelligence stays in the user's repo. No accounts.
|
|
177
|
+
- **Generic linting.** ESLint, Stylelint, Biome already exist. Whale's
|
|
178
|
+
validators only check what's tied to operational context (foundations,
|
|
179
|
+
refinements, decisions). Everything else is out of scope.
|
|
180
|
+
- **Lighthouse-style perf / SEO audits.** Different problem space. The
|
|
181
|
+
`lighthouse` pack name is about *guidance* (the lighthouse metaphor),
|
|
182
|
+
not the Google tool.
|
|
183
|
+
- **Project management.** No tasks, no kanban, no time tracking.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Operational milestones (not engineering work)
|
|
188
|
+
|
|
189
|
+
These are tasks that depend on the project owner, not on the codebase:
|
|
190
|
+
|
|
191
|
+
- **Publish to npm.** Code is ready. Requires an npm account and
|
|
192
|
+
`npm publish` from a clean checkout.
|
|
193
|
+
- **Public repo.** Move from local zips to a versioned GitHub repo
|
|
194
|
+
with releases.
|
|
195
|
+
- **Demo video.** Record the 5-minute "adopt a real repo and watch
|
|
196
|
+
Claude Code work with full context" walkthrough referenced in the
|
|
197
|
+
done criteria.
|
|
198
|
+
- **Field test.** Adopt the tool in three real projects (own or
|
|
199
|
+
partner teams) and feed observations into v1.1.
|
|
200
|
+
|
|
201
|
+
Until those happen, v1.0 is "feature-complete and ready to ship" but
|
|
202
|
+
not "released and validated in the wild."
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
_Last updated: v1.1 release._
|
package/package.json
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "whale-igniter",
|
|
3
|
+
"version": "1.1.0",
|
|
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
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"whale": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE",
|
|
14
|
+
"docs/ROADMAP.md"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"dev": "tsx src/index.ts",
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"start": "node dist/index.js",
|
|
20
|
+
"test": "tsx tests/run.ts && tsx tests/mcp-smoke.ts",
|
|
21
|
+
"prepublishOnly": "npm run build && npm test"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=20.0.0"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"cli",
|
|
28
|
+
"design-system",
|
|
29
|
+
"ai",
|
|
30
|
+
"claude",
|
|
31
|
+
"claude-code",
|
|
32
|
+
"cursor",
|
|
33
|
+
"codex",
|
|
34
|
+
"mcp",
|
|
35
|
+
"model-context-protocol",
|
|
36
|
+
"tailwind",
|
|
37
|
+
"react",
|
|
38
|
+
"design-ops",
|
|
39
|
+
"intelligence",
|
|
40
|
+
"documentation",
|
|
41
|
+
"ai-context",
|
|
42
|
+
"agents-md"
|
|
43
|
+
],
|
|
44
|
+
"author": "Whale Igniter contributors",
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "git+ssh://git@github.com/luisviol/whale-igniter.git"
|
|
49
|
+
},
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/luisviol/whale-igniter/issues"
|
|
52
|
+
},
|
|
53
|
+
"homepage": "https://github.com/luisviol/whale-igniter#readme",
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"@babel/parser": "^7.25.0",
|
|
56
|
+
"@babel/traverse": "^7.25.0",
|
|
57
|
+
"@babel/types": "^7.25.0",
|
|
58
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
59
|
+
"chalk": "^5.3.0",
|
|
60
|
+
"commander": "^12.1.0",
|
|
61
|
+
"fs-extra": "^11.2.0",
|
|
62
|
+
"glob": "^10.4.5",
|
|
63
|
+
"ora": "^8.1.0",
|
|
64
|
+
"postcss": "^8.4.47",
|
|
65
|
+
"prompts": "^2.4.2",
|
|
66
|
+
"zod": "^4.4.3"
|
|
67
|
+
},
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@types/babel__traverse": "^7.20.6",
|
|
70
|
+
"@types/fs-extra": "^11.0.4",
|
|
71
|
+
"@types/node": "^22.0.0",
|
|
72
|
+
"@types/prompts": "^2.4.9",
|
|
73
|
+
"tsx": "^4.16.0",
|
|
74
|
+
"typescript": "^5.5.4"
|
|
75
|
+
}
|
|
76
|
+
}
|