dsh-plugin-teamflow 0.1.8 → 0.1.9

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/lib/store.mjs CHANGED
@@ -110,6 +110,7 @@ function serializeJournal(journal) {
110
110
  workspacePath: journal.workspacePath || null,
111
111
  ownerSession: journal.ownerSession || null,
112
112
  product: journal.product || null,
113
+ locale: journal.locale || null,
113
114
  sanity: journal.sanity || null,
114
115
  blueprint: journal.blueprint || null,
115
116
  reqId: journal.reqId || null,
@@ -118,6 +119,9 @@ function serializeJournal(journal) {
118
119
  taskMap: journal.taskMap || {},
119
120
  agentsStarted: journal.agentsStarted || 0,
120
121
  humanIntervention: journal.humanIntervention === true,
122
+ /** E 方案(2026-09-15):本轮验收是「已知问题」只读模式(QA 打回超限后补跑)——report 据此给
123
+ * 「结论被强制为需人工裁定、不要据此合回」的显式提示(持久化:重启/resume 后仍可判)。 */
124
+ knownIssuesAcceptance: journal.knownIssuesAcceptance === true,
121
125
  cancelled: journal.cancelled === true,
122
126
  interrupted: journal.interrupted === true,
123
127
  interruptedAt: journal.interruptedAt || null,
@@ -145,6 +149,27 @@ function serializeJournal(journal) {
145
149
  t: l.t,
146
150
  level: l.level,
147
151
  message: clip(l.message, 500)
152
+ })),
153
+ qaRounds: (journal.qaRounds || []).slice(-12).map((r) => ({
154
+ round: r.round,
155
+ seq: r.seq,
156
+ blocking: r.blocking,
157
+ p3: r.p3,
158
+ defects: Array.isArray(r.defects) ? r.defects.slice(0, 20).map((d) => ({
159
+ id: clip(d.id, 40),
160
+ sev: d.sev,
161
+ module: clip(d.module, 60),
162
+ fp: clip(d.fp, 200)
163
+ })) : [],
164
+ withCheck: r.withCheck,
165
+ withCriterion: r.withCriterion,
166
+ qaCalls: r.qaCalls,
167
+ fixCalls: r.fixCalls,
168
+ gate: r.gate,
169
+ newFps: r.newFps,
170
+ repeats: r.repeats,
171
+ resolved: r.resolved,
172
+ outcome: r.outcome
148
173
  }))
149
174
  };
150
175
  }
@@ -161,17 +186,41 @@ function writeText(file, text) {
161
186
  return false;
162
187
  }
163
188
  }
164
- /** 工作区下日志落点:<工作区>/logs/teamflow/<runId>.log(存在 workspacePath 时才落)。 */
165
- function runLogFile(journal) {
189
+ /** 工作区内暂存目录段(与 host/constants.TF_LOG_DIR 同址;store 是独立 entry、刻意不引 host 代码,一致性由 test/runlogs.test.js 守门)。 */
190
+ const STAGING_SEGMENTS = ["logs", "teamflow"];
191
+ /** 归档用的工作区槽位:优先 journal.workspace,缺失/兜底时按 workspacePath 派生(与 backlog 同键)。 */
192
+ function logWorkspaceKey(journal) {
193
+ const w = journal && typeof journal.workspace === "string" ? journal.workspace.trim() : "";
194
+ if (w && w !== "default") return w;
195
+ const p = journal ? journal.workspacePath : null;
196
+ return p ? slugPath(p) : null;
197
+ }
198
+ /** 归档根(工作区级):`$DSH_HOME/teamflow/<workspace>/logs/`(每个 run 一个子目录)。 */
199
+ function logsArchiveRoot(journal) {
200
+ const key = logWorkspaceKey(journal);
201
+ return key ? join(teamflowRoot(), key, "logs") : null;
202
+ }
203
+ /** 归档落点(run 级目录):`$DSH_HOME/teamflow/<workspace>/logs/<runId>/`(与 journal/backlog 同槽位)。 */
204
+ function runLogArchiveDir(journal) {
205
+ const root = logsArchiveRoot(journal);
206
+ return root ? join(root, journal.id) : null;
207
+ }
208
+ /** 工作区内暂存落点(子代理写、run 结束归档后删除):`<workspacePath>/logs/teamflow/<runId>/`。 */
209
+ function runLogStagingDir(journal) {
166
210
  if (!journal.workspacePath) return null;
167
- return join(journal.workspacePath, "logs", "teamflow", `${journal.id}.log`);
211
+ return join(journal.workspacePath, ...STAGING_SEGMENTS, journal.id);
212
+ }
213
+ /** host 事件日志落点:`<归档 run 目录>/run.log`(run 期间即写终态位置,无需搬运)。 */
214
+ function runLogFile(journal) {
215
+ const dir = runLogArchiveDir(journal);
216
+ return dir ? join(dir, "run.log") : null;
168
217
  }
169
- /** 把运行事件日志聚合写到 <工作区>/logs/teamflow/<runId>.log(logs 收口,防止污染宿主)。 */
218
+ /** 把运行事件日志聚合写到 `$DSH_HOME/teamflow/<workspace>/logs/<runId>/run.log`(logs 离开用户项目)。 */
170
219
  function persistRunLog(journal) {
171
220
  const file = runLogFile(journal);
172
221
  if (!file) return false;
173
222
  const lines = [
174
- `# TeamFlow 运行日志(${journal.name})`,
223
+ journal.locale === "en" ? `# TeamFlow run log (${journal.name})` : `# TeamFlow 运行日志(${journal.name})`,
175
224
  `runId=${journal.id}`,
176
225
  `workspace=${journal.workspacePath || ""}`,
177
226
  `product=${journal.product || ""}`,
@@ -255,4 +304,4 @@ function loadJournals() {
255
304
  return out;
256
305
  }
257
306
  //#endregion
258
- export { STAGE_OUTPUT_CLIP, dshHome, fileFor, journalFile, loadJournals, persistJournal, persistRunLog, productDir, readJson, readJsonAny, runLogFile, runsDir, serializeJournal, slugPath, teamflowRoot, workspaceDir, writeJson, writeText };
307
+ export { STAGE_OUTPUT_CLIP, dshHome, fileFor, journalFile, loadJournals, logsArchiveRoot, persistJournal, persistRunLog, productDir, readJson, readJsonAny, runLogArchiveDir, runLogFile, runLogStagingDir, runsDir, serializeJournal, slugPath, teamflowRoot, workspaceDir, writeJson, writeText };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-teamflow",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "TeamFlow 团队研发流水线(TypeScript):需求→PRD→设计→架构→技术方案→并行开发→QA→验收;backlog 持久化 + 断点续跑 + 完成汇报 + 防假交付;Web 团队工作台(conversation.view tab + 拖拽看板)",
5
5
  "type": "module",
6
6
  "main": "./lib/host.mjs",
@@ -41,8 +41,8 @@
41
41
  "watch": "tsdown --watch",
42
42
  "deploy": "node deploy.mjs",
43
43
  "typecheck": "tsc --noEmit",
44
- "test": "node test/smoke.js && node test/verdict.test.js && node test/stages.test.js && node test/journal.test.js && node test/diagnostic.test.js && node test/evidence.test.js && node test/metering.test.js && node test/gitignore.test.js && node test/product-scope.test.js && node test/prompt-contract.test.js && node test/conformance.test.js",
45
- "prepublishOnly": "npx tsdown && npx tsdown -c tsdown.host.config.ts && node test/smoke.js && node test/verdict.test.js && node test/stages.test.js && node test/journal.test.js && node test/diagnostic.test.js && node test/evidence.test.js && node test/metering.test.js && node test/gitignore.test.js && node test/product-scope.test.js && node test/prompt-contract.test.js && node test/conformance.test.js"
44
+ "test": "node test/smoke.js && node test/locale.test.js && node test/verdict.test.js && node test/stages.test.js && node test/journal.test.js && node test/runlogs.test.js && node test/diagnostic.test.js && node test/evidence.test.js && node test/metering.test.js && node test/gitignore.test.js && node test/commit-path.test.js && node test/product-scope.test.js && node test/prompt-contract.test.js && node test/conformance.test.js",
45
+ "prepublishOnly": "npx tsdown && npx tsdown -c tsdown.host.config.ts && node test/smoke.js && node test/locale.test.js && node test/verdict.test.js && node test/stages.test.js && node test/journal.test.js && node test/runlogs.test.js && node test/diagnostic.test.js && node test/evidence.test.js && node test/metering.test.js && node test/gitignore.test.js && node test/commit-path.test.js && node test/product-scope.test.js && node test/prompt-contract.test.js && node test/conformance.test.js"
46
46
  },
47
47
  "files": [
48
48
  "lib",