Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7589959
refactor(generators): use file processor chain pattern for dogfooding
deepracticexs Oct 10, 2025
363ded6
refactor: implement file processor chain and mirror-based template sy…
deepracticexs Oct 10, 2025
fa02a43
feat(configurer): unify config naming to 'base' and create vitest-cuc…
deepracticexs Oct 10, 2025
4b29f58
refactor: migrate all configs to unified @deepracticex/configurer
deepracticexs Oct 10, 2025
8c9b765
chore: ignore tsup bundled config cache files
deepracticexs Oct 10, 2025
c344c9c
chore: remove obsolete cucumber.cjs config files
deepracticexs Oct 10, 2025
002325e
fix: allow vitest-cucumber tests to pass with no test files
deepracticexs Oct 10, 2025
4c6df94
feat(vitest-cucumber): implement plugin architecture with core features
deepracticexs Oct 11, 2025
08bdc04
feat(vitest-cucumber): add advanced Gherkin features support
deepracticexs Oct 11, 2025
04f0f94
feat: implement native Cucumber features for vitest-cucumber
deepracticexs Oct 11, 2025
d1c91b5
fix: resolve GherkinParser state pollution and vitest-cucumber depend…
deepracticexs Oct 11, 2025
5cbbf1b
refactor: Remove vitest-cucumber package - migrated to EnhancedVitest
deepracticexs Oct 11, 2025
ca372c8
refactor(configurer): improve Cucumber exports and fix version conflicts
deepracticexs Oct 11, 2025
e2185ed
fix(error-handling): update Cucumber imports to use /cucumber subpath
deepracticexs Oct 11, 2025
3dee66b
fix(example-package): update Cucumber imports to use /cucumber subpath
deepracticexs Oct 11, 2025
6539e76
fix(error-handling): fix hook type errors in Cucumber hooks
deepracticexs Oct 11, 2025
6a78632
refactor: split configurer into config-preset and testing-utils packages
deepracticexs Oct 11, 2025
562cd68
refactor: migrate packages to vitest-cucumber and standardize config
deepracticexs Oct 11, 2025
9e05ff7
chore: Bump version to 2025.10.12 in package.json
deepracticexs Oct 12, 2025
cce2602
fix(logger): disable worker threads in test environment
deepracticexs Oct 12, 2025
d9d8489
feat(logger): add platform-specific entry points for cross-platform s…
deepracticexs Oct 12, 2025
63a0e31
fix(logger): correct Logger type import path
deepracticexs Oct 12, 2025
715d85e
docs(logger): update README for 1.0 release with platform-specific en…
deepracticexs Oct 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ coverage/
.eslintcache
.turbo/

# Tsup bundled configs
*.bundled_*.mjs

# Lefthook
lefthook-local.yml

Expand All @@ -48,3 +51,4 @@ lefthook-local.yml

# Test reports
**/reports/
../../temp/
245 changes: 245 additions & 0 deletions .promptx/pouch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
{
"currentState": "initial",
"stateHistory": [
{
"from": "initial",
"command": "action",
"timestamp": "2025-10-11T09:34:06.196Z",
"args": ["sean"]
},
{
"from": "initial",
"command": "discover",
"timestamp": "2025-10-11T10:55:40.594Z",
"args": []
},
{
"from": "initial",
"command": "action",
"timestamp": "2025-10-11T10:55:44.612Z",
"args": ["sean"]
},
{
"from": "initial",
"command": "action",
"timestamp": "2025-10-11T13:07:00.161Z",
"args": ["sean"]
},
{
"from": "initial",
"command": "project",
"timestamp": "2025-10-11T13:07:20.826Z",
"args": [
{
"workingDirectory": "/Users/sean/Deepractice/projects/NodeSpec",
"ideType": "claude"
}
]
},
{
"from": "initial",
"command": "recall",
"timestamp": "2025-10-11T13:13:29.153Z",
"args": [
{
"role": "sean",
"query": "矛盾论 决策",
"mode": "focused"
}
]
},
{
"from": "initial",
"command": "remember",
"timestamp": "2025-10-11T13:21:59.642Z",
"args": [
{
"role": "sean",
"engrams": [
{
"content": "NodeSpec eslint-config 包实现了 defaultSeverity 支持,规则可以在 .rule.md 中声明默认严格度(error/warn/off),未声明则默认 error。no-interface-prefix 规则改为 warn,因为接口重命名是重构操作不适合 autoFix。测试步骤自动使用规则的 defaultSeverity。",
"schema": "NodeSpec - eslint-config - defaultSeverity - warn - autoFix",
"strength": 0.8,
"type": "ATOMIC"
},
{
"content": "no-interface-prefix 规则的检测逻辑经过优化,避免误判正常 I 开头单词(Image、Icon)和缩写词(IO、IPC、IPv4)。判断条件:I + 大写 + 小写字母(ILogger),排除 I + 小写(Image)和版本号模式(IPv4)。正则 /^[A-Z][a-z]?[0-9]/ 排除缩写+版本号。",
"schema": "no-interface-prefix - 边界情况 - 正则表达式 - IPv4 - Image",
"strength": 0.7,
"type": "PATTERN"
},
{
"content": "ESLint 规则测试失败的根因是缺少 @typescript-eslint/parser 配置。TypeScript AST 节点(TSInterfaceDeclaration)需要 TypeScript parser 才能解析,测试步骤中添加 languageOptions.parser: tsParser 解决。",
"schema": "ESLint - TypeScript - parser - TSInterfaceDeclaration - 测试",
"strength": 0.7,
"type": "LINK"
}
]
}
]
},
{
"from": "initial",
"command": "recall",
"timestamp": "2025-10-11T13:22:21.698Z",
"args": [
{
"role": "sean",
"query": "Java 规范 标准",
"mode": "balanced"
}
]
},
{
"from": "initial",
"command": "remember",
"timestamp": "2025-10-11T13:40:24.436Z",
"args": [
{
"role": "sean",
"engrams": [
{
"content": "ESLint 规则设计采用 Wrapper 模式:复用 @typescript-eslint 的检测逻辑,但用自己的 .rule.md 提供 AI-friendly 文档。优势是不重复造轮子,同时保持统一的错误信息格式和 defaultSeverity 控制。wrapRule 函数封装外部规则,加载自定义文档,统一错误信息体验。",
"schema": "ESLint - Wrapper模式 - AI-friendly - rule.md - 复用",
"strength": 0.9,
"type": "PATTERN"
},
{
"content": "AI-first 代码规范的核心原则:单一标准无备选方案(deterministic rules)、利用 AI 预训练知识(TypeScript 生态最大公约数)、短提示词即可生效(ESLint 自动检查)。遵循 AI 肌肉记忆:PascalCase for types、camelCase for variables、kebab-case for files、无匈牙利前缀。目标是让 AI 一句话 'Follow @deepracticex/eslint-config' 就能理解所有规范。",
"schema": "AI-first - 代码规范 - 单一标准 - 预训练知识 - ESLint - 肌肉记忆",
"strength": 0.9,
"type": "ATOMIC"
},
{
"content": "BDD 开发流程:先写 feature 测试场景,再实现规则(Feature First 原则)。Phase 1 核心规则包含 naming(no-type-prefix、class-pascal-case、variable-camel-case)、file-naming(kebab-case-files、file-suffix-convention)、structure(no-core-in-api、no-implementation-in-types)、imports(use-tilde-alias、no-relative-parent)。规则优先级基于影响:error 破坏架构、warn 风格不一致、off 极致规范。",
"schema": "BDD - Feature First - Phase 1 - 规则分类 - 优先级 - defaultSeverity",
"strength": 0.8,
"type": "PATTERN"
}
]
}
]
},
{
"from": "initial",
"command": "action",
"timestamp": "2025-10-12T01:50:32.289Z",
"args": ["sean"]
},
{
"from": "initial",
"command": "recall",
"timestamp": "2025-10-12T01:53:14.080Z",
"args": [
{
"role": "sean",
"query": "矛盾论 主要矛盾 决策",
"mode": "focused"
}
]
},
{
"from": "initial",
"command": "remember",
"timestamp": "2025-10-12T01:57:38.537Z",
"args": [
{
"role": "sean",
"engrams": [
{
"content": "决定将 eslint-config 的 AI-friendly 特性拆分为独立项目 DeepLint。主要矛盾是通用性 vs AI友好性,通过产品拆分实现矛盾转化。DeepLint 专注于 AI 可理解的代码规范系统,每个规则包含可执行逻辑和 .rule.md 文档。NodeSpec 的 eslint-config 将使用 DeepLint 提供的规则,形成产品驱动生态的模式。",
"schema": "DeepLint - NodeSpec - AI友好 - 矛盾转化 - 产品拆分",
"strength": 0.9,
"type": "PATTERN"
},
{
"content": "Issue #19 的根本问题:rules 被 preset 的 import 语句打包进 dist/index.js,导致 import.meta.url 指向错误位置,无法找到对应的 .rule.md 文件。虽然 tsup 配置了分离规则文件,但 src/api/presets/common.ts 中的 import ~/rules 触发了打包。",
"schema": "Issue19 - import.meta.url - 打包问题 - preset导入",
"strength": 0.8,
"type": "LINK"
}
]
}
]
},
{
"from": "initial",
"command": "recall",
"timestamp": "2025-10-12T01:59:59.363Z",
"args": [
{
"role": "sean",
"query": "品牌命名 产品定位 Deepractice",
"mode": "balanced"
}
]
},
{
"from": "initial",
"command": "remember",
"timestamp": "2025-10-12T02:03:25.146Z",
"args": [
{
"role": "sean",
"engrams": [
{
"content": "项目命名讨论:DeepLint vs PracticeLint vs Deeplinter。最终选择 Deeplinter。命名考虑因素:品牌关联度、独特性、社区接受度、产品定位(AI可学习的linting规则系统)。Deeplinter 结合了 Deep(AI/智能)+ linter(检查工具),er后缀给人工具感和专业感。",
"schema": "Deeplinter - 命名 - 品牌策略 - AI-linting",
"strength": 0.8,
"type": "ATOMIC"
}
]
}
]
},
{
"from": "initial",
"command": "remember",
"timestamp": "2025-10-12T02:06:21.257Z",
"args": [
{
"role": "sean",
"engrams": [
{
"content": "使用 NodeSpec CLI 成功创建了 Deeplinter monorepo 项目。命令:node NodeSpec/apps/cli/dist/cli.js infra monorepo create Deeplinter --skip-git --skip-install。创建的结构包含:src/(core, domain), packages/, apps/, services/ 目录,完整的 pnpm workspace 配置,turbo.json, lefthook, commitlint 等标准配置。这验证了 NodeSpec CLI 的完整性和可用性。",
"schema": "NodeSpec-CLI - Deeplinter - monorepo创建 - 项目结构",
"strength": 0.9,
"type": "PATTERN"
},
{
"content": "Deeplinter 定位为 AI-learnable linting framework,口号 'Linting rules that AI can learn'。核心特性:每个规则包含可执行 JS + AI 可读的 .rule.md 文档。解决 Issue #19 的根本方案是将规则系统独立为 Deeplinter 项目,NodeSpec 的 eslint-config 将作为 Deeplinter 的第一个用户。这是矛盾转化的实践:通用性 vs AI友好性 → 产品拆分。",
"schema": "Deeplinter - 产品定位 - AI-learnable - 矛盾转化 - Issue19",
"strength": 0.9,
"type": "LINK"
}
]
}
]
},
{
"from": "initial",
"command": "remember",
"timestamp": "2025-10-12T02:10:11.392Z",
"args": [
{
"role": "sean",
"engrams": [
{
"content": "完成 Deeplinter 项目初始化。使用 NodeSpec CLI 创建 monorepo,手动创建 @deeplinter/framework 包(因为 CLI mirror 文件缺失)。Framework 包含 api/core/types 三层架构,实现了 createRule() 和 RuleRegistry 核心 API。已初始化 git 仓库并提交首个 commit。项目地址:/Users/sean/Deepractice/projects/Deeplinter",
"schema": "Deeplinter - 项目初始化 - framework包 - git仓库",
"strength": 0.9,
"type": "PATTERN"
}
]
}
]
},
{
"from": "initial",
"command": "action",
"timestamp": "2025-10-12T02:15:41.860Z",
"args": ["sean"]
}
],
"lastUpdated": "2025-10-12T02:15:41.870Z"
}
18 changes: 0 additions & 18 deletions apps/cli/cucumber.cjs

This file was deleted.

5 changes: 3 additions & 2 deletions apps/cli/features/infra/app/add.feature
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ Feature: Add Application to Monorepo
Given I am in the monorepo root
When I run "nodespec infra app add my-cli"
Then the command should succeed
And "apps/my-cli/package.json" should contain "\"build\": \"tsup\""
And "apps/my-cli/package.json" should contain "\"dev\""
And "apps/my-cli/package.json" should contain "\"build\":"
And "apps/my-cli/package.json" should contain "tsup"
And "apps/my-cli/package.json" should contain "\"dev\":"
And "apps/my-cli/package.json" should contain "\"typecheck\": \"tsc --noEmit\""

Scenario: Generated application is buildable and executable
Expand Down
16 changes: 7 additions & 9 deletions apps/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,25 @@
}
},
"scripts": {
"build": "NODE_OPTIONS='--import tsx' tsup",
"dev": "NODE_OPTIONS='--import tsx' tsup --watch",
"build": "tsup && tsx scripts/copy-mirror.ts",
"dev": "tsup --watch",
"clean": "rimraf dist",
"typecheck": "tsc --noEmit",
"test": "pnpm build && vitest run && cucumber-tsx",
"test:unit": "vitest run",
"test:e2e": "pnpm build && cucumber-tsx"
"test": "pnpm build && vitest run",
"test:dev": "vitest"
},
"dependencies": {
"@deepracticex/nodespec-core": "workspace:*",
"@deepracticex/nodespec-mirror": "workspace:*",
"commander": "^12.1.0",
"chalk": "^5.4.1",
"ora": "^8.1.1",
"prompts": "^2.4.2",
"execa": "^9.5.2"
},
"devDependencies": {
"@deepracticex/tsup-config": "workspace:*",
"@deepracticex/typescript-config": "workspace:*",
"@deepracticex/vitest-config": "workspace:*",
"@deepracticex/cucumber-config": "workspace:*"
"@deepracticex/config-preset": "workspace:*",
"@deepracticex/testing-utils": "workspace:*"
},
"files": [
"dist",
Expand Down
41 changes: 41 additions & 0 deletions apps/cli/scripts/copy-mirror.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env tsx

/**
* Copy mirror from nodespec-mirror package to CLI dist
*/

import path from "node:path";
import fs from "fs-extra";
import { fileURLToPath } from "node:url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

async function copyMirror() {
console.log("🪞 Copying NodeSpec mirror to CLI dist...");

const mirrorSource = path.resolve(
__dirname,
"../../../src/mirror/dist/mirror",
);
const mirrorDest = path.resolve(__dirname, "../dist/mirror");

// Check if mirror source exists
if (!(await fs.pathExists(mirrorSource))) {
console.error(
"❌ Mirror source not found. Please run 'pnpm --filter @deepracticex/nodespec-mirror build' first.",
);
process.exit(1);
}

// Copy mirror
await fs.copy(mirrorSource, mirrorDest);

console.log(`✅ Mirror copied to dist/mirror/`);
}

// Run
copyMirror().catch((error) => {
console.error("❌ Failed to copy mirror:", error);
process.exit(1);
});
6 changes: 3 additions & 3 deletions apps/cli/src/commands/infra/monorepo/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import fs from "fs-extra";
import chalk from "chalk";
import ora from "ora";
import { execa } from "execa";
import { ProjectGenerator } from "@deepracticex/nodespec-core";
import { MonorepoGenerator } from "@deepracticex/nodespec-core";

interface InitOptions {
name?: string;
Expand All @@ -30,9 +30,9 @@ export async function initAction(options: InitOptions): Promise<void> {
console.log(chalk.blue(`Initializing NodeSpec monorepo: ${projectName}`));
console.log(chalk.gray(`Target directory: ${targetDir}\n`));

// Generate project structure using ProjectGenerator
// Generate project structure using MonorepoGenerator
spinner.start("Generating project structure");
const generator = new ProjectGenerator();
const generator = new MonorepoGenerator();
await generator.generate(targetDir, { name: projectName });
spinner.succeed("Project structure generated");

Expand Down
Loading
Loading