dev-workflows 0.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/bin/devw.js +2 -0
- package/content/blocks/nextjs-approuter.yml +37 -0
- package/content/blocks/react-conventions.yml +36 -0
- package/content/blocks/supabase-rls.yml +30 -0
- package/content/blocks/tailwind.yml +28 -0
- package/content/blocks/testing-basics.yml +36 -0
- package/content/blocks/typescript-strict.yml +33 -0
- package/dist/blocks/installer.d.ts +4 -0
- package/dist/blocks/installer.d.ts.map +1 -0
- package/dist/blocks/installer.js +119 -0
- package/dist/blocks/installer.js.map +1 -0
- package/dist/blocks/registry.d.ts +18 -0
- package/dist/blocks/registry.d.ts.map +1 -0
- package/dist/blocks/registry.js +85 -0
- package/dist/blocks/registry.js.map +1 -0
- package/dist/bridges/claude.d.ts +3 -0
- package/dist/bridges/claude.d.ts.map +1 -0
- package/dist/bridges/claude.js +54 -0
- package/dist/bridges/claude.js.map +1 -0
- package/dist/bridges/cursor.d.ts +3 -0
- package/dist/bridges/cursor.d.ts.map +1 -0
- package/dist/bridges/cursor.js +61 -0
- package/dist/bridges/cursor.js.map +1 -0
- package/dist/bridges/gemini.d.ts +3 -0
- package/dist/bridges/gemini.d.ts.map +1 -0
- package/dist/bridges/gemini.js +54 -0
- package/dist/bridges/gemini.js.map +1 -0
- package/dist/bridges/types.d.ts +25 -0
- package/dist/bridges/types.d.ts.map +1 -0
- package/dist/bridges/types.js +2 -0
- package/dist/bridges/types.js.map +1 -0
- package/dist/commands/add.d.ts +7 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +64 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/compile.d.ts +9 -0
- package/dist/commands/compile.d.ts.map +1 -0
- package/dist/commands/compile.js +130 -0
- package/dist/commands/compile.js.map +1 -0
- package/dist/commands/doctor.d.ts +16 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +229 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +159 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +3 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +106 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/remove.d.ts +3 -0
- package/dist/commands/remove.d.ts.map +1 -0
- package/dist/commands/remove.js +40 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/core/hash.d.ts +5 -0
- package/dist/core/hash.d.ts.map +1 -0
- package/dist/core/hash.js +24 -0
- package/dist/core/hash.js.map +1 -0
- package/dist/core/markers.d.ts +4 -0
- package/dist/core/markers.d.ts.map +1 -0
- package/dist/core/markers.js +18 -0
- package/dist/core/markers.js.map +1 -0
- package/dist/core/parser.d.ts +4 -0
- package/dist/core/parser.d.ts.map +1 -0
- package/dist/core/parser.js +82 -0
- package/dist/core/parser.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/detect-tools.d.ts +8 -0
- package/dist/utils/detect-tools.d.ts.map +1 -0
- package/dist/utils/detect-tools.js +28 -0
- package/dist/utils/detect-tools.js.map +1 -0
- package/dist/utils/prompt.d.ts +3 -0
- package/dist/utils/prompt.d.ts.map +1 -0
- package/dist/utils/prompt.js +21 -0
- package/dist/utils/prompt.js.map +1 -0
- package/package.json +42 -0
package/bin/devw.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
id: nextjs-approuter
|
|
2
|
+
name: "Next.js App Router"
|
|
3
|
+
description: "App Router patterns, RSC, and server actions"
|
|
4
|
+
version: "0.1.0"
|
|
5
|
+
|
|
6
|
+
rules:
|
|
7
|
+
- id: nextjs-use-client-minimal
|
|
8
|
+
scope: architecture
|
|
9
|
+
severity: error
|
|
10
|
+
content: |
|
|
11
|
+
Minimize "use client" directives. Default to Server Components.
|
|
12
|
+
Only add "use client" when the component needs browser APIs,
|
|
13
|
+
event handlers, or React hooks that require client state.
|
|
14
|
+
|
|
15
|
+
- id: nextjs-server-actions
|
|
16
|
+
scope: architecture
|
|
17
|
+
severity: warning
|
|
18
|
+
content: |
|
|
19
|
+
Prefer server actions for form submissions and data mutations.
|
|
20
|
+
Define them with "use server" in a separate file or at the
|
|
21
|
+
top of an async function.
|
|
22
|
+
|
|
23
|
+
- id: nextjs-route-segments
|
|
24
|
+
scope: architecture
|
|
25
|
+
severity: error
|
|
26
|
+
content: |
|
|
27
|
+
Follow the App Router file conventions: page.tsx, layout.tsx,
|
|
28
|
+
loading.tsx, error.tsx, not-found.tsx. Do not create custom
|
|
29
|
+
routing abstractions.
|
|
30
|
+
|
|
31
|
+
- id: nextjs-no-client-fetch
|
|
32
|
+
scope: architecture
|
|
33
|
+
severity: warning
|
|
34
|
+
content: |
|
|
35
|
+
Fetch data in Server Components or server actions, not in
|
|
36
|
+
client components with useEffect. Use React Suspense for
|
|
37
|
+
loading states.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
id: react-conventions
|
|
2
|
+
name: "React Conventions"
|
|
3
|
+
description: "Hooks rules, component patterns, and naming conventions"
|
|
4
|
+
version: "0.1.0"
|
|
5
|
+
|
|
6
|
+
rules:
|
|
7
|
+
- id: react-hooks-rules
|
|
8
|
+
scope: conventions
|
|
9
|
+
severity: error
|
|
10
|
+
content: |
|
|
11
|
+
Follow the Rules of Hooks: only call hooks at the top level,
|
|
12
|
+
never inside conditions or loops. Custom hooks must start
|
|
13
|
+
with "use".
|
|
14
|
+
|
|
15
|
+
- id: react-component-naming
|
|
16
|
+
scope: conventions
|
|
17
|
+
severity: error
|
|
18
|
+
content: |
|
|
19
|
+
Use PascalCase for component names and their files.
|
|
20
|
+
Use camelCase for hook files prefixed with "use"
|
|
21
|
+
(e.g. useAuth.ts).
|
|
22
|
+
|
|
23
|
+
- id: react-prefer-composition
|
|
24
|
+
scope: conventions
|
|
25
|
+
severity: warning
|
|
26
|
+
content: |
|
|
27
|
+
Prefer composition over prop drilling. Use children,
|
|
28
|
+
render props, or context for shared behavior rather than
|
|
29
|
+
deeply nested prop chains.
|
|
30
|
+
|
|
31
|
+
- id: react-no-inline-styles
|
|
32
|
+
scope: conventions
|
|
33
|
+
severity: warning
|
|
34
|
+
content: |
|
|
35
|
+
Avoid inline styles. Use CSS modules, Tailwind classes,
|
|
36
|
+
or styled-components for styling.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
id: supabase-rls
|
|
2
|
+
name: "Supabase RLS"
|
|
3
|
+
description: "Row-Level Security enforcement and auth patterns"
|
|
4
|
+
version: "0.1.0"
|
|
5
|
+
|
|
6
|
+
rules:
|
|
7
|
+
- id: supabase-rls-required
|
|
8
|
+
scope: security
|
|
9
|
+
severity: error
|
|
10
|
+
content: |
|
|
11
|
+
Every new table must have RLS policies before merging.
|
|
12
|
+
Enable RLS with ALTER TABLE ... ENABLE ROW LEVEL SECURITY
|
|
13
|
+
and create at least one policy per operation (SELECT, INSERT,
|
|
14
|
+
UPDATE, DELETE) as needed.
|
|
15
|
+
|
|
16
|
+
- id: supabase-auth-context
|
|
17
|
+
scope: security
|
|
18
|
+
severity: error
|
|
19
|
+
content: |
|
|
20
|
+
Always use auth.uid() in RLS policies to scope data to
|
|
21
|
+
the authenticated user. Never rely on client-provided
|
|
22
|
+
user IDs in queries.
|
|
23
|
+
|
|
24
|
+
- id: supabase-no-service-role-client
|
|
25
|
+
scope: security
|
|
26
|
+
severity: error
|
|
27
|
+
content: |
|
|
28
|
+
Never expose the service_role key to the client.
|
|
29
|
+
Use the anon key in browser code and the service_role key
|
|
30
|
+
only in server-side or admin contexts.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
id: tailwind
|
|
2
|
+
name: "Tailwind CSS"
|
|
3
|
+
description: "Utility-first CSS conventions and design tokens"
|
|
4
|
+
version: "0.1.0"
|
|
5
|
+
|
|
6
|
+
rules:
|
|
7
|
+
- id: tailwind-utility-first
|
|
8
|
+
scope: conventions
|
|
9
|
+
severity: error
|
|
10
|
+
content: |
|
|
11
|
+
Use Tailwind utility classes for all styling. Do not write
|
|
12
|
+
custom CSS unless absolutely necessary (e.g. complex
|
|
13
|
+
animations or third-party overrides).
|
|
14
|
+
|
|
15
|
+
- id: tailwind-design-tokens
|
|
16
|
+
scope: conventions
|
|
17
|
+
severity: warning
|
|
18
|
+
content: |
|
|
19
|
+
Use Tailwind's design tokens (spacing, colors, typography)
|
|
20
|
+
from the theme config. Avoid arbitrary values like
|
|
21
|
+
w-[137px]; prefer the closest token.
|
|
22
|
+
|
|
23
|
+
- id: tailwind-no-apply
|
|
24
|
+
scope: conventions
|
|
25
|
+
severity: warning
|
|
26
|
+
content: |
|
|
27
|
+
Avoid @apply in CSS files. Extract reusable patterns into
|
|
28
|
+
React components instead of creating CSS abstractions.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
id: testing-basics
|
|
2
|
+
name: "Testing Basics"
|
|
3
|
+
description: "Test naming, coverage expectations, and mock patterns"
|
|
4
|
+
version: "0.1.0"
|
|
5
|
+
|
|
6
|
+
rules:
|
|
7
|
+
- id: testing-descriptive-names
|
|
8
|
+
scope: testing
|
|
9
|
+
severity: error
|
|
10
|
+
content: |
|
|
11
|
+
Use descriptive test names that explain the expected behavior.
|
|
12
|
+
Follow the pattern: "should [expected behavior] when [condition]".
|
|
13
|
+
|
|
14
|
+
- id: testing-arrange-act-assert
|
|
15
|
+
scope: testing
|
|
16
|
+
severity: warning
|
|
17
|
+
content: |
|
|
18
|
+
Structure tests with Arrange-Act-Assert (AAA) pattern.
|
|
19
|
+
Separate setup, execution, and verification into distinct
|
|
20
|
+
sections for readability.
|
|
21
|
+
|
|
22
|
+
- id: testing-no-implementation-details
|
|
23
|
+
scope: testing
|
|
24
|
+
severity: warning
|
|
25
|
+
content: |
|
|
26
|
+
Test behavior, not implementation details. Avoid asserting
|
|
27
|
+
on internal state, private methods, or specific function calls
|
|
28
|
+
unless testing integration points.
|
|
29
|
+
|
|
30
|
+
- id: testing-mock-boundaries
|
|
31
|
+
scope: testing
|
|
32
|
+
severity: warning
|
|
33
|
+
content: |
|
|
34
|
+
Only mock at system boundaries: network requests, databases,
|
|
35
|
+
file system, and third-party services. Do not mock internal
|
|
36
|
+
modules or utility functions.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
id: typescript-strict
|
|
2
|
+
name: "TypeScript Strict"
|
|
3
|
+
description: "Strict TypeScript conventions for professional codebases"
|
|
4
|
+
version: "0.1.0"
|
|
5
|
+
|
|
6
|
+
rules:
|
|
7
|
+
- id: ts-strict-no-any
|
|
8
|
+
scope: conventions
|
|
9
|
+
severity: error
|
|
10
|
+
content: |
|
|
11
|
+
Never use `any`. Use `unknown` when the type is truly unknown,
|
|
12
|
+
then narrow with type guards.
|
|
13
|
+
|
|
14
|
+
- id: ts-strict-explicit-returns
|
|
15
|
+
scope: conventions
|
|
16
|
+
severity: warning
|
|
17
|
+
content: |
|
|
18
|
+
Always declare explicit return types on exported functions.
|
|
19
|
+
Inferred types are fine for internal/private functions.
|
|
20
|
+
|
|
21
|
+
- id: ts-strict-no-enums
|
|
22
|
+
scope: conventions
|
|
23
|
+
severity: warning
|
|
24
|
+
content: |
|
|
25
|
+
Prefer union types over enums.
|
|
26
|
+
Use `as const` objects when you need runtime values.
|
|
27
|
+
|
|
28
|
+
- id: ts-strict-no-non-null-assertion
|
|
29
|
+
scope: conventions
|
|
30
|
+
severity: error
|
|
31
|
+
content: |
|
|
32
|
+
Never use non-null assertion (!). Handle null/undefined explicitly
|
|
33
|
+
with optional chaining, nullish coalescing, or type guards.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { BlockDefinition } from './registry.js';
|
|
2
|
+
export declare function installBlock(cwd: string, block: BlockDefinition): Promise<number>;
|
|
3
|
+
export declare function uninstallBlock(cwd: string, blockId: string): Promise<number>;
|
|
4
|
+
//# sourceMappingURL=installer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/blocks/installer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAmCrD,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CA8CvF;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgClF"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { parse, stringify } from 'yaml';
|
|
4
|
+
async function readRuleFile(filePath) {
|
|
5
|
+
try {
|
|
6
|
+
const raw = await readFile(filePath, 'utf-8');
|
|
7
|
+
const parsed = parse(raw);
|
|
8
|
+
if (!parsed || typeof parsed !== 'object')
|
|
9
|
+
return null;
|
|
10
|
+
const doc = parsed;
|
|
11
|
+
return {
|
|
12
|
+
scope: typeof doc['scope'] === 'string' ? doc['scope'] : '',
|
|
13
|
+
rules: Array.isArray(doc['rules']) ? doc['rules'] : [],
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function writeRuleFile(doc) {
|
|
21
|
+
return stringify(doc, { lineWidth: 0 });
|
|
22
|
+
}
|
|
23
|
+
export async function installBlock(cwd, block) {
|
|
24
|
+
const rulesDir = join(cwd, '.dwf', 'rules');
|
|
25
|
+
await mkdir(rulesDir, { recursive: true });
|
|
26
|
+
// Group block rules by scope
|
|
27
|
+
const byScope = new Map();
|
|
28
|
+
for (const rule of block.rules) {
|
|
29
|
+
const existing = byScope.get(rule.scope);
|
|
30
|
+
if (existing) {
|
|
31
|
+
existing.push(rule);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
byScope.set(rule.scope, [rule]);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
let rulesAdded = 0;
|
|
38
|
+
for (const [scope, blockRules] of byScope) {
|
|
39
|
+
const filePath = join(rulesDir, `${scope}.yml`);
|
|
40
|
+
let doc = await readRuleFile(filePath);
|
|
41
|
+
if (!doc) {
|
|
42
|
+
doc = { scope, rules: [] };
|
|
43
|
+
}
|
|
44
|
+
// Remove any existing rules from this block to avoid duplicates on re-add
|
|
45
|
+
doc.rules = doc.rules.filter((r) => r.sourceBlock !== block.id);
|
|
46
|
+
// Append new rules
|
|
47
|
+
for (const rule of blockRules) {
|
|
48
|
+
doc.rules.push({
|
|
49
|
+
id: rule.id,
|
|
50
|
+
severity: rule.severity,
|
|
51
|
+
content: rule.content,
|
|
52
|
+
sourceBlock: block.id,
|
|
53
|
+
});
|
|
54
|
+
rulesAdded++;
|
|
55
|
+
}
|
|
56
|
+
await writeFile(filePath, writeRuleFile(doc), 'utf-8');
|
|
57
|
+
}
|
|
58
|
+
// Update config.yml blocks array
|
|
59
|
+
await addBlockToConfig(cwd, block.id);
|
|
60
|
+
return rulesAdded;
|
|
61
|
+
}
|
|
62
|
+
export async function uninstallBlock(cwd, blockId) {
|
|
63
|
+
const rulesDir = join(cwd, '.dwf', 'rules');
|
|
64
|
+
let entries;
|
|
65
|
+
try {
|
|
66
|
+
const { readdir } = await import('node:fs/promises');
|
|
67
|
+
entries = await readdir(rulesDir);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
const ymlFiles = entries.filter((f) => f.endsWith('.yml') || f.endsWith('.yaml'));
|
|
73
|
+
let rulesRemoved = 0;
|
|
74
|
+
for (const file of ymlFiles) {
|
|
75
|
+
const filePath = join(rulesDir, file);
|
|
76
|
+
const doc = await readRuleFile(filePath);
|
|
77
|
+
if (!doc)
|
|
78
|
+
continue;
|
|
79
|
+
const before = doc.rules.length;
|
|
80
|
+
doc.rules = doc.rules.filter((r) => r.sourceBlock !== blockId);
|
|
81
|
+
const removed = before - doc.rules.length;
|
|
82
|
+
if (removed > 0) {
|
|
83
|
+
rulesRemoved += removed;
|
|
84
|
+
await writeFile(filePath, writeRuleFile(doc), 'utf-8');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Update config.yml blocks array
|
|
88
|
+
await removeBlockFromConfig(cwd, blockId);
|
|
89
|
+
return rulesRemoved;
|
|
90
|
+
}
|
|
91
|
+
async function readRawConfig(cwd) {
|
|
92
|
+
const configPath = join(cwd, '.dwf', 'config.yml');
|
|
93
|
+
const raw = await readFile(configPath, 'utf-8');
|
|
94
|
+
const parsed = parse(raw);
|
|
95
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
96
|
+
throw new Error('Invalid config.yml');
|
|
97
|
+
}
|
|
98
|
+
return parsed;
|
|
99
|
+
}
|
|
100
|
+
async function writeRawConfig(cwd, doc) {
|
|
101
|
+
const configPath = join(cwd, '.dwf', 'config.yml');
|
|
102
|
+
await writeFile(configPath, stringify(doc, { lineWidth: 0 }), 'utf-8');
|
|
103
|
+
}
|
|
104
|
+
async function addBlockToConfig(cwd, blockId) {
|
|
105
|
+
const doc = await readRawConfig(cwd);
|
|
106
|
+
const blocks = Array.isArray(doc['blocks']) ? doc['blocks'] : [];
|
|
107
|
+
if (!blocks.includes(blockId)) {
|
|
108
|
+
blocks.push(blockId);
|
|
109
|
+
}
|
|
110
|
+
doc['blocks'] = blocks;
|
|
111
|
+
await writeRawConfig(cwd, doc);
|
|
112
|
+
}
|
|
113
|
+
async function removeBlockFromConfig(cwd, blockId) {
|
|
114
|
+
const doc = await readRawConfig(cwd);
|
|
115
|
+
const blocks = Array.isArray(doc['blocks']) ? doc['blocks'] : [];
|
|
116
|
+
doc['blocks'] = blocks.filter((b) => b !== blockId);
|
|
117
|
+
await writeRawConfig(cwd, doc);
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installer.js","sourceRoot":"","sources":["../../src/blocks/installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Rule } from '../bridges/types.js';
|
|
2
|
+
export interface BlockDefinition {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
version: string;
|
|
7
|
+
rules: BlockRule[];
|
|
8
|
+
}
|
|
9
|
+
export interface BlockRule {
|
|
10
|
+
id: string;
|
|
11
|
+
scope: string;
|
|
12
|
+
severity: 'error' | 'warning' | 'info';
|
|
13
|
+
content: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function loadAllBlocks(blocksDir?: string): Promise<BlockDefinition[]>;
|
|
16
|
+
export declare function loadBlock(blockId: string, blocksDir?: string): Promise<BlockDefinition | null>;
|
|
17
|
+
export declare function blockRulesToRules(block: BlockDefinition): Rule[];
|
|
18
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/blocks/registry.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,SAAS,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACvC,OAAO,EAAE,MAAM,CAAC;CACjB;AAuDD,wBAAsB,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAuBlF;AAED,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAGpG;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,EAAE,CAShE"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { readFile, readdir } from 'node:fs/promises';
|
|
2
|
+
import { join, dirname } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { parse } from 'yaml';
|
|
5
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
function defaultBlocksDir() {
|
|
7
|
+
// From dist/blocks/ → packages/cli/ (2 up), then content/blocks
|
|
8
|
+
return join(__dirname, '..', '..', 'content', 'blocks');
|
|
9
|
+
}
|
|
10
|
+
function normalizeBlockRule(raw) {
|
|
11
|
+
if (!raw.id || !raw.scope || !raw.content)
|
|
12
|
+
return null;
|
|
13
|
+
const severity = raw.severity ?? 'error';
|
|
14
|
+
if (severity !== 'error' && severity !== 'warning' && severity !== 'info')
|
|
15
|
+
return null;
|
|
16
|
+
return {
|
|
17
|
+
id: raw.id,
|
|
18
|
+
scope: raw.scope,
|
|
19
|
+
severity,
|
|
20
|
+
content: raw.content.trimEnd(),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function parseBlock(raw) {
|
|
24
|
+
const parsed = parse(raw);
|
|
25
|
+
if (!parsed || typeof parsed !== 'object')
|
|
26
|
+
return null;
|
|
27
|
+
const doc = parsed;
|
|
28
|
+
const id = typeof doc['id'] === 'string' ? doc['id'] : null;
|
|
29
|
+
const name = typeof doc['name'] === 'string' ? doc['name'] : null;
|
|
30
|
+
const description = typeof doc['description'] === 'string' ? doc['description'] : '';
|
|
31
|
+
const version = typeof doc['version'] === 'string' ? doc['version'] : '0.1.0';
|
|
32
|
+
if (!id || !name)
|
|
33
|
+
return null;
|
|
34
|
+
const rulesRaw = doc['rules'];
|
|
35
|
+
if (!Array.isArray(rulesRaw))
|
|
36
|
+
return null;
|
|
37
|
+
const rules = [];
|
|
38
|
+
for (const rawRule of rulesRaw) {
|
|
39
|
+
if (!rawRule || typeof rawRule !== 'object')
|
|
40
|
+
continue;
|
|
41
|
+
const rule = normalizeBlockRule(rawRule);
|
|
42
|
+
if (rule)
|
|
43
|
+
rules.push(rule);
|
|
44
|
+
}
|
|
45
|
+
return { id, name, description, version, rules };
|
|
46
|
+
}
|
|
47
|
+
export async function loadAllBlocks(blocksDir) {
|
|
48
|
+
const dir = blocksDir ?? defaultBlocksDir();
|
|
49
|
+
let entries;
|
|
50
|
+
try {
|
|
51
|
+
entries = await readdir(dir);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
const ymlFiles = entries.filter((f) => f.endsWith('.yml') || f.endsWith('.yaml'));
|
|
57
|
+
const blocks = [];
|
|
58
|
+
for (const file of ymlFiles) {
|
|
59
|
+
try {
|
|
60
|
+
const raw = await readFile(join(dir, file), 'utf-8');
|
|
61
|
+
const block = parseBlock(raw);
|
|
62
|
+
if (block)
|
|
63
|
+
blocks.push(block);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// Skip files that can't be read or parsed
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return blocks;
|
|
70
|
+
}
|
|
71
|
+
export async function loadBlock(blockId, blocksDir) {
|
|
72
|
+
const all = await loadAllBlocks(blocksDir);
|
|
73
|
+
return all.find((b) => b.id === blockId) ?? null;
|
|
74
|
+
}
|
|
75
|
+
export function blockRulesToRules(block) {
|
|
76
|
+
return block.rules.map((r) => ({
|
|
77
|
+
id: r.id,
|
|
78
|
+
scope: r.scope,
|
|
79
|
+
severity: r.severity,
|
|
80
|
+
content: r.content,
|
|
81
|
+
enabled: true,
|
|
82
|
+
sourceBlock: block.id,
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/blocks/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/bridges/claude.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAuB,MAAM,YAAY,CAAC;AAoD9D,eAAO,MAAM,YAAY,EAAE,MAS1B,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
function filterRules(rules) {
|
|
2
|
+
return rules.filter((r) => r.enabled && r.severity !== 'info');
|
|
3
|
+
}
|
|
4
|
+
function groupByScope(rules) {
|
|
5
|
+
const groups = new Map();
|
|
6
|
+
for (const rule of rules) {
|
|
7
|
+
const existing = groups.get(rule.scope);
|
|
8
|
+
if (existing) {
|
|
9
|
+
existing.push(rule);
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
groups.set(rule.scope, [rule]);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return groups;
|
|
16
|
+
}
|
|
17
|
+
function capitalize(s) {
|
|
18
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
19
|
+
}
|
|
20
|
+
function buildMarkdown(rules) {
|
|
21
|
+
const lines = [
|
|
22
|
+
'# Project Rules',
|
|
23
|
+
];
|
|
24
|
+
const filtered = filterRules(rules);
|
|
25
|
+
const grouped = groupByScope(filtered);
|
|
26
|
+
for (const [scope, scopeRules] of grouped) {
|
|
27
|
+
lines.push('', `## ${capitalize(scope)}`);
|
|
28
|
+
for (const rule of scopeRules) {
|
|
29
|
+
const contentLines = rule.content.split('\n');
|
|
30
|
+
const first = contentLines[0];
|
|
31
|
+
if (first !== undefined) {
|
|
32
|
+
lines.push('', `- ${first}`);
|
|
33
|
+
}
|
|
34
|
+
for (let i = 1; i < contentLines.length; i++) {
|
|
35
|
+
const line = contentLines[i];
|
|
36
|
+
if (line !== undefined) {
|
|
37
|
+
lines.push(` ${line}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
lines.push('');
|
|
43
|
+
return lines.join('\n');
|
|
44
|
+
}
|
|
45
|
+
export const claudeBridge = {
|
|
46
|
+
id: 'claude',
|
|
47
|
+
outputPaths: ['CLAUDE.md'],
|
|
48
|
+
compile(rules, _config) {
|
|
49
|
+
const output = new Map();
|
|
50
|
+
output.set('CLAUDE.md', buildMarkdown(rules));
|
|
51
|
+
return output;
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/bridges/claude.ts"],"names":[],"mappings":"AAEA,SAAS,WAAW,CAAC,KAAa;IAChC,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAClC,MAAM,KAAK,GAAa;QACtB,iBAAiB;KAClB,CAAC;IAEF,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAEvC,KAAK,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,OAAO,EAAE,CAAC;QAC1C,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1C,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;YAC9B,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC9C,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,KAAK,EAAE,CAAC,CAAC;YAC/B,CAAC;YACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7C,MAAM,IAAI,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;gBAC7B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;oBACvB,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAW;IAClC,EAAE,EAAE,QAAQ;IACZ,WAAW,EAAE,CAAC,WAAW,CAAC;IAE1B,OAAO,CAAC,KAAa,EAAE,OAAsB;QAC3C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9C,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/bridges/cursor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAuB,MAAM,YAAY,CAAC;AA4D9D,eAAO,MAAM,YAAY,EAAE,MAS1B,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
function filterRules(rules) {
|
|
2
|
+
return rules.filter((r) => r.enabled && r.severity !== 'info');
|
|
3
|
+
}
|
|
4
|
+
function groupByScope(rules) {
|
|
5
|
+
const groups = new Map();
|
|
6
|
+
for (const rule of rules) {
|
|
7
|
+
const existing = groups.get(rule.scope);
|
|
8
|
+
if (existing) {
|
|
9
|
+
existing.push(rule);
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
groups.set(rule.scope, [rule]);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return groups;
|
|
16
|
+
}
|
|
17
|
+
function capitalize(s) {
|
|
18
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
19
|
+
}
|
|
20
|
+
const FRONTMATTER = `---
|
|
21
|
+
description: Project rules generated by dev-workflows
|
|
22
|
+
globs:
|
|
23
|
+
alwaysApply: true
|
|
24
|
+
---`;
|
|
25
|
+
function buildMdc(rules) {
|
|
26
|
+
const lines = [
|
|
27
|
+
FRONTMATTER,
|
|
28
|
+
'',
|
|
29
|
+
'<!-- Generated by dev-workflows. Do not edit manually. -->',
|
|
30
|
+
];
|
|
31
|
+
const filtered = filterRules(rules);
|
|
32
|
+
const grouped = groupByScope(filtered);
|
|
33
|
+
for (const [scope, scopeRules] of grouped) {
|
|
34
|
+
lines.push('', `## ${capitalize(scope)}`);
|
|
35
|
+
for (const rule of scopeRules) {
|
|
36
|
+
const contentLines = rule.content.split('\n');
|
|
37
|
+
const first = contentLines[0];
|
|
38
|
+
if (first !== undefined) {
|
|
39
|
+
lines.push('', `- ${first}`);
|
|
40
|
+
}
|
|
41
|
+
for (let i = 1; i < contentLines.length; i++) {
|
|
42
|
+
const line = contentLines[i];
|
|
43
|
+
if (line !== undefined) {
|
|
44
|
+
lines.push(` ${line}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
lines.push('');
|
|
50
|
+
return lines.join('\n');
|
|
51
|
+
}
|
|
52
|
+
export const cursorBridge = {
|
|
53
|
+
id: 'cursor',
|
|
54
|
+
outputPaths: ['.cursor/rules/devworkflows.mdc'],
|
|
55
|
+
compile(rules, _config) {
|
|
56
|
+
const output = new Map();
|
|
57
|
+
output.set('.cursor/rules/devworkflows.mdc', buildMdc(rules));
|
|
58
|
+
return output;
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=cursor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/bridges/cursor.ts"],"names":[],"mappings":"AAEA,SAAS,WAAW,CAAC,KAAa;IAChC,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,WAAW,GAAG;;;;IAIhB,CAAC;AAEL,SAAS,QAAQ,CAAC,KAAa;IAC7B,MAAM,KAAK,GAAa;QACtB,WAAW;QACX,EAAE;QACF,4DAA4D;KAC7D,CAAC;IAEF,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAEvC,KAAK,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,OAAO,EAAE,CAAC;QAC1C,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,MAAM,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1C,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;YAC9B,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC9C,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,KAAK,EAAE,CAAC,CAAC;YAC/B,CAAC;YACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7C,MAAM,IAAI,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;gBAC7B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;oBACvB,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAW;IAClC,EAAE,EAAE,QAAQ;IACZ,WAAW,EAAE,CAAC,gCAAgC,CAAC;IAE/C,OAAO,CAAC,KAAa,EAAE,OAAsB;QAC3C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,MAAM,CAAC,GAAG,CAAC,gCAAgC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9D,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/bridges/gemini.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAuB,MAAM,YAAY,CAAC;AAoD9D,eAAO,MAAM,YAAY,EAAE,MAS1B,CAAC"}
|