paseo-req-kit 1.12.1 → 1.13.0-beta.1
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/CHANGELOG.md +16 -0
- package/README.md +8 -3
- package/bin/bootstrap.d.mts +12 -0
- package/bin/bootstrap.mjs +418 -0
- package/bin/req-docs.d.mts +5 -0
- package/bin/req-docs.mjs +169 -0
- package/bin/req.mjs +12 -1
- package/docs/adr/0032-npm-only-install.md +27 -0
- package/docs/adr/README.md +1 -0
- package/docs/guide//345/256/211/350/243/205/344/270/216/345/215/207/347/272/247.md +22 -2
- package/package.json +3 -1
- package/paseo-plugin/package.json +1 -1
- package/site-dist/404.html +27 -0
- package/site-dist/assets/app.C_2Vhmv-.js +1 -0
- package/site-dist/assets/changelog.md.VHiXRXap.js +1 -0
- package/site-dist/assets/changelog.md.VHiXRXap.lean.js +1 -0
- package/site-dist/assets/chunks/@localSearchIndexroot.hC_y1UNZ.js +1 -0
- package/site-dist/assets/chunks/VPLocalSearchBox.zPMXlb4V.js +9 -0
- package/site-dist/assets/chunks/framework.B9qR_F1m.js +20 -0
- package/site-dist/assets/chunks/theme.DRjHgCIR.js +2 -0
- package/site-dist/assets/guide_getting-started.md.DjqrOQ_8.js +6 -0
- package/site-dist/assets/guide_getting-started.md.DjqrOQ_8.lean.js +1 -0
- package/site-dist/assets/guide_how-it-works.md.D-kQsF1t.js +25 -0
- package/site-dist/assets/guide_how-it-works.md.D-kQsF1t.lean.js +1 -0
- package/site-dist/assets/guide_index.md.CLnGCmGW.js +1 -0
- package/site-dist/assets/guide_index.md.CLnGCmGW.lean.js +1 -0
- package/site-dist/assets/guide_install.md.DkCyZsOU.js +42 -0
- package/site-dist/assets/guide_install.md.DkCyZsOU.lean.js +42 -0
- package/site-dist/assets/guide_maintainer.md.C7Aav_lk.js +1 -0
- package/site-dist/assets/guide_maintainer.md.C7Aav_lk.lean.js +1 -0
- package/site-dist/assets/guide_phases.md.BpGAb1re.js +1 -0
- package/site-dist/assets/guide_phases.md.BpGAb1re.lean.js +1 -0
- package/site-dist/assets/guide_project.md.r2g5uU_4.js +77 -0
- package/site-dist/assets/guide_project.md.r2g5uU_4.lean.js +77 -0
- package/site-dist/assets/guide_user.md.FpCmz9S0.js +1 -0
- package/site-dist/assets/guide_user.md.FpCmz9S0.lean.js +1 -0
- package/site-dist/assets/index.md.Cf_sSf_f.js +1 -0
- package/site-dist/assets/index.md.Cf_sSf_f.lean.js +1 -0
- package/site-dist/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
- package/site-dist/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
- package/site-dist/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
- package/site-dist/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
- package/site-dist/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
- package/site-dist/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
- package/site-dist/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
- package/site-dist/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
- package/site-dist/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
- package/site-dist/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
- package/site-dist/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
- package/site-dist/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
- package/site-dist/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
- package/site-dist/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
- package/site-dist/assets/reference_adr_0001-step-agents-under-origin-chat.md.RtRTq7oi.js +1 -0
- package/site-dist/assets/reference_adr_0001-step-agents-under-origin-chat.md.RtRTq7oi.lean.js +1 -0
- package/site-dist/assets/reference_adr_0002-no-directory-switch-in-chat.md.BxtN-Aa2.js +1 -0
- package/site-dist/assets/reference_adr_0002-no-directory-switch-in-chat.md.BxtN-Aa2.lean.js +1 -0
- package/site-dist/assets/reference_adr_0003-script-engine-not-hub.md.66EgZtqx.js +1 -0
- package/site-dist/assets/reference_adr_0003-script-engine-not-hub.md.66EgZtqx.lean.js +1 -0
- package/site-dist/assets/reference_adr_0004-result-files.md.DbqcCozI.js +1 -0
- package/site-dist/assets/reference_adr_0004-result-files.md.DbqcCozI.lean.js +1 -0
- package/site-dist/assets/reference_adr_0005-no-default-branch-local-commits-only.md.CkImA4s6.js +1 -0
- package/site-dist/assets/reference_adr_0005-no-default-branch-local-commits-only.md.CkImA4s6.lean.js +1 -0
- package/site-dist/assets/reference_adr_0006-skill-install-targets.md.CwY8YepV.js +1 -0
- package/site-dist/assets/reference_adr_0006-skill-install-targets.md.CwY8YepV.lean.js +1 -0
- package/site-dist/assets/reference_adr_0007-own-interview-skill.md.CryhxRyG.js +1 -0
- package/site-dist/assets/reference_adr_0007-own-interview-skill.md.CryhxRyG.lean.js +1 -0
- package/site-dist/assets/reference_adr_0008-entries-do-not-call-entries.md.DsRWAgeA.js +1 -0
- package/site-dist/assets/reference_adr_0008-entries-do-not-call-entries.md.DsRWAgeA.lean.js +1 -0
- package/site-dist/assets/reference_adr_0009-versioned-install-layout.md.CSg1VqlW.js +1 -0
- package/site-dist/assets/reference_adr_0009-versioned-install-layout.md.CSg1VqlW.lean.js +1 -0
- package/site-dist/assets/reference_adr_0010-generated-feature-overview.md.D8F3MK-h.js +1 -0
- package/site-dist/assets/reference_adr_0010-generated-feature-overview.md.D8F3MK-h.lean.js +1 -0
- package/site-dist/assets/reference_adr_0011-resume-after-completion.md.BCrZrKjf.js +1 -0
- package/site-dist/assets/reference_adr_0011-resume-after-completion.md.BCrZrKjf.lean.js +1 -0
- package/site-dist/assets/reference_adr_0012-review-panel.md.k9rrHFFc.js +1 -0
- package/site-dist/assets/reference_adr_0012-review-panel.md.k9rrHFFc.lean.js +1 -0
- package/site-dist/assets/reference_adr_0013-no-release-tooling.md.BQeJ8dEI.js +1 -0
- package/site-dist/assets/reference_adr_0013-no-release-tooling.md.BQeJ8dEI.lean.js +1 -0
- package/site-dist/assets/reference_adr_0014-notifier-slot.md.C23QR1xO.js +1 -0
- package/site-dist/assets/reference_adr_0014-notifier-slot.md.C23QR1xO.lean.js +1 -0
- package/site-dist/assets/reference_adr_0015-incremental-continue.md.Buy7wwO8.js +1 -0
- package/site-dist/assets/reference_adr_0015-incremental-continue.md.Buy7wwO8.lean.js +1 -0
- package/site-dist/assets/reference_adr_0016-upgrade-from-tags.md.qfIW-tqJ.js +1 -0
- package/site-dist/assets/reference_adr_0016-upgrade-from-tags.md.qfIW-tqJ.lean.js +1 -0
- package/site-dist/assets/reference_adr_0017-use-paseo-capabilities.md.CjcGli87.js +1 -0
- package/site-dist/assets/reference_adr_0017-use-paseo-capabilities.md.CjcGli87.lean.js +1 -0
- package/site-dist/assets/reference_adr_0018-own-worktree-option.md.fVDpgGSE.js +1 -0
- package/site-dist/assets/reference_adr_0018-own-worktree-option.md.fVDpgGSE.lean.js +1 -0
- package/site-dist/assets/reference_adr_0019-parallel-orchestration.md.DrfrV0To.js +1 -0
- package/site-dist/assets/reference_adr_0019-parallel-orchestration.md.DrfrV0To.lean.js +1 -0
- package/site-dist/assets/reference_adr_0020-scheduling-through-the-chat.md.BqSemGFG.js +1 -0
- package/site-dist/assets/reference_adr_0020-scheduling-through-the-chat.md.BqSemGFG.lean.js +1 -0
- package/site-dist/assets/reference_adr_0021-npm-version-manager.md.CU3PG6y5.js +1 -0
- package/site-dist/assets/reference_adr_0021-npm-version-manager.md.CU3PG6y5.lean.js +1 -0
- package/site-dist/assets/reference_adr_0022-develop-and-verify-phases.md.C6fQDLq4.js +1 -0
- package/site-dist/assets/reference_adr_0022-develop-and-verify-phases.md.C6fQDLq4.lean.js +1 -0
- package/site-dist/assets/reference_adr_0023-types-gate-slices.md.D2E6yyYQ.js +1 -0
- package/site-dist/assets/reference_adr_0023-types-gate-slices.md.D2E6yyYQ.lean.js +1 -0
- package/site-dist/assets/reference_adr_0024-confirm-early-review-axes.md.FmK_ke0x.js +1 -0
- package/site-dist/assets/reference_adr_0024-confirm-early-review-axes.md.FmK_ke0x.lean.js +1 -0
- package/site-dist/assets/reference_adr_0025-joint-requirements.md.ChoKvMUx.js +1 -0
- package/site-dist/assets/reference_adr_0025-joint-requirements.md.ChoKvMUx.lean.js +1 -0
- package/site-dist/assets/reference_adr_0026-machine-records-and-api.md.veybjBPq.js +1 -0
- package/site-dist/assets/reference_adr_0026-machine-records-and-api.md.veybjBPq.lean.js +1 -0
- package/site-dist/assets/reference_adr_0027-paseo-plugin.md.BMX33ZNU.js +1 -0
- package/site-dist/assets/reference_adr_0027-paseo-plugin.md.BMX33ZNU.lean.js +1 -0
- package/site-dist/assets/reference_adr_0028-external-integrations.md.DtdMe8RK.js +1 -0
- package/site-dist/assets/reference_adr_0028-external-integrations.md.DtdMe8RK.lean.js +1 -0
- package/site-dist/assets/reference_adr_0029-requirements-from-cards.md.BHd1SQPe.js +1 -0
- package/site-dist/assets/reference_adr_0029-requirements-from-cards.md.BHd1SQPe.lean.js +1 -0
- package/site-dist/assets/reference_adr_0030-card-intake-process.md.kLc-DG9_.js +1 -0
- package/site-dist/assets/reference_adr_0030-card-intake-process.md.kLc-DG9_.lean.js +1 -0
- package/site-dist/assets/reference_adr_0031-fewer-interventions.md.BDnQcz8g.js +1 -0
- package/site-dist/assets/reference_adr_0031-fewer-interventions.md.BDnQcz8g.lean.js +1 -0
- package/site-dist/assets/reference_adr_0032-npm-only-install.md.C-3L1FkX.js +1 -0
- package/site-dist/assets/reference_adr_0032-npm-only-install.md.C-3L1FkX.lean.js +1 -0
- package/site-dist/assets/reference_adr_index.md.DTVyIA6V.js +1 -0
- package/site-dist/assets/reference_adr_index.md.DTVyIA6V.lean.js +1 -0
- package/site-dist/assets/reference_commands.md.ClKbS-t8.js +1 -0
- package/site-dist/assets/reference_commands.md.ClKbS-t8.lean.js +1 -0
- package/site-dist/assets/reference_config.md.CRe27LaA.js +6 -0
- package/site-dist/assets/reference_config.md.CRe27LaA.lean.js +1 -0
- package/site-dist/assets/reference_contracts_cli-json.md.gkER6rX7.js +1 -0
- package/site-dist/assets/reference_contracts_cli-json.md.gkER6rX7.lean.js +1 -0
- package/site-dist/assets/reference_contracts_feature-files.md.DSiA8OEH.js +26 -0
- package/site-dist/assets/reference_contracts_feature-files.md.DSiA8OEH.lean.js +26 -0
- package/site-dist/assets/reference_contracts_index.md.Bkznz4px.js +1 -0
- package/site-dist/assets/reference_contracts_index.md.Bkznz4px.lean.js +1 -0
- package/site-dist/assets/reference_contracts_notifier-event.md.CCfrkm_A.js +24 -0
- package/site-dist/assets/reference_contracts_notifier-event.md.CCfrkm_A.lean.js +24 -0
- package/site-dist/assets/reference_contracts_result-file.md.DmR4fjB-.js +1 -0
- package/site-dist/assets/reference_contracts_result-file.md.DmR4fjB-.lean.js +1 -0
- package/site-dist/assets/reference_contracts_spec.md.BwwS0L_j.js +8 -0
- package/site-dist/assets/reference_contracts_spec.md.BwwS0L_j.lean.js +8 -0
- package/site-dist/assets/reference_contracts_state.md.5bNTC3ow.js +1 -0
- package/site-dist/assets/reference_contracts_state.md.5bNTC3ow.lean.js +1 -0
- package/site-dist/assets/reference_contracts_usage-record.md._C0OXWeq.js +10 -0
- package/site-dist/assets/reference_contracts_usage-record.md._C0OXWeq.lean.js +10 -0
- package/site-dist/assets/reference_contracts_verify.md.CbA88u6S.js +29 -0
- package/site-dist/assets/reference_contracts_verify.md.CbA88u6S.lean.js +29 -0
- package/site-dist/assets/reference_scope.md.Kzqw8U_f.js +1 -0
- package/site-dist/assets/reference_scope.md.Kzqw8U_f.lean.js +1 -0
- package/site-dist/assets/style.Dwsa4SMe.css +1 -0
- package/site-dist/changelog.html +30 -0
- package/site-dist/guide/getting-started.html +35 -0
- package/site-dist/guide/how-it-works.html +54 -0
- package/site-dist/guide/index.html +30 -0
- package/site-dist/guide/install.html +71 -0
- package/site-dist/guide/maintainer.html +30 -0
- package/site-dist/guide/phases.html +30 -0
- package/site-dist/guide/project.html +106 -0
- package/site-dist/guide/user.html +30 -0
- package/site-dist/hashmap.json +1 -0
- package/site-dist/icons/agents.svg +1 -0
- package/site-dist/icons/chat.svg +1 -0
- package/site-dist/icons/paseo.svg +1 -0
- package/site-dist/icons/phases.svg +1 -0
- package/site-dist/icons/review.svg +1 -0
- package/site-dist/icons/safe.svg +1 -0
- package/site-dist/index.html +30 -0
- package/site-dist/install.ps1 +118 -0
- package/site-dist/install.sh +198 -0
- package/site-dist/logo.svg +11 -0
- package/site-dist/reference/adr/0001-step-agents-under-origin-chat.html +30 -0
- package/site-dist/reference/adr/0002-no-directory-switch-in-chat.html +30 -0
- package/site-dist/reference/adr/0003-script-engine-not-hub.html +30 -0
- package/site-dist/reference/adr/0004-result-files.html +30 -0
- package/site-dist/reference/adr/0005-no-default-branch-local-commits-only.html +30 -0
- package/site-dist/reference/adr/0006-skill-install-targets.html +30 -0
- package/site-dist/reference/adr/0007-own-interview-skill.html +30 -0
- package/site-dist/reference/adr/0008-entries-do-not-call-entries.html +30 -0
- package/site-dist/reference/adr/0009-versioned-install-layout.html +30 -0
- package/site-dist/reference/adr/0010-generated-feature-overview.html +30 -0
- package/site-dist/reference/adr/0011-resume-after-completion.html +30 -0
- package/site-dist/reference/adr/0012-review-panel.html +30 -0
- package/site-dist/reference/adr/0013-no-release-tooling.html +30 -0
- package/site-dist/reference/adr/0014-notifier-slot.html +30 -0
- package/site-dist/reference/adr/0015-incremental-continue.html +30 -0
- package/site-dist/reference/adr/0016-upgrade-from-tags.html +30 -0
- package/site-dist/reference/adr/0017-use-paseo-capabilities.html +30 -0
- package/site-dist/reference/adr/0018-own-worktree-option.html +30 -0
- package/site-dist/reference/adr/0019-parallel-orchestration.html +30 -0
- package/site-dist/reference/adr/0020-scheduling-through-the-chat.html +30 -0
- package/site-dist/reference/adr/0021-npm-version-manager.html +30 -0
- package/site-dist/reference/adr/0022-develop-and-verify-phases.html +30 -0
- package/site-dist/reference/adr/0023-types-gate-slices.html +30 -0
- package/site-dist/reference/adr/0024-confirm-early-review-axes.html +30 -0
- package/site-dist/reference/adr/0025-joint-requirements.html +30 -0
- package/site-dist/reference/adr/0026-machine-records-and-api.html +30 -0
- package/site-dist/reference/adr/0027-paseo-plugin.html +30 -0
- package/site-dist/reference/adr/0028-external-integrations.html +30 -0
- package/site-dist/reference/adr/0029-requirements-from-cards.html +30 -0
- package/site-dist/reference/adr/0030-card-intake-process.html +30 -0
- package/site-dist/reference/adr/0031-fewer-interventions.html +30 -0
- package/site-dist/reference/adr/0032-npm-only-install.html +30 -0
- package/site-dist/reference/adr/index.html +30 -0
- package/site-dist/reference/commands.html +30 -0
- package/site-dist/reference/config.html +35 -0
- package/site-dist/reference/contracts/cli-json.html +30 -0
- package/site-dist/reference/contracts/feature-files.html +55 -0
- package/site-dist/reference/contracts/index.html +30 -0
- package/site-dist/reference/contracts/notifier-event.html +53 -0
- package/site-dist/reference/contracts/result-file.html +30 -0
- package/site-dist/reference/contracts/spec.html +37 -0
- package/site-dist/reference/contracts/state.html +30 -0
- package/site-dist/reference/contracts/usage-record.html +39 -0
- package/site-dist/reference/contracts/verify.html +58 -0
- package/site-dist/reference/scope.html +30 -0
- package/site-dist/vp-icons.css +1 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import{_ as e,o as a,c as n,j as i,a as l}from"./chunks/framework.B9qR_F1m.js";const o=JSON.parse('{"title":"项目定制与运行规则","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"guide/project.md","filePath":"guide/project.md","lastUpdated":null}'),t={name:"guide/project.md"};function h(k,s,d,r,E,p){return a(),n("div",null,[...s[0]||(s[0]=[i("div",null,[i("h1",{id:"项目定制与运行规则",tabindex:"-1"},[l("项目定制与运行规则 "),i("a",{class:"header-anchor",href:"#项目定制与运行规则","aria-label":'Permalink to "项目定制与运行规则"'},"")]),i("h2",{id:"每个需求一个-worktree-工作区",tabindex:"-1"},[l("每个需求一个 worktree 工作区 "),i("a",{class:"header-anchor",href:"#每个需求一个-worktree-工作区","aria-label":'Permalink to "每个需求一个 worktree 工作区"'},"")]),i("p",null,[l("在 Paseo 中为每个需求新建工作区:"),i("strong",null,"New workspace"),l(" → 选择项目 → "),i("strong",null,"Isolation"),l(" 选 "),i("strong",null,"New worktree"),l(" → 起点选主分支,然后在这个工作区的对话里输入 "),i("code",null,"/req"),l("。")]),i("ul",null,[i("li",null,"流水线在这个工作区自己的目录和分支上运行、提交,不影响项目主目录。"),i("li",null,"同一个目录一次只能运行一条流水线;用了 worktree,几个需求可以同时进行。"),i("li",null,[l("在主目录发起时,"),i("code",null,"/req"),l(" 会先建议改用 worktree;使用者坚持的话,它会新建 "),i("code",null,"feature/<功能目录名>"),l(" 分支再继续。")])]),i("p",null,[i("strong",null,"分支规则"),l(":流水线把启动时检出的分支作为本次需求的工作分支,所有步骤都提交到这里,不切换、不新建分支。它拒绝在默认分支("),i("code",null,"main"),l("、"),i("code",null,"master"),l(" 或 "),i("code",null,"origin/HEAD"),l(" 指向的分支)或 detached HEAD 上启动;续跑时分支变了也会拒绝。")]),i("h2",{id:"档位",tabindex:"-1"},[l("档位 "),i("a",{class:"header-anchor",href:"#档位","aria-label":'Permalink to "档位"'},"")]),i("table",{tabindex:"0"},[i("thead",null,[i("tr",null,[i("th",null,"档位"),i("th",null,"适用"),i("th",null,"访谈"),i("th",null,"流程")])]),i("tbody",null,[i("tr",null,[i("td",null,[l("快速("),i("code",null,"quick"),l(")")]),i("td",null,"小改动:文案、样式、配置项、字段显示等,不涉及数据结构、权限、对外接口"),i("td",null,"只问要改什么、改成什么样、不改什么、验收标准"),i("td",null,"审核、评审、缺陷修复各一轮;不做服务启动验证;产物从简")]),i("tr",null,[i("td",null,[l("标准("),i("code",null,"standard"),l(")")]),i("td",null,"其他情况"),i("td",null,"完整访谈"),i("td",null,"审核最多 2 轮、评审最多 3 轮、缺陷修复最多 3 轮")])])]),i("p",null,[i("code",null,"/req"),l(" 会根据需求推荐档位,用户确认后写进 spec("),i("code",null,"- 档位:快速"),l(")。流水线按以下顺序决定档位:"),i("code",null,"--profile"),l(" 参数 → 续跑时沿用上次的档位 → spec 中的档位 → 配置中的 "),i("code",null,"defaultProfile"),l("。各档的轮数和是否做服务启动验证可以在配置的 "),i("code",null,"profiles"),l(" 中调整。")]),i("h2",{id:"需求类型",tabindex:"-1"},[l("需求类型 "),i("a",{class:"header-anchor",href:"#需求类型","aria-label":'Permalink to "需求类型"'},"")]),i("p",null,[l("spec 头部的 "),i("code",null,"- 类型:"),l(" 决定流水线走哪种做法(1.8 起)。缺陷、重构、评估有自己的做法,新需求和小改动走通常的流程:")]),i("table",{tabindex:"0"},[i("thead",null,[i("tr",null,[i("th",null,"类型"),i("th",null,"做法"),i("th",null,"关键证据")])]),i("tbody",null,[i("tr",null,[i("td",null,[l("缺陷("),i("code",null,"缺陷"),l("、"),i("code",null,"bug"),l(")")]),i("td",null,[l('方案设计改为"复现与定位":先提交一个修复前失败的复现测试或脚本,写 '),i("code",null,"diagnosis.md"),l("(根因、影响面);复现不了就暂停,把需要补充的信息发回对话。修复要让复现转绿,评审实际确认它修复前失败")]),i("td",null,"同一个复现,修复前失败、修复后通过")]),i("tr",null,[i("td",null,[l("重构("),i("code",null,"重构"),l("、"),i("code",null,"技术改进"),l(")")]),i("td",null,'先补特征测试锁住现有行为并单独提交,再小步改动、每步全绿;评审的首要问题是"行为有没有变"'),i("td",null,"重构前后同一组测试一致")]),i("tr",null,[i("td",null,[l("评估("),i("code",null,"评估"),l("、"),i("code",null,"调研"),l(")")]),i("td",null,[l("只读:调研评估("),i("code",null,"assessment.md"),l(")→ 评估审阅 ⇄ 修订 → 评估报告;没有实现、评审、提测和验证,执行方式按连续")]),i("td",null,"引用的代码位置和实际运行的命令")])])]),i("p",null,[l("各类型的做法写在 "),i("code",null,"engine/prompts/types/<类型>.md"),l(",按步骤分节,接在每一步的任务之后;可以用 "),i("code",null,"prompts.local/types/"),l(" 覆盖。不想用某个类型的做法时,从配置 "),i("code",null,"requirementTypes"),l("(默认 "),i("code",null,'["defect", "refactor", "assessment"]'),l(")中去掉它,这个类型就按新需求处理。设计决定见 ADR 0023。")]),i("h2",{id:"方案确认点-开工前请需求方确认-做完后会看到什么",tabindex:"-1"},[l('方案确认点:开工前请需求方确认"做完后会看到什么" '),i("a",{class:"header-anchor",href:"#方案确认点-开工前请需求方确认-做完后会看到什么","aria-label":'Permalink to "方案确认点:开工前请需求方确认"做完后会看到什么""'},"")]),i("p",null,[l("方案审核通过后、写代码之前,流水线可以停下来请需求方确认(1.8 起)。方案设计写 "),i("code",null,"preview.md"),l("(按操作顺序描述做完后会看到什么、需要确认的假设、不会变的地方),界面改动还在 "),i("code",null,"prototype/"),l(" 中画出静态的原型页面。对话里的 AI 把要点讲给需求方:确认后执行 "),i("code",null,"--approve"),l("(终端里 "),i("code",null,"req approve <需求>"),l(")开始写代码;要改的,更新需求说明后 "),i("code",null,"--resume"),l(",方案调整后再确认一次。需求方确认过的预览和原型,实现和功能验证都以它为准:界面与原型不一致按缺陷处理。")]),i("table",{tabindex:"0"},[i("thead",null,[i("tr",null,[i("th",null,"配置"),i("th",null,"默认"),i("th",null,"说明")])]),i("tbody",null,[i("tr",null,[i("td",null,[i("code",null,"designApproval.mode")]),i("td",null,[i("code",null,"ui")]),i("td",null,[i("code",null,"ui"),l(":方案判断这次是界面改动(结果文件 "),i("code",null,"ui_change"),l(")时才停;"),i("code",null,"always"),l(":每次都停;"),i("code",null,"off"),l(":不停")])]),i("tr",null,[i("td",null,[i("code",null,"designApproval.profiles")]),i("td",null,[i("code",null,'["standard"]')]),i("td",null,"哪些档位使用;快速档默认不停")]),i("tr",null,[i("td",null,[i("code",null,"designApproval.autoContinueHours")]),i("td",null,"0"),i("td",null,[l("大于 0 时,等了这么久还没确认就按方案继续(通过对话执行);0 表示一直等待。等待超过 "),i("code",null,"waitingReminderHours"),l(" 会提醒一次")])])])]),i("p",null,[l('等待确认时进度显示"等待需求方确认方案",需求总览归入"需要处理",外部通知收到 '),i("code",null,"approval"),l(" 事件。评估类需求不写代码,不经过确认点。")]),i("h2",{id:"代码评审分两个方向",tabindex:"-1"},[l("代码评审分两个方向 "),i("a",{class:"header-anchor",href:"#代码评审分两个方向","aria-label":'Permalink to "代码评审分两个方向"'},"")]),i("p",null,"标准档第一轮代码评审由两位评审者同时进行(1.8 起),各自写意见,再由 reviewer 核实、汇总成一份结论:"),i("ul",null,[i("li",null,[i("strong",null,"规格评审"),l(":每条验收标准是否真的实现并有测试、测试的期望值是否与验收标准的例子一致、有没有做需求之外的事、与确认过的预览是否一致。")]),i("li",null,[i("strong",null,"规范评审"),l(":项目惯例和范例文件、术语表中的代码名称、测试质量、安全与数据、简单性,以及可以变成规则的问题。")])]),i("p",null,[l("两位都用配置的 reviewer agent,相当于多两次评审的用量;之后的轮次只核对修复,仍由一位评审。"),i("code",null,"reviewAxes.enabled"),l(" 设为 "),i("code",null,"false"),l(" 关闭,"),i("code",null,"reviewAxes.profiles"),l(" 选择档位(默认只有标准档)。配置了评审小组("),i("code",null,"reviewPanel"),l(")时,以评审小组为准。")]),i("h2",{id:"验收测试先提交",tabindex:"-1"},[l("验收测试先提交 "),i("a",{class:"header-anchor",href:"#验收测试先提交","aria-label":'Permalink to "验收测试先提交"'},"")]),i("p",null,"方案判断适合测试先行时,代码实现先把从验收标准的例子写出的测试单独提交一次(这时它们是失败的),在结果文件中写明这些测试文件和那次提交。代码评审前,流水线核对它们之后有没有被改过,被改过的交给评审逐个确认有没有依据:为了让测试通过而放宽断言的,按阻塞提出。"),i("h2",{id:"术语表和范例文件",tabindex:"-1"},[l("术语表和范例文件 "),i("a",{class:"header-anchor",href:"#术语表和范例文件","aria-label":'Permalink to "术语表和范例文件"'},"")]),i("ul",null,[i("li",null,[i("strong",null,[i("code",null,"GLOSSARY.md")]),l("(仓库根目录):业务词、含义、代码中的名字。"),i("code",null,"/req-setup"),l(" 第一次整理,访谈遇到新词时补充,方案设计为新概念补上代码中的名字;各步骤按它命名,规范评审检查是否一致。")]),i("li",null,[i("strong",null,"范例文件"),l(":"),i("code",null,"/req-setup"),l(" 在 "),i("code",null,"project-notes.md"),l(" 中列出各类代码(接口、页面、测试、迁移脚本)写得最好的文件。方案的每个任务写明参照哪个文件,实现照它的结构、命名、错误处理和测试写法来。")])]),i("h2",{id:"反复出现的问题变成规则",tabindex:"-1"},[l("反复出现的问题变成规则 "),i("a",{class:"header-anchor",href:"#反复出现的问题变成规则","aria-label":'Permalink to "反复出现的问题变成规则"'},"")]),i("p",null,[l('完成报告把这次评审、质量门、缺陷中"一条项目规则就能挡住"的问题写进功能目录的 '),i("code",null,"lessons.tsv"),l("(类别、问题、出处、建议的规则、放在哪一层)。同一个类别在两个以上的需求里出现时,"),i("code",null,"req digest"),l(' 的需求总览会列在"反复出现的问题"中,'),i("code",null,"/req-retro"),l(" 会建议把它变成 lint 规则、类型约束、测试或项目说明里的一行,批准后落地。已经处理的类别写进 "),i("code",null,".requirement-pipeline/lessons-handled.txt"),l("(一行一个),总览不再提示。")]),i("h2",{id:"质量门-流水线自己运行的检查",tabindex:"-1"},[l("质量门:流水线自己运行的检查 "),i("a",{class:"header-anchor",href:"#质量门-流水线自己运行的检查","aria-label":'Permalink to "质量门:流水线自己运行的检查"'},"")]),i("p",null,[l("项目配置 "),i("code",null,".requirement-pipeline.json"),l(" 的 "),i("code",null,"checks"),l(" 列出流水线"),i("strong",null,"自己运行"),l("的检查,通常由 "),i("code",null,"/req-setup"),l(" 从实际跑通的命令写入:")]),i("div",{class:"language-json vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"json"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"{")]),l(`
|
|
2
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "checks"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": [")]),l(`
|
|
3
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"name"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"lint"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"command"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"npm run lint"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," },")]),l(`
|
|
4
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"name"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"web 测试"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"command"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"npm test"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"cwd"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"web"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," },")]),l(`
|
|
5
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"name"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"server 测试"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"command"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"npm test"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"cwd"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"server"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"timeoutMinutes"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},"15"),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," }")]),l(`
|
|
6
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," ]")]),l(`
|
|
7
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"}")])])])]),i("ul",null,[i("li",null,[i("strong",null,"基线"),l(":每次尝试开始时(方案设计之前)把所有检查运行一遍,记下哪些原本就失败。")]),i("li",null,[i("strong",null,"之后"),l(":代码实现(每一片)、评审问题修复、缺陷修复结束后,运行与改动相关的检查。"),i("strong",null,"改动前通过、现在失败"),l("的,把命令和输出发回那一步的 agent 修复,最多 "),i("code",null,"qualityGate.fixAttempts"),l(' 次(默认 2)。仍然失败时照常往下走,交给代码评审和报告:报告的结论最高为"有遗留问题"。原本就失败的检查不拦,但会在报告中列出。')]),i("li",null,[i("strong",null,"多模块"),l(":带 "),i("code",null,"cwd"),l(" 的检查只在这个目录有改动时运行;需要更精确时用 "),i("code",null,"paths"),l("(例如 "),i("code",null,'["server/", "shared/"]'),l(",可以用 "),i("code",null,"*"),l(")。")]),i("li",null,[l("只放几分钟内能跑完的检查(格式、lint、类型检查、单元测试、构建)。端到端测试、需要启动服务的检查由功能验证负责。命令通过系统 shell 运行(Windows 上是 cmd.exe),和 "),i("code",null,"paseo.json"),l(" 一样写成各系统通用的形式。单项检查的时限是 "),i("code",null,"timeoutMinutes"),l(",默认 "),i("code",null,"qualityGate.timeoutMinutes"),l("(20 分钟)。")]),i("li",null,[l("输出保存在 "),i("code",null,"<功能目录>/.pipeline/checks/<步骤>/"),l(",结果在状态文件的 "),i("code",null,"gate"),l(" 中,进度查询显示最近一次的结果。没有配置 "),i("code",null,"checks"),l(' 时不运行,报告注明"未配置",'),i("code",null,"/req-doctor"),l(" 会提醒。")])]),i("h2",{id:"按切片实现",tabindex:"-1"},[l("按切片实现 "),i("a",{class:"header-anchor",href:"#按切片实现","aria-label":'Permalink to "按切片实现"'},"")]),i("p",null,[l("方案把实施计划分成几个"),i("strong",null,"纵向切片"),l('(每片是一段能单独演示和验证的功能,例如"能发送验证码")。标准档有两片以上时,代码实现按片逐个进行:每片一个新的 agent、各自提交、各自过一次质量门,子 agent 列表中显示为"5-代码实现 第2/3片";中断后只重做当前片。快速档、只有一片时与原来相同。')]),i("table",{tabindex:"0"},[i("thead",null,[i("tr",null,[i("th",null,"配置"),i("th",null,"默认"),i("th",null,"说明")])]),i("tbody",null,[i("tr",null,[i("td",null,[i("code",null,"slices.profiles")]),i("td",null,[i("code",null,'["standard"]')]),i("td",null,[l("哪些档位按切片实现;"),i("code",null,"[]"),l(" 关闭")])]),i("tr",null,[i("td",null,[i("code",null,"slices.max")]),i("td",null,"6"),i("td",null,"最多几片;方案分得更多时最后几片合并")])])]),i("h2",{id:"范围检查",tabindex:"-1"},[l("范围检查 "),i("a",{class:"header-anchor",href:"#范围检查","aria-label":'Permalink to "范围检查"'},"")]),i("p",null,[l("方案在结果文件中列出预计改动的文件和目录("),i("code",null,"files"),l(")。代码评审前,流水线比对这次实际改动的文件,把清单之外的列给评审逐一判断:为实现需求所必需的写理由,与需求无关的要求撤回。结论写进报告附录。")]),i("h2",{id:"关联仓库-只读参考",tabindex:"-1"},[l("关联仓库(只读参考) "),i("a",{class:"header-anchor",href:"#关联仓库-只读参考","aria-label":'Permalink to "关联仓库(只读参考)"'},"")]),i("p",null,"前端项目要用后端的接口、一个服务要用另一个服务的数据格式时,在项目配置中登记相关的仓库,步骤 agent 就能读它们,不用猜:"),i("div",{class:"language-json vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"json"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"{ "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"relatedRepos"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": [{ "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"name"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"后端"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"path"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"../backend"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"role"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"提供登录和订单接口"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," }] }")])])])]),i("ul",null,[i("li",null,[i("code",null,"path"),l(" 相对项目目录(团队约定把相关仓库放在同一个上级目录最方便),也可以写 "),i("code",null,"~/"),l(" 开头的路径。本机没有这个目录时跳过,"),i("code",null,"/req-doctor"),l(" 会提醒。")]),i("li",null,"步骤会看到每个关联仓库的位置、当前分支和提交,只读参考:不修改、不提交、不切换分支。验证需要对方的服务时,优先用已部署的测试环境。"),i("li",null,"两边都要改的需求(例如后端加接口、前端加页面)可以作为联合需求一起做,见下一节。")]),i("h2",{id:"联合需求-一个需求-几个仓库",tabindex:"-1"},[l("联合需求:一个需求,几个仓库 "),i("a",{class:"header-anchor",href:"#联合需求-一个需求-几个仓库","aria-label":'Permalink to "联合需求:一个需求,几个仓库"'},"")]),i("p",null,[l("需求说明头部写 "),i("code",null,"- 联合开发:后端"),l("("),i("code",null,"relatedRepos"),l(" 中登记的名称,最多两个)时(1.8 起):")]),i("ol",null,[i("li",null,[i("strong",null,"准备"),l(":流水线为每个联合开发的仓库新建一个 Paseo 工作区,分支同名("),i("code",null,"feature/<需求>"),l("),从那个仓库当前检出的分支切出;那份检出本身不动。需求说明同步过去并提交。")]),i("li",null,[i("strong",null,"方案和接口约定"),l(":在主仓库(发起需求的仓库)设计整个需求,"),i("code",null,"design.md"),l(" 按仓库分开写,"),i("code",null,"contract.md"),l(" 写双方的接口约定(字段、错误码、示例)。方案审核把接口约定一起审,通过后冻结。需求说明、方案、接口约定同步到其他仓库的功能目录并提交。")]),i("li",null,[i("strong",null,"同时开发"),l(":每个仓库各由一个 agent 实现、各自评审和修复,互不等待:提供接口的一边按约定写接口测试,调用的一边用约定的示例做测试替身。每个仓库用它自己的 "),i("code",null,"checks"),l(" 做质量门(写在它自己的 "),i("code",null,".requirement-pipeline.json"),l(" 中),用它自己的项目说明和验证方法。")]),i("li",null,[i("strong",null,"一起验证"),l(":提测说明、功能验证和报告在主仓库。验证前各仓库 "),i("code",null,"paseo.json"),l(" 中的服务都由 Paseo 用当前代码启动;验证结果写明每个缺陷属于哪个仓库,缺陷发回那个仓库修复,再一起复验。")]),i("li",null,[i("strong",null,"合并"),l(":每个仓库各有自己的分支,只做本地提交。提测说明和报告写明合并顺序(通常先合提供接口的一边),由人来合并。")])]),i("p",null,"一个仓库的步骤失败时,流水线等其他仓库正在进行的步骤做完再中断;继续时沿用已建的工作区和已完成的步骤。不做的:跨仓库的统一提交或合并、自动部署、超过三个仓库、克隆本机没有的仓库。设计决定见 ADR 0025。"),i("h2",{id:"执行方式-连续、分阶段、只做研发",tabindex:"-1"},[l("执行方式:连续、分阶段、只做研发 "),i("a",{class:"header-anchor",href:"#执行方式-连续、分阶段、只做研发","aria-label":'Permalink to "执行方式:连续、分阶段、只做研发"'},"")]),i("p",null,[l("第 3–11 步分为两个阶段:"),i("strong",null,"研发"),l("(方案设计 → 方案审核 ⇄ 修订 → 实现 → 代码评审 ⇄ 修复 → 提测说明)和"),i("strong",null,"测试验证"),l("(服务启动 → 功能验证 → 缺陷处理),之后是完成报告。研发阶段的最后一步写提测说明 "),i("code",null,"handoff.md"),l(":改了什么、怎么跑起来、自测结果、建议重点测试、已知问题、测试前的准备。")]),i("table",{tabindex:"0"},[i("thead",null,[i("tr",null,[i("th",null,"执行方式"),i("th",null,"研发完成时"),i("th",null,"适合")])]),i("tbody",null,[i("tr",null,[i("td",null,[l("连续("),i("code",null,"continuous"),l(",默认)")]),i("td",null,"直接进入测试验证,与 1.7 之前一致"),i("td",null,"本地就能验证的项目")]),i("tr",null,[i("td",null,[l("分阶段("),i("code",null,"gated"),l(")")]),i("td",null,[l('停下来通知"研发完成,可以提测";由人说"开始测试验证",或到 '),i("code",null,"--verify-at"),l(" 预约的时间开始")]),i("td",null,"有专门测试、需要先部署测试环境")]),i("tr",null,[i("td",null,[l("只做研发("),i("code",null,"develop-only"),l(")")]),i("td",null,[l("写研发报告后结束;验收时按提测说明人工测试。之后仍可用 "),i("code",null,"--phase verify"),l(" 让流水线验证")]),i("td",null,"测试必须由人完成")])])]),i("p",null,[l("来源,后者覆盖前者:配置 "),i("code",null,"phases.mode"),l(" → spec 头部 "),i("code",null,"- 执行方式:分阶段"),l(" → 启动参数 "),i("code",null,"--phases"),l("。有测试团队的项目建议在项目配置中写:")]),i("div",{class:"language-json vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"json"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"{")]),l(`
|
|
8
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "phases"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": {")]),l(`
|
|
9
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "mode"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"gated"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
|
|
10
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "verify"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": {")]),l(`
|
|
11
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "environment"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"deployed"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
|
|
12
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "agents"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"reviewer"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"paseoProfile"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"测试"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," } },")]),l(`
|
|
13
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "defects"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"handback"')]),l(`
|
|
14
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," }")]),l(`
|
|
15
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," }")]),l(`
|
|
16
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"}")])])])]),i("table",{tabindex:"0"},[i("thead",null,[i("tr",null,[i("th",null,[i("code",null,"phases.verify"),l(" 中的配置")]),i("th",null,"默认"),i("th",null,"作用")])]),i("tbody",null,[i("tr",null,[i("td",null,[i("code",null,"environment")]),i("td",null,[i("code",null,'"local"')]),i("td",null,[i("code",null,'"deployed"'),l(":不在本地启动服务,对已部署的测试环境验证。功能目录中需要 "),i("code",null,"test-env.md"),l("(地址、怎么确认版本、账号和口令从哪里取、可用的测试数据;不写口令本身),没有就拒绝开始。开始测试时可用 "),i("code",null,"--verify-env"),l(" 临时指定")])]),i("tr",null,[i("td",null,[i("code",null,"agents")]),i("td",null,[i("code",null,"{}")]),i("td",null,[l("测试阶段的步骤(服务启动、功能验证、缺陷修复、复验)用的 agent,格式同顶层 "),i("code",null,"agents"),l(",可用 "),i("code",null,"paseoProfile"),l(";没写的角色用顶层的。完成报告仍用顶层的 builder")])]),i("tr",null,[i("td",null,[i("code",null,"defects")]),i("td",null,[i("code",null,'"fix"')]),i("td",null,[i("code",null,'"fix"'),l(":当场修复并复验;"),i("code",null,'"handback"'),l(":只记录,在 "),i("code",null,"changes.md"),l(' 追加"测试验证退回"一节,回到研发阶段从方案设计开始修复,经过代码评审、重写提测说明后再提测(分阶段时再次停在闸口),最多退回档位的缺陷修复轮数次;'),i("code",null,'"report"'),l(":只记录,直接出报告。开始测试时可用 "),i("code",null,"--defects"),l(" 临时指定")])]),i("tr",null,[i("td",null,[i("code",null,"serviceStart")]),i("td",null,[i("code",null,"null")]),i("td",null,[l("测试阶段是否做服务启动验证;"),i("code",null,"null"),l(" 按档位。"),i("code",null,"deployed"),l(" 时不做")])])])]),i("p",null,[i("strong",null,"谁可以开始测试验证"),l(":发起的对话;需求在自动新建的工作区中("),i("code",null,"--worktree"),l(")时,同一仓库任何工作区中的对话也可以(研发阶段仍只能从原对话操作),之后的通知转到那个对话。测试阶段开始前需求说明改过的,先回到研发阶段处理变化。用时与用量在状态和完成报告中按阶段分别统计。见 ADR 0022。")]),i("h2",{id:"进展通知",tabindex:"-1"},[l("进展通知 "),i("a",{class:"header-anchor",href:"#进展通知","aria-label":'Permalink to "进展通知"'},"")]),i("p",null,[l('除了"需要需求方决定""等待批准""中断""完成"这几种通知,流水线默认还会在三个节点各发一句进展:技术方案已经确定、开始写代码;代码通过检查、开始验证;验证发现问题、正在修复。续跑时不会重复发送。不需要的话,在配置中设 '),i("code",null,'"notifyMilestones": false'),l("。")]),i("p",null,[i("strong",null,"同时发到企业 IM"),l(":配置 "),i("code",null,"notifiers"),l(" 后,这些通知还会交给你实现的通知模块,例如转发到企业内部 IM。"),i("code",null,"notifiers"),l(" 只能写在本机或团队配置中(项目配置中的会被忽略)。做法见 "),i("a",{href:"./install"},"安装与升级"),l(" 第 12 节,事件格式见 "),i("code",null,"contracts/notifier-event.md"),l("。")]),i("p",null,[i("strong",null,"按人通知"),l("(1.12 起):从卡片开始的需求,需要需求方处理的事(回答问题、确认方案)和结果(研发完成、流水线结束)在事件中标明发给需求方本人("),i("code",null,"people.audience"),l(" 为 "),i("code",null,"requester"),l(")。在本机或团队配置中写上姓名到账号的对应,事件里就带上账号,通知模块可以按人发送;其余事件发到群里:")]),i("div",{class:"language-json vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"json"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"people"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"张广祥"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"um"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"ZHANGGX001"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," } }")])])])]),i("h2",{id:"运行时文件",tabindex:"-1"},[l("运行时文件 "),i("a",{class:"header-anchor",href:"#运行时文件","aria-label":'Permalink to "运行时文件"'},"")]),i("p",null,[l("运行时的文件都在功能目录下的 "),i("code",null,".pipeline/"),l(" 中,不会被提交:")]),i("ul",null,[i("li",null,[i("code",null,"state.json"),l(":当前状态、档位、工作分支、每个步骤的 agent ID 和结果、历次尝试的记录")]),i("li",null,[i("code",null,"results/<步骤>.json"),l(":每个步骤的结果文件")]),i("li",null,[i("code",null,"pipeline.log"),l(":运行日志,包括使用了哪些配置文件、发出的每一条通知和每次自动重试")])]),i("p",null,[i("strong",null,"用时与用量"),l(":每个步骤记录 agent 的起止时间和 agent 报告的 token 用量、费用(有的 agent 不报告)。查看进度("),i("code",null,"req status"),l(")、需求总览("),i("code",null,"req list"),l(')和完成报告都会显示合计。评审小组的成员并行运行,所以"agent 合计用时"可能比实际经过的时间长。')]),i("h2",{id:"按项目定制",tabindex:"-1"},[l("按项目定制 "),i("a",{class:"header-anchor",href:"#按项目定制","aria-label":'Permalink to "按项目定制"'},"")]),i("p",null,[l("本机配置("),i("code",null,"~/.req-kit/config.json"),l(")对所有项目生效。各项目可以在仓库里放自己的定制,随代码一起提交,团队共享。最简单的做法是在项目根目录的对话中运行 "),i("code",null,"/req-setup"),l(",它会生成前两份文件并实际运行验证命令:")]),i("div",{class:"language-text vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"text"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",null,"<仓库根目录>/")]),l(`
|
|
17
|
+
`),i("span",{class:"line"},[i("span",null,"├── .requirement-pipeline.json 覆盖本机配置中的项")]),l(`
|
|
18
|
+
`),i("span",{class:"line"},[i("span",null,"└── .requirement-pipeline/")]),l(`
|
|
19
|
+
`),i("span",{class:"line"},[i("span",null," ├── project-notes.md 追加到每个步骤的提示词;/req 访谈前也会读")]),l(`
|
|
20
|
+
`),i("span",{class:"line"},[i("span",null," ├── verify.md 验证方法;追加到实现、修复、服务启动、验证、复验步骤")]),l(`
|
|
21
|
+
`),i("span",{class:"line"},[i("span",null," └── steps/")]),l(`
|
|
22
|
+
`),i("span",{class:"line"},[i("span",null," └── <步骤>.md 只追加到某一步,例如 verify.md")])])])]),i("p",null,[i("strong",null,[i("code",null,".requirement-pipeline.json")]),l(" 可以设置除 "),i("code",null,"daemonUrl"),l("、"),i("code",null,"daemonPasswordEnv"),l("、"),i("code",null,"teamConfig"),l(" 以外的所有项(这几项描述的是本机,写了会被忽略,并在日志和 "),i("code",null,"/req-doctor"),l(" 中提示)。例如这个项目默认走快速档、实现用另一个模型:")]),i("div",{class:"language-json vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"json"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"{")]),l(`
|
|
23
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "defaultProfile"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"quick"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
|
|
24
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "agents"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"builder"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"provider"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"claude/<模型 ID>"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"modeId"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"bypassPermissions"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," } },")]),l(`
|
|
25
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "profiles"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"standard"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"rounds"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"codeReview"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},"2"),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," } } }")]),l(`
|
|
26
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"}")])])])]),i("p",null,[i("code",null,"agents"),l(" 按角色整体替换;"),i("code",null,"profiles"),l("、"),i("code",null,"stepTimeoutMinutes"),l(" 按项合并。")]),i("p",null,[i("strong",null,[i("code",null,"project-notes.md")]),l(" 写这个项目的约定,例如:")]),i("div",{class:"language-markdown vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"markdown"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#E36209","--shiki-dark":"#FFAB70"}},"-"),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," 包管理用 pnpm,不要用 npm。")]),l(`
|
|
27
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#E36209","--shiki-dark":"#FFAB70"}},"-"),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," 不要改动 legacy/ 目录。")]),l(`
|
|
28
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#E36209","--shiki-dark":"#FFAB70"}},"-"),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," 数据库变更必须写成 migrations/ 下的迁移脚本。")])])])]),i("p",null,[i("strong",null,[i("code",null,"verify.md")]),l(" 写这个项目怎么安装依赖、启动服务、运行测试、准备测试数据,命令要实际运行过。结构建议见 "),i("code",null,"contracts/verify.md"),l("。步骤 agent 发现它过时或不准确时,会在 "),i("code",null,"service-start.md"),l(" 或 "),i("code",null,"verification.md"),l(' 的"建议写入 verify.md 的内容"一节给出实际可行的做法;再次运行 '),i("code",null,"/req-setup"),l(" 会参考这些建议更新它。项目的构建文件改过而 "),i("code",null,"verify.md"),l(" 没有更新时,"),i("code",null,"/req-doctor"),l(" 会提醒。")]),i("p",null,[l("项目配置还常写 "),i("code",null,"checks"),l("(质量门)和 "),i("code",null,"relatedRepos"),l("(关联仓库),见上文。"),i("code",null,"checks"),l("、"),i("code",null,"relatedRepos"),l("、"),i("code",null,"requirementTypes"),l(" 整体替换,"),i("code",null,"qualityGate"),l("、"),i("code",null,"slices"),l(" 按项合并。")]),i("p",null,[i("strong",null,[i("code",null,"steps/<步骤>.md")]),l(" 的文件名用步骤 ID:"),i("code",null,"design"),l("、"),i("code",null,"design_review"),l("、"),i("code",null,"design_revise"),l("、"),i("code",null,"implement"),l("、"),i("code",null,"code_review"),l("、"),i("code",null,"review_fix"),l("、"),i("code",null,"service_start"),l("、"),i("code",null,"verify"),l("、"),i("code",null,"defect_fix"),l("、"),i("code",null,"reverify"),l("、"),i("code",null,"report"),l("。例如 "),i("code",null,"steps/verify.md"),l(' 写"端到端测试用 '),i("code",null,"pnpm e2e"),l(' 运行,测试账号见 docs/test-accounts.md"。')]),i("p",null,'这些内容追加在步骤任务之后,并注明"与通用要求冲突时以项目说明为准",但"如实报告"和安全要求始终有效。'),i("p",null,[i("strong",null,"统一修改某一步的提示词"),l(":在 "),i("code",null,"~/.req-kit/prompts.local/"),l(" 中放入与 "),i("code",null,"engine/prompts/"),l(" 中同名的文件,就会替换随版本发布的那一篇。升级只替换版本目录,"),i("code",null,"prompts.local/"),l(" 不受影响;但新版本对同名提示词的改进也不会生效,升级时请对比。这是最后的手段:能写进项目说明、配置或测试的,优先写在那里。")]),i("h2",{id:"paseo-json-环境准备和由-paseo-管理的服务-推荐",tabindex:"-1"},[l("paseo.json:环境准备和由 Paseo 管理的服务(推荐) "),i("a",{class:"header-anchor",href:"#paseo-json-环境准备和由-paseo-管理的服务-推荐","aria-label":'Permalink to "paseo.json:环境准备和由 Paseo 管理的服务(推荐)"'},"")]),i("p",null,[i("code",null,"paseo.json"),l(" 是 Paseo 自己的项目文件,放在仓库根目录并提交。"),i("code",null,"/req-setup"),l(" 可以生成它:")]),i("div",{class:"language-json vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"json"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"{")]),l(`
|
|
29
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "worktree"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"setup"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": ["),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"npm ci"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"node scripts/paseo/copy-local-files.mjs .env"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"] },")]),l(`
|
|
30
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "scripts"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": {")]),l(`
|
|
31
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "test"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"command"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"npm test"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," },")]),l(`
|
|
32
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "web"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"type"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"service"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"command"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"node scripts/paseo/with-port.mjs npm run dev -- --port {PORT}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," }")]),l(`
|
|
33
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," }")]),l(`
|
|
34
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"}")])])])]),i("p",null,[i("code",null,"paseo.json"),l(" 是团队共用的,而 Paseo 在各系统上用不同的 shell 执行它的命令(macOS/Linux:bash 和 sh;Windows:准备命令用 PowerShell,带 "),i("code",null,"-ExecutionPolicy Bypass"),l(",不受执行策略限制;脚本和服务用 cmd.exe)。所以 "),i("code",null,"/req-setup"),l(" 只写各系统一样的命令,用到环境变量的地方交给它写进项目的两个小脚本:"),i("code",null,"scripts/paseo/copy-local-files.mjs"),l("(从来源目录复制不提交的本地文件,没有就跳过)和 "),i("code",null,"scripts/paseo/with-port.mjs"),l("(把 "),i("code",null,"{PORT}"),l(" 换成 Paseo 分配的端口,并设置 "),i("code",null,"PORT"),l(")。手写 "),i("code",null,"$PASEO_PORT"),l("、"),i("code",null,"%PASEO_PORT%"),l("、"),i("code",null,"cp"),l("、"),i("code",null,"Copy-Item"),l(" 这类只在某个系统上能用的命令时,"),i("code",null,"/req-doctor"),l(" 会指出:在本机上会失败的标为⚠,只是换系统会失败的给出提示。")]),i("ul",null,[i("li",null,[i("code",null,"worktree.setup"),l(":Paseo 新建 worktree 工作区时自动执行,新需求的工作区一建好就装好了依赖、带上了本地配置。")]),i("li",null,[i("code",null,'"type": "service"'),l(" 的脚本:流水线在服务启动验证、功能验证、缺陷修复和复验之前,通过 Paseo 带着当前代码重启它们,把地址("),i("code",null,"http://web--<分支>--<项目>.localhost:6767"),l(" 这样的代理地址)交给步骤 agent,验证结束后停止。Paseo 为每个工作区分配独立端口,几个需求同时验证不会冲突,服务必须监听 Paseo 分配的端口(环境变量 "),i("code",null,"PASEO_PORT"),l(",用 "),i("code",null,"with-port.mjs"),l(" 传给程序)。")]),i("li",null,[l("服务没有启动成功时,最后的输出写到功能目录的 "),i("code",null,".pipeline/services/<服务名>.log"),l(",交给步骤 agent 查原因。")]),i("li",null,[l("只有从 Paseo 对话启动的流水线才会这样做(需要知道是哪个工作区)。不想用时在配置中设 "),i("code",null,'"paseoServices": "off"'),l(",步骤 agent 会像以前一样自己启动服务。"),i("code",null,"serviceReadySeconds"),l("(默认 120)是等待服务就绪的时间。")]),i("li",null,[l("在 Paseo 设置中打开 "),i("strong",null,"Enable Paseo tools"),l(" 后,步骤 agent 改完代码还可以自己重启这些服务。")]),i("li",null,"写错时服务起不来,流水线会改由步骤 agent 自己启动服务,不会中断。"),i("li",null,[l("PowerShell 被完全禁用(不只是执行策略)的 Windows 机器上,"),i("code",null,"worktree.setup"),l(" 无法执行;新工作区不会自动装依赖,步骤 agent 会按验证方法自己准备。")])]),i("h2",{id:"额度提醒",tabindex:"-1"},[l("额度提醒 "),i("a",{class:"header-anchor",href:"#额度提醒","aria-label":'Permalink to "额度提醒"'},"")]),i("p",null,[l("开始前,流水线读取 Paseo 的用量信息(需要 Paseo 能读到对应 agent 的订阅用量)。所用 agent 的某个额度窗口用到 "),i("code",null,"quotaWarnPercent"),l("(默认 85)以上时,在对话里提醒一次,流水线照常进行;用完时遇到限流会自动等待重试。设为 0 关闭提醒。")]),i("h2",{id:"并行编排-确认前审阅、方案提案、浏览器验证",tabindex:"-1"},[l("并行编排:确认前审阅、方案提案、浏览器验证 "),i("a",{class:"header-anchor",href:"#并行编排-确认前审阅、方案提案、浏览器验证","aria-label":'Permalink to "并行编排:确认前审阅、方案提案、浏览器验证"'},"")]),i("table",{tabindex:"0"},[i("thead",null,[i("tr",null,[i("th",null,"配置"),i("th",null,"默认"),i("th",null,"作用")])]),i("tbody",null,[i("tr",null,[i("td",null,[i("code",null,"specReview")]),i("td",null,[i("code",null,'"standard"')]),i("td",null,[l("请需求方确认之前,由 reviewer 在后台独立审阅需求说明草稿,问题写进 "),i("code",null,"spec-review.md"),l("。"),i("code",null,'"always"'),l(" 快速档也做,"),i("code",null,'"off"'),l(" 关闭")])]),i("tr",null,[i("td",null,[i("code",null,"designProposals")]),i("td",null,"关闭"),i("td",null,[i("code",null,'{"enabled": true}'),l(" 后,标准档的方案设计之前由几个 agent 并行各提一份方案("),i("code",null,"design-proposals/"),l("),方案设计比较后决定。"),i("code",null,"members"),l(" 不写时用 builder 和 reviewer,也可以像评审小组一样列出成员(可用 "),i("code",null,"paseoProfile"),l(")。需求变更后的增量继续不做")])]),i("tr",null,[i("td",null,[i("code",null,"browserVerify")]),i("td",null,[i("code",null,'"auto"')]),i("td",null,[l("步骤 agent 有 Paseo 浏览器工具(Paseo 设置中打开 Enable Paseo tools 和浏览器工具,桌面端在线)时,功能验证、缺陷修复、复验按验收标准在浏览器中实际操作。"),i("code",null,'"off"'),l(" 关闭")])])])]),i("p",null,[l("Paseo 自带的 "),i("code",null,"/paseo-advisor"),l("、"),i("code",null,"/paseo-committee"),l(" 等编排 skill 也可以单独使用,例如对一个疑难问题请两个模型分别分析;它们不参与流水线(见 ADR 0019)。")]),i("h2",{id:"自动新建工作区-可选",tabindex:"-1"},[l("自动新建工作区(可选) "),i("a",{class:"header-anchor",href:"#自动新建工作区-可选","aria-label":'Permalink to "自动新建工作区(可选)"'},"")]),i("p",null,[l("在项目主目录、主分支上发起的需求,可以用 "),i("code",null,"--worktree"),l(" 启动("),i("code",null,"/req"),l(' 中的"启动(自动新建工作区)"):流水线从当前分支切出 '),i("code",null,"feature/<功能目录名>"),l(",在 Paseo 中新建 worktree 工作区,把需求说明移过去并提交,之后的步骤都在那个工作区中运行,仍然挂在发起的对话下。对话的工作目录不变,查看进度、暂停、继续都在原对话中进行;读写需求文件用通知中给出的完整路径。只能在第一次启动时选择。见 ADR 0018。")]),i("h2",{id:"调度-预约、提醒、自动继续、排队",tabindex:"-1"},[l("调度:预约、提醒、自动继续、排队 "),i("a",{class:"header-anchor",href:"#调度-预约、提醒、自动继续、排队","aria-label":'Permalink to "调度:预约、提醒、自动继续、排队"'},"")]),i("p",null,'需要"以后再做"的事,流水线用 Paseo 的定时任务把一条写明步骤的消息发回发起的对话,由对话 agent 执行(机器或 daemon 重启后仍然有效,在 Paseo 的 Schedules 中可以看到)。暂停命令会取消这些预约。'),i("table",{tabindex:"0"},[i("thead",null,[i("tr",null,[i("th",null,"配置"),i("th",null,"默认"),i("th",null,"作用")])]),i("tbody",null,[i("tr",null,[i("td",null,[l("(启动参数 "),i("code",null,"--at"),l(")")]),i("td",null,"—"),i("td",null,[l("预约开始时间:"),i("code",null,"22:00"),l("、"),i("code",null,"明天 8:30"),l("、"),i("code",null,"2026-10-14 08:30"),l("、"),i("code",null,"+2h")])]),i("tr",null,[i("td",null,[i("code",null,"waitingReminderHours")]),i("td",null,"24"),i("td",null,"等待需求方回答、或研发完成后等待测试验证超过这么久,在对话里提醒一次;0 关闭")]),i("tr",null,[i("td",null,[l("(启动参数 "),i("code",null,"--verify-at"),l(")")]),i("td",null,"—"),i("td",null,[l("分阶段时,研发完成后在这个时间自动开始测试验证(写法同 "),i("code",null,"--at"),l(";隐含分阶段)。研发完成时时间已过就直接继续")])]),i("tr",null,[i("td",null,[i("code",null,"autoResumeMinutes"),l(" / "),i("code",null,"autoResumeMax")]),i("td",null,"30 / 2"),i("td",null,"临时错误(重试用完)中断后,这么久之后在对话里自动继续;每次尝试最多几次;0 关闭")]),i("tr",null,[i("td",null,[i("code",null,"watchdogMinutes")]),i("td",null,"60(1.12 起默认打开)"),i("td",null,[l("运行期间对话定时检查,后台进程意外退出时自动继续。每次检查对话 agent 会运行一个回合;0 关闭。接单器("),i("code",null,"req factory"),l(")每次检查时也会发现这样的流水线并请它的对话继续")])]),i("tr",null,[i("td",null,[i("code",null,"maxConcurrentPipelines")]),i("td",null,"0(不限)"),i("td",null,"本机同时运行的流水线上限,满了排队。只能写在本机配置中才有意义")])])]),i("h2",{id:"需求总览",tabindex:"-1"},[l("需求总览 "),i("a",{class:"header-anchor",href:"#需求总览","aria-label":'Permalink to "需求总览"'},"")]),i("p",null,[i("code",null,"req digest"),l(' 在项目目录中列出所有工作区里的需求,按"需要处理、待验收、开发中、对齐中、已验收(最近 7 天)"分组,附用时与用量。'),i("code",null,"--notify"),l(" 同时发给外部通知(事件类型 "),i("code",null,"digest"),l(");"),i("code",null,'--schedule "<cron>"'),l(" 让 Paseo 按时间表(本机时区)启动一个短暂的 agent 执行 "),i("code",null,"req digest --notify"),l(",例如每周一 9 点:"),i("code",null,'req digest --schedule "0 9 * * 1"'),l(";取消:"),i("code",null,"req digest --cancel <定时任务 ID>"),l("。")]),i("h2",{id:"使用统计",tabindex:"-1"},[l("使用统计 "),i("a",{class:"header-anchor",href:"#使用统计","aria-label":'Permalink to "使用统计"'},"")]),i("p",null,[l("1.9.0 起,每次流水线运行结束时,引擎在本机的 "),i("code",null,"~/.req-kit/usage/runs.jsonl"),l(" 追加一条记录:各步骤的用时和用量、质量门、评审和缺陷轮数、结束时的状态(格式见 "),i("a",{href:"./../reference/contracts/usage-record"},"使用记录"),l(")。只记在本机,不记需求内容和代码,也不会自动发往任何地方。")]),i("ul",null,[i("li",null,[i("code",null,"req stats"),l(":最近 30 天的统计("),i("code",null,"--since 2w"),l("、"),i("code",null,"--since 2026-10-01"),l("、"),i("code",null,"--month 2026-10"),l("):有进展和完成的需求数、交付周期、返工(评审轮数、需要缺陷修复的占比、质量门失败)、各种等待的时长、各步骤用时、用量,以及不同 builder 的比较。"),i("code",null,"--json"),l("、"),i("code",null,"--csv"),l(" 输出机器可读的格式。")]),i("li",null,[i("code",null,"req stats --report --month 2026-10 [--out 目录]"),l(":生成给管理方汇报用的两份文件:"),i("code",null,"req-kit-usage-2026-10.md"),l("(汇总)和 "),i("code",null,".csv"),l("(每个需求一行,可以用表格软件打开)。")]),i("li",null,[l("几台机器一起汇报:每台机器运行 "),i("code",null,"req stats --month 2026-10 --export"),l(",得到 "),i("code",null,"req-kit-usage-<主机名>-<日期>.jsonl"),l(";把这些文件放到一起,运行 "),i("code",null,"req stats --merge <文件…> --month 2026-10 --report"),l("。")])]),i("p",null,[l("本机的需求索引 "),i("code",null,"~/.req-kit/index/"),l(" 记录每个运行过的需求在哪个目录,Paseo 插件据此在一个页面列出本机所有项目的需求。1.9 之前运行过的需求不在索引里,在项目目录运行一次 "),i("code",null,"req index --rebuild"),l(" 补登;目录删掉后用 "),i("code",null,"req index --prune"),l(" 清理。")]),i("h2",{id:"外部系统对接-需求管理等",tabindex:"-1"},[l("外部系统对接(需求管理等) "),i("a",{class:"header-anchor",href:"#外部系统对接-需求管理等","aria-label":'Permalink to "外部系统对接(需求管理等)"'},"")]),i("p",null,"1.9.0 起,流水线可以把需求同步到团队的需求管理系统:需求开始时建一张卡片,之后每到一个阶段改卡片的状态,卡片编号和链接写回需求,显示在进度、完成报告和 Paseo 插件里。对接的是本机已有的命令行工具(例如需求管理系统的 CLI),写在本机或团队配置中(它会运行命令,项目配置中的会被忽略):"),i("div",{class:"language-json vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"json"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"integrations"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": [")]),l(`
|
|
35
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," {")]),l(`
|
|
36
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "name"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"ALM"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
|
|
37
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "command"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"alm"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
|
|
38
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "create"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": {")]),l(`
|
|
39
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "args"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": ["),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"card"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"create"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"--title"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"{title}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"--type"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"{field.issueType}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"--project"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"{field.projectId}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"--priority"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"{card.priority}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"--body"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"{body}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"],")]),l(`
|
|
40
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "id"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"(?<id>[A-Z][A-Z0-9-]*#'),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},"\\\\"),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'d+)"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
|
|
41
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "url"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"(https?://'),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},"\\\\"),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'S+)"')]),l(`
|
|
42
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," },")]),l(`
|
|
43
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "status"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"args"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": ["),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"card"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"edit"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"{id}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"--state"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"{status}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"] },")]),l(`
|
|
44
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "statusMap"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"started"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"开发中"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"phase_done"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"待测试"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"verify"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"测试中"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"completed"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"已完成"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"not_completed"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"已挂起"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," },")]),l(`
|
|
45
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "cardFields"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"priority"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"优先级:高 / 中 / 低"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," },")]),l(`
|
|
46
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "defaults"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"issueType"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"用户故事"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," }")]),l(`
|
|
47
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," }")]),l(`
|
|
48
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"],")]),l(`
|
|
49
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"integrationDefaults"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"ALM"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"projectId"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"<团队的项目编号>"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," } }")])])])]),i("ul",null,[i("li",null,[i("strong",null,"命令"),l(":"),i("code",null,"args"),l(" 是参数数组,引擎不经过 shell 运行,标题或描述里有空格、换行、引号都不会出问题。Windows 上 npm 安装的命令("),i("code",null,".cmd"),l(")会改用 node 直接运行它的脚本。")]),i("li",null,[i("strong",null,"占位符"),l(":"),i("code",null,"{title}"),l("("),i("code",null,"card.json"),l(" 的标题,否则需求说明的标题)、"),i("code",null,"{body}"),l("("),i("code",null,"card.json"),l(" 的描述,否则 "),i("code",null,"spec.md"),l(" 全文)、"),i("code",null,"{card.<字段>}"),l("("),i("code",null,"card.json"),l(" 中需求方确认过的字段)、"),i("code",null,"{field.<名称>}"),l("("),i("code",null,"defaults"),l(" 和项目配置的 "),i("code",null,"integrationDefaults"),l(",项目可以只写自己的项目编号)、"),i("code",null,"{id}"),l("、"),i("code",null,"{url}"),l("、"),i("code",null,"{status}"),l("、"),i("code",null,"{feature}"),l("、"),i("code",null,"{branch}"),l("、"),i("code",null,"{type}"),l("、"),i("code",null,"{outcome}"),l("。一个参数只是占位符且没有值时,它和前面的选项一起省略。")]),i("li",null,[i("strong",null,"卡片编号"),l(":"),i("code",null,"create.id"),l(" 是从建卡命令输出中取编号的正则表达式(取名为 "),i("code",null,"id"),l(" 的组或第一个组),"),i("code",null,"url"),l(" 同理,可以不写。")]),i("li",null,[i("strong",null,"状态"),l(":"),i("code",null,"statusMap"),l(" 的键是流水线事件:"),i("code",null,"started"),l("(开始开发)、"),i("code",null,"approval"),l("(等待确认方案)、"),i("code",null,"blocked"),l("(等待需求方决定)、"),i("code",null,"phase_done"),l("(研发完成,待测试)、"),i("code",null,"verify"),l("(开始测试验证)、"),i("code",null,"completed"),l("(完成;可以用 "),i("code",null,"completed_with_issues"),l("、"),i("code",null,"not_completed"),l(" 细分)、"),i("code",null,"failed"),l('(中断)。没写的事件不改状态。"只做研发"的需求在研发完成时发的是 '),i("code",null,"phase_done"),l("(1.10 起;之前是 "),i("code",null,"completed"),l(")。")]),i("li",null,[i("strong",null,"卡片字段由 AI 整理、需求方确认"),l(":写了 "),i("code",null,"cardFields"),l(" 时,"),i("code",null,"/req"),l(" 在请需求方确认需求说明时,从需求说明中整理出这些字段的取值一起确认,写进功能目录的 "),i("code",null,"card.json"),l("。命令的写法固定在配置里,运行时不让 AI 决定怎么调用。")]),i("li",null,[i("strong",null,"失败不影响流水线"),l(":调用失败或超时("),i("code",null,"timeoutSeconds"),l(",默认 60)记在状态文件里,下一个事件时先按顺序补发;等待中的状态只留最新的一个,不会重复建卡。流水线没在运行时,"),i("code",null,"req sync <需求>"),l(' 立即补发(插件中也有"同步到外部系统")。')]),i("li",null,[i("strong",null,"先试再用"),l(":"),i("code",null,"req integration test [需求]"),l(" 显示每个事件会执行的完整命令(用这个需求的需求说明和 "),i("code",null,"card.json"),l(" 填好),不真正调用;"),i("code",null,"req integration fields"),l(" 显示需求方要确认的字段。")]),i("li",null,"认证由工具自己负责(例如工具已登录本机账号)。不要把口令写进配置;工具需要时放在环境变量里。")]),i("h3",{id:"从卡片开始需求-1-10-起-beta",tabindex:"-1"},[l("从卡片开始需求(1.10 起,beta) "),i("a",{class:"header-anchor",href:"#从卡片开始需求-1-10-起-beta","aria-label":'Permalink to "从卡片开始需求(1.10 起,beta)"'},"")]),i("p",null,[l("需求方在需求管理系统中写好一张卡片,就可以从卡片开始需求,不必有人在 Paseo 对话里发起。对接配置中再写两项:"),i("code",null,"query"),l(" 读一张卡片,"),i("code",null,"describe"),l(" 改卡片描述:")]),i("div",{class:"language-json vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"json"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"{")]),l(`
|
|
50
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "name"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"ALM"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
|
|
51
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "command"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"shenbing"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
|
|
52
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "query"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": {")]),l(`
|
|
53
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "args"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": ["),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"alm-card"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"view"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"{id}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"--fields"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"globalId,name,state,createdBy,subsysName,description"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"],")]),l(`
|
|
54
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "fields"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"title"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"data.name"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"body"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"data.description"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"state"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"data.state"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"author"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"data.createdBy"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"subsystem"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"data.subsysName"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," }")]),l(`
|
|
55
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," },")]),l(`
|
|
56
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "describe"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"args"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": ["),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"alm-card"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"edit"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"{id}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"-b"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"{description}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"] },")]),l(`
|
|
57
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "status"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"args"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": ["),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"alm-card"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"edit"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"{id}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"--state-detail"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"{status}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"] },")]),l(`
|
|
58
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "statusMap"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"started"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"开发中"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"phase_done"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"待测试"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," }")]),l(`
|
|
59
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"}")])])])]),i("ul",null,[i("li",null,[i("p",null,[i("code",null,"query.fields"),l(" 写输出 JSON 中各值的位置(点分路径);"),i("code",null,"title"),l(" 和 "),i("code",null,"body"),l(" 必填,"),i("code",null,"state"),l("、"),i("code",null,"author"),l("、"),i("code",null,"subsystem"),l("、"),i("code",null,"url"),l(" 可选。输出前后有日志行也可以。")])]),i("li",null,[i("p",null,[i("code",null,"describe"),l(" 的 "),i("code",null,"{description}"),l(" 是完整的新描述。req-kit 只在描述末尾维护两个区块,需求方自己写的内容原样保留:")]),i("ul",null,[i("li",null,[i("code",null,"## req-kit AI 区(自动维护,请勿修改)"),l(":进度、需求说明摘要、验收标准、假设、要问需求方的问题(Q1、Q2…),方案待确认时附上方案摘要。")]),i("li",null,[i("code",null,"## 需求方回复(请在下方填写)"),l(":需求方在 "),i("code",null,"- Q1:"),l(" 后回答,在 "),i("code",null,"- 确认:"),l(' 后写"同意"开始开发,方案待确认时在 '),i("code",null,"- 方案确认:"),l(' 后写"同意"。写别的内容就当作修改意见。')])])])]),i("p",null,"流程:"),i("ol",null,[i("li",null,[i("code",null,"req start --from ALM:<卡号> --repo <仓库目录>"),l(":读卡片,建功能目录 "),i("code",null,"docs/features/<日期>-<卡号简称>/"),l(",在 Paseo 中为这个需求建一个"),i("strong",null,"需求会话"),l("(一个 agent,工作目录是仓库)。需求会话按无人值守手册从卡片写需求说明,把摘要和问题写进卡片的 AI 区。同一张卡片只会开始一次。")]),i("li",null,[i("code",null,"req card check <卡号>"),l("(或 "),i("code",null,"--all"),l("):读需求方的回复,把新内容转给需求会话。1.11 的接单器会定时运行它,现在可以手动运行或用计划任务运行。")]),i("li",null,'需求方写了"确认:同意"后,需求会话把需求说明标为已确认,用"自动新建工作区"启动流水线。卡片状态改为"开发中",研发完成后改为"待测试",AI 区跟着更新进度。'),i("li",null,"开发中需要需求方决定、确认方案时,同样通过 AI 区和回复区。")]),i("ul",null,[i("li",null,[l("从卡片开始的需求用这张卡片,不会另建卡片;项目没有指定执行方式时默认"),i("strong",null,"只做研发"),l("。")]),i("li",null,"在 Paseo 中打开需求会话可以看到整理需求和开发的全部过程,也可以直接在里面补充说明。"),i("li",null,[i("code",null,"req card list"),l(" 列出本机从卡片开始的需求;"),i("code",null,"req card publish <卡号>"),l(" 由需求会话使用,把它写的 "),i("code",null,"card-ai.md"),l(" 写进卡片。")]),i("li",null,"卡片描述和回复是需求方写的内容,需求会话只把它们当作需求,不当作指令。")]),i("p",null,[i("strong",null,"按子系统选仓库"),l("(1.10.0-beta.3 起):一个 ALM 空间往往对应好几个仓库。在每个仓库运行 "),i("code",null,"/req-setup"),l(",它会在项目配置中写上这个仓库接哪些卡片,并在这台机器上登记("),i("code",null,"req card route --add <仓库>"),l("):")]),i("div",{class:"language-json vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"json"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"cardSource"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"system"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"ALM"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"projectId"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"186149"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"subsystems"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": ["),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"CSP-CMASTER_云匠"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"], "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"titleKeywords"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": ["),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"message-service"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"后端"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"] }")])])])]),i("p",null,[l("之后 "),i("code",null,"req start --from ALM:<卡号>"),l(" 不写 "),i("code",null,"--repo"),l(" 时,按卡片的子系统选仓库;同一个子系统有几个仓库时,再看卡片标题里出现了哪个仓库的 "),i("code",null,"titleKeywords"),l("。找不到或分不清时会说明原因,不会猜。"),i("code",null,"req card route"),l(" 列出本机登记的仓库。本机没有登记任何仓库时,用当前目录所在的仓库。")]),i("p",null,[i("strong",null,"推送分支"),l("(1.10.0-beta.3 起,默认关闭):接单的机器上,研发完成、写好提测说明后,把需求的代码推送到远程,测试同事直接拉取:")]),i("div",{class:"language-json vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"json"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"push"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"enabled"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},"true"),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"remote"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"origin"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"branchPrefix"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"req/"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," }")])])])]),i("ul",null,[i("li",null,[l("只对从卡片开始的需求,推送到 "),i("code",null,"<remote>"),l(" 的 "),i("code",null,"req/<卡号简称>"),l(" 分支(例如 "),i("code",null,"req/cmaster-business-9902"),l("),联合需求的几个仓库各推各的。分支名写进卡片的 AI 区和状态文件。")]),i("li",null,"只推这个前缀的分支;从不强推、不合并,合并仍由人做。推送被拒绝(例如远程分支有别人的提交)时记下原因、写进 AI 区,流水线照常结束。"),i("li",null,"只能写在本机或团队配置中,写在项目配置里会被忽略。推送用这台机器上 git 已配置的账号。"),i("li",null,"在个人电脑上通过对话发起的需求不受影响,仍然只在本地提交。")]),i("p",null,[i("strong",null,"草稿合并请求"),l("(1.12 起,可选):推送后用机器上的 GitLab 命令行(或其他工具)建一个草稿合并请求。命令写法与对接配置一样,参数中用占位符:")]),i("div",{class:"language-json vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"json"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"push"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": {")]),l(`
|
|
60
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "enabled"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},"true"),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
|
|
61
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "mergeRequest"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": {")]),l(`
|
|
62
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "command"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"glab"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
|
|
63
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "args"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": ["),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"mr"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"create"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"--draft"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"--source-branch"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"{branch}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"--target-branch"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"{target}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"--title"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"{title}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"--description"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"{description}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"--yes"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"],")]),l(`
|
|
64
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "check"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": ["),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"auth"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"status"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"]")]),l(`
|
|
65
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," }")]),l(`
|
|
66
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"}")])])])]),i("ul",null,[i("li",null,[l("占位符:"),i("code",null,"{branch}"),l(" 推送的分支;"),i("code",null,"{target}"),l(" 目标分支("),i("code",null,"target"),l(" 没写时用远程的默认分支,读不到时 "),i("code",null,"main"),l(");"),i("code",null,"{title}"),l(' 为"[卡号] 需求标题";'),i("code",null,"{description}"),l(" 为提测说明加卡片链接,开头注明是草稿、合并前请人工评审;"),i("code",null,"{card}"),l("、"),i("code",null,"{cardUrl}"),l("。")]),i("li",null,"在需求的仓库中执行;输出中的第一个网址记为合并请求地址,写进卡片 AI 区和状态文件。每个仓库只建一次,测试退回后再推送时合并请求自动更新。"),i("li",null,[l("建失败(例如没有登录)只记下原因,分支照常推送。"),i("code",null,"req doctor"),l(" 用 "),i("code",null,"check"),l(" 中的参数检查是否已登录。")]),i("li",null,[l("需要机器上提前登录好(例如 "),i("code",null,"glab auth login"),l("),req-kit 不保存令牌。")])]),i("p",null,[i("strong",null,"使用统计"),l(":从卡片开始的需求,运行记录带上需求方(卡片的提出人)和卡号。"),i("code",null,"req stats --report"),l(' 多一节"从卡片开始的需求(按需求方)",CSV 多 '),i("code",null,"requester"),l("、"),i("code",null,"card"),l(" 两列。")]),i("h3",{id:"接单器-1-11-起-beta",tabindex:"-1"},[l("接单器(1.11 起,beta) "),i("a",{class:"header-anchor",href:"#接单器-1-11-起-beta","aria-label":'Permalink to "接单器(1.11 起,beta)"'},"")]),i("p",null,[l("接单器在一台共享研发机器上常驻运行,需求方只在卡片上操作:标题以 "),i("code",null,"[AI]"),l("(或 "),i("code",null,"【AI】"),l(")开头的新卡片会被自动接手,需求方在卡片中的回复会自动转给需求会话。")]),i("p",null,[l("在对接配置中再写 "),i("code",null,"list"),l("(列出卡片的命令),例如:")]),i("div",{class:"language-json vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"json"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"list"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": {")]),l(`
|
|
67
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "args"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": ["),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"alm-card"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"list"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"--project-id"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"{projectId}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"-t"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"用户故事"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"-S"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"新建"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"-s"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"AI"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"-L"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"{pageSize}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"-P"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"{page}"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"--fields"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"globalId,name,state,subsysName,createdBy"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"],")]),l(`
|
|
68
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "fields"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"id"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"globalId"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"title"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"name"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"state"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"state"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"subsystem"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"subsysName"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"author"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"createdBy"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," }")]),l(`
|
|
69
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"}")])])])]),i("ul",null,[i("li",null,[i("code",null,"{projectId}"),l(" 是本机登记的仓库在 "),i("code",null,"cardSource"),l(" 中写的空间,每个空间查一次;"),i("code",null,"{page}"),l("、"),i("code",null,"{pageSize}"),l(" 用于翻页("),i("code",null,"pageSize"),l(" 默认 100,最多 "),i("code",null,"maxPages"),l(" 页,默认 5)。")]),i("li",null,[l("输出中卡片列表的位置不在 data.list、data.records、data.items、data.rows 或 data 时,用 "),i("code",null,"items"),l(" 写明,例如 "),i("code",null,'"items": "data.result"'),l("。")]),i("li",null,[l("只接什么样的卡片(类型、状态)写在参数里;接单器再按标题开头的标识筛一遍,"),i("code",null,"-s"),l(" 只是让列表短一些。")])]),i("p",null,"本机或团队配置中可以调整(都有默认值):"),i("div",{class:"language-json vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"json"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"factory"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"pollMinutes"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},"5"),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"titleTags"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": ["),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"[AI]"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"【AI】"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"], "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"maxNewPerPoll"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},"3"),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," }")])])])]),i("p",null,"运行:"),i("table",{tabindex:"0"},[i("thead",null,[i("tr",null,[i("th",null,"命令"),i("th",null,"做什么")])]),i("tbody",null,[i("tr",null,[i("td",null,[i("code",null,"req factory once")]),i("td",null,"检查一次:为新卡片开始需求,转达新回复。先用它试配置")]),i("tr",null,[i("td",null,[i("code",null,"req factory start"),l(" / "),i("code",null,"stop")]),i("td",null,[l("在后台运行 / 停止,日志在 "),i("code",null,"~/.req-kit/factory/factory.log")])]),i("tr",null,[i("td",null,[i("code",null,"req factory status")]),i("td",null,"是否在运行、最近一次检查的结果、没能接的卡片和原因")]),i("tr",null,[i("td",null,[i("code",null,"req factory service")]),i("td",null,"作为系统服务运行的写法(Linux systemd 用户服务、Windows 计划任务),机器重启后自动恢复")])])]),i("ul",null,[i("li",null,[l("每次最多开始 "),i("code",null,"maxNewPerPoll"),l(" 个需求,其余下次再接;开发仍受 "),i("code",null,"maxConcurrentPipelines"),l(" 限制。")]),i("li",null,"接不了的卡片(例如子系统没有对应的仓库)记下原因;卡片的标题和子系统改了会马上再试,否则一天后再试。"),i("li",null,"Paseo daemon 要同时运行:接单器通过它创建需求会话。"),i("li",null,"现在只支持一台机器接单。几台机器同时运行接单器会重复接同一张卡片。")]),i("p",null,[i("strong",null,"自检与告警"),l("(1.12 起):每次检查前先确认 Paseo 连得上、builder 和 reviewer 用的 agent 已登录、额度没有用完(配置了备用模型时,备用的也用完才算),以及需求管理系统的命令能列出卡片。不正常时这次不接新卡片、不转达回复,原因写进 "),i("code",null,"req factory status"),l(" 和日志,并通过外部通知发一条 "),i("code",null,"alert"),l(" 事件;同样的问题只发一次,恢复正常时再发一次。")]),i("p",null,[i("strong",null,"续跑中断的需求"),l('(1.12 起):每次检查时,发现本机有流水线标着"运行中"但后台进程已经不在(机器重启、进程被杀),请它的对话检查并继续,每个进程只提醒一次。')]),i("p",null,[i("strong",null,"小改动自动确认"),l("(1.12 起,默认关闭):")]),i("div",{class:"language-json vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"json"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"autoConfirm"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"hours"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},"4"),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," }")])])])]),i("p",null,'快速档、没有待回答问题的卡片,AI 区写明"到某时前没有异议就开始";到时需求方没有在回复区写任何内容,接单器按"确认:同意"处理。需求方随时可以写"同意"提前开始,或写修改意见。每次摘要更新都重新计时。'),i("h2",{id:"团队配置",tabindex:"-1"},[l("团队配置 "),i("a",{class:"header-anchor",href:"#团队配置","aria-label":'Permalink to "团队配置"'},"")]),i("p",null,[l("几台机器、多个项目共用的设置(统一的模型、评审小组、超时、要求的 req-kit 版本)可以放在一份团队配置里。把它放进一个团队共用的 git 仓库,各台机器克隆下来,在本机配置 "),i("code",null,"~/.req-kit/config.json"),l(" 中写上它的路径(绝对路径,或相对 "),i("code",null,"~/.req-kit/"),l(" 的路径):")]),i("div",{class:"language-json vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"json"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"{ "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"teamConfig"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"D:/Users/me/team-config/req-kit.json"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," }")])])])]),i("p",null,[l("合并顺序是 本机 → 团队 → 项目 → spec 中的档位 → 启动参数,后面的覆盖前面的。"),i("code",null,"daemonUrl"),l("、"),i("code",null,"daemonPasswordEnv"),l("、"),i("code",null,"teamConfig"),l(" 只在本机配置中生效,写在团队或项目配置里会被忽略并提示。")]),i("p",null,[l("团队配置中可以写 "),i("code",null,'"requiredVersion": ">=1.2.0 <2"'),l("。本机的 req-kit 版本不在范围内时,"),i("code",null,"/req-doctor"),l(" 和流水线日志会提醒升级,但不会阻止运行。")]),i("h2",{id:"评审小组-可选",tabindex:"-1"},[l("评审小组(可选) "),i("a",{class:"header-anchor",href:"#评审小组-可选","aria-label":'Permalink to "评审小组(可选)"'},"")]),i("p",null,[l("开启后,标准档的方案审核和代码评审在"),i("strong",null,"第一轮"),l("先由几位评审者(建议使用不同厂商的模型)各自独立评审,再由配置的 "),i("code",null,"reviewer"),l(" 逐条核实、归类(必须修改 / 建议修改 / 留给人决定 / 已驳回),写出正式结论。被驳回和留给人决定的意见记入 "),i("code",null,"decisions.tsv"),l(",最终报告会展示它们。后续轮次只核对修复,用单个评审者。")]),i("div",{class:"language-json vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"json"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"reviewPanel"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": {")]),l(`
|
|
70
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "enabled"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},"true"),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
|
|
71
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "steps"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": ["),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"design_review"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"code_review"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"],")]),l(`
|
|
72
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "profiles"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": ["),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"standard"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"],")]),l(`
|
|
73
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "members"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": [")]),l(`
|
|
74
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"name"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"安全视角"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"provider"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"codex/<模型 ID>"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"modeId"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"full-access"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"focus"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"重点检查权限、输入校验和数据安全"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," },")]),l(`
|
|
75
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"name"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"可维护性"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"provider"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"opencode/anthropic/<模型 ID>"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"modeId"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"build"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"featureValues"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"auto_accept"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},"true"),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," } }")]),l(`
|
|
76
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," ]")]),l(`
|
|
77
|
+
`),i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"}")])])])]),i("ul",null,[i("li",null,[l("成员并行运行,在同一个目录里只读代码、写各自的意见文件("),i("code",null,"<功能目录>/review-panel/"),l("),不提交,不改文件。")]),i("li",null,"某位成员失败时,只汇总完成的成员;全部失败时该步骤失败。"),i("li",null,"成本:每次启用的评审多出 N 个 agent 的用量,所以默认只用于标准档的第一轮。"),i("li",null,[l("成员的模型和模式会在 "),i("code",null,"/req-doctor"),l(" 中一并检查。")])]),i("h2",{id:"需求总览、决策记录、变更与验收记录",tabindex:"-1"},[l("需求总览、决策记录、变更与验收记录 "),i("a",{class:"header-anchor",href:"#需求总览、决策记录、变更与验收记录","aria-label":'Permalink to "需求总览、决策记录、变更与验收记录"'},"")]),i("ul",null,[i("li",null,[i("strong",null,"需求总览"),l(":"),i("code",null,"node <req-kit>/bin/start-pipeline.mjs --list"),l(" 列出这个仓库所有 worktree 中的需求和各自的阶段(对齐中、开发中、待验收、已验收等)。总览现场生成,不提交到仓库,避免各分支合并时冲突。")]),i("li",null,[i("strong",null,"决策记录"),l(),i("code",null,"decisions.tsv"),l(":各步骤把不显而易见的选择(假设、取舍、偏离方案、驳回的评审意见、决定不修的问题)各记一行。会影响结果的标为 "),i("code",null,"needs_human=yes"),l(',完成报告把它们列入"需要你确认的决定"。')]),i("li",null,[i("strong",null,"变更记录"),l(),i("code",null,"changes.md"),l(':每次修改需求(包括方案审核提出问题、验收发现问题)记一节,spec 头部的"版本"随之加 1。')]),i("li",null,[i("strong",null,"验收记录"),l(),i("code",null,"acceptance.md"),l(":由 "),i("code",null,"/req"),l(" 的验收手册写,逐条记录验收结果和结论。")])]),i("p",null,[l("格式见 "),i("code",null,"contracts/feature-files.md"),l("。")]),i("h2",{id:"运行规则",tabindex:"-1"},[l("运行规则 "),i("a",{class:"header-anchor",href:"#运行规则","aria-label":'Permalink to "运行规则"'},"")]),i("p",null,[i("strong",null,"步骤和轮数"),l("(轮数按档位,在配置的 "),i("code",null,"profiles"),l(" 中调整;下面是标准档的默认值):")]),i("table",{tabindex:"0"},[i("thead",null,[i("tr",null,[i("th",null,"环节"),i("th",null,"规则")])]),i("tbody",null,[i("tr",null,[i("td",null,"评审小组(可选)"),i("td",null,"开启时,标准档的方案审核和代码评审第一轮先由小组成员并行评审,再由评审者核实汇总")]),i("tr",null,[i("td",null,"方案审核 ⇄ 方案修订"),i("td",null,'最多 2 轮审核。判定"阻塞"时暂停并请需求方决定;最后一轮仍要求修改时,修订后直接进入实现')]),i("tr",null,[i("td",null,"代码评审 ⇄ 评审问题修复"),i("td",null,"最多 3 轮评审,通过即止;轮数用完时修复后进入下一阶段")]),i("tr",null,[i("td",null,"提测说明"),i("td",null,[l("代码评审之后执行,写 "),i("code",null,"handoff.md"),l("。分阶段执行时研发阶段到此结束")])]),i("tr",null,[i("td",null,"服务启动验证"),i("td",null,[l("方案设计判断项目有常驻服务、且档位开启了 "),i("code",null,"serviceStart"),l(" 时才执行(在已部署的测试环境中验证时不执行)")])]),i("tr",null,[i("td",null,"缺陷修复 ⇄ 复验"),i("td",null,[l("功能验证发现缺陷时执行,最多 3 轮,复验通过即止("),i("code",null,"phases.verify.defects"),l(" 为 "),i("code",null,"handback"),l(" 或 "),i("code",null,"report"),l(' 时见上文"执行方式")')])]),i("tr",null,[i("td",null,"完成报告"),i("td",null,"只要没有暂停或中断就一定执行,遗留问题写进报告")]),i("tr",null,[i("td",null,"完成后继续"),i("td",null,[l("完成后 spec.md 被修改过(需求变更、验收发现问题),"),i("code",null,"--resume"),l(" 从方案设计开始,各步骤在已有方案和代码的基础上只处理变化的部分;没改过则拒绝。"),i("code",null,"--restart"),l(" 则完全从零开始")])]),i("tr",null,[i("td",null,"增量继续"),i("td",null,[l('需求变更、回答了方案审核的问题后继续时:方案在原文末尾追加"第 N 次尝试"一节;实现只改需要改的;代码评审只看本次开始以来的改动;验证重新验证变化涉及的验收标准,其余的至少跑一遍现有测试;报告说明是第几次。做法写在 '),i("code",null,"engine/prompts/incremental.md"),l(",可以用 "),i("code",null,"prompts.local/"),l(" 替换")])])])]),i("p",null,[i("strong",null,"结果文件"),l(":每步必须写一个 JSON 结果文件,流水线只看它,不看 agent 的回复文字。文件缺失或格式不对时,会在同一个会话里提醒 agent 补写,最多 2 次,仍不对则判定该步骤失败。")]),i("p",null,[i("strong",null,"等待与超时"),l(":每步有总时限("),i("code",null,"stepTimeoutMinutes"),l(")。到时 agent 还在做时,先再给它同样长的时间("),i("code",null,"selfHeal"),l(",见下);仍未完成才判定失败,但不停止 agent。继续("),i("code",null,"--resume"),l("、自动重试)时先看这一步上一次的 agent:已经做完、结果文件有效就直接用它的结果;还在做就接着等它一轮(这一轮不再额外延长);第二次仍超时才停止它、另起一个 agent。需求改过、开始了新一次尝试时,上一次留下的 agent 直接停掉,不接手(1.12.1)。同一步不会有两个 agent 同时在做(它们会改同样的文件、在同一个工作区提交、写同一个结果文件)。连续读不到 agent 状态时同样处理。等待被拆成每段 10 分钟,连接断开时自动重试。agent 等待权限批准时,同一个请求只通知一次,然后继续等待。")]),i("p",null,[i("strong",null,"临时错误自动重试"),l(":步骤因限流(429)、服务暂时不可用(502/503/504/529、overloaded)、网络中断等临时错误失败时,等待后用新的 agent 重做这一步,并告诉它工作区里可能留有上一次没做完的改动。默认最多重试 2 次,分别等 1 分钟和 5 分钟:")]),i("div",{class:"language-json vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"json"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"retry"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"attempts"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},"2"),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"backoffSeconds"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": ["),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},"60"),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},", "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},"300"),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"] }")])])])]),i("p",null,[i("code",null,"attempts"),l(" 设为 0 关闭;"),i("code",null,"backoffSeconds"),l(" 的个数少于重试次数时,后面的重试使用最后一个值。超时、结果文件不合格、agent 自己判定失败等不是临时错误,不按这里重试。重试用完仍失败时,中断通知会注明已重试的次数。")]),i("p",null,[i("strong",null,"自愈"),l("(1.12,"),i("code",null,"selfHeal"),l(",默认 "),i("code",null,"true"),l("):能安全自动处理的中断不再等人。")]),i("table",{tabindex:"0"},[i("thead",null,[i("tr",null,[i("th",null,"情况"),i("th",null,"自动处理")])]),i("tbody",null,[i("tr",null,[i("td",null,"步骤超时,agent 还在做"),i("td",null,"不打断它,再等同样长的时间;仍未完成才中断")]),i("tr",null,[i("td",null,"agent 报错(不是临时错误)"),i("td",null,"新开一个 agent 重做这一步一次;配置了备用模型时用备用模型")]),i("tr",null,[i("td",null,"提醒后仍没有有效的结果文件"),i("td",null,"新开一个 agent 重做这一步一次")]),i("tr",null,[i("td",null,"限流、额度用完,重试用完"),i("td",null,[l("配置了备用模型时,用备用模型再做一次;仍不行就中断,并按 Paseo 显示的额度恢复时间预约自动继续(恢复后 5 分钟;没有恢复时间时按 "),i("code",null,"autoResumeMinutes"),l(")")])]),i("tr",null,[i("td",null,"方案审核说需要需求方决定"),i("td",null,[l("先请 builder 从代码、文档和需求说明中找答案("),i("code",null,"answerQuestionsFirst"),l(",默认 "),i("code",null,"true"),l("),只把真正的业务取舍连同推荐答案交给需求方;都能回答时不停下。最后一轮审核的问题被自答时,再加一轮审核复核这些答案(1.12.1)")])])])]),i("p",null,[i("strong",null,"备用模型"),l("(1.12,可选):"),i("code",null,"agents.fallback"),l(",写法同 builder、reviewer,可以用 "),i("code",null,"paseoProfile"),l("。"),i("code",null,"req configure"),l(' 和插件的"模型"设置页会推荐一个与主模型不同厂商的模型。')]),i("div",{class:"language-json vp-adaptive-theme"},[i("button",{title:"Copy Code",class:"copy"}),i("span",{class:"lang"},"json"),i("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[i("code",null,[i("span",{class:"line"},[i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"agents"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"builder"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#B31D28","--shiki-light-font-style":"italic","--shiki-dark":"#FDAEB7","--shiki-dark-font-style":"italic"}},"…"),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," }, "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"reviewer"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#B31D28","--shiki-light-font-style":"italic","--shiki-dark":"#FDAEB7","--shiki-dark-font-style":"italic"}},"…"),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," }, "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"fallback"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": { "),i("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},'"provider"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),i("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"opencode/<模型 ID>"'),i("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}}," } }")])])])]),i("p",null,[l("自动处理的每一次都记在进度日志、状态文件的 "),i("code",null,"recoveries"),l(" 和使用记录中,"),i("code",null,"req stats"),l(' 的"人工介入"一节汇总:停下等人的原因、自动处理了多少次、到达提测的需求中没有非必要介入的比例。')]),i("p",null,[i("strong",null,"同一个目录一次只运行一条流水线"),l(",因为各步骤都在这个目录中修改和提交。需要并行时,为每个需求使用单独的 worktree 工作区。")]),i("h2",{id:"注意事项",tabindex:"-1"},[l("注意事项 "),i("a",{class:"header-anchor",href:"#注意事项","aria-label":'Permalink to "注意事项"'},"")]),i("ul",null,[i("li",null,[i("strong",null,"发起流水线的聊天 agent 需要能访问本机网络。"),l(" 流水线进程继承它的运行环境,需要连接 "),i("code",null,"ws://127.0.0.1:6767"),l("。用 Codex 做聊天 agent 时,请使用 "),i("code",null,"full-access"),l(" 模式;沙箱模式可能禁止网络。")]),i("li",null,[i("strong",null,"必须在仓库对应的项目对话中发起,对话过程中不要切换工作目录。"),l(" 步骤 agent 一律作为子 agent 挂在发起的对话下,而 Paseo 会让子 agent 使用父 agent 的工作目录,所以仓库目录必须就是这个对话的工作目录。在对话中启动时,"),i("code",null,"--repo"),l(" 默认就取对话的工作目录;两者不一致、或发起的对话已不存在时,流水线拒绝启动并说明原因。")]),i("li",null,[i("strong",null,"步骤 agent 以免确认模式运行"),l(",在本机拥有执行命令的权限。提示词禁止了危险操作,但这不是安全边界。请让仓库目录中不包含生产环境凭据。")]),i("li",null,[i("strong",null,"聊天被归档时"),l(",挂在它下面的步骤 agent 也会被归档;通知会发送失败,但流水线会继续运行到结束,结果仍可在 "),i("code",null,"report.md"),l(" 和日志中查看。")]),i("li",null,[i("strong",null,"daemon 重启"),l("会中断正在运行的步骤 agent。流水线会在连续 5 次无法获取状态后判定该步骤失败,之后可以用 "),i("code",null,"--resume"),l(" 继续。")])])],-1),i("p",{class:"source-note"},[l("本页由仓库中的 "),i("a",{href:"https://github.com/yiyisf/paseo-req-kit/blob/main/docs/guide/项目定制与运行规则.md"},"docs/guide/项目定制与运行规则.md"),l(" 生成。"),i("a",{href:"https://github.com/yiyisf/paseo-req-kit/edit/main/docs/guide/项目定制与运行规则.md"},"在 GitHub 上编辑")],-1)])])}const c=e(t,[["render",h]]);export{o as __pageData,c as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as o,o as e,c as d,a3 as r}from"./chunks/framework.B9qR_F1m.js";const g=JSON.parse('{"title":"使用者指南","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"guide/user.md","filePath":"guide/user.md","lastUpdated":null}'),a={name:"guide/user.md"};function u(s,t,i,l,q,n){return e(),d("div",null,[...t[0]||(t[0]=[r('<div><h1 id="使用者指南" tabindex="-1">使用者指南 <a class="header-anchor" href="#使用者指南" aria-label="Permalink to "使用者指南""></a></h1><p>req-kit 帮你把一个需求从"我想要……"做到"可以验收":你在 Paseo 的对话里把需求讲清楚、确认一份需求说明,之后的方案设计、写代码、评审、测试和报告由一组 AI agent 在后台完成,结果发回同一个对话。</p><p>适合测试、产品经理、项目经理等不写代码、但熟悉需求和测试的同事。你不需要读代码,但可以随时查看每一步的产物,也可以亲自执行测试命令核对结果。</p><h2 id="第一次使用之前" tabindex="-1">第一次使用之前 <a class="header-anchor" href="#第一次使用之前" aria-label="Permalink to "第一次使用之前""></a></h2><p>请开发同事确认这台机器已经装好 req-kit(<code>/req-doctor</code> 全部正常),并且项目已经接入:在项目根目录的对话中运行过 <code>/req-setup</code>,生成了项目说明和验证方法。测试同事熟悉项目的话,也可以自己运行 <code>/req-setup</code>。</p><h2 id="提一个需求" tabindex="-1">提一个需求 <a class="header-anchor" href="#提一个需求" aria-label="Permalink to "提一个需求""></a></h2><ol><li><strong>准备工作区</strong>:每个需求最好有自己的 worktree 工作区,几个需求可以同时进行,互不影响。两种方式任选: <ul><li>直接在项目的对话里开始,AI 问到时选"开发时自动新建工作区":照常谈需求,启动开发时流水线会自动新建工作区并在那里开发,这个对话不用动。</li><li>自己新建:在 Paseo 中点 <strong>New workspace</strong> → 选择项目 → <strong>Isolation</strong> 选 <strong>New worktree</strong> → 起点选主分支,然后在新工作区的对话里开始。</li></ul></li><li><strong>输入 <code>/req</code> 和一句话</strong>:例如 <code>/req 登录页增加短信验证码登录</code>。用 Pi 时输入 <code>/skill:req ……</code>。</li><li><strong>回答问题</strong>:AI 会先复述它的理解,然后一次问一个问题,给出选项和推荐。它会问到异常情况、权限、已有数据、测试数据和验证环境,这些往往是你最清楚的。拿不准时可以说"你定",它会采用推荐项并记为假设,最后请你过目。</li><li><strong>独立审阅</strong>(标准档):确认之前,AI 会请另一个模型把需求说明独立审一遍,几分钟后把发现的问题(歧义、遗漏、没法验证的验收标准)逐个问你。这一步常常能省掉开发之后的返工。</li><li><strong>确认需求说明</strong>:AI 给出一份 10 行以内的摘要,完整的需求说明在 <code>docs/features/<日期>-<名称>/spec.md</code>。确认后它会问是否开始开发。</li><li><strong>等待</strong>:开发在后台进行,通常需要几个小时,不需要盯着。期间你会收到几句进展(方案定了、开始验证等)。</li></ol><p>小改动(改文案、样式、一个配置项)会走快速流程:只问 2–3 个问题,开发环节各做一轮。</p><p><strong>需求的类型</strong>:AI 复述时会和你确认这是哪一类,流水线按类型走不同的做法:</p><table tabindex="0"><thead><tr><th>类型</th><th>说法举例</th><th>流水线怎么做</th><th>你需要讲清楚的</th></tr></thead><tbody><tr><td>新需求</td><td>"加一个……"</td><td>方案、实现、评审、验证</td><td>要什么、怎么算做对</td></tr><tr><td>缺陷</td><td>"……不对""报错了"</td><td>先复现、找到原因再修;复现不了会回来问你</td><td>复现步骤:环境、账号或数据、操作、看到的、应有的</td></tr><tr><td>重构</td><td>"整理一下……""升级依赖"</td><td>先用测试锁住现有行为,再小步改,确认行为没变</td><td>改进目标,以及哪些行为必须保持不变</td></tr><tr><td>评估</td><td>"能不能做……""影响多大"</td><td>只调研、写评估报告,由另一个模型审阅,不写代码</td><td>要回答的问题,结论用来做什么决定</td></tr></tbody></table><p>评估做完后,可以直接说"按评估结果提一个新需求"。</p><p><strong>前端和后端都要改</strong>:另一个仓库已经由开发同事登记过(<code>/req-setup</code> 时登记)的,AI 会问是否作为联合需求一起做:流水线先设计整体方案和双方的接口约定,再在每个仓库各开一个工作区同时开发,最后一起验证,报告里写明每个仓库的分支和合并顺序。</p><p><strong>验收标准带例子</strong>:AI 写验收标准时会给每条配上具体的数据("输入 13800000000,60 秒内再点发送,提示'请 45 秒后重试'")。请认真看这些例子:它们会直接变成测试检查的期望值,你确认的就是测试会检查的东西。</p><p><strong>开工前先看一眼"做完后会看到什么"</strong>(标准档的界面改动):方案审核通过后、写代码之前,流水线会停下来,AI 把 <code>preview.md</code> 的要点讲给你听:会看到什么变化、有哪些需要你确认的假设;界面改动还会有静态的原型页面(功能目录的 <code>prototype/</code> 中),可以在浏览器里打开看。说"可以"就开始写代码;想改的直接说,AI 会更新需求说明,方案调整后再请你看一次。这时调整的成本最低。</p><p><strong>研发和测试分开做</strong>(标准档,确定档位时 AI 会问,团队配置里定好了就不问):</p><ul><li><strong>连续</strong>(默认):研发完成后流水线接着做测试验证,一次跑完。</li><li><strong>分阶段</strong>:研发完成、写好提测说明(<code>handoff.md</code>)后停下来通知你:"研发完成,可以提测"。你或测试同事准备好之后说"开始测试验证",AI 会讲一遍提测说明,问清在哪里测(本地,或已部署的测试环境)、发现缺陷怎么办(当场修复、退回研发修复后再提测,或只记录),然后开始;也可以预约时间。用"开发时自动新建工作区"开发的需求,测试同事可以在自己的对话里输入 <code>/req 开始测试验证 <需求名称></code> 接手。</li><li><strong>只做研发</strong>:做到提测说明和研发报告为止,测试由人完成,验收时 AI 会按提测说明带你逐条测试。</li></ul><h2 id="过程中" tabindex="-1">过程中 <a class="header-anchor" href="#过程中" aria-label="Permalink to "过程中""></a></h2><table tabindex="0"><thead><tr><th>你想做的</th><th>在对话里说</th></tr></thead><tbody><tr><td>看进度</td><td>"做到哪了"(会说明当前在哪一步、agent 最近在做什么,例如正在运行测试)</td></tr><tr><td>暂停</td><td>"先停一下"(当前步骤做到一半的工作不保留,已完成的步骤保留)</td></tr><tr><td>继续</td><td>"继续开发"</td></tr><tr><td>确认方案</td><td>收到"请确认方案"时,看过之后说"可以,按这个做",或者说要改哪里</td></tr><tr><td>改需求</td><td>"我想改一下……":先暂停,谈清变化的部分,更新需求说明(版本加 1,记入 <code>changes.md</code>)后继续,开发会在已有方案和代码的基础上只处理变化的部分。开发已经完成的也可以改</td></tr><tr><td>看看项目里有哪些需求</td><td>"现在有哪些需求":列出所有工作区中的需求和各自的阶段</td></tr><tr><td>研发完成后提测</td><td>"开始测试验证"(分阶段执行时);想晚点开始就说"等测试环境部署好,明早 9 点开始测试"</td></tr><tr><td>晚点再开始</td><td>确认需求后说"今晚 10 点开始""明天早上开始":到时会在这个对话里自动开始,说"先停一下"可以取消</td></tr><tr><td>接手别人的需求</td><td>"这个需求之前是同事提的,现在什么情况":讲清现状、待决事项和下一步</td></tr></tbody></table><p>也可以不进对话,在终端里用 <code>req</code> 命令(需要开发同事装好并加入 PATH,见 <a href="./install">安装与升级</a>):在项目目录中 <code>req list</code> 看所有需求,<code>req status</code> 看进度(多个需求时写名称的一部分,如 <code>req status sms-login</code>),<code>req stop</code>、<code>req resume</code> 暂停和继续。</p><p>装了 req-kit 插件的话(见 <a href="./install">安装与升级</a> 第 13 节),在 Paseo 侧边栏点"需求":本机所有项目的需求一页看完,"需要你处理"的排在最前;点开一个需求能看到每一步的进度和用时、读需求说明、方案、确认预览和完成报告,也可以直接确认方案、停止、继续或开始测试验证。网页端、桌面版和手机上都能用。</p><p>1.12 起,首页最上面是"等你处理":所有等你确认方案、回答问题、中断了的需求,等得最久的在前,每条写明要做什么、等了多久。方案可以直接确认,也可以写修改意见;方案审核的问题可以直接写回答,插件会转给这个需求的对话,效果和在对话里回答一样。首页的"配置"列出 req-kit 的全部设置:每一项是什么、现在的值、来自本机、团队还是项目的配置文件,可以按项目查看、搜索、只看改过的。</p><p>每个步骤都会出现在这个对话的子 agent 列表里(名字形如"[20261012-sms-login] 6-代码评审 第2轮"),点开可以看到它在做什么。功能目录下的 <code>progress.md</code> 按时间记录了每一步的结果。</p><p>可能收到的通知(团队接入了企业 IM 的话,这些通知也会发到 IM):</p><ul><li><strong>需要你决定</strong>:方案审核发现只有你能回答的问题。AI 会逐个问你,然后继续。一天没有回答的话,会在对话里提醒一次。</li><li><strong>研发完成,可以提测</strong>(分阶段执行时):代码已写完并通过评审,提测说明在 <code>handoff.md</code>。一天没有开始测试验证的话,会在对话里提醒一次。</li><li><strong>等待批准</strong>:某一步在等权限批准,按提示打开对应的 agent 处理,或请开发同事处理。</li><li><strong>中断</strong>:限流、网络中断这类临时问题会先自动等待重试,仍然不行才中断,并预约半小时后自动继续(说"先停一下"可以取消)。AI 会说明原因和日志位置。环境类问题(例如测试服务没启动)你可以自己处理;涉及配置或代码的请开发同事处理。处理后说"继续开发"。</li></ul><h2 id="验收" tabindex="-1">验收 <a class="header-anchor" href="#验收" aria-label="Permalink to "验收""></a></h2><p>完成后你会收到结论和摘要,完整报告在功能目录的 <code>report.md</code>:</p><ul><li><strong>验收对照表</strong>:每条验收标准的结果,以及是怎么确认的(运行了什么命令、看到了什么、截图在哪里)。</li><li><strong>需要你确认的决定</strong>:开发过程中替你做的假设和取舍,以及被驳回的评审意见里会影响结果的那些。请逐条表态。</li><li><strong>遗留问题</strong>和<strong>需要你做的事</strong>。</li><li><strong>用时与用量</strong>:各步骤 agent 合计用了多长时间、多少 token、大约多少费用,便于估算后续需求的成本。</li></ul><p>然后说"我要验收"。AI 会按验收标准一条一条带你核对:告诉你怎么操作、应该看到什么;能用命令验证的给出命令,你可以自己执行。每条结果记入功能目录的 <code>acceptance.md</code>。</p><ul><li><strong>全部通过</strong>:请开发同事审阅代码并合并上线。流水线只做本地提交,不会自己合并或上线。</li><li><strong>有不通过的</strong>:逐项决定怎么处理:做得不对的,补进需求说明后继续开发;发现想要的不是这样的,按改需求处理;也可以接受现状并记下理由。</li></ul><p>测试同事可以把验收标准直接转成测试用例:每条都写成了"前置条件 / 操作 / 预期结果"。</p><h2 id="上线后发现问题" tabindex="-1">上线后发现问题 <a class="header-anchor" href="#上线后发现问题" aria-label="Permalink to "上线后发现问题""></a></h2><p>说"线上发现……不对"。AI 会先问这个问题是否正在影响真实用户:是的话,请马上联系开发同事或值班人员处理线上情况(req-kit 不碰生产环境)。然后它会问清现象、复现步骤、影响范围,关联到原来的需求,生成一份缺陷说明,按快速流程修复,修复后照常验收。</p><h2 id="注意" tabindex="-1">注意 <a class="header-anchor" href="#注意" aria-label="Permalink to "注意""></a></h2><ul><li>一个对话只谈一个需求;对话过程中不要切换工作目录。</li><li>需求属于另一个项目时,到那个项目里新开对话。</li><li>遇到"未启动"或其他看不懂的情况,输入 <code>/req-doctor</code> 做一次体检,或请开发同事看一下。</li></ul></div><p class="source-note">本页由仓库中的 <a href="https://github.com/yiyisf/paseo-req-kit/blob/main/docs/guide/使用者指南.md">docs/guide/使用者指南.md</a> 生成。<a href="https://github.com/yiyisf/paseo-req-kit/edit/main/docs/guide/使用者指南.md">在 GitHub 上编辑</a></p>',2)])])}const p=o(a,[["render",u]]);export{g as __pageData,p as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as o,o as e,c as d,a3 as r}from"./chunks/framework.B9qR_F1m.js";const g=JSON.parse('{"title":"使用者指南","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"guide/user.md","filePath":"guide/user.md","lastUpdated":null}'),a={name:"guide/user.md"};function u(s,t,i,l,q,n){return e(),d("div",null,[...t[0]||(t[0]=[r("",2)])])}const p=o(a,[["render",u]]);export{g as __pageData,p as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as e,o as t,c as i}from"./chunks/framework.B9qR_F1m.js";const p=JSON.parse('{"title":"req-kit","titleTemplate":"从一句需求,到可验收的功能","description":"","frontmatter":{"layout":"home","title":"req-kit","titleTemplate":"从一句需求,到可验收的功能","hero":{"name":"req-kit","text":"从一句需求,到可验收的功能","tagline":"在 Paseo 中用对话把需求谈清楚,由一组 AI agent 在后台完成方案设计、代码实现、评审和验证,结果发回同一个对话。","image":{"src":"/logo.svg","alt":"req-kit"},"actions":[{"theme":"brand","text":"快速开始","link":"/guide/getting-started"},{"theme":"alt","text":"req-kit 是什么","link":"/guide/"},{"theme":"alt","text":"GitHub","link":"https://github.com/yiyisf/paseo-req-kit"}]},"features":[{"icon":{"src":"/icons/chat.svg"},"title":"对话对齐需求","details":"一次一个问题,给出选项和推荐;把异常情况、权限、测试数据都问到。确认前还会请另一个模型独立审阅需求说明。"},{"icon":{"src":"/icons/agents.svg"},"title":"后台 agent 流水线","details":"方案设计、实现、评审、验证、报告依次由不同的 agent 完成;缺陷先复现再修、重构先锁住行为、评估只调研不写代码,大需求按切片逐片实现。"},{"icon":{"src":"/icons/review.svg"},"title":"质量门,如实报告","details":"流水线自己运行项目的 lint、测试、构建,改坏了发回修复;做事的和检查的分开,结论只看结果文件和证据,遗留问题如实写进报告。"},{"icon":{"src":"/icons/phases.svg"},"title":"分阶段提测","details":"研发完成写好提测说明,可以停下来交给测试同事,在测试环境中验证;发现缺陷可以退回研发,修完再提测。"},{"icon":{"src":"/icons/paseo.svg"},"title":"用好 Paseo","details":"复用 Paseo 的 agent profile、paseo.json 服务和 worktree、定时任务与内置浏览器;几个需求可以并行,前后端分仓的需求可以作为联合需求,每个仓库一个工作区同时开发。"},{"icon":{"src":"/icons/safe.svg"},"title":"安全边界清楚","details":"只做本地提交,不合并、不推送、不上线;不连接生产环境,测试环境说明里只写口令在哪里取。"}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1792020458000}'),s={name:"index.md"};function a(n,o,r,c,l,d){return t(),i("div")}const m=e(s,[["render",a]]);export{p as __pageData,m as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{_ as e,o as t,c as i}from"./chunks/framework.B9qR_F1m.js";const p=JSON.parse('{"title":"req-kit","titleTemplate":"从一句需求,到可验收的功能","description":"","frontmatter":{"layout":"home","title":"req-kit","titleTemplate":"从一句需求,到可验收的功能","hero":{"name":"req-kit","text":"从一句需求,到可验收的功能","tagline":"在 Paseo 中用对话把需求谈清楚,由一组 AI agent 在后台完成方案设计、代码实现、评审和验证,结果发回同一个对话。","image":{"src":"/logo.svg","alt":"req-kit"},"actions":[{"theme":"brand","text":"快速开始","link":"/guide/getting-started"},{"theme":"alt","text":"req-kit 是什么","link":"/guide/"},{"theme":"alt","text":"GitHub","link":"https://github.com/yiyisf/paseo-req-kit"}]},"features":[{"icon":{"src":"/icons/chat.svg"},"title":"对话对齐需求","details":"一次一个问题,给出选项和推荐;把异常情况、权限、测试数据都问到。确认前还会请另一个模型独立审阅需求说明。"},{"icon":{"src":"/icons/agents.svg"},"title":"后台 agent 流水线","details":"方案设计、实现、评审、验证、报告依次由不同的 agent 完成;缺陷先复现再修、重构先锁住行为、评估只调研不写代码,大需求按切片逐片实现。"},{"icon":{"src":"/icons/review.svg"},"title":"质量门,如实报告","details":"流水线自己运行项目的 lint、测试、构建,改坏了发回修复;做事的和检查的分开,结论只看结果文件和证据,遗留问题如实写进报告。"},{"icon":{"src":"/icons/phases.svg"},"title":"分阶段提测","details":"研发完成写好提测说明,可以停下来交给测试同事,在测试环境中验证;发现缺陷可以退回研发,修完再提测。"},{"icon":{"src":"/icons/paseo.svg"},"title":"用好 Paseo","details":"复用 Paseo 的 agent profile、paseo.json 服务和 worktree、定时任务与内置浏览器;几个需求可以并行,前后端分仓的需求可以作为联合需求,每个仓库一个工作区同时开发。"},{"icon":{"src":"/icons/safe.svg"},"title":"安全边界清楚","details":"只做本地提交,不合并、不推送、不上线;不连接生产环境,测试环境说明里只写口令在哪里取。"}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1792020458000}'),s={name:"index.md"};function a(n,o,r,c,l,d){return t(),i("div")}const m=e(s,[["render",a]]);export{p as __pageData,m as default};
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|