원클릭으로
plan-and-analyze
Launch PRD discovery with codebase grounding and context ingestion
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Launch PRD discovery with codebase grounding and context ingestion
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Bridgebuilder — Autonomous PR Review
Triage a bug report through structured phases and create micro-sprint
Execute sprint tasks with production-quality code and tests
Validate sprint implementation against acceptance criteria
Security and quality audit of application codebase
Autonomous agent execution mode
| name | plan-and-analyze |
| description | Launch PRD discovery with codebase grounding and context ingestion |
| role | planning |
| allowed-tools | Read, Grep, Glob, AskUserQuestion, WebFetch, Write, Bash(git log *), Bash(wc *) |
| capabilities | {"schema_version":1,"read_files":true,"search_code":true,"write_files":true,"execute_commands":{"allowed":[{"command":"git","args":["log","*"]},{"command":"wc","args":["*"]}],"deny_raw_shell":true},"web_access":true,"user_interaction":true,"agent_spawn":false,"task_management":false} |
| cost-profile | moderate |
| parallel_threshold | 2000 |
| timeout_minutes | 90 |
| zones | {"system":{"path":".claude","permission":"none"},"state":{"paths":["grimoires/loa",".beads"],"permission":"read-write"},"app":{"paths":["src","lib","app"],"permission":"read"}} |
<prompt_enhancement_prelude>
If .loa.config.yaml sets prompt_enhancement.invisible_mode.enabled: true and this command's
frontmatter does not set enhance: false, silently apply the PTCF scoring + template flow from
.claude/skills/enhancing-prompts/SKILL.md to the user's request before main logic (log per that
skill; never show enhancement output). On any error, or when disabled: proceed with the original
prompt unchanged.
</prompt_enhancement_prelude>
<interview_config>
interview_mode=$(yq eval '.interview.mode // "thorough"' .loa.config.yaml 2>/dev/null || echo "thorough")
skill_mode=$(yq eval '.interview.per_skill.discovering-requirements // ""' .loa.config.yaml 2>/dev/null || echo "")
[[ -n "$skill_mode" ]] && interview_mode="$skill_mode"
pacing=$(yq eval '.interview.pacing // "sequential"' .loa.config.yaml 2>/dev/null || echo "sequential")
discovery_style=$(yq eval '.interview.input_style.discovery_questions // "plain"' .loa.config.yaml 2>/dev/null || echo "plain")
routing_style=$(yq eval '.interview.input_style.routing_gates // "structured"' .loa.config.yaml 2>/dev/null || echo "structured")
confirmation_style=$(yq eval '.interview.input_style.confirmation // "structured"' .loa.config.yaml 2>/dev/null || echo "structured")
no_infer=$(yq eval '.interview.backpressure.no_infer // true' .loa.config.yaml 2>/dev/null || echo "true")
show_work=$(yq eval '.interview.backpressure.show_work // true' .loa.config.yaml 2>/dev/null || echo "true")
gate_between=$(yq eval '.interview.phase_gates.between_phases // true' .loa.config.yaml 2>/dev/null || echo "true")
gate_before_gen=$(yq eval '.interview.phase_gates.before_generation // true' .loa.config.yaml 2>/dev/null || echo "true")
min_confirm=$(yq eval '.interview.backpressure.min_confirmation_questions // 1' .loa.config.yaml 2>/dev/null || echo "1")
| Mode | Questions/Phase | Pacing | Phase Gates | Gap Skipping |
|---|---|---|---|---|
thorough | 3-6 (scales down with context) | sequential | All ON | Suppressed: always ask min_confirm questions |
minimal | 1-2 | batch | before_generation only | Active: skip covered phases |
| Interaction Type | structured | plain |
|---|---|---|
| Routing gates | AskUserQuestion with options | "Continue, go back, or skip ahead?" |
| Discovery questions | AskUserQuestion with suggested answers | Markdown question, user responds freely |
| Confirmations | AskUserQuestion (Yes/Correct/Adjust) | "Is this accurate? [yes/corrections]" |
| Pacing | Behavior |
|---|---|
sequential | Ask ONE question per turn. Wait for response. Then ask the next. |
batch | Present 3-6 numbered questions. User responds to all at once. |
When no_infer is true (DEFAULT):
PROHIBITED:
REQUIRED:
Schema supports future construct manifest override:
{ "workflow": { "interview": { "mode": "minimal", "trust_tier": "BACKTESTED" } } }
Precedence: Construct (if trust >= BACKTESTED) > per_skill config > global mode > default (thorough). Not wired yet. Extension point documented here for forward compatibility. </interview_config>
Lore Integration: When framing requirements, reference relevant archetypes from .claude/data/lore/ to ground the project's philosophical context. Use short fields for inline naming explanations (e.g., why a feature is called "bridge" or "vision"). Use context fields when a requirement discussion benefits from deeper framing — for instance, connecting iterative refinement patterns to kaironic time concepts. Only reference lore when contextually appropriate; never force philosophical connections.
<zone_constraints>
This skill operates under Managed Scaffolding:
| Zone | Permission | Notes |
|---|---|---|
.claude/ | NONE | System zone - never suggest edits |
grimoires/loa/, .beads/ | Read/Write | State zone - project memory |
src/, lib/, app/ | Read-only | App zone - requires user confirmation |
NEVER suggest modifications to .claude/. Direct users to .claude/overrides/ or .loa.config.yaml.
Agents MAY proactively run read-only CLI tools (e.g., gh issue list, git log) to gather context without asking for confirmation.
</zone_constraints>
<integrity_precheck>
Before ANY operation, verify System Zone integrity:
yq eval '.integrity_enforcement' .loa.config.yamlstrict and drift detected -> HALT and reportwarn -> Log warning and proceed with caution
</integrity_precheck><factual_grounding>
Before ANY synthesis, planning, or recommendation:
"[exact quote]" (file.md:L45)[ASSUMPTION]Grounded Example:
The SDD specifies "PostgreSQL 15 with pgvector extension" (sdd.md:L123)
Ungrounded Example:
[ASSUMPTION] The database likely needs connection pooling
</factual_grounding>
<context_discipline>
Follow .claude/protocols/tool-result-clearing.md. Thresholds: single result >2K tokens /
accumulated >5K / full file >3K / session total >15K → extract findings (≤10 files, ≤20 words
each, with file:line) to grimoires/loa/NOTES.md, then reason from the synthesis, not raw dumps.
Session start: read NOTES.md "Session Continuity". Session end / pre-compaction: update it
(decisions → Decision Log, discovered issues → Technical Debt).
</context_discipline>
<trajectory_logging>
Log each significant step to grimoires/loa/a2a/trajectory/{agent}-{date}.jsonl:
{"timestamp": "...", "agent": "...", "action": "...", "reasoning": "...", "grounding": {...}}
</trajectory_logging>
<kernel_framework>
Produce comprehensive PRD by:
grimoires/loa/context/grimoires/loa/context/*.md (optional), developer interviewgrimoires/loa/prd.mdgrimoires/loa/a2a/integration-context.md (if exists)> From vision.md:12: "exact quote"PRD traces every requirement to either:
<codebase_grounding>
Purpose: Ground PRD creation in codebase reality to prevent hallucinated requirements.
Read configuration from .loa.config.yaml (with defaults):
# Check if codebase grounding is enabled (default: true)
enabled=$(yq eval '.plan_and_analyze.codebase_grounding.enabled // true' .loa.config.yaml 2>/dev/null || echo "true")
# Get staleness threshold in days (default: 7)
staleness_days=$(yq eval '.plan_and_analyze.codebase_grounding.reality_staleness_days // 7' .loa.config.yaml 2>/dev/null || echo "7")
# Get /ride timeout in minutes (default: 20)
timeout_minutes=$(yq eval '.plan_and_analyze.codebase_grounding.ride_timeout_minutes // 20' .loa.config.yaml 2>/dev/null || echo "20")
# Get skip-on-error behavior (default: false)
skip_on_error=$(yq eval '.plan_and_analyze.codebase_grounding.skip_on_ride_error // false' .loa.config.yaml 2>/dev/null || echo "false")
If enabled: false, skip Phase -0.5 entirely (equivalent to GREENFIELD behavior).
When /plan-and-analyze runs, check the codebase_detection pre-flight result:
IF config.enabled == false:
→ Skip to Phase -1 (feature disabled)
→ Do NOT mention codebase grounding to user
ELSE IF codebase_detection.type == "GREENFIELD":
→ Skip to Phase -1 (no codebase to analyze)
→ Do NOT mention codebase grounding to user
ELSE IF codebase_detection.type == "BROWNFIELD":
IF codebase_detection.reality_exists == true:
IF codebase_detection.reality_age_days < config.staleness_days:
→ Use cached reality (no /ride needed)
→ Show: "Using recent codebase analysis (N days old)"
ELSE IF --fresh flag provided:
→ Run /ride regardless of cache
ELSE:
→ Prompt user with AskUserQuestion:
- "Re-run /ride for fresh analysis (recommended)"
- "Proceed with existing analysis (faster)"
ELSE:
→ Present recommendation via AskUserQuestion:
questions:
- question: "This is a brownfield project with no codebase reality files. How would you like to proceed?"
header: "Grounding"
options:
- label: "Run /ride (Recommended)"
description: "Analyze codebase first to ground PRD in code reality"
- label: "Run /ride --enriched"
description: "Full analysis with gap tracking, decision archaeology, and terminology extraction"
- label: "Skip grounding"
description: "Proceed without codebase analysis (not recommended for brownfield)"
multiSelect: false
→ If "Run /ride": invoke ride skill (standard mode)
→ If "Run /ride --enriched": invoke ride skill with --enriched flag
→ If "Skip grounding":
- Log warning to NOTES.md blockers:
"- [ ] [BLOCKER] PRD created without codebase grounding — user skipped /ride for brownfield project"
- Proceed to Phase -1 without reality context
- Add warning banner to generated PRD
Invoke the ride skill (NOT the command) for codebase analysis:
CODEBASE GROUNDING PHASE
Analyzing your existing codebase to ground PRD requirements in reality.
This typically takes 5-15 minutes depending on codebase size.
Progress:
- [ ] Extracting component inventory
- [ ] Analyzing architecture patterns
- [ ] Identifying existing requirements
- [ ] Building consistency report
Use the Skill tool to invoke ride:
Skill: ride
This will produce:
grimoires/loa/reality/extracted-prd.mdgrimoires/loa/reality/extracted-sdd.mdgrimoires/loa/reality/component-inventory.mdgrimoires/loa/consistency-report.mdIf /ride fails or times out:
Capture error in NOTES.md Decision Log:
| Date | Decision | Rationale | Source |
|------|----------|-----------|--------|
| YYYY-MM-DD | /ride failed during codebase grounding | [error message] | Phase -0.5 |
Check config for auto-skip:
skip_on_error=$(yq eval '.plan_and_analyze.codebase_grounding.skip_on_ride_error // false' .loa.config.yaml)
If skip_on_error: true, automatically skip to Phase -1 with warning.
Otherwise prompt user with AskUserQuestion:
questions:
- question: "/ride analysis failed. How would you like to proceed?"
header: "Recovery"
options:
- label: "Retry /ride analysis"
description: "Re-run codebase analysis (recommended)"
- label: "Skip codebase grounding"
description: "Proceed without code-based requirements (not recommended)"
- label: "Abort"
description: "Cancel /plan-and-analyze entirely"
multiSelect: false
Handle user response:
If "Retry":
If "Skip":
- [ ] [BLOCKER] PRD created without codebase grounding - /ride failed: [error]
> ⚠️ **WARNING**: This PRD was created without codebase grounding.
> Run `/ride` and `/plan-and-analyze --fresh` for accurate requirements.
If "Abort":
Preserve partial results if available:
Default timeout: 20 minutes (configurable in .loa.config.yaml)
plan_and_analyze:
codebase_grounding:
ride_timeout_minutes: 20
For GREENFIELD projects:
Run context assessment:
./.claude/scripts/assess-discovery-context.sh
| Result | Strategy |
|---|---|
NO_CONTEXT_DIR | Create directory, offer guidance, proceed to full interview |
EMPTY | Proceed to full 7-phase interview |
SMALL (<500 lines) | Sequential ingestion, then targeted interview |
MEDIUM (500-2000) | Sequential ingestion, then targeted interview |
LARGE (>2000) | Parallel subagent ingestion, then targeted interview |
Load and synthesize context in priority order:
| Priority | Source | Citation Format | Trust Level |
|---|---|---|---|
| 1 | grimoires/loa/reality/ | [CODE:file:line] | Highest (code is truth) |
| 2 | grimoires/loa/context/ | > From file.md:line | High (user-provided) |
| 3 | Interview responses | (Phase N QN) | Standard |
Conflict Resolution: When reality contradicts context:
If reality files exist (from /ride or cached):
Present the canonical codebase-understanding specimen from resources/templates/context-understanding.md.
Read in priority order:
grimoires/loa/reality/*.md (if exists)grimoires/loa/context/*.md (and subdirectories)Internally categorize discovered information:
<context_map>
<phase name="problem_vision">
<reality source="extracted-prd.md:10-30">
Implicit problem statement from codebase
</reality>
<found source="vision.md:1-45">
Product vision, mission statement, core problem
</found>
<gap>Success metrics not defined</gap>
</phase>
<phase name="goals_metrics">
<found source="vision.md:47-52">
High-level goals mentioned
</found>
<gap>No quantifiable success criteria</gap>
<gap>Timeline not specified</gap>
</phase>
<phase name="users_stakeholders">
<found source="users.md:1-289">
3 personas defined with jobs-to-be-done
</found>
<ambiguity>Persona priorities unclear - which is primary?</ambiguity>
</phase>
<phase name="functional_requirements">
<reality source="component-inventory.md:1-200">
Existing features extracted from code
</reality>
<found source="requirements.md:1-100">
User-documented requirements
</found>
<conflict>User docs mention feature X, but not found in codebase</conflict>
</phase>
<!-- Continue for all 7 phases -->
</context_map>
For brownfield projects, present codebase understanding FIRST:
Present the combined codebase + documentation understanding specimen in resources/templates/context-understanding.md.
Purpose: Surface relevant captured visions from previous bridge reviews to inform planning.
vr_enabled=$(yq eval '.vision_registry.enabled // false' .loa.config.yaml 2>/dev/null || echo "false")
If vision_registry.enabled is false or absent: skip this step entirely — no mention to user, no code runs.
When enabled, derive tags from available context in priority order:
grimoires/loa/sprint.md exists): Extract **File**: \...`patterns and map throughvision_extract_tags()` path-to-tag rulesarchitecture, security, constraints, multi-model, testing, philosophy, orchestration, configuration, eventing)grimoires/loa/prd.md exists): Map headers to tags (e.g., "Security" → security)Tags are deduplicated and sorted before matching.
visions=$(.claude/scripts/vision-registry-query.sh \
--tags "$work_tags" \
--status "$(yq eval '.vision_registry.status_filter | join(",")' .loa.config.yaml 2>/dev/null || echo 'Captured,Exploring')" \
--min-overlap "$(yq eval '.vision_registry.min_tag_overlap // 2' .loa.config.yaml 2>/dev/null || echo '2')" \
--max-results "$(yq eval '.vision_registry.max_visions_per_session // 3' .loa.config.yaml 2>/dev/null || echo '3')" \
--include-text \
--json)
Shadow mode (vision_registry.shadow_mode: true):
# Log silently — do NOT present to user
.claude/scripts/vision-registry-query.sh \
--tags "$work_tags" \
--shadow \
--shadow-cycle "$(yq eval '.active_cycle' grimoires/loa/ledger.json 2>/dev/null)" \
--shadow-phase "plan-and-analyze" \
--json > /dev/null
grimoires/loa/a2a/trajectory/vision-shadow-{date}.jsonlgrimoires/loa/visions/.shadow-state.jsonActive mode (vision_registry.shadow_mode: false):
Present matched visions to user using the template below, then process user decisions.
For each matched vision, present using the presentation template in resources/templates/vision-registry-templates.md.
IMPORTANT: The relevance explanation is template-based (tag match + score), NOT LLM-generated. Do not fabricate a narrative about why the vision is relevant — state the matched tags and score.
For each vision the user responds to:
| Choice | Action |
|---|---|
| Explore | Call vision_update_status(vision_id, "Exploring", visions_dir). Record reference via vision_record_ref(). Log choice to trajectory JSONL. |
| Defer | Log choice to trajectory JSONL. No status change. |
| Skip | Log choice to trajectory JSONL. No status change. |
Log format (append to grimoires/loa/a2a/trajectory/vision-decisions-{date}.jsonl):
{
"timestamp": "ISO8601",
"cycle": "cycle-NNN",
"phase": "plan-and-analyze",
"vision_id": "vision-NNN",
"decision": "explore|defer|skip",
"score": N,
"matched_tags": ["tag1", "tag2"]
}
When the query script returns graduation.ready: true, present the shadow-graduation prompt in resources/templates/vision-registry-templates.md.
On "Enable active mode": Update config via yq eval '.vision_registry.shadow_mode = false' -i .loa.config.yaml
For each gap/ambiguity identified:
Example:
### Goals & Success Metrics
I found high-level goals in vision.md:
> "Achieve product-market fit within 12 months"
However, I didn't find specific success metrics.
**Questions:**
1. What metrics would indicate product-market fit for this product?
2. Are there intermediate milestones (3-month, 6-month)?
For each phase, follow this logic:
IF phase fully covered AND interview_mode == "minimal":
→ Summarize understanding with citations
→ Ask: "Is this accurate?" (1 confirmation, uses confirmation_style)
→ Move to next phase
ELSE IF phase fully covered AND interview_mode == "thorough":
→ Summarize understanding with citations
→ Ask at least {min_confirm} questions: "Is this accurate?" +
"What am I missing about [specific aspect]?"
→ DO NOT skip. Context coverage does not exempt from confirmation.
→ Wait for response. Respect pacing setting.
ELSE IF phase partially covered:
→ Summarize what's known (with citations)
→ Ask about gaps (respect configured question range and pacing)
ELSE IF phase not covered:
→ Full discovery (respect configured question range and pacing)
→ Iterate until user confirms phase is complete
After each phase (1-7), run the Phase Transition Protocol
(resources/REFERENCE.md §Phase Transition Protocol), substituting the
phase-specific values below ({THIS} = current phase, {NEXT} = next phase,
{NEXT_NUM} = next phase number):
| After Phase | {THIS} | {NEXT} | {NEXT_NUM} |
|---|---|---|---|
| 1 | Problem & Vision | Goals & Success Metrics | 2 |
| 2 | Goals & Success Metrics | User & Stakeholder Context | 3 |
| 3 | User & Stakeholder Context | Functional Requirements | 4 |
| 4 | Functional Requirements | Technical & Non-Functional | 5 |
| 5 | Technical & Non-Functional | Scope & Prioritization | 6 |
| 6 | Scope & Prioritization | Risks & Dependencies | 7 |
| 7 | Risks & Dependencies | pre-generation review (terminal) | — |
Anti-Inference Directive: When the user provides a feature list, DO NOT expand it with "you'll probably also need..." additions. If you believe something is missing, ASK: "I notice [X] isn't mentioned. Intentional, or should we add it?"
For high-precision requirements, use EARS notation from
resources/templates/ears-requirements.md:
| Pattern | Format | Use When |
|---|---|---|
| Ubiquitous | The system shall [action] | Always-true requirements |
| Event-Driven | When [trigger], the system shall [action] | Trigger-based behavior |
| Conditional | If [condition], the system shall [action] | Precondition-based |
When to use EARS: Security-critical features, regulatory compliance, complex triggers.
When gate_before_gen is true:
Present completeness summary:
Discovery Complete
---
Phases covered: {N}/7
Questions asked: {count}
Assumptions made: {count}
Top assumptions (review before I generate):
1. [ASSUMPTION] {description} — if wrong, {impact}
2. [ASSUMPTION] {description} — if wrong, {impact}
3. [ASSUMPTION] {description} — if wrong, {impact}
Ready to generate PRD?
Use routing_style for the "Ready to generate?" prompt.
DO NOT generate the PRD until the user explicitly confirms.
When gate_before_gen is false:
Proceed directly to generation with a one-line notice: "Generating PRD based on discovery."
Purpose: When a user chose "Explore" for a vision in Step 0.5, synthesize it with the work context to propose additional requirements the user may not have considered.
Gate: This step ONLY runs when ALL conditions are met:
vision_registry.enabled: true in .loa.config.yamlvision_registry.propose_requirements: true in .loa.config.yaml (default: false)If any condition is false: skip this step silently.
For each vision the user chose "Explore" in Step 0.5:
entry_file="grimoires/loa/visions/entries/${vision_id}.md"
Read the full entry file including ## Insight, ## Potential, and ## Connection Points sections.
For each explored vision, synthesize with the work context gathered from Phases 1-7 to propose 1-3 requirements. Each proposal must:
[VISION-INSPIRED: vision-NNN]Present using the vision-inspired proposals specimen in resources/templates/vision-registry-templates.md.
| Choice | Action |
|---|---|
| Accept | Include in PRD under "## Vision-Inspired Requirements" section. Call vision_update_status(vision_id, "Proposed", visions_dir). Record reference. |
| Modify | User edits the requirement text. Include modified version in PRD. Status → Proposed. Record reference. |
| Reject | Do not include. Log rejection reason to trajectory JSONL. No status change. |
Log all decisions to grimoires/loa/a2a/trajectory/vision-proposals-{date}.jsonl:
{
"timestamp": "ISO8601",
"cycle": "cycle-NNN",
"vision_id": "vision-NNN",
"proposal_title": "short title",
"decision": "accept|modify|reject",
"rejection_reason": "optional — only for reject"
}
Accepted/modified proposals go in a dedicated PRD section — use the PRD-integration specimen in resources/templates/vision-registry-templates.md.
This section is clearly separated from user-driven requirements and carries full provenance.
Only generate PRD when:
Generate PRD with source tracing:
## 1. Problem Statement
[Content derived from vision.md:12-30 and Phase 1 interview]
> Sources: vision.md:12-15, confirmed in Phase 1 Q2
<parallel_execution>
If context assessment returns LARGE:
Task(subagent_type="Explore", prompt="
CONTEXT INGESTION: Problem & Vision
Read these files: [vision.md, any *vision* or *problem* files]
Extract and summarize:
- Core problem statement
- Product vision
- Mission/purpose
- 'Why now' factors
Return as structured summary with file:line citations.
")
Spawn 4 parallel ingestors:
Merge summaries into unified context map before proceeding. </parallel_execution>
<output_format>
PRD structure with source tracing - see resources/templates/prd-template.md
Each section must include:
> **Sources**: vision.md:12-30, users.md:45-67, Phase 3 Q1-Q2
</output_format>
<success_criteria>
<uncertainty_protocol>
<grounding_requirements> Every claim about existing context must include citation:
> From {filename}:{line}: "exact quote"(vision.md:12-45)<edge_cases>
Edge-case handling table: see resources/REFERENCE.md §Edge Cases.
</edge_cases>
<visual_communication>
Visual-communication guidance (when to include diagrams, Mermaid output format, theme configuration): see resources/REFERENCE.md §Visual Communication.
</visual_communication>
<post_completion>
After saving the PRD to grimoires/loa/prd.md, MUST run .claude/scripts/validate-artifact.sh --type prd --file grimoires/loa/prd.md before the debrief; repair per its output on exit 1; exit 2 (usage/file-not-found) is a validator FAILURE — fix the path and re-run, do not proceed. ALWAYS present a structured debrief before the user decides to continue.
Present the following in this exact order:
Confirmation: "✓ PRD saved to grimoires/loa/prd.md"
Key Decisions (3-5 items): The most impactful choices made during discovery. Each decision should be one line: "• {choice made} (not {alternative rejected})"
Assumptions (1-3 items): Things assumed true but not explicitly confirmed by the user. Each assumption should be falsifiable: "• {assumption} — if wrong, {consequence}"
Biggest Tradeoff (1 item): The most consequential either/or decision. Format: "• Chose {A} over {B} — {reason}. Risk: {what could go wrong}"
Steer Prompt: Use AskUserQuestion:
question: "Anything to steer before architecture?"
header: "Review"
options:
- label: "Continue (Recommended)"
description: "Design the system architecture now"
- label: "Adjust"
description: "Tell me what to change — I'll regenerate the PRD"
- label: "Stop here"
description: "Save progress — resume with /plan next time. Not what you expected? /feedback helps us fix it."
multiSelect: false
When the user selects "Adjust":