feat: add D.intelligence Agent Corps (9 skills + shared infra)

Add 9 agent skills (#70-#77, #88) for D.intelligence business operations:
brand guardian, brand editor, doc secretary, quotation manager, service
architect, marketing manager, back office manager, account manager, and
skill update meta-agent. Includes shared Python package (dintel), reference
docs, document/quotation templates, service module CSVs, cross-device
installer, and comprehensive user guide.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-09 00:49:04 +09:00
parent 72a6be6a74
commit 338176abbe
71 changed files with 15054 additions and 2 deletions

View File

@@ -0,0 +1,49 @@
# 73-dintel-quotation-mgr
> **Agent #73** | `dintel-quotation-mgr` v1.0.0 | D.intelligence Agent Corps
Quotation Manager -- the most complex skill in the D.intelligence Agent Corps. Uses a multi-agent sub-system (Scope, Resource, Pricing, Output) to generate professional quotations and estimates for D.intelligence service modules.
## Autonomy Level
**Draft & Wait** -- Generates a quote draft in branded Excel (.xlsx), then waits for Andrew's review. Andrew reviews in Google Sheets and leaves cell comments for feedback. The agent reads feedback and learns patterns over time via `shared/feedback-log.md`.
## Multi-Agent Sub-System
| Sub-Agent | Role |
|-----------|------|
| **Scope Agent** | Analyzes client requirements, maps to service modules (A1--G4) |
| **Resource Agent** | Estimates effort hours, timeline, team allocation |
| **Pricing Agent** | Calculates pricing using module rates, package discounts, discount policies |
| **Output Generator** | Produces branded Excel .xlsx file using `dintel-shared/src/dintel/excel.py` |
## Directory Structure
```
73-dintel-quotation-mgr/
├── code/
│ ├── CLAUDE.md # Claude Code instructions
│ └── scripts/
│ └── generate_quotation.py # Excel generation script stub
├── desktop/
│ └── SKILL.md # Full skill definition (sub-agents, pricing, workflow)
├── shared/
│ ├── pricing-reference.md # Pricing quick reference
│ └── feedback-log.md # Learning from Andrew's corrections
└── README.md # This file
```
## Key References
- Brand Guide: `../../dintel-shared/src/dintel/brand.py`
- Excel utilities: `../../dintel-shared/src/dintel/excel.py`
- Service Map: `/Users/ourdigital/Documents/D.intelligence Service Package/00_SERVICE-MAP.md`
- Pricing Packages: `/Users/ourdigital/Documents/D.intelligence Service Package/06_PRICING-PACKAGES.md`
## Universal Guardrails
1. Never send to clients without Andrew's approval
2. Never delete -- always archive
3. **Never commit pricing without Andrew's sign-off** (CRITICAL)
4. Korean-first, jargon = 한글(English) bilingual notation
5. Never cross-reference client data without consent

View File

@@ -0,0 +1,65 @@
# D.intelligence Quotation Manager
> **Agent #73** | `dintel-quotation-mgr` v1.0.0 | D.intelligence Agent Corps
Generate professional quotations and estimates for D.intelligence service modules using a multi-agent sub-system (Scope, Resource, Pricing, Output).
## Agent Corps Context
- **Agent #73** -- Quotation Manager (Multi-Agent)
- **Collaborates with**: Agent #70 (Brand Guardian), Agent #71 (Brand Editor)
- **Shared constants**: `dintel-shared/src/dintel/brand.py` (colors, terminology, style tokens)
- **Excel utilities**: `dintel-shared/src/dintel/excel.py` (branded workbook generation)
## Universal Guardrails
1. **Never send to clients without Andrew's approval** -- All quotations require Andrew's review.
2. **Never delete -- always archive** -- Move outdated quotes to archive; never permanently delete.
3. **Never commit pricing without Andrew's sign-off** -- CRITICAL. All pricing is draft until approved.
4. **Korean-first, bilingual notation** -- Korean primary; jargon uses 한글(English) notation on first use.
5. **Never cross-reference client data without consent** -- Client data is siloed by account.
## Autonomy Level: Draft & Wait
This agent generates quotation drafts and STOPS. It never finalizes or sends quotes without Andrew's explicit approval. All generated files are marked as DRAFT with yellow-highlighted price cells.
## Workflow
1. Receive client brief
2. Run Scope Agent -> map requirements to modules (A1--G4)
3. Run Resource Agent -> estimate hours, timeline, team
4. Run Pricing Agent -> calculate prices, apply discounts
5. Run Output Generator -> produce branded .xlsx
6. **STOP** -- Notify Andrew for review
7. Process feedback from Google Sheets comments -> update `shared/feedback-log.md`
8. Revise if requested, then await final approval
## Quick Reference
- **Full skill definition**: `../desktop/SKILL.md` (sub-agents, pricing tables, discount rules, output format)
- **Pricing reference**: `../shared/pricing-reference.md` and `../../dintel-shared/references/pricing-reference.md`
- **Feedback log**: `../shared/feedback-log.md`
- **Generate script**: `scripts/generate_quotation.py`
- **Excel utilities**: `../../dintel-shared/src/dintel/excel.py`
## Quotation Template Library
Reference templates are available in `shared/quotation-templates/`:
| Template | Filename | Description |
|----------|----------|-------------|
| Standard 2026 | `D.intelligence-표준 견적서_2026.xlsx` | Current standard quotation template |
| GA Analytics | `[템플릿] D.intelligence-Google Analytics-표준 견적서.xlsx` | GA4/GTM service quotes |
| Content Marketing | `[템플릿] D.intelligence-콘텐츠 마케팅-표준 견적서 2026.xlsx` | Content marketing quotes |
| GA Training | `[템플릿] D.intelligence-디지털 마케터를 위한 GA활용-중급-견적 _ 커리큘럼.xlsx` | Training/workshop quotes |
Use these as structural references for sheet layout, column headers, and formatting conventions when generating new quotations.
## Key Rules
- Quotation reference format: `DI-Q-{YYYYMMDD}-{NNN}`
- All prices are VAT 별도
- Discounts: apply highest single base discount; 재계약 10% stacks on top; never exceed 35% total
- Payment terms default: 착수금 50% / 완료 후 50%
- Validity: 견적 유효기간 30일
- File naming: `DI-Q-{YYYYMMDD}-{NNN}_{ClientName}_DRAFT.xlsx`

View File

@@ -0,0 +1,355 @@
"""
D.intelligence Quotation Generator
Agent #73 - dintel-quotation-mgr
Generates branded Excel .xlsx quotation files using dintel-shared utilities.
This is a stub script -- extend with full implementation as needed.
Usage:
python generate_quotation.py --client "고객사명" --modules A3,T6 --output ./output/
Dependencies:
- dintel-shared (../../dintel-shared/)
- openpyxl
"""
from __future__ import annotations
import argparse
import sys
from dataclasses import dataclass, field
from datetime import date, timedelta
from pathlib import Path
from typing import Optional
# ---------------------------------------------------------------------------
# Pricing data (mirrors shared/pricing-reference.md)
# ---------------------------------------------------------------------------
MODULE_PRICING: dict[str, dict] = {
# Analysis (진단)
"A1": {"name": "비즈니스·브랜드 진단", "duration": "2-3주", "min": 3_000_000, "max": 5_000_000, "phase": "Analysis"},
"A2": {"name": "고객·소비자 분석", "duration": "3-4주", "min": 4_000_000, "max": 7_000_000, "phase": "Analysis"},
"A3": {"name": "데이터 분석 (웹·앱)", "duration": "3-5주", "min": 4_000_000, "max": 8_000_000, "phase": "Analysis"},
"A4": {"name": "디지털 마케팅 진단", "duration": "2-4주", "min": 3_000_000, "max": 6_000_000, "phase": "Analysis"},
"A5": {"name": "퍼포먼스 마케팅 진단", "duration": "2-3주", "min": 3_000_000, "max": 5_000_000, "phase": "Analysis"},
"A6": {"name": "운영·관리 진단", "duration": "2-3주", "min": 2_000_000, "max": 4_000_000, "phase": "Analysis"},
# Treatment (처방)
"T1": {"name": "브랜드 스토리텔링 & 가이드", "duration": "4-8주", "min": 5_000_000, "max": 12_000_000, "phase": "Treatment"},
"T2": {"name": "고객 접점 경험 최적화", "duration": "4-6주", "min": 4_000_000, "max": 8_000_000, "phase": "Treatment"},
"T3": {"name": "디지털 자산 통합관리", "duration": "4-8주", "min": 6_000_000, "max": 15_000_000, "phase": "Treatment"},
"T4": {"name": "콘텐츠 마케팅", "duration": "4-8주", "min": 4_000_000, "max": 10_000_000, "phase": "Treatment"},
"T5": {"name": "광고·전환 최적화", "duration": "3-6주", "min": 4_000_000, "max": 8_000_000, "phase": "Treatment"},
"T6": {"name": "Brand Visibility Treatment", "duration": "4-12주", "min": 5_000_000, "max": 15_000_000, "phase": "Treatment"},
"T7": {"name": "운영 시스템·자동화", "duration": "4-8주", "min": 4_000_000, "max": 10_000_000, "phase": "Treatment"},
# Growth (성장)
"G1": {"name": "퍼포먼스 마케팅", "duration": "월간", "min": 2_000_000, "max": 5_000_000, "phase": "Growth", "monthly": True},
"G2": {"name": "콘텐츠 마케팅 대행", "duration": "월간", "min": 3_000_000, "max": 6_000_000, "phase": "Growth", "monthly": True},
"G3": {"name": "모니터링·이슈관리", "duration": "월간", "min": 2_000_000, "max": 4_000_000, "phase": "Growth", "monthly": True},
"G4": {"name": "연간 계약·운영", "duration": "12개월", "min": 0, "max": 0, "phase": "Growth", "monthly": True},
}
COMPLEXITY_PERCENTILE = {
"standard": 0.30,
"complex": 0.60,
"enterprise": 0.90,
}
DISCOUNT_POLICIES = {
"multi_3plus": {"label": "3개 모듈 이상 동시 계약", "rate": 0.15},
"analysis_treatment": {"label": "Analysis → Treatment 연계", "rate": 0.20},
"full_cycle": {"label": "Full cycle (A→T→G)", "rate": 0.25},
"g4_annual": {"label": "G4 연간 계약", "rate": 0.20},
"renewal": {"label": "재계약 (기존 고객)", "rate": 0.10, "stackable": True},
}
# ---------------------------------------------------------------------------
# Data classes
# ---------------------------------------------------------------------------
@dataclass
class LineItem:
code: str
name: str
phase: str
complexity: str = "standard"
base_price: int = 0
months: int = 1 # for Growth modules
subtotal: int = 0
@dataclass
class QuotationDraft:
ref: str = ""
client_name: str = ""
industry: str = ""
date_created: date = field(default_factory=date.today)
validity_days: int = 30
line_items: list[LineItem] = field(default_factory=list)
subtotal: int = 0
discount_label: str = ""
discount_rate: float = 0.0
discount_amount: int = 0
total_before_vat: int = 0
is_renewal: bool = False
# ---------------------------------------------------------------------------
# Pricing logic
# ---------------------------------------------------------------------------
def calculate_price(code: str, complexity: str = "standard") -> int:
"""Calculate module price based on complexity percentile within range."""
module = MODULE_PRICING.get(code)
if not module:
raise ValueError(f"Unknown module code: {code}")
pct = COMPLEXITY_PERCENTILE.get(complexity, 0.30)
price_range = module["max"] - module["min"]
return int(module["min"] + price_range * pct)
def determine_discount(line_items: list[LineItem], is_renewal: bool = False) -> tuple[str, float]:
"""Determine the highest applicable base discount, plus renewal if applicable."""
phases = {item.phase for item in line_items}
num_modules = len(line_items)
has_g4 = any(item.code == "G4" for item in line_items)
# Determine base discount (highest wins)
base_label = ""
base_rate = 0.0
if phases >= {"Analysis", "Treatment", "Growth"}:
base_label = DISCOUNT_POLICIES["full_cycle"]["label"]
base_rate = DISCOUNT_POLICIES["full_cycle"]["rate"]
elif "Analysis" in phases and "Treatment" in phases:
base_label = DISCOUNT_POLICIES["analysis_treatment"]["label"]
base_rate = DISCOUNT_POLICIES["analysis_treatment"]["rate"]
elif has_g4:
base_label = DISCOUNT_POLICIES["g4_annual"]["label"]
base_rate = DISCOUNT_POLICIES["g4_annual"]["rate"]
elif num_modules >= 3:
base_label = DISCOUNT_POLICIES["multi_3plus"]["label"]
base_rate = DISCOUNT_POLICIES["multi_3plus"]["rate"]
# Stack renewal discount
if is_renewal and base_rate > 0:
base_label += " + 재계약"
base_rate = min(base_rate + 0.10, 0.35)
elif is_renewal:
base_label = DISCOUNT_POLICIES["renewal"]["label"]
base_rate = 0.10
return base_label, base_rate
def build_quotation(
client_name: str,
modules: list[tuple[str, str]], # [(code, complexity), ...]
industry: str = "",
is_renewal: bool = False,
growth_months: int = 3,
) -> QuotationDraft:
"""Build a complete quotation draft."""
today = date.today()
ref = f"DI-Q-{today.strftime('%Y%m%d')}-001"
draft = QuotationDraft(
ref=ref,
client_name=client_name,
industry=industry,
date_created=today,
is_renewal=is_renewal,
)
for code, complexity in modules:
module = MODULE_PRICING[code]
price = calculate_price(code, complexity)
months = growth_months if module.get("monthly") else 1
item = LineItem(
code=code,
name=module["name"],
phase=module["phase"],
complexity=complexity,
base_price=price,
months=months,
subtotal=price * months,
)
draft.line_items.append(item)
draft.subtotal = sum(item.subtotal for item in draft.line_items)
draft.discount_label, draft.discount_rate = determine_discount(draft.line_items, is_renewal)
draft.discount_amount = int(draft.subtotal * draft.discount_rate)
draft.total_before_vat = draft.subtotal - draft.discount_amount
return draft
# ---------------------------------------------------------------------------
# Excel generation (stub -- requires openpyxl and dintel-shared)
# ---------------------------------------------------------------------------
def generate_xlsx(draft: QuotationDraft, output_dir: Path) -> Path:
"""Generate branded .xlsx quotation file.
TODO: Implement full branded workbook using dintel-shared/src/dintel/excel.py.
This stub creates a basic workbook structure.
"""
try:
from openpyxl import Workbook
from openpyxl.styles import Alignment, Font, PatternFill
except ImportError:
print("ERROR: openpyxl is required. Install with: pip install openpyxl", file=sys.stderr)
sys.exit(1)
wb = Workbook()
# -- Sheet 1: Cover --
ws_cover = wb.active
ws_cover.title = "표지"
ws_cover["B2"] = "D.intelligence :: SMART Marketing Clinic ::"
ws_cover["B2"].font = Font(name="Pretendard", size=16, bold=True)
ws_cover["B4"] = "견적서 (Quotation)"
ws_cover["B4"].font = Font(name="Pretendard", size=24, bold=True)
ws_cover["B6"] = f"고객사: {draft.client_name}"
ws_cover["B7"] = f"업종: {draft.industry}"
ws_cover["B8"] = f"견적번호: {draft.ref}"
ws_cover["B9"] = f"작성일: {draft.date_created.isoformat()}"
ws_cover["B10"] = f"유효기간: {(draft.date_created + timedelta(days=draft.validity_days)).isoformat()}"
ws_cover["B12"] = "DRAFT -- 검토 대기"
ws_cover["B12"].font = Font(color="FF0000", bold=True, size=14)
# -- Sheet 2: Scope --
ws_scope = wb.create_sheet("서비스 범위")
headers = ["모듈 코드", "모듈명", "Phase", "복잡도", "비고"]
for col, header in enumerate(headers, 1):
cell = ws_scope.cell(row=1, column=col, value=header)
cell.font = Font(bold=True)
for row, item in enumerate(draft.line_items, 2):
ws_scope.cell(row=row, column=1, value=item.code)
ws_scope.cell(row=row, column=2, value=item.name)
ws_scope.cell(row=row, column=3, value=item.phase)
ws_scope.cell(row=row, column=4, value=item.complexity)
# -- Sheet 3: Timeline (placeholder) --
ws_timeline = wb.create_sheet("일정")
ws_timeline["A1"] = "Phase"
ws_timeline["B1"] = "Module"
ws_timeline["C1"] = "Duration"
ws_timeline["A1"].font = Font(bold=True)
ws_timeline["B1"].font = Font(bold=True)
ws_timeline["C1"].font = Font(bold=True)
for row, item in enumerate(draft.line_items, 2):
ws_timeline.cell(row=row, column=1, value=item.phase)
ws_timeline.cell(row=row, column=2, value=f"{item.code} {item.name}")
module = MODULE_PRICING[item.code]
ws_timeline.cell(row=row, column=3, value=module["duration"])
# -- Sheet 4: Pricing --
ws_pricing = wb.create_sheet("견적 내역")
draft_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid")
price_headers = ["모듈 코드", "모듈명", "단가 (원)", "수량/개월", "소계 (원)"]
for col, header in enumerate(price_headers, 1):
cell = ws_pricing.cell(row=1, column=col, value=header)
cell.font = Font(bold=True)
for row, item in enumerate(draft.line_items, 2):
ws_pricing.cell(row=row, column=1, value=item.code)
ws_pricing.cell(row=row, column=2, value=item.name)
price_cell = ws_pricing.cell(row=row, column=3, value=item.base_price)
price_cell.fill = draft_fill
price_cell.number_format = "#,##0"
ws_pricing.cell(row=row, column=4, value=item.months)
subtotal_cell = ws_pricing.cell(row=row, column=5, value=item.subtotal)
subtotal_cell.fill = draft_fill
subtotal_cell.number_format = "#,##0"
summary_row = len(draft.line_items) + 3
ws_pricing.cell(row=summary_row, column=4, value="소계").font = Font(bold=True)
ws_pricing.cell(row=summary_row, column=5, value=draft.subtotal).number_format = "#,##0"
if draft.discount_rate > 0:
summary_row += 1
ws_pricing.cell(row=summary_row, column=3, value=draft.discount_label)
ws_pricing.cell(row=summary_row, column=4, value=f"-{int(draft.discount_rate * 100)}%")
disc_cell = ws_pricing.cell(row=summary_row, column=5, value=-draft.discount_amount)
disc_cell.number_format = "#,##0"
disc_cell.font = Font(color="FF0000")
summary_row += 1
ws_pricing.cell(row=summary_row, column=4, value="합계 (VAT 별도)").font = Font(bold=True, size=12)
total_cell = ws_pricing.cell(row=summary_row, column=5, value=draft.total_before_vat)
total_cell.font = Font(bold=True, size=12)
total_cell.number_format = "#,##0"
total_cell.fill = draft_fill
summary_row += 1
ws_pricing.cell(row=summary_row, column=5, value="Andrew 검토 필요").font = Font(color="FF0000", italic=True)
# -- Sheet 5: Terms --
ws_terms = wb.create_sheet("계약 조건")
terms = [
("결제 조건", "착수금 50% / 완료 후 50%"),
("견적 유효기간", "발행일로부터 30일"),
("부가세", "별도 (10%)"),
("범위 변경", "서면 합의 후 별도 견적"),
("계약 해지", "착수 전 전액 환불 / 착수 후 진행분 정산"),
("", ""),
("D.intelligence", "SMART Marketing Clinic"),
("Website", "dintelligence.co.kr"),
("담당자", "Andrew Yim"),
]
for row, (label, value) in enumerate(terms, 1):
ws_terms.cell(row=row, column=1, value=label).font = Font(bold=True)
ws_terms.cell(row=row, column=2, value=value)
# Save
output_dir.mkdir(parents=True, exist_ok=True)
filename = f"{draft.ref}_{draft.client_name.replace(' ', '_')}_DRAFT.xlsx"
filepath = output_dir / filename
wb.save(filepath)
return filepath
# ---------------------------------------------------------------------------
# CLI entry point
# ---------------------------------------------------------------------------
def main():
parser = argparse.ArgumentParser(description="D.intelligence Quotation Generator")
parser.add_argument("--client", required=True, help="Client name (고객사명)")
parser.add_argument("--industry", default="", help="Client industry (업종)")
parser.add_argument("--modules", required=True, help="Comma-separated module codes (e.g., A3,T6,G2)")
parser.add_argument("--complexity", default="standard", choices=["standard", "complex", "enterprise"],
help="Default complexity tier for all modules")
parser.add_argument("--renewal", action="store_true", help="Existing client (재계약)")
parser.add_argument("--growth-months", type=int, default=3, help="Number of months for Growth modules")
parser.add_argument("--output", default="./output", help="Output directory")
args = parser.parse_args()
module_list = [(code.strip(), args.complexity) for code in args.modules.split(",")]
draft = build_quotation(
client_name=args.client,
modules=module_list,
industry=args.industry,
is_renewal=args.renewal,
growth_months=args.growth_months,
)
filepath = generate_xlsx(draft, Path(args.output))
print(f"Quotation draft generated: {filepath}")
print(f" Reference: {draft.ref}")
print(f" Client: {draft.client_name}")
print(f" Modules: {', '.join(item.code for item in draft.line_items)}")
print(f" Subtotal: {draft.subtotal:,}")
if draft.discount_rate > 0:
print(f" Discount: {draft.discount_label} (-{int(draft.discount_rate * 100)}%, -{draft.discount_amount:,}원)")
print(f" Total (VAT 별도): {draft.total_before_vat:,}")
print()
print("STATUS: DRAFT -- Andrew 검토 대기")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,399 @@
---
name: dintel-quotation-mgr
version: 1.0.0
agent-id: "73"
agent-corps: D.intelligence Agent Corps
description: |
Quotation Manager for D.intelligence. Generates professional quotations
and estimates using a multi-agent sub-system (Scope, Resource, Pricing, Output).
Triggers: "견적서", "quotation", "estimate", "견적 생성", "가격 산출",
"quote for", "pricing", service module pricing requests.
autonomy: draft-and-wait
---
# D.intelligence Quotation Manager
> **Agent #73** | `dintel-quotation-mgr` v1.0.0 | D.intelligence Agent Corps
Generate professional quotations and estimates for D.intelligence service modules using a multi-agent sub-system. Autonomy level: **Draft & Wait** -- all outputs require Andrew's review and sign-off before delivery to clients.
---
## Agent Corps Context
- **Agent #73** -- Quotation Manager (Multi-Agent)
- **Collaborates with**: Agent #70 (Brand Guardian) for brand compliance, Agent #71 (Brand Editor) for cover letter copy
- **Shared constants**: `dintel-shared/src/dintel/brand.py` (colors, terminology)
- **Excel utilities**: `dintel-shared/src/dintel/excel.py` (branded workbook generation)
---
## Universal Guardrails
1. **Never send to clients without Andrew's approval** -- All quotations require Andrew's review.
2. **Never delete -- always archive** -- Move outdated quotes to archive; never permanently delete.
3. **Never commit pricing without Andrew's sign-off** -- CRITICAL for this agent. All pricing is draft until approved.
4. **Korean-first, bilingual notation** -- Korean primary; jargon uses 한글(English) notation on first use.
5. **Never cross-reference client data without consent** -- Client data is siloed by account.
---
## Multi-Agent Sub-System
This skill orchestrates 4 sub-agents in sequence. Each sub-agent produces a structured output that feeds the next.
### Sub-Agent 1: Scope Agent
**Purpose**: Analyze client requirements and map them to D.intelligence service modules.
**Inputs**:
- Client brief or requirements description (text, email, or meeting notes)
- Client industry and company size (if known)
- Any specific constraints or preferences
**Process**:
1. Parse the client's needs into discrete workstreams
2. Map each workstream to one or more service modules (A1--A6, T1--T7, G1--G4)
3. Identify module dependencies (e.g., A3 is prerequisite for T6)
4. Flag any ambiguities that need clarification from Andrew
5. Check for pre-built package fit (Starter, Standard, Premium, SEO Intensive)
**Output** (structured):
```yaml
scope:
client_name: "고객사명"
industry: "업종"
modules:
- code: "A3"
name: "데이터 분석 (웹·앱)"
rationale: "웹사이트 트래픽 및 전환 분석 필요"
complexity: "standard | complex | enterprise"
- code: "T6"
name: "Brand Visibility Treatment"
rationale: "검색 노출 최적화 요청"
complexity: "complex"
dependencies:
- from: "A3"
to: "T6"
type: "prerequisite"
package_fit: "SEO Intensive" # or null
ambiguities:
- "콘텐츠 제작 범위 확인 필요 (블로그만 vs 소셜 포함)"
```
### Sub-Agent 2: Resource Agent
**Purpose**: Estimate effort hours, project timeline, and team allocation.
**Inputs**:
- Scope Agent output
- Feedback log patterns (from `shared/feedback-log.md`)
**Process**:
1. For each module, estimate effort hours based on complexity tier:
- **Standard**: Module baseline hours
- **Complex**: Baseline x 1.5
- **Enterprise**: Baseline x 2.0
2. Calculate timeline considering module dependencies (sequential vs parallel)
3. Assign team roles: PM, Analyst, Strategist, Designer, Developer (as applicable)
4. Apply learned adjustments from feedback log
**Baseline Effort Hours** (per module):
| Module | Standard (hours) | Duration |
|--------|-----------------|----------|
| A1 비즈니스·브랜드 진단 | 40--60 | 2--3주 |
| A2 고객·소비자 분석 | 60--80 | 3--4주 |
| A3 데이터 분석 (웹·앱) | 60--100 | 3--5주 |
| A4 디지털 마케팅 진단 | 40--80 | 2--4주 |
| A5 퍼포먼스 마케팅 진단 | 40--60 | 2--3주 |
| A6 운영·관리 진단 | 40--60 | 2--3주 |
| T1 브랜드 스토리텔링 & 가이드 | 80--160 | 4--8주 |
| T2 고객 접점 경험 최적화 | 60--120 | 4--6주 |
| T3 디지털 자산 통합관리 | 80--160 | 4--8주 |
| T4 콘텐츠 마케팅 | 60--120 | 4--8주 |
| T5 광고·전환 최적화 | 60--100 | 3--6주 |
| T6 Brand Visibility Treatment | 80--200 | 4--12주 |
| T7 운영 시스템·자동화 | 60--120 | 4--8주 |
| G1 퍼포먼스 마케팅 | 40--80/월 | 월간 |
| G2 콘텐츠 마케팅 대행 | 60--100/월 | 월간 |
| G3 모니터링·이슈관리 | 40--60/월 | 월간 |
| G4 연간 계약·운영 | 별도 협의 | 12개월 |
**Output** (structured):
```yaml
resources:
total_hours: 220
timeline:
total_weeks: 10
phases:
- phase: "Analysis"
weeks: "1--4"
modules: ["A3", "A4"]
parallel: true
- phase: "Treatment"
weeks: "5--10"
modules: ["T6"]
team:
- role: "PM"
allocation: "20%"
- role: "SEO Analyst"
allocation: "80%"
- role: "Content Strategist"
allocation: "40%"
```
### Sub-Agent 3: Pricing Agent
**Purpose**: Calculate pricing using module rates, apply discount policies, and produce a pricing breakdown.
**Inputs**:
- Scope Agent output (modules, package fit)
- Resource Agent output (hours, timeline)
- Pricing reference (`shared/pricing-reference.md`)
- Feedback log adjustments
**Process**:
1. Look up base price range for each module
2. Position within range based on complexity tier:
- Standard: 30th percentile of range
- Complex: 60th percentile
- Enterprise: 90th percentile
3. Check discount eligibility (see Discount Policies below)
4. Apply highest applicable discount (discounts do NOT stack, except 재계약)
5. Calculate subtotal, discount amount, and total (VAT 별도)
6. Compare against feedback log for similar scope patterns
**Module Pricing Table** (VAT 별도):
| Module | Duration | Price Range |
|--------|----------|-------------|
| **A1** 비즈니스·브랜드 진단 | 2--3주 | 300--500만원 |
| **A2** 고객·소비자 분석 | 3--4주 | 400--700만원 |
| **A3** 데이터 분석 (웹·앱) | 3--5주 | 400--800만원 |
| **A4** 디지털 마케팅 진단 | 2--4주 | 300--600만원 |
| **A5** 퍼포먼스 마케팅 진단 | 2--3주 | 300--500만원 |
| **A6** 운영·관리 진단 | 2--3주 | 200--400만원 |
| **T1** 브랜드 스토리텔링 & 가이드 | 4--8주 | 500--1,200만원 |
| **T2** 고객 접점 경험 최적화 | 4--6주 | 400--800만원 |
| **T3** 디지털 자산 통합관리 | 4--8주 | 600--1,500만원 |
| **T4** 콘텐츠 마케팅 | 4--8주 | 400--1,000만원 |
| **T5** 광고·전환 최적화 | 3--6주 | 400--800만원 |
| **T6** Brand Visibility Treatment | 4--12주 | 500--1,500만원 |
| **T7** 운영 시스템·자동화 | 4--8주 | 400--1,000만원 |
| **G1** 퍼포먼스 마케팅 | 월간 | 200--500만원/월 |
| **G2** 콘텐츠 마케팅 대행 | 월간 | 300--600만원/월 |
| **G3** 모니터링·이슈관리 | 월간 | 200--400만원/월 |
| **G4** 연간 계약·운영 | 12개월 | 별도 협의 |
**Discount Policies**:
| Condition | Discount | Stackable |
|-----------|----------|-----------|
| 3개 모듈 이상 동시 계약 | 15% | No (base) |
| Analysis -> Treatment 연계 | 20% | No (base) |
| Full cycle (Analysis -> Treatment -> Growth) | 25% | No (base) |
| G4 연간 계약 | 월 단가 20% 할인 | No (base) |
| 재계약 (기존 고객) | 10% 추가 할인 | Yes (stacks on top of base) |
> **Rule**: Apply the single highest base discount. If the client is a 재계약 customer, add 10% on top. Discounts never exceed 35% total.
**Pre-built Packages** (pre-discounted):
| Package | Modules | Price Range | Discount |
|---------|---------|-------------|----------|
| **Starter** | A3 + A4 + A5 | 800--1,500만원 | 15% |
| **Standard** | Starter + T3/T5/T6 택1 | 1,500--2,800만원 | 20% |
| **Premium** | Starter + 2 Treatment + 1 Growth (3개월) | 3,000--5,000만원 | 25% |
| **SEO Intensive** | A3 + T6 + G2 (3개월) | 2,000--3,500만원 | 20% |
**Output** (structured):
```yaml
pricing:
line_items:
- module: "A3"
name: "데이터 분석 (웹·앱)"
base_price: 5600000 # 560만원 (complex, 60th percentile)
quantity: 1
- module: "T6"
name: "Brand Visibility Treatment"
base_price: 9000000 # 900만원 (complex)
quantity: 1
subtotal: 14600000
discount:
type: "Analysis -> Treatment 연계"
rate: 0.20
amount: 2920000
total_before_vat: 11680000
vat_note: "VAT 별도"
package_applied: null # or package name
```
### Sub-Agent 4: Output Generator
**Purpose**: Produce a branded Excel .xlsx file ready for Andrew's review.
**Inputs**:
- All outputs from Sub-Agents 1--3
- Brand assets from `dintel-shared/src/dintel/brand.py`
- Excel utilities from `dintel-shared/src/dintel/excel.py`
**Process**:
1. Create workbook with branded styling (D.intelligence colors, fonts, logo)
2. Generate all sheets (see Output Format below)
3. Save as `.xlsx` to the designated output directory
4. Notify Andrew that the draft is ready for review
**Excel Output Format**:
The generated `.xlsx` file contains the following sheets:
#### Sheet 1: 표지 (Cover)
- D.intelligence logo and brand header
- 견적서 (Quotation) title
- Client name and date
- Quotation reference number: `DI-Q-{YYYYMMDD}-{NNN}`
- Validity period: 견적 유효기간 30일
#### Sheet 2: 서비스 범위 (Scope)
- Table of selected modules with:
- Module code and name
- Description / rationale
- Complexity tier
- Dependencies noted
#### Sheet 3: 일정 (Timeline)
- Gantt-style timeline with:
- Phase breakdown (Analysis / Treatment / Growth)
- Module start/end weeks
- Milestones and deliverables
#### Sheet 4: 견적 내역 (Pricing)
- Detailed pricing table:
- Module code | Module name | Base price | Quantity | Subtotal
- Discount row (type, rate, amount)
- Total before VAT
- VAT note
- Grand total placeholder (for Andrew to finalize)
- **IMPORTANT**: All price cells must be clearly marked as DRAFT
#### Sheet 5: 계약 조건 (Terms)
- Payment terms: 착수금 50% / 완료 후 50% (standard)
- Validity: 견적 유효기간 30일
- Scope change policy
- Cancellation terms
- D.intelligence contact information
---
## Workflow: Draft & Wait
```
[1] Client brief received
|
[2] Scope Agent analyzes requirements
|
[3] Resource Agent estimates effort & timeline
|
[4] Pricing Agent calculates costs & discounts
|
[5] Output Generator creates branded .xlsx
|
[6] *** STOP -- Draft Ready ***
|
Andrew reviews in Google Sheets
Andrew leaves cell comments (adjustments, notes)
|
[7] Agent reads feedback -> updates feedback-log.md
|
[8] If revisions needed -> loop back to relevant sub-agent
|
[9] Andrew approves -> quote finalized
```
### Draft Markers
All generated quotations include these markers until Andrew approves:
- File name suffix: `_DRAFT`
- Watermark text in header: "DRAFT -- 검토 대기"
- All price cells highlighted in yellow
- Comment on total cell: "Andrew 검토 필요"
---
## Feedback Learning Loop
### How It Works
1. Andrew opens the `.xlsx` in Google Sheets
2. Andrew leaves cell comments with feedback:
- Price adjustment: "A3는 이 고객에게 520만원이 적절" (price override)
- Scope change: "T4 추가 필요" (add module) or "A6 제외" (remove module)
- Timeline note: "T6는 8주 필요" (timeline adjustment)
- General note: "이 업종은 보통 Standard 패키지 적용" (pattern note)
3. Agent reads comments and logs to `shared/feedback-log.md`:
- Date, client industry, original vs adjusted values, reason
4. Over time, the feedback log builds a pattern database:
- Industry-specific pricing tendencies
- Common module combinations
- Andrew's preferred discount thresholds
### Feedback Log Format
See `shared/feedback-log.md` for the structured format. Each entry records:
- Date and quotation reference
- Client industry
- Adjustment type (price / scope / timeline / discount)
- Original value and adjusted value
- Andrew's reasoning (from comment text)
---
## Invocation
### Generate a New Quotation
Provide the client brief and the agent will run all 4 sub-agents:
```
Generate a quotation for [Client Name].
Requirements:
- [Requirement 1]
- [Requirement 2]
- [Requirement 3]
Industry: [업종]
Company size: [중소/중견/대기업]
Existing client: [Yes/No]
```
### Review Feedback
After Andrew has reviewed in Google Sheets:
```
Review feedback for quotation DI-Q-20260308-001.
Update feedback-log.md with Andrew's comments.
```
### Revise a Quotation
```
Revise quotation DI-Q-20260308-001 based on Andrew's feedback.
```
---
## Key References
| Resource | Path |
|----------|------|
| Brand constants | `../../dintel-shared/src/dintel/brand.py` |
| Excel utilities | `../../dintel-shared/src/dintel/excel.py` |
| Pricing reference | `../shared/pricing-reference.md` |
| Feedback log | `../shared/feedback-log.md` |
| Service Map | `/Users/ourdigital/Documents/D.intelligence Service Package/00_SERVICE-MAP.md` |
| Pricing Packages | `/Users/ourdigital/Documents/D.intelligence Service Package/06_PRICING-PACKAGES.md` |
| Brand Guide | `/Users/ourdigital/Documents/D.intelligence Service Package/08_BRAND-GUIDE-v1.1.md` |
| Generate script | `../code/scripts/generate_quotation.py` |

View File

@@ -0,0 +1,54 @@
# Feedback Log
> Quotation Manager learning log -- records Andrew's corrections and adjustments.
> Over time, this log builds patterns for more accurate estimates.
---
## Log Format
Each entry follows this structure:
```yaml
- date: "YYYY-MM-DD"
quotation_ref: "DI-Q-YYYYMMDD-NNN"
client_industry: "업종"
adjustments:
- type: "price | scope | timeline | discount | terms"
module: "A3" # or null for general
original: "560만원"
adjusted: "520만원"
reason: "Andrew's comment text"
pattern_note: "Optional generalized learning"
```
---
## Entries
_No entries yet. This log will be populated as Andrew reviews quotation drafts._
<!--
Example entry (for reference):
- date: "2026-03-08"
quotation_ref: "DI-Q-20260308-001"
client_industry: "이커머스"
adjustments:
- type: "price"
module: "A3"
original: "560만원"
adjusted: "520만원"
reason: "이커머스 업종은 A3 데이터 분석 범위가 표준보다 좁음"
- type: "scope"
module: "T4"
original: null
adjusted: "추가"
reason: "콘텐츠 마케팅 포함 필요"
- type: "discount"
module: null
original: "20%"
adjusted: "25%"
reason: "Full cycle 계약 확정으로 할인율 상향"
pattern_note: "이커머스 업종은 A3 단가를 range 하단에 가깝게 책정"
-->

View File

@@ -0,0 +1,82 @@
# Pricing Quick Reference
> D.intelligence Service Module Pricing | VAT 별도
---
## Individual Module Pricing
### Analysis (진단) -- Phase 1
| Code | Module | Duration | Price Range |
|------|--------|----------|-------------|
| A1 | 비즈니스·브랜드 진단 | 2--3주 | 300--500만원 |
| A2 | 고객·소비자 분석 | 3--4주 | 400--700만원 |
| A3 | 데이터 분석 (웹·앱) | 3--5주 | 400--800만원 |
| A4 | 디지털 마케팅 진단 | 2--4주 | 300--600만원 |
| A5 | 퍼포먼스 마케팅 진단 | 2--3주 | 300--500만원 |
| A6 | 운영·관리 진단 | 2--3주 | 200--400만원 |
### Treatment (처방) -- Phase 2
| Code | Module | Duration | Price Range |
|------|--------|----------|-------------|
| T1 | 브랜드 스토리텔링 & 가이드 | 4--8주 | 500--1,200만원 |
| T2 | 고객 접점 경험 최적화 | 4--6주 | 400--800만원 |
| T3 | 디지털 자산 통합관리 | 4--8주 | 600--1,500만원 |
| T4 | 콘텐츠 마케팅 | 4--8주 | 400--1,000만원 |
| T5 | 광고·전환 최적화 | 3--6주 | 400--800만원 |
| T6 | Brand Visibility Treatment | 4--12주 | 500--1,500만원 |
| T7 | 운영 시스템·자동화 | 4--8주 | 400--1,000만원 |
### Growth (성장) -- Phase 3
| Code | Module | Duration | Price Range |
|------|--------|----------|-------------|
| G1 | 퍼포먼스 마케팅 | 월간 | 200--500만원/월 |
| G2 | 콘텐츠 마케팅 대행 | 월간 | 300--600만원/월 |
| G3 | 모니터링·이슈관리 | 월간 | 200--400만원/월 |
| G4 | 연간 계약·운영 | 12개월 | 별도 협의 |
---
## Complexity Pricing Position
| Tier | Percentile in Range | Multiplier (hours) |
|------|--------------------|--------------------|
| Standard | 30th percentile | 1.0x |
| Complex | 60th percentile | 1.5x |
| Enterprise | 90th percentile | 2.0x |
---
## Discount Policies
| Condition | Discount | Stackable |
|-----------|----------|-----------|
| 3개 모듈 이상 동시 계약 | 15% | No (base) |
| Analysis -> Treatment 연계 | 20% | No (base) |
| Full cycle (Analysis -> Treatment -> Growth) | 25% | No (base) |
| G4 연간 계약 | 월 단가 20% 할인 | No (base) |
| 재계약 (기존 고객) | 10% 추가 할인 | Yes (stacks on base) |
**Rule**: Apply the single highest base discount. 재계약 stacks on top. Max total discount: 35%.
---
## Pre-built Packages
| Package | Modules | Price Range | Discount |
|---------|---------|-------------|----------|
| Starter | A3 + A4 + A5 | 800--1,500만원 | 15% |
| Standard | Starter + T3/T5/T6 택1 | 1,500--2,800만원 | 20% |
| Premium | Starter + 2 Treatment + 1 Growth (3개월) | 3,000--5,000만원 | 25% |
| SEO Intensive | A3 + T6 + G2 (3개월) | 2,000--3,500만원 | 20% |
---
## Standard Terms
- **Payment**: 착수금 50% / 완료 후 50%
- **Validity**: 견적 유효기간 30일
- **VAT**: 별도 (10%)