@sushanglewis/lincoln 1.6.3 → 1.7.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.
- package/framework/.claude/agents/pm.md +2 -2
- package/framework/.claude/agents/security-reviewer.md +57 -0
- package/framework/.claude/harnesses/codex.yaml +31 -2
- package/framework/.claude/harnesses/command-map.yaml +4 -0
- package/framework/.claude/harnesses/opencode.yaml +33 -3
- package/framework/.claude/hooks/hooks.yaml +37 -0
- package/framework/.claude/hooks/on-session-start.sh +20 -5
- package/framework/.claude/hooks/on-stop.sh +22 -0
- package/framework/.claude/hooks/pre-tool-use.sh +22 -0
- package/framework/.claude/mcp/mcp.yaml +34 -0
- package/framework/.claude/policies/friction.yaml +18 -0
- package/framework/.claude/policies/security.yaml +46 -0
- package/framework/.claude/schemas/design-review-feedback.json +32 -0
- package/framework/.claude/schemas/stage-definition.schema.json +22 -0
- package/framework/.claude/skills/clarify-requirements/SKILL.md +1 -0
- package/framework/.claude/skills/clarify-requirements/prompts/main.md +44 -10
- package/framework/.claude/stages/clarify.yaml +3 -1
- package/framework/.claude/stages/phase-1-p0-design.yaml +44 -0
- package/framework/.claude/stages/phase-1-p0-implement.yaml +47 -0
- package/framework/.claude/stages/phase-2-p1-design.yaml +53 -0
- package/framework/.claude/stages/phase-2-p1-implement.yaml +45 -0
- package/framework/.claude/workflows/framework-self-improvement.yaml +100 -0
- package/framework/.claude/workflows/interview-to-knowledge.yaml +1 -0
- package/framework/.claude-plugin/marketplace.json +2 -2
- package/framework/.claude-plugin/plugin.json +1 -1
- package/framework/.version-bump.json +1 -1
- package/framework/README.en.md +24 -5
- package/framework/README.md +24 -5
- package/framework/RELEASE.md +22 -0
- package/framework/SKILL.md +15 -6
- package/framework/manifest.json +93 -37
- package/framework/scripts/check-harness-drift.sh +11 -1
- package/framework/scripts/lincoln-setup.py +17 -0
- package/framework/scripts/lincoln_condenser.py +110 -0
- package/framework/scripts/lincoln_friction.py +266 -0
- package/framework/scripts/lincoln_harness_adapter.py +185 -13
- package/framework/scripts/lincoln_mr_mine.py +146 -0
- package/framework/scripts/lincoln_recall.py +142 -0
- package/framework/scripts/lincoln_trace.py +119 -3
- package/framework/scripts/security_analyzer.py +234 -0
- package/framework/scripts/stage_loader.py +124 -1
- package/framework/tools/lincoln/package-lock.json +2 -2
- package/framework/tools/lincoln/package.json +1 -1
- package/framework/tools/lincoln-installer/package.json +6 -1
- package/package.json +6 -1
|
@@ -17,8 +17,8 @@ extends:
|
|
|
17
17
|
|
|
18
18
|
1. 与人类 PM 多轮对话,将访谈或 issue 输入转化为统一、可追溯、已确认的需求与设计方案。
|
|
19
19
|
2. 维护工作包门户 `index.html`:每新增或重命名一个文档/原型子页面,同步更新导航与「相关产物链接」表。
|
|
20
|
-
3. 维护跨子页面影响关系:PRD
|
|
21
|
-
4. 对 designer 的输入完整性负责:PRD
|
|
20
|
+
3. 维护跨子页面影响关系:PRD、用户故事、相关者分析、数据模型等核心文档变更时,在门户中标注受影响的设计文档与原型页面,使下游阶段知悉影响范围。
|
|
21
|
+
4. 对 designer 的输入完整性负责:PRD、用户故事、相关者分析、数据模型、流程图、页面地图必须完整、一致、无歧义;designer 回退确认时,PM 优先澄清,而非让 designer 自行假设。
|
|
22
22
|
5. 在 `product-prototype` 阶段以 reviewer 身份确认原型的功能、字段、流程与需求文档一致。
|
|
23
23
|
|
|
24
24
|
## 专属规则
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lc-security-reviewer
|
|
3
|
+
description: Lincoln 安全审查员角色,专注于框架策略、hook 门控与实现中的安全风险识别。
|
|
4
|
+
language: zh-CN
|
|
5
|
+
extends:
|
|
6
|
+
- agents/default.md
|
|
7
|
+
model: sonnet
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Lincoln Security Reviewer
|
|
11
|
+
|
|
12
|
+
你是 Lincoln 工作流中的安全审查员角色。本角色继承通用契约 [`agents/default.md`](agents/default.md),并补充以下安全专业职责。
|
|
13
|
+
|
|
14
|
+
## 关注点
|
|
15
|
+
|
|
16
|
+
1. **策略完整性**
|
|
17
|
+
- `.claude/policies/*.yaml` 是否覆盖关键风险面(删除、写入、外部调用、git 推送等)。
|
|
18
|
+
- 策略是否可绕过(前缀命令 `sudo`、`cd &&`、`env VAR=`、路径遍历等)。
|
|
19
|
+
|
|
20
|
+
2. **Hook 门控**
|
|
21
|
+
- `pre-tool-use.sh` 是否正确调用 `security_analyzer.py`。
|
|
22
|
+
- 危险操作(`rm -rf`、递归删除、绝对路径删除、git push)是否触发确认或阻断。
|
|
23
|
+
- 日志是否记录充分且不泄露敏感信息。
|
|
24
|
+
|
|
25
|
+
3. **Harness 分发安全**
|
|
26
|
+
- 生成到 codex / opencode 的适配产物是否保留安全策略语义。
|
|
27
|
+
- 默认关闭的能力(hooks/skills)是否确实没有在产物中留下痕迹。
|
|
28
|
+
|
|
29
|
+
4. **实现安全**
|
|
30
|
+
- 新增脚本是否验证输入、避免命令注入、避免路径遍历。
|
|
31
|
+
- 外部 API 调用是否经过允许列表或显式确认。
|
|
32
|
+
- 密钥、token 是否未硬编码。
|
|
33
|
+
|
|
34
|
+
## 输出格式
|
|
35
|
+
|
|
36
|
+
在 stage 评审中返回结构化反馈:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"risks": [
|
|
41
|
+
{
|
|
42
|
+
"severity": "critical|high|medium|low",
|
|
43
|
+
"category": "policy|hook|harness|implementation|secret",
|
|
44
|
+
"description": "风险描述",
|
|
45
|
+
"location": "文件路径:行号",
|
|
46
|
+
"recommendation": "修复建议"
|
|
47
|
+
}
|
|
48
|
+
],
|
|
49
|
+
"approvable": true|false
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## 工作原则
|
|
54
|
+
|
|
55
|
+
- 不阻塞合法的研发活动,但对高危操作必须显式标记。
|
|
56
|
+
- 优先使用自动化检查(策略、测试),人工评审作为补充。
|
|
57
|
+
- 所有发现必须可追溯回具体文件与行号。
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
# codex harness manifest
|
|
2
2
|
# 生成:AGENTS.md(项目根,角色契约 + lc-* 命令清单 + 轻量门控)
|
|
3
3
|
# ~/.codex/prompts/lc-*.md(用户级斜杠命令)
|
|
4
|
+
# ~/.codex/skills/<skill>/SKILL.md(用户级技能)
|
|
4
5
|
# .codex-plugin/plugin.json(显式声明 hooks:{} 以关闭默认 hook 回退)
|
|
6
|
+
# .codex/rules/**/*.md(项目级规则)
|
|
7
|
+
# .codex/hooks/*.sh(项目级 hook)
|
|
8
|
+
# .codex/mcp.json(项目级 MCP 配置)
|
|
5
9
|
# spike 备注:codex 官方 docs 对 prompts frontmatter 描述不完整(网络受限),
|
|
6
10
|
# 采用稳妥约定:prompt 文件为纯 markdown 正文;若真实 CLI 验证不符,
|
|
7
11
|
# 移除 prompts target,命令说明已在 AGENTS.md 内联(回退方案零成本)。
|
|
@@ -13,8 +17,8 @@ capabilities:
|
|
|
13
17
|
# (superpowers codex hooks 陷阱 obra/superpowers@7d8d3d4——hooks 字段缺失时
|
|
14
18
|
# codex 回退到默认 hooks/hooks.json)。新增能力必须显式写出;空能力显式置 false,
|
|
15
19
|
# 不得省略字段。验收测试:tests/test_harness_default_off.py
|
|
16
|
-
hooks:
|
|
17
|
-
skills:
|
|
20
|
+
hooks: true
|
|
21
|
+
skills: true
|
|
18
22
|
agents: true # 经 AGENTS.md 拼接承载
|
|
19
23
|
commands: true
|
|
20
24
|
|
|
@@ -33,6 +37,31 @@ targets:
|
|
|
33
37
|
scope: home
|
|
34
38
|
transform: command-template
|
|
35
39
|
|
|
40
|
+
- kind: skill
|
|
41
|
+
source: .claude/skills/*/SKILL.md
|
|
42
|
+
output: "{home}/.codex/skills/{parent}/{name}.md"
|
|
43
|
+
scope: home
|
|
44
|
+
transform: copy
|
|
45
|
+
|
|
46
|
+
- kind: rule
|
|
47
|
+
source: .claude/rules/**/*.md
|
|
48
|
+
output: "{project}/.codex/rules/{relative_path}.md"
|
|
49
|
+
scope: project
|
|
50
|
+
transform: copy
|
|
51
|
+
optional: true
|
|
52
|
+
|
|
53
|
+
- kind: hook
|
|
54
|
+
source: .claude/hooks/*.sh
|
|
55
|
+
output: "{project}/.codex/hooks/{name}.sh"
|
|
56
|
+
scope: project
|
|
57
|
+
transform: copy
|
|
58
|
+
|
|
59
|
+
- kind: mcp
|
|
60
|
+
source: .claude/mcp/mcp.yaml
|
|
61
|
+
output: "{project}/.codex/mcp.json"
|
|
62
|
+
scope: project
|
|
63
|
+
transform: mcp-config
|
|
64
|
+
|
|
36
65
|
- kind: plugin
|
|
37
66
|
source: .claude-plugin/plugin.json
|
|
38
67
|
output: "{project}/.codex-plugin/{name}.json"
|
|
@@ -244,6 +244,10 @@ commands:
|
|
|
244
244
|
description: 已有源码项目的 Lincoln 迭代工作流
|
|
245
245
|
action: python3 "$LINCOLN_ROOT/scripts/lincoln_workflow.py"
|
|
246
246
|
args_hint: start --workflow existing-project-iteration
|
|
247
|
+
lc-wf-framework-self-improvement:
|
|
248
|
+
description: Lincoln 框架自身持续改进工作流(安全门控、harness 分发、摩擦学习、事件追踪、子代理委托)
|
|
249
|
+
action: python3 "$LINCOLN_ROOT/scripts/lincoln_workflow.py"
|
|
250
|
+
args_hint: start --workflow framework-self-improvement --issue-number <N>
|
|
247
251
|
lc-wf-interview-to-knowledge:
|
|
248
252
|
description: 从访谈录音到 GitHub Issues 再到 Obsidian 知识库沉淀的标准工作流
|
|
249
253
|
action: python3 "$LINCOLN_ROOT/scripts/lincoln_workflow.py"
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# opencode harness manifest
|
|
2
|
-
# 生成:.opencode/agent/*.md(角色)
|
|
2
|
+
# 生成:.opencode/agent/*.md(角色)
|
|
3
|
+
# .opencode/command/lc-*.md(命令)
|
|
4
|
+
# .opencode/skills/<skill>/SKILL.md(项目级技能)
|
|
5
|
+
# .opencode/rules/**/*.md(项目级规则)
|
|
6
|
+
# .opencode/hooks/*.sh(项目级 hook)
|
|
7
|
+
# .opencode/mcp.json(项目级 MCP 配置)
|
|
3
8
|
# spike 结论(Context7 /anomalyco/opencode):
|
|
4
9
|
# agent frontmatter 字段:description/mode/model/temperature/tools/permission
|
|
5
10
|
# command 文件:frontmatter(description/agent/model)+ 正文模板($ARGUMENTS)
|
|
@@ -10,8 +15,8 @@ capabilities:
|
|
|
10
15
|
# 缺省即关闭(#64):任何未显式声明的能力都可能被 harness 按默认值激活
|
|
11
16
|
# (superpowers codex hooks 陷阱 obra/superpowers@7d8d3d4)。新增能力必须显式写出;
|
|
12
17
|
# 空能力显式置 false,不得省略字段。验收测试:tests/test_harness_default_off.py
|
|
13
|
-
hooks:
|
|
14
|
-
skills:
|
|
18
|
+
hooks: true
|
|
19
|
+
skills: true
|
|
15
20
|
agents: true
|
|
16
21
|
commands: true
|
|
17
22
|
|
|
@@ -30,3 +35,28 @@ targets:
|
|
|
30
35
|
output: "{project}/.opencode/command/{name}.md"
|
|
31
36
|
scope: project
|
|
32
37
|
transform: command-template
|
|
38
|
+
|
|
39
|
+
- kind: skill
|
|
40
|
+
source: .claude/skills/*/SKILL.md
|
|
41
|
+
output: "{project}/.opencode/skills/{parent}/{name}.md"
|
|
42
|
+
scope: project
|
|
43
|
+
transform: copy
|
|
44
|
+
|
|
45
|
+
- kind: rule
|
|
46
|
+
source: .claude/rules/**/*.md
|
|
47
|
+
output: "{project}/.opencode/rules/{relative_path}.md"
|
|
48
|
+
scope: project
|
|
49
|
+
transform: copy
|
|
50
|
+
optional: true
|
|
51
|
+
|
|
52
|
+
- kind: hook
|
|
53
|
+
source: .claude/hooks/*.sh
|
|
54
|
+
output: "{project}/.opencode/hooks/{name}.sh"
|
|
55
|
+
scope: project
|
|
56
|
+
transform: copy
|
|
57
|
+
|
|
58
|
+
- kind: mcp
|
|
59
|
+
source: .claude/mcp/mcp.yaml
|
|
60
|
+
output: "{project}/.opencode/mcp.json"
|
|
61
|
+
scope: project
|
|
62
|
+
transform: mcp-config
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
schema_version: 1.0.0
|
|
3
|
+
description: |
|
|
4
|
+
Declarative hook registry for Lincoln.
|
|
5
|
+
Each entry declares the shell hook file, the events it handles, the harnesses
|
|
6
|
+
it applies to, and its execution order. Lower order values run first.
|
|
7
|
+
|
|
8
|
+
hooks:
|
|
9
|
+
- name: pre-tool-use
|
|
10
|
+
file: pre-tool-use.sh
|
|
11
|
+
events: [pre_tool_use]
|
|
12
|
+
harnesses: [claude-code, codex, opencode]
|
|
13
|
+
order: 10
|
|
14
|
+
|
|
15
|
+
- name: on-session-start
|
|
16
|
+
file: on-session-start.sh
|
|
17
|
+
events: [session_start]
|
|
18
|
+
harnesses: [claude-code]
|
|
19
|
+
order: 10
|
|
20
|
+
|
|
21
|
+
- name: on-stop
|
|
22
|
+
file: on-stop.sh
|
|
23
|
+
events: [session_stop]
|
|
24
|
+
harnesses: [claude-code]
|
|
25
|
+
order: 10
|
|
26
|
+
|
|
27
|
+
- name: post-tool-use
|
|
28
|
+
file: post-tool-use.sh
|
|
29
|
+
events: [post_tool_use]
|
|
30
|
+
harnesses: [claude-code]
|
|
31
|
+
order: 10
|
|
32
|
+
|
|
33
|
+
- name: on-pr-event
|
|
34
|
+
file: on-pr-event.sh
|
|
35
|
+
events: [pull_request]
|
|
36
|
+
harnesses: [claude-code]
|
|
37
|
+
order: 10
|
|
@@ -263,7 +263,22 @@ echo "Design ID: ${DESIGN_ID:-(unset)}"
|
|
|
263
263
|
echo "Waiting for: $WAITING_FOR"
|
|
264
264
|
echo ""
|
|
265
265
|
|
|
266
|
-
# 4.
|
|
266
|
+
# 4. Recall relevant knowledge before injecting full context.
|
|
267
|
+
RECALL_JSON=$("$PYTHON" "$FRAMEWORK_ROOT/scripts/lincoln_recall.py" \
|
|
268
|
+
--query "$CURRENT_STAGE" \
|
|
269
|
+
--top-k 5 \
|
|
270
|
+
--format json \
|
|
271
|
+
2>/dev/null || echo '{"docs":[]}')
|
|
272
|
+
_RECALL_COUNT=$(echo "$RECALL_JSON" | "$PYTHON" -c "import sys,json; print(len(json.load(sys.stdin).get('docs',[])))" 2>/dev/null || echo 0)
|
|
273
|
+
if [[ "$_RECALL_COUNT" -gt 0 ]]; then
|
|
274
|
+
echo "=== Lincoln 相关知识 ==="
|
|
275
|
+
echo "$RECALL_JSON" | "$PYTHON" -c "import sys,json; docs=json.load(sys.stdin).get('docs',[]); [print(f'- [{d[\"title\"]}]({d[\"path\"]}) — score {d[\"score\"]}') for d in docs]"
|
|
276
|
+
echo ""
|
|
277
|
+
echo "=== End Lincoln 相关知识 ==="
|
|
278
|
+
echo ""
|
|
279
|
+
fi
|
|
280
|
+
|
|
281
|
+
# 5. Load stage context, agent role, and workflow template (summaries only)
|
|
267
282
|
if [[ "$CURRENT_STAGE" != "not_started" ]]; then
|
|
268
283
|
STAGE_YAML="$FRAMEWORK_ROOT/.claude/stages/$CURRENT_STAGE.yaml"
|
|
269
284
|
if [[ -f "$STAGE_YAML" ]]; then
|
|
@@ -339,7 +354,7 @@ else
|
|
|
339
354
|
NEEDS_OPENING_GUIDANCE="true"
|
|
340
355
|
fi
|
|
341
356
|
|
|
342
|
-
#
|
|
357
|
+
# 6. Load Conductor / OMC context
|
|
343
358
|
if [[ -d "$ROOT/.context" || -d "$ROOT/.omc" ]]; then
|
|
344
359
|
echo "=== Conductor / OMC Context ==="
|
|
345
360
|
for dir in "$ROOT/.context" "$ROOT/.omc"; do
|
|
@@ -362,7 +377,7 @@ if [[ -d "$ROOT/.context" || -d "$ROOT/.omc" ]]; then
|
|
|
362
377
|
echo ""
|
|
363
378
|
fi
|
|
364
379
|
|
|
365
|
-
#
|
|
380
|
+
# 7. Read last node handoff
|
|
366
381
|
HANDOFF_FILE=""
|
|
367
382
|
if [[ "$LAST_NODE" != "{}" ]]; then
|
|
368
383
|
HANDOFF_FILE=$(echo "$LAST_NODE" | "$PYTHON" -c "import sys,json; print(json.load(sys.stdin).get('handoff_file',''))" 2>/dev/null || echo "")
|
|
@@ -387,7 +402,7 @@ if [[ -n "$PROCESS_SLUG" && -d "$ROOT/$PROCESS_SLUG/handoffs" ]]; then
|
|
|
387
402
|
fi
|
|
388
403
|
fi
|
|
389
404
|
|
|
390
|
-
#
|
|
405
|
+
# 8. Run status summary
|
|
391
406
|
STATUS_OUTPUT=$("$PYTHON" "$FRAMEWORK_ROOT/scripts/lincoln-status.py" --format markdown --state-file "$STATE_FILE" 2>/dev/null) || STATUS_OUTPUT=""
|
|
392
407
|
if [[ -n "$STATUS_OUTPUT" ]]; then
|
|
393
408
|
echo "=== Lincoln Status Summary ==="
|
|
@@ -396,7 +411,7 @@ if [[ -n "$STATUS_OUTPUT" ]]; then
|
|
|
396
411
|
echo ""
|
|
397
412
|
fi
|
|
398
413
|
|
|
399
|
-
#
|
|
414
|
+
# 9. Opening guidance for a work package that has not started yet
|
|
400
415
|
if [[ "${NEEDS_OPENING_GUIDANCE:-}" == "true" ]]; then
|
|
401
416
|
_LINCOLN_GUIDANCE_INJECTED="true"
|
|
402
417
|
echo "=== Lincoln 开场引导 ==="
|
|
@@ -101,4 +101,26 @@ if [[ -n "$CURRENT_STAGE" && ( "$STAGE_STATUS" == "waiting_for_human" || "$STAGE
|
|
|
101
101
|
>/dev/null 2>&1 || true
|
|
102
102
|
fi
|
|
103
103
|
|
|
104
|
+
# Record session stop lifecycle event (best-effort).
|
|
105
|
+
"$PYTHON" - "$STATE_FILE" "$FRAMEWORK_ROOT" <<'PY' >/dev/null 2>&1 || true
|
|
106
|
+
import sys
|
|
107
|
+
sys.path.insert(0, sys.argv[2])
|
|
108
|
+
from pathlib import Path
|
|
109
|
+
from scripts import lincoln_trace
|
|
110
|
+
lincoln_trace.append_event_entry(
|
|
111
|
+
Path(sys.argv[1]),
|
|
112
|
+
"session",
|
|
113
|
+
{"event_type": "session_ended"},
|
|
114
|
+
)
|
|
115
|
+
PY
|
|
116
|
+
|
|
117
|
+
# Score session friction asynchronously; failures must not block hook exit.
|
|
118
|
+
(
|
|
119
|
+
"$PYTHON" "$FRAMEWORK_ROOT/scripts/lincoln_friction.py" \
|
|
120
|
+
--root "$FRAMEWORK_ROOT" \
|
|
121
|
+
--state-file "$STATE_FILE" \
|
|
122
|
+
--tail-lines 500 \
|
|
123
|
+
>/dev/null 2>&1 || true
|
|
124
|
+
) &
|
|
125
|
+
|
|
104
126
|
exit 0
|
|
@@ -220,6 +220,28 @@ if [[ "$STAGE_STATUS" == "not_started" || "$STAGE_STATUS" == "entry_validating"
|
|
|
220
220
|
fi
|
|
221
221
|
fi
|
|
222
222
|
|
|
223
|
+
# SecurityAnalyzer: evaluate side-effect tools against risk policy.
|
|
224
|
+
# File deletion requires explicit human confirmation; git push / API calls are logged.
|
|
225
|
+
if is_side_effect "$TOOL_NAME"; then
|
|
226
|
+
SECURITY_LOG_DIR="$FRAMEWORK_ROOT/$PROCESS_SLUG/logs"
|
|
227
|
+
SECURITY_RESULT=$("$PYTHON" "$FRAMEWORK_ROOT/scripts/security_analyzer.py" \
|
|
228
|
+
--root "$FRAMEWORK_ROOT" \
|
|
229
|
+
--tool "$TOOL_NAME" \
|
|
230
|
+
--args "$TOOL_ARGS" \
|
|
231
|
+
--process-slug "$PROCESS_SLUG" \
|
|
232
|
+
--log-dir "$SECURITY_LOG_DIR" \
|
|
233
|
+
2>/dev/null || echo '{"level":"unknown","confirm_required":true,"message":"Security analyzer failed."}')
|
|
234
|
+
|
|
235
|
+
CONFIRM_REQUIRED=$(echo "$SECURITY_RESULT" | "$PYTHON" -c 'import sys,json; print(json.load(sys.stdin).get("confirm_required", False))')
|
|
236
|
+
SECURITY_MESSAGE=$(echo "$SECURITY_RESULT" | "$PYTHON" -c 'import sys,json; print(json.load(sys.stdin).get("message", ""))')
|
|
237
|
+
|
|
238
|
+
if [[ "$CONFIRM_REQUIRED" == "True" ]]; then
|
|
239
|
+
echo "BLOCKED: $SECURITY_MESSAGE" >&2
|
|
240
|
+
echo "Run: $PYTHON $FRAMEWORK_ROOT/scripts/stage_loader.py --stage $CURRENT_STAGE --action approve-gate --approved-by human-pm" >&2
|
|
241
|
+
exit 1
|
|
242
|
+
fi
|
|
243
|
+
fi
|
|
244
|
+
|
|
223
245
|
# When paused/waiting_for_human/validation_failed, only allow read-only tools
|
|
224
246
|
if [[ "$STAGE_STATUS" == "paused" || "$STAGE_STATUS" == "waiting_for_human" || "$STAGE_STATUS" == "validation_failed" ]]; then
|
|
225
247
|
if [[ "$TOOL_NAME" != "Read" && "$TOOL_NAME" != "Grep" && "$TOOL_NAME" != "Glob" ]]; then
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
schema_version: 1.0.0
|
|
3
|
+
description: |
|
|
4
|
+
Declarative MCP server configuration for Lincoln.
|
|
5
|
+
This file is the single source of truth; `scripts/lincoln_harness_adapter.py`
|
|
6
|
+
distributes it to Codex / OpenCode harnesses in their native formats.
|
|
7
|
+
Sensitive values use `${VAR}` placeholders and are resolved from `.env` or the
|
|
8
|
+
runtime environment. Never commit real secrets.
|
|
9
|
+
|
|
10
|
+
servers:
|
|
11
|
+
pencil:
|
|
12
|
+
command: npx
|
|
13
|
+
args:
|
|
14
|
+
- "-y"
|
|
15
|
+
- "@pencil/mcp-server"
|
|
16
|
+
env:
|
|
17
|
+
PENCIL_API_KEY: ${PENCIL_API_KEY}
|
|
18
|
+
enabled: true
|
|
19
|
+
description: Pencil design-file MCP server for .pen import/export.
|
|
20
|
+
harness_overrides:
|
|
21
|
+
codex:
|
|
22
|
+
enabled: false
|
|
23
|
+
opencode:
|
|
24
|
+
enabled: false
|
|
25
|
+
|
|
26
|
+
github:
|
|
27
|
+
command: npx
|
|
28
|
+
args:
|
|
29
|
+
- "-y"
|
|
30
|
+
- "@modelcontextprotocol/server-github"
|
|
31
|
+
env:
|
|
32
|
+
GITHUB_PERSONAL_ACCESS_TOKEN: ${GITHUB_PERSONAL_ACCESS_TOKEN}
|
|
33
|
+
enabled: true
|
|
34
|
+
description: GitHub operations - issues, PRs, repos.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
schema_version: 1.0.0
|
|
2
|
+
thresholds:
|
|
3
|
+
prompt_user: 5
|
|
4
|
+
auto_suggest: 3
|
|
5
|
+
weights:
|
|
6
|
+
tool_failed: 2
|
|
7
|
+
tool_rejected: 3
|
|
8
|
+
retry_spike: 3
|
|
9
|
+
human_override: 5
|
|
10
|
+
long_session: 1
|
|
11
|
+
long_session_minutes: 30
|
|
12
|
+
retry_count_threshold: 3
|
|
13
|
+
signals:
|
|
14
|
+
- tool_failed
|
|
15
|
+
- tool_rejected
|
|
16
|
+
- retry_spike
|
|
17
|
+
- human_override
|
|
18
|
+
- long_session
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
schema_version: 1.0.0
|
|
2
|
+
policies:
|
|
3
|
+
- name: recursive-delete
|
|
4
|
+
tool: Bash
|
|
5
|
+
condition: 'command matches "rm -r" or "rm -rf"'
|
|
6
|
+
level: high
|
|
7
|
+
message: "递归删除风险极高,需人工确认。"
|
|
8
|
+
confirm: true
|
|
9
|
+
|
|
10
|
+
- name: file-deletion
|
|
11
|
+
tool: Bash
|
|
12
|
+
condition: 'command matches any of ["rm", "rmdir"]'
|
|
13
|
+
level: high
|
|
14
|
+
message: "文件/目录删除操作不可逆,需人工确认。"
|
|
15
|
+
confirm: true
|
|
16
|
+
|
|
17
|
+
- name: git-push
|
|
18
|
+
tool: Bash
|
|
19
|
+
condition: 'command matches "git push"'
|
|
20
|
+
level: medium
|
|
21
|
+
message: "git push 将改变远程仓库状态。"
|
|
22
|
+
confirm: false
|
|
23
|
+
log: true
|
|
24
|
+
|
|
25
|
+
- name: external-api-call
|
|
26
|
+
tool: Bash
|
|
27
|
+
condition: 'command matches any external HTTP client (curl, wget, httpie)'
|
|
28
|
+
level: medium
|
|
29
|
+
message: "正在调用外部 API。"
|
|
30
|
+
confirm: false
|
|
31
|
+
log: true
|
|
32
|
+
|
|
33
|
+
- name: file-write-outside-process
|
|
34
|
+
tool: Write|Edit
|
|
35
|
+
condition: "target outside current process_slug"
|
|
36
|
+
level: high
|
|
37
|
+
message: "不允许写入当前 issue 工作包之外的产物目录。"
|
|
38
|
+
confirm: true
|
|
39
|
+
|
|
40
|
+
- name: file-write-inside-process
|
|
41
|
+
tool: Write|Edit
|
|
42
|
+
condition: "target inside current process_slug"
|
|
43
|
+
level: medium
|
|
44
|
+
message: "写入当前 issue 工作包内的文件。"
|
|
45
|
+
confirm: false
|
|
46
|
+
log: true
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "Design Review Feedback",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"required": ["findings"],
|
|
6
|
+
"properties": {
|
|
7
|
+
"findings": {
|
|
8
|
+
"type": "array",
|
|
9
|
+
"items": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"required": ["severity", "summary"],
|
|
12
|
+
"properties": {
|
|
13
|
+
"severity": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"enum": ["critical", "high", "medium", "low"]
|
|
16
|
+
},
|
|
17
|
+
"summary": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"maxLength": 500
|
|
20
|
+
},
|
|
21
|
+
"file": {
|
|
22
|
+
"type": "string"
|
|
23
|
+
},
|
|
24
|
+
"recommendation": {
|
|
25
|
+
"type": "string",
|
|
26
|
+
"maxLength": 1000
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -100,6 +100,28 @@
|
|
|
100
100
|
{ "type": "null" }
|
|
101
101
|
],
|
|
102
102
|
"description": "Agent role to hand off to at stage end"
|
|
103
|
+
},
|
|
104
|
+
"parallel_specialists": {
|
|
105
|
+
"type": "array",
|
|
106
|
+
"items": {
|
|
107
|
+
"type": "string",
|
|
108
|
+
"pattern": "^[a-z][a-z0-9-]*$"
|
|
109
|
+
},
|
|
110
|
+
"default": [],
|
|
111
|
+
"description": "Specialist agents that may be invoked in parallel during this stage"
|
|
112
|
+
},
|
|
113
|
+
"merge_strategy": {
|
|
114
|
+
"type": "string",
|
|
115
|
+
"enum": ["priority", "vote", "consensus"],
|
|
116
|
+
"default": "priority",
|
|
117
|
+
"description": "How to combine outputs from parallel specialists"
|
|
118
|
+
},
|
|
119
|
+
"output_schema": {
|
|
120
|
+
"oneOf": [
|
|
121
|
+
{ "type": "string", "minLength": 1 },
|
|
122
|
+
{ "type": "null" }
|
|
123
|
+
],
|
|
124
|
+
"description": "JSON Schema path for structured specialist outputs"
|
|
103
125
|
}
|
|
104
126
|
},
|
|
105
127
|
"additionalProperties": false
|
|
@@ -10,6 +10,7 @@ inputs:
|
|
|
10
10
|
required: true
|
|
11
11
|
outputs:
|
|
12
12
|
- "{process_slug}/pages/docs/requirements.html"
|
|
13
|
+
- "{process_slug}/pages/docs/stakeholders.html"
|
|
13
14
|
- "{process_slug}/pages/docs/user-stories.html"
|
|
14
15
|
- "{process_slug}/pages/docs/prd.html"
|
|
15
16
|
- "{process_slug}/pages/docs/snapshots/prd-v*.html"
|
|
@@ -33,11 +33,44 @@ Produce a clear, agreed-upon `{process_slug}/pages/docs/requirements.html` and t
|
|
|
33
33
|
Write `{process_slug}/pages/docs/requirements.md` as a regular Markdown document. Use H2 headings for the major chapters (e.g. `## 背景`, `## 问题`, `## 用户`, `## 方案`, `## 验收标准`, `## 非目标`, `## 开放问题`). Within each chapter you may use paragraphs, bullet lists, tables, and ` ```mermaid ` diagrams freely. If a rigid table (e.g. a user-story table) is clearer, you may still create a YAML `--data` file and use `page-doc-structured.html.tpl`.
|
|
34
34
|
|
|
35
35
|
The renderer will derive `nav-label`, `version`, and `uid` automatically if omitted. Include `<!-- version: v1.0 -->` near the top of the Markdown file.
|
|
36
|
-
3.
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
3. Perform a stakeholder analysis and produce `{process_slug}/pages/docs/stakeholders.html`.
|
|
37
|
+
|
|
38
|
+
First, check whether `{process_slug}/research/{session_id}/stakeholders.md` already exists from the `pm-research` workflow. If it does, read it and use it as a starting point rather than starting from scratch.
|
|
39
|
+
|
|
40
|
+
Identify all stakeholders that are relevant to the requirement. For each stakeholder, capture at least the following dimensions in a structured table:
|
|
41
|
+
|
|
42
|
+
| Dimension | Description |
|
|
43
|
+
|-----------|-------------|
|
|
44
|
+
| 角色名称 | A concise role label (e.g., 最终用户, 需求提出方, 建设方, 运营方, 成本承担方, 方向决策者, 影响者/守门人). |
|
|
45
|
+
| 具体是谁 | The actual person, team, or group, if known. |
|
|
46
|
+
| 与需求的关系 | How they interact with the product or requirement. |
|
|
47
|
+
| 权力/影响力 | Their ability to affect decisions or outcomes (高/中/低 + 一句话说明). |
|
|
48
|
+
| 利益诉求 | What they want from this product or requirement. |
|
|
49
|
+
| 经济价值 | Monetary, efficiency, or cost-related value they gain or lose. |
|
|
50
|
+
| 情绪价值 | Emotional or experiential value (e.g., 愉悦感, 安全感, 掌控感, 归属感). |
|
|
51
|
+
| 个人实现价值 | Self-actualization value (e.g., 成长, 成就感, 认同感, 影响力). |
|
|
52
|
+
| 心理预期 | Their implicit expectations, anxieties, or assumptions. |
|
|
53
|
+
| 潜在冲突 | Tensions or misalignments with other stakeholders. |
|
|
54
|
+
| 应对策略 | How the product team should engage or satisfy this stakeholder. |
|
|
55
|
+
|
|
56
|
+
Also capture stakeholder relationships: who depends on whom, who can block whom, and who shares goals.
|
|
57
|
+
|
|
58
|
+
Render the artifact:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
python scripts/lincoln_render.py \
|
|
62
|
+
--stage clarify \
|
|
63
|
+
--target {process_slug}/pages/docs/stakeholders.html \
|
|
64
|
+
--title "相关者分析" \
|
|
65
|
+
--markdown {process_slug}/pages/docs/stakeholders.md
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Write `{process_slug}/pages/docs/stakeholders.md` as a regular Markdown document with H2 chapters such as `## 相关者清单`, `## 关系与冲突`, `## 关键洞察`, `## 开放问题`. Include `<!-- version: v1.0 -->` near the top.
|
|
69
|
+
4. Identify 1-3 ambiguities or missing details, and tag each with its Johari quadrant (认知象限): 知道自己知道 → 复述确认题; 知道自己不知道 → 直接回答 + coach; 不知道自己知道 → 展示已有资产; 不知道自己不知道 → 探查题.
|
|
70
|
+
5. Ask the human PM these questions one batch at a time in the terminal, using the quadrant-appropriate style.
|
|
71
|
+
6. Update `requirements.md` and `stakeholders.md` based on the answers and re-render both `requirements.html` and `stakeholders.html` (always rewrite the Markdown source and re-render; do not mutate HTML in-place).
|
|
72
|
+
7. Repeat until the PM confirms the requirements are clear.
|
|
73
|
+
8. Also generate `{process_slug}/pages/docs/user-stories.html`. You may either write a Markdown file or use the structured renderer with `--data` containing a `stories` array, whichever fits the material:
|
|
41
74
|
|
|
42
75
|
```bash
|
|
43
76
|
python scripts/lincoln_render.py \
|
|
@@ -47,7 +80,7 @@ Produce a clear, agreed-upon `{process_slug}/pages/docs/requirements.html` and t
|
|
|
47
80
|
--markdown {process_slug}/pages/docs/user-stories.md
|
|
48
81
|
```
|
|
49
82
|
|
|
50
|
-
|
|
83
|
+
9. Generate the root-level PRD at `{process_slug}/pages/docs/prd.html` using the Markdown-first renderer:
|
|
51
84
|
|
|
52
85
|
```bash
|
|
53
86
|
python scripts/lincoln_render.py \
|
|
@@ -73,15 +106,15 @@ Produce a clear, agreed-upon `{process_slug}/pages/docs/requirements.html` and t
|
|
|
73
106
|
It must also carry:
|
|
74
107
|
- `<!-- version: v1.0 -->` marker (added automatically by the renderer from the Markdown file or `--version`).
|
|
75
108
|
- Meta tags: `doc-title`, `nav-group="Docs"`, `doc-version="v1.0"`, and a stable `doc-uid` (all injected by the renderer).
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
109
|
+
10. When the PM confirms, add an approval marker inside `requirements.html`: `<!-- status: approved -->`.
|
|
110
|
+
11. After human approval, run `python scripts/lincoln_prd.py freeze` to create the immutable snapshot `{process_slug}/pages/docs/snapshots/prd-v1.0.html`.
|
|
111
|
+
12. Run `python scripts/stage_loader.py --stage clarify --action record-artifacts` to persist the artifact paths and refresh `{process_slug}/assets/js/package-data.js`.
|
|
79
112
|
|
|
80
113
|
## Human Interaction Rules
|
|
81
114
|
|
|
82
115
|
- Ask at most 3 questions per turn.
|
|
83
116
|
- After each answer, update the document and show the changed sections.
|
|
84
|
-
- If the PM edits `requirements.html` or `prd.html` directly and runs `workflow-continue`, re-read the file and continue from there.
|
|
117
|
+
- If the PM edits `requirements.html`, `stakeholders.html`, or `prd.html` directly and runs `workflow-continue`, re-read the file and continue from there.
|
|
85
118
|
- Do not proceed to the next step until the PM explicitly confirms (e.g., says "confirm" or "确认").
|
|
86
119
|
|
|
87
120
|
## 认知象限确认(Johari)
|
|
@@ -103,6 +136,7 @@ Produce a clear, agreed-upon `{process_slug}/pages/docs/requirements.html` and t
|
|
|
103
136
|
## Output Artifacts
|
|
104
137
|
|
|
105
138
|
- `{process_slug}/pages/docs/requirements.html`
|
|
139
|
+
- `{process_slug}/pages/docs/stakeholders.html`
|
|
106
140
|
- `{process_slug}/pages/docs/user-stories.html`
|
|
107
141
|
- `{process_slug}/pages/docs/prd.html` (root-level PRD, versioned)
|
|
108
142
|
- `{process_slug}/pages/docs/snapshots/prd-v1.0.html` (immutable snapshot after approval)
|
|
@@ -19,6 +19,7 @@ variables:
|
|
|
19
19
|
- process_slug
|
|
20
20
|
artifact_templates:
|
|
21
21
|
'{process_slug}/pages/docs/requirements.html': .claude/templates/issue-package/page-doc.html.tpl
|
|
22
|
+
'{process_slug}/pages/docs/stakeholders.html': .claude/templates/issue-package/page-doc.html.tpl
|
|
22
23
|
'{process_slug}/pages/docs/user-stories.html': .claude/templates/issue-package/page-doc.html.tpl
|
|
23
24
|
'{process_slug}/pages/docs/prd.html': .claude/templates/issue-package/page-doc.html.tpl
|
|
24
25
|
'{process_slug}/pages/docs/snapshots/prd-v*.html': .claude/templates/issue-package/page-doc.html.tpl
|
|
@@ -38,6 +39,7 @@ skills:
|
|
|
38
39
|
artifacts:
|
|
39
40
|
required:
|
|
40
41
|
- '{process_slug}/pages/docs/requirements.html'
|
|
42
|
+
- '{process_slug}/pages/docs/stakeholders.html'
|
|
41
43
|
- '{process_slug}/pages/docs/user-stories.html'
|
|
42
44
|
- '{process_slug}/pages/docs/prd.html'
|
|
43
45
|
optional:
|
|
@@ -47,7 +49,7 @@ references:
|
|
|
47
49
|
agent_guide: .claude/agents/pm.md
|
|
48
50
|
context:
|
|
49
51
|
goal: 基于访谈产物(逐字稿、摘要、初始洞察)与人类 PM 进行多轮澄清,形成统一、可追溯、已确认的需求文档,并将 PRD 置于 HTML 门户({process_slug}/pages/docs/prd.html)作为串联后续所有阶段的主线文档与单一事实来源。人类读者通过 {process_slug}/index.html 浏览所有产物。
|
|
50
|
-
execution: "调用 clarify-requirements skill 与人类 PM 进行多轮澄清对话,基于访谈产物识别歧义并达成共识;产出 requirements
|
|
52
|
+
execution: "调用 clarify-requirements skill 与人类 PM 进行多轮澄清对话,基于访谈产物识别歧义并达成共识;产出 requirements、stakeholders、user-stories、prd 四个 HTML 文档,PRD 携带 <!-- version: vX.Y --> 版本标记,确认后通过 scripts/lincoln_prd.py freeze 生成不可变的快照。"
|
|
51
53
|
constraints: "- PRD 必须位于 {process_slug}/pages/docs/prd.html,并携带 <!-- version: vX.Y --> 版本标记;确认后通过 scripts/lincoln_prd.py freeze 生成不可变的 pages/docs/snapshots/prd-vX.Y.html 快照。\n\n - PRD 是产研流程的主线文档,需在后续阶段持续维护「相关产物链接」章节,指向设计、原型、OpenSpec、实现等产物。"
|
|
52
54
|
gates:
|
|
53
55
|
entry:
|