@bastani/atomic 0.9.0-alpha.3 → 0.9.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/CHANGELOG.md +48 -0
- package/dist/builtin/cursor/CHANGELOG.md +7 -0
- package/dist/builtin/cursor/package.json +2 -2
- package/dist/builtin/intercom/CHANGELOG.md +8 -0
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/CHANGELOG.md +12 -0
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +17 -0
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/CHANGELOG.md +8 -0
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +50 -0
- package/dist/builtin/workflows/README.md +12 -12
- package/dist/builtin/workflows/builtin/goal-prompts.ts +8 -0
- package/dist/builtin/workflows/builtin/goal-runner.ts +96 -1
- package/dist/builtin/workflows/builtin/goal-types.ts +2 -0
- package/dist/builtin/workflows/builtin/goal.d.ts +3 -0
- package/dist/builtin/workflows/builtin/goal.ts +12 -1
- package/dist/builtin/workflows/builtin/index.d.ts +8 -8
- package/dist/builtin/workflows/builtin/open-claude-design-feedback.ts +359 -0
- package/dist/builtin/workflows/builtin/open-claude-design-phases.ts +254 -352
- package/dist/builtin/workflows/builtin/open-claude-design-runner.ts +256 -414
- package/dist/builtin/workflows/builtin/open-claude-design-setup.ts +272 -0
- package/dist/builtin/workflows/builtin/open-claude-design-utils.ts +58 -68
- package/dist/builtin/workflows/builtin/open-claude-design.d.ts +5 -9
- package/dist/builtin/workflows/builtin/open-claude-design.ts +14 -26
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/skills/impeccable/SKILL.md +14 -23
- package/dist/builtin/workflows/skills/impeccable/reference/brand.md +2 -2
- package/dist/builtin/workflows/skills/impeccable/reference/live.md +25 -4
- package/dist/builtin/workflows/skills/impeccable/scripts/context-signals.mjs +1 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/context.mjs +724 -29
- package/dist/builtin/workflows/skills/impeccable/scripts/critique-storage.mjs +1 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/browser/injected/index.mjs +219 -7
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/cli/main.mjs +57 -11
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/design-system.mjs +750 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +648 -53
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/detect-antipatterns.mjs +7 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs +29 -4
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +44 -11
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +29 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs +27 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/node/file-system.mjs +1 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/registry/antipatterns.mjs +29 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/rules/checks.mjs +401 -46
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/inline-ignores.mjs +148 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/detector/shared/page.mjs +6 -6
- package/dist/builtin/workflows/skills/impeccable/scripts/{design-parser.mjs → lib/design-parser.mjs} +8 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/impeccable-config.mjs +638 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/impeccable-paths.mjs +128 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/{is-generated.mjs → lib/is-generated.mjs} +2 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/lib/target-args.mjs +42 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live/browser-script-parts.mjs +49 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/{live-completion.mjs → live/completion.mjs} +1 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/{live-event-validation.mjs → live/event-validation.mjs} +6 -5
- package/dist/builtin/workflows/skills/impeccable/scripts/live/manual-apply.mjs +939 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live/manual-edit-routes.mjs +357 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/{live-manual-edits-buffer.mjs → live/manual-edits-buffer.mjs} +1 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/{live-session-store.mjs → live/session-store.mjs} +21 -3
- package/dist/builtin/workflows/skills/impeccable/scripts/live/svelte-component.mjs +835 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live/sveltekit-adapter.mjs +274 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live/ui-core.mjs +180 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live/vocabulary.mjs +36 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-accept.mjs +185 -60
- package/dist/builtin/workflows/skills/impeccable/scripts/live-browser-dom.js +146 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-browser.js +3369 -1026
- package/dist/builtin/workflows/skills/impeccable/scripts/live-commit-manual-edits.mjs +2 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/live-complete.mjs +2 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/live-discard-manual-edits.mjs +1 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/live-inject.mjs +133 -9
- package/dist/builtin/workflows/skills/impeccable/scripts/live-insert.mjs +42 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/live-manual-edit-evidence.mjs +4 -4
- package/dist/builtin/workflows/skills/impeccable/scripts/live-poll.mjs +21 -15
- package/dist/builtin/workflows/skills/impeccable/scripts/live-resume.mjs +1 -1
- package/dist/builtin/workflows/skills/impeccable/scripts/live-server.mjs +205 -1269
- package/dist/builtin/workflows/skills/impeccable/scripts/live-status.mjs +2 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/live-target.mjs +30 -0
- package/dist/builtin/workflows/skills/impeccable/scripts/live-wrap.mjs +69 -26
- package/dist/builtin/workflows/skills/impeccable/scripts/live.mjs +73 -22
- package/dist/core/atomic-guide-command.d.ts.map +1 -1
- package/dist/core/atomic-guide-command.js +5 -5
- package/dist/core/atomic-guide-command.js.map +1 -1
- package/docs/index.md +2 -2
- package/docs/quickstart.md +9 -9
- package/docs/workflows.md +42 -23
- package/package.json +2 -2
- package/dist/builtin/workflows/skills/impeccable/scripts/cleanup-deprecated.mjs +0 -284
- package/dist/builtin/workflows/skills/impeccable/scripts/impeccable-paths.mjs +0 -126
- /package/dist/builtin/workflows/skills/impeccable/scripts/{live-insert-ui.mjs → live/insert-ui.mjs} +0 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inline, in-file ignore directives — eslint-disable-style waivers that live at
|
|
3
|
+
* the point they apply and travel with the artifact instead of (or alongside)
|
|
4
|
+
* an ignore in `.impeccable/config.json`.
|
|
5
|
+
*
|
|
6
|
+
* A config ignore is the right default for repo-wide policy. This complements it
|
|
7
|
+
* for the one case config can't cover: a waiver that belongs to a single file and
|
|
8
|
+
* needs to follow that file when it leaves the repo — a generated/exported
|
|
9
|
+
* standalone document, an emailed HTML file, a snippet scanned out of context.
|
|
10
|
+
*
|
|
11
|
+
* Comment-syntax-agnostic: the directive is a raw token matched anywhere on a
|
|
12
|
+
* line, so the same marker works across every comment style impeccable scans —
|
|
13
|
+
* `//`, `/* *\/`, `<!-- -->`, `#`, `{/* *\/}`, `{# #}`. Trailing comment closers
|
|
14
|
+
* are stripped before the rule list is parsed.
|
|
15
|
+
*
|
|
16
|
+
* Syntax (reason optional; eslint `--` or biome `:` separator):
|
|
17
|
+
*
|
|
18
|
+
* impeccable-disable <rule>[, <rule>...] [-- reason] whole file
|
|
19
|
+
* impeccable-disable-line <rule>... [-- reason] the same line
|
|
20
|
+
* impeccable-disable-next-line <rule>... [-- reason] the following line
|
|
21
|
+
* impeccable-disable bare / `*` = every rule
|
|
22
|
+
*
|
|
23
|
+
* Examples:
|
|
24
|
+
*
|
|
25
|
+
* <!-- impeccable-disable overused-font -- exported brand doc, font is first-party -->
|
|
26
|
+
* .brand { font-family: Inter; } /* impeccable-disable-line overused-font *\/
|
|
27
|
+
* // impeccable-disable-next-line bounce-easing: intentional playful affordance
|
|
28
|
+
*
|
|
29
|
+
* Behavior is suppression, for parity with config ignores: a matched directive
|
|
30
|
+
* drops the finding. The inline reason is self-documenting in the diff; it is not
|
|
31
|
+
* required and is discarded at scan time (only used here to keep reason words out
|
|
32
|
+
* of the parsed rule list).
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
const DIRECTIVE_RE = /impeccable-(disable-next-line|disable-line|disable)\b[ \t]*([^\n\r]*)/gi;
|
|
36
|
+
|
|
37
|
+
// Trailing comment closers, so `*/`, `*/}`, `-->`, `*}`, `#}`, `%>`, `}}` don't
|
|
38
|
+
// leak into the rule list. Anchored to end-of-line; the leading `\s*` mops up the
|
|
39
|
+
// space before the closer. `--+>` covers `-->` and any longer dash run.
|
|
40
|
+
const TRAILING_CLOSER_RE = /\s*(?:\*\/\}?|--+>|\*\}|#\}|%>|\}\})\s*$/;
|
|
41
|
+
|
|
42
|
+
function normalizeRule(token) {
|
|
43
|
+
return String(token || '').trim().toLowerCase();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Split the directive remainder into rule tokens, dropping any human reason that
|
|
47
|
+
// follows an eslint-style `--` or biome-style `:` separator. Rule ids only ever
|
|
48
|
+
// contain single hyphens (`overused-font`, `bounce-easing`), so `--` and `:`
|
|
49
|
+
// are unambiguous separators.
|
|
50
|
+
function parseRuleList(remainder) {
|
|
51
|
+
let text = String(remainder || '').replace(TRAILING_CLOSER_RE, '').trim();
|
|
52
|
+
// Cut off a human reason at the first `--` (eslint) or `:` (biome) separator.
|
|
53
|
+
const reasonSep = text.match(/\s*(?:--+|:)\s*/);
|
|
54
|
+
if (reasonSep) text = text.slice(0, reasonSep.index);
|
|
55
|
+
const tokens = text.split(/[\s,]+/).map(normalizeRule).filter(Boolean);
|
|
56
|
+
if (tokens.length === 0 || tokens.includes('*')) return ['*'];
|
|
57
|
+
return tokens;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function addRules(set, rules) {
|
|
61
|
+
for (const rule of rules) set.add(rule);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function getSet(map, key) {
|
|
65
|
+
let set = map.get(key);
|
|
66
|
+
if (!set) {
|
|
67
|
+
set = new Set();
|
|
68
|
+
map.set(key, set);
|
|
69
|
+
}
|
|
70
|
+
return set;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Parse every inline ignore directive in a file's raw text.
|
|
75
|
+
*
|
|
76
|
+
* Returns sets keyed by the 1-based line the directive *targets* so matching is a
|
|
77
|
+
* direct lookup:
|
|
78
|
+
* - file: rules disabled for the whole file
|
|
79
|
+
* - line: line -> rules disabled on that exact line (disable-line)
|
|
80
|
+
* - nextLine: line -> rules disabled on that line (disable-next-line on line-1)
|
|
81
|
+
*
|
|
82
|
+
* `*` in any set means "every rule".
|
|
83
|
+
*/
|
|
84
|
+
function parseInlineIgnores(content) {
|
|
85
|
+
const result = { file: new Set(), line: new Map(), nextLine: new Map() };
|
|
86
|
+
const text = typeof content === 'string' ? content : '';
|
|
87
|
+
// Cheap bail-out: the substring must be present for any directive to exist.
|
|
88
|
+
// Case-insensitive to match DIRECTIVE_RE's `i` flag (e.g. `Impeccable-Disable`).
|
|
89
|
+
if (!/impeccable-disable/i.test(text)) return result;
|
|
90
|
+
|
|
91
|
+
// Split on `\n` only, exactly as detectText numbers lines, so directive line
|
|
92
|
+
// keys line up with finding `line` values (incl. on `\r`-only line endings).
|
|
93
|
+
// The directive regex excludes `\r`, so a trailing `\r` on `\r\n` files is
|
|
94
|
+
// never captured into the rule list.
|
|
95
|
+
const lines = text.split('\n');
|
|
96
|
+
for (let i = 0; i < lines.length; i++) {
|
|
97
|
+
DIRECTIVE_RE.lastIndex = 0;
|
|
98
|
+
let m;
|
|
99
|
+
while ((m = DIRECTIVE_RE.exec(lines[i])) !== null) {
|
|
100
|
+
const variant = m[1].toLowerCase();
|
|
101
|
+
const rules = parseRuleList(m[2]);
|
|
102
|
+
if (variant === 'disable') {
|
|
103
|
+
addRules(result.file, rules);
|
|
104
|
+
} else if (variant === 'disable-line') {
|
|
105
|
+
addRules(getSet(result.line, i + 1), rules);
|
|
106
|
+
} else {
|
|
107
|
+
// disable-next-line on line i+1 targets line i+2.
|
|
108
|
+
addRules(getSet(result.nextLine, i + 2), rules);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function setMatches(set, rule) {
|
|
116
|
+
return Boolean(set) && (set.has('*') || set.has(rule));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function isInlineIgnored(finding, directives) {
|
|
120
|
+
const rule = normalizeRule(finding && finding.antipattern);
|
|
121
|
+
if (!rule) return false;
|
|
122
|
+
if (setMatches(directives.file, rule)) return true;
|
|
123
|
+
const line = Number(finding && finding.line) || 0;
|
|
124
|
+
if (line > 0) {
|
|
125
|
+
if (setMatches(directives.line.get(line), rule)) return true;
|
|
126
|
+
if (setMatches(directives.nextLine.get(line), rule)) return true;
|
|
127
|
+
}
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function hasDirectives(directives) {
|
|
132
|
+
return directives.file.size > 0 || directives.line.size > 0 || directives.nextLine.size > 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Drop findings waived by an inline directive in the same file's source text.
|
|
137
|
+
* Findings without a usable line number (e.g. static-HTML page-level findings)
|
|
138
|
+
* are only matched by whole-file directives — which is the standalone-document
|
|
139
|
+
* case this primitive exists for.
|
|
140
|
+
*/
|
|
141
|
+
function applyInlineIgnores(findings, content) {
|
|
142
|
+
if (!Array.isArray(findings) || findings.length === 0) return findings;
|
|
143
|
+
const directives = parseInlineIgnores(content);
|
|
144
|
+
if (!hasDirectives(directives)) return findings;
|
|
145
|
+
return findings.filter((finding) => !isInlineIgnored(finding, directives));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export { parseInlineIgnores, applyInlineIgnores, isInlineIgnored };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/** Check if content looks like a full page (not a component/partial) */
|
|
2
2
|
function isFullPage(content) {
|
|
3
|
-
// Strip comments
|
|
4
|
-
// survive a single pass (
|
|
5
|
-
let stripped = content;
|
|
6
|
-
let
|
|
3
|
+
// Strip comments to a fixpoint so nested/overlapping comment markers cannot
|
|
4
|
+
// survive a single pass (CodeQL: complete sanitization).
|
|
5
|
+
let stripped = String(content);
|
|
6
|
+
let prev;
|
|
7
7
|
do {
|
|
8
|
-
|
|
8
|
+
prev = stripped;
|
|
9
9
|
stripped = stripped.replace(/<!--[\s\S]*?-->/g, '');
|
|
10
|
-
} while (stripped !==
|
|
10
|
+
} while (stripped !== prev);
|
|
11
11
|
return /<!doctype\s|<html[\s>]|<head[\s>]/i.test(stripped);
|
|
12
12
|
}
|
|
13
13
|
|
package/dist/builtin/workflows/skills/impeccable/scripts/{design-parser.mjs → lib/design-parser.mjs}
RENAMED
|
@@ -62,7 +62,7 @@ function parseYamlSubset(yaml) {
|
|
|
62
62
|
stack.pop();
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
const key = content.slice(0, colonIdx).trim();
|
|
65
|
+
const key = unquoteYamlKey(content.slice(0, colonIdx).trim());
|
|
66
66
|
const rest = stripInlineYamlComment(content.slice(colonIdx + 1).trim());
|
|
67
67
|
const parent = stack[stack.length - 1].obj;
|
|
68
68
|
|
|
@@ -93,6 +93,13 @@ function findTopLevelColon(s) {
|
|
|
93
93
|
return -1;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
function unquoteYamlKey(key) {
|
|
97
|
+
if ((key.startsWith('"') && key.endsWith('"')) || (key.startsWith("'") && key.endsWith("'"))) {
|
|
98
|
+
return key.slice(1, -1);
|
|
99
|
+
}
|
|
100
|
+
return key;
|
|
101
|
+
}
|
|
102
|
+
|
|
96
103
|
function stripInlineYamlComment(s) {
|
|
97
104
|
let inQuote = null;
|
|
98
105
|
for (let i = 0; i < s.length; i++) {
|