prizmkit 1.0.66 → 1.0.68
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/bundled/VERSION.json +3 -3
- package/bundled/adapters/claude/settings-adapter.js +29 -0
- package/bundled/dev-pipeline/run-bugfix.sh +2 -2
- package/bundled/dev-pipeline/run.sh +88 -4
- package/bundled/dev-pipeline/scripts/init-pipeline.py +9 -0
- package/bundled/dev-pipeline/templates/bootstrap-tier1.md +7 -6
- package/bundled/dev-pipeline/templates/bootstrap-tier2.md +6 -2
- package/bundled/dev-pipeline/templates/bootstrap-tier3.md +6 -2
- package/bundled/skills/_metadata.json +1 -1
- package/bundled/skills/app-planner/SKILL.md +7 -1
- package/bundled/skills/dev-pipeline-launcher/SKILL.md +26 -12
- package/package.json +1 -1
- package/src/upgrade.js +14 -2
package/bundled/VERSION.json
CHANGED
|
@@ -30,9 +30,38 @@ export async function generateSettings(targetRoot, options = {}) {
|
|
|
30
30
|
if (!existing.permissions.allow) existing.permissions.allow = [];
|
|
31
31
|
|
|
32
32
|
const prizmkitPermissions = [
|
|
33
|
+
// Core tools
|
|
33
34
|
'Bash(python3 *)',
|
|
34
35
|
'Bash(git *)',
|
|
35
36
|
'Bash(jq *)',
|
|
37
|
+
// Common dev commands
|
|
38
|
+
'Bash(node *)',
|
|
39
|
+
'Bash(npm *)',
|
|
40
|
+
'Bash(npx *)',
|
|
41
|
+
// File operations
|
|
42
|
+
'Bash(cat *)',
|
|
43
|
+
'Bash(ls *)',
|
|
44
|
+
'Bash(pwd)',
|
|
45
|
+
'Bash(mkdir *)',
|
|
46
|
+
'Bash(cp *)',
|
|
47
|
+
'Bash(mv *)',
|
|
48
|
+
'Bash(rm *)',
|
|
49
|
+
'Bash(chmod *)',
|
|
50
|
+
'Bash(touch *)',
|
|
51
|
+
// Search & text tools
|
|
52
|
+
'Bash(find *)',
|
|
53
|
+
'Bash(grep *)',
|
|
54
|
+
'Bash(sed *)',
|
|
55
|
+
'Bash(awk *)',
|
|
56
|
+
'Bash(head *)',
|
|
57
|
+
'Bash(tail *)',
|
|
58
|
+
'Bash(wc *)',
|
|
59
|
+
'Bash(sort *)',
|
|
60
|
+
'Bash(echo *)',
|
|
61
|
+
// Script execution
|
|
62
|
+
'Bash(./*)',
|
|
63
|
+
'Bash(bash *)',
|
|
64
|
+
'Bash(sh *)',
|
|
36
65
|
];
|
|
37
66
|
|
|
38
67
|
if (options.pipeline) {
|
|
@@ -605,12 +605,12 @@ main() {
|
|
|
605
605
|
# Track current session (atomic write via temp file)
|
|
606
606
|
python3 -c "
|
|
607
607
|
import json, sys, os
|
|
608
|
-
from datetime import datetime
|
|
608
|
+
from datetime import datetime, timezone
|
|
609
609
|
bug_id, session_id, state_dir = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
610
610
|
data = {
|
|
611
611
|
'bug_id': bug_id,
|
|
612
612
|
'session_id': session_id,
|
|
613
|
-
'started_at': datetime.now(
|
|
613
|
+
'started_at': datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')
|
|
614
614
|
}
|
|
615
615
|
target = os.path.join(state_dir, 'current-session.json')
|
|
616
616
|
tmp = target + '.tmp'
|
|
@@ -240,15 +240,89 @@ with open(p, 'w', encoding='utf-8') as f:
|
|
|
240
240
|
|
|
241
241
|
log_info "Session result: $session_status"
|
|
242
242
|
|
|
243
|
+
# Write lightweight session summary for post-session inspection
|
|
244
|
+
local feature_slug
|
|
245
|
+
feature_slug=$(python3 -c "
|
|
246
|
+
import json, re, sys
|
|
247
|
+
flist, fid = sys.argv[1], sys.argv[2]
|
|
248
|
+
with open(flist) as f:
|
|
249
|
+
data = json.load(f)
|
|
250
|
+
for feat in data.get('features', []):
|
|
251
|
+
if feat.get('id') == fid:
|
|
252
|
+
fnum = feat['id'].replace('F-', '').replace('f-', '').zfill(3)
|
|
253
|
+
title = feat.get('title', '').lower()
|
|
254
|
+
title = re.sub(r'[^a-z0-9\s-]', '', title)
|
|
255
|
+
title = re.sub(r'[\s]+', '-', title.strip())
|
|
256
|
+
title = re.sub(r'-+', '-', title).strip('-')
|
|
257
|
+
print(f'{fnum}-{title}')
|
|
258
|
+
sys.exit(0)
|
|
259
|
+
sys.exit(1)
|
|
260
|
+
" "$feature_list" "$feature_id" 2>/dev/null) || {
|
|
261
|
+
log_warn "Could not resolve feature slug for $feature_id — session summary and artifact validation will be skipped"
|
|
262
|
+
feature_slug=""
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if [[ -n "$feature_slug" ]]; then
|
|
266
|
+
local project_root_for_summary
|
|
267
|
+
project_root_for_summary="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
268
|
+
local summary_path="$project_root_for_summary/.prizmkit/specs/${feature_slug}/session-summary.json"
|
|
269
|
+
mkdir -p "$(dirname "$summary_path")"
|
|
270
|
+
local session_start_time
|
|
271
|
+
session_start_time=$(python3 -c "
|
|
272
|
+
import json, sys, os
|
|
273
|
+
p = os.path.join(sys.argv[1], 'current-session.json')
|
|
274
|
+
if os.path.isfile(p):
|
|
275
|
+
with open(p) as f: print(json.load(f).get('started_at', ''))
|
|
276
|
+
else: print('')
|
|
277
|
+
" "$STATE_DIR" 2>/dev/null) || session_start_time=""
|
|
278
|
+
local exec_tier
|
|
279
|
+
exec_tier=$(python3 -c "
|
|
280
|
+
import json, sys, os
|
|
281
|
+
p = sys.argv[1]
|
|
282
|
+
if os.path.isfile(p):
|
|
283
|
+
with open(p) as f: print(json.load(f).get('exec_tier', ''))
|
|
284
|
+
else: print('')
|
|
285
|
+
" "$session_dir/session-status.json" 2>/dev/null) || exec_tier=""
|
|
286
|
+
cat > "$summary_path" <<SUMMARY
|
|
287
|
+
{
|
|
288
|
+
"feature_id": "$feature_id",
|
|
289
|
+
"session_id": "$session_id",
|
|
290
|
+
"status": "$session_status",
|
|
291
|
+
"started_at": "$session_start_time",
|
|
292
|
+
"completed_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
|
293
|
+
"tier": "$exec_tier"
|
|
294
|
+
}
|
|
295
|
+
SUMMARY
|
|
296
|
+
fi
|
|
297
|
+
|
|
298
|
+
# Validate key artifacts exist after successful session
|
|
299
|
+
if [[ "$session_status" == "success" && -n "$feature_slug" ]]; then
|
|
300
|
+
local project_root_for_artifacts
|
|
301
|
+
project_root_for_artifacts="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
302
|
+
local context_snapshot="$project_root_for_artifacts/.prizmkit/specs/${feature_slug}/context-snapshot.md"
|
|
303
|
+
local plan_file="$project_root_for_artifacts/.prizmkit/specs/${feature_slug}/plan.md"
|
|
304
|
+
|
|
305
|
+
if [[ ! -f "$context_snapshot" ]]; then
|
|
306
|
+
log_warn "ARTIFACT_MISSING: context-snapshot.md not found at $context_snapshot"
|
|
307
|
+
fi
|
|
308
|
+
if [[ ! -f "$plan_file" ]]; then
|
|
309
|
+
log_warn "ARTIFACT_MISSING: plan.md not found at $plan_file"
|
|
310
|
+
fi
|
|
311
|
+
fi
|
|
312
|
+
|
|
243
313
|
# Update feature status
|
|
244
|
-
|
|
314
|
+
local update_output
|
|
315
|
+
update_output=$(python3 "$SCRIPTS_DIR/update-feature-status.py" \
|
|
245
316
|
--feature-list "$feature_list" \
|
|
246
317
|
--state-dir "$STATE_DIR" \
|
|
247
318
|
--feature-id "$feature_id" \
|
|
248
319
|
--session-status "$session_status" \
|
|
249
320
|
--session-id "$session_id" \
|
|
250
321
|
--max-retries "$max_retries" \
|
|
251
|
-
--action update
|
|
322
|
+
--action update 2>&1) || {
|
|
323
|
+
log_error "Failed to update feature status: $update_output"
|
|
324
|
+
log_error "feature-list.json may be out of sync. Manual intervention needed."
|
|
325
|
+
}
|
|
252
326
|
|
|
253
327
|
# Return status via global variable (avoids $() swallowing stdout)
|
|
254
328
|
_SPAWN_RESULT="$session_status"
|
|
@@ -709,6 +783,16 @@ main() {
|
|
|
709
783
|
exit 1
|
|
710
784
|
fi
|
|
711
785
|
|
|
786
|
+
# Validate feature-list.json is at project root
|
|
787
|
+
local fl_dir
|
|
788
|
+
fl_dir="$(cd "$(dirname "$feature_list")" && pwd)"
|
|
789
|
+
local project_root
|
|
790
|
+
project_root="$(pwd)"
|
|
791
|
+
if [[ "$fl_dir" != "$project_root" ]]; then
|
|
792
|
+
log_warn "feature-list.json is not at project root ($project_root), found at $fl_dir"
|
|
793
|
+
log_warn "Pipeline expects feature-list.json at project root. Proceeding but results may be unstable."
|
|
794
|
+
fi
|
|
795
|
+
|
|
712
796
|
check_dependencies
|
|
713
797
|
run_log_cleanup
|
|
714
798
|
|
|
@@ -883,12 +967,12 @@ for f in data.get('stuck_features', []):
|
|
|
883
967
|
# Update current session tracking (atomic write via temp file)
|
|
884
968
|
python3 -c "
|
|
885
969
|
import json, sys, os
|
|
886
|
-
from datetime import datetime
|
|
970
|
+
from datetime import datetime, timezone
|
|
887
971
|
feature_id, session_id, state_dir = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
888
972
|
data = {
|
|
889
973
|
'feature_id': feature_id,
|
|
890
974
|
'session_id': session_id,
|
|
891
|
-
'started_at': datetime.now(
|
|
975
|
+
'started_at': datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')
|
|
892
976
|
}
|
|
893
977
|
target = os.path.join(state_dir, 'current-session.json')
|
|
894
978
|
tmp = target + '.tmp'
|
|
@@ -300,6 +300,15 @@ def main():
|
|
|
300
300
|
print(json.dumps(output, indent=2, ensure_ascii=False))
|
|
301
301
|
sys.exit(1)
|
|
302
302
|
|
|
303
|
+
# Warn if feature-list.json is not at project root
|
|
304
|
+
feature_list_dir = os.path.dirname(os.path.abspath(args.feature_list))
|
|
305
|
+
indicators = ['.git', 'package.json', '.prizmkit']
|
|
306
|
+
is_at_root = any(os.path.exists(os.path.join(feature_list_dir, i)) for i in indicators)
|
|
307
|
+
if not is_at_root:
|
|
308
|
+
sys.stderr.write(
|
|
309
|
+
"Warning: feature-list.json may not be at project root: {}\n".format(feature_list_dir)
|
|
310
|
+
)
|
|
311
|
+
|
|
303
312
|
# Validate schema
|
|
304
313
|
schema_errors = validate_schema(data)
|
|
305
314
|
if schema_errors:
|
|
@@ -99,14 +99,14 @@ Files changed/created: [list]
|
|
|
99
99
|
Key decisions: [list]
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
-
### Phase 4:
|
|
102
|
+
### Phase 4: Code Review (mandatory)
|
|
103
103
|
|
|
104
104
|
1. Re-read acceptance criteria from Section 1 of context-snapshot.md
|
|
105
|
-
2. Run
|
|
106
|
-
3.
|
|
107
|
-
4.
|
|
105
|
+
2. Run `/prizmkit-code-review` — verify all acceptance criteria, check code quality and correctness
|
|
106
|
+
3. Run the full test suite
|
|
107
|
+
4. If review uncovers issues, fix them (max 2 fix rounds)
|
|
108
108
|
|
|
109
|
-
**CP-2**: All acceptance criteria met, tests pass.
|
|
109
|
+
**CP-2**: All acceptance criteria met, tests pass, code review passed.
|
|
110
110
|
|
|
111
111
|
### Phase 4.5: Memory Maintenance (mandatory before commit)
|
|
112
112
|
|
|
@@ -183,7 +183,8 @@ Re-check `git status --short` and ensure it is empty before exiting.
|
|
|
183
183
|
|
|
184
184
|
## Reminders
|
|
185
185
|
|
|
186
|
-
- Tier 1: you
|
|
186
|
+
- Tier 1: you handle everything directly — invoke skills yourself (no subagents needed for simple tasks)
|
|
187
|
+
- MANDATORY skills: `/prizmkit-code-review`, `/prizmkit-retrospective`, `/prizmkit-committer` — never skip these
|
|
187
188
|
- Build context-snapshot.md FIRST; use it throughout instead of re-reading files
|
|
188
189
|
- ALWAYS write session-status.json before exiting
|
|
189
190
|
- `/prizmkit-committer` is mandatory — do NOT skip the commit phase, and do NOT replace it with manual git commit commands
|
|
@@ -101,7 +101,9 @@ Spawn Dev subagent (Agent tool, subagent_type="prizm-dev-team-dev", run_in_backg
|
|
|
101
101
|
Prompt:
|
|
102
102
|
> "Read {{DEV_SUBAGENT_PATH}}. Implement feature {{FEATURE_ID}} (slug: {{FEATURE_SLUG}}).
|
|
103
103
|
>
|
|
104
|
-
>
|
|
104
|
+
> **IMPORTANT**: Read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` FIRST.
|
|
105
|
+
> This file contains ALL source code and context. Do NOT re-read individual source files.
|
|
106
|
+
> 1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` — all project context, source files, and tests are embedded there.
|
|
105
107
|
> 2. Read `.prizmkit/specs/{{FEATURE_SLUG}}/plan.md` (including Tasks section).
|
|
106
108
|
> 3. Implement task-by-task using TDD. Mark each task `[x]` in plan.md Tasks section immediately after completion.
|
|
107
109
|
> 4. After ALL tasks complete, append an 'Implementation Log' section to `context-snapshot.md`:
|
|
@@ -119,7 +121,9 @@ Spawn Reviewer subagent (Agent tool, subagent_type="prizm-dev-team-reviewer", ru
|
|
|
119
121
|
Prompt:
|
|
120
122
|
> "Read {{REVIEWER_SUBAGENT_PATH}}. Review feature {{FEATURE_ID}} (slug: {{FEATURE_SLUG}}).
|
|
121
123
|
>
|
|
122
|
-
>
|
|
124
|
+
> **IMPORTANT**: Read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` FIRST.
|
|
125
|
+
> This file contains ALL source code and context. Do NOT re-read individual source files.
|
|
126
|
+
> 1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md`:
|
|
123
127
|
> - Section 1: acceptance criteria to verify against
|
|
124
128
|
> - Section 4: original source files (before changes)
|
|
125
129
|
> - 'Implementation Log': what Dev changed
|
|
@@ -222,7 +222,9 @@ Append the following to the Dev agent prompt:
|
|
|
222
222
|
|
|
223
223
|
Prompt:
|
|
224
224
|
> "Read {{DEV_SUBAGENT_PATH}}. Implement feature {{FEATURE_ID}} (slug: {{FEATURE_SLUG}}) using TDD.
|
|
225
|
-
>
|
|
225
|
+
> **IMPORTANT**: Read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` FIRST.
|
|
226
|
+
> This file contains ALL source code and context. Do NOT re-read individual source files.
|
|
227
|
+
> 1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` — all source files and context are there.
|
|
226
228
|
> 2. Read `plan.md` (including Tasks section) from `.prizmkit/specs/{{FEATURE_SLUG}}/`.
|
|
227
229
|
> 3. Implement task-by-task. Mark each `[x]` in plan.md Tasks section **immediately** after completion (do NOT batch).
|
|
228
230
|
> 4. Use `TEST_CMD=<TEST_CMD>` to run tests — do NOT explore alternative test commands.
|
|
@@ -262,7 +264,9 @@ Append the following to the Reviewer agent prompt:
|
|
|
262
264
|
|
|
263
265
|
Prompt:
|
|
264
266
|
> "Read {{REVIEWER_SUBAGENT_PATH}}. For feature {{FEATURE_ID}} (slug: {{FEATURE_SLUG}}):
|
|
265
|
-
>
|
|
267
|
+
> **IMPORTANT**: Read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` FIRST.
|
|
268
|
+
> This file contains ALL source code and context. Do NOT re-read individual source files.
|
|
269
|
+
> 1. Read `.prizmkit/specs/{{FEATURE_SLUG}}/context-snapshot.md` — Section 4 has original source files, 'Implementation Log' section lists exactly what Dev changed. Do NOT re-read source files that are NOT mentioned in the Implementation Log.
|
|
266
270
|
> 2. Run prizmkit-code-review: spec compliance (against spec.md), code quality, correctness. Read ONLY files listed in Implementation Log.
|
|
267
271
|
> 3. Write and execute integration tests covering all user stories from spec.md. Use `TEST_CMD=<TEST_CMD>` — do NOT try alternative test commands.
|
|
268
272
|
> 4. Append 'Review Notes' to context-snapshot.md: issues (severity), test results, final verdict.
|
|
@@ -311,7 +311,13 @@ Resume incremental planning? (Y/n)"
|
|
|
311
311
|
|
|
312
312
|
### Artifact Path Convention
|
|
313
313
|
|
|
314
|
-
|
|
314
|
+
**CRITICAL PATH RULE**: `feature-list.json` MUST be written to the project root directory
|
|
315
|
+
(same level as `package.json` / `.git`).
|
|
316
|
+
|
|
317
|
+
Before writing, verify: `ls package.json .git 2>/dev/null` — if these exist in the current
|
|
318
|
+
directory, you are at the project root. NEVER write to `dev-pipeline/` or any subdirectory.
|
|
319
|
+
|
|
320
|
+
After writing, verify: `ls -la feature-list.json` from project root.
|
|
315
321
|
|
|
316
322
|
```
|
|
317
323
|
<project-root>/
|
|
@@ -9,7 +9,16 @@ Launch the autonomous development pipeline from within an AI CLI conversation. T
|
|
|
9
9
|
|
|
10
10
|
### Execution Mode
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
**Default: Foreground mode** via `dev-pipeline/run.sh run` — this provides visible output and direct error feedback. Use `launch-daemon.sh` only when the user explicitly requests background execution (e.g., "run in background", "detached mode", "后台运行").
|
|
13
|
+
|
|
14
|
+
Foreground `run.sh` is preferred because:
|
|
15
|
+
- Immediate visibility of errors and progress
|
|
16
|
+
- No orphaned processes if something goes wrong
|
|
17
|
+
- Session summary artifacts are written reliably
|
|
18
|
+
|
|
19
|
+
Use daemon mode (`launch-daemon.sh`) only when:
|
|
20
|
+
- User explicitly requests background/detached execution
|
|
21
|
+
- Pipeline must survive AI CLI session closure
|
|
13
22
|
|
|
14
23
|
### When to Use
|
|
15
24
|
|
|
@@ -98,31 +107,36 @@ Detect user intent from their message, then follow the corresponding workflow:
|
|
|
98
107
|
```
|
|
99
108
|
|
|
100
109
|
4. **Ask execution mode**: Present the user with a choice before launching:
|
|
101
|
-
- **(1)
|
|
102
|
-
- **(2)
|
|
110
|
+
- **(1) Foreground in session (recommended)**: Pipeline runs in the current session via `run.sh run`. Visible output and direct error feedback.
|
|
111
|
+
- **(2) Background daemon**: Pipeline runs fully detached via `launch-daemon.sh`. Survives session closure. Use only when user explicitly requests background execution.
|
|
103
112
|
- **(3) Manual — show commands**: Display the exact commands the user can run themselves. No execution.
|
|
104
113
|
|
|
105
|
-
Default to option 1 if user says "just run it" or doesn't specify.
|
|
114
|
+
Default to option 1 if user says "just run it" or doesn't specify. Default to option 2 only if user explicitly says "background", "detached", or "后台".
|
|
106
115
|
|
|
107
|
-
**If option
|
|
116
|
+
**If option 1 (foreground)**:
|
|
108
117
|
```bash
|
|
109
118
|
dev-pipeline/run.sh run feature-list.json
|
|
110
119
|
```
|
|
111
|
-
Note: This will block the session. Warn user about timeout risk.
|
|
112
120
|
|
|
113
|
-
**If option
|
|
114
|
-
```
|
|
115
|
-
# To run in background (recommended):
|
|
121
|
+
**If option 2 (background)**:
|
|
122
|
+
```bash
|
|
116
123
|
dev-pipeline/launch-daemon.sh start feature-list.json
|
|
124
|
+
```
|
|
125
|
+
Note: Pipeline runs fully detached. Survives session closure.
|
|
117
126
|
|
|
118
|
-
|
|
127
|
+
**If option 3 (manual)**: Print commands and stop. Do not execute anything.
|
|
128
|
+
```
|
|
129
|
+
# To run in foreground (recommended):
|
|
119
130
|
dev-pipeline/run.sh run feature-list.json
|
|
120
131
|
|
|
132
|
+
# To run in background (detached):
|
|
133
|
+
dev-pipeline/launch-daemon.sh start feature-list.json
|
|
134
|
+
|
|
121
135
|
# To check status:
|
|
122
|
-
dev-pipeline/
|
|
136
|
+
dev-pipeline/run.sh status feature-list.json
|
|
123
137
|
```
|
|
124
138
|
|
|
125
|
-
5. **Ask user to confirm**: "Ready to launch the pipeline? It will process N features
|
|
139
|
+
5. **Ask user to confirm**: "Ready to launch the pipeline? It will process N features."
|
|
126
140
|
|
|
127
141
|
6. **Launch**:
|
|
128
142
|
```bash
|
package/package.json
CHANGED
package/src/upgrade.js
CHANGED
|
@@ -213,13 +213,25 @@ export async function runUpgrade(directory, options = {}) {
|
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
// 3. Resolve new skill list using old manifest's suite + platform (or defaults)
|
|
216
|
-
const
|
|
216
|
+
const oldManifestPlatform = oldManifest?.platform || 'claude';
|
|
217
217
|
const suite = oldManifest?.suite || 'full';
|
|
218
218
|
const team = oldManifest?.options?.team ?? true;
|
|
219
219
|
const pipeline = oldManifest?.options?.pipeline ?? true;
|
|
220
220
|
const rulesPreset = oldManifest?.options?.rules || 'recommended';
|
|
221
221
|
const aiCli = userConfig.ai_cli || oldManifest?.options?.aiCli || '';
|
|
222
222
|
|
|
223
|
+
// Filesystem-based platform detection (overrides manifest if dirs exist)
|
|
224
|
+
const hasClaude = await fs.pathExists(path.join(projectRoot, '.claude', 'commands'))
|
|
225
|
+
|| await fs.pathExists(path.join(projectRoot, '.claude', 'agents'));
|
|
226
|
+
const hasCodeBuddy = await fs.pathExists(path.join(projectRoot, '.codebuddy', 'skills'))
|
|
227
|
+
|| await fs.pathExists(path.join(projectRoot, '.codebuddy', 'agents'));
|
|
228
|
+
|
|
229
|
+
let platform;
|
|
230
|
+
if (hasClaude && hasCodeBuddy) platform = 'both';
|
|
231
|
+
else if (hasCodeBuddy) platform = 'codebuddy';
|
|
232
|
+
else if (hasClaude) platform = 'claude';
|
|
233
|
+
else platform = oldManifestPlatform; // fallback to manifest
|
|
234
|
+
|
|
223
235
|
const newSkillList = await resolveSkillList(suite);
|
|
224
236
|
const agentsDir = getAgentsDir();
|
|
225
237
|
const newAgentFiles = (await fs.readdir(agentsDir)).filter(f => f.endsWith('.md'));
|
|
@@ -255,7 +267,7 @@ export async function runUpgrade(directory, options = {}) {
|
|
|
255
267
|
const oldVersion = oldManifest?.version || 'unknown';
|
|
256
268
|
console.log(chalk.bold(' Upgrade Summary:'));
|
|
257
269
|
console.log(` Version: ${chalk.gray(oldVersion)} → ${chalk.cyan(pkg.version)}`);
|
|
258
|
-
console.log(` Platform: ${platform}`);
|
|
270
|
+
console.log(` Platform: ${platform}${platform !== oldManifestPlatform ? chalk.yellow(` (detected from filesystem, manifest had: ${oldManifestPlatform})`) : ''}`);
|
|
259
271
|
console.log(` Suite: ${suite}`);
|
|
260
272
|
console.log('');
|
|
261
273
|
|