@miniidealab/openlogos 0.9.4 → 0.9.6
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/README.md +1 -0
- package/claude-plugin-template/.claude-plugin/plugin.json +13 -0
- package/claude-plugin-template/agents/change-reviewer.md +46 -0
- package/claude-plugin-template/bin/openlogos-phase +428 -0
- package/claude-plugin-template/commands/archive.md +22 -0
- package/claude-plugin-template/commands/change.md +19 -0
- package/claude-plugin-template/commands/index.md +13 -0
- package/claude-plugin-template/commands/init.md +30 -0
- package/claude-plugin-template/commands/launch.md +16 -0
- package/claude-plugin-template/commands/merge.md +20 -0
- package/claude-plugin-template/commands/next.md +18 -0
- package/claude-plugin-template/commands/status.md +10 -0
- package/claude-plugin-template/commands/sync.md +12 -0
- package/claude-plugin-template/commands/verify.md +17 -0
- package/claude-plugin-template/hooks/hooks.json +14 -0
- package/claude-plugin-template/skills/api-designer/SKILL.md +230 -0
- package/claude-plugin-template/skills/architecture-designer/SKILL.md +186 -0
- package/claude-plugin-template/skills/change-writer/SKILL.md +160 -0
- package/claude-plugin-template/skills/code-implementor/SKILL.md +116 -0
- package/claude-plugin-template/skills/code-reviewer/SKILL.md +214 -0
- package/claude-plugin-template/skills/db-designer/SKILL.md +259 -0
- package/claude-plugin-template/skills/merge-executor/SKILL.md +118 -0
- package/claude-plugin-template/skills/prd-writer/SKILL.md +203 -0
- package/claude-plugin-template/skills/product-designer/SKILL.md +235 -0
- package/claude-plugin-template/skills/project-init/SKILL.md +168 -0
- package/claude-plugin-template/skills/scenario-architect/SKILL.md +229 -0
- package/claude-plugin-template/skills/test-orchestrator/SKILL.md +147 -0
- package/claude-plugin-template/skills/test-writer/SKILL.md +252 -0
- package/dist/commands/init.d.ts +7 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +145 -10
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/module.d.ts.map +1 -1
- package/dist/commands/module.js +14 -9
- package/dist/commands/module.js.map +1 -1
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +15 -1
- package/dist/commands/sync.js.map +1 -1
- package/dist/commands/verify.d.ts +3 -1
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +60 -28
- package/dist/commands/verify.js.map +1 -1
- package/dist/i18n.d.ts.map +1 -1
- package/dist/i18n.js +10 -4
- package/dist/i18n.js.map +1 -1
- package/dist/index.js +0 -0
- package/package.json +5 -4
- package/skills/test-writer/SKILL.md +21 -1
- package/spec/cli-json-output.md +2 -1
- package/spec/test-results.md +16 -0
package/README.md
CHANGED
|
@@ -31,6 +31,7 @@ openlogos --version
|
|
|
31
31
|
| `openlogos change <slug>` | 创建变更提案(Delta 工作流) |
|
|
32
32
|
| `openlogos merge` / `archive` | 合并与归档变更 |
|
|
33
33
|
| `openlogos launch` | 从首轮开发切换到「活跃迭代」并强化变更管理 |
|
|
34
|
+
| `openlogos module <sub>` | 管理项目模块(list / add / rename / remove) |
|
|
34
35
|
|
|
35
36
|
**注意**:请在**项目根目录**(存在 `logos/logos.config.json`)下执行上述命令。
|
|
36
37
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "openlogos",
|
|
3
|
+
"description": "OpenLogos methodology plugin — structured AI-driven development with Why → What → How progression",
|
|
4
|
+
"version": "0.9.6",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "MiniIdeaLab",
|
|
7
|
+
"url": "https://github.com/miniidealab"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://openlogos.ai",
|
|
10
|
+
"repository": "https://github.com/miniidealab/openlogos",
|
|
11
|
+
"license": "Apache-2.0",
|
|
12
|
+
"keywords": ["methodology", "openlogos", "ai-development", "skills", "requirements", "scenario-driven"]
|
|
13
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: change-reviewer
|
|
3
|
+
description: >
|
|
4
|
+
Review OpenLogos change proposals for completeness and methodology compliance.
|
|
5
|
+
Invoke when the user creates or updates a change proposal under logos/changes/,
|
|
6
|
+
or when reviewing a proposal before implementation begins.
|
|
7
|
+
model: sonnet
|
|
8
|
+
effort: high
|
|
9
|
+
maxTurns: 10
|
|
10
|
+
disallowedTools: Write, Edit
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
You are an OpenLogos change proposal reviewer. Your role is to review change proposals for quality, completeness, and methodology compliance.
|
|
14
|
+
|
|
15
|
+
## Review Checklist
|
|
16
|
+
|
|
17
|
+
For each change proposal, check the following:
|
|
18
|
+
|
|
19
|
+
### proposal.md
|
|
20
|
+
1. **Reason for Change**: Is the motivation clear and well-articulated?
|
|
21
|
+
2. **Change Type**: Is it correctly categorized (bug fix, enhancement, refactor, etc.)?
|
|
22
|
+
3. **Change Scope**: Are all affected files and components listed?
|
|
23
|
+
4. **Change Summary**: Is the technical approach described clearly?
|
|
24
|
+
5. **Backward Compatibility**: Are any breaking changes identified?
|
|
25
|
+
|
|
26
|
+
### tasks.md
|
|
27
|
+
1. **Task Granularity**: Are tasks broken down into implementable units?
|
|
28
|
+
2. **Task Dependencies**: Are dependencies between tasks clear?
|
|
29
|
+
3. **Completeness**: Do the tasks cover all items in the Change Scope?
|
|
30
|
+
4. **Testability**: Can each task be verified independently?
|
|
31
|
+
|
|
32
|
+
### Methodology Compliance
|
|
33
|
+
1. Does the change follow the Why → What → How progression?
|
|
34
|
+
2. If API changes are involved, do they trace back to scenarios?
|
|
35
|
+
3. If new test cases are needed, are they included in the tasks?
|
|
36
|
+
4. Are YAML formatting rules followed for any OpenAPI changes?
|
|
37
|
+
|
|
38
|
+
## Output Format
|
|
39
|
+
|
|
40
|
+
Provide your review as:
|
|
41
|
+
1. **Summary**: One-sentence assessment (APPROVE / NEEDS REVISION / REJECT)
|
|
42
|
+
2. **Strengths**: What the proposal does well
|
|
43
|
+
3. **Issues**: Specific problems that need to be addressed (if any)
|
|
44
|
+
4. **Suggestions**: Optional improvements
|
|
45
|
+
|
|
46
|
+
Be constructive and specific. Reference exact sections when pointing out issues.
|
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# OpenLogos Phase Detector — lightweight shell script for Claude Code plugin hooks.
|
|
3
|
+
# Reads logos/logos.config.json and scans logos/resources/ to determine current phase.
|
|
4
|
+
#
|
|
5
|
+
# When called from SessionStart hook: outputs JSON with systemMessage + additionalContext.
|
|
6
|
+
# When called directly (e.g. from commands): outputs plain text.
|
|
7
|
+
#
|
|
8
|
+
# Usage:
|
|
9
|
+
# ./openlogos-phase → JSON output (for hooks)
|
|
10
|
+
# ./openlogos-phase --plain → plain text output (for commands / terminal)
|
|
11
|
+
|
|
12
|
+
set -euo pipefail
|
|
13
|
+
|
|
14
|
+
MODE="json"
|
|
15
|
+
if [ "${1:-}" = "--plain" ]; then
|
|
16
|
+
MODE="plain"
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
has_files() {
|
|
20
|
+
local dir="$1"
|
|
21
|
+
[ -d "$dir" ] && find "$dir" -type f ! -name '.gitkeep' -maxdepth 3 2>/dev/null | head -1 | grep -q .
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
# 从 logos-project.yaml 读取 scenarios[].id 列表,空格分隔
|
|
25
|
+
# 若字段不存在或解析失败,返回空字符串
|
|
26
|
+
get_scenario_ids() {
|
|
27
|
+
local yaml_file="logos/logos-project.yaml"
|
|
28
|
+
if [ ! -f "$yaml_file" ]; then
|
|
29
|
+
echo ""
|
|
30
|
+
return
|
|
31
|
+
fi
|
|
32
|
+
if command -v python3 &>/dev/null; then
|
|
33
|
+
python3 - "$yaml_file" <<'PYEOF' 2>/dev/null || echo ""
|
|
34
|
+
import sys, re
|
|
35
|
+
path = sys.argv[1]
|
|
36
|
+
content = open(path).read()
|
|
37
|
+
# 简单解析 scenarios 块中的 id 字段(不依赖 PyYAML)
|
|
38
|
+
in_scenarios = False
|
|
39
|
+
ids = []
|
|
40
|
+
for line in content.splitlines():
|
|
41
|
+
if re.match(r'^scenarios\s*:', line):
|
|
42
|
+
in_scenarios = True
|
|
43
|
+
continue
|
|
44
|
+
if in_scenarios:
|
|
45
|
+
# 遇到新的顶层字段则退出
|
|
46
|
+
if re.match(r'^[a-zA-Z]', line):
|
|
47
|
+
break
|
|
48
|
+
m = re.match(r'\s+-?\s*id\s*:\s*["\']?(\S+?)["\']?\s*$', line)
|
|
49
|
+
if m:
|
|
50
|
+
ids.append(m.group(1))
|
|
51
|
+
print(' '.join(ids))
|
|
52
|
+
PYEOF
|
|
53
|
+
elif command -v node &>/dev/null; then
|
|
54
|
+
node - "$yaml_file" <<'JSEOF' 2>/dev/null || echo ""
|
|
55
|
+
const fs = require('fs');
|
|
56
|
+
const content = fs.readFileSync(process.argv[1], 'utf-8');
|
|
57
|
+
const ids = [];
|
|
58
|
+
let inScenarios = false;
|
|
59
|
+
for (const line of content.split('\n')) {
|
|
60
|
+
if (/^scenarios\s*:/.test(line)) { inScenarios = true; continue; }
|
|
61
|
+
if (inScenarios) {
|
|
62
|
+
if (/^[a-zA-Z]/.test(line)) break;
|
|
63
|
+
const m = line.match(/\s+-?\s*id\s*:\s*["']?(\S+?)["']?\s*$/);
|
|
64
|
+
if (m) ids.push(m[1]);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
console.log(ids.join(' '));
|
|
68
|
+
JSEOF
|
|
69
|
+
else
|
|
70
|
+
echo ""
|
|
71
|
+
fi
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
# 检查某个 phase 下所有已声明场景是否都有对应文件
|
|
75
|
+
# 参数: $1=目录, $2=文件名 glob 模式(不含SXX前缀), $3=扩展名(如 .md 或 .yaml .yml)
|
|
76
|
+
# 返回: 0=全部完成, 1=有缺失; 缺失的 ID 输出到 stdout
|
|
77
|
+
check_scenarios_complete() {
|
|
78
|
+
local dir="$1"
|
|
79
|
+
local ext_pattern="$2" # 例如 "*.md" 或 "*.yaml *.yml"
|
|
80
|
+
local scenario_ids
|
|
81
|
+
scenario_ids=$(get_scenario_ids)
|
|
82
|
+
|
|
83
|
+
if [ -z "$scenario_ids" ]; then
|
|
84
|
+
# 无 scenarios 声明,降级为旧逻辑
|
|
85
|
+
echo "__fallback__"
|
|
86
|
+
return 0
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
local missing=""
|
|
90
|
+
for sid in $scenario_ids; do
|
|
91
|
+
local found=false
|
|
92
|
+
for pat in $ext_pattern; do
|
|
93
|
+
if find "$dir" -maxdepth 1 -name "${sid}-${pat}" 2>/dev/null | grep -q .; then
|
|
94
|
+
found=true
|
|
95
|
+
break
|
|
96
|
+
fi
|
|
97
|
+
done
|
|
98
|
+
if [ "$found" = "false" ]; then
|
|
99
|
+
missing="$missing $sid"
|
|
100
|
+
fi
|
|
101
|
+
done
|
|
102
|
+
|
|
103
|
+
if [ -n "$missing" ]; then
|
|
104
|
+
echo "$missing"
|
|
105
|
+
return 1
|
|
106
|
+
fi
|
|
107
|
+
return 0
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
CONFIG="logos/logos.config.json"
|
|
111
|
+
|
|
112
|
+
if [ ! -f "$CONFIG" ]; then
|
|
113
|
+
if [ "$MODE" = "json" ]; then
|
|
114
|
+
echo '{"systemMessage":"Not an OpenLogos project"}'
|
|
115
|
+
else
|
|
116
|
+
echo "⚠ This is not an OpenLogos project (logos/logos.config.json not found)."
|
|
117
|
+
echo "Run \`openlogos init\` to initialize."
|
|
118
|
+
fi
|
|
119
|
+
exit 0
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
LOCALE="en"
|
|
123
|
+
LIFECYCLE="initial"
|
|
124
|
+
PROJECT_NAME=""
|
|
125
|
+
|
|
126
|
+
if command -v python3 &>/dev/null; then
|
|
127
|
+
LOCALE=$(python3 -c "import json; d=json.load(open('$CONFIG')); print(d.get('locale','en'))" 2>/dev/null || echo "en")
|
|
128
|
+
PROJECT_NAME=$(python3 -c "import json; d=json.load(open('$CONFIG')); print(d.get('name',''))" 2>/dev/null || echo "")
|
|
129
|
+
elif command -v node &>/dev/null; then
|
|
130
|
+
LOCALE=$(node -e "const d=JSON.parse(require('fs').readFileSync('$CONFIG','utf-8')); console.log(d.locale||'en')" 2>/dev/null || echo "en")
|
|
131
|
+
PROJECT_NAME=$(node -e "const d=JSON.parse(require('fs').readFileSync('$CONFIG','utf-8')); console.log(d.name||'')" 2>/dev/null || echo "")
|
|
132
|
+
fi
|
|
133
|
+
|
|
134
|
+
# 从 logos-project.yaml 的 modules[].lifecycle 推导项目级 lifecycle
|
|
135
|
+
# 任意模块标记为 launched 则项目为 launched
|
|
136
|
+
# skip_phases 只读取 lifecycle=initial 的模块,避免多模块时误跳过其他模块的阶段
|
|
137
|
+
YAML_FILE="logos/logos-project.yaml"
|
|
138
|
+
SKIP_API=false
|
|
139
|
+
SKIP_DATABASE=false
|
|
140
|
+
SKIP_SCENARIO=false
|
|
141
|
+
|
|
142
|
+
if [ -f "$YAML_FILE" ]; then
|
|
143
|
+
if grep -q 'lifecycle.*launched' "$YAML_FILE" 2>/dev/null; then
|
|
144
|
+
LIFECYCLE="launched"
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
# 只从 initial 模块读取 skip_phases,用 awk 解析避免 heredoc 语法问题
|
|
148
|
+
_skip_result=""
|
|
149
|
+
if command -v python3 &>/dev/null; then
|
|
150
|
+
_py_script=$(mktemp /tmp/openlogos_skip_XXXXXX.py)
|
|
151
|
+
cat > "$_py_script" << 'PYEOF'
|
|
152
|
+
import sys, re
|
|
153
|
+
path = sys.argv[1]
|
|
154
|
+
content = open(path).read()
|
|
155
|
+
in_modules = False
|
|
156
|
+
current_lifecycle = 'initial'
|
|
157
|
+
current_skip = []
|
|
158
|
+
all_skip = []
|
|
159
|
+
for line in content.splitlines():
|
|
160
|
+
if re.match(r'^modules\s*:', line):
|
|
161
|
+
in_modules = True
|
|
162
|
+
continue
|
|
163
|
+
if in_modules:
|
|
164
|
+
if re.match(r'^[a-zA-Z]', line) and not re.match(r'^\s', line):
|
|
165
|
+
break
|
|
166
|
+
if re.match(r'\s+-\s+id\s*:', line):
|
|
167
|
+
if current_lifecycle == 'initial':
|
|
168
|
+
all_skip.extend(current_skip)
|
|
169
|
+
current_lifecycle = 'initial'
|
|
170
|
+
current_skip = []
|
|
171
|
+
m = re.search(r'lifecycle\s*:\s*(\S+)', line)
|
|
172
|
+
if m:
|
|
173
|
+
current_lifecycle = m.group(1).strip('"\'')
|
|
174
|
+
m = re.search(r'skip_phases\s*:\s*\[([^\]]*)\]', line)
|
|
175
|
+
if m:
|
|
176
|
+
current_skip = [s.strip().strip('"\'') for s in m.group(1).split(',') if s.strip()]
|
|
177
|
+
if current_lifecycle == 'initial':
|
|
178
|
+
all_skip.extend(current_skip)
|
|
179
|
+
print(' '.join(set(all_skip)))
|
|
180
|
+
PYEOF
|
|
181
|
+
_skip_result=$(python3 "$_py_script" "$YAML_FILE" 2>/dev/null || echo "")
|
|
182
|
+
rm -f "$_py_script"
|
|
183
|
+
elif command -v node &>/dev/null; then
|
|
184
|
+
_js_script=$(mktemp /tmp/openlogos_skip_XXXXXX.js)
|
|
185
|
+
cat > "$_js_script" << 'JSEOF'
|
|
186
|
+
const fs = require('fs');
|
|
187
|
+
const content = fs.readFileSync(process.argv[2], 'utf-8');
|
|
188
|
+
let inModules = false, curLifecycle = 'initial', curSkip = [], allSkip = [];
|
|
189
|
+
for (const line of content.split('\n')) {
|
|
190
|
+
if (/^modules\s*:/.test(line)) { inModules = true; continue; }
|
|
191
|
+
if (inModules) {
|
|
192
|
+
if (/^[a-zA-Z]/.test(line) && !/^\s/.test(line)) break;
|
|
193
|
+
if (/\s+-\s+id\s*:/.test(line)) {
|
|
194
|
+
if (curLifecycle === 'initial') allSkip.push(...curSkip);
|
|
195
|
+
curLifecycle = 'initial'; curSkip = [];
|
|
196
|
+
}
|
|
197
|
+
const lm = line.match(/lifecycle\s*:\s*(\S+)/);
|
|
198
|
+
if (lm) curLifecycle = lm[1].replace(/['"]/g, '');
|
|
199
|
+
const sm = line.match(/skip_phases\s*:\s*\[([^\]]*)\]/);
|
|
200
|
+
if (sm) curSkip = sm[1].split(',').map(s => s.trim().replace(/['"]/g, '')).filter(Boolean);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (curLifecycle === 'initial') allSkip.push(...curSkip);
|
|
204
|
+
console.log([...new Set(allSkip)].join(' '));
|
|
205
|
+
JSEOF
|
|
206
|
+
_skip_result=$(node "$_js_script" "$YAML_FILE" 2>/dev/null || echo "")
|
|
207
|
+
rm -f "$_js_script"
|
|
208
|
+
else
|
|
209
|
+
# 降级:全文 grep(多模块时可能误判,但总比不跳过好)
|
|
210
|
+
grep 'skip_phases' "$YAML_FILE" 2>/dev/null | grep -q 'api' && _skip_result="$_skip_result api"
|
|
211
|
+
grep 'skip_phases' "$YAML_FILE" 2>/dev/null | grep -q 'database' && _skip_result="$_skip_result database"
|
|
212
|
+
grep 'skip_phases' "$YAML_FILE" 2>/dev/null | grep -q 'scenario' && _skip_result="$_skip_result scenario"
|
|
213
|
+
fi
|
|
214
|
+
|
|
215
|
+
echo "$_skip_result" | grep -q '\bapi\b' && SKIP_API=true || true
|
|
216
|
+
echo "$_skip_result" | grep -q '\bdatabase\b' && SKIP_DATABASE=true || true
|
|
217
|
+
echo "$_skip_result" | grep -q '\bscenario\b' && SKIP_SCENARIO=true || true
|
|
218
|
+
fi
|
|
219
|
+
|
|
220
|
+
P1="logos/resources/prd/1-product-requirements"
|
|
221
|
+
P2="logos/resources/prd/2-product-design"
|
|
222
|
+
P3_ARCH="logos/resources/prd/3-technical-plan/1-architecture"
|
|
223
|
+
P3_SCEN="logos/resources/prd/3-technical-plan/2-scenario-implementation"
|
|
224
|
+
P_API="logos/resources/api"
|
|
225
|
+
P_DATABASE="logos/resources/database"
|
|
226
|
+
P_TEST="logos/resources/test"
|
|
227
|
+
P_SCENARIO="logos/resources/scenario"
|
|
228
|
+
P_VERIFY="logos/resources/verify"
|
|
229
|
+
|
|
230
|
+
PHASE=""
|
|
231
|
+
SKILL=""
|
|
232
|
+
SKILL_DESC=""
|
|
233
|
+
|
|
234
|
+
# 向后看兜底逻辑:后续阶段已有文件时,自动跳过空的 api/database/scenario 目录
|
|
235
|
+
# 与 CLI 的 lastDoneIdx 逻辑对应,向后兼容无 skip_phases 的旧项目
|
|
236
|
+
if [ "$SKIP_API" = "false" ] && ! has_files "$P_API"; then
|
|
237
|
+
if has_files "$P_TEST" || has_files "$P_SCENARIO" || has_files "$P_VERIFY"; then
|
|
238
|
+
SKIP_API=true
|
|
239
|
+
fi
|
|
240
|
+
fi
|
|
241
|
+
if [ "$SKIP_DATABASE" = "false" ] && ! has_files "$P_DATABASE"; then
|
|
242
|
+
if has_files "$P_TEST" || has_files "$P_SCENARIO" || has_files "$P_VERIFY"; then
|
|
243
|
+
SKIP_DATABASE=true
|
|
244
|
+
fi
|
|
245
|
+
fi
|
|
246
|
+
if [ "$SKIP_SCENARIO" = "false" ] && ! has_files "$P_SCENARIO"; then
|
|
247
|
+
if has_files "$P_VERIFY"; then
|
|
248
|
+
SKIP_SCENARIO=true
|
|
249
|
+
fi
|
|
250
|
+
fi
|
|
251
|
+
|
|
252
|
+
if ! has_files "$P1"; then
|
|
253
|
+
PHASE="Phase 1: Product Requirements"
|
|
254
|
+
SKILL="prd-writer"
|
|
255
|
+
SKILL_DESC="Write product requirements documents"
|
|
256
|
+
elif ! has_files "$P2"; then
|
|
257
|
+
PHASE="Phase 2: Product Design"
|
|
258
|
+
SKILL="product-designer"
|
|
259
|
+
SKILL_DESC="Create product design specifications"
|
|
260
|
+
elif ! has_files "$P3_ARCH"; then
|
|
261
|
+
PHASE="Phase 3 Step 0: Architecture Design"
|
|
262
|
+
SKILL="architecture-designer"
|
|
263
|
+
SKILL_DESC="Design technical architecture"
|
|
264
|
+
elif ! has_files "$P3_SCEN"; then
|
|
265
|
+
PHASE="Phase 3 Step 1: Scenario Modeling"
|
|
266
|
+
SKILL="scenario-architect"
|
|
267
|
+
SKILL_DESC="Model business scenarios as sequence diagrams"
|
|
268
|
+
else
|
|
269
|
+
# Phase 3-1 目录有文件,进一步检查场景完整性
|
|
270
|
+
_scen_missing=$(check_scenarios_complete "$P3_SCEN" "*.md" || true)
|
|
271
|
+
if [ "$_scen_missing" = "__fallback__" ]; then
|
|
272
|
+
: # 无 scenarios 声明,视为完成,继续向下走
|
|
273
|
+
elif [ -n "$_scen_missing" ]; then
|
|
274
|
+
PHASE="Phase 3 Step 1: Scenario Modeling (incomplete: missing${_scen_missing})"
|
|
275
|
+
SKILL="scenario-architect"
|
|
276
|
+
SKILL_DESC="Complete remaining scenario sequence diagrams"
|
|
277
|
+
fi
|
|
278
|
+
fi
|
|
279
|
+
|
|
280
|
+
if [ -z "$PHASE" ]; then
|
|
281
|
+
if [ "$SKIP_API" = "true" ]; then
|
|
282
|
+
: # skip api phase
|
|
283
|
+
elif ! has_files "$P_API"; then
|
|
284
|
+
PHASE="Phase 3 Step 2: API & Database Design"
|
|
285
|
+
SKILL="api-designer"
|
|
286
|
+
SKILL_DESC="Design OpenAPI specifications (also run db-designer)"
|
|
287
|
+
else
|
|
288
|
+
# Phase 3-2 目录有文件,检查场景完整性
|
|
289
|
+
_api_missing=$(check_scenarios_complete "$P_API" "*.yaml *.yml" || true)
|
|
290
|
+
if [ "$_api_missing" = "__fallback__" ]; then
|
|
291
|
+
: # 降级,继续
|
|
292
|
+
elif [ -n "$_api_missing" ]; then
|
|
293
|
+
PHASE="Phase 3 Step 2: API & Database Design (incomplete: missing${_api_missing})"
|
|
294
|
+
SKILL="api-designer"
|
|
295
|
+
SKILL_DESC="Complete remaining API designs"
|
|
296
|
+
fi
|
|
297
|
+
fi
|
|
298
|
+
fi
|
|
299
|
+
|
|
300
|
+
if [ -z "$PHASE" ]; then
|
|
301
|
+
if [ "$SKIP_DATABASE" = "true" ]; then
|
|
302
|
+
: # skip database phase
|
|
303
|
+
elif ! has_files "$P_DATABASE"; then
|
|
304
|
+
PHASE="Phase 3 Step 2: Database Design"
|
|
305
|
+
SKILL="db-designer"
|
|
306
|
+
SKILL_DESC="Design database schema (DDL)"
|
|
307
|
+
fi
|
|
308
|
+
fi
|
|
309
|
+
|
|
310
|
+
if [ -z "$PHASE" ]; then
|
|
311
|
+
if ! has_files "$P_TEST"; then
|
|
312
|
+
PHASE="Phase 3 Step 3a: Test Cases"
|
|
313
|
+
SKILL="test-writer"
|
|
314
|
+
SKILL_DESC="Write test case documents"
|
|
315
|
+
else
|
|
316
|
+
# Phase 3-3a 目录有文件,检查场景完整性
|
|
317
|
+
_test_missing=$(check_scenarios_complete "$P_TEST" "*.md" || true)
|
|
318
|
+
if [ "$_test_missing" = "__fallback__" ]; then
|
|
319
|
+
: # 降级,继续
|
|
320
|
+
elif [ -n "$_test_missing" ]; then
|
|
321
|
+
PHASE="Phase 3 Step 3a: Test Cases (incomplete: missing${_test_missing})"
|
|
322
|
+
SKILL="test-writer"
|
|
323
|
+
SKILL_DESC="Complete remaining test case documents"
|
|
324
|
+
fi
|
|
325
|
+
fi
|
|
326
|
+
fi
|
|
327
|
+
|
|
328
|
+
if [ -z "$PHASE" ]; then
|
|
329
|
+
if [ "$SKIP_SCENARIO" = "true" ]; then
|
|
330
|
+
: # skip scenario/orchestration phase
|
|
331
|
+
elif ! has_files "$P_SCENARIO"; then
|
|
332
|
+
PHASE="Phase 3 Step 3b: Orchestration Tests"
|
|
333
|
+
SKILL="test-orchestrator"
|
|
334
|
+
SKILL_DESC="Design API orchestration test scenarios"
|
|
335
|
+
fi
|
|
336
|
+
fi
|
|
337
|
+
|
|
338
|
+
if [ -z "$PHASE" ]; then
|
|
339
|
+
if ! has_files "$P_VERIFY"; then
|
|
340
|
+
PHASE="Phase 3 Step 4-5: Code Generation & Verification"
|
|
341
|
+
SKILL="code-reviewer"
|
|
342
|
+
SKILL_DESC="Generate code and run verification"
|
|
343
|
+
else
|
|
344
|
+
PHASE="All phases complete"
|
|
345
|
+
SKILL=""
|
|
346
|
+
fi
|
|
347
|
+
fi
|
|
348
|
+
|
|
349
|
+
# Build language policy text
|
|
350
|
+
if [ "$LOCALE" = "zh" ]; then
|
|
351
|
+
LANG_POLICY="Language Policy: ALL output MUST be in Chinese (中文)."
|
|
352
|
+
else
|
|
353
|
+
LANG_POLICY="Language Policy: ALL output MUST be in English."
|
|
354
|
+
fi
|
|
355
|
+
|
|
356
|
+
# Detect guard file for active lifecycle
|
|
357
|
+
GUARD_FILE="logos/.openlogos-guard"
|
|
358
|
+
GUARD_STATUS=""
|
|
359
|
+
ACTIVE_CHANGE=""
|
|
360
|
+
|
|
361
|
+
if [ "$LIFECYCLE" = "launched" ] && [ -f "$GUARD_FILE" ]; then
|
|
362
|
+
if command -v python3 &>/dev/null; then
|
|
363
|
+
ACTIVE_CHANGE=$(python3 -c "import json; d=json.load(open('$GUARD_FILE')); print(d.get('activeChange',''))" 2>/dev/null || echo "")
|
|
364
|
+
elif command -v node &>/dev/null; then
|
|
365
|
+
ACTIVE_CHANGE=$(node -e "const d=JSON.parse(require('fs').readFileSync('$GUARD_FILE','utf-8')); console.log(d.activeChange||'')" 2>/dev/null || echo "")
|
|
366
|
+
fi
|
|
367
|
+
fi
|
|
368
|
+
|
|
369
|
+
# Build change management text
|
|
370
|
+
if [ "$LIFECYCLE" = "launched" ]; then
|
|
371
|
+
if [ -n "$ACTIVE_CHANGE" ]; then
|
|
372
|
+
GUARD_STATUS="🔓 Active change: $ACTIVE_CHANGE — modify files within the scope of this proposal only."
|
|
373
|
+
CHANGE_MGMT="Change Management: ACTIVE — guard file detected. Active change proposal: '$ACTIVE_CHANGE'. Only modify files within the scope of logos/changes/$ACTIVE_CHANGE/proposal.md. Full workflow: (1) produce deltas, (2) user authorizes openlogos merge, (3) AI auto-commits spec, (4) implement code per updated spec, (5) AI auto-commits code, (6) user runs openlogos verify — must PASS, (7) user authorizes openlogos archive, (8) AI auto-commits archive, (9) user confirms git push. openlogos merge / verify / archive and git push are human confirmation points: AI must not execute them without explicit user authorization."
|
|
374
|
+
else
|
|
375
|
+
GUARD_STATUS="⛔ NO active change proposal. You MUST run openlogos change <slug> before modifying any code."
|
|
376
|
+
CHANGE_MGMT="Change Management: ACTIVE — ⛔ NO guard file found. Before modifying ANY source code, you MUST first run openlogos change <slug> to create a change proposal. Direct code changes without a proposal are FORBIDDEN."
|
|
377
|
+
fi
|
|
378
|
+
else
|
|
379
|
+
CHANGE_MGMT="Change Management: Initial development — follow Phase progression, no change proposals needed."
|
|
380
|
+
if [ "$PHASE" = "All phases complete" ]; then
|
|
381
|
+
CHANGE_MGMT="$CHANGE_MGMT Run openlogos launch to activate change management."
|
|
382
|
+
fi
|
|
383
|
+
fi
|
|
384
|
+
|
|
385
|
+
# Build status line for systemMessage (user-visible, keep short)
|
|
386
|
+
if [ -n "$GUARD_STATUS" ]; then
|
|
387
|
+
STATUS_LINE="📊 OpenLogos: $PHASE | $GUARD_STATUS"
|
|
388
|
+
elif [ -n "$SKILL" ]; then
|
|
389
|
+
STATUS_LINE="📊 OpenLogos: $PHASE → use $SKILL skill"
|
|
390
|
+
else
|
|
391
|
+
STATUS_LINE="📊 OpenLogos: $PHASE"
|
|
392
|
+
fi
|
|
393
|
+
|
|
394
|
+
# Build full context for additionalContext (Claude-visible)
|
|
395
|
+
CONTEXT="=== OpenLogos Project Context ===
|
|
396
|
+
Project: $PROJECT_NAME
|
|
397
|
+
Locale: $LOCALE
|
|
398
|
+
Lifecycle: $LIFECYCLE
|
|
399
|
+
Current Phase: $PHASE"
|
|
400
|
+
|
|
401
|
+
if [ -n "$SKILL" ]; then
|
|
402
|
+
CONTEXT="$CONTEXT
|
|
403
|
+
Suggested Skill: $SKILL ($SKILL_DESC)"
|
|
404
|
+
fi
|
|
405
|
+
|
|
406
|
+
CONTEXT="$CONTEXT
|
|
407
|
+
$LANG_POLICY
|
|
408
|
+
$CHANGE_MGMT
|
|
409
|
+
=== End OpenLogos Context ==="
|
|
410
|
+
|
|
411
|
+
if [ "$MODE" = "json" ]; then
|
|
412
|
+
# Escape special characters for JSON
|
|
413
|
+
CONTEXT_ESCAPED=$(printf '%s' "$CONTEXT" | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))" 2>/dev/null || printf '%s' "$CONTEXT" | node -e "let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>console.log(JSON.stringify(d)))" 2>/dev/null)
|
|
414
|
+
|
|
415
|
+
cat <<ENDJSON
|
|
416
|
+
{
|
|
417
|
+
"systemMessage": "$STATUS_LINE",
|
|
418
|
+
"hookSpecificOutput": {
|
|
419
|
+
"hookEventName": "SessionStart",
|
|
420
|
+
"additionalContext": $CONTEXT_ESCAPED
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
ENDJSON
|
|
424
|
+
else
|
|
425
|
+
echo ""
|
|
426
|
+
echo "$CONTEXT"
|
|
427
|
+
echo ""
|
|
428
|
+
fi
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Archive a completed change proposal after implementation is done
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
This slash command is treated as explicit human authorization to run `openlogos archive $ARGUMENTS`.
|
|
6
|
+
|
|
7
|
+
Archive the completed change proposal: "$ARGUMENTS"
|
|
8
|
+
|
|
9
|
+
1. If `$ARGUMENTS` is empty, ask the user to provide the change slug (e.g., `/openlogos:archive my-change`).
|
|
10
|
+
2. Before running, inform the user:
|
|
11
|
+
- **Prerequisite**: `openlogos verify` must have passed (PASS) before archiving
|
|
12
|
+
- Archiving will move `logos/changes/$ARGUMENTS/` to `logos/changes/archive/`
|
|
13
|
+
- If the active guard points to this proposal, it will be removed
|
|
14
|
+
- This action is irreversible
|
|
15
|
+
3. Run `openlogos archive $ARGUMENTS` in the project root directory.
|
|
16
|
+
4. If the `openlogos` CLI is not found, tell the user to install it:
|
|
17
|
+
```
|
|
18
|
+
npm install -g @miniidealab/openlogos
|
|
19
|
+
```
|
|
20
|
+
5. After archiving, inform the user that the change proposal has been moved to `logos/changes/archive/` and is now complete.
|
|
21
|
+
|
|
22
|
+
Note: `openlogos archive` is a human confirmation point. AI must not execute it without explicit user authorization. This slash command itself constitutes that authorization.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Create an OpenLogos change proposal for tracking modifications to the project
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Create a new OpenLogos change proposal with the slug provided as argument: "$ARGUMENTS"
|
|
6
|
+
|
|
7
|
+
1. If `$ARGUMENTS` is empty, ask the user to provide a slug (short kebab-case name describing the change).
|
|
8
|
+
2. Run `openlogos change $ARGUMENTS` in the project root directory.
|
|
9
|
+
3. If `openlogos` CLI is not found, create the change proposal manually:
|
|
10
|
+
- Create directory `logos/changes/$ARGUMENTS/`
|
|
11
|
+
- Create `logos/changes/$ARGUMENTS/proposal.md` with the standard template
|
|
12
|
+
- Create `logos/changes/$ARGUMENTS/tasks.md` with the standard template
|
|
13
|
+
- Create `logos/changes/$ARGUMENTS/deltas/` directory
|
|
14
|
+
4. Tell the user the proposal was created and suggest next steps:
|
|
15
|
+
- Fill in `proposal.md` with the change reason, scope, and summary
|
|
16
|
+
- Fill in `tasks.md` with the implementation tasks
|
|
17
|
+
- After approval, implement the changes
|
|
18
|
+
- When ready to merge, explicitly request `/openlogos:merge $ARGUMENTS` to generate merge instructions
|
|
19
|
+
- After reviewing the merge, explicitly request `/openlogos:archive $ARGUMENTS` to archive the proposal
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Generate an AI-ready prompt to rebuild logos-project.yaml resource_index with file-content-based descriptions
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Generate a structured prompt that lets AI read actual file contents and write high-quality descriptions into `logos-project.yaml`.
|
|
6
|
+
|
|
7
|
+
1. Run `openlogos index` in the project root directory.
|
|
8
|
+
2. If the `openlogos` CLI is not found, tell the user to install it:
|
|
9
|
+
```
|
|
10
|
+
npm install -g @miniidealab/openlogos
|
|
11
|
+
```
|
|
12
|
+
3. After the command completes, `logos/index-prompt.md` will be generated.
|
|
13
|
+
4. Tell the user: "Read `logos/index-prompt.md` and execute the instructions" — the AI will read each file's content and directly update `logos/logos-project.yaml`'s `resource_index` field.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Initialize OpenLogos project — MUST ask language preference first, then run init"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
**STOP — do NOT run any command yet.**
|
|
6
|
+
|
|
7
|
+
You MUST ask the user this question first and WAIT for their answer:
|
|
8
|
+
|
|
9
|
+
> 请选择语言 / Choose language:
|
|
10
|
+
> 1. English
|
|
11
|
+
> 2. 中文
|
|
12
|
+
|
|
13
|
+
After the user replies, determine the locale value:
|
|
14
|
+
- User says 1 or "English" → locale is `en`
|
|
15
|
+
- User says 2 or "中文" → locale is `zh`
|
|
16
|
+
|
|
17
|
+
Then run this exact command:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
openlogos init --locale <LOCALE> --ai-tool claude-code $ARGUMENTS
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Replace `<LOCALE>` with `en` or `zh` based on the user's answer. If `$ARGUMENTS` is provided, append it as the project name.
|
|
24
|
+
|
|
25
|
+
If `openlogos` command is not found, tell the user:
|
|
26
|
+
```
|
|
27
|
+
npm install -g @miniidealab/openlogos
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
After init completes, suggest running `/openlogos:next` for guidance.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Transition the OpenLogos project from initial development to active lifecycle, enabling change management
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Transition the project lifecycle from "initial" to "active":
|
|
6
|
+
|
|
7
|
+
1. Run `openlogos launch` in the project root directory.
|
|
8
|
+
2. If `openlogos` CLI is not found, perform the transition manually:
|
|
9
|
+
- Read `logos/logos.config.json`
|
|
10
|
+
- Change the `lifecycle` field from `"initial"` to `"active"`
|
|
11
|
+
- Write the updated config back
|
|
12
|
+
- Inform the user that change management is now active
|
|
13
|
+
3. Explain to the user what this means:
|
|
14
|
+
- From now on, any modification to source code or methodology documents requires a change proposal first
|
|
15
|
+
- Use `/openlogos:change <slug>` to create proposals before making changes
|
|
16
|
+
- Exception: pure typo fixes and non-methodology files (README, .gitignore, etc.)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Generate MERGE_PROMPT.md for an approved change proposal to guide AI-assisted delta merging
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
This slash command is treated as explicit human authorization to run `openlogos merge $ARGUMENTS`.
|
|
6
|
+
|
|
7
|
+
Generate the merge prompt for a change proposal: "$ARGUMENTS"
|
|
8
|
+
|
|
9
|
+
1. If `$ARGUMENTS` is empty, ask the user to provide the change slug (e.g., `/openlogos:merge my-change`).
|
|
10
|
+
2. Run `openlogos merge $ARGUMENTS` in the project root directory.
|
|
11
|
+
3. If the `openlogos` CLI is not found, tell the user to install it:
|
|
12
|
+
```
|
|
13
|
+
npm install -g @miniidealab/openlogos
|
|
14
|
+
```
|
|
15
|
+
4. After the merge prompt is generated, inform the user:
|
|
16
|
+
- A `MERGE_PROMPT.md` file has been created in `logos/changes/$ARGUMENTS/`
|
|
17
|
+
- They should read and follow the merge prompt to apply the delta changes
|
|
18
|
+
- After merging: commit spec documents, implement code per the updated specs, run `openlogos verify`, and only after PASS explicitly request `/openlogos:archive $ARGUMENTS`
|
|
19
|
+
|
|
20
|
+
Note: `openlogos archive` is a separate human confirmation point. Do not automatically trigger it after merge — wait for the user to explicitly request archiving.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Detect current OpenLogos phase and provide actionable next-step guidance with a ready-to-use prompt
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Help the user determine their next step in the OpenLogos methodology:
|
|
6
|
+
|
|
7
|
+
1. Run `${CLAUDE_PLUGIN_ROOT}/bin/openlogos-phase --plain` to detect the current project phase.
|
|
8
|
+
2. Based on the detected phase and suggested skill, provide:
|
|
9
|
+
- A clear explanation of what this phase involves
|
|
10
|
+
- The specific skill that should be used (it will be auto-activated)
|
|
11
|
+
- A ready-to-use prompt the user can say to start the work, for example:
|
|
12
|
+
- Phase 1: "Help me write the product requirements document for this project"
|
|
13
|
+
- Phase 2: "Help me create the product design based on the requirements"
|
|
14
|
+
- Phase 3 Step 0: "Help me design the technical architecture"
|
|
15
|
+
- Phase 3 Step 1: "Help me model the business scenarios as sequence diagrams"
|
|
16
|
+
- etc.
|
|
17
|
+
3. If all phases are complete and lifecycle is "initial", suggest running `/openlogos:launch`.
|
|
18
|
+
4. If lifecycle is "active", remind the user about change management workflow.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Show OpenLogos project phase progress and next step suggestions
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Check the current OpenLogos project status by running the following steps:
|
|
6
|
+
|
|
7
|
+
1. Run `openlogos status` in the project root directory.
|
|
8
|
+
2. If the `openlogos` command is not found, run `${CLAUDE_PLUGIN_ROOT}/bin/openlogos-phase --plain` instead.
|
|
9
|
+
3. Display the output to the user clearly.
|
|
10
|
+
4. Based on the current phase, suggest what the user should do next and which skill to use.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Regenerate AI instruction files (AGENTS.md, CLAUDE.md) and re-deploy skills from current config
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Sync the OpenLogos project configuration by regenerating AI instruction files and re-deploying skills.
|
|
6
|
+
|
|
7
|
+
1. Run `openlogos sync` in the project root directory.
|
|
8
|
+
2. If the `openlogos` CLI is not found, tell the user to install it:
|
|
9
|
+
```
|
|
10
|
+
npm install -g @miniidealab/openlogos
|
|
11
|
+
```
|
|
12
|
+
3. After sync completes, inform the user that AGENTS.md, CLAUDE.md, and skills have been refreshed based on the current `logos/logos.config.json` settings.
|