Files
ai-proj-helper/skills-dev/dev-coding-plugin/skills/SKILL.md
T
johnQ 2e0f7fe68c feat(dev-coding): 新增「Step 0.5 Shell 环境自检」— node/npm 缺 PATH + HOME 未设置
在 macOS + Slark/DSH 实测定位到:bash 工具以 bash -c(非登录非交互)执行,
子进程环境等于宿主进程环境(PATH 不被清洗,HOME/USER/TMPDIR/LANG 未设置),
宿主由 GUI 应用拉起继承最小 PATH → node/npm/git 直接不可用。

沉淀内容:
- 5 条根因(不读 rc / PATH 不被清洗 / GUI 宿主 / HOME 未设置 / shell-env 只认 DSH_*)
- 两行 export 模板:HOME + node v22.22.3 PATH(勿混用 homebrew 的 v26)
- HOME 必须补的理由:~ 靠 passwd 展开易误判,git 报 fatal: $HOME not set,
  set -u 脚本报 unbound variable;「node 能跑」≠ 环境完整
- 交付纪律:禁止把「没有 shell / 不能构建」写成交付结论,未跑构建就如实标注
2026-10-07 07:42:00 +08:00

18 KiB
Raw Blame History

name, description
name description
dev-coding 软件编码开发技能。用于代码编写、功能实现、重构优化。集成 ai-proj CLI 进行任务管理和进度跟踪。核心支持 Go 后端 + Vue/React 前端开发。

软件编码开发 Skill (dev-coding)

概述

本技能用于软件编码实现,核心覆盖:

  • Go 后端 (Gin + GORM)
  • Vue 3 / React 前端

集成 ai-proj CLI 进行任务管理。

不包含(由其他技能/插件负责):

  • 开发设计(API 契约、任务拆分)→ req-design
  • 代码评审 → dev-review(批次2)
  • iOS 开发 → dev-ios(插件)
  • Android 开发 → dev-android(插件)
  • MCP 开发 → dev-mcp(插件)

ai-proj 任务管理

开发任务工作流

1. 查看/创建任务 → 2. 启动任务 → 3. 编码实现 → 4. 完成任务 → 5. 记录文档

任务操作速查

操作 CLI 命令 说明
查看任务列表 ai-proj task list 查看项目所有任务
创建任务 ai-proj task create 创建新任务
创建子任务 ai-proj task create --parent-id 分解任务
启动任务 ai-proj task start --id 开始执行
完成任务 ai-proj task complete --id 标记完成
更新任务 ai-proj task update --id 更新状态/描述
查看详情 ai-proj task get --id 完整任务信息
记录文档 ai-proj task append-doc --id 附加文档

开始新任务

# 1. 查看任务列表
ai-proj task list --status todo,in_progress

# 2. 启动任务
ai-proj task start --id <taskId>

# 3. 完成后
ai-proj task complete --id <taskId>

# 4. 记录文档
ai-proj task append-doc --id <taskId> --content "实现说明"

项目类型速查

当前项目生态

项目 类型 后端 前端
TWMS 仓储物流 Go+Gin+MySQL Vue 3
AI-Proj 项目管理 Go+Gin+PostgreSQL React 18
DICIAI 进销存SaaS Go+Gin+MySQL Vue 3

Step 0:验证优先(Karpathy: Goal-Driven Execution)

编写任何代码前,必须先写验证脚本。 规则来源:Karpathy "Goal-Driven Execution" 原则。

"Define success criteria. Loop until verified." "Fix the bug" → "Write a test that reproduces it, then make it pass"

执行流程

① 写验证脚本(按类型选择)
② 运行一遍,确认全部 FAIL(证明功能确实不存在 / bug 确实存在)
③ 编码实现
④ 再次运行验证脚本,全部 PASS → 完成

后端验证脚本模板

实现 API 前,先写好所有 curl 命令并标注期望结果:

# 验证脚本:REQ-XXXX [功能名]
BASE="http://localhost:8080"
TOKEN="<JWT>"

echo "=== T1: 正常创建 ==="
curl -s -X POST "$BASE/api/v1/xxx" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"name":"test"}' | jq '.code'
# 期望: 0

echo "=== T2: 缺少必填字段 ==="
curl -s -X POST "$BASE/api/v1/xxx" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{}' | jq '.code'
# 期望: 非 0(参数错误)

echo "=== T3: 跨租户访问 ==="
curl -s -X GET "$BASE/api/v1/xxx/999" \
  -H "Authorization: Bearer $TOKEN_OTHER_TENANT" | jq '.code'
# 期望: 403

先运行 → 全部 FAIL → 编码 → 再次运行 → 全部 PASS

前端验证脚本模板

实现页面前,先列出所有 data-testid 和期望的 DOM 状态:

验证清单(编码前先确认这些状态不存在 / 行为不正确):
- data-testid="xxx-btn-submit"  点击 → 列表刷新,行数增加 1
- data-testid="xxx-table"       行数 === API 返回 total
- data-testid="xxx-input-name"  空值提交 → 显示「请输入名称」提示

与 VP 三件套的关系

VP 协议 验证优先对应
VP-Data 先在环境建好测试数据(curl 确认成功)
VP-Steps 即为本节验证脚本 — 编码前写好,编码后执行
VP-Pass 验证脚本每条命令的期望输出值

Go 后端开发

分层架构

backend/
├── cmd/main.go                 # 入口点
├── internal/
│   ├── controller/handlers/    # HTTP 处理层
│   ├── biz/services/           # 业务逻辑层
│   ├── store/database/         # 数据访问层
│   └── middleware/             # 中间件
├── pkg/
│   ├── model/                  # 数据模型
│   ├── errno/                  # 错误定义
│   ├── api/                    # API 类型
│   └── util/                   # 工具函数
└── configs/migrations/         # 配置和迁移

代码规范

// 包声明和导入组织
package main

import (
    // 标准库
    "context"
    "fmt"

    // 第三方
    "github.com/gin-gonic/gin"

    // 项目内部
    "project/internal/pkg/errno"
)

// 错误处理 (Errno 模式)
if err != nil {
    core.WriteResponse(c, errno.ErrBind, nil)
    return
}

// 接口定义
type IStore interface {
    Users() UserStore
}

// 服务注入
type userBiz struct {
    ds store.IStore
}

func NewUserBiz(ds store.IStore) *userBiz {
    return &userBiz{ds: ds}
}

常用命令

# 构建
make build
go build -o ./_output/main ./cmd/main.go

# 运行
./_output/main --config ./configs/config.yaml

# 测试
make test
go test -v ./...

# 代码检查
make lint
golangci-lint run

# Swagger 文档
make swagger
swag init -g cmd/main.go

数据库模型

type UserM struct {
    Id         int64  `gorm:"column:id;primary_key"`
    Username   string `gorm:"column:username;not null"`
    CreateTime int64  `gorm:"column:create_time"`
    UpdateTime int64  `gorm:"column:update_time"`
    DeletedAt  soft_delete.DeletedAt `gorm:"column:deleted_at"`
}

func (m *UserM) TableName() string { return "users" }

func (m *UserM) BeforeCreate(tx *gorm.DB) error {
    m.CreateTime = time.Now().Unix()
    m.UpdateTime = m.CreateTime
    return nil
}

前端 data-testid 规范

编写或修改前端组件时,所有可交互元素必须加 data-testid。

命名格式: <模块>-<元素类型>[-<标识>]

<!-- ✅ 正确 -->
<a-input data-testid="product-input-name" v-model:value="form.name" placeholder="商品名称" />
<a-button data-testid="product-btn-submit" type="primary">创建商品</a-button>
<a-select data-testid="product-select-brand" v-model:value="form.brandId" />
<a-table data-testid="product-table" :dataSource="list" />

<!-- ❌ 错误 — 交互元素无 data-testid -->
<a-input v-model:value="form.name" placeholder="商品名称" />
<a-button type="primary">创建商品</a-button>

必须加: 输入框、选择器、开关、按钮(提交/取消/删除)、表格、模态框确认按钮、导航菜单项 不需要加: 纯展示文本、图标、布局容器(Row/Col/Space)


Vue 3 前端开发

项目结构

frontend/src/
├── api/                  # API 服务 (按模块分组)
│   ├── wms/             # 仓储管理
│   ├── oms/             # 订单管理
│   └── system/          # 系统管理
├── views/               # 页面组件
├── components/          # 可复用组件
├── store/modules/       # Pinia 状态
├── router/              # 路由配置
├── utils/
│   ├── request.ts       # Axios 拦截器
│   └── permission.ts    # 权限检查
└── i18n/                # 国际化

代码规范

// API 服务层
// api/user/model/index.ts
export interface User {
    id: number;
    username: string;
}

// api/user/index.ts
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api';
import type { User } from './model';

export async function getUsers(params: UserParams) {
    const res = await request.get<ApiResult<PageResult<User>>>(
        '/v1/users',
        { params }
    );
    if (res.status === 200) {
        return res.data;
    }
    return Promise.reject(new Error(res.data.message));
}

常用命令

# 安装依赖
npm install
pnpm install  # DICIAI 使用 pnpm

# 开发
npm run dev

# 构建
npm run build:prod
npm run build:test

# 代码检查
npm run lint:eslint

React 前端开发

项目结构

frontend/src/
├── pages/               # 页面组件
├── components/          # 可复用组件
├── services/            # API 服务
├── hooks/               # 自定义 Hooks
├── contexts/            # Context Providers
├── types/               # TypeScript 类型
├── utils/               # 工具函数
└── config/              # 配置

代码规范

// Context 集成
<QueryProvider>
    <AuthProvider>
        <TimerProvider>
            <ConfigProvider locale={zhCN}>
                <Router>
                    <Routes />
                </Router>
            </ConfigProvider>
        </TimerProvider>
    </AuthProvider>
</QueryProvider>

// API 服务
const api = axios.create({
    baseURL: API_BASE_URL,
    timeout: 120000,
});

api.interceptors.request.use((config) => {
    const token = TokenManager.getToken();
    if (token) {
        config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
});

常用命令

# 开发
npm start

# 构建
npm run build

# 测试
npm test
npm run test:e2e

通用开发规范

API 响应格式

{
  "code": 0,
  "message": "success",
  "data": {}
}

分页参数

{
  "page": 1,
  "limit": 20,
  "sort": "created_at",
  "order": "desc"
}

认证方式

  • JWT Token
  • Header: Authorization: Bearer <token>

错误处理

// Go
if err != nil {
    core.WriteResponse(c, errno.ErrXxx, nil)
    return
}

// TypeScript
try {
    const result = await api.call();
} catch (error) {
    message.error(error.message);
}

Git 工作流

提交规范

类型 说明
feat 新功能
fix Bug 修复
docs 文档
refactor 重构
test 测试
chore 杂项

双电脑同步 (au-dev / cn-dev)

# 离开时
git add -A
git commit -m "WIP: sync from $(hostname)"
git push origin $(git branch --show-current)

# 到达时
git fetch origin
git pull origin $(git branch --show-current)

Docker 部署

标准配置

# docker-compose.yml
services:
  backend:
    build: ./backend
    ports:
      - "8080:8080"
    depends_on:
      - db
      - redis

  frontend:
    build: ./frontend
    ports:
      - "80:80"

  db:
    image: mysql:8.0
    # 或 postgres:15

  redis:
    image: redis:alpine

常用端口

服务 端口
Backend 8080 / 9099
Frontend 80 / 3000
MySQL 3306
PostgreSQL 5432
Redis 6379

Push 前必须通过:变更包单元测试

在 git push 或 /pr create 之前,必须跑所有变更文件对应包的单元测试。

# 找出变更的 Go 文件所在包,跑对应测试
PKGS=$(git diff --name-only origin/main...HEAD | grep '\.go$' | grep -v '_test\.go' | sed 's|/[^/]*$||' | sort -u | sed 's|^|./|' | tr '\n' ' ')

if [ -n "$PKGS" ]; then
    echo "Running tests for changed packages: $PKGS"
    go test -v -count=1 $PKGS
else
    echo "No Go files changed, skipping tests"
fi

规则:

  • 测试通过 → 继续 push + /pr create
  • 测试失败 → 尝试自动修复,修复后重跑
    • 修复成功 → 继续 push
    • 修复失败 → 禁止 push,向用户报告失败原因,等待指示
  • 仅改了 _test.go → 同样需要跑(验证测试本身通过)
  • 无 Go 文件变更(纯前端/文档) → 跳过

最佳实践

  1. 任务驱动 - 使用 ai-proj 管理所有开发任务
  2. 分层清晰 - Controller → Service → Repository
  3. 接口先行 - 先定义接口再实现
  4. 小步提交 - 频繁提交,每次做一件事
  5. 测试覆盖 - 核心逻辑必须有测试
  6. 文档同步 - 代码变更同步更新文档

相关技能

技能 用途
req-design 开发设计(API 契约、任务拆分)— dev-coding 的输入
dev-test 测试与质量门禁
dev-review 代码评审(五视角扫描)
dev-ios iOS 开发(插件,按需加载)
dev-android Android 开发(插件,按需加载)
dev-mcp MCP bridge 开发(插件,按需加载)

CLAUDE.md 架构检查机制(REQ-20260416-0017 P0-5)

原则:本 skill 不硬编码任何项目的架构细节,从项目 CLAUDE.md 读取。

为什么

同一套 skill 要支持多个技术栈(Go+Gin / React+AntD / Vue+Element / Python+FastAPI)。如果把分层、命名、目录结构写死在 SKILL.md 里,跨项目就会冲突。

devflow-claude 的做法(借鉴):skill 只管流程和模板,项目架构由 CLAUDE.md 的 "Architecture" / "项目架构" 章节定义。

执行前检查

开始编码任务前,skill 先检查项目根 CLAUDE.md:

# 检查 CLAUDE.md 是否含架构关键词
if [ -f "CLAUDE.md" ]; then
    if grep -qiE "(架构|分层|目录结构|tech stack|architecture|project structure)" CLAUDE.md; then
        echo "✅ 检测到项目架构信息"
    else
        echo "⚠️ CLAUDE.md 缺少架构描述"
        echo "   dev-coding 需要架构信息来生成准确的文件路径和分层顺序"
        echo ""
        echo "   📋 建议操作:"
        echo "   - 查看预置架构片段: ai-proj-helper/skills-dev/dev-coding-plugin/templates/claude-md-snippets/"
        echo "   - 选择匹配技术栈的片段,补充到 CLAUDE.md 的 '## Architecture' 章节"
        echo ""
        echo "   ⚠️ 继续执行,但生成的文件路径可能不够准确"
    fi
else
    echo "⚠️ 未找到项目 CLAUDE.md,建议创建"
fi

架构片段模板库

位于 skills-dev/dev-coding-plugin/templates/claude-md-snippets/:

文件 适用场景
go-gin-gorm.md Go + Gin + GORM 后端(ai-proj backend 风格)
react-antd.md React + TypeScript + Ant Design(ai-proj frontend 风格)
vue-element.md Vue 3 + Element Plus(coolbuy-paas 风格)
mcp-typescript.md MCP bridge TypeScript(mcp-task-bridge 风格)
generic.md 通用空白骨架

非阻断原则

架构信息缺失时仅警告不阻止。用户仍可继续,但会被告知"生成的建议可能不够准确"。


Step 0.5:Shell 环境自检(node/npm command not found 先看这里)

在任何 npm / pnpm / node 命令之前,先确认解释器可解析。 报 command not found 时 不要下结论"当前环境没有 shell",也不要去找"给 agent 配 shell"的开关(DSH 没有这个开关)。

根因(不要重复侦察;已在 macOS + Slark/DSH 上定位到代码)

# 事实
1 DSH 的 bash 工具(@deepseek-ai/dsh-bash-local)一律以 bash -c(非登录、非交互) 执行 → 不读 ~/.zprofile / ~/.zshrc / ~/.profile
2 子进程环境 = 宿主进程环境 − 凭据类变量 − DSH_*(@deepseek-ai/dsh-subprocess)→ PATH 不被清洗,它等于启动宿主那个进程的 PATH
3 宿主由 GUI 应用(Slark.app)拉起 → 继承 macOS GUI 的最小 PATH(/usr/local/bin:/bin:/usr/bin:...)→ node 不在里面
4 HOME 未设置(不是空值);USER / TMPDIR / LANG 同样未设置
5 @deepseek-ai/dsh-shell-env 只注册/注入 DSH_* 变量,PATH 是保留键 → 改 profile/cordis.patch.yml 加 PATH 无效

正确做法(两行 export,别多一步)

export HOME="/Users/johnq"                                              # 必须补:git 等直接读 $HOME
export PATH="/Users/johnq/.local/node-v22.22.3-darwin-arm64/bin:$PATH"  # node/npm/pnpm
cd <项目> && npm install && npm run build

为什么 HOME 必须补(实测):

  • ~ 在 bash 里靠 passwd 查表展开,所以 ls ~、cd ~/x 仍能用 → 容易误判环境正常;

  • 直接读 $HOME 的会崩:git → fatal: $HOME not set(status / commit / config --global 全废); 带 set -u 的脚本 → HOME: unbound variable(例:ai-proj-helper 的 install-skills.sh);

  • node 侧多数无事(os.homedir() 走 passwd 兜底,只有 process.env.HOME 是 undefined) → 「node 能跑」≠ 环境完整,别据此跳过 HOME。

  • 本机 node 必须用这一支(定义在 ~/.zprofile,对齐项目 engines.node): /Users/johnq/.local/node-v22.22.3-darwin-arm64/bin/node = v22.22.3,npm 10.9.8。

  • /opt/homebrew/bin/node 是另一支 v26,不要混用;/usr/local/bin/node 不存在。

  • 备选①:/bin/zsh -lic '<命令>'(登录 zsh 会读 ~/.zprofile)。

  • 备选②:绝对路径直调 /Users/johnq/.local/node-v22.22.3-darwin-arm64/bin/node build.mjs。

  • 路径变了先 ls -d /Users/johnq/.local/node-v*-darwin-arm64/bin 重新取真实版本号,不要猜。

交付纪律(配合「Step 0:验证优先」)

  • 禁止把"没有 shell / 不能构建"写成交付结论:bash 工具是好的,缺的只是 HOME + PATH。 正确表述是"我未执行构建(缺 node PATH,已给用户补 PATH 后的构建命令)"。
  • 构建/测试没跑就说没跑(未经构建与实机验证),不要用"构建配置已就绪"之类中间信号冒充验收。
  • 校验环境的最快方式(输出直接贴进交付):
export HOME="/Users/johnq"; export PATH="/Users/johnq/.local/node-v22.22.3-darwin-arm64/bin:$PATH"
node -v && npm -v && git status --short | head -3