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 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",