@xulthekl/team-flow 0.33.0 → 0.34.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/.claude/always/phase-guard.md +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor-plugin/marketplace.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/.github/plugin/marketplace.json +2 -2
- package/AGENTS.md +2 -0
- package/CHANGELOG.md +35 -0
- package/CONTRIBUTING.md +44 -0
- package/GEMINI.md +1 -1
- package/INSTALL.md +1 -1
- package/README.md +1 -1
- package/docs/README_en.md +1 -1
- package/docs/solutions/INDEX.md +1 -0
- package/docs/solutions/cross-phase/2026-08-04-no-summary.md +17 -0
- package/gemini-extension.json +1 -1
- package/hooks/session-start +2 -2
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/scripts/lib/conventions-generator.mjs +350 -0
- package/scripts/lib/test-record.mjs +65 -2
- package/skills/test-strategy/SKILL.md +37 -0
- package/skills/test-strategy/references/integration-test-contracts.md +237 -0
- package/skills/test-strategy/references/integration-test-isolation.md +346 -0
- package/skills/test-strategy/references/test-quality-rules.md +292 -0
- package/skills/workflow-bootstrap/SKILL.md +40 -3
- package/templates/agent-template.md +41 -0
- package/templates/conventions/_manifest.json +39 -0
- package/templates/conventions/glaf4-compliant/java-testing.md +367 -0
- package/templates/conventions/glaf4-compliant/spring-patterns.md +415 -0
- package/templates/conventions/js-testing.md +261 -0
- package/templates/conventions/python-testing.md +333 -0
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
{
|
|
10
10
|
"name": "team-flow",
|
|
11
11
|
"description": "8-state spec workflow + compound global compounding + architecture-design (4A/DDD) + local HTML prototype + product-level orchestration + bootstrap + e2e + session handoff + workflow feedback. 24 skills + 15 agents with embedded TDD, SDD, code review, debugging, delta spec sync, and design-system-driven prototyping.",
|
|
12
|
-
"version": "0.
|
|
12
|
+
"version": "0.34.0",
|
|
13
13
|
"source": "./",
|
|
14
14
|
"author": {
|
|
15
15
|
"name": "LT",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "team-flow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.0",
|
|
4
4
|
"description": "Unified workflow plugin: team-flow (spec-driven dev: TDD/SDD/code-review/debugging) + compound-engineering core subset (brainstorm/plan/compound/strategy/ideate/proof, global compounding) + architecture-design (4A+DDD incremental design & global compounding) + prototype (local HTML prototype, zero external deps) + e2e (Playwright E2E, AC-driven) + workflow-orchestrator (product-level workflow orchestration) + workflow-bootstrap (existing project onboarding) + session-handoff (context transfer) + workflow-feedback (issue tracking). 24 skills + 15 agents, one install.",
|
|
5
5
|
"source": "./",
|
|
6
6
|
"author": {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "team-flow",
|
|
3
3
|
"displayName": "team-flow",
|
|
4
4
|
"description": "Unified workflow plugin: team-flow (spec-driven dev: TDD/SDD/code-review/debugging) + compound-engineering core subset (brainstorm/plan/compound/strategy/ideate/proof, global compounding) + architecture-design (4A+DDD incremental design & global compounding) + prototype (local HTML prototype, zero external deps) + e2e (Playwright E2E, AC-driven) + workflow-orchestrator (product-level workflow orchestration) + workflow-bootstrap (existing project onboarding) + session-handoff (context transfer) + workflow-feedback (issue tracking). 24 skills + 15 agents, one install.",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.34.0",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "LT",
|
|
8
8
|
"url": "https://github.com/LT"
|
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "Unified workflow plugins and skills for AI coding agents (team-flow: team-flow + compound + architecture-design + prototype).",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.34.0"
|
|
10
10
|
},
|
|
11
11
|
"plugins": [
|
|
12
12
|
{
|
|
13
13
|
"name": "team-flow",
|
|
14
14
|
"description": "Unified workflow with planning artifacts, execution contracts, TDD, review gates, systematic debugging, delta spec sync, architecture-design, and local HTML prototyping.",
|
|
15
|
-
"version": "0.
|
|
15
|
+
"version": "0.34.0",
|
|
16
16
|
"source": ".",
|
|
17
17
|
"author": {
|
|
18
18
|
"name": "LT",
|
package/AGENTS.md
CHANGED
|
@@ -210,6 +210,8 @@ STRATEGY.md CONCEPTS.md 产品策略(BA) / 领域词汇
|
|
|
210
210
|
|
|
211
211
|
### Agents 索引(v0.7 新增,v0.30.0 增至 15 个)
|
|
212
212
|
|
|
213
|
+
> **agent 文件设计规范见 CONTRIBUTING.md §6 + `templates/agent-template.md`**(v0.33.0):frontmatter 必须合法 YAML(非法时 Claude Code 静默降级,skills: 预加载与 tools: 限制全部失效);description 单句、禁 `<example>` 块;新增/修改 agent 必过 frontmatter-lint + 实证探针。
|
|
214
|
+
|
|
213
215
|
| Agent | 职责 | Tools | 触发场景 |
|
|
214
216
|
|-------|------|-------|---------|
|
|
215
217
|
| architecture-design | 架构设计门控 agent——五项检查 + 三件套产出 + SQL 制品(workflow-start 子代理调用,判断+执行一体化) | Read/Bash/Grep/Glob/Write | workflow-start exploring→specifying 状态转换时(架构设计门控,v0.27.2) |
|
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,41 @@ The format loosely follows Keep a Changelog.
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.34.0] - 2026-08-04
|
|
10
|
+
|
|
11
|
+
### Added(测试能力增强——吸收 glaf4-test 通用能力 + conventions 机制,设计见工作区级文档 team-flow-workspace/docs/plan/test-capability-enhancement-design.md)
|
|
12
|
+
|
|
13
|
+
#### P0:组合覆盖声明(test-strategy SKILL.md)
|
|
14
|
+
- **§8 组合覆盖声明**:多参数方法(param_count > 1)必须声明 `pairwise`,有分支逻辑必须声明 `branch`;contract-builder 生成矩阵后强制对账
|
|
15
|
+
|
|
16
|
+
#### P1:测试质量规则 + failure 分类法
|
|
17
|
+
- **skills/test-strategy/references/test-quality-rules.md**:从 glaf4-test scan-generated-tests.py 抽取 16 条通用规则(断言质量、调试代码残留、测试状态、测试数据、测试结构、矩阵对账、语言特定)
|
|
18
|
+
- **scripts/lib/test-record.mjs**:新增 `classifyFailure` 函数,测试失败时自动分类为 6 类(assertion_failure / runtime_error / framework_error / compile_error / dependency_blocker / unknown),记录到 test_result
|
|
19
|
+
|
|
20
|
+
#### P2:社交测试契约 + 测试隔离分级
|
|
21
|
+
- **skills/test-strategy/references/integration-test-contracts.md**:5 种契约类型(入口/协作者/数据/中间件/清理),集成测试的组织方法论
|
|
22
|
+
- **skills/test-strategy/references/integration-test-isolation.md**:4 级隔离策略(L1 进程内 / L2 事务 / L3 手动清理 / L4 无隔离),基础设施隔离策略
|
|
23
|
+
|
|
24
|
+
#### P2:conventions 机制建设(v0.34.0 核心特性)
|
|
25
|
+
- **templates/conventions/**:plugin 内置 conventions 模板
|
|
26
|
+
- `glaf4-compliant/java-testing.md`:Java 测试规范(JUnit 5 + Mockito),符合 glaf4-test 要求
|
|
27
|
+
- `glaf4-compliant/spring-patterns.md`:Spring Boot 测试规范,符合 glaf4-test 要求
|
|
28
|
+
- `js-testing.md`:JavaScript 测试规范(Jest/Vitest)
|
|
29
|
+
- `python-testing.md`:Python 测试规范(Pytest)
|
|
30
|
+
- `_manifest.json`:模板清单(版本、描述、适用技术栈)
|
|
31
|
+
- **scripts/lib/conventions-generator.mjs**:conventions 生成器脚本
|
|
32
|
+
- 技术栈自动检测(Java/JavaScript/Python)
|
|
33
|
+
- conventions 模板选择和生成
|
|
34
|
+
- 版本管理机制(.versions.json)
|
|
35
|
+
- team-flow.config.json 自动更新
|
|
36
|
+
- 支持存量项目(自动识别)和全新项目(交互式引导)
|
|
37
|
+
- **skills/workflow-bootstrap/SKILL.md**:增加 B1.5 阶段(Conventions Generator)
|
|
38
|
+
|
|
39
|
+
### Tests
|
|
40
|
+
- **tests/lib/conventions-generator.test.mjs**:15 个测试(detectTechStack/selectTemplates/generateConventions/updateConfig)
|
|
41
|
+
- 全量回归:571/571 通过(含 15 个新增测试)
|
|
42
|
+
- check-versions ✅
|
|
43
|
+
|
|
9
44
|
## [0.33.0] - 2026-08-03
|
|
10
45
|
|
|
11
46
|
### Fixed(skills 注入恢复——frontmatter YAML 非法导致预加载静默失效,设计见工作区级文档 team-flow-workspace/docs/architecture-api-db-design-enhancement-v0.13.md §54)
|
package/CONTRIBUTING.md
CHANGED
|
@@ -86,6 +86,50 @@ Skill text should help an agent decide:
|
|
|
86
86
|
|
|
87
87
|
Avoid vague motivational language when an operational rule would be clearer.
|
|
88
88
|
|
|
89
|
+
### 6. Agent file design spec (v0.33.0+)
|
|
90
|
+
|
|
91
|
+
Background: before v0.33.0, every agent's YAML frontmatter was invalid (an
|
|
92
|
+
`<example>` block at column 0 inside the `description` field). Claude Code
|
|
93
|
+
degrades SILENTLY on invalid frontmatter — `skills:` preload and `tools:`
|
|
94
|
+
restrictions are dropped with no warning, and the agent body alone is kept.
|
|
95
|
+
The defect survived the entire plugin lifetime. `tests/lib/frontmatter-lint.test.mjs`
|
|
96
|
+
(npm test) is the machine gate; this spec is the human gate.
|
|
97
|
+
|
|
98
|
+
Copy `templates/agent-template.md` when creating a new agent. Hard rules:
|
|
99
|
+
|
|
100
|
+
1. **`description` is a single-line string.** No `>-` block scalars, no
|
|
101
|
+
`<example>` blocks — the official Anthropic plugin-dev agents use that
|
|
102
|
+
pattern and it is a trap (it breaks YAML indentation and silently disables
|
|
103
|
+
the whole frontmatter). If the text must contain an ASCII `: `, wrap the
|
|
104
|
+
entire value in double quotes. team-flow agents are dispatched explicitly
|
|
105
|
+
by `workflow-start`, so example-driven auto-triggering buys nothing.
|
|
106
|
+
2. **`name` must equal the file name** (minus `.md`). On degraded parsing the
|
|
107
|
+
registry falls back to the file name — a mismatch means silent mislabeling.
|
|
108
|
+
3. **Declare `tools` explicitly.** Since v0.33.0 the restriction is enforced;
|
|
109
|
+
the subagent holds ONLY the declared tools (no MCP tools unless listed).
|
|
110
|
+
4. **`skills` entries must resolve.** Each entry must match an existing
|
|
111
|
+
`skills/<name>/SKILL.md` (bare name, same as glaf4-test's proven pattern).
|
|
112
|
+
A dangling entry means a silent no-preload.
|
|
113
|
+
5. **Body ≤ 100 lines, WHO/WHAT only.** No SOP/methodology in the body — that
|
|
114
|
+
belongs to the preloaded Skill. If the body says "Your preloaded Skill
|
|
115
|
+
contains the detailed methodology", the `skills:` field MUST declare it.
|
|
116
|
+
|
|
117
|
+
Anti-patterns (forbidden):
|
|
118
|
+
|
|
119
|
+
- `<example>` blocks anywhere in frontmatter
|
|
120
|
+
- Unquoted ASCII `: ` inside `description` values
|
|
121
|
+
- Copying frontmatter style from other plugins without running the lint
|
|
122
|
+
|
|
123
|
+
Verification (mandatory for new/changed agents):
|
|
124
|
+
|
|
125
|
+
1. `npm test` — the frontmatter-lint gate must pass.
|
|
126
|
+
2. **Empirical probe** — dispatch the agent once and verify with a BEHAVIORAL
|
|
127
|
+
probe (ask it to recite a rule that exists only in the preloaded Skill or
|
|
128
|
+
the agent body). Do NOT rely on exact-string introspection questions — they
|
|
129
|
+
produce false negatives. Do not write "mechanism works" claims into any doc
|
|
130
|
+
without this probe. See design doc §54.6 (workspace-level
|
|
131
|
+
`docs/architecture-api-db-design-enhancement-v0.13.md`).
|
|
132
|
+
|
|
89
133
|
## Pull Request Guidance
|
|
90
134
|
|
|
91
135
|
When opening a change, explain:
|
package/GEMINI.md
CHANGED
|
@@ -8,7 +8,7 @@ The workflow is self-contained and does not require OpenSpec or Superpowers at r
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
<!-- team-flow-phase-guard-start -->
|
|
11
|
-
# team-flow v0.
|
|
11
|
+
# team-flow v0.34.0 | 阶段: {{state}} | 工作流: {{workflow}}
|
|
12
12
|
当前阶段允许的操作由 workflow-start 路由规则定义。
|
|
13
13
|
禁止跨越 DP gate 进入下一阶段。变更范围以 execution-contract.md 的 Intent Lock 为准。
|
|
14
14
|
<!-- team-flow-phase-guard-end -->
|
package/INSTALL.md
CHANGED
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# team-flow
|
|
2
2
|
|
|
3
|
-
> 当前版本:`v0.
|
|
3
|
+
> 当前版本:`v0.34.0`
|
|
4
4
|
|
|
5
5
|
> 统一插件:**team-flow**(spec 驱动开发)+ **compound-engineering 核心子集**(全局复利)+ **architecture-design**(4A+DDD 增量设计)+ **prototype**(本地 HTML 原型)+ **e2e**(AC 驱动 E2E)+ **workflow-orchestrator**(产品级编排)+ **workflow-bootstrap**(既有项目接入)。一次安装,七套能力协同。
|
|
6
6
|
|
package/docs/README_en.md
CHANGED
|
@@ -126,7 +126,7 @@ npm install -g team-flow
|
|
|
126
126
|
|
|
127
127
|
### Version
|
|
128
128
|
|
|
129
|
-
- Current: `v0.
|
|
129
|
+
- Current: `v0.34.0`
|
|
130
130
|
- v0.9.1 highlights: DP-4 execution-mode recommendations, a portable runtime across 17 platforms, and a raw-package smoke with no plugin-root variable.
|
|
131
131
|
- Self-contained — no OpenSpec or Superpowers runtime required
|
|
132
132
|
- Upstream: [Fission-AI/OpenSpec](https://github.com/Fission-AI/OpenSpec), [obra/superpowers](https://github.com/obra/superpowers)
|
package/docs/solutions/INDEX.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
<!-- 每条一行,按 severity 降序,≤150 行硬上限 -->
|
|
3
3
|
| date | phase | domain | type | severity | summary | file |
|
|
4
4
|
|------|-------|--------|------|----------|---------|------|
|
|
5
|
+
| 2026-08-04 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-08-04-no-summary.md |
|
|
5
6
|
| 2026-08-03 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-08-03-no-summary.md |
|
|
6
7
|
| 2026-08-01 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-08-01-no-summary.md |
|
|
7
8
|
| 2026-07-31 | cross-phase | general | insight | medium | (no summary) | cross-phase/2026-07-31-no-summary.md |
|
package/gemini-extension.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "team-flow",
|
|
3
3
|
"description": "Unified workflow plugin: team-flow (spec-driven dev) + compound-engineering core subset + architecture-design (4A/DDD) + prototype (local HTML). 24 skills, one install.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.34.0",
|
|
5
5
|
"contextFileName": "GEMINI.md"
|
|
6
6
|
}
|
package/hooks/session-start
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# v0.
|
|
2
|
+
# v0.34.0: auto-sync CLI version with plugin version
|
|
3
3
|
set -e
|
|
4
4
|
|
|
5
5
|
# ═══════════════════════════════════════════════════════════════
|
|
6
6
|
# Plugin version (update this when releasing new versions)
|
|
7
7
|
# ═══════════════════════════════════════════════════════════════
|
|
8
|
-
PLUGIN_VERSION="0.
|
|
8
|
+
PLUGIN_VERSION="0.34.0"
|
|
9
9
|
|
|
10
10
|
# ═══════════════════════════════════════════════════════════════
|
|
11
11
|
# Step 1: Auto-sync CLI version with plugin version
|
package/llms.txt
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
## Overview
|
|
4
4
|
spec-superflow is a self-contained workflow integration plugin for Claude Code, Cursor, OpenAI Codex CLI/App, GitHub Copilot CLI, Gemini CLI, OpenCode, WorkBuddy, and Trae. It merges spec-driven planning artifacts (proposal, specs, design, tasks) with disciplined execution guardrails (TDD, review gates, controlled handoff) into one unified workflow.
|
|
5
5
|
|
|
6
|
-
Current version: v0.
|
|
6
|
+
Current version: v0.34.0.
|
|
7
7
|
|
|
8
8
|
## Key Documents
|
|
9
9
|
- README.md: Chinese homepage with full usage guide and FAQ
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xulthekl/team-flow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.0",
|
|
4
4
|
"description": "Unified plugin (24 skills + 15 agents) integrating team-flow, compound-engineering, architecture-design, prototype, design-system, workflow-orchestrator, workflow-bootstrap, e2e, session-handoff, workflow-feedback for multi-agent coding tools.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
package/plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "team-flow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.0",
|
|
4
4
|
"description": "Unified workflow plugin: team-flow (spec-driven dev: TDD/SDD/code-review/debugging) + compound-engineering core subset (brainstorm/plan/compound/strategy/ideate/proof, global compounding) + architecture-design (4A+DDD incremental design & global compounding) + prototype (local HTML prototype, zero external deps) + e2e (Playwright E2E, AC-driven) + workflow-orchestrator (product-level workflow orchestration) + workflow-bootstrap (existing project onboarding) + session-handoff (context transfer) + workflow-feedback (issue tracking). 24 skills + 15 agents, one install.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "LT"
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// scripts/lib/conventions-generator.mjs — conventions 生成器(v0.34.0 新增)
|
|
3
|
+
//
|
|
4
|
+
// 根据项目技术栈自动生成测试规范 conventions,符合 glaf4-test 要求。
|
|
5
|
+
// 支持存量项目(自动识别)和全新项目(交互式引导)。
|
|
6
|
+
//
|
|
7
|
+
// 使用方式:
|
|
8
|
+
// node scripts/lib/conventions-generator.mjs --root <项目根目录> [--interactive]
|
|
9
|
+
//
|
|
10
|
+
// 设计来源:test-capability-enhancement-design v1.0 §四
|
|
11
|
+
|
|
12
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync } from 'node:fs';
|
|
13
|
+
import path, { join } from 'node:path';
|
|
14
|
+
import { parseArgs } from 'node:util';
|
|
15
|
+
|
|
16
|
+
// ── 常量 ─────────────────────────────────────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
const TEMPLATE_DIR = join(import.meta.dirname, '../../templates/conventions');
|
|
19
|
+
const GLAF4_TEMPLATE_DIR = join(TEMPLATE_DIR, 'glaf4-compliant');
|
|
20
|
+
|
|
21
|
+
// 技术栈检测特征
|
|
22
|
+
const TECH_STACK_SIGNATURES = {
|
|
23
|
+
java: ['pom.xml', 'build.gradle', 'build.gradle.kts'],
|
|
24
|
+
javascript: ['package.json', 'yarn.lock', 'pnpm-lock.yaml'],
|
|
25
|
+
python: ['requirements.txt', 'pyproject.toml', 'setup.py', 'Pipfile'],
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// 测试框架检测特征
|
|
29
|
+
const TEST_FRAMEWORK_SIGNATURES = {
|
|
30
|
+
'junit5-mockito': { file: 'pom.xml', content: /junit-jupiter|org\.junit\.jupiter/ },
|
|
31
|
+
jest: { file: 'package.json', content: /"jest"|"@jest\/|vitest/ },
|
|
32
|
+
pytest: { file: 'requirements.txt', content: /pytest/ },
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// 应用框架检测特征
|
|
36
|
+
const APP_FRAMEWORK_SIGNATURES = {
|
|
37
|
+
'spring-boot': { file: 'pom.xml', content: /spring-boot|org\.springframework\.boot/ },
|
|
38
|
+
express: { file: 'package.json', content: /"express"/ },
|
|
39
|
+
django: { file: 'requirements.txt', content: /django/ },
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// ── 技术栈检测 ─────────────────────────────────────────────────────────────
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 检测项目技术栈
|
|
46
|
+
* @param {string} root 项目根目录
|
|
47
|
+
* @returns {{ language: string|null, buildTool: string|null, testFramework: string|null, appFramework: string|null }}
|
|
48
|
+
*/
|
|
49
|
+
export function detectTechStack(root) {
|
|
50
|
+
const result = {
|
|
51
|
+
language: null,
|
|
52
|
+
buildTool: null,
|
|
53
|
+
testFramework: null,
|
|
54
|
+
appFramework: null,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// 检测语言
|
|
58
|
+
for (const [lang, files] of Object.entries(TECH_STACK_SIGNATURES)) {
|
|
59
|
+
if (files.some(f => existsSync(join(root, f)))) {
|
|
60
|
+
result.language = lang;
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// 检测构建工具
|
|
66
|
+
if (existsSync(join(root, 'pom.xml'))) result.buildTool = 'maven';
|
|
67
|
+
else if (existsSync(join(root, 'build.gradle')) || existsSync(join(root, 'build.gradle.kts'))) result.buildTool = 'gradle';
|
|
68
|
+
else if (existsSync(join(root, 'package.json'))) result.buildTool = 'npm';
|
|
69
|
+
else if (existsSync(join(root, 'yarn.lock'))) result.buildTool = 'yarn';
|
|
70
|
+
else if (existsSync(join(root, 'pnpm-lock.yaml'))) result.buildTool = 'pnpm';
|
|
71
|
+
else if (existsSync(join(root, 'requirements.txt')) || existsSync(join(root, 'pyproject.toml'))) result.buildTool = 'pip';
|
|
72
|
+
else if (existsSync(join(root, 'Pipfile'))) result.buildTool = 'pipenv';
|
|
73
|
+
|
|
74
|
+
// 检测测试框架
|
|
75
|
+
for (const [fw, sig] of Object.entries(TEST_FRAMEWORK_SIGNATURES)) {
|
|
76
|
+
const filePath = join(root, sig.file);
|
|
77
|
+
if (existsSync(filePath)) {
|
|
78
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
79
|
+
if (sig.content.test(content)) {
|
|
80
|
+
result.testFramework = fw;
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 检测应用框架
|
|
87
|
+
for (const [fw, sig] of Object.entries(APP_FRAMEWORK_SIGNATURES)) {
|
|
88
|
+
const filePath = join(root, sig.file);
|
|
89
|
+
if (existsSync(filePath)) {
|
|
90
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
91
|
+
if (sig.content.test(content)) {
|
|
92
|
+
result.appFramework = fw;
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ── 模板选择 ─────────────────────────────────────────────────────────────
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* 根据技术栈选择 conventions 模板
|
|
105
|
+
* @param {{ language: string|null, buildTool: string|null, testFramework: string|null, appFramework: string|null }} techStack
|
|
106
|
+
* @returns {string[]} 模板文件名列表
|
|
107
|
+
*/
|
|
108
|
+
export function selectTemplates(techStack) {
|
|
109
|
+
const templates = [];
|
|
110
|
+
|
|
111
|
+
if (techStack.language === 'java') {
|
|
112
|
+
// Java 项目:使用 glaf4-compliant 模板
|
|
113
|
+
if (existsSync(join(GLAF4_TEMPLATE_DIR, 'java-testing.md'))) {
|
|
114
|
+
templates.push('glaf4-compliant/java-testing.md');
|
|
115
|
+
}
|
|
116
|
+
if (techStack.appFramework === 'spring-boot') {
|
|
117
|
+
if (existsSync(join(GLAF4_TEMPLATE_DIR, 'spring-patterns.md'))) {
|
|
118
|
+
templates.push('glaf4-compliant/spring-patterns.md');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
} else if (techStack.language === 'javascript') {
|
|
122
|
+
templates.push('js-testing.md');
|
|
123
|
+
} else if (techStack.language === 'python') {
|
|
124
|
+
templates.push('python-testing.md');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return templates;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ── conventions 生成 ─────────────────────────────────────────────────────
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 生成 conventions 文件
|
|
134
|
+
* @param {string} root 项目根目录
|
|
135
|
+
* @param {{ language: string|null, buildTool: string|null, testFramework: string|null, appFramework: string|null }} techStack
|
|
136
|
+
* @param {string[]} templates 模板文件名列表
|
|
137
|
+
* @returns {{ created: string[], skipped: string[] }}
|
|
138
|
+
*/
|
|
139
|
+
export function generateConventions(root, techStack, templates) {
|
|
140
|
+
const conventionsDir = join(root, '.team-flow', 'conventions');
|
|
141
|
+
const versionsFile = join(conventionsDir, '.versions.json');
|
|
142
|
+
|
|
143
|
+
// 创建目录
|
|
144
|
+
mkdirSync(conventionsDir, { recursive: true });
|
|
145
|
+
|
|
146
|
+
// 读取现有版本信息
|
|
147
|
+
let versions = {};
|
|
148
|
+
if (existsSync(versionsFile)) {
|
|
149
|
+
try {
|
|
150
|
+
versions = JSON.parse(readFileSync(versionsFile, 'utf-8'));
|
|
151
|
+
} catch {
|
|
152
|
+
versions = {};
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (!versions.conventions) versions.conventions = {};
|
|
156
|
+
|
|
157
|
+
const created = [];
|
|
158
|
+
const skipped = [];
|
|
159
|
+
|
|
160
|
+
for (const template of templates) {
|
|
161
|
+
const templatePath = join(TEMPLATE_DIR, template);
|
|
162
|
+
const fileName = path.basename(template);
|
|
163
|
+
const targetPath = join(conventionsDir, fileName);
|
|
164
|
+
|
|
165
|
+
// 检查是否已存在且未自定义
|
|
166
|
+
if (existsSync(targetPath)) {
|
|
167
|
+
const existingVersion = versions.conventions[fileName];
|
|
168
|
+
if (existingVersion && !existingVersion.customized) {
|
|
169
|
+
// 读取模板版本
|
|
170
|
+
const templateContent = readFileSync(templatePath, 'utf-8');
|
|
171
|
+
const versionMatch = templateContent.match(/version:\s*(\d+\.\d+\.\d+)/);
|
|
172
|
+
const templateVersion = versionMatch ? versionMatch[1] : '1.0.0';
|
|
173
|
+
|
|
174
|
+
if (existingVersion.source_version === templateVersion) {
|
|
175
|
+
skipped.push(fileName);
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// 复制模板
|
|
182
|
+
const templateContent = readFileSync(templatePath, 'utf-8');
|
|
183
|
+
writeFileSync(targetPath, templateContent, 'utf-8');
|
|
184
|
+
|
|
185
|
+
// 更新版本信息
|
|
186
|
+
const versionMatch = templateContent.match(/version:\s*(\d+\.\d+\.\d+)/);
|
|
187
|
+
const templateVersion = versionMatch ? versionMatch[1] : '1.0.0';
|
|
188
|
+
|
|
189
|
+
versions.conventions[fileName] = {
|
|
190
|
+
source_version: templateVersion,
|
|
191
|
+
installed_at: new Date().toISOString().split('T')[0],
|
|
192
|
+
customized: false,
|
|
193
|
+
last_checked: new Date().toISOString().split('T')[0],
|
|
194
|
+
source: template,
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
created.push(fileName);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// 写入版本信息
|
|
201
|
+
writeFileSync(versionsFile, JSON.stringify(versions, null, 2), 'utf-8');
|
|
202
|
+
|
|
203
|
+
return { created, skipped };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// ── 更新 team-flow.config.json ─────────────────────────────────────────
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* 更新 team-flow.config.json 的 conventions 字段
|
|
210
|
+
* @param {string} root 项目根目录
|
|
211
|
+
* @param {string[]} conventionsFiles conventions 文件名列表
|
|
212
|
+
*/
|
|
213
|
+
export function updateConfig(root, conventionsFiles) {
|
|
214
|
+
const teamFlowDir = join(root, '.team-flow');
|
|
215
|
+
const configPath = join(teamFlowDir, 'team-flow.config.json');
|
|
216
|
+
|
|
217
|
+
// 确保目录存在
|
|
218
|
+
mkdirSync(teamFlowDir, { recursive: true });
|
|
219
|
+
|
|
220
|
+
let config = {};
|
|
221
|
+
if (existsSync(configPath)) {
|
|
222
|
+
try {
|
|
223
|
+
config = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
224
|
+
} catch {
|
|
225
|
+
config = {};
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (!config.conventions) config.conventions = {};
|
|
230
|
+
|
|
231
|
+
for (const file of conventionsFiles) {
|
|
232
|
+
const key = file.replace(/\.md$/, '').replace(/\//g, '-');
|
|
233
|
+
config.conventions[key] = `.team-flow/conventions/${file}`;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// ── 交互式引导 ─────────────────────────────────────────────────────────────
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* 交互式引导用户选择技术栈(全新项目)
|
|
243
|
+
* @returns {Promise<{ language: string, buildTool: string, testFramework: string, appFramework: string }>}
|
|
244
|
+
*/
|
|
245
|
+
export async function interactiveSetup() {
|
|
246
|
+
// 注意:在实际使用中,这里需要使用 readline 或 inquirer 等库
|
|
247
|
+
// 这里提供默认值,实际实现需要集成到 workflow-bootstrap 的交互流程中
|
|
248
|
+
console.log('\n=== 全新项目技术栈配置 ===\n');
|
|
249
|
+
console.log('由于当前为脚本模式,使用默认配置:');
|
|
250
|
+
console.log(' - 编程语言:Java');
|
|
251
|
+
console.log(' - 构建工具:Maven');
|
|
252
|
+
console.log(' - 测试框架:JUnit 5 + Mockito');
|
|
253
|
+
console.log(' - 应用框架:Spring Boot');
|
|
254
|
+
console.log('\n如需自定义配置,请在 workflow-bootstrap 中使用交互式模式。\n');
|
|
255
|
+
|
|
256
|
+
return {
|
|
257
|
+
language: 'java',
|
|
258
|
+
buildTool: 'maven',
|
|
259
|
+
testFramework: 'junit5-mockito',
|
|
260
|
+
appFramework: 'spring-boot',
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// ── CLI ─────────────────────────────────────────────────────────────────────
|
|
265
|
+
|
|
266
|
+
export async function run(args) {
|
|
267
|
+
const { positionals, values } = parseArgs({
|
|
268
|
+
args,
|
|
269
|
+
options: {
|
|
270
|
+
root: { type: 'string', default: '.' },
|
|
271
|
+
interactive: { type: 'boolean', default: false },
|
|
272
|
+
json: { type: 'boolean', default: false },
|
|
273
|
+
},
|
|
274
|
+
allowPositionals: true,
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
const root = path.resolve(values.root);
|
|
278
|
+
|
|
279
|
+
// 检查项目根目录
|
|
280
|
+
if (!existsSync(root)) {
|
|
281
|
+
console.error(`项目根目录不存在: ${root}`);
|
|
282
|
+
process.exit(1);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// 检查 conventions 是否已存在
|
|
286
|
+
const conventionsDir = join(root, '.team-flow', 'conventions');
|
|
287
|
+
if (existsSync(conventionsDir) && readdirSync(conventionsDir).length > 0) {
|
|
288
|
+
console.log('⚠️ conventions 已存在,跳过生成');
|
|
289
|
+
console.log(` 路径: ${conventionsDir}`);
|
|
290
|
+
process.exit(0);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// 检测技术栈
|
|
294
|
+
let techStack = detectTechStack(root);
|
|
295
|
+
|
|
296
|
+
// 如果未检测到技术栈且启用交互式模式
|
|
297
|
+
if (!techStack.language && values.interactive) {
|
|
298
|
+
techStack = await interactiveSetup();
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// 如果仍未检测到技术栈
|
|
302
|
+
if (!techStack.language) {
|
|
303
|
+
console.error('❌ 未检测到技术栈特征');
|
|
304
|
+
console.error(' 请指定项目根目录,或使用 --interactive 模式手动配置');
|
|
305
|
+
process.exit(1);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// 选择模板
|
|
309
|
+
const templates = selectTemplates(techStack);
|
|
310
|
+
|
|
311
|
+
if (templates.length === 0) {
|
|
312
|
+
console.error('❌ 未找到匹配的 conventions 模板');
|
|
313
|
+
console.error(` 技术栈: ${JSON.stringify(techStack)}`);
|
|
314
|
+
process.exit(1);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// 生成 conventions
|
|
318
|
+
const result = generateConventions(root, techStack, templates);
|
|
319
|
+
|
|
320
|
+
// 更新配置
|
|
321
|
+
updateConfig(root, result.created);
|
|
322
|
+
|
|
323
|
+
// 输出结果
|
|
324
|
+
if (values.json) {
|
|
325
|
+
console.log(JSON.stringify({
|
|
326
|
+
ok: true,
|
|
327
|
+
techStack,
|
|
328
|
+
templates,
|
|
329
|
+
created: result.created,
|
|
330
|
+
skipped: result.skipped,
|
|
331
|
+
conventionsDir,
|
|
332
|
+
}));
|
|
333
|
+
} else {
|
|
334
|
+
console.log('✅ conventions 生成完成');
|
|
335
|
+
console.log(` 技术栈: ${techStack.language} + ${techStack.testFramework}`);
|
|
336
|
+
console.log(` 创建: ${result.created.join(', ')}`);
|
|
337
|
+
if (result.skipped.length > 0) {
|
|
338
|
+
console.log(` 跳过: ${result.skipped.join(', ')}`);
|
|
339
|
+
}
|
|
340
|
+
console.log(` 路径: ${conventionsDir}`);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// 直接运行
|
|
345
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
346
|
+
run(process.argv.slice(2)).catch(err => {
|
|
347
|
+
console.error(err);
|
|
348
|
+
process.exit(1);
|
|
349
|
+
});
|
|
350
|
+
}
|