paseo-req-kit 1.14.0-beta.4 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/bin/req.mjs +6 -0
  3. package/contracts/notifier-event.md +1 -1
  4. package/contracts/spec.md +1 -0
  5. package/contracts/state.md +3 -1
  6. package/contracts/usage-record.md +16 -2
  7. package/docs/guide//344/275/277/347/224/250/350/200/205/346/214/207/345/215/227.md +3 -1
  8. package/docs/guide//351/241/271/347/233/256/345/256/232/345/210/266/344/270/216/350/277/220/350/241/214/350/247/204/345/210/231.md +17 -1
  9. package/engine/prompts/00-shared-context.md +3 -2
  10. package/engine/src/activity.ts +21 -0
  11. package/engine/src/api.ts +30 -5
  12. package/engine/src/code-review.ts +3 -0
  13. package/engine/src/config-view.ts +10 -0
  14. package/engine/src/config.ts +27 -0
  15. package/engine/src/danger-guard.ts +180 -0
  16. package/engine/src/features.ts +1 -1
  17. package/engine/src/messages.ts +29 -0
  18. package/engine/src/outcomes.ts +145 -0
  19. package/engine/src/paseo-runtime.ts +9 -1
  20. package/engine/src/pipeline.ts +135 -6
  21. package/engine/src/records.ts +71 -0
  22. package/engine/src/reply.ts +30 -11
  23. package/engine/src/review.ts +15 -1
  24. package/engine/src/runtime.ts +2 -0
  25. package/engine/src/secret-scan.ts +177 -0
  26. package/engine/src/state.ts +30 -0
  27. package/engine/src/stats.ts +143 -9
  28. package/engine/src/watchdog.ts +38 -4
  29. package/package.json +1 -1
  30. package/paseo-plugin/client/stats.tsx +15 -0
  31. package/paseo-plugin/package.json +1 -1
  32. package/paseo-plugin/shared/contracts.ts +7 -0
  33. package/site-dist/404.html +2 -2
  34. package/site-dist/assets/{app.Cp7WwPWE.js → app.VQ-QxRPH.js} +1 -1
  35. package/site-dist/assets/changelog.md.CIKYJXpF.js +1 -0
  36. package/site-dist/assets/{changelog.md.Zi-_3Rjh.lean.js → changelog.md.CIKYJXpF.lean.js} +1 -1
  37. package/site-dist/assets/chunks/@localSearchIndexroot.h7oQE_np.js +1 -0
  38. package/site-dist/assets/chunks/{VPLocalSearchBox.CMTXQK-Q.js → VPLocalSearchBox.CT4Vlj76.js} +1 -1
  39. package/site-dist/assets/chunks/{theme.DvVUfKr3.js → theme.B_UmHHou.js} +2 -2
  40. package/site-dist/assets/{guide_getting-started.md.D8XlIQOg.js → guide_getting-started.md.CZM53rO_.js} +1 -1
  41. package/site-dist/assets/{guide_project.md.Csi5wiyt.js → guide_project.md.DIjDRoAq.js} +1 -1
  42. package/site-dist/assets/{guide_project.md.Csi5wiyt.lean.js → guide_project.md.DIjDRoAq.lean.js} +1 -1
  43. package/site-dist/assets/{guide_user.md.B4N9ywmr.js → guide_user.md.UV0WxdJa.js} +1 -1
  44. package/site-dist/assets/{guide_user.md.B4N9ywmr.lean.js → guide_user.md.UV0WxdJa.lean.js} +1 -1
  45. package/site-dist/assets/{reference_contracts_notifier-event.md.CCfrkm_A.js → reference_contracts_notifier-event.md.B9WqeZdO.js} +1 -1
  46. package/site-dist/assets/{reference_contracts_notifier-event.md.CCfrkm_A.lean.js → reference_contracts_notifier-event.md.B9WqeZdO.lean.js} +1 -1
  47. package/site-dist/assets/{reference_contracts_spec.md.BwwS0L_j.js → reference_contracts_spec.md.Dh5XczZL.js} +2 -2
  48. package/site-dist/assets/{reference_contracts_spec.md.BwwS0L_j.lean.js → reference_contracts_spec.md.Dh5XczZL.lean.js} +2 -2
  49. package/site-dist/assets/reference_contracts_state.md.STlqkPPS.js +1 -0
  50. package/site-dist/assets/{reference_contracts_usage-record.md.D5krNLW7.lean.js → reference_contracts_usage-record.md.MjVps4CA.js} +2 -2
  51. package/site-dist/assets/{reference_contracts_usage-record.md.D5krNLW7.js → reference_contracts_usage-record.md.MjVps4CA.lean.js} +2 -2
  52. package/site-dist/changelog.html +5 -5
  53. package/site-dist/guide/getting-started.html +5 -5
  54. package/site-dist/guide/how-it-works.html +4 -4
  55. package/site-dist/guide/index.html +4 -4
  56. package/site-dist/guide/install.html +4 -4
  57. package/site-dist/guide/maintainer.html +4 -4
  58. package/site-dist/guide/phases.html +4 -4
  59. package/site-dist/guide/project.html +6 -6
  60. package/site-dist/guide/user.html +5 -5
  61. package/site-dist/hashmap.json +1 -1
  62. package/site-dist/index.html +4 -4
  63. package/site-dist/reference/adr/0001-step-agents-under-origin-chat.html +4 -4
  64. package/site-dist/reference/adr/0002-no-directory-switch-in-chat.html +4 -4
  65. package/site-dist/reference/adr/0003-script-engine-not-hub.html +4 -4
  66. package/site-dist/reference/adr/0004-result-files.html +4 -4
  67. package/site-dist/reference/adr/0005-no-default-branch-local-commits-only.html +4 -4
  68. package/site-dist/reference/adr/0006-skill-install-targets.html +4 -4
  69. package/site-dist/reference/adr/0007-own-interview-skill.html +4 -4
  70. package/site-dist/reference/adr/0008-entries-do-not-call-entries.html +4 -4
  71. package/site-dist/reference/adr/0009-versioned-install-layout.html +4 -4
  72. package/site-dist/reference/adr/0010-generated-feature-overview.html +4 -4
  73. package/site-dist/reference/adr/0011-resume-after-completion.html +4 -4
  74. package/site-dist/reference/adr/0012-review-panel.html +4 -4
  75. package/site-dist/reference/adr/0013-no-release-tooling.html +4 -4
  76. package/site-dist/reference/adr/0014-notifier-slot.html +4 -4
  77. package/site-dist/reference/adr/0015-incremental-continue.html +4 -4
  78. package/site-dist/reference/adr/0016-upgrade-from-tags.html +4 -4
  79. package/site-dist/reference/adr/0017-use-paseo-capabilities.html +4 -4
  80. package/site-dist/reference/adr/0018-own-worktree-option.html +4 -4
  81. package/site-dist/reference/adr/0019-parallel-orchestration.html +4 -4
  82. package/site-dist/reference/adr/0020-scheduling-through-the-chat.html +4 -4
  83. package/site-dist/reference/adr/0021-npm-version-manager.html +4 -4
  84. package/site-dist/reference/adr/0022-develop-and-verify-phases.html +4 -4
  85. package/site-dist/reference/adr/0023-types-gate-slices.html +4 -4
  86. package/site-dist/reference/adr/0024-confirm-early-review-axes.html +4 -4
  87. package/site-dist/reference/adr/0025-joint-requirements.html +4 -4
  88. package/site-dist/reference/adr/0026-machine-records-and-api.html +4 -4
  89. package/site-dist/reference/adr/0027-paseo-plugin.html +4 -4
  90. package/site-dist/reference/adr/0028-external-integrations.html +4 -4
  91. package/site-dist/reference/adr/0029-requirements-from-cards.html +4 -4
  92. package/site-dist/reference/adr/0030-card-intake-process.html +4 -4
  93. package/site-dist/reference/adr/0031-fewer-interventions.html +4 -4
  94. package/site-dist/reference/adr/0032-npm-only-install.html +4 -4
  95. package/site-dist/reference/adr/0033-prototype-review-and-ui-check.html +4 -4
  96. package/site-dist/reference/adr/index.html +4 -4
  97. package/site-dist/reference/commands.html +4 -4
  98. package/site-dist/reference/config.html +4 -4
  99. package/site-dist/reference/contracts/cli-json.html +4 -4
  100. package/site-dist/reference/contracts/feature-files.html +4 -4
  101. package/site-dist/reference/contracts/index.html +4 -4
  102. package/site-dist/reference/contracts/notifier-event.html +6 -6
  103. package/site-dist/reference/contracts/result-file.html +4 -4
  104. package/site-dist/reference/contracts/spec.html +6 -6
  105. package/site-dist/reference/contracts/state.html +5 -5
  106. package/site-dist/reference/contracts/usage-record.html +6 -6
  107. package/site-dist/reference/contracts/verify.html +4 -4
  108. package/site-dist/reference/scope.html +4 -4
  109. package/skills/req/SKILL.md +1 -0
  110. package/skills/req/playbooks/incident.md +1 -1
  111. package/skills/spec-writing/SKILL.md +2 -1
  112. package/site-dist/assets/changelog.md.Zi-_3Rjh.js +0 -1
  113. package/site-dist/assets/chunks/@localSearchIndexroot.COxp5Rrc.js +0 -1
  114. package/site-dist/assets/reference_contracts_state.md.EEBd_l2P.js +0 -1
  115. /package/site-dist/assets/{guide_getting-started.md.D8XlIQOg.lean.js → guide_getting-started.md.CZM53rO_.lean.js} +0 -0
  116. /package/site-dist/assets/{reference_contracts_state.md.EEBd_l2P.lean.js → reference_contracts_state.md.STlqkPPS.lean.js} +0 -0
@@ -1,4 +1,4 @@
1
- import{_ as n,o as i,c as t,j as e,a as l}from"./chunks/framework.B9qR_F1m.js";const p=JSON.parse('{"title":"本机的需求索引与使用记录","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"reference/contracts/usage-record.md","filePath":"reference/contracts/usage-record.md","lastUpdated":null}'),a={name:"reference/contracts/usage-record.md"};function d(o,s,r,u,c,h){return i(),t("div",null,[...s[0]||(s[0]=[e("div",null,[e("h1",{id:"本机的需求索引与使用记录",tabindex:"-1"},[l("本机的需求索引与使用记录 "),e("a",{class:"header-anchor",href:"#本机的需求索引与使用记录","aria-label":'Permalink to "本机的需求索引与使用记录"'},"​")]),e("p",null,[l("1.9.0 起,引擎在本机配置目录(默认 "),e("code",null,"~/.req-kit"),l(",可用 "),e("code",null,"REQ_KIT_HOME"),l(" 改变)下记两样东西。它们只在这台机器上,不提交进任何仓库,也不会自动发往任何地方。环境变量 "),e("code",null,"REQ_KIT_NO_RECORD=1"),l(" 时两样都不记(评估运行就是这样)。")]),e("h2",{id:"需求索引-index-key-json",tabindex:"-1"},[l("需求索引 "),e("code",null,"index/<key>.json"),l(),e("a",{class:"header-anchor",href:"#需求索引-index-key-json","aria-label":'Permalink to "需求索引 `index/<key>.json`"'},"​")]),e("p",null,[l("每个在本机运行过的需求一个文件,记录它在哪里,供 "),e("code",null,"req api list --all"),l(" 和 Paseo 插件找到本机所有的需求。需求的阶段、进度仍然现场从功能目录读取(ADR 0010)。")]),e("div",{class:"language-json vp-adaptive-theme"},[e("button",{title:"Copy Code",class:"copy"}),e("span",{class:"lang"},"json"),e("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[e("code",null,[e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"{")]),l(`
1
+ import{_ as s,o as t,c as i,j as e,a as l}from"./chunks/framework.B9qR_F1m.js";const p=JSON.parse('{"title":"本机的需求索引与使用记录","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"reference/contracts/usage-record.md","filePath":"reference/contracts/usage-record.md","lastUpdated":null}'),d={name:"reference/contracts/usage-record.md"};function a(o,n,u,c,r,h){return t(),i("div",null,[...n[0]||(n[0]=[e("div",null,[e("h1",{id:"本机的需求索引与使用记录",tabindex:"-1"},[l("本机的需求索引与使用记录 "),e("a",{class:"header-anchor",href:"#本机的需求索引与使用记录","aria-label":'Permalink to "本机的需求索引与使用记录"'},"​")]),e("p",null,[l("1.9.0 起,引擎在本机配置目录(默认 "),e("code",null,"~/.req-kit"),l(",可用 "),e("code",null,"REQ_KIT_HOME"),l(" 改变)下记两样东西。它们只在这台机器上,不提交进任何仓库,也不会自动发往任何地方。环境变量 "),e("code",null,"REQ_KIT_NO_RECORD=1"),l(" 时两样都不记(评估运行就是这样)。")]),e("h2",{id:"需求索引-index-key-json",tabindex:"-1"},[l("需求索引 "),e("code",null,"index/<key>.json"),l(),e("a",{class:"header-anchor",href:"#需求索引-index-key-json","aria-label":'Permalink to "需求索引 `index/<key>.json`"'},"​")]),e("p",null,[l("每个在本机运行过的需求一个文件,记录它在哪里,供 "),e("code",null,"req api list --all"),l(" 和 Paseo 插件找到本机所有的需求。需求的阶段、进度仍然现场从功能目录读取(ADR 0010)。")]),e("div",{class:"language-json vp-adaptive-theme"},[e("button",{title:"Copy Code",class:"copy"}),e("span",{class:"lang"},"json"),e("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[e("code",null,[e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"{")]),l(`
2
2
  `),e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "schema"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),e("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},"1"),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
3
3
  `),e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "key"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),e("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"3f2a9c1e5b7d4e8a"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
4
4
  `),e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "repo"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),e("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"/home/me/work/shop-sms-login"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
@@ -7,4 +7,4 @@ import{_ as n,o as i,c as t,j as e,a as l}from"./chunks/framework.B9qR_F1m.js";c
7
7
  `),e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "workspaceId"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),e("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"ws_123"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
8
8
  `),e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "project"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),e("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"shop"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
9
9
  `),e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "registeredAt"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),e("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"2026-10-12T09:00:00.000Z"')]),l(`
10
- `),e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"}")])])])]),e("p",null,[e("code",null,"key"),l(" 由对话所在的目录(没有自己的工作区时即 "),e("code",null,"repo"),l(")和功能目录算出。1.14 起:开始谈需求时("),e("code",null,"start-pipeline --feature <功能目录> --track"),l(")就登记,此时多一个可选字段 "),e("code",null,"chatAgentId"),l("(谈需求的对话),之后的登记保留它;新建需求自己的工作区时,条目改为指向那个工作区。目录里有 "),e("code",null,"spec.md"),l("、"),e("code",null,"alignment.md"),l(" 或 "),e("code",null,".pipeline/"),l(" 下的状态或登记标记时算作存在。")]),e("h2",{id:"新建工作区的记录-worktrees-key-json-1-14",tabindex:"-1"},[l("新建工作区的记录 "),e("code",null,"worktrees/<key>.json"),l("(1.14) "),e("a",{class:"header-anchor",href:"#新建工作区的记录-worktrees-key-json-1-14","aria-label":'Permalink to "新建工作区的记录 `worktrees/<key>.json`(1.14)"'},"​")]),e("p",null,[l("用 "),e("code",null,"--worktree"),l(" 启动时,工作区一建好就写下:"),e("code",null,"{ schema, sourceRepo, featureDir, repo, workspaceId, branch, baseRef, createdAt, originAgentId }"),l('。之后的启动失败了,再次启动时在这个工作区里接着做,不再新建;插件据此把"工作区已建、开发没开始"的需求列进"等你处理"。'),e("code",null,"req index --rebuild"),l(" 为 1.9 之前运行过的需求补登,"),e("code",null,"req index --prune"),l(" 移除目录已不在的。")]),e("h2",{id:"使用记录-usage-runs-jsonl",tabindex:"-1"},[l("使用记录 "),e("code",null,"usage/runs.jsonl"),l(),e("a",{class:"header-anchor",href:"#使用记录-usage-runs-jsonl","aria-label":'Permalink to "使用记录 `usage/runs.jsonl`"'},"​")]),e("p",null,"每次流水线运行(后台进程从开始到结束,包括停在等待确认、等待需求方、研发完成处)结束时追加一行:"),e("table",{tabindex:"0"},[e("thead",null,[e("tr",null,[e("th",null,"字段"),e("th",null,"含义")])]),e("tbody",null,[e("tr",null,[e("td",null,[e("code",null,"schema"),l(" / "),e("code",null,"kind")]),e("td",null,[e("code",null,"1"),l(" / "),e("code",null,'"run"')])]),e("tr",null,[e("td",null,[e("code",null,"machine"),l(" / "),e("code",null,"kitVersion")]),e("td",null,"主机名、req-kit 版本")]),e("tr",null,[e("td",null,[e("code",null,"requirement")]),e("td",null,[e("code",null,"{ key, project, name, title, type, profile }"),l(";从卡片开始的需求(1.10 起)另有 "),e("code",null,"requester"),l("(卡片的提出人)和 "),e("code",null,"source"),l("("),e("code",null,"{ system, id }"),l(")")])]),e("tr",null,[e("td",null,[e("code",null,"steps[].cachedInputTokens"),l(" / "),e("code",null,"steps[].agent")]),e("td",null,'1.13 起。输入中来自提示缓存的 tokens(agent 报告时);这一步用的 agent(Paseo profile 名,或 "provider/model")。更早的记录没有')]),e("tr",null,[e("td",null,[e("code",null,"run")]),e("td",null,[e("code",null,"{ startedAt, endedAt, attempt, phase, phaseMode, status, outcome, stopReason, stopKind, recoveries }"),l(";"),e("code",null,"status"),l(" 是运行结束时的状态,"),e("code",null,"outcome"),l(" 是完成时报告的结论;"),e("code",null,"stopKind"),l("(1.12 起)是停下等人的原因代码(见 "),e("a",{href:"./state"},"state.md"),l("),"),e("code",null,"recoveries"),l("(1.12 起)是这次运行中自动处理的次数,按种类,如 "),e("code",null,'{ "retry": 2 }'),l("。更早的记录没有这两项")])]),e("tr",null,[e("td",null,[e("code",null,"agents")]),e("td",null,[e("code",null,"{ builder, reviewer }"),l(":当时配置的 agent(如 "),e("code",null,"claude/opus(bypassPermissions)"),l(")")])]),e("tr",null,[e("td",null,[e("code",null,"steps")]),e("td",null,[l("这次运行中开始的步骤:"),e("code",null,"{ key, stepId, phase, attempt, round, startedAt, endedAt, minutes, outcome, inputTokens, outputTokens, costUsd }"),l(";agent 没有报告的用量为 null")])]),e("tr",null,[e("td",null,[e("code",null,"gate")]),e("td",null,[e("code",null,"{ runs, failed }"),l(":这次运行中质量门运行的次数、发现新失败的次数")])])])]),e("p",null,"不记录需求内容、代码和对话。"),e("h2",{id:"统计口径-req-stats",tabindex:"-1"},[l("统计口径("),e("code",null,"req stats"),l(") "),e("a",{class:"header-anchor",href:"#统计口径-req-stats","aria-label":'Permalink to "统计口径(`req stats`)"'},"​")]),e("ul",null,[e("li",null,"一段时间的用量、步骤用时:结束时间在这段时间内的运行。"),e("li",null,'交付周期:需求第一次开始到完成(最后一次运行以"已完成"结束)的小时数,用这个需求的全部运行,算在完成的那段时间。'),e("li",null,"代码评审轮数、缺陷修复轮数:不同的(尝试、轮次、仓库)个数;评审分方向或评审小组的几个成员算一轮。"),e("li",null,"等待:相邻两次运行之间的间隔,按前一次结束时的状态归类:等待确认方案、等待需求方决定、研发完成到开始测试验证、中断到继续。"),e("li",null,[l("token 花在哪(1.13 起,"),e("code",null,"tokens"),l("):这段时间的步骤按 "),e("code",null,"stepId"),l("、按 "),e("code",null,"agent"),l(" 合计 token(输入 + 输出)和占比;返工("),e("code",null,"design_revise"),l("、"),e("code",null,"review_fix"),l("、"),e("code",null,"defect_fix"),l("、"),e("code",null,"reverify"),l(",以及 "),e("code",null,"design_review"),l("、"),e("code",null,"code_review"),l(" 第 2 轮起)的合计和占比;报告了 "),e("code",null,"cachedInputTokens"),l(" 的,算出输入中来自提示缓存的比例;已完成需求的 token 中位数(按档位)。")]),e("li",null,[l("停下等人的原因(1.12 起):这段时间结束的运行按 "),e("code",null,"stopKind"),l(" 计数;更早的记录按结束时的状态推断。确认方案、研发完成等待测试是必要的决定。")]),e("li",null,"无人工到提测的比例(1.12 起):这段时间有进展、已经研发完成或完成的需求中,所有运行都只停在必要决定处的比例。"),e("li",null,"自动处理的比例(1.12 起):自动处理的次数 ÷(自动处理的次数 + 以中断结束的运行数);需求方决定、缺陷复现不了不算中断。"),e("li",null,"合并多台机器的导出时,同一机器、同一需求、同一开始时间的运行只算一次。")]),e("p",null,[e("code",null,"req stats --json"),l(" 和 "),e("code",null,"req api stats"),l(" 输出同样的对象("),e("code",null,"schema: 1"),l("):"),e("code",null,"period"),l("、"),e("code",null,"machines"),l("、"),e("code",null,"active"),l("、"),e("code",null,"completed"),l("、"),e("code",null,"byType"),l("、"),e("code",null,"cycleHours"),l("、"),e("code",null,"steps"),l("、"),e("code",null,"rework"),l("、"),e("code",null,"waits"),l("、"),e("code",null,"usage"),l("、"),e("code",null,"byBuilder"),l("、"),e("code",null,"requirements"),l("(每个需求一项,字段与 "),e("code",null,"req stats --csv"),l(" 的列对应)。")])],-1),e("p",{class:"source-note"},[l("本页由仓库中的 "),e("a",{href:"https://github.com/yiyisf/paseo-req-kit/blob/main/contracts/usage-record.md"},"contracts/usage-record.md"),l(" 生成。"),e("a",{href:"https://github.com/yiyisf/paseo-req-kit/edit/main/contracts/usage-record.md"},"在 GitHub 上编辑")],-1)])])}const E=n(a,[["render",d]]);export{p as __pageData,E as default};
10
+ `),e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"}")])])])]),e("p",null,[e("code",null,"key"),l(" 由对话所在的目录(没有自己的工作区时即 "),e("code",null,"repo"),l(")和功能目录算出。1.14 起:开始谈需求时("),e("code",null,"start-pipeline --feature <功能目录> --track"),l(")就登记,此时多一个可选字段 "),e("code",null,"chatAgentId"),l("(谈需求的对话),之后的登记保留它;新建需求自己的工作区时,条目改为指向那个工作区。目录里有 "),e("code",null,"spec.md"),l("、"),e("code",null,"alignment.md"),l(" 或 "),e("code",null,".pipeline/"),l(" 下的状态或登记标记时算作存在。")]),e("h2",{id:"新建工作区的记录-worktrees-key-json-1-14",tabindex:"-1"},[l("新建工作区的记录 "),e("code",null,"worktrees/<key>.json"),l("(1.14) "),e("a",{class:"header-anchor",href:"#新建工作区的记录-worktrees-key-json-1-14","aria-label":'Permalink to "新建工作区的记录 `worktrees/<key>.json`(1.14)"'},"​")]),e("p",null,[l("用 "),e("code",null,"--worktree"),l(" 启动时,工作区一建好就写下:"),e("code",null,"{ schema, sourceRepo, featureDir, repo, workspaceId, branch, baseRef, createdAt, originAgentId }"),l('。之后的启动失败了,再次启动时在这个工作区里接着做,不再新建;插件据此把"工作区已建、开发没开始"的需求列进"等你处理"。'),e("code",null,"req index --rebuild"),l(" 为 1.9 之前运行过的需求补登,"),e("code",null,"req index --prune"),l(" 移除目录已不在的。")]),e("h2",{id:"使用记录-usage-runs-jsonl",tabindex:"-1"},[l("使用记录 "),e("code",null,"usage/runs.jsonl"),l(),e("a",{class:"header-anchor",href:"#使用记录-usage-runs-jsonl","aria-label":'Permalink to "使用记录 `usage/runs.jsonl`"'},"​")]),e("p",null,"每次流水线运行(后台进程从开始到结束,包括停在等待确认、等待需求方、研发完成处)结束时追加一行:"),e("table",{tabindex:"0"},[e("thead",null,[e("tr",null,[e("th",null,"字段"),e("th",null,"含义")])]),e("tbody",null,[e("tr",null,[e("td",null,[e("code",null,"schema"),l(" / "),e("code",null,"kind")]),e("td",null,[e("code",null,"1"),l(" / "),e("code",null,'"run"')])]),e("tr",null,[e("td",null,[e("code",null,"machine"),l(" / "),e("code",null,"kitVersion")]),e("td",null,"主机名、req-kit 版本")]),e("tr",null,[e("td",null,[e("code",null,"requirement")]),e("td",null,[e("code",null,"{ key, project, name, title, type, profile }"),l(";从卡片开始的需求(1.10 起)另有 "),e("code",null,"requester"),l("(卡片的提出人)和 "),e("code",null,"source"),l("("),e("code",null,"{ system, id }"),l(")")])]),e("tr",null,[e("td",null,[e("code",null,"steps[].cachedInputTokens"),l(" / "),e("code",null,"steps[].agent")]),e("td",null,'1.13 起。输入中来自提示缓存的 tokens(agent 报告时);这一步用的 agent(Paseo profile 名,或 "provider/model")。更早的记录没有')]),e("tr",null,[e("td",null,[e("code",null,"run")]),e("td",null,[e("code",null,"{ startedAt, endedAt, attempt, phase, phaseMode, status, outcome, stopReason, stopKind, recoveries }"),l(";"),e("code",null,"status"),l(" 是运行结束时的状态,"),e("code",null,"outcome"),l(" 是完成时报告的结论;"),e("code",null,"stopKind"),l("(1.12 起)是停下等人的原因代码(见 "),e("a",{href:"./state"},"state.md"),l("),"),e("code",null,"recoveries"),l("(1.12 起)是这次运行中自动处理的次数,按种类,如 "),e("code",null,'{ "retry": 2 }'),l("。更早的记录没有这两项")])]),e("tr",null,[e("td",null,[e("code",null,"agents")]),e("td",null,[e("code",null,"{ builder, reviewer }"),l(":当时配置的 agent(如 "),e("code",null,"claude/opus(bypassPermissions)"),l(")")])]),e("tr",null,[e("td",null,[e("code",null,"steps")]),e("td",null,[l("这次运行中开始的步骤:"),e("code",null,"{ key, stepId, phase, attempt, round, startedAt, endedAt, minutes, outcome, inputTokens, outputTokens, costUsd }"),l(";agent 没有报告的用量为 null")])]),e("tr",null,[e("td",null,[e("code",null,"gate")]),e("td",null,[e("code",null,"{ runs, failed }"),l(":这次运行中质量门运行的次数、发现新失败的次数")])])])]),e("p",null,"不记录需求内容、代码和对话。"),e("h3",{id:"运行之后的事-1-14-起",tabindex:"-1"},[l("运行之后的事(1.14 起) "),e("a",{class:"header-anchor",href:"#运行之后的事-1-14-起","aria-label":'Permalink to "运行之后的事(1.14 起)"'},"​")]),e("p",null,[l("同一个文件里还有几种记录,都有 "),e("code",null,"schema"),l("(1)、"),e("code",null,"kind"),l("、"),e("code",null,"machine"),l("、"),e("code",null,"kitVersion"),l("、"),e("code",null,"at"),l(" 和 "),e("code",null,"requirement"),l("("),e("code",null,"{ key, project, name, title }"),l(","),e("code",null,"key"),l(" 与运行记录相同)。读运行记录的旧版本会跳过它们。")]),e("table",{tabindex:"0"},[e("thead",null,[e("tr",null,[e("th",null,[e("code",null,"kind")]),e("th",null,"何时写"),e("th",null,"字段")])]),e("tbody",null,[e("tr",null,[e("td",null,[e("code",null,"review")]),e("td",null,'插件代码审查页提交"退回修改"或"评审通过"'),e("td",null,[e("code",null,'review: { verdict: "approved" | "changes_requested", reviewer, items, head }'),l(":评审人、意见条数、评审的提交")])]),e("tr",null,[e("td",null,[e("code",null,"acceptance")]),e("td",null,"验收清单页提交"),e("td",null,[e("code",null,'acceptance: { verdict: "通过" | "不通过", reviewer, total, passed, failed, unchecked }')])]),e("tr",null,[e("td",null,[e("code",null,"merge")]),e("td",null,[e("code",null,"req stats"),l("、"),e("code",null,"req api stats"),l("、"),e("code",null,"req outcome"),l(" 发现需求的流水线文件("),e("code",null,"implementation.md"),l("、"),e("code",null,"report.md"),l(" 等)已经在主干("),e("code",null,"origin/HEAD"),l(",没有时 "),e("code",null,"origin/main"),l("、"),e("code",null,"main"),l(" 等)里;或者 "),e("code",null,"req outcome <需求> --merged")]),e("td",null,[e("code",null,'merge: { into, commit, mergedAt, how: "files" | "manual" }'),l(":"),e("code",null,"commit"),l("、"),e("code",null,"mergedAt"),l(" 是把它带进主干的那次提交(合并提交或压缩合并的提交);只看本机已有的分支,不 fetch")])]),e("tr",null,[e("td",null,[e("code",null,"issue")]),e("td",null,[l("缺陷需求的 spec 写了 "),e("code",null,"- 引入问题的需求:<目录名>"),l("(扫描时发现),或者 "),e("code",null,'req outcome <需求> --issue "<问题>"')]),e("td",null,[e("code",null,"issue: { text, by, id }"),l(":"),e("code",null,"by"),l(" 是那个缺陷需求的目录名,手动记的为 null;同一个 "),e("code",null,"id"),l(" 只算一次")])])])]),e("p",null,[l("每个需求的 "),e("code",null,"merge"),l(" 只记一次。评审和验收的全文在需求目录的 "),e("code",null,"code-review.md"),l("、"),e("code",null,"acceptance.md"),l(" 里,随需求分支提交;这里只记结论和数量,用于统计。")]),e("h2",{id:"统计口径-req-stats",tabindex:"-1"},[l("统计口径("),e("code",null,"req stats"),l(") "),e("a",{class:"header-anchor",href:"#统计口径-req-stats","aria-label":'Permalink to "统计口径(`req stats`)"'},"​")]),e("ul",null,[e("li",null,"一段时间的用量、步骤用时:结束时间在这段时间内的运行。"),e("li",null,'交付周期:需求第一次开始到完成(最后一次运行以"已完成"结束)的小时数,用这个需求的全部运行,算在完成的那段时间。'),e("li",null,"代码评审轮数、缺陷修复轮数:不同的(尝试、轮次、仓库)个数;评审分方向或评审小组的几个成员算一轮。"),e("li",null,"等待:相邻两次运行之间的间隔,按前一次结束时的状态归类:等待确认方案、等待需求方决定、研发完成到开始测试验证、中断到继续。"),e("li",null,[l("token 花在哪(1.13 起,"),e("code",null,"tokens"),l("):这段时间的步骤按 "),e("code",null,"stepId"),l("、按 "),e("code",null,"agent"),l(" 合计 token(输入 + 输出)和占比;返工("),e("code",null,"design_revise"),l("、"),e("code",null,"review_fix"),l("、"),e("code",null,"defect_fix"),l("、"),e("code",null,"reverify"),l(",以及 "),e("code",null,"design_review"),l("、"),e("code",null,"code_review"),l(" 第 2 轮起)的合计和占比;报告了 "),e("code",null,"cachedInputTokens"),l(" 的,算出输入中来自提示缓存的比例;已完成需求的 token 中位数(按档位)。")]),e("li",null,[l("停下等人的原因(1.12 起):这段时间结束的运行按 "),e("code",null,"stopKind"),l(" 计数;更早的记录按结束时的状态推断。确认方案、研发完成等待测试是必要的决定。")]),e("li",null,"无人工到提测的比例(1.12 起):这段时间有进展、已经研发完成或完成的需求中,所有运行都只停在必要决定处的比例。"),e("li",null,"自动处理的比例(1.12 起):自动处理的次数 ÷(自动处理的次数 + 以中断结束的运行数);需求方决定、缺陷复现不了不算中断。"),e("li",null,[l("人工把关和合并后(1.14 起,"),e("code",null,"oversight"),l('):这段时间里的人工代码评审次数、退回修改次数、意见条数,验收次数和不通过次数;"第一次就通过"看每个需求最早的那次评审(验收),它在这段时间里并且是通过;合并进主干的需求数和"完成到合并"的小时数中位数;合并后发现的问题数和涉及的需求数。每个需求一项里的 '),e("code",null,"afterRun"),l(" 汇总它全部的这类记录("),e("code",null,"humanReviews"),l("、"),e("code",null,"sentBack"),l("、"),e("code",null,"lastReview"),l("、"),e("code",null,"acceptance"),l("、"),e("code",null,"acceptanceFailed"),l("、"),e("code",null,"mergedAt"),l("、"),e("code",null,"issues"),l(")。")]),e("li",null,[l("合并多台机器的导出时,同一机器、同一需求、同一开始时间的运行只算一次;同一个需求、同一种、同一时间的事件(问题按 "),e("code",null,"id"),l(")只算一次。"),e("code",null,"req stats --export"),l(" 同时导出这些需求的事件。")])]),e("p",null,[e("code",null,"req stats --json"),l(" 和 "),e("code",null,"req api stats"),l(" 输出同样的对象("),e("code",null,"schema: 1"),l("):"),e("code",null,"period"),l("、"),e("code",null,"machines"),l("、"),e("code",null,"active"),l("、"),e("code",null,"completed"),l("、"),e("code",null,"byType"),l("、"),e("code",null,"cycleHours"),l("、"),e("code",null,"steps"),l("、"),e("code",null,"rework"),l("、"),e("code",null,"waits"),l("、"),e("code",null,"usage"),l("、"),e("code",null,"tokens"),l("、"),e("code",null,"oversight"),l("、"),e("code",null,"byBuilder"),l("、"),e("code",null,"requirements"),l("(每个需求一项,字段与 "),e("code",null,"req stats --csv"),l(" 的列对应)。")])],-1),e("p",{class:"source-note"},[l("本页由仓库中的 "),e("a",{href:"https://github.com/yiyisf/paseo-req-kit/blob/main/contracts/usage-record.md"},"contracts/usage-record.md"),l(" 生成。"),e("a",{href:"https://github.com/yiyisf/paseo-req-kit/edit/main/contracts/usage-record.md"},"在 GitHub 上编辑")],-1)])])}const g=s(d,[["render",a]]);export{p as __pageData,g as default};
@@ -1,4 +1,4 @@
1
- import{_ as n,o as i,c as t,j as e,a as l}from"./chunks/framework.B9qR_F1m.js";const p=JSON.parse('{"title":"本机的需求索引与使用记录","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"reference/contracts/usage-record.md","filePath":"reference/contracts/usage-record.md","lastUpdated":null}'),a={name:"reference/contracts/usage-record.md"};function d(o,s,r,u,c,h){return i(),t("div",null,[...s[0]||(s[0]=[e("div",null,[e("h1",{id:"本机的需求索引与使用记录",tabindex:"-1"},[l("本机的需求索引与使用记录 "),e("a",{class:"header-anchor",href:"#本机的需求索引与使用记录","aria-label":'Permalink to "本机的需求索引与使用记录"'},"​")]),e("p",null,[l("1.9.0 起,引擎在本机配置目录(默认 "),e("code",null,"~/.req-kit"),l(",可用 "),e("code",null,"REQ_KIT_HOME"),l(" 改变)下记两样东西。它们只在这台机器上,不提交进任何仓库,也不会自动发往任何地方。环境变量 "),e("code",null,"REQ_KIT_NO_RECORD=1"),l(" 时两样都不记(评估运行就是这样)。")]),e("h2",{id:"需求索引-index-key-json",tabindex:"-1"},[l("需求索引 "),e("code",null,"index/<key>.json"),l(),e("a",{class:"header-anchor",href:"#需求索引-index-key-json","aria-label":'Permalink to "需求索引 `index/<key>.json`"'},"​")]),e("p",null,[l("每个在本机运行过的需求一个文件,记录它在哪里,供 "),e("code",null,"req api list --all"),l(" 和 Paseo 插件找到本机所有的需求。需求的阶段、进度仍然现场从功能目录读取(ADR 0010)。")]),e("div",{class:"language-json vp-adaptive-theme"},[e("button",{title:"Copy Code",class:"copy"}),e("span",{class:"lang"},"json"),e("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[e("code",null,[e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"{")]),l(`
1
+ import{_ as s,o as t,c as i,j as e,a as l}from"./chunks/framework.B9qR_F1m.js";const p=JSON.parse('{"title":"本机的需求索引与使用记录","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"reference/contracts/usage-record.md","filePath":"reference/contracts/usage-record.md","lastUpdated":null}'),d={name:"reference/contracts/usage-record.md"};function a(o,n,u,c,r,h){return t(),i("div",null,[...n[0]||(n[0]=[e("div",null,[e("h1",{id:"本机的需求索引与使用记录",tabindex:"-1"},[l("本机的需求索引与使用记录 "),e("a",{class:"header-anchor",href:"#本机的需求索引与使用记录","aria-label":'Permalink to "本机的需求索引与使用记录"'},"​")]),e("p",null,[l("1.9.0 起,引擎在本机配置目录(默认 "),e("code",null,"~/.req-kit"),l(",可用 "),e("code",null,"REQ_KIT_HOME"),l(" 改变)下记两样东西。它们只在这台机器上,不提交进任何仓库,也不会自动发往任何地方。环境变量 "),e("code",null,"REQ_KIT_NO_RECORD=1"),l(" 时两样都不记(评估运行就是这样)。")]),e("h2",{id:"需求索引-index-key-json",tabindex:"-1"},[l("需求索引 "),e("code",null,"index/<key>.json"),l(),e("a",{class:"header-anchor",href:"#需求索引-index-key-json","aria-label":'Permalink to "需求索引 `index/<key>.json`"'},"​")]),e("p",null,[l("每个在本机运行过的需求一个文件,记录它在哪里,供 "),e("code",null,"req api list --all"),l(" 和 Paseo 插件找到本机所有的需求。需求的阶段、进度仍然现场从功能目录读取(ADR 0010)。")]),e("div",{class:"language-json vp-adaptive-theme"},[e("button",{title:"Copy Code",class:"copy"}),e("span",{class:"lang"},"json"),e("pre",{class:"shiki shiki-themes github-light github-dark vp-code",tabindex:"0","v-pre":""},[e("code",null,[e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"{")]),l(`
2
2
  `),e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "schema"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),e("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},"1"),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
3
3
  `),e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "key"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),e("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"3f2a9c1e5b7d4e8a"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
4
4
  `),e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "repo"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),e("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"/home/me/work/shop-sms-login"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
@@ -7,4 +7,4 @@ import{_ as n,o as i,c as t,j as e,a as l}from"./chunks/framework.B9qR_F1m.js";c
7
7
  `),e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "workspaceId"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),e("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"ws_123"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
8
8
  `),e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "project"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),e("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"shop"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},",")]),l(`
9
9
  `),e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#005CC5","--shiki-dark":"#79B8FF"}},' "registeredAt"'),e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},": "),e("span",{style:{"--shiki-light":"#032F62","--shiki-dark":"#9ECBFF"}},'"2026-10-12T09:00:00.000Z"')]),l(`
10
- `),e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"}")])])])]),e("p",null,[e("code",null,"key"),l(" 由对话所在的目录(没有自己的工作区时即 "),e("code",null,"repo"),l(")和功能目录算出。1.14 起:开始谈需求时("),e("code",null,"start-pipeline --feature <功能目录> --track"),l(")就登记,此时多一个可选字段 "),e("code",null,"chatAgentId"),l("(谈需求的对话),之后的登记保留它;新建需求自己的工作区时,条目改为指向那个工作区。目录里有 "),e("code",null,"spec.md"),l("、"),e("code",null,"alignment.md"),l(" 或 "),e("code",null,".pipeline/"),l(" 下的状态或登记标记时算作存在。")]),e("h2",{id:"新建工作区的记录-worktrees-key-json-1-14",tabindex:"-1"},[l("新建工作区的记录 "),e("code",null,"worktrees/<key>.json"),l("(1.14) "),e("a",{class:"header-anchor",href:"#新建工作区的记录-worktrees-key-json-1-14","aria-label":'Permalink to "新建工作区的记录 `worktrees/<key>.json`(1.14)"'},"​")]),e("p",null,[l("用 "),e("code",null,"--worktree"),l(" 启动时,工作区一建好就写下:"),e("code",null,"{ schema, sourceRepo, featureDir, repo, workspaceId, branch, baseRef, createdAt, originAgentId }"),l('。之后的启动失败了,再次启动时在这个工作区里接着做,不再新建;插件据此把"工作区已建、开发没开始"的需求列进"等你处理"。'),e("code",null,"req index --rebuild"),l(" 为 1.9 之前运行过的需求补登,"),e("code",null,"req index --prune"),l(" 移除目录已不在的。")]),e("h2",{id:"使用记录-usage-runs-jsonl",tabindex:"-1"},[l("使用记录 "),e("code",null,"usage/runs.jsonl"),l(),e("a",{class:"header-anchor",href:"#使用记录-usage-runs-jsonl","aria-label":'Permalink to "使用记录 `usage/runs.jsonl`"'},"​")]),e("p",null,"每次流水线运行(后台进程从开始到结束,包括停在等待确认、等待需求方、研发完成处)结束时追加一行:"),e("table",{tabindex:"0"},[e("thead",null,[e("tr",null,[e("th",null,"字段"),e("th",null,"含义")])]),e("tbody",null,[e("tr",null,[e("td",null,[e("code",null,"schema"),l(" / "),e("code",null,"kind")]),e("td",null,[e("code",null,"1"),l(" / "),e("code",null,'"run"')])]),e("tr",null,[e("td",null,[e("code",null,"machine"),l(" / "),e("code",null,"kitVersion")]),e("td",null,"主机名、req-kit 版本")]),e("tr",null,[e("td",null,[e("code",null,"requirement")]),e("td",null,[e("code",null,"{ key, project, name, title, type, profile }"),l(";从卡片开始的需求(1.10 起)另有 "),e("code",null,"requester"),l("(卡片的提出人)和 "),e("code",null,"source"),l("("),e("code",null,"{ system, id }"),l(")")])]),e("tr",null,[e("td",null,[e("code",null,"steps[].cachedInputTokens"),l(" / "),e("code",null,"steps[].agent")]),e("td",null,'1.13 起。输入中来自提示缓存的 tokens(agent 报告时);这一步用的 agent(Paseo profile 名,或 "provider/model")。更早的记录没有')]),e("tr",null,[e("td",null,[e("code",null,"run")]),e("td",null,[e("code",null,"{ startedAt, endedAt, attempt, phase, phaseMode, status, outcome, stopReason, stopKind, recoveries }"),l(";"),e("code",null,"status"),l(" 是运行结束时的状态,"),e("code",null,"outcome"),l(" 是完成时报告的结论;"),e("code",null,"stopKind"),l("(1.12 起)是停下等人的原因代码(见 "),e("a",{href:"./state"},"state.md"),l("),"),e("code",null,"recoveries"),l("(1.12 起)是这次运行中自动处理的次数,按种类,如 "),e("code",null,'{ "retry": 2 }'),l("。更早的记录没有这两项")])]),e("tr",null,[e("td",null,[e("code",null,"agents")]),e("td",null,[e("code",null,"{ builder, reviewer }"),l(":当时配置的 agent(如 "),e("code",null,"claude/opus(bypassPermissions)"),l(")")])]),e("tr",null,[e("td",null,[e("code",null,"steps")]),e("td",null,[l("这次运行中开始的步骤:"),e("code",null,"{ key, stepId, phase, attempt, round, startedAt, endedAt, minutes, outcome, inputTokens, outputTokens, costUsd }"),l(";agent 没有报告的用量为 null")])]),e("tr",null,[e("td",null,[e("code",null,"gate")]),e("td",null,[e("code",null,"{ runs, failed }"),l(":这次运行中质量门运行的次数、发现新失败的次数")])])])]),e("p",null,"不记录需求内容、代码和对话。"),e("h2",{id:"统计口径-req-stats",tabindex:"-1"},[l("统计口径("),e("code",null,"req stats"),l(") "),e("a",{class:"header-anchor",href:"#统计口径-req-stats","aria-label":'Permalink to "统计口径(`req stats`)"'},"​")]),e("ul",null,[e("li",null,"一段时间的用量、步骤用时:结束时间在这段时间内的运行。"),e("li",null,'交付周期:需求第一次开始到完成(最后一次运行以"已完成"结束)的小时数,用这个需求的全部运行,算在完成的那段时间。'),e("li",null,"代码评审轮数、缺陷修复轮数:不同的(尝试、轮次、仓库)个数;评审分方向或评审小组的几个成员算一轮。"),e("li",null,"等待:相邻两次运行之间的间隔,按前一次结束时的状态归类:等待确认方案、等待需求方决定、研发完成到开始测试验证、中断到继续。"),e("li",null,[l("token 花在哪(1.13 起,"),e("code",null,"tokens"),l("):这段时间的步骤按 "),e("code",null,"stepId"),l("、按 "),e("code",null,"agent"),l(" 合计 token(输入 + 输出)和占比;返工("),e("code",null,"design_revise"),l("、"),e("code",null,"review_fix"),l("、"),e("code",null,"defect_fix"),l("、"),e("code",null,"reverify"),l(",以及 "),e("code",null,"design_review"),l("、"),e("code",null,"code_review"),l(" 第 2 轮起)的合计和占比;报告了 "),e("code",null,"cachedInputTokens"),l(" 的,算出输入中来自提示缓存的比例;已完成需求的 token 中位数(按档位)。")]),e("li",null,[l("停下等人的原因(1.12 起):这段时间结束的运行按 "),e("code",null,"stopKind"),l(" 计数;更早的记录按结束时的状态推断。确认方案、研发完成等待测试是必要的决定。")]),e("li",null,"无人工到提测的比例(1.12 起):这段时间有进展、已经研发完成或完成的需求中,所有运行都只停在必要决定处的比例。"),e("li",null,"自动处理的比例(1.12 起):自动处理的次数 ÷(自动处理的次数 + 以中断结束的运行数);需求方决定、缺陷复现不了不算中断。"),e("li",null,"合并多台机器的导出时,同一机器、同一需求、同一开始时间的运行只算一次。")]),e("p",null,[e("code",null,"req stats --json"),l(" 和 "),e("code",null,"req api stats"),l(" 输出同样的对象("),e("code",null,"schema: 1"),l("):"),e("code",null,"period"),l("、"),e("code",null,"machines"),l("、"),e("code",null,"active"),l("、"),e("code",null,"completed"),l("、"),e("code",null,"byType"),l("、"),e("code",null,"cycleHours"),l("、"),e("code",null,"steps"),l("、"),e("code",null,"rework"),l("、"),e("code",null,"waits"),l("、"),e("code",null,"usage"),l("、"),e("code",null,"byBuilder"),l("、"),e("code",null,"requirements"),l("(每个需求一项,字段与 "),e("code",null,"req stats --csv"),l(" 的列对应)。")])],-1),e("p",{class:"source-note"},[l("本页由仓库中的 "),e("a",{href:"https://github.com/yiyisf/paseo-req-kit/blob/main/contracts/usage-record.md"},"contracts/usage-record.md"),l(" 生成。"),e("a",{href:"https://github.com/yiyisf/paseo-req-kit/edit/main/contracts/usage-record.md"},"在 GitHub 上编辑")],-1)])])}const E=n(a,[["render",d]]);export{p as __pageData,E as default};
10
+ `),e("span",{class:"line"},[e("span",{style:{"--shiki-light":"#24292E","--shiki-dark":"#E1E4E8"}},"}")])])])]),e("p",null,[e("code",null,"key"),l(" 由对话所在的目录(没有自己的工作区时即 "),e("code",null,"repo"),l(")和功能目录算出。1.14 起:开始谈需求时("),e("code",null,"start-pipeline --feature <功能目录> --track"),l(")就登记,此时多一个可选字段 "),e("code",null,"chatAgentId"),l("(谈需求的对话),之后的登记保留它;新建需求自己的工作区时,条目改为指向那个工作区。目录里有 "),e("code",null,"spec.md"),l("、"),e("code",null,"alignment.md"),l(" 或 "),e("code",null,".pipeline/"),l(" 下的状态或登记标记时算作存在。")]),e("h2",{id:"新建工作区的记录-worktrees-key-json-1-14",tabindex:"-1"},[l("新建工作区的记录 "),e("code",null,"worktrees/<key>.json"),l("(1.14) "),e("a",{class:"header-anchor",href:"#新建工作区的记录-worktrees-key-json-1-14","aria-label":'Permalink to "新建工作区的记录 `worktrees/<key>.json`(1.14)"'},"​")]),e("p",null,[l("用 "),e("code",null,"--worktree"),l(" 启动时,工作区一建好就写下:"),e("code",null,"{ schema, sourceRepo, featureDir, repo, workspaceId, branch, baseRef, createdAt, originAgentId }"),l('。之后的启动失败了,再次启动时在这个工作区里接着做,不再新建;插件据此把"工作区已建、开发没开始"的需求列进"等你处理"。'),e("code",null,"req index --rebuild"),l(" 为 1.9 之前运行过的需求补登,"),e("code",null,"req index --prune"),l(" 移除目录已不在的。")]),e("h2",{id:"使用记录-usage-runs-jsonl",tabindex:"-1"},[l("使用记录 "),e("code",null,"usage/runs.jsonl"),l(),e("a",{class:"header-anchor",href:"#使用记录-usage-runs-jsonl","aria-label":'Permalink to "使用记录 `usage/runs.jsonl`"'},"​")]),e("p",null,"每次流水线运行(后台进程从开始到结束,包括停在等待确认、等待需求方、研发完成处)结束时追加一行:"),e("table",{tabindex:"0"},[e("thead",null,[e("tr",null,[e("th",null,"字段"),e("th",null,"含义")])]),e("tbody",null,[e("tr",null,[e("td",null,[e("code",null,"schema"),l(" / "),e("code",null,"kind")]),e("td",null,[e("code",null,"1"),l(" / "),e("code",null,'"run"')])]),e("tr",null,[e("td",null,[e("code",null,"machine"),l(" / "),e("code",null,"kitVersion")]),e("td",null,"主机名、req-kit 版本")]),e("tr",null,[e("td",null,[e("code",null,"requirement")]),e("td",null,[e("code",null,"{ key, project, name, title, type, profile }"),l(";从卡片开始的需求(1.10 起)另有 "),e("code",null,"requester"),l("(卡片的提出人)和 "),e("code",null,"source"),l("("),e("code",null,"{ system, id }"),l(")")])]),e("tr",null,[e("td",null,[e("code",null,"steps[].cachedInputTokens"),l(" / "),e("code",null,"steps[].agent")]),e("td",null,'1.13 起。输入中来自提示缓存的 tokens(agent 报告时);这一步用的 agent(Paseo profile 名,或 "provider/model")。更早的记录没有')]),e("tr",null,[e("td",null,[e("code",null,"run")]),e("td",null,[e("code",null,"{ startedAt, endedAt, attempt, phase, phaseMode, status, outcome, stopReason, stopKind, recoveries }"),l(";"),e("code",null,"status"),l(" 是运行结束时的状态,"),e("code",null,"outcome"),l(" 是完成时报告的结论;"),e("code",null,"stopKind"),l("(1.12 起)是停下等人的原因代码(见 "),e("a",{href:"./state"},"state.md"),l("),"),e("code",null,"recoveries"),l("(1.12 起)是这次运行中自动处理的次数,按种类,如 "),e("code",null,'{ "retry": 2 }'),l("。更早的记录没有这两项")])]),e("tr",null,[e("td",null,[e("code",null,"agents")]),e("td",null,[e("code",null,"{ builder, reviewer }"),l(":当时配置的 agent(如 "),e("code",null,"claude/opus(bypassPermissions)"),l(")")])]),e("tr",null,[e("td",null,[e("code",null,"steps")]),e("td",null,[l("这次运行中开始的步骤:"),e("code",null,"{ key, stepId, phase, attempt, round, startedAt, endedAt, minutes, outcome, inputTokens, outputTokens, costUsd }"),l(";agent 没有报告的用量为 null")])]),e("tr",null,[e("td",null,[e("code",null,"gate")]),e("td",null,[e("code",null,"{ runs, failed }"),l(":这次运行中质量门运行的次数、发现新失败的次数")])])])]),e("p",null,"不记录需求内容、代码和对话。"),e("h3",{id:"运行之后的事-1-14-起",tabindex:"-1"},[l("运行之后的事(1.14 起) "),e("a",{class:"header-anchor",href:"#运行之后的事-1-14-起","aria-label":'Permalink to "运行之后的事(1.14 起)"'},"​")]),e("p",null,[l("同一个文件里还有几种记录,都有 "),e("code",null,"schema"),l("(1)、"),e("code",null,"kind"),l("、"),e("code",null,"machine"),l("、"),e("code",null,"kitVersion"),l("、"),e("code",null,"at"),l(" 和 "),e("code",null,"requirement"),l("("),e("code",null,"{ key, project, name, title }"),l(","),e("code",null,"key"),l(" 与运行记录相同)。读运行记录的旧版本会跳过它们。")]),e("table",{tabindex:"0"},[e("thead",null,[e("tr",null,[e("th",null,[e("code",null,"kind")]),e("th",null,"何时写"),e("th",null,"字段")])]),e("tbody",null,[e("tr",null,[e("td",null,[e("code",null,"review")]),e("td",null,'插件代码审查页提交"退回修改"或"评审通过"'),e("td",null,[e("code",null,'review: { verdict: "approved" | "changes_requested", reviewer, items, head }'),l(":评审人、意见条数、评审的提交")])]),e("tr",null,[e("td",null,[e("code",null,"acceptance")]),e("td",null,"验收清单页提交"),e("td",null,[e("code",null,'acceptance: { verdict: "通过" | "不通过", reviewer, total, passed, failed, unchecked }')])]),e("tr",null,[e("td",null,[e("code",null,"merge")]),e("td",null,[e("code",null,"req stats"),l("、"),e("code",null,"req api stats"),l("、"),e("code",null,"req outcome"),l(" 发现需求的流水线文件("),e("code",null,"implementation.md"),l("、"),e("code",null,"report.md"),l(" 等)已经在主干("),e("code",null,"origin/HEAD"),l(",没有时 "),e("code",null,"origin/main"),l("、"),e("code",null,"main"),l(" 等)里;或者 "),e("code",null,"req outcome <需求> --merged")]),e("td",null,[e("code",null,'merge: { into, commit, mergedAt, how: "files" | "manual" }'),l(":"),e("code",null,"commit"),l("、"),e("code",null,"mergedAt"),l(" 是把它带进主干的那次提交(合并提交或压缩合并的提交);只看本机已有的分支,不 fetch")])]),e("tr",null,[e("td",null,[e("code",null,"issue")]),e("td",null,[l("缺陷需求的 spec 写了 "),e("code",null,"- 引入问题的需求:<目录名>"),l("(扫描时发现),或者 "),e("code",null,'req outcome <需求> --issue "<问题>"')]),e("td",null,[e("code",null,"issue: { text, by, id }"),l(":"),e("code",null,"by"),l(" 是那个缺陷需求的目录名,手动记的为 null;同一个 "),e("code",null,"id"),l(" 只算一次")])])])]),e("p",null,[l("每个需求的 "),e("code",null,"merge"),l(" 只记一次。评审和验收的全文在需求目录的 "),e("code",null,"code-review.md"),l("、"),e("code",null,"acceptance.md"),l(" 里,随需求分支提交;这里只记结论和数量,用于统计。")]),e("h2",{id:"统计口径-req-stats",tabindex:"-1"},[l("统计口径("),e("code",null,"req stats"),l(") "),e("a",{class:"header-anchor",href:"#统计口径-req-stats","aria-label":'Permalink to "统计口径(`req stats`)"'},"​")]),e("ul",null,[e("li",null,"一段时间的用量、步骤用时:结束时间在这段时间内的运行。"),e("li",null,'交付周期:需求第一次开始到完成(最后一次运行以"已完成"结束)的小时数,用这个需求的全部运行,算在完成的那段时间。'),e("li",null,"代码评审轮数、缺陷修复轮数:不同的(尝试、轮次、仓库)个数;评审分方向或评审小组的几个成员算一轮。"),e("li",null,"等待:相邻两次运行之间的间隔,按前一次结束时的状态归类:等待确认方案、等待需求方决定、研发完成到开始测试验证、中断到继续。"),e("li",null,[l("token 花在哪(1.13 起,"),e("code",null,"tokens"),l("):这段时间的步骤按 "),e("code",null,"stepId"),l("、按 "),e("code",null,"agent"),l(" 合计 token(输入 + 输出)和占比;返工("),e("code",null,"design_revise"),l("、"),e("code",null,"review_fix"),l("、"),e("code",null,"defect_fix"),l("、"),e("code",null,"reverify"),l(",以及 "),e("code",null,"design_review"),l("、"),e("code",null,"code_review"),l(" 第 2 轮起)的合计和占比;报告了 "),e("code",null,"cachedInputTokens"),l(" 的,算出输入中来自提示缓存的比例;已完成需求的 token 中位数(按档位)。")]),e("li",null,[l("停下等人的原因(1.12 起):这段时间结束的运行按 "),e("code",null,"stopKind"),l(" 计数;更早的记录按结束时的状态推断。确认方案、研发完成等待测试是必要的决定。")]),e("li",null,"无人工到提测的比例(1.12 起):这段时间有进展、已经研发完成或完成的需求中,所有运行都只停在必要决定处的比例。"),e("li",null,"自动处理的比例(1.12 起):自动处理的次数 ÷(自动处理的次数 + 以中断结束的运行数);需求方决定、缺陷复现不了不算中断。"),e("li",null,[l("人工把关和合并后(1.14 起,"),e("code",null,"oversight"),l('):这段时间里的人工代码评审次数、退回修改次数、意见条数,验收次数和不通过次数;"第一次就通过"看每个需求最早的那次评审(验收),它在这段时间里并且是通过;合并进主干的需求数和"完成到合并"的小时数中位数;合并后发现的问题数和涉及的需求数。每个需求一项里的 '),e("code",null,"afterRun"),l(" 汇总它全部的这类记录("),e("code",null,"humanReviews"),l("、"),e("code",null,"sentBack"),l("、"),e("code",null,"lastReview"),l("、"),e("code",null,"acceptance"),l("、"),e("code",null,"acceptanceFailed"),l("、"),e("code",null,"mergedAt"),l("、"),e("code",null,"issues"),l(")。")]),e("li",null,[l("合并多台机器的导出时,同一机器、同一需求、同一开始时间的运行只算一次;同一个需求、同一种、同一时间的事件(问题按 "),e("code",null,"id"),l(")只算一次。"),e("code",null,"req stats --export"),l(" 同时导出这些需求的事件。")])]),e("p",null,[e("code",null,"req stats --json"),l(" 和 "),e("code",null,"req api stats"),l(" 输出同样的对象("),e("code",null,"schema: 1"),l("):"),e("code",null,"period"),l("、"),e("code",null,"machines"),l("、"),e("code",null,"active"),l("、"),e("code",null,"completed"),l("、"),e("code",null,"byType"),l("、"),e("code",null,"cycleHours"),l("、"),e("code",null,"steps"),l("、"),e("code",null,"rework"),l("、"),e("code",null,"waits"),l("、"),e("code",null,"usage"),l("、"),e("code",null,"tokens"),l("、"),e("code",null,"oversight"),l("、"),e("code",null,"byBuilder"),l("、"),e("code",null,"requirements"),l("(每个需求一项,字段与 "),e("code",null,"req stats --csv"),l(" 的列对应)。")])],-1),e("p",{class:"source-note"},[l("本页由仓库中的 "),e("a",{href:"https://github.com/yiyisf/paseo-req-kit/blob/main/contracts/usage-record.md"},"contracts/usage-record.md"),l(" 生成。"),e("a",{href:"https://github.com/yiyisf/paseo-req-kit/edit/main/contracts/usage-record.md"},"在 GitHub 上编辑")],-1)])])}const g=s(d,[["render",a]]);export{p as __pageData,g as default};