@xulthekl/team-flow 0.23.0 → 0.25.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/.claude/always/phase-guard.md +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor-plugin/marketplace.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/.github/plugin/marketplace.json +2 -2
- package/AGENTS.md +3 -3
- package/CHANGELOG.md +121 -0
- package/GEMINI.md +1 -1
- package/INSTALL.md +1 -1
- package/README.md +1 -1
- package/docs/README_en.md +1 -1
- package/docs/solutions/INDEX.md +6 -0
- package/docs/solutions/cross-phase/2026-07-28-no-summary.md +17 -0
- package/docs/solutions/cross-phase/2026-07-29-no-summary.md +17 -0
- package/gemini-extension.json +1 -1
- package/hooks/pre-tool-use-guard +9 -9
- package/hooks/session-start +2 -2
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/scripts/guard/checks/compound-captured.mjs +70 -0
- package/scripts/guard/guard.mjs +3 -1
- package/scripts/lib/cmd-state.mjs +2 -0
- package/scripts/lib/config-loader.mjs +3 -0
- package/scripts/lib/solutions-promote.mjs +1 -1
- package/scripts/lib/state-loader.mjs +5 -0
- package/skills/bug-investigator/SKILL.md +1 -1
- package/skills/build-executor/SKILL.md +19 -19
- package/skills/build-executor/implementer-prompt.md +1 -1
- package/skills/build-executor/references/execution-modes.md +6 -6
- package/skills/build-executor/task-reviewer-prompt.md +1 -1
- package/skills/ce-brainstorm/SKILL.md +49 -348
- package/skills/ce-brainstorm/references/brainstorm-sections.md +11 -0
- package/skills/ce-brainstorm/references/grounding.md +47 -0
- package/skills/ce-brainstorm/references/output-format.md +25 -0
- package/skills/ce-brainstorm/references/phase0-routing.md +96 -0
- package/skills/ce-brainstorm/references/prd-mapping.md +37 -0
- package/skills/ce-brainstorm/references/prototype-loop.md +55 -0
- package/skills/ce-ideate/SKILL.md +31 -348
- package/skills/ce-ideate/references/grounding.md +107 -0
- package/skills/ce-ideate/references/phase0-scope.md +134 -0
- package/skills/ce-ideate/references/topic-surface.md +37 -0
- package/skills/ce-proof/SKILL.md +8 -266
- package/skills/ce-proof/references/api-recipes.md +145 -0
- package/skills/ce-proof/references/workflows.md +124 -0
- package/skills/code-reviewer/SKILL.md +2 -2
- package/skills/code-reviewer/code-reviewer-prompt.md +1 -1
- package/skills/contract-builder/SKILL.md +6 -6
- package/skills/need-explorer/SKILL.md +2 -2
- package/skills/prototype/SKILL.md +16 -2
- package/skills/prototype/references/agents/design-system-architect.md +11 -122
- package/skills/prototype/references/interactive-prototype.md +110 -0
- package/skills/prototype/references/layouts.md +188 -2
- package/skills/prototype/references/orchestration-flow.md +8 -1
- package/skills/prototype/references/template.html +32 -0
- package/skills/prototype/references/wireframe.md +117 -0
- package/skills/release-archivist/SKILL.md +14 -12
- package/skills/release-archivist/references/closing-procedures.md +11 -9
- package/skills/spec-merger/SKILL.md +2 -2
- package/skills/spec-writer/SKILL.md +3 -3
- package/skills/workflow-bootstrap/SKILL.md +13 -2
- package/skills/workflow-bootstrap/references/b1-reconnaissance.md +13 -7
- package/skills/workflow-bootstrap/scripts/recon-probe.sh +122 -1
- package/skills/workflow-orchestrator/references/s2-prd-prototype-loop.md +1 -1
- package/skills/workflow-orchestrator/references/s4-split-validate.md +1 -1
- package/skills/workflow-orchestrator/references/s5-monitoring.md +1 -1
- package/skills/workflow-start/SKILL.md +16 -16
- package/skills/workflow-start/references/routing-rules.md +17 -17
- package/templates/prd-brainstorm-profile.md +69 -0
- package/tests/lib/guard-compound-captured.test.mjs +92 -0
- package/tests/lib/guard-specs-merged.test.mjs +2 -0
- package/tests/lib/guard-tests-passing.test.mjs +2 -0
- package/tests/lib/guard.test.mjs +2 -0
- package/tests/lib/solutions-capture.test.mjs +108 -0
- package/tests/lib/solutions-index-gen.test.mjs +147 -0
- package/tests/lib/solutions-inject.test.mjs +115 -0
- package/tests/lib/solutions-promote.test.mjs +200 -0
|
@@ -36,6 +36,7 @@ set -u # 未定义变量报错;不用 -e(单条采集失败不应中断整
|
|
|
36
36
|
# ----------------------------------------------------------------------------
|
|
37
37
|
ROOT="."
|
|
38
38
|
OUT=""
|
|
39
|
+
DDL_OUT="" # v0.24.0: DDL 输出文件路径(默认不写,仅含在 JSON 中)
|
|
39
40
|
MAX_FILES=50000 # LOC 统计文件数上限(保护超大仓库)
|
|
40
41
|
TREE_DEPTH=4 # 目录树限深
|
|
41
42
|
|
|
@@ -51,6 +52,8 @@ while [ $# -gt 0 ]; do
|
|
|
51
52
|
--root=*) ROOT="${1#*=}"; shift ;;
|
|
52
53
|
--out) OUT="${2:-}"; shift 2 ;;
|
|
53
54
|
--out=*) OUT="${1#*=}"; shift ;;
|
|
55
|
+
--ddl-out) DDL_OUT="${2:-}"; shift 2 ;;
|
|
56
|
+
--ddl-out=*) DDL_OUT="${1#*=}"; shift ;;
|
|
54
57
|
-h|--help) print_help; exit 0 ;;
|
|
55
58
|
*) echo "[recon-probe] warn: unknown arg '$1' (ignored)" >&2; shift ;;
|
|
56
59
|
esac
|
|
@@ -260,6 +263,111 @@ pruned_find -maxdepth 2 -type f \
|
|
|
260
263
|
-print 2>/dev/null | sed "s#^$ROOT_ABS/##" | sort > "$TMP/doc_files.txt"
|
|
261
264
|
if [ -d "$ROOT_ABS/docs" ]; then DOCS_DIR=true; else DOCS_DIR=false; fi
|
|
262
265
|
|
|
266
|
+
# ============================================================================
|
|
267
|
+
# ⑦ DDL 提取(v0.24.0:schema-baseline 兜底采集)
|
|
268
|
+
# ----------------------------------------------------------------------------
|
|
269
|
+
# 策略(优先级):
|
|
270
|
+
# 1. 既有 .sql 中的 CREATE TABLE 语句 → 直接提取
|
|
271
|
+
# 2. Java Entity 类(@Entity / @Table 注解)→ 正则提取表名+字段
|
|
272
|
+
# 3. 以上均无 → 输出空 schema-baseline.sql + 提示手动补充
|
|
273
|
+
# 设计契约:只做确定性机械采集(regex),语义推断交给侦察子代理。
|
|
274
|
+
# ============================================================================
|
|
275
|
+
|
|
276
|
+
: > "$TMP/ddl_statements.sql"
|
|
277
|
+
: > "$TMP/ddl_tables.txt"
|
|
278
|
+
DDL_SOURCE="none"
|
|
279
|
+
DDL_TABLE_COUNT=0
|
|
280
|
+
|
|
281
|
+
# --- 策略 1:从既有 .sql 文件提取 CREATE TABLE ----------------------------------
|
|
282
|
+
if [ -s "$TMP/sql_files.txt" ]; then
|
|
283
|
+
while IFS= read -r sql_rel; do
|
|
284
|
+
sql_abs="$ROOT_ABS/$sql_rel"
|
|
285
|
+
[ -f "$sql_abs" ] || continue
|
|
286
|
+
# 提取 CREATE TABLE 语句(多行匹配,到第一个 ; 结束)
|
|
287
|
+
# 兼容:CREATE TABLE / CREATE TABLE IF NOT EXISTS / 大小写不敏感
|
|
288
|
+
awk '
|
|
289
|
+
BEGIN { IGNORECASE=1; in_stmt=0; stmt="" }
|
|
290
|
+
/CREATE[[:space:]]+TABLE/ { in_stmt=1; stmt="" }
|
|
291
|
+
in_stmt {
|
|
292
|
+
stmt = stmt $0 "\n"
|
|
293
|
+
if (/;/) {
|
|
294
|
+
printf "%s-- Source: %s\n\n", stmt, sql_file
|
|
295
|
+
in_stmt=0; stmt=""
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
' sql_file="$sql_rel" "$sql_abs" 2>/dev/null >> "$TMP/ddl_statements.sql" || true
|
|
299
|
+
done < "$TMP/sql_files.txt"
|
|
300
|
+
if [ -s "$TMP/ddl_statements.sql" ]; then
|
|
301
|
+
DDL_SOURCE="sql_files"
|
|
302
|
+
# 提取表名(用于计数和 JSON)
|
|
303
|
+
grep -ioE 'CREATE[[:space:]]+TABLE[[:space:]]+(IF[[:space:]]+NOT[[:space:]]+EXISTS[[:space:]]+)?[`"]?([a-zA-Z_][a-zA-Z0-9_.]*)[`"]?' \
|
|
304
|
+
"$TMP/ddl_statements.sql" 2>/dev/null \
|
|
305
|
+
| grep -ioE '[`"]?[a-zA-Z_][a-zA-Z0-9_]*\.[a-zA-Z_][a-zA-Z0-9_]*[`"]?|[a-zA-Z_][a-zA-Z0-9_]*[`"]?$' \
|
|
306
|
+
| sed -E 's/[`"]//g' | sort -u > "$TMP/ddl_tables.txt" || true
|
|
307
|
+
DDL_TABLE_COUNT=$(wc -l < "$TMP/ddl_tables.txt" | tr -d ' ')
|
|
308
|
+
fi
|
|
309
|
+
fi
|
|
310
|
+
|
|
311
|
+
# --- 策略 2:从 Java Entity 类提取(@Entity / @Table 注解)-----------------------
|
|
312
|
+
if [ "$DDL_TABLE_COUNT" -eq 0 ]; then
|
|
313
|
+
: > "$TMP/entity_files.txt"
|
|
314
|
+
pruned_find -type f -name '*.java' -print 2>/dev/null \
|
|
315
|
+
| while IFS= read -r jf; do
|
|
316
|
+
if grep -qlE '@(Entity|Table|Document|TableName)' "$jf" 2>/dev/null; then
|
|
317
|
+
echo "$jf"
|
|
318
|
+
fi
|
|
319
|
+
done | sort > "$TMP/entity_files.txt"
|
|
320
|
+
|
|
321
|
+
ENTITY_COUNT=$(wc -l < "$TMP/entity_files.txt" | tr -d ' ')
|
|
322
|
+
if [ "$ENTITY_COUNT" -gt 0 ]; then
|
|
323
|
+
DDL_SOURCE="java_entity"
|
|
324
|
+
while IFS= read -r ef; do
|
|
325
|
+
ef_rel="${ef#"$ROOT_ABS"/}"
|
|
326
|
+
# 提取 @Table(name="xxx") 或类名作为表名
|
|
327
|
+
table_name=""
|
|
328
|
+
tn="$(grep -oE '@Table\([^)]*name[[:space:]]*=[[:space:]]*"[^"]+"' "$ef" 2>/dev/null | head -1 \
|
|
329
|
+
| grep -oE '"[^"]+"' | tr -d '"')" || true
|
|
330
|
+
if [ -n "$tn" ]; then
|
|
331
|
+
table_name="$tn"
|
|
332
|
+
else
|
|
333
|
+
# 降级:用类名转 snake_case 作为表名
|
|
334
|
+
table_name="$(grep -oE 'class[[:space:]]+[A-Z][a-zA-Z0-9]*' "$ef" 2>/dev/null | head -1 \
|
|
335
|
+
| sed -E 's/class[[:space:]]+//' \
|
|
336
|
+
| sed -E 's/([A-Z])/_\1/g' | tr '[:upper:]' '[:lower:]' | sed 's/^_//')" || true
|
|
337
|
+
fi
|
|
338
|
+
[ -z "$table_name" ] && continue
|
|
339
|
+
|
|
340
|
+
# 攒完整 DDL 到临时文件再一次性追加(避免多次 >> 缓冲问题)
|
|
341
|
+
: > "$TMP/_entity_ddl.tmp"
|
|
342
|
+
echo "-- Entity: $ef_rel" >> "$TMP/_entity_ddl.tmp"
|
|
343
|
+
echo "CREATE TABLE $table_name (" >> "$TMP/_entity_ddl.tmp"
|
|
344
|
+
# 机械提取 private 字段声明:private Type fieldName;
|
|
345
|
+
grep -E '^[[:space:]]*private[[:space:]]+' "$ef" 2>/dev/null \
|
|
346
|
+
| grep -vE 'static[[:space:]]|final[[:space:]]|Logger|log|serialVersionUID' \
|
|
347
|
+
| sed -E 's/^[[:space:]]*private[[:space:]]+([A-Za-z0-9_<>, ]+)[[:space:]]+([a-zA-Z_][a-zA-Z0-9_]*)[[:space:]]*(=|;).*/ \2 \1,/' \
|
|
348
|
+
| sed -E 's/String|varchar|text/varchar(255)/g; s/Long|Integer|int|long/bigint/g; s/Boolean|boolean/tinyint(1)/g; s/Date|LocalDateTime|Timestamp/datetime/g; s/BigDecimal|Double|Float/decimal(15,4)/g' \
|
|
349
|
+
>> "$TMP/_entity_ddl.tmp" 2>/dev/null || true
|
|
350
|
+
echo " create_time datetime," >> "$TMP/_entity_ddl.tmp"
|
|
351
|
+
echo " update_time datetime," >> "$TMP/_entity_ddl.tmp"
|
|
352
|
+
echo " del_flag tinyint(1) DEFAULT 0" >> "$TMP/_entity_ddl.tmp"
|
|
353
|
+
echo ");" >> "$TMP/_entity_ddl.tmp"
|
|
354
|
+
echo "" >> "$TMP/_entity_ddl.tmp"
|
|
355
|
+
cat "$TMP/_entity_ddl.tmp" >> "$TMP/ddl_statements.sql"
|
|
356
|
+
echo "$table_name" >> "$TMP/ddl_tables.txt"
|
|
357
|
+
done < "$TMP/entity_files.txt"
|
|
358
|
+
sort -u "$TMP/ddl_tables.txt" -o "$TMP/ddl_tables.txt"
|
|
359
|
+
DDL_TABLE_COUNT=$(wc -l < "$TMP/ddl_tables.txt" | tr -d ' ')
|
|
360
|
+
fi
|
|
361
|
+
fi
|
|
362
|
+
|
|
363
|
+
# --- 策略 3:生成占位 schema-baseline.sql ---------------------------------------
|
|
364
|
+
if [ "$DDL_TABLE_COUNT" -eq 0 ]; then
|
|
365
|
+
DDL_SOURCE="none"
|
|
366
|
+
printf -- '-- schema-baseline.sql (auto-generated placeholder)\n' > "$TMP/ddl_statements.sql"
|
|
367
|
+
printf -- '-- No CREATE TABLE statements or Java Entity classes detected.\n' >> "$TMP/ddl_statements.sql"
|
|
368
|
+
printf -- '-- Please populate manually with your database schema.\n\n' >> "$TMP/ddl_statements.sql"
|
|
369
|
+
fi
|
|
370
|
+
|
|
263
371
|
# ============================================================================
|
|
264
372
|
# 组装 JSON
|
|
265
373
|
# ============================================================================
|
|
@@ -288,8 +396,13 @@ if [ -d "$ROOT_ABS/docs" ]; then DOCS_DIR=true; else DOCS_DIR=false; fi
|
|
|
288
396
|
"$(json_array_from_file "$TMP/migration_dirs.txt")" \
|
|
289
397
|
"$(json_array_from_file "$TMP/sql_samples.txt")"
|
|
290
398
|
# ⑥ docs
|
|
291
|
-
printf ' "docs": {"docs_dir": %s, "doc_files": %s}
|
|
399
|
+
printf ' "docs": {"docs_dir": %s, "doc_files": %s},\n' \
|
|
292
400
|
"$DOCS_DIR" "$(json_array_from_file "$TMP/doc_files.txt")"
|
|
401
|
+
# ⑦ DDL 提取(v0.24.0)
|
|
402
|
+
printf ' "ddl_extraction": {"source": "%s", "table_count": %s, "tables": %s, "ddl_statements": "%s"}\n' \
|
|
403
|
+
"$(json_escape "$DDL_SOURCE")" "$DDL_TABLE_COUNT" \
|
|
404
|
+
"$(json_array_from_file "$TMP/ddl_tables.txt")" \
|
|
405
|
+
"$(json_escape "$(cat "$TMP/ddl_statements.sql" 2>/dev/null)")"
|
|
293
406
|
printf '}\n'
|
|
294
407
|
} > "$TMP/out.json"
|
|
295
408
|
|
|
@@ -311,6 +424,13 @@ else
|
|
|
311
424
|
emit_json
|
|
312
425
|
fi
|
|
313
426
|
|
|
427
|
+
# v0.24.0: DDL 独立输出文件(--ddl-out)
|
|
428
|
+
if [ -n "$DDL_OUT" ] && [ -s "$TMP/ddl_statements.sql" ]; then
|
|
429
|
+
mkdir -p "$(dirname "$DDL_OUT")" 2>/dev/null || true
|
|
430
|
+
cp "$TMP/ddl_statements.sql" "$DDL_OUT" 2>/dev/null || true
|
|
431
|
+
echo "[recon-probe] DDL baseline written to: $DDL_OUT" >&2
|
|
432
|
+
fi
|
|
433
|
+
|
|
314
434
|
# 人类可读摘要 → stderr
|
|
315
435
|
{
|
|
316
436
|
echo "================ recon-probe 摘要 ================"
|
|
@@ -322,6 +442,7 @@ fi
|
|
|
322
442
|
echo "SQL 迁移 : $SQL_COUNT 个"
|
|
323
443
|
echo "docs/ 目录 : $DOCS_DIR"
|
|
324
444
|
echo "README 等 : $(wc -l < "$TMP/doc_files.txt" | tr -d ' ') 个"
|
|
445
|
+
echo "DDL 提取 : source=$DDL_SOURCE, tables=$DDL_TABLE_COUNT"
|
|
325
446
|
echo "================================================="
|
|
326
447
|
} >&2
|
|
327
448
|
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
检测可复利时刻(需求矛盾、原型返工、自动评审发现不一致并修正等)。每次自动评审发现不一致并修正后触发:
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
57
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf solutions capture --phase prd --domain <domain> --type pitfall --severity <sev> --summary "<summary>"
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
### 6. 反馈环路检查点
|
|
@@ -38,7 +38,7 @@ verdict = FAIL → 必须回退 S3 调整拆分后重新审计,不可绕过直
|
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
40
|
mkdir -p changes/<change-name>
|
|
41
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
41
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf state init changes/<change-name>
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
> ⚠️ **路径约束**:change 脚手架目录固定为项目根 `changes/<change-name>/`。
|
|
@@ -15,14 +15,14 @@ Do NOT invoke for: general coding tasks outside team-flow changes, casual questi
|
|
|
15
15
|
|
|
16
16
|
## States
|
|
17
17
|
|
|
18
|
-
`exploring` → `specifying` → `bridging` → `approved-for-build` → `executing` → `closing`, with `debugging` side-path from `executing`, and `abandoned` as terminal. If a transition is ambiguous, run `npx --yes --package @xulthekl/team-flow@0.
|
|
18
|
+
`exploring` → `specifying` → `bridging` → `approved-for-build` → `executing` → `closing`, with `debugging` side-path from `executing`, and `abandoned` as terminal. If a transition is ambiguous, run `npx --yes --package @xulthekl/team-flow@0.25.1 tf runtime asset read docs/state-machine.md`.
|
|
19
19
|
|
|
20
20
|
## Initialization
|
|
21
21
|
|
|
22
|
-
1. **Update check**: Run `npx --yes --package @xulthekl/team-flow@0.
|
|
22
|
+
1. **Update check**: Run `npx --yes --package @xulthekl/team-flow@0.25.1 tf runtime check-update`. Exit 0 → continue. Exit 1 → non-blocking upgrade reminder. Exit 2 → skip.
|
|
23
23
|
2. **Inspect change folder**: Check for `proposal.md`, `specs/`, `design.md`, `tasks.md`, `execution-contract.md`. Answer: Is the change fuzzy? Artifacts missing/unstable? Contract exist? User approved contract? Execution in progress or blocked? In verification/wrap-up?
|
|
24
|
-
3. **Overlay recovery scan**: Run `npx --yes --package @xulthekl/team-flow@0.
|
|
25
|
-
4. **Execution-control recovery scan**: For `approved-for-build`, `executing`, `debugging`, or `closing`, run `npx --yes --package @xulthekl/team-flow@0.
|
|
24
|
+
3. **Overlay recovery scan**: Run `npx --yes --package @xulthekl/team-flow@0.25.1 tf handoff list <change-dir> --json` and `npx --yes --package @xulthekl/team-flow@0.25.1 tf checkpoint list <change-dir> --json`. A `result-ready` handoff requires explicit review and `npx --yes --package @xulthekl/team-flow@0.25.1 tf handoff resolve` before resuming the affected work. An `active` handoff is non-blocking side work. Show a non-stale checkpoint as recovery context; show a stale checkpoint only as historical evidence.
|
|
25
|
+
4. **Execution-control recovery scan**: For `approved-for-build`, `executing`, `debugging`, or `closing`, run `npx --yes --package @xulthekl/team-flow@0.25.1 tf execution show <change-dir> --json`. Treat only `current: true` plus `waves[].eligible: true` as permission to start a wave; report plan revision, mode, next eligible wave, and every wave's receipt/blockers. A missing, invalid, or stale plan blocks implementation and routes to `build-executor`; do not infer progress from chat history.
|
|
26
26
|
|
|
27
27
|
## DP-0: User Confirmation Gate
|
|
28
28
|
|
|
@@ -36,17 +36,17 @@ Ask (manual path): change name + one-sentence intent, known constraints, related
|
|
|
36
36
|
|
|
37
37
|
After confirmation:
|
|
38
38
|
```bash
|
|
39
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
40
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
41
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
42
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
39
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf state set <change-dir> dp_0_decisions "<summary>"
|
|
40
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf state set <change-dir> dp_0_result confirmed
|
|
41
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf state set <change-dir> dp_0_confirmed true
|
|
42
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf state set <change-dir> dp_0_timestamp $(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
Config-aware routing: check `artifacts.order` and `artifacts.skip` from project config.
|
|
46
46
|
|
|
47
47
|
## Mode Detection
|
|
48
48
|
|
|
49
|
-
If workflow is `auto`/`null`/unset: run `npx --yes --package @xulthekl/team-flow@0.
|
|
49
|
+
If workflow is `auto`/`null`/unset: run `npx --yes --package @xulthekl/team-flow@0.25.1 tf runtime infer <change-dir>`. Inference: **hotfix** (≤2 tasks, ≤2 files, no schema/API/new modules), **tweak** (≤4 tasks, config/doc only), **full** (anything larger). Persist with `npx --yes --package @xulthekl/team-flow@0.25.1 tf state set <dir> workflow <mode>`.
|
|
50
50
|
|
|
51
51
|
Validate mode against artifact content. If hotfix/tweak criteria not met → upgrade to `full` and output reason. Don't overwrite explicit mode unless user asks.
|
|
52
52
|
|
|
@@ -59,19 +59,19 @@ Change is fuzzy, scope unclear, comparing options, no stable change name.
|
|
|
59
59
|
Guard: `arch_design_decision` in `.team-flow.yaml` is `null` → must run before spec-writer. Dispatch `architecture-design` as sub-agent; after return, run reasonableness check and write yaml. Full protocol in `references/routing-rules.md`「Route to architecture-design」.
|
|
60
60
|
|
|
61
61
|
### Route to spec-writer
|
|
62
|
-
Guard: `npx --yes --package @xulthekl/team-flow@0.
|
|
62
|
+
Guard: `npx --yes --package @xulthekl/team-flow@0.25.1 tf runtime guard check <dir> exploring specifying --json` → fail = BLOCK. **arch_design_decision must not be null** → fail = BLOCK (v0.9 §26). User knows what they want, artifacts missing/incomplete.
|
|
63
63
|
|
|
64
64
|
### Route to contract-builder
|
|
65
65
|
Guard: `... check <dir> specifying bridging --json` → fail = BLOCK. Artifacts exist, implementation requested, contract missing/stale. Include `DP-3: 契约批准`.
|
|
66
66
|
|
|
67
67
|
### Route to build-executor
|
|
68
|
-
Contract exists and approved, contract matches artifacts. Include `DP-4: 执行模式选择`: propose waves, run `npx --yes --package @xulthekl/team-flow@0.
|
|
68
|
+
Contract exists and approved, contract matches artifacts. Include `DP-4: 执行模式选择`: propose waves, run `npx --yes --package @xulthekl/team-flow@0.25.1 tf execution recommend <change-dir> [--wave ...]`, show the user every available mode plus evidence and the recommendation, then obtain a clear selection. The command saves a current receipt; before the first implementation edit, `build-executor` must run `npx --yes --package @xulthekl/team-flow@0.25.1 tf execution plan <change-dir> --mode <selected> --confirm ...` (and `--acknowledge-recommendation` when the selected mode differs from the recommendation) using matching artifacts, contract, and waves, then `npx --yes --package @xulthekl/team-flow@0.25.1 tf execution show <change-dir> --json`; report the saved revision, selected mode, recommendation alignment, ordered waves, and actual concurrent-dispatch capability. A revision must repeat recommend and confirmation. Do not transition to `executing` until `show` reports `current: true`; then run `... check <dir> approved-for-build executing --json` → fail = BLOCK.
|
|
69
69
|
|
|
70
70
|
### Route to bug-investigator
|
|
71
71
|
Execution hit blockage: test failure, unexpected behavior, build error, task cannot proceed. After debugging, route back to build-executor.
|
|
72
72
|
|
|
73
73
|
### Route to code-reviewer
|
|
74
|
-
The current planned wave is implemented and ready for spec-compliance + code-quality verification. A reviewer must write an `npx --yes --package @xulthekl/team-flow@0.
|
|
74
|
+
The current planned wave is implemented and ready for spec-compliance + code-quality verification. A reviewer must write an `npx --yes --package @xulthekl/team-flow@0.25.1 tf execution review <change-dir> --wave <id> --base <sha> --head <sha> --report <path> --verdict <pass|fail>` receipt before any dependent wave or closing transition.
|
|
75
75
|
|
|
76
76
|
### Route to release-archivist
|
|
77
77
|
Guard: `... check <dir> executing closing --json` → fail = BLOCK. Implementation complete, verification complete/nearly complete. Include `DP-7: 归档确认`.
|
|
@@ -90,10 +90,10 @@ uncertainty. Do not create a prototype handoff or enter a prototype worktree
|
|
|
90
90
|
until the user confirms. After confirmation:
|
|
91
91
|
|
|
92
92
|
```bash
|
|
93
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
93
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf handoff create <change-dir> \
|
|
94
94
|
--type prototype --objective "<confirmed objective>" \
|
|
95
95
|
--expected-output "<expected evidence>" --acceptance "<completion criterion>"
|
|
96
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
96
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf isolate <change-dir> prototype-<handoff-id>
|
|
97
97
|
```
|
|
98
98
|
|
|
99
99
|
Never suggest or enter this route automatically for backend, CLI, configuration,
|
|
@@ -107,7 +107,7 @@ work.
|
|
|
107
107
|
- **Hotfix**: Route to contract-builder (minimal), skip need-explorer + spec-writer, guard check `exploring bridging --workflow hotfix`, then `bridging -> approved-for-build`, after DP-3 → build-executor (recommend, show, and confirm an execution mode), after → release-archivist (lightweight). Hotfix may skip `proposal.md`, `design.md`, `tasks.md`, and `specs/`, but it still requires a fresh minimal `execution-contract.md`, DP-3 approval, and a current execution plan before build. **architecture-design 不豁免**(v0.9 §26):同样过 architecture-design 子代理判断门,快速判定是否涉及架构变更(hotfix 可能正是架构缺陷导致)
|
|
108
108
|
- **Tweak**: Route to build-executor (direct edit), skip need-explorer + spec-writer + contract-builder, guard check `exploring approved-for-build --workflow tweak`, after → release-archivist (lightweight). **architecture-design 不豁免**(v0.9 §26):同样过 architecture-design 子代理判断门
|
|
109
109
|
|
|
110
|
-
Post-transition: 💡 `npx --yes --package @xulthekl/team-flow@0.
|
|
110
|
+
Post-transition: 💡 `npx --yes --package @xulthekl/team-flow@0.25.1 tf inject <change-dir>` to update phase-guard artifacts.
|
|
111
111
|
|
|
112
112
|
## Staleness Detection
|
|
113
113
|
|
|
@@ -124,7 +124,7 @@ Use content inspection, not timestamps.
|
|
|
124
124
|
## Guardrails
|
|
125
125
|
|
|
126
126
|
- No implementation before planning artifacts or contract exist
|
|
127
|
-
- No implementation for full/hotfix without a current `npx --yes --package @xulthekl/team-flow@0.
|
|
127
|
+
- No implementation for full/hotfix without a current `npx --yes --package @xulthekl/team-flow@0.25.1 tf execution plan`; no state transition based on an unverified DP-4 string
|
|
128
128
|
- No "continue" without state inspection
|
|
129
129
|
- No implementation past stale contract
|
|
130
130
|
- No implementation past bug without investigation
|
|
@@ -32,17 +32,17 @@ artifacts: # required 时必填
|
|
|
32
32
|
- `null`(未判定)→ **BLOCK**
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
36
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
37
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
35
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf state set <change-dir> arch_design_decision "<required|skipped>"
|
|
36
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf state set <change-dir> arch_design_reason "<reason>"
|
|
37
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf state set <change-dir> arch_design_timestamp $(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
38
38
|
# if required:
|
|
39
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
39
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf state set <change-dir> arch_design_artifacts "architecture/architecture.md,architecture/database.md,architecture/api.md"
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
**hotfix / tweak 不豁免**:同样过 architecture-design 子代理判断门。
|
|
43
43
|
|
|
44
44
|
## Route to spec-writer
|
|
45
|
-
Guard: `npx --yes --package @xulthekl/team-flow@0.
|
|
45
|
+
Guard: `npx --yes --package @xulthekl/team-flow@0.25.1 tf runtime guard check <dir> exploring specifying --json` → fail = BLOCK.
|
|
46
46
|
**arch_design_decision must not be null** → fail = BLOCK(architecture-design gate not passed,v0.9 §26)。
|
|
47
47
|
User knows what they want, artifacts missing/incomplete.
|
|
48
48
|
|
|
@@ -55,12 +55,12 @@ Contract exists and approved, contract matches artifacts. Include DP-4: 执行
|
|
|
55
55
|
|
|
56
56
|
Propose waves, run:
|
|
57
57
|
```bash
|
|
58
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
58
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf execution recommend <change-dir> [--wave ...]
|
|
59
59
|
```
|
|
60
60
|
Show every available mode plus evidence and recommendation, obtain clear selection. Then:
|
|
61
61
|
```bash
|
|
62
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
63
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
62
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf execution plan <change-dir> --mode <selected> --confirm ...
|
|
63
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf execution show <change-dir> --json
|
|
64
64
|
```
|
|
65
65
|
Do not transition to `executing` until `show` reports `current: true`.
|
|
66
66
|
Guard: `... check <dir> approved-for-build executing --json` → fail = BLOCK.
|
|
@@ -71,7 +71,7 @@ Execution hit blockage: test failure, unexpected behavior, build error. After de
|
|
|
71
71
|
## Route to code-reviewer
|
|
72
72
|
Current planned wave implemented and ready for review. Reviewer must write:
|
|
73
73
|
```bash
|
|
74
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
74
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf execution review <change-dir> --wave <id> --base <sha> --head <sha> --report <path> --verdict <pass|fail>
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
## Route to release-archivist
|
|
@@ -93,10 +93,10 @@ User explicitly requests, bug-investigator escalates after 3+ failures AND user
|
|
|
93
93
|
|
|
94
94
|
When the user's brief explicitly contains UI/screen/interaction/layout/UX uncertainty, ask once whether a prototype would reduce uncertainty. After confirmation:
|
|
95
95
|
```bash
|
|
96
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
96
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf handoff create <change-dir> \
|
|
97
97
|
--type prototype --objective "<confirmed objective>" \
|
|
98
98
|
--expected-output "<expected evidence>" --acceptance "<completion criterion>"
|
|
99
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
99
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf isolate <change-dir> prototype-<handoff-id>
|
|
100
100
|
```
|
|
101
101
|
Never suggest for backend/CLI/config/internal-refactor work. Never pass `--force`.
|
|
102
102
|
|
|
@@ -130,17 +130,17 @@ else:
|
|
|
130
130
|
|
|
131
131
|
After confirmation:
|
|
132
132
|
```bash
|
|
133
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
134
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
135
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
136
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
133
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf state set <change-dir> dp_0_decisions "<summary>"
|
|
134
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf state set <change-dir> dp_0_result confirmed
|
|
135
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf state set <change-dir> dp_0_confirmed true
|
|
136
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf state set <change-dir> dp_0_timestamp $(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
137
137
|
```
|
|
138
138
|
|
|
139
139
|
## Mode Detection
|
|
140
140
|
|
|
141
141
|
If workflow is `auto`/`null`/unset:
|
|
142
142
|
```bash
|
|
143
|
-
npx --yes --package @xulthekl/team-flow@0.
|
|
143
|
+
npx --yes --package @xulthekl/team-flow@0.25.1 tf runtime infer <change-dir>
|
|
144
144
|
```
|
|
145
145
|
Inference: **hotfix** (≤2 tasks, ≤2 files, no schema/API/new modules), **tweak** (≤4 tasks, config/doc only), **full** (anything larger).
|
|
146
146
|
|
|
@@ -152,4 +152,4 @@ Inference: **hotfix** (≤2 tasks, ≤2 files, no schema/API/new modules), **twe
|
|
|
152
152
|
- **Brief drift (advisory, v0.9)**: change-brief.md 的 `plan_hash` 与当前 plan.md 不一致 → 提示回 orchestrator 重新分发;**不**阻断、**不**进 artifacts_hash、**不**混入上述三条产物互查
|
|
153
153
|
|
|
154
154
|
## Post-transition
|
|
155
|
-
💡 `npx --yes --package @xulthekl/team-flow@0.
|
|
155
|
+
💡 `npx --yes --package @xulthekl/team-flow@0.25.1 tf inject <change-dir>` to update phase-guard artifacts.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# PRD Brainstorm Profile: GTMC D7 业务要件
|
|
2
|
+
|
|
3
|
+
本文件定义 ce-brainstorm Phase 2 方案探索的**产品维度锚点**。
|
|
4
|
+
Phase 2 产出的每个方案必须覆盖核心维度,按需覆盖扩展维度,不得越入反例边界。
|
|
5
|
+
|
|
6
|
+
## 核心思考维度(每个方案必须覆盖)
|
|
7
|
+
|
|
8
|
+
| 维度 | 对应 PRD 章节 | 引导问题 |
|
|
9
|
+
|------|-------------|---------|
|
|
10
|
+
| 业务流程 | §2 业务流程一览 + §3 D7.1 | 完整的业务操作流程是什么?L1分类→L2分组→L3流程→L4子流程分别是什么? |
|
|
11
|
+
| 状态模型 | §3(流程步骤中的状态流转) | 核心实体有哪些状态?状态之间如何流转?触发条件和约束是什么? |
|
|
12
|
+
| 权限模型 | §8.2.1 权限说明 | 谁(用户类型)在什么条件下能做什么操作?登录前/后有区别吗? |
|
|
13
|
+
| 用户角色 | §8.2.1 + §10.4.1 项目体制 | 系统有哪些使用者类型?各自职责?与画面如何映射? |
|
|
14
|
+
| 数据关系 | §4.3 信息结构图 | 核心业务实体之间的关联规则是什么?实体间的层级/归属/引用关系? |
|
|
15
|
+
| 业务规则 | §8.2.4 其他机制与规则 | 排序规则?搜索规则?加载机制?异常处理?校验逻辑? |
|
|
16
|
+
| 系统功能 | §7 D7.5 系统功能清单 | 需要哪些功能点?每个功能点关联哪个业务流程/活动? |
|
|
17
|
+
|
|
18
|
+
## 扩展思考维度(按需触发)
|
|
19
|
+
|
|
20
|
+
| 维度 | 触发条件 | 对应 PRD 章节 | 引导问题 |
|
|
21
|
+
|------|---------|-------------|---------|
|
|
22
|
+
| 画面设计 | 涉及 UI 交互 | §4 D7.2 | 画面结构如何?页面间如何迁移? |
|
|
23
|
+
| 业务术语 | 出现领域专有名词 | §6 D7.4 | 哪些术语需要统一定义?有无同义词? |
|
|
24
|
+
| 报表需求 | 用户提到"报表/统计/分析" | §5 D7.3 | 需要哪些报表?关联哪些流程和数据? |
|
|
25
|
+
| 交互机制 | 有特殊交互需求 | §8.2.2 | 键盘/画面/弹层交互细节? |
|
|
26
|
+
| 非功能性需求 | 有性能/安全/可用性要求 | §8.5 | 响应时间?并发数?安全要求? |
|
|
27
|
+
| 编码规则 | 有自动编号需求 | §8.7 | 编号规则是什么?自动生成还是手工? |
|
|
28
|
+
|
|
29
|
+
## 反例边界(Phase 2 禁止产出)
|
|
30
|
+
|
|
31
|
+
以下内容属于 ce-plan(技术实施阶段),在 Phase 2 方案探索中**不应包含**:
|
|
32
|
+
|
|
33
|
+
- 后端模块划分(如:domainpolicy/、deptpolicy/)
|
|
34
|
+
- 前端页面/组件结构(如:views/policy/domainPolicy.vue)
|
|
35
|
+
- 数据库表设计(表名、字段名、索引、物理模型)
|
|
36
|
+
- API 接口定义(路径、参数、响应结构)
|
|
37
|
+
- 技术选型(框架、库、中间件选择)
|
|
38
|
+
- 部署架构(服务器、容器、网络拓扑)
|
|
39
|
+
- 代码结构(类名、方法名、包结构)
|
|
40
|
+
|
|
41
|
+
## 正向示例
|
|
42
|
+
|
|
43
|
+
**正确的产品方案输出**(以"方针管理"为例):
|
|
44
|
+
|
|
45
|
+
> **方案 A:集中式方针管理**
|
|
46
|
+
> - 业务流程:方针创建→内容填写→提交审批→审批通过→发布上线→定期回顾→停用/续期
|
|
47
|
+
> - 状态模型:草稿(可编辑)→ 待审批(锁定)→ 已发布(只读)→ 已停用 → 可续期为新草稿
|
|
48
|
+
> - 权限模型:管理员(全流程操作)、部门负责人(创建+编辑本部门)、普通用户(查看已发布)
|
|
49
|
+
> - 业务规则:每个年度只能有一条有效方针;发布后不可编辑,需停用后创建新版本
|
|
50
|
+
>
|
|
51
|
+
> **方案 B:分布式方针管理**
|
|
52
|
+
> - 业务流程:部门自主创建→部门内审批→自动发布→总部可抽查
|
|
53
|
+
> - 状态模型:草稿 → 部门审批中 → 已发布 → 已归档
|
|
54
|
+
> - ...
|
|
55
|
+
|
|
56
|
+
**错误的技术方案输出**(Phase 2 不应出现):
|
|
57
|
+
|
|
58
|
+
> ~~方案采用标准分离式实现:~~
|
|
59
|
+
> ~~后端模块:domainpolicy/(领域方针)、deptpolicy/(部门方针)~~
|
|
60
|
+
> ~~数据库表:t_domain_policy(id, name, status, created_by...)~~
|
|
61
|
+
> ~~前端页面:views/policy/domainPolicy.vue~~
|
|
62
|
+
|
|
63
|
+
## 自定义 Profile
|
|
64
|
+
|
|
65
|
+
创建新 PRD 模板时,应同步创建对应的 brainstorm profile:
|
|
66
|
+
|
|
67
|
+
1. 文件命名:`<模板名>-brainstorm-profile.md`(与模板同目录)
|
|
68
|
+
2. 三段结构:核心维度(必选覆盖)+ 扩展维度(按需触发)+ 反例边界(禁止越界)
|
|
69
|
+
3. 未配套 profile 的模板将使用本文件(内置默认)——维度可能不匹配
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// tests/lib/guard-compound-captured.test.mjs
|
|
2
|
+
// v0.24.0: compound-captured guard — executing:closing must require learnings.md
|
|
3
|
+
// or explicit compound_skipped=true in state.
|
|
4
|
+
|
|
5
|
+
import { describe, it, before, after } from 'node:test';
|
|
6
|
+
import assert from 'node:assert/strict';
|
|
7
|
+
import { mkdtempSync, writeFileSync, rmSync, mkdirSync, existsSync } from 'node:fs';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
import { tmpdir } from 'node:os';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
import { dirname } from 'node:path';
|
|
12
|
+
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const ROOT = join(__dirname, '..', '..');
|
|
15
|
+
|
|
16
|
+
// Import the check function directly for unit-level testing.
|
|
17
|
+
const { checkCompoundCaptured } = await import(
|
|
18
|
+
join(ROOT, 'scripts', 'guard', 'checks', 'compound-captured.mjs')
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
function makeDir(prefix) {
|
|
22
|
+
return mkdtempSync(join(tmpdir(), `tf-compound-${prefix}-`));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function cleanup(dir) {
|
|
26
|
+
if (existsSync(dir)) rmSync(dir, { recursive: true, force: true });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
describe('compound-captured guard', () => {
|
|
30
|
+
describe('learnings.md existence', () => {
|
|
31
|
+
let dir;
|
|
32
|
+
before(() => { dir = makeDir('learnings'); });
|
|
33
|
+
after(() => cleanup(dir));
|
|
34
|
+
|
|
35
|
+
it('SHALL fail when no learnings.md and no compound_skipped', () => {
|
|
36
|
+
writeFileSync(join(dir, '.team-flow.yaml'), 'state: executing\nworkflow: full\n');
|
|
37
|
+
const result = checkCompoundCaptured(dir);
|
|
38
|
+
assert.equal(result.pass, false);
|
|
39
|
+
assert.ok(result.failures.length > 0);
|
|
40
|
+
assert.match(result.failures[0], /Compound capture missing/);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('SHALL pass when learnings.md exists and is non-empty', () => {
|
|
44
|
+
writeFileSync(join(dir, 'learnings.md'), '# Session Learnings\n\n## Lesson 1\nTest.\n');
|
|
45
|
+
const result = checkCompoundCaptured(dir);
|
|
46
|
+
assert.equal(result.pass, true);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('SHALL fail when learnings.md exists but is empty', () => {
|
|
50
|
+
writeFileSync(join(dir, 'learnings.md'), '');
|
|
51
|
+
const result = checkCompoundCaptured(dir);
|
|
52
|
+
assert.equal(result.pass, false);
|
|
53
|
+
assert.match(result.failures[0], /empty/);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe('compound_skipped explicit opt-out', () => {
|
|
58
|
+
let dir;
|
|
59
|
+
before(() => { dir = makeDir('skip'); });
|
|
60
|
+
after(() => cleanup(dir));
|
|
61
|
+
|
|
62
|
+
it('SHALL pass when compound_skipped=true and no learnings.md', () => {
|
|
63
|
+
writeFileSync(join(dir, '.team-flow.yaml'), 'state: executing\nworkflow: full\ncompound_skipped: true\n');
|
|
64
|
+
const result = checkCompoundCaptured(dir);
|
|
65
|
+
assert.equal(result.pass, true);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('SHALL fail when compound_skipped=false (not opted out)', () => {
|
|
69
|
+
writeFileSync(join(dir, '.team-flow.yaml'), 'state: executing\nworkflow: full\ncompound_skipped: false\n');
|
|
70
|
+
const result = checkCompoundCaptured(dir);
|
|
71
|
+
assert.equal(result.pass, false);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe('no state file (backward compatibility)', () => {
|
|
76
|
+
let dir;
|
|
77
|
+
before(() => { dir = makeDir('no-state'); });
|
|
78
|
+
after(() => cleanup(dir));
|
|
79
|
+
|
|
80
|
+
it('SHALL fail when no state file and no learnings.md', () => {
|
|
81
|
+
// No .team-flow.yaml, no learnings.md — guard should still fail
|
|
82
|
+
const result = checkCompoundCaptured(dir);
|
|
83
|
+
assert.equal(result.pass, false);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('SHALL pass when no state file but learnings.md exists', () => {
|
|
87
|
+
writeFileSync(join(dir, 'learnings.md'), '# Learnings\nContent.\n');
|
|
88
|
+
const result = checkCompoundCaptured(dir);
|
|
89
|
+
assert.equal(result.pass, true);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
});
|
|
@@ -27,6 +27,8 @@ function makeChangeDir(withDelta) {
|
|
|
27
27
|
? '## ADDED Requirements\n\n### Requirement: New\n\nThe system SHALL do new.\n\n#### Scenario: New\n- **WHEN** x\n- **THEN** y\n'
|
|
28
28
|
: '## Requirements\n\n### Requirement: Existing\n\nThe system SHALL exist.\n\n#### Scenario: Existing\n- **WHEN** a\n- **THEN** b\n';
|
|
29
29
|
writeFileSync(join(dir, 'specs', 'test.md'), specsContent);
|
|
30
|
+
// v0.24.0: compound-captured dimension requires learnings.md
|
|
31
|
+
writeFileSync(join(dir, 'learnings.md'), '# Session Learnings\n\n## Lesson 1\nTest.\n');
|
|
30
32
|
initializeGitRepository(dir);
|
|
31
33
|
return dir;
|
|
32
34
|
}
|
|
@@ -25,6 +25,8 @@ function makeChangeDir() {
|
|
|
25
25
|
writeFileSync(join(dir, 'tasks.md'), '# Tasks\n\n- [x] Task 1\n- [x] Task 2\n');
|
|
26
26
|
writeFileSync(join(dir, 'specs', 'test.md'), '## ADDED Requirements\n\n### Requirement: Test\n\nThe system SHALL test.\n\n#### Scenario: Test\n- **WHEN** test\n- **THEN** test\n');
|
|
27
27
|
writeFileSync(join(dir, 'execution-contract.md'), '# Execution Contract\n\n## Intent Lock\nTest.\n');
|
|
28
|
+
// v0.24.0: compound-captured dimension requires learnings.md
|
|
29
|
+
writeFileSync(join(dir, 'learnings.md'), '# Session Learnings\n\n## Lesson 1\nTest.\n');
|
|
28
30
|
initializeGitRepository(dir);
|
|
29
31
|
return dir;
|
|
30
32
|
}
|
package/tests/lib/guard.test.mjs
CHANGED
|
@@ -312,6 +312,8 @@ describe('guard: execution control records', () => {
|
|
|
312
312
|
function recordPassingClosingPrerequisites() {
|
|
313
313
|
runNodeScript(CLI_PATH, ['state', 'set', dir, 'test_result', 'pass: unit tests']);
|
|
314
314
|
runNodeScript(CLI_PATH, ['state', 'set', dir, 'spec_merged', 'true']);
|
|
315
|
+
// v0.24.0: compound-captured dimension requires learnings.md (or explicit skip)
|
|
316
|
+
writeFileSync(join(dir, 'learnings.md'), '# Session Learnings\n\n## Lesson 1\nCaptured during guard test.\n');
|
|
315
317
|
}
|
|
316
318
|
|
|
317
319
|
function writeReviewReport(name, content = 'Review completed without blocking findings.\n') {
|