feat: 根目录文档、脚本、gitignore
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
pmassist-v3 session initializer
|
||||
初始化 pmassist-v3 会话工作目录与基础文件
|
||||
|
||||
用法:
|
||||
python3 skills/pmassist-v3/scripts/init_session.py \
|
||||
--path <workdir> \
|
||||
--doc prd|frd|dar \
|
||||
--alias <简称> \
|
||||
--title <标题> \
|
||||
--desc <原始需求> \
|
||||
[--enable-prototype] \
|
||||
[--enable-acceptance]
|
||||
"""
|
||||
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
DOC_MAP = {
|
||||
"prd": "prd.md",
|
||||
"frd": "frd.md",
|
||||
"dar": "dar.md",
|
||||
}
|
||||
|
||||
|
||||
def now_ts():
|
||||
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
|
||||
def read_template(doc_type: str, skill_dir: Path) -> str:
|
||||
ref_name = DOC_MAP[doc_type]
|
||||
ref_path = skill_dir / "references" / ref_name
|
||||
if ref_path.exists():
|
||||
return ref_path.read_text(encoding="utf-8")
|
||||
return f"# {doc_type.upper()}\n\n> 模板缺失,请手动补充。\n"
|
||||
|
||||
|
||||
def read_acceptance_template(skill_dir: Path) -> str:
|
||||
ref_path = skill_dir / "references" / "acceptance_template.md"
|
||||
if ref_path.exists():
|
||||
return ref_path.read_text(encoding="utf-8")
|
||||
return "# 验收标准(Acceptance Criteria)\n\n> 按 Given/When/Then 格式填写。\n"
|
||||
|
||||
|
||||
def write_file(path: Path, content: str, force: bool = False) -> bool:
|
||||
if path.exists() and not force:
|
||||
return False
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_text(content, encoding="utf-8")
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Initialize pmassist-v3 session workspace"
|
||||
)
|
||||
parser.add_argument("--path", required=True, help="Work directory path")
|
||||
parser.add_argument(
|
||||
"--doc", required=True, choices=["prd", "frd", "dar"], help="Document type"
|
||||
)
|
||||
parser.add_argument("--alias", default="", help="Project alias (short name)")
|
||||
parser.add_argument("--title", default="", help="Document title")
|
||||
parser.add_argument("--desc", default="", help="Raw requirement description")
|
||||
parser.add_argument("--force", action="store_true", help="Overwrite existing files")
|
||||
parser.add_argument(
|
||||
"--enable-prototype",
|
||||
action="store_true",
|
||||
help="Enable prototype design phase",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--enable-acceptance",
|
||||
action="store_true",
|
||||
help="Pre-create acceptance.md for Given/When/Then AC output",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
workdir = Path(args.path).resolve()
|
||||
workdir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Skill 根目录(脚本位于 scripts/ 下)
|
||||
skill_dir = Path(__file__).resolve().parent.parent
|
||||
|
||||
# ── 基础目录 ──────────────────────────────────────
|
||||
base_dirs = ["materials", "rounds", "questions", "outputs"]
|
||||
|
||||
# ── 原型目录(可选)──────────────────────────────
|
||||
proto_dirs = [
|
||||
"materials/prototypes",
|
||||
"materials/prototypes/reference",
|
||||
"materials/prototypes/analysis",
|
||||
"prototypes",
|
||||
"prototypes/screenshots",
|
||||
"prototypes/webapp",
|
||||
]
|
||||
|
||||
dirs_to_create = base_dirs + (proto_dirs if args.enable_prototype else [])
|
||||
for d in dirs_to_create:
|
||||
(workdir / d).mkdir(parents=True, exist_ok=True)
|
||||
|
||||
ts = now_ts()
|
||||
alias = args.alias or ""
|
||||
title = args.title or ""
|
||||
raw_desc = args.desc or ""
|
||||
|
||||
# ── desc.md ──────────────────────────────────────
|
||||
desc_md = f"""# 需求描述
|
||||
|
||||
## 元信息
|
||||
- 创建时间: {ts}
|
||||
- 最后更新: {ts}
|
||||
- 文档类型: {args.doc.upper()}
|
||||
- 项目简称: {alias}
|
||||
- 标题: {title}
|
||||
|
||||
## 原始输入
|
||||
{raw_desc if raw_desc else '[待补充原始需求]'}
|
||||
|
||||
## WWH 分析
|
||||
|
||||
### What - 做什么
|
||||
[待补充]
|
||||
|
||||
### Why - 为什么
|
||||
[待补充]
|
||||
|
||||
### How - 怎么做
|
||||
[待补充]
|
||||
"""
|
||||
|
||||
# ── session.yaml ─────────────────────────────────
|
||||
proto_section = ""
|
||||
if args.enable_prototype:
|
||||
proto_section = """
|
||||
prototype:
|
||||
enabled: true
|
||||
status: "proto_pending"
|
||||
proto_round: 0
|
||||
tech_stack: []
|
||||
outputs: []
|
||||
unresolved_proto_questions: []
|
||||
"""
|
||||
|
||||
session_yaml = f"""project_alias: "{alias}"
|
||||
doc_type: "{args.doc}"
|
||||
title: "{title}"
|
||||
created_at: "{ts}"
|
||||
updated_at: "{ts}"
|
||||
|
||||
round: 0
|
||||
status: "init"
|
||||
|
||||
# 功能需求统计(v3 新增)
|
||||
fr_count: 0
|
||||
ac_count: 0
|
||||
ac_coverage: "0/0"
|
||||
|
||||
# 未解决问题
|
||||
unresolved_questions: []
|
||||
|
||||
# 跳过标记
|
||||
skip_flags:
|
||||
prototype: {'true' if not args.enable_prototype else 'false'}
|
||||
ac_batch: false
|
||||
diff_list: false
|
||||
|
||||
last_output: ""
|
||||
materials: []{proto_section}
|
||||
"""
|
||||
|
||||
# ── summary.md ───────────────────────────────────
|
||||
summary_md = f"""# 会话摘要
|
||||
|
||||
- {ts} 初始化 pmassist-v3 会话
|
||||
- 文档类型:{args.doc.upper()}
|
||||
- 项目:{alias or '(未设置)'}
|
||||
"""
|
||||
|
||||
# ── decision_log.md ──────────────────────────────
|
||||
decision_log_md = """# 决策记录
|
||||
|
||||
| 时间 | 变更编号 | 事项 | 决策内容 | 影响 FR | 依据 |
|
||||
|---|---|---|---|---|---|
|
||||
"""
|
||||
|
||||
# ── materials_index.md ───────────────────────────
|
||||
materials_index_md = """# 资料索引
|
||||
|
||||
| ID | 标题 | 类型 | 来源/路径 | 摘要 | 日期 |
|
||||
|---|---|---|---|---|---|
|
||||
"""
|
||||
|
||||
# ── 输出文档模板 ──────────────────────────────────
|
||||
output_template = read_template(args.doc, skill_dir)
|
||||
|
||||
# ── acceptance.md(可选,PRD/FRD 推荐)──────────
|
||||
acceptance_template = read_acceptance_template(skill_dir)
|
||||
|
||||
# ── 写文件 ────────────────────────────────────────
|
||||
wrote = []
|
||||
|
||||
def wf(rel_path: str, content: str):
|
||||
if write_file(workdir / rel_path, content, args.force):
|
||||
wrote.append(rel_path)
|
||||
|
||||
wf("desc.md", desc_md)
|
||||
wf("session.yaml", session_yaml)
|
||||
wf("summary.md", summary_md)
|
||||
wf("decision_log.md", decision_log_md)
|
||||
wf("materials_index.md", materials_index_md)
|
||||
wf(f"outputs/{DOC_MAP[args.doc]}", output_template)
|
||||
|
||||
# 验收标准(按需或 PRD/FRD 默认启用)
|
||||
if args.enable_acceptance or args.doc in ("prd", "frd"):
|
||||
wf("outputs/acceptance.md", acceptance_template)
|
||||
|
||||
if wrote:
|
||||
print("[OK] pmassist-v3 会话初始化完成,创建/更新文件:")
|
||||
for f in wrote:
|
||||
print(f" - {f}")
|
||||
print(f"\n工作目录:{workdir}")
|
||||
print(f"下一步:加载 pmassist-v3 skill,开始 Round 1 PDCA。")
|
||||
else:
|
||||
print("[SKIP] 无文件变更。使用 --force 覆盖已有文件。")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user