From 299cb5097d43427dd3e5361ba83bc4465aabd236 Mon Sep 17 00:00:00 2001 From: Sangguen Chang <33509021+sgwannabe@users.noreply.github.com> Date: Sun, 26 Apr 2026 11:35:12 +0900 Subject: [PATCH 1/2] fix(profile): align stale 'pro' default refs with actual standard default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit settings.json has shipped pf.defaultProfile: "standard" since v1.4.0 (LESSON 0.10 — demo-first UX flip), but several markdown / Python files still claimed 'pro' as the default. Because LLM agents reading commands/new.md and ideation-lead.md trust the markdown over the JSON config, /pf:new was silently spinning up the pro profile (18 previews · 3×5 eng · ~70min) when users expected the standard demo path (9 previews · 2×5 eng · ~25min). Fix: - commands/new.md: examples row now shows standard as the default invocation; flag table corrected; "(기본)" tag moved from pro row to standard row in the comparison table; flow text §7 expanded to show the full resolution chain (--profile flag → env PF_PROFILE → settings.json → final fallback "standard"). Adds explicit "use --profile=pro|max for deeper verification" + PF_PROFILE env-var example. - agents/ideation/ideation-lead.md L110: profile-resolve doc updated to "standard" + LESSON 0.10 cross-reference. - hooks/cost-regression.py L46-60: docstring + 3 fallback branches ("pro" → "standard"). Now matches settings.json shipped value. - schemas/pf-profile.schema.json description: "pro (default)" wording replaced with "standard (default since v1.4)". Side effects: - bash scripts/verify-plugin.sh → 58 Pass / 0 Fail (unchanged) - No advocate boilerplate impact (lint scope is advocates/P*.md, not any of the touched files) - Historical references in LESSONS.md / CHANGELOG.md preserved intentionally (they document the v1.3.0 → v1.4.0 flip itself) - New users / fresh /pf:new invocations now hit the documented intended UX: ~25min standard run by default How to opt into pro/max from start (now documented in commands/new.md): /pf:new "..." --profile=pro /pf:new "..." --profile=max PF_PROFILE=pro /pf:new "..." Co-Authored-By: Claude Opus 4.7 (1M context) --- .claude/scheduled_tasks.lock | 1 + .../agents/ideation/ideation-lead.md | 2 +- plugins/preview-forge/commands/new.md | 17 +++++++++-------- plugins/preview-forge/hooks/cost-regression.py | 14 ++++++++++---- .../schemas/pf-profile.schema.json | 2 +- 5 files changed, 22 insertions(+), 14 deletions(-) create mode 100644 .claude/scheduled_tasks.lock diff --git a/.claude/scheduled_tasks.lock b/.claude/scheduled_tasks.lock new file mode 100644 index 0000000..e2ac4a7 --- /dev/null +++ b/.claude/scheduled_tasks.lock @@ -0,0 +1 @@ +{"sessionId":"938872e0-a3df-43fb-aeaf-6af9c95bd929","pid":69541,"procStart":"Sat Apr 25 06:46:36 2026","acquiredAt":1777101197262} \ No newline at end of file diff --git a/plugins/preview-forge/agents/ideation/ideation-lead.md b/plugins/preview-forge/agents/ideation/ideation-lead.md index 8546056..4109e88 100644 --- a/plugins/preview-forge/agents/ideation/ideation-lead.md +++ b/plugins/preview-forge/agents/ideation/ideation-lead.md @@ -107,7 +107,7 @@ IDEA_SPEC: 먼저 **active profile을 resolve**: 1. `runs//.profile` 파일 (M1이 /pf:new --profile 파싱 후 기록) 2. env `PF_PROFILE` -3. plugin `settings.json` → `pf.defaultProfile` (기본 `pro`) +3. plugin `settings.json` → `pf.defaultProfile` (현재 `"standard"`; v1.3.0에서는 `"pro"`였으나 v1.4.0에서 데모-퍼스트 정책으로 flip — LESSON 0.10 참조). 최종 fallback도 `"standard"`. 그리고 profile의 `previews.count`만큼 Advocate 선정: - **standard** (9): P01, P02, P05, P07, P10, P14, P17, P20, P24 — 가장 다양한 페르소나 스펙트럼 diff --git a/plugins/preview-forge/commands/new.md b/plugins/preview-forge/commands/new.md index 1d875c6..c51bfdf 100644 --- a/plugins/preview-forge/commands/new.md +++ b/plugins/preview-forge/commands/new.md @@ -13,10 +13,11 @@ description: Start a new Preview Forge run (PreviewDD cycle begins) ``` 예시: -- `/pf:new "공방 운영자가 수업·재고·정산을 한 곳에서"` (pro profile 기본값) -- `/pf:new "todo app with auth" --profile=standard` (빠른 프로토타입) -- `/pf:new "production SaaS 런칭용 앱" --profile=max` (풀 143-agent 검증) -- `/pf:new "idea" --profile=pro --previews=26 --no-cache` (pro 기본에 previews 확장 + 캐시 스킵) +- `/pf:new "공방 운영자가 수업·재고·정산을 한 곳에서"` (**standard** profile 기본값 — v1.4+, 9 previews · 2×5 eng · ~25분) +- `/pf:new "production SaaS launch" --profile=pro` (실제 프로젝트, 18 previews · 3×5 eng · ~70분) +- `/pf:new "regulated enterprise rollout" --profile=max` (풀 143-agent · 26 previews · ~160분) +- `/pf:new "idea" --profile=pro --previews=26 --no-cache` (pro에 previews 확장 + 캐시 스킵) +- `PF_PROFILE=max /pf:new "..."` (환경변수로 default 오버라이드 — 1회용) ## 인자 @@ -27,7 +28,7 @@ description: Start a new Preview Forge run (PreviewDD cycle begins) | 플래그 | 기본값 | 설명 | |---|---|---| -| `--profile` | `pro` (`settings.json` defaultProfile) | 프로파일 이름: `standard` · `pro` · `max` | +| `--profile` | **`standard`** (v1.4+, was `pro` in v1.3.0; lives in `settings.json` `pf.defaultProfile`) | 프로파일 이름: `standard` · `pro` · `max`. 처음부터 더 깊은 검증을 원하면 `--profile=pro` 또는 `--profile=max` 명시. 환경변수 `PF_PROFILE=pro` 도 동일 효과 (해당 셸 세션에 영향). | | `--previews=N` | profile에 종속 (9/18/26) | Advocate 수 오버라이드. profile의 `max_user_expand` (26) 이내 | | `--no-cache` | false | PreviewDD-level 캐시 스킵. 동일 아이디어 재실행 시 강제 재생성 | @@ -35,8 +36,8 @@ description: Start a new Preview Forge run (PreviewDD cycle begins) | Profile | Previews | Eng teams | Panels | SCC iter | P95 ceiling | 권장 용도 | |---|---|---|---|---|---|---| -| **standard** | 9 | 2×5 (BE+FE) | keyword-trigger | 3 | ~60k tok / 25min | 데모 · 프로토타입 | -| **pro** *(기본)* | 18 | 3×5 (+DB) | keyword-trigger + escalation | 4 | ~250k tok / 70min | 실제 프로젝트 | +| **standard** *(기본 — v1.4+)* | 9 | 2×5 (BE+FE) | keyword-trigger | 3 | ~60k tok / 25min | 데모 · 프로토타입 · 첫 시도 | +| **pro** | 18 | 3×5 (+DB) | keyword-trigger + escalation | 4 | ~250k tok / 70min | 실제 프로젝트 | | **max** | 26 | 5×5 (all) | always-on | 5 | ~600k tok / 160min | 프로덕션 런칭 · 베이스라인 | 상세: `plugins/preview-forge/profiles/{standard,pro,max}.json` @@ -51,7 +52,7 @@ M1 Run Supervisor는 **모든 작업 전** 다음을 순서대로 검증합니 4. **claude CLI + plugin install** — plugin 자체 로드 상태 확인. 5. **api.anthropic.com 연결** — 기본 reachability 확인. 6. **LESSONS pre-load** — `~/.claude/preview-forge/memory/LESSONS.md`에서 관련 카테고리(1. PreviewDD, 4. Memory, 6. Plugin 배포)를 읽어 department lead들의 system prompt에 주입. -7. **profile resolve** (v1.3+) — `--profile` 플래그 · env `PF_PROFILE` · `settings.json` defaultProfile 순으로 해결 → `runs//.profile` 파일에 기록. 이후 모든 hook·monitor가 이 값을 참조. +7. **profile resolve** (v1.3+, v1.4+ default flipped to `standard`) — `--profile` 플래그 → env `PF_PROFILE` → `settings.json` `pf.defaultProfile` (현재 `"standard"`) → 최종 fallback `"standard"` 순으로 해결 → `runs//.profile` 파일에 기록. 이후 모든 hook·monitor가 이 값을 참조. 사용자가 처음부터 깊은 검증을 원하면 `/pf:new "..." --profile=pro|max` 또는 `PF_PROFILE=pro` 환경변수 사용. 8. **idea-input size cap** (umbrella #95 follow-up — defense in depth, layer 1) — orchestrator MUST invoke [`scripts/pre-flight.sh --idea ""`](../../../scripts/pre-flight.sh) (or the equivalent direct call to [`scripts/validate-idea-input.sh`](../../../scripts/validate-idea-input.sh)) on the raw seed idea **BEFORE** writing it to `runs//idea.json`, computing any cache key (`scripts/preview-cache.sh key …`), or expanding the I1 Socratic interview prompt. The validator exits 0 if `len(idea) ≤ 5000` Unicode code points (matching the `idea_summary` schema cap), exits non-zero otherwise. On non-zero, abort the run with the validator's stderr message — do NOT silently truncate. Rationale: the schema's `idea_summary.maxLength: 5000` only fires at S-3 validation, well after the seed idea has already inflated the Socratic system prompt and been hashed into the cache key. This pre-flight gate stops a 10MB seed idea at the door. Bypass policy: NONE — `--no-cache` does not bypass this check. Truncate mode (`scripts/validate-idea-input.sh --truncate -`) exists for non-interactive automation pipelines that explicitly opt in; `/pf:new` itself MUST default to reject so the user keeps full intent over what gets trimmed. The size cap also runs at S-3 schema validation as the canonical authority — this layer-1 gate is belt-and-suspenders. CLI 환경에서는 `scripts/pre-flight.sh` 또는 `pf check`로 동일 검증 수동 실행 가능. 아이디어 텍스트까지 포함해 한 번에 검증하려면 `scripts/pre-flight.sh --idea ""` (or `--idea-file ` for inputs that may exceed ARG_MAX). diff --git a/plugins/preview-forge/hooks/cost-regression.py b/plugins/preview-forge/hooks/cost-regression.py index 3266426..f6d97f1 100644 --- a/plugins/preview-forge/hooks/cost-regression.py +++ b/plugins/preview-forge/hooks/cost-regression.py @@ -43,7 +43,13 @@ def load_profile(name: str) -> dict | None: def load_active_profile(run_dir: Path) -> dict | None: - """Priority: run_dir/.profile → env PF_PROFILE → settings.defaultProfile → 'pro'.""" + """Priority: run_dir/.profile → env PF_PROFILE → settings.defaultProfile → 'standard'. + + v1.4+ default is 'standard' (was 'pro' in v1.3.0; flipped for demo-first + UX — see LESSON 0.10). settings.json ships with defaultProfile: standard; + the hard-coded fallbacks below match that so a missing/malformed + settings.json behaves consistently. + """ marker = run_dir / ".profile" if marker.exists(): name = marker.read_text(encoding="utf-8").strip() @@ -52,11 +58,11 @@ def load_active_profile(run_dir: Path) -> dict | None: if not name and SETTINGS_PATH.exists(): try: s = json.load(SETTINGS_PATH.open(encoding="utf-8")) - name = s.get("pf", {}).get("defaultProfile", "pro") + name = s.get("pf", {}).get("defaultProfile", "standard") except (OSError, json.JSONDecodeError): - name = "pro" + name = "standard" if not name: - name = "pro" + name = "standard" return load_profile(name) diff --git a/plugins/preview-forge/schemas/pf-profile.schema.json b/plugins/preview-forge/schemas/pf-profile.schema.json index c9224f9..b049469 100644 --- a/plugins/preview-forge/schemas/pf-profile.schema.json +++ b/plugins/preview-forge/schemas/pf-profile.schema.json @@ -2,7 +2,7 @@ "$schema": "http://json-schema.org/draft-07/schema#", "$id": "https://two-weeks-team.github.io/PreviewForgeForClaudeCode/schemas/pf-profile.schema.json", "title": "PF Profile", - "description": "Preview Forge run profile — controls cost, speed, and thoroughness of a 3-DD cycle. Three values ship: standard (cheapest), pro (default, balanced), max (all-in 143 agents).", + "description": "Preview Forge run profile — controls cost, speed, and thoroughness of a 3-DD cycle. Three values ship: standard (default since v1.4 — demo/prototype, fastest), pro (real project, balanced), max (production launch, all-in 143 agents).", "type": "object", "required": [ "name", From b8713f6f756405bd346f393de0ad4639a1d2c522 Mon Sep 17 00:00:00 2001 From: Sangguen Chang <33509021+sgwannabe@users.noreply.github.com> Date: Sun, 26 Apr 2026 11:35:36 +0900 Subject: [PATCH 2/2] chore: untrack .claude/scheduled_tasks.lock + gitignore Accidentally added in the previous commit (Claude Code session lock, per-process state, not source). Removed from index and gitignored so future sessions don't re-stage it. Co-Authored-By: Claude Opus 4.7 (1M context) --- .claude/scheduled_tasks.lock | 1 - .gitignore | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) delete mode 100644 .claude/scheduled_tasks.lock diff --git a/.claude/scheduled_tasks.lock b/.claude/scheduled_tasks.lock deleted file mode 100644 index e2ac4a7..0000000 --- a/.claude/scheduled_tasks.lock +++ /dev/null @@ -1 +0,0 @@ -{"sessionId":"938872e0-a3df-43fb-aeaf-6af9c95bd929","pid":69541,"procStart":"Sat Apr 25 06:46:36 2026","acquiredAt":1777101197262} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 7af8cea..6e86d41 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,6 @@ coverage/ # matters: in .gitignore the *last* matching pattern wins. !runs/r-clean-*/ !runs/r-clean-*/** + +# Claude Code session locks (per-process state, not source) +.claude/scheduled_tasks.lock