[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6FK0P9J2BZH2QMNDPFDPNMK":3,"skill-same:01M6FK0P9J2BZH2QMNDPFDPNMK":65},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":32,"linkOnly":33,"markdownContent":34,"markdownBody":35,"frontMatter":36,"refName":38,"commitSha":39,"skillDirectory":40,"forksCount":41,"repositoryHtmlUrl":42,"repositoryHomepageUrl":6,"ownerHtmlUrl":43,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":44,"install":45,"resources":58},"01M6FK0P9J2BZH2QMNDPFDPNMK","meeting-minutes-generator",null,"Generate structured construction meeting minutes. Track action items, decisions, and attendees.","kbarbel640-del\u002Fskills","kbarbel640-del","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F255315490?v=4","01M6CJPPQGCCESXMG3K7BBGQ5J","01M6CJPPX2PB2BCZERFVM2C2B3",1,"MIT","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fdatadrivenconstruction\u002Fmeeting-minutes-generator\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000034","行政与办公人员","PROFESSION","适用职业",[23,24,25,26,27,28,29,30,31],"meeting minutes","meeting minutes generator","generator","meeting","minutes","generate","decisions","meeting-minutes","structured","2026-11-10 10:12:30",false,"---\r\nslug: \"meeting-minutes-generator\"\r\ndisplay_name: \"Meeting Minutes Generator\"\r\ndescription: \"Generate structured construction meeting minutes. Track action items, decisions, and attendees.\"\r\n---\r\n\r\n# Meeting Minutes Generator\r\n\r\n## Business Case\r\n\r\n### Problem Statement\r\nMeeting documentation is inconsistent:\r\n- Minutes not standardized\r\n- Action items lost\r\n- Decisions not tracked\r\n- Poor distribution\r\n\r\n### Solution\r\nStandardized meeting minutes generation with action item tracking, decision logging, and automatic distribution.\r\n\r\n## Technical Implementation\r\n\r\n```python\r\nimport pandas as pd\r\nfrom datetime import datetime, date, timedelta\r\nfrom typing import Dict, Any, List, Optional\r\nfrom dataclasses import dataclass, field\r\nfrom enum import Enum\r\n\r\n\r\nclass MeetingType(Enum):\r\n    OAC = \"oac\"  # Owner-Architect-Contractor\r\n    PROGRESS = \"progress\"\r\n    COORDINATION = \"coordination\"\r\n    SAFETY = \"safety\"\r\n    PRECONSTRUCTION = \"preconstruction\"\r\n    CLOSEOUT = \"closeout\"\r\n    OTHER = \"other\"\r\n\r\n\r\nclass ActionStatus(Enum):\r\n    OPEN = \"open\"\r\n    IN_PROGRESS = \"in_progress\"\r\n    COMPLETE = \"complete\"\r\n    OVERDUE = \"overdue\"\r\n\r\n\r\nclass Priority(Enum):\r\n    HIGH = \"high\"\r\n    MEDIUM = \"medium\"\r\n    LOW = \"low\"\r\n\r\n\r\n@dataclass\r\nclass Attendee:\r\n    name: str\r\n    company: str\r\n    role: str\r\n    email: str\r\n    present: bool = True\r\n\r\n\r\n@dataclass\r\nclass ActionItem:\r\n    action_id: str\r\n    description: str\r\n    assigned_to: str\r\n    due_date: date\r\n    priority: Priority\r\n    status: ActionStatus\r\n    created_meeting: str\r\n    completed_date: Optional[date] = None\r\n    notes: str = \"\"\r\n\r\n\r\n@dataclass\r\nclass Decision:\r\n    decision_id: str\r\n    description: str\r\n    made_by: str\r\n    decision_date: date\r\n    impact: str = \"\"\r\n\r\n\r\n@dataclass\r\nclass DiscussionTopic:\r\n    topic_id: str\r\n    title: str\r\n    presenter: str\r\n    discussion: str\r\n    decisions: List[Decision] = field(default_factory=list)\r\n    actions: List[str] = field(default_factory=list)  # Action IDs\r\n\r\n\r\n@dataclass\r\nclass MeetingMinutes:\r\n    meeting_id: str\r\n    meeting_type: MeetingType\r\n    title: str\r\n    date: date\r\n    time_start: str\r\n    time_end: str\r\n    location: str\r\n    attendees: List[Attendee]\r\n    topics: List[DiscussionTopic]\r\n    action_items: List[ActionItem]\r\n    next_meeting: Optional[date] = None\r\n    prepared_by: str = \"\"\r\n    approved_by: str = \"\"\r\n\r\n\r\nclass MeetingMinutesGenerator:\r\n    \"\"\"Generate and track meeting minutes.\"\"\"\r\n\r\n    def __init__(self, project_name: str):\r\n        self.project_name = project_name\r\n        self.meetings: Dict[str, MeetingMinutes] = {}\r\n        self.all_actions: Dict[str, ActionItem] = {}\r\n        self._meeting_counter = 0\r\n        self._action_counter = 0\r\n        self._decision_counter = 0\r\n\r\n    def create_meeting(self, meeting_type: MeetingType, title: str,\r\n                      meeting_date: date, time_start: str, time_end: str,\r\n                      location: str) -> MeetingMinutes:\r\n        self._meeting_counter += 1\r\n        meeting_id = f\"MTG-{self._meeting_counter:04d}\"\r\n\r\n        meeting = MeetingMinutes(\r\n            meeting_id=meeting_id,\r\n            meeting_type=meeting_type,\r\n            title=title,\r\n            date=meeting_date,\r\n            time_start=time_start,\r\n            time_end=time_end,\r\n            location=location,\r\n            attendees=[],\r\n            topics=[],\r\n            action_items=[]\r\n        )\r\n        self.meetings[meeting_id] = meeting\r\n        return meeting\r\n\r\n    def add_attendee(self, meeting_id: str, name: str, company: str,\r\n                    role: str, email: str, present: bool = True):\r\n        if meeting_id not in self.meetings:\r\n            return\r\n        attendee = Attendee(name, company, role, email, present)\r\n        self.meetings[meeting_id].attendees.append(attendee)\r\n\r\n    def add_topic(self, meeting_id: str, title: str, presenter: str,\r\n                 discussion: str) -> str:\r\n        if meeting_id not in self.meetings:\r\n            return \"\"\r\n        topic_id = f\"{meeting_id}-T{len(self.meetings[meeting_id].topics) + 1:02d}\"\r\n        topic = DiscussionTopic(topic_id, title, presenter, discussion)\r\n        self.meetings[meeting_id].topics.append(topic)\r\n        return topic_id\r\n\r\n    def add_decision(self, meeting_id: str, topic_id: str, description: str,\r\n                    made_by: str, impact: str = \"\") -> Decision:\r\n        if meeting_id not in self.meetings:\r\n            return None\r\n\r\n        self._decision_counter += 1\r\n        decision_id = f\"DEC-{self._decision_counter:04d}\"\r\n\r\n        decision = Decision(\r\n            decision_id=decision_id,\r\n            description=description,\r\n            made_by=made_by,\r\n            decision_date=self.meetings[meeting_id].date,\r\n            impact=impact\r\n        )\r\n\r\n        # Find topic and add decision\r\n        for topic in self.meetings[meeting_id].topics:\r\n            if topic.topic_id == topic_id:\r\n                topic.decisions.append(decision)\r\n                break\r\n\r\n        return decision\r\n\r\n    def create_action(self, meeting_id: str, description: str, assigned_to: str,\r\n                     due_date: date, priority: Priority = Priority.MEDIUM) -> ActionItem:\r\n        if meeting_id not in self.meetings:\r\n            return None\r\n\r\n        self._action_counter += 1\r\n        action_id = f\"ACT-{self._action_counter:04d}\"\r\n\r\n        action = ActionItem(\r\n            action_id=action_id,\r\n            description=description,\r\n            assigned_to=assigned_to,\r\n            due_date=due_date,\r\n            priority=priority,\r\n            status=ActionStatus.OPEN,\r\n            created_meeting=meeting_id\r\n        )\r\n\r\n        self.meetings[meeting_id].action_items.append(action)\r\n        self.all_actions[action_id] = action\r\n        return action\r\n\r\n    def update_action_status(self, action_id: str, status: ActionStatus):\r\n        if action_id in self.all_actions:\r\n            self.all_actions[action_id].status = status\r\n            if status == ActionStatus.COMPLETE:\r\n                self.all_actions[action_id].completed_date = date.today()\r\n\r\n    def get_open_actions(self, assigned_to: str = None) -> List[ActionItem]:\r\n        actions = [a for a in self.all_actions.values()\r\n                  if a.status in [ActionStatus.OPEN, ActionStatus.IN_PROGRESS]]\r\n        if assigned_to:\r\n            actions = [a for a in actions if assigned_to.lower() in a.assigned_to.lower()]\r\n        return sorted(actions, key=lambda x: x.due_date)\r\n\r\n    def get_overdue_actions(self) -> List[ActionItem]:\r\n        today = date.today()\r\n        overdue = []\r\n        for action in self.all_actions.values():\r\n            if action.status in [ActionStatus.OPEN, ActionStatus.IN_PROGRESS]:\r\n                if action.due_date \u003C today:\r\n                    action.status = ActionStatus.OVERDUE\r\n                    overdue.append(action)\r\n        return overdue\r\n\r\n    def generate_minutes_document(self, meeting_id: str) -> str:\r\n        \"\"\"Generate formatted meeting minutes.\"\"\"\r\n        if meeting_id not in self.meetings:\r\n            return \"\"\r\n\r\n        mtg = self.meetings[meeting_id]\r\n\r\n        lines = [\r\n            f\"# {mtg.title}\",\r\n            f\"**Date:** {mtg.date.strftime('%B %d, %Y')}\",\r\n            f\"**Time:** {mtg.time_start} - {mtg.time_end}\",\r\n            f\"**Location:** {mtg.location}\",\r\n            f\"**Project:** {self.project_name}\",\r\n            \"\",\r\n            \"## Attendees\",\r\n        ]\r\n\r\n        for att in mtg.attendees:\r\n            status = \"Present\" if att.present else \"Absent\"\r\n            lines.append(f\"- {att.name} ({att.company}) - {att.role} [{status}]\")\r\n\r\n        lines.extend([\"\", \"## Discussion Topics\"])\r\n\r\n        for topic in mtg.topics:\r\n            lines.extend([\r\n                f\"### {topic.title}\",\r\n                f\"*Presented by: {topic.presenter}*\",\r\n                \"\",\r\n                topic.discussion,\r\n                \"\"\r\n            ])\r\n\r\n            if topic.decisions:\r\n                lines.append(\"**Decisions:**\")\r\n                for dec in topic.decisions:\r\n                    lines.append(f\"- [{dec.decision_id}] {dec.description}\")\r\n                lines.append(\"\")\r\n\r\n        if mtg.action_items:\r\n            lines.extend([\"## Action Items\", \"\"])\r\n            lines.append(\"| ID | Action | Assigned | Due | Priority |\")\r\n            lines.append(\"|---|---|---|---|---|\")\r\n            for action in mtg.action_items:\r\n                lines.append(f\"| {action.action_id} | {action.description} | \"\r\n                           f\"{action.assigned_to} | {action.due_date} | {action.priority.value} |\")\r\n\r\n        if mtg.next_meeting:\r\n            lines.extend([\"\", f\"## Next Meeting: {mtg.next_meeting.strftime('%B %d, %Y')}\"])\r\n\r\n        return \"\\n\".join(lines)\r\n\r\n    def export_all_actions(self, output_path: str):\r\n        \"\"\"Export action items to Excel.\"\"\"\r\n        data = [{\r\n            'ID': a.action_id,\r\n            'Description': a.description,\r\n            'Assigned To': a.assigned_to,\r\n            'Due Date': a.due_date,\r\n            'Priority': a.priority.value,\r\n            'Status': a.status.value,\r\n            'Meeting': a.created_meeting\r\n        } for a in self.all_actions.values()]\r\n\r\n        df = pd.DataFrame(data)\r\n        df.to_excel(output_path, index=False)\r\n        return output_path\r\n```\r\n\r\n## Quick Start\r\n\r\n```python\r\nfrom datetime import date, timedelta\r\n\r\ngenerator = MeetingMinutesGenerator(\"Office Tower\")\r\n\r\n# Create meeting\r\nmeeting = generator.create_meeting(\r\n    meeting_type=MeetingType.OAC,\r\n    title=\"Weekly OAC Meeting #15\",\r\n    meeting_date=date.today(),\r\n    time_start=\"10:00 AM\",\r\n    time_end=\"11:30 AM\",\r\n    location=\"Conference Room A\"\r\n)\r\n\r\n# Add attendees\r\ngenerator.add_attendee(meeting.meeting_id, \"John Smith\", \"Owner LLC\", \"Owner Rep\", \"john@owner.com\")\r\n\r\n# Add topic\r\ntopic_id = generator.add_topic(meeting.meeting_id, \"Schedule Update\",\r\n                               \"Project Manager\", \"Discussed current schedule status...\")\r\n\r\n# Add decision\r\ngenerator.add_decision(meeting.meeting_id, topic_id,\r\n                      \"Approved 2-week extension for concrete work\", \"Owner Rep\")\r\n\r\n# Create action\r\ngenerator.create_action(meeting.meeting_id,\r\n                       \"Submit revised schedule\", \"Contractor\",\r\n                       date.today() + timedelta(days=7), Priority.HIGH)\r\n\r\n# Generate document\r\nminutes = generator.generate_minutes_document(meeting.meeting_id)\r\nprint(minutes)\r\n```\r\n\r\n## Resources\r\n- **DDC Book**: Chapter 4 - Project Communication\r\n","# Meeting Minutes Generator\r\n\r\n## Business Case\r\n\r\n### Problem Statement\r\nMeeting documentation is inconsistent:\r\n- Minutes not standardized\r\n- Action items lost\r\n- Decisions not tracked\r\n- Poor distribution\r\n\r\n### Solution\r\nStandardized meeting minutes generation with action item tracking, decision logging, and automatic distribution.\r\n\r\n## Technical Implementation\r\n\r\n```python\r\nimport pandas as pd\r\nfrom datetime import datetime, date, timedelta\r\nfrom typing import Dict, Any, List, Optional\r\nfrom dataclasses import dataclass, field\r\nfrom enum import Enum\r\n\r\n\r\nclass MeetingType(Enum):\r\n    OAC = \"oac\"  # Owner-Architect-Contractor\r\n    PROGRESS = \"progress\"\r\n    COORDINATION = \"coordination\"\r\n    SAFETY = \"safety\"\r\n    PRECONSTRUCTION = \"preconstruction\"\r\n    CLOSEOUT = \"closeout\"\r\n    OTHER = \"other\"\r\n\r\n\r\nclass ActionStatus(Enum):\r\n    OPEN = \"open\"\r\n    IN_PROGRESS = \"in_progress\"\r\n    COMPLETE = \"complete\"\r\n    OVERDUE = \"overdue\"\r\n\r\n\r\nclass Priority(Enum):\r\n    HIGH = \"high\"\r\n    MEDIUM = \"medium\"\r\n    LOW = \"low\"\r\n\r\n\r\n@dataclass\r\nclass Attendee:\r\n    name: str\r\n    company: str\r\n    role: str\r\n    email: str\r\n    present: bool = True\r\n\r\n\r\n@dataclass\r\nclass ActionItem:\r\n    action_id: str\r\n    description: str\r\n    assigned_to: str\r\n    due_date: date\r\n    priority: Priority\r\n    status: ActionStatus\r\n    created_meeting: str\r\n    completed_date: Optional[date] = None\r\n    notes: str = \"\"\r\n\r\n\r\n@dataclass\r\nclass Decision:\r\n    decision_id: str\r\n    description: str\r\n    made_by: str\r\n    decision_date: date\r\n    impact: str = \"\"\r\n\r\n\r\n@dataclass\r\nclass DiscussionTopic:\r\n    topic_id: str\r\n    title: str\r\n    presenter: str\r\n    discussion: str\r\n    decisions: List[Decision] = field(default_factory=list)\r\n    actions: List[str] = field(default_factory=list)  # Action IDs\r\n\r\n\r\n@dataclass\r\nclass MeetingMinutes:\r\n    meeting_id: str\r\n    meeting_type: MeetingType\r\n    title: str\r\n    date: date\r\n    time_start: str\r\n    time_end: str\r\n    location: str\r\n    attendees: List[Attendee]\r\n    topics: List[DiscussionTopic]\r\n    action_items: List[ActionItem]\r\n    next_meeting: Optional[date] = None\r\n    prepared_by: str = \"\"\r\n    approved_by: str = \"\"\r\n\r\n\r\nclass MeetingMinutesGenerator:\r\n    \"\"\"Generate and track meeting minutes.\"\"\"\r\n\r\n    def __init__(self, project_name: str):\r\n        self.project_name = project_name\r\n        self.meetings: Dict[str, MeetingMinutes] = {}\r\n        self.all_actions: Dict[str, ActionItem] = {}\r\n        self._meeting_counter = 0\r\n        self._action_counter = 0\r\n        self._decision_counter = 0\r\n\r\n    def create_meeting(self, meeting_type: MeetingType, title: str,\r\n                      meeting_date: date, time_start: str, time_end: str,\r\n                      location: str) -> MeetingMinutes:\r\n        self._meeting_counter += 1\r\n        meeting_id = f\"MTG-{self._meeting_counter:04d}\"\r\n\r\n        meeting = MeetingMinutes(\r\n            meeting_id=meeting_id,\r\n            meeting_type=meeting_type,\r\n            title=title,\r\n            date=meeting_date,\r\n            time_start=time_start,\r\n            time_end=time_end,\r\n            location=location,\r\n            attendees=[],\r\n            topics=[],\r\n            action_items=[]\r\n        )\r\n        self.meetings[meeting_id] = meeting\r\n        return meeting\r\n\r\n    def add_attendee(self, meeting_id: str, name: str, company: str,\r\n                    role: str, email: str, present: bool = True):\r\n        if meeting_id not in self.meetings:\r\n            return\r\n        attendee = Attendee(name, company, role, email, present)\r\n        self.meetings[meeting_id].attendees.append(attendee)\r\n\r\n    def add_topic(self, meeting_id: str, title: str, presenter: str,\r\n                 discussion: str) -> str:\r\n        if meeting_id not in self.meetings:\r\n            return \"\"\r\n        topic_id = f\"{meeting_id}-T{len(self.meetings[meeting_id].topics) + 1:02d}\"\r\n        topic = DiscussionTopic(topic_id, title, presenter, discussion)\r\n        self.meetings[meeting_id].topics.append(topic)\r\n        return topic_id\r\n\r\n    def add_decision(self, meeting_id: str, topic_id: str, description: str,\r\n                    made_by: str, impact: str = \"\") -> Decision:\r\n        if meeting_id not in self.meetings:\r\n            return None\r\n\r\n        self._decision_counter += 1\r\n        decision_id = f\"DEC-{self._decision_counter:04d}\"\r\n\r\n        decision = Decision(\r\n            decision_id=decision_id,\r\n            description=description,\r\n            made_by=made_by,\r\n            decision_date=self.meetings[meeting_id].date,\r\n            impact=impact\r\n        )\r\n\r\n        # Find topic and add decision\r\n        for topic in self.meetings[meeting_id].topics:\r\n            if topic.topic_id == topic_id:\r\n                topic.decisions.append(decision)\r\n                break\r\n\r\n        return decision\r\n\r\n    def create_action(self, meeting_id: str, description: str, assigned_to: str,\r\n                     due_date: date, priority: Priority = Priority.MEDIUM) -> ActionItem:\r\n        if meeting_id not in self.meetings:\r\n            return None\r\n\r\n        self._action_counter += 1\r\n        action_id = f\"ACT-{self._action_counter:04d}\"\r\n\r\n        action = ActionItem(\r\n            action_id=action_id,\r\n            description=description,\r\n            assigned_to=assigned_to,\r\n            due_date=due_date,\r\n            priority=priority,\r\n            status=ActionStatus.OPEN,\r\n            created_meeting=meeting_id\r\n        )\r\n\r\n        self.meetings[meeting_id].action_items.append(action)\r\n        self.all_actions[action_id] = action\r\n        return action\r\n\r\n    def update_action_status(self, action_id: str, status: ActionStatus):\r\n        if action_id in self.all_actions:\r\n            self.all_actions[action_id].status = status\r\n            if status == ActionStatus.COMPLETE:\r\n                self.all_actions[action_id].completed_date = date.today()\r\n\r\n    def get_open_actions(self, assigned_to: str = None) -> List[ActionItem]:\r\n        actions = [a for a in self.all_actions.values()\r\n                  if a.status in [ActionStatus.OPEN, ActionStatus.IN_PROGRESS]]\r\n        if assigned_to:\r\n            actions = [a for a in actions if assigned_to.lower() in a.assigned_to.lower()]\r\n        return sorted(actions, key=lambda x: x.due_date)\r\n\r\n    def get_overdue_actions(self) -> List[ActionItem]:\r\n        today = date.today()\r\n        overdue = []\r\n        for action in self.all_actions.values():\r\n            if action.status in [ActionStatus.OPEN, ActionStatus.IN_PROGRESS]:\r\n                if action.due_date \u003C today:\r\n                    action.status = ActionStatus.OVERDUE\r\n                    overdue.append(action)\r\n        return overdue\r\n\r\n    def generate_minutes_document(self, meeting_id: str) -> str:\r\n        \"\"\"Generate formatted meeting minutes.\"\"\"\r\n        if meeting_id not in self.meetings:\r\n            return \"\"\r\n\r\n        mtg = self.meetings[meeting_id]\r\n\r\n        lines = [\r\n            f\"# {mtg.title}\",\r\n            f\"**Date:** {mtg.date.strftime('%B %d, %Y')}\",\r\n            f\"**Time:** {mtg.time_start} - {mtg.time_end}\",\r\n            f\"**Location:** {mtg.location}\",\r\n            f\"**Project:** {self.project_name}\",\r\n            \"\",\r\n            \"## Attendees\",\r\n        ]\r\n\r\n        for att in mtg.attendees:\r\n            status = \"Present\" if att.present else \"Absent\"\r\n            lines.append(f\"- {att.name} ({att.company}) - {att.role} [{status}]\")\r\n\r\n        lines.extend([\"\", \"## Discussion Topics\"])\r\n\r\n        for topic in mtg.topics:\r\n            lines.extend([\r\n                f\"### {topic.title}\",\r\n                f\"*Presented by: {topic.presenter}*\",\r\n                \"\",\r\n                topic.discussion,\r\n                \"\"\r\n            ])\r\n\r\n            if topic.decisions:\r\n                lines.append(\"**Decisions:**\")\r\n                for dec in topic.decisions:\r\n                    lines.append(f\"- [{dec.decision_id}] {dec.description}\")\r\n                lines.append(\"\")\r\n\r\n        if mtg.action_items:\r\n            lines.extend([\"## Action Items\", \"\"])\r\n            lines.append(\"| ID | Action | Assigned | Due | Priority |\")\r\n            lines.append(\"|---|---|---|---|---|\")\r\n            for action in mtg.action_items:\r\n                lines.append(f\"| {action.action_id} | {action.description} | \"\r\n                           f\"{action.assigned_to} | {action.due_date} | {action.priority.value} |\")\r\n\r\n        if mtg.next_meeting:\r\n            lines.extend([\"\", f\"## Next Meeting: {mtg.next_meeting.strftime('%B %d, %Y')}\"])\r\n\r\n        return \"\\n\".join(lines)\r\n\r\n    def export_all_actions(self, output_path: str):\r\n        \"\"\"Export action items to Excel.\"\"\"\r\n        data = [{\r\n            'ID': a.action_id,\r\n            'Description': a.description,\r\n            'Assigned To': a.assigned_to,\r\n            'Due Date': a.due_date,\r\n            'Priority': a.priority.value,\r\n            'Status': a.status.value,\r\n            'Meeting': a.created_meeting\r\n        } for a in self.all_actions.values()]\r\n\r\n        df = pd.DataFrame(data)\r\n        df.to_excel(output_path, index=False)\r\n        return output_path\r\n```\r\n\r\n## Quick Start\r\n\r\n```python\r\nfrom datetime import date, timedelta\r\n\r\ngenerator = MeetingMinutesGenerator(\"Office Tower\")\r\n\r\n# Create meeting\r\nmeeting = generator.create_meeting(\r\n    meeting_type=MeetingType.OAC,\r\n    title=\"Weekly OAC Meeting #15\",\r\n    meeting_date=date.today(),\r\n    time_start=\"10:00 AM\",\r\n    time_end=\"11:30 AM\",\r\n    location=\"Conference Room A\"\r\n)\r\n\r\n# Add attendees\r\ngenerator.add_attendee(meeting.meeting_id, \"John Smith\", \"Owner LLC\", \"Owner Rep\", \"john@owner.com\")\r\n\r\n# Add topic\r\ntopic_id = generator.add_topic(meeting.meeting_id, \"Schedule Update\",\r\n                               \"Project Manager\", \"Discussed current schedule status...\")\r\n\r\n# Add decision\r\ngenerator.add_decision(meeting.meeting_id, topic_id,\r\n                      \"Approved 2-week extension for concrete work\", \"Owner Rep\")\r\n\r\n# Create action\r\ngenerator.create_action(meeting.meeting_id,\r\n                       \"Submit revised schedule\", \"Contractor\",\r\n                       date.today() + timedelta(days=7), Priority.HIGH)\r\n\r\n# Generate document\r\nminutes = generator.generate_minutes_document(meeting.meeting_id)\r\nprint(minutes)\r\n```\r\n\r\n## Resources\r\n- **DDC Book**: Chapter 4 - Project Communication\r\n",{"slug":5,"description":7,"display_name":37},"Meeting Minutes Generator","main","e7e336ac628c3e3bd771aff1aaa469c93778f94a","skills\u002Fdatadrivenconstruction\u002Fmeeting-minutes-generator",0,"https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del","2026-08-23 22:39:37",{"source":8,"skillName":5,"commands":46,"prompt":56,"zipAvailable":57},[47,50,53],{"tool":48,"command":49},"npx","npx skills add kbarbel640-del\u002Fskills --skill meeting-minutes-generator",{"tool":51,"command":52},"bunx","bunx skills add kbarbel640-del\u002Fskills --skill meeting-minutes-generator",{"tool":54,"command":55},"pnpm","pnpm dlx skills add kbarbel640-del\u002Fskills --skill meeting-minutes-generator","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fdatadrivenconstruction\u002Fmeeting-minutes-generator\u002FSKILL.md",true,[59],{"path":60,"resourceType":61,"resourceTypeDesc":62,"sizeBytes":63,"sourceHtmlUrl":64},"_meta.json","REFERENCE","参考文档",318,"https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fdatadrivenconstruction\u002Fmeeting-minutes-generator\u002F_meta.json",[66,95,124,145,151,171],{"skillNo":67,"name":68,"nameZh":6,"description":69,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":70,"categories":71,"keywords":75,"publishedAt":32},"01M6G8J55967D6281ACMKAKTEQ","crowd-prompting","A marketplace where AI agents improve prompts, system instructions, tool descriptions, and other text-based content with domain expertise from real-world operations — and earn tokens for valuable contributions.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzzadrian\u002Fcrowd-prompting\u002FSKILL.md",[72],{"categoryNo":73,"categoryName":74,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000036","内容创作者",[76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94],"crowd prompting","prompting","api","with","tokens","domain","world","prompts","operations","instructions","text","tool","system","improve","productivity","marketplace","https","content","ai agents",{"skillNo":96,"name":97,"nameZh":6,"description":98,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":99,"categories":100,"keywords":106,"publishedAt":32},"01M6G8J0PKPAYVET6BWE8W4C26","dilemm-ai","Compete in DilemmAI, the prisoner's dilemma AI arena at dilemm.ai. Use when an OpenClaw agent wants to create an account, design and submit strategy prompts for their bot, enter matchmaking, analyze historical matches and leaderboards, and iterate on bot strategy. Requires headless browser automation (no API available yet).","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzyori\u002Fdilemm-ai\u002FSKILL.md",[101],{"categoryNo":102,"categoryName":103,"taxonomyType":104,"taxonomyTypeDesc":105},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[107,78,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,83,123],"dilemm ai","arena","analyze","browser","openclaw agent","create","automation","browser automation","bot","openclaw","design","strategy","headless","compete","submit","matchmaking","use",{"skillNo":125,"name":126,"nameZh":6,"description":127,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":128,"categories":129,"keywords":133,"publishedAt":32},"01M6G8HWAF3K9SW7NP3Z83CPJ6","arxiv-paper-reviews","Interact with arXiv Crawler API to fetch papers, read reviews, and submit comments. Use when working with arXiv papers, fetching paper lists by date\u002Fcategory\u002Finterest, viewing paper details with comments, or submitting paper reviews via API at http:\u002F\u002F150.158.152.82:8000.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzxrys\u002Fweak-accept\u002FSKILL.md",[130],{"categoryNo":131,"categoryName":132,"taxonomyType":104,"taxonomyTypeDesc":105},"01JBSEEDCAT000000000000021","资料检索与研究",[134,135,136,137,138,139,140,79,141,121,123,142,78,143,144],"arxiv paper reviews","reviews","arxiv","paper","crawler","papers","comments","fetch","read","http","via",{"skillNo":146,"name":126,"nameZh":6,"description":127,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":147,"categories":148,"keywords":150,"publishedAt":32},"01M6G8HQJ7N7WMY6YV7D7SSJ16","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzxrys\u002Farxiv-paper-reviews\u002FSKILL.md",[149],{"categoryNo":131,"categoryName":132,"taxonomyType":104,"taxonomyTypeDesc":105},[137,136,135,134,144,139,140,79,138,121,123,141,142,78,143],{"skillNo":152,"name":153,"nameZh":6,"description":154,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":155,"categories":156,"keywords":157,"publishedAt":32},"01M6G8HM95Y64JNVFC2HN4E2BG","git-summary","Get a quick summary of the current Git repository including status, recent commits, branches, and contributors.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzweack\u002Fgit-summary\u002FSKILL.md",[],[158,159,160,161,162,163,164,165,166,167,168,169,170],"git","summary","git summary","commits","repository","win32","status","linux","contributors","true","quick","get","branches",{"skillNo":172,"name":173,"nameZh":6,"description":174,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":175,"categories":176,"keywords":181,"publishedAt":32},"01M6G8HGEGF05CNEJCGVYFSC4R","agent-constitution","Interact with AgentConstitution governance contracts on Base Sepolia. Check compliance, read rules, log actions, query governance state.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fztsalexey\u002Fagent-constitution\u002FSKILL.md",[177,178],{"categoryNo":102,"categoryName":103,"taxonomyType":104,"taxonomyTypeDesc":105},{"categoryNo":179,"categoryName":180,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000037","律师与法务",[182,183,184,185,79,186,187,38,188,142,189,190,191,192,193,92,194,195,196],"agent constitution","constitution","contracts","tree","query","base","log","check","Rules","projects","compliance","actions","state","governance","github"]