{"id":"d9214f93-9c41-49da-ae1e-9c5cdd9e07a0","entityType":"agent","slug":"clawhub-felox63-m365-planner-v2","name":"M365 Planner","canonicalUrl":"https://www.xpersona.co/agent/clawhub-felox63-m365-planner-v2","canonicalPath":"/agent/clawhub-felox63-m365-planner-v2","generatedAt":"2026-10-11T17:45:00.490Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-11T15:44:44.374Z","emptyReason":null},"description":"Manage Microsoft 365 Planner plans, buckets, and tasks via Microsoft Graph API. Use when creating, listing, updating, or deleting Planner resources. Supports... Skill: M365 Planner Owner: felox63 Summary: Manage Microsoft 365 Planner plans, buckets, and tasks via Microsoft Graph API. Use when creating, listing, updating, or deleting Planner resources. Supports... Tags: latest:1.2.3 Version history: v1.2.3 | 2026-04-18T13:08:24.799Z | user v1.2.3 is a major documentation update for international users. - Full documentation translated to English for worldwide ClawHub access -","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1K downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s171gk0y8ds0jr7dg5f05ap4p183pb80:m365-planner-v2","sourceUrl":"https://clawhub.ai/felox63/m365-planner-v2","homepage":"https://clawhub.ai/felox63/skills/m365-planner-v2","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/felox63/m365-planner-v2","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/felox63/skills/m365-planner-v2","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":60,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Manage Microsoft 365 Planner plans, buckets, and tasks via Microsoft Graph API. Use when creating, listing, updating, or deleting Planner resources. Supports..."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T15:44:44.374Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T15:44:44.374Z","emptyReason":null},"stars":null,"forks":null,"downloads":1036,"packageName":null,"latestVersion":"1.2.3","tractionLabel":"1K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T15:44:44.307Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T15:44:44.374Z","lastCrawledAt":"2026-10-11T15:44:44.307Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T15:44:44.307Z","lastVerifiedAt":null,"highlights":[{"version":"1.2.3","createdAt":"2026-04-18T13:08:24.799Z","changelog":"v1.2.3 is a major documentation update for international users. - Full documentation translated to English for worldwide ClawHub access - Retains all portability, security, and packaging improvements from 1.2.2 - No functional or API changes; all scripts and usage remain unchanged","fileCount":19,"zipByteSize":27897},{"version":"1.2.2","createdAt":"2026-04-18T13:04:07.030Z","changelog":"m365-planner-v2 1.2.2 introduces improved portability and security. - Env file path now uses `os.homedir()` for better compatibility across environments. - Complete check to ensure no sensitive data (IDs, names, domains) remains in the codebase. - Packaging adjustments: tarball is created; node_modules are excluded to streamline distribution.","fileCount":18,"zipByteSize":27567},{"version":"1.2.1","createdAt":"2026-04-18T11:17:11.896Z","changelog":"m365-planner-v2 v1.2.1 makes all scripts fully generic and removes project-specific data. - Removed all hardcoded Group IDs and plan names—scripts now require these as parameters. - Improved \"list plans\" script: now lists all groups if no ID is provided. - Cleanup functionality is now flexible and works for any plan or bucket. - All scripts are ready for generic use, including in ClawHub setups. - Documentation updated to reflect these changes and provide clearer setup instructions.","fileCount":17,"zipByteSize":24465}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s171gk0y8ds0jr7dg5f05ap4p183pb80:m365-planner-v2","setupComplexity":"low","setupSteps":["Setup complexity is LOW. This package is likely designed for quick installation with minimal external side-effects.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-felox63-m365-planner-v2/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-felox63-m365-planner-v2/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-felox63-m365-planner-v2/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-felox63-m365-planner-v2/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-felox63-m365-planner-v2/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-felox63-m365-planner-v2/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-11T17:45:00.487Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-felox63-m365-planner-v2/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-felox63-m365-planner-v2/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-felox63-m365-planner-v2/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-felox63-m365-planner-v2/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-10-11T15:44:44.374Z","emptyReason":null},"readme":"Skill: M365 Planner\n\nOwner: felox63\n\nSummary: Manage Microsoft 365 Planner plans, buckets, and tasks via Microsoft Graph API. Use when creating, listing, updating, or deleting Planner resources. Supports...\n\nTags: latest:1.2.3\n\nVersion history:\n\nv1.2.3 | 2026-04-18T13:08:24.799Z | user\n\nv1.2.3 is a major documentation update for international users.\n\n- Full documentation translated to English for worldwide ClawHub access  \n- Retains all portability, security, and packaging improvements from 1.2.2  \n- No functional or API changes; all scripts and usage remain unchanged\n\nv1.2.2 | 2026-04-18T13:04:07.030Z | user\n\nm365-planner-v2 1.2.2 introduces improved portability and security.\n\n- Env file path now uses `os.homedir()` for better compatibility across environments.\n- Complete check to ensure no sensitive data (IDs, names, domains) remains in the codebase.\n- Packaging adjustments: tarball is created; node_modules are excluded to streamline distribution.\n\nv1.2.1 | 2026-04-18T11:17:11.896Z | user\n\nm365-planner-v2 v1.2.1 makes all scripts fully generic and removes project-specific data.\n\n- Removed all hardcoded Group IDs and plan names—scripts now require these as parameters.\n- Improved \"list plans\" script: now lists all groups if no ID is provided.\n- Cleanup functionality is now flexible and works for any plan or bucket.\n- All scripts are ready for generic use, including in ClawHub setups.\n- Documentation updated to reflect these changes and provide clearer setup instructions.\n\nArchive index:\n\nArchive v1.2.3: 19 files, 27897 bytes\n\nFiles: CHANGELOG.md (3884b), package-lock.json (11786b), package.json (630b), references/common-patterns.md (1834b), references/planner-api.md (1803b), references/setup-guide.md (2023b), scripts/assign_task.sh (756b), scripts/cleanup_verlaengerungen.js (5138b), scripts/create_plan.js (3366b), scripts/create_plan.sh (965b), scripts/create_task.js (2884b), scripts/delete_task.js (2719b), scripts/list_plans.js (4920b), scripts/list_tasks.sh (867b), scripts/test_connection.js (3665b), scripts/test-connection.js (3773b), skill-card.md (2725b), SKILL.md (12230b), _meta.json (134b)\n\nFile v1.2.3:SKILL.md\n\n---\nname: m365-planner\ndescription: Manage Microsoft 365 Planner plans, buckets, and tasks via Microsoft Graph API. Use when creating, listing, updating, or deleting Planner resources. Supports group-based plan management, task assignment, progress tracking, and recurring tasks. Requires Azure AD app registration with Group.Read.All and Tasks.ReadWrite.All permissions.\nlicense: MIT\nversion: 1.2.3\n---\n\n# M365 Planner Skill\n\nManage Microsoft 365 Planner through Microsoft Graph API.\n\n## What's New in v1.2.3\n\n- 🌍 **English Documentation** – Complete translation for international ClawHub availability\n- 🔧 **Portability** – Env path now uses `os.homedir()` instead of hardcoded paths\n- 🧹 **Security Cleanup** – Full audit for sensitive data (no IDs, names, domains)\n- 📦 **ClawHub-ready** – Tarball created, node_modules excluded\n\n## What's New in v1.2.2\n\n- 🔧 **Portability** – Env path now uses `os.homedir()` instead of hardcoded `/home/claw/.openclaw/.env`\n- 🧹 **Security Cleanup** – Full audit for sensitive data (no IDs, names, domains)\n- 📦 **ClawHub-ready** – Tarball created, node_modules excluded\n\n## What's New in v1.2.1\n\n- ✅ **Generic Scripts** – No hardcoded Group-IDs or Plan names anymore\n- ✅ **Command-Line Parameters** – All scripts accept IDs as arguments\n- ✅ **List Plans Improved** – Shows all groups when no ID provided\n- ✅ **Flexible Cleanup** – Works with any plans/buckets\n- ✅ **ClawHub-ready** – No project-specific data included\n\n## What's New in v1.1.0\n\n- ✅ **Node.js Scripts** – Standalone scripts without `mgc` CLI\n- ✅ **If-Match Header Support** – Correct ETag handling for updates/deletes\n- ✅ **Group-Based API** – Direct access via M365 Group-ID\n- ✅ **Recurring Tasks** – Note about native Planner recurrence feature\n- ✅ **Cleanup Scripts** – Automated task cleanup\n\n## Prerequisites\n\n1. Azure AD App Registration (see Setup below)\n2. Node.js v18+ with `@microsoft/microsoft-graph-client` and `axios`\n3. M365 Group (not Security Group or Distribution List!)\n\n## Quick Start\n\n```bash\n# Test connection\nnode scripts/test-connection.js\n\n# List all plans\nnode scripts/list_plans.js\n\n# List plans for specific group\nnode scripts/list_plans.js <group-id>\n\n# Create plan\nnode scripts/create_plan.js \"Project Name\" <group-id>\n\n# Create task\nnode scripts/create_task.js <plan-id> <bucket-id> \"Task Title\"\n\n# Delete completed tasks\nnode scripts/cleanup_verlaengerungen.js <group-id> \"<plan-name>\" \"<bucket-name>\"\n```\n\n## Setup: Azure AD App Registration\n\n### Step 1: Create App Registration\n\n**Azure Portal:**\n1. https://portal.azure.com → Azure Active Directory → App registrations\n2. \"New registration\"\n3. Name: `M365-Planner-Integration`\n4. Supported account types: `Accounts in this organizational directory only`\n5. Redirect URI: None (Client Credentials Flow)\n\n**Or via Azure CLI:**\n```bash\naz login\naz ad app create --display-name \"M365-Planner-Integration\" --sign-in-audience \"AzureADMyOrg\"\n```\nNote the **Application (client) ID** from the output.\n\n### Step 2: Add API Permissions\n\n**Important:** Use **Application Permissions** (not Delegated)!\n\n**Azure Portal:**\n1. App → API permissions → Add a permission\n2. Microsoft Graph → Application permissions\n3. Add:\n   - `Group.Read.All` (not Group.ReadWrite.All – sufficient for Planner)\n   - `Tasks.ReadWrite.All`\n4. **Grant Admin Consent:** Click \"Grant admin consent for [Tenant]\"!\n\n**Or via Azure CLI:**\n```bash\nAPP_ID=\"your-app-id\"\n\n# Group.Read.All\naz ad app permission add \\\n  --id $APP_ID \\\n  --api 00000003-0000-0000-c000-000000000000 \\\n  --api-permissions 5b567253-7703-48e2-861c-caed61531407=Role\n\n# Tasks.ReadWrite.All\naz ad app permission add \\\n  --id $APP_ID \\\n  --api 00000003-0000-0000-c000-000000000000 \\\n  --api-permissions bdfbf15f-ee85-495a-99a9-ef9b2abb1dcb=Role\n\n# Admin Consent\naz ad app permission admin-consent --id $APP_ID\n```\n\n### Step 3: Create Client Secret\n\n**Azure Portal:**\n1. App → Certificates & secrets → Client secrets → New client secret\n2. Description: `OpenClaw Integration`\n3. Expires: 24 months (Maximum)\n4. **Copy values immediately!** – Only shown once\n\n**Or via Azure CLI:**\n```bash\naz ad app credential reset \\\n  --id $APP_ID \\\n  --append \\\n  --display-name \"OpenClaw Integration\"\n```\n\n### Step 4: Configure Environment\n\nStore credentials in `~/.openclaw/.env`:\n\n```bash\n# Microsoft 365 Planner Credentials\nM365_CLIENT_ID=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\nM365_CLIENT_SECRET=\"your-secret-value\"\nM365_TENANT_ID=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\n```\n\n**Secure permissions:**\n```bash\nchmod 600 ~/.openclaw/.env\n```\n\n### Step 5: Test Connection\n\n```bash\nnode scripts/test-connection.js\n```\n\nExpected output:\n```\n✅ Access Token successfully received!\n📋 Test: M365 Groups...\n   3 groups found:\n   - My Team ✅ M365/Planner-capable\n✅ Connection successful!\n```\n\n## Important Notes\n\n### M365 Groups vs. Security Groups\n\n**Planner ONLY works with M365 Groups!**\n\n- ✅ **M365 Group** – Has Exchange mailbox, Teams, Planner (recognizable by mail attribute)\n- ❌ **Security Group** – Only for permissions, no Planner\n- ❌ **Distribution List** – Only for email distribution, no Planner\n\n**Check groups:**\n```bash\nnode scripts/test-connection.js\n```\nShows all groups with status \"✅ M365/Planner-capable\".\n\n**Create M365 Group (if none exists):**\n- Microsoft 365 Admin Center → Groups → Add a group\n- Or Teams: Create new team (automatically creates M365 Group)\n\n### If-Match Header (ETag)\n\n**All update and delete operations require the `If-Match` header!**\n\nPlanner uses Optimistic Concurrency Control. Requests fail without ETag.\n\n**Delete Example:**\n```javascript\n// Wrong ❌\nawait client.api(`/planner/tasks/${taskId}`).delete();\n\n// Correct ✅\nconst task = await client.api(`/planner/tasks/${taskId}`).get();\nawait client.api(`/planner/tasks/${taskId}`)\n    .headers({ 'If-Match': task['@odata.etag'] })\n    .delete();\n```\n\n**Update Example:**\n```javascript\nconst task = await client.api(`/planner/tasks/${taskId}`).get();\nawait client.api(`/planner/tasks/${taskId}`)\n    .headers({ 'If-Match': task['@odata.etag'] })\n    .update({ percentComplete: 50 });\n```\n\n### Group-Based API Endpoints\n\n**Do NOT use:**\n```\nGET /planner/plans  ❌ (requires complex filter)\n```\n\n**Use:**\n```\nGET /groups/{group-id}/planner/plans  ✅\n```\n\n**Example:**\n```javascript\nconst plans = await client.api(`/groups/${groupId}/planner/plans`).get();\n```\n\n### Recurring Tasks\n\n**Microsoft Planner supports native recurring tasks!**\n\nIn Planner Web UI or Mobile App:\n1. Open task\n2. Click \"Repeat\"\n3. Choose frequency: Daily, Weekly, Monthly, Yearly, Custom\n\n**Example:**\n- \"Domain renewal example.com\" → Repeat yearly\n- \"Check backup\" → Repeat weekly\n\n⚠️ **API Limitation:** The Graph API does not support creating recurring tasks directly.\nRecurring tasks must be set up via Planner UI.\n\n## Common Operations\n\n### Plans\n\n| Operation | Script |\n|-----------|--------|\n| List all plans | `node scripts/list_plans.js` |\n| Create plan | `node scripts/create_plan.js <name> <group-id>` |\n| Delete plan | `node scripts/delete_plan.js <plan-id>` |\n\n### Buckets\n\n| Operation | Script |\n|-----------|--------|\n| List buckets | Integrated in `list_plans.js` |\n| Create bucket | `node scripts/create_bucket.js <plan-id> <name>` |\n| Delete bucket | `node scripts/delete_bucket.js <bucket-id>` |\n\n### Tasks\n\n| Operation | Script |\n|-----------|--------|\n| List tasks | Integrated in `list_plans.js` |\n| Create task | `node scripts/create_task.js <plan-id> <bucket-id> <title>` |\n| Update task | `node scripts/update_task.js <task-id> --percent-complete 50` |\n| Delete task | `node scripts/delete_task.js <task-id>` |\n| Cleanup | `node scripts/cleanup_verlaengerungen.js <group-id> \"<plan-name>\" \"<bucket-name>\"` |\n\n## Helper Scripts\n\n### test-connection.js\nTests connection to Microsoft Graph:\n- Request access token\n- Display tenant information\n- List available M365 Groups\n- Check Planner capability\n\n```bash\nnode scripts/test-connection.js\n```\n\n### list_plans.js\nShows all plans in an M365 Group with:\n- Buckets and their tasks\n- Task status (completed/in progress/open)\n- Percentage progress indicator\n\n```bash\n# Without argument: Shows all available groups\nnode scripts/list_plans.js\n\n# With Group ID: Shows plans for specific group\nnode scripts/list_plans.js <group-id>\n```\n\n### create_plan.js\nCreates a new plan with default buckets:\n- To Do\n- In Progress  \n- Done\n\n```bash\nnode scripts/create_plan.js \"Project Alpha\" <group-id>\n```\n\n### cleanup_verlaengerungen.js\nCleans up completed tasks from a bucket:\n- Deletes tasks with 100% progress\n- Keeps open tasks\n- Correct If-Match header handling\n\n```bash\nnode scripts/cleanup_verlaengerungen.js <group-id> \"<plan-name>\" \"<bucket-name>\"\n```\n\n**Example:**\n```bash\nnode scripts/cleanup_verlaengerungen.js abc-123 \"My Project\" \"Completed\"\n```\n\n## Troubleshooting\n\n### Error: Insufficient privileges\n\n**Cause:** Admin consent not granted\n\n**Solution:**\n```bash\naz ad app permission admin-consent --id <app-id>\n```\nOr in Azure Portal: API permissions → Grant admin consent\n\n### Error: Group not found\n\n**Cause:** Planner only works with M365 Groups\n\n**Solution:**\n1. Check if it's an M365 Group (has mail attribute)\n2. Security Groups/Distribution Lists don't work\n3. Create new M365 Group (Teams or Admin Center)\n\n### Error: The If-Match header must be specified\n\n**Cause:** Update/Delete without ETag\n\n**Solution:**\n```javascript\n// First get task for ETag\nconst task = await client.api(`/planner/tasks/${id}`).get();\n// Then update/delete with If-Match header\nawait client.api(`/planner/tasks/${id}`)\n    .headers({ 'If-Match': task['@odata.etag'] })\n    .delete();\n```\n\n### Error: This entity set must be queried with a filter\n\n**Cause:** `/planner/plans` endpoint requires filter\n\n**Solution:** Use group-based endpoint:\n```javascript\n// Wrong ❌\nconst plans = await client.api('/planner/plans').get();\n\n// Correct ✅\nconst plans = await client.api(`/groups/${groupId}/planner/plans`).get();\n```\n\n### Error: Cannot find module '@microsoft/microsoft-graph-client'\n\n**Cause:** Node.js packages not installed\n\n**Solution:**\n```bash\ncd ~/.openclaw/workspace/skills/m365-planner\nnpm install\n```\n\n## Dependencies\n\nInstall packages locally in skill directory:\n\n```bash\ncd ~/.openclaw/workspace/skills/m365-planner\nnpm install @microsoft/microsoft-graph-client axios\n```\n\n## References\n\n- [Planner API Overview](references/planner-api.md)\n- [Setup Guide](references/setup-guide.md)\n- [Common Patterns](references/common-patterns.md)\n- [Microsoft Graph API Docs](https://docs.microsoft.com/en-us/graph/api/overview)\n- [Planner REST API Reference](https://docs.microsoft.com/en-us/graph/api/resources/planner-overview)\n\n## Changelog\n\n### v1.2.3 (2026-04-18)\n- 🌍 **English Documentation** – Complete translation for international ClawHub availability\n- 🔧 **Portability** – Env path uses `os.homedir()` for cross-system compatibility\n- 🧹 **Security Audit** – No hardcoded IDs, names, or domains\n\n### v1.2.2 (2026-04-18)\n- 🔧 **Portability** – Env path now uses `os.homedir()` instead of hardcoded `/home/claw/.openclaw/.env`\n- 🧹 **Security Cleanup** – Full audit for sensitive data (no IDs, names, domains)\n- 📦 **ClawHub-ready** – Tarball created, node_modules excluded\n\n### v1.2.1 (2026-04-18)\n- ✅ **Generic Scripts** – No hardcoded Group-IDs or Plan names anymore\n- ✅ **Command-Line Parameters** – All scripts accept IDs as arguments\n- ✅ **List Plans Improved** – Shows all groups when no ID provided\n- ✅ **Flexible Cleanup** – Works with any plans/buckets\n- ✅ **ClawHub-ready** – No project-specific data included\n\n### v1.1.0 (2026-04-17)\n- ✅ Node.js Scripts instead of mgc CLI\n- ✅ If-Match Header Support for updates/deletes\n- ✅ Group-based API Endpoints\n- ✅ Test-Connection Script with M365 Group Detection\n- ✅ List Plans Script with Bucket/Task overview\n- ✅ Cleanup Script for completed tasks\n- ✅ Documentation for recurring tasks (native Planner feature)\n- ✅ Troubleshooting Section expanded\n\n### v1.0.0 (2023-01-19)\n- Initial version with mgc CLI\n- Azure AD Setup Guide\n- Basic CRUD operations\n\nFile v1.2.3:_meta.json\n\n{\n  \"ownerId\": \"kn73k7k4tnef2q480xd4y7dnkx82nhzj\",\n  \"slug\": \"m365-planner-v2\",\n  \"version\": \"1.2.3\",\n  \"publishedAt\": 1776517704799\n}\n\nFile v1.2.3:references/common-patterns.md\n\n# Common Patterns for M365 Planner\n\n## Pattern 1: Create Project Structure\n\nCreate a complete project with predefined buckets:\n\n```bash\n# 1. Create or get group\nGROUP_ID=$(az ad group list --query \"[?displayName=='Project Team'].id\" -o tsv)\n\n# 2. Create plan with buckets (using helper script)\n./scripts/create_plan.sh \"Website Redesign\" \"$GROUP_ID\"\n```\n\n## Pattern 2: Bulk Task Import\n\nCreate multiple tasks from a list:\n\n```bash\nBUCKET_ID=\"your-bucket-id\"\n\ncat tasks.txt | while read -r TASK; do\n    mgc planner tasks create \\\n        --title \"$TASK\" \\\n        --bucket-id \"$BUCKET_ID\" \\\n        --output none\n    echo \"Created: $TASK\"\ndone\n```\n\n## Pattern 3: Task Status Update\n\nUpdate task progress:\n\n```bash\nTASK_ID=\"your-task-id\"\n\n# Mark as in progress (50%)\nmgc planner tasks patch \\\n    --planner-task-id \"$TASK_ID\" \\\n    --percent-complete 50\n\n# Mark as complete (100%)\nmgc planner tasks patch \\\n    --planner-task-id \"$TASK_ID\" \\\n    --percent-complete 100\n```\n\n## Pattern 4: Weekly Report\n\nGenerate a task summary:\n\n```bash\nPLAN_ID=\"your-plan-id\"\n\n# Get all tasks\necho \"Weekly Planner Report\"\necho \"====================\"\n./scripts/list_tasks.sh \"$PLAN_ID\"\n```\n\n## Pattern 5: Assign Tasks to Team\n\nAssign tasks to multiple users:\n\n```bash\n# Get user IDs\nUSER1=$(az ad user show --id \"alice@company.com\" --query id -o tsv)\nUSER2=$(az ad user show --id \"bob@company.com\" --query id -o tsv)\n\n# Assign tasks\n./scripts/assign_task.sh \"task-id-1\" \"$USER1\"\n./scripts/assign_task.sh \"task-id-2\" \"$USER2\"\n```\n\n## JSON Output Processing\n\nMany commands support `--output json` for automation:\n\n```bash\n# Extract specific fields\nmgc planner plans list --output json | \\\n    jq -r '.value[] | select(.title | contains(\"Project\")) | .id'\n\n# Save to file\nmgc planner tasks list --planner-bucket-id \"$BUCKET\" --output json > tasks.json\n```\n\nFile v1.2.3:references/planner-api.md\n\n# Microsoft Planner API Reference\n\n## Core Resources\n\n### plannerPlan\nRepresents a plan in Planner. Always associated with a Microsoft 365 group.\n\n**Key Properties:**\n- `id` – Unique identifier\n- `title` – Plan name\n- `owner` – Group ID that owns the plan\n- `createdDateTime` – Creation timestamp\n\n**Relationships:**\n- `buckets` – Collection of buckets in the plan\n- `tasks` – Collection of tasks in the plan\n\n### plannerBucket\nContainer for tasks within a plan. Represents stages or categories.\n\n**Key Properties:**\n- `id` – Unique identifier\n- `name` – Bucket name\n- `planId` – Parent plan ID\n- `orderHint` – Sorting hint\n\n### plannerTask\nIndividual work item in Planner.\n\n**Key Properties:**\n- `id` – Unique identifier\n- `title` – Task title\n- `bucketId` – Parent bucket ID\n- `planId` – Parent plan ID\n- `percentComplete` – Progress (0, 50, or 100)\n- `assignedTo` – User assignment\n- `dueDateTime` – Due date\n- `priority` – Priority (1=urgent, 3=normal, 5=low)\n\n## API Endpoints\n\n### Plans\n```\nGET    /planner/plans\nPOST   /planner/plans\nGET    /planner/plans/{id}\nPATCH  /planner/plans/{id}\nDELETE /planner/plans/{id}\n```\n\n### Buckets\n```\nGET    /planner/buckets\nPOST   /planner/buckets\nGET    /planner/buckets/{id}\nDELETE /planner/buckets/{id}\n```\n\n### Tasks\n```\nGET    /planner/tasks\nPOST   /planner/tasks\nGET    /planner/tasks/{id}\nPATCH  /planner/tasks/{id}\nDELETE /planner/tasks/{id}\n```\n\n## Required Permissions\n\n| Permission Type | Needed |\n|----------------|--------|\n| Delegated (work/school) | Group.ReadWrite.All, Tasks.ReadWrite |\n| Application | Group.ReadWrite.All, Tasks.ReadWrite |\n\n## Constraints\n\n- Plans require M365 Groups (no standalone plans)\n- Maximum 10 buckets per plan\n- Maximum 200 active tasks per plan\n- Plan names: max 64 characters\n\nFile v1.2.3:references/setup-guide.md\n\n# Detailed Setup Guide\n\n## Azure AD App Registration - Step by Step\n\n### 1. Portal Method (Browser)\n\n1. Go to https://portal.azure.com → Azure Active Directory → App registrations\n2. Click \"New registration\"\n3. Enter:\n   - Name: `M365-Planner-Integration`\n   - Supported account types: `Accounts in this organizational directory only`\n   - Redirect URI: None (for client credentials flow)\n4. Click \"Register\"\n5. Note the **Application (client) ID** and **Directory (tenant) ID**\n\n### 2. Add API Permissions\n\n1. Go to \"API permissions\" → \"Add a permission\"\n2. Select \"Microsoft Graph\" → \"Application permissions\"\n3. Add:\n   - `Group.ReadWrite.All`\n   - `Tasks.ReadWrite`\n4. Click \"Grant admin consent for [tenant]\"\n\n### 3. Create Client Secret\n\n1. Go to \"Certificates & secrets\" → \"Client secrets\" → \"New client secret\"\n2. Description: `OpenClaw Integration`\n3. Expires: Select duration (24 months max)\n4. Copy the **Value** (shown only once!)\n\n### 4. Environment Configuration\n\nCreate `~/.openclaw/.env`:\n\n```bash\n# M365 Planner Integration\nM365_CLIENT_ID=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\nM365_CLIENT_SECRET=\"your-secret-value\"\nM365_TENANT_ID=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\n```\n\n### 5. Test Authentication\n\n```bash\n# Using mgc with client credentials\nmgc login --strategy ClientSecret \\\n  --client-id $M365_CLIENT_ID \\\n  --client-secret $M365_CLIENT_SECRET \\\n  --tenant-id $M365_TENANT_ID\n\n# Verify access\nmgc me get\n```\n\n## Finding Group IDs\n\nPlanner plans require M365 groups. Find your groups:\n\n```bash\n# List all groups\nmgc groups list --output table --select displayName,id\n\n# Or use Azure CLI\naz ad group list --query \"[].{Name:displayName, ID:id}\" -o table\n```\n\n## Common Issues\n\n### \"Insufficient privileges\"\nSolution: Grant admin consent in Azure Portal → API permissions → Grant admin consent\n\n### \"Group not found\"\nSolution: Ensure you're using an M365 group, not a security group or distribution list\n\n### \"Invalid authentication token\"\nSolution: Token expired. Re-run `mgc login`\n\nFile v1.2.3:CHANGELOG.md\n\n# Changelog - m365-planner Skill\n\nAll notable changes to the m365-planner Skill are documented in this file.\n\n## [1.2.3] - 2026-04-18\n\n### 🌍 Added\n\n**English Documentation:**\n- Complete translation of SKILL.md for international ClawHub availability\n- All sections translated: Setup, Quick Start, Troubleshooting, References\n- International audience ready\n\n### 🔧 Changed\n\n**Portability:**\n- Env path in all scripts uses `path.join(os.homedir(), '.openclaw', '.env')`\n- Works on any system without modifications\n- Cross-platform compatible\n\n### 🧹 Security\n\n**Audit Completed:**\n- Full check for hardcoded sensitive data (Group-IDs, Tenant-IDs, Client-IDs, domains, names)\n- No project-specific data included\n- ClawHub publication ready\n\n---\n\n## [1.2.2] - 2026-04-18\n\n### 🔧 Changed\n\n**Improved Portability:**\n- Env path in all scripts changed from hardcoded `/home/claw/.openclaw/.env` to `path.join(os.homedir(), '.openclaw', '.env')`\n- Skill now works on any system without modifications\n- ClawHub-ready: No system-specific paths anymore\n\n### 🧹 Cleanup\n\n**Security & Privacy:**\n- Complete check for hardcoded sensitive data (Group-IDs, Tenant-IDs, Client-IDs, Domains, Names)\n- No project-specific data included\n- All scripts now use generic, portable paths\n\n### 📦 Packaging\n\n**Prepared for ClawHub:**\n- Tarball created (`m365-planner-v1.2.2.tar.gz`)\n- Only necessary files included (SKILL.md, Scripts, References, Package-Files)\n- node_modules excluded (installed separately)\n\n---\n\n## [1.2.1] - 2026-04-18\n\n### ✅ Added\n\n**Generic Scripts:**\n- No hardcoded Group-IDs or Plan names anymore\n- All scripts accept IDs as command-line parameters\n- List Plans shows all groups when no ID provided\n- Cleanup script works with any plans/buckets\n- ClawHub-ready with no project-specific data\n\n---\n\n## [1.1.0] - 2026-04-17\n\n### 🎉 Added\n\n**Node.js Scripts (replacing mgc CLI dependency):**\n- `scripts/test-connection.js` – Connection test with M365 Group Detection\n- `scripts/list_plans.js` – Complete Plan/Bucket/Task overview\n- `scripts/create_plan.js` – Plan creation with default buckets\n- `scripts/cleanup_verlaengerungen.js` – Automated cleanup of completed tasks\n\n**Documentation:**\n- If-Match Header / ETag handling for updates and deletes\n- Group-based API endpoints (`/groups/{id}/planner/plans`)\n- M365 Groups vs. Security Groups explanation\n- Native Planner Recurring Tasks documentation\n- Expanded Troubleshooting section\n\n### 🔧 Changed\n\n**Setup Process:**\n- No `mgc` CLI required anymore\n- Node.js packages (`@microsoft/microsoft-graph-client`, `axios`) sufficient\n- Credentials in `~/.openclaw/.env` (not in script)\n- Admin Consent explicitly documented\n\n**API Usage:**\n- Switched from `/planner/plans` to `/groups/{id}/planner/plans`\n- Automatic ETag handling in all scripts\n- Better error messages for permission issues\n\n### 🐛 Fixed\n\n- **If-Match Header Error** – All Delete/Update operations now send correct ETag\n- **Group Filter Error** – Plans now queried via Group-ID\n- **Module Not Found** – Local npm installation in skill directory\n\n### 📝 Technical Notes\n\n**Key insights from implementation:**\n\n1. **If-Match Header is mandatory**\n   - Planner uses Optimistic Concurrency Control\n   - DELETE/PATCH requests fail without `If-Match: <etag>` header\n   - Solution: Always fetch resource first, then use ETag\n\n2. **Only M365 Groups support Planner**\n   - Security Groups and Distribution Lists don't work\n   - Recognition: M365 Groups have mail attribute\n   - Creation: Via Teams or M365 Admin Center\n\n3. **Recurring Tasks only via UI**\n   - Graph API doesn't support creating recurring tasks\n   - Must be configured in Planner Web/Mobile UI\n   - Native feature works reliably\n\n---\n\n## [1.0.0] - 2023-01-19\n\n### 🎉 Initial Release\n\n- Basic CRUD operations via mgc CLI\n- Azure AD Setup Guide\n- Foundation for Planner integration\n\nFile v1.2.3:skill-card.md\n\n## Description:\n\nManage Microsoft 365 Planner plans, buckets, and tasks via Microsoft Graph API. Use when creating, listing, updating, or deleting Planner resources. Supports group-based plan management, task assignment, progress tracking, and recurring tasks. Requires Azure AD app registration with Group.Read.All and Tasks.ReadWrite.All permissions.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[felox63](https://clawhub.ai/user/felox63)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and administrators use this skill to manage Microsoft 365 Planner plans, buckets, and tasks from an agent workflow through Microsoft Graph. It is intended for creating, listing, assigning, updating, deleting, and cleaning up Planner resources in Microsoft 365 groups.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Setup documentation may lead administrators to grant broader Microsoft 365 group-write permissions than the scripts need.\n\nMitigation: Use Group.Read.All instead of Group.ReadWrite.All unless a separate reviewed use case requires group write access.\n\nRisk: The skill relies on a Microsoft 365 client secret stored in a local environment file.\n\nMitigation: Store the secret in a dedicated restricted file, keep file permissions tight, and rotate any secret previously used with overbroad permissions.\n\nRisk: Connection-test output may expose tenant, client, secret-suffix, and group details.\n\nMitigation: Avoid sharing test output and redact operational identifiers before posting logs or support traces.\n\n## Reference(s):\n\n- [Planner API Overview](references/planner-api.md)\n- [Setup Guide](references/setup-guide.md)\n- [Common Patterns](references/common-patterns.md)\n- [Microsoft Graph API Docs](https://docs.microsoft.com/en-us/graph/api/overview)\n- [Planner REST API Reference](https://docs.microsoft.com/en-us/graph/api/resources/planner-overview)\n\n## Skill Output:\n\n**Output Type(s):** [Shell commands, Code, Configuration instructions, Guidance]\n\n**Output Format:** [Markdown with inline bash and JavaScript code blocks]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Produces command guidance and helper-script usage for Microsoft Graph Planner operations; scripts may print tenant, client, secret-suffix, group, plan, bucket, and task details.]\n\n## Skill Version(s):\n\n1.2.3 (source: frontmatter, package.json, CHANGELOG, server release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v1.2.3:package-lock.json\n\n{\n  \"name\": \"m365-planner\",\n  \"version\": \"1.0.0\",\n  \"lockfileVersion\": 3,\n  \"requires\": true,\n  \"packages\": {\n    \"\": {\n      \"name\": \"m365-planner\",\n      \"version\": \"1.0.0\",\n      \"license\": \"ISC\",\n      \"dependencies\": {\n        \"@microsoft/microsoft-graph-client\": \"^3.0.7\",\n        \"axios\": \"^1.15.0\"\n      }\n    },\n    \"node_modules/@babel/runtime\": {\n      \"version\": \"7.29.2\",\n      \"resolved\": \"https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz\",\n      \"integrity\": \"sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=6.9.0\"\n      }\n    },\n    \"node_modules/@microsoft/microsoft-graph-client\": {\n      \"version\": \"3.0.7\",\n      \"resolved\": \"https://registry.npmjs.org/@microsoft/microsoft-graph-client/-/microsoft-graph-client-3.0.7.tgz\",\n      \"integrity\": \"sha512-/AazAV/F+HK4LIywF9C+NYHcJo038zEnWkteilcxC1FM/uK/4NVGDKGrxx7nNq1ybspAroRKT4I1FHfxQzxkUw==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@babel/runtime\": \"^7.12.5\",\n        \"tslib\": \"^2.2.0\"\n      },\n      \"engines\": {\n        \"node\": \">=12.0.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"@azure/identity\": {\n          \"optional\": true\n        },\n        \"@azure/msal-browser\": {\n          \"optional\": true\n        },\n        \"buffer\": {\n          \"optional\": true\n        },\n        \"stream-browserify\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/asynckit\": {\n      \"version\": \"0.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz\",\n      \"integrity\": \"sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==\",\n      \"license\": \"MIT\"\n    },\n    \"node_modules/axios\": {\n      \"version\": \"1.15.0\",\n      \"resolved\": \"https://registry.npmjs.org/axios/-/axios-1.15.0.tgz\",\n      \"integrity\": \"sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"follow-redirects\": \"^1.15.11\",\n        \"form-data\": \"^4.0.5\",\n        \"proxy-from-env\": \"^2.1.0\"\n      }\n    },\n    \"node_modules/call-bind-apply-helpers\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz\",\n      \"integrity\": \"sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"es-errors\": \"^1.3.0\",\n        \"function-bind\": \"^1.1.2\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/combined-stream\": {\n      \"version\": \"1.0.8\",\n      \"resolved\": \"https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz\",\n      \"integrity\": \"sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"delayed-stream\": \"~1.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.8\"\n      }\n    },\n    \"node_modules/delayed-stream\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz\",\n      \"integrity\": \"sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=0.4.0\"\n      }\n    },\n    \"node_modules/dunder-proto\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz\",\n      \"integrity\": \"sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"call-bind-apply-helpers\": \"^1.0.1\",\n        \"es-errors\": \"^1.3.0\",\n        \"gopd\": \"^1.2.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/es-define-property\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz\",\n      \"integrity\": \"sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/es-errors\": {\n      \"version\": \"1.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz\",\n      \"integrity\": \"sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/es-object-atoms\": {\n      \"version\": \"1.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz\",\n      \"integrity\": \"sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"es-errors\": \"^1.3.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/es-set-tostringtag\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz\",\n      \"integrity\": \"sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"es-errors\": \"^1.3.0\",\n        \"get-intrinsic\": \"^1.2.6\",\n        \"has-tostringtag\": \"^1.0.2\",\n        \"hasown\": \"^2.0.2\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/follow-redirects\": {\n      \"version\": \"1.16.0\",\n      \"resolved\": \"https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz\",\n      \"integrity\": \"sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==\",\n      \"funding\": [\n        {\n          \"type\": \"individual\",\n          \"url\": \"https://github.com/sponsors/RubenVerborgh\"\n        }\n      ],\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=4.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"debug\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/form-data\": {\n      \"version\": \"4.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz\",\n      \"integrity\": \"sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"asynckit\": \"^0.4.0\",\n        \"combined-stream\": \"^1.0.8\",\n        \"es-set-tostringtag\": \"^2.1.0\",\n        \"hasown\": \"^2.0.2\",\n        \"mime-types\": \"^2.1.12\"\n      },\n      \"engines\": {\n        \"node\": \">= 6\"\n      }\n    },\n    \"node_modules/function-bind\": {\n      \"version\": \"1.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz\",\n      \"integrity\": \"sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==\",\n      \"license\": \"MIT\",\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/ljharb\"\n      }\n    },\n    \"node_modules/get-intrinsic\": {\n      \"version\": \"1.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz\",\n      \"integrity\": \"sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"call-bind-apply-helpers\": \"^1.0.2\",\n        \"es-define-property\": \"^1.0.1\",\n        \"es-errors\": \"^1.3.0\",\n        \"es-object-atoms\": \"^1.1.1\",\n        \"function-bind\": \"^1.1.2\",\n        \"get-proto\": \"^1.0.1\",\n        \"gopd\": \"^1.2.0\",\n        \"has-symbols\": \"^1.1.0\",\n        \"hasown\": \"^2.0.2\",\n        \"math-intrinsics\": \"^1.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/ljharb\"\n      }\n    },\n    \"node_modules/get-proto\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz\",\n      \"integrity\": \"sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"dunder-proto\": \"^1.0.1\",\n        \"es-object-atoms\": \"^1.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/gopd\": {\n      \"version\": \"1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz\",\n      \"integrity\": \"sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/ljharb\"\n      }\n    },\n    \"node_modules/has-symbols\": {\n      \"version\": \"1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz\",\n      \"integrity\": \"sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/ljharb\"\n      }\n    },\n    \"node_modules/has-tostringtag\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz\",\n      \"integrity\": \"sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"has-symbols\": \"^1.0.3\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/ljharb\"\n      }\n    },\n    \"node_modules/hasown\": {\n      \"version\": \"2.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz\",\n      \"integrity\": \"sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"function-bind\": \"^1.1.2\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/math-intrinsics\": {\n      \"version\": \"1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz\",\n      \"integrity\": \"sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/mime-db\": {\n      \"version\": \"1.52.0\",\n      \"resolved\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz\",\n      \"integrity\": \"sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 0.6\"\n      }\n    },\n    \"node_modules/mime-types\": {\n      \"version\": \"2.1.35\",\n      \"resolved\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz\",\n      \"integrity\": \"sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"mime-db\": \"1.52.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.6\"\n      }\n    },\n    \"node_modules/proxy-from-env\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz\",\n      \"integrity\": \"sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/tslib\": {\n      \"version\": \"2.8.1\",\n      \"resolved\": \"https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz\",\n      \"integrity\": \"sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==\",\n      \"license\": \"0BSD\"\n    }\n  }\n}\n\nFile v1.2.3:package.json\n\n{\n  \"name\": \"m365-planner\",\n  \"version\": \"1.2.3\",\n  \"description\": \"Microsoft 365 Planner Skill for OpenClaw - Manage plans, buckets, and tasks via Graph API\",\n  \"main\": \"scripts/test-connection.js\",\n  \"scripts\": {\n    \"test\": \"node scripts/test-connection.js\",\n    \"list\": \"node scripts/list_plans.js\",\n    \"cleanup\": \"node scripts/cleanup_verlaengerungen.js\"\n  },\n  \"keywords\": [\n    \"microsoft\",\n    \"planner\",\n    \"m365\",\n    \"graph-api\",\n    \"openclaw\",\n    \"skill\"\n  ],\n  \"author\": \"OpenClaw Community\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"@microsoft/microsoft-graph-client\": \"^3.0.7\",\n    \"axios\": \"^1.15.0\"\n  }\n}\n\nArchive v1.2.2: 18 files, 27567 bytes\n\nFiles: CHANGELOG.md (5435b), package-lock.json (11786b), package.json (630b), references/common-patterns.md (1834b), references/planner-api.md (1803b), references/setup-guide.md (2023b), scripts/assign_task.sh (756b), scripts/cleanup_verlaengerungen.js (5138b), scripts/create_plan.js (3366b), scripts/create_plan.sh (965b), scripts/create_task.js (2884b), scripts/delete_task.js (2719b), scripts/list_plans.js (4920b), scripts/list_tasks.sh (867b), scripts/test_connection.js (3665b), scripts/test-connection.js (3773b), SKILL.md (11897b), _meta.json (134b)\n\nFile v1.2.2:SKILL.md\n\n---\nname: m365-planner\ndescription: Manage Microsoft 365 Planner plans, buckets, and tasks via Microsoft Graph API. Use when creating, listing, updating, or deleting Planner resources. Supports group-based plan management, task assignment, progress tracking, and recurring tasks. Requires Azure AD app registration with Group.Read.All and Tasks.ReadWrite.All permissions.\nlicense: MIT\nversion: 1.2.2\n---\n\n# M365 Planner Skill\n\nManage Microsoft 365 Planner through Microsoft Graph API.\n\n## What's New in v1.2.2\n\n- 🔧 **Portabilität** – Env-Pfad nutzt jetzt `os.homedir()` statt hardcoded `/home/claw/.openclaw/.env`\n- 🧹 **Security Cleanup** – Vollständiger Check auf sensible Daten (keine IDs, Namen, Domains)\n- 📦 **ClawHub-ready** – Tarball erstellt, node_modules ausgeschlossen\n\n## What's New in v1.2.1\n\n- ✅ **Generische Skripte** – Keine hardcoded Group-IDs oder Plan-Namen mehr\n- ✅ **Command-Line Parameter** – Alle Skripte akzeptieren IDs als Argumente\n- ✅ **List Plans verbessert** – Zeigt alle Gruppen wenn keine ID angegeben\n- ✅ **Cleanup Script flexibel** – Funktioniert mit beliebigen Plans/Buckets\n- ✅ **ClawHub-ready** – Keine projektspezifischen Daten mehr enthalten\n\n## What's New in v1.1.0\n\n- ✅ **Node.js Scripts** – Standalone scripts ohne `mgc` CLI\n- ✅ **If-Match Header Support** – Korrekte ETag-Behandlung für Updates/Löschungen\n- ✅ **Group-Based API** – Direkter Zugriff über M365 Group-ID\n- ✅ **Recurring Tasks** – Hinweis auf native Planner-Wiederholungsfunktion\n- ✅ **Cleanup Scripts** – Automatisierte Bereinigung von Tasks\n\n## Prerequisites\n\n1. Azure AD App Registration (see Setup below)\n2. Node.js v18+ mit `@microsoft/microsoft-graph-client` und `axios`\n3. M365 Group (kein Security Group oder Distribution List!)\n\n## Quick Start\n\n```bash\n# Connection testen\nnode scripts/test-connection.js\n\n# Alle Pläne anzeigen\nnode scripts/list_plans.js\n\n# Pläne einer spezifischen Gruppe anzeigen\nnode scripts/list_plans.js <group-id>\n\n# Plan erstellen\nnode scripts/create_plan.js \"Project Name\" <group-id>\n\n# Task erstellen\nnode scripts/create_task.js <plan-id> <bucket-id> \"Task Title\"\n\n# Abgeschlossene Tasks löschen\nnode scripts/cleanup_verlaengerungen.js <group-id> \"<plan-name>\" \"<bucket-name>\"\n```\n\n## Setup: Azure AD App Registration\n\n### Schritt 1: App Registration erstellen\n\n**Azure Portal:**\n1. https://portal.azure.com → Azure Active Directory → App registrations\n2. \"New registration\"\n3. Name: `M365-Planner-Integration`\n4. Supported account types: `Accounts in this organizational directory only`\n5. Redirect URI: None (Client Credentials Flow)\n\n**Oder per Azure CLI:**\n```bash\naz login\naz ad app create --display-name \"M365-Planner-Integration\" --sign-in-audience \"AzureADMyOrg\"\n```\nNotiere die **Application (client) ID** aus der Ausgabe.\n\n### Schritt 2: API Permissions hinzufügen\n\n**Wichtig:** Verwende **Application Permissions** (nicht Delegated)!\n\n**Azure Portal:**\n1. App → API permissions → Add a permission\n2. Microsoft Graph → Application permissions\n3. Hinzufügen:\n   - `Group.Read.All` (nicht Group.ReadWrite.All – reicht für Planner)\n   - `Tasks.ReadWrite.All`\n4. **Admin Consent erteilen:** \"Grant admin consent for [Tenant]\" klicken!\n\n**Oder per Azure CLI:**\n```bash\nAPP_ID=\"deine-app-id\"\n\n# Group.Read.All\naz ad app permission add \\\n  --id $APP_ID \\\n  --api 00000003-0000-0000-c000-000000000000 \\\n  --api-permissions 5b567253-7703-48e2-861c-caed61531407=Role\n\n# Tasks.ReadWrite.All\naz ad app permission add \\\n  --id $APP_ID \\\n  --api 00000003-0000-0000-c000-000000000000 \\\n  --api-permissions bdfbf15f-ee85-495a-99a9-ef9b2abb1dcb=Role\n\n# Admin Consent\naz ad app permission admin-consent --id $APP_ID\n```\n\n### Schritt 3: Client Secret erstellen\n\n**Azure Portal:**\n1. App → Certificates & secrets → Client secrets → New client secret\n2. Description: `OpenClaw Integration`\n3. Expires: 24 Monate (Maximum)\n4. **Werte sofort kopieren!** – Wird nur einmal angezeigt\n\n**Oder per Azure CLI:**\n```bash\naz ad app credential reset \\\n  --id $APP_ID \\\n  --append \\\n  --display-name \"OpenClaw Integration\"\n```\n\n### Schritt 4: Environment konfigurieren\n\nCredentials in `~/.openclaw/.env` speichern:\n\n```bash\n# Microsoft 365 Planner Credentials\nM365_CLIENT_ID=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\nM365_CLIENT_SECRET=\"your-secret-value\"\nM365_TENANT_ID=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\n```\n\n**Berechtigungen sichern:**\n```bash\nchmod 600 ~/.openclaw/.env\n```\n\n### Schritt 5: Verbindung testen\n\n```bash\nnode scripts/test-connection.js\n```\n\nErwartete Ausgabe:\n```\n✅ Access Token erfolgreich erhalten!\n📋 Test: M365 Groups...\n   3 Gruppen gefunden:\n   - My Team ✅ M365/Planner-fähig\n✅ Verbindung erfolgreich!\n```\n\n## Wichtige Hinweise\n\n### M365 Groups vs. Security Groups\n\n**Planner funktioniert NUR mit M365 Groups!**\n\n- ✅ **M365 Group** – Hat Exchange-Postfach, Teams, Planner (erkennbar an Mail-Attribut)\n- ❌ **Security Group** – Nur für Berechtigungen, kein Planner\n- ❌ **Distribution List** – Nur für E-Mail-Verteiler, kein Planner\n\n**Gruppen prüfen:**\n```bash\nnode scripts/test-connection.js\n```\nZeigt alle Gruppen mit Status \"✅ M365/Planner-fähig\" an.\n\n**M365 Group erstellen (falls keine existiert):**\n- Microsoft 365 Admin Center → Groups → Add a group\n- Oder Teams: Neues Team erstellen (erstellt automatisch M365 Group)\n\n### If-Match Header (ETag)\n\n**Alle Update- und Lösch-Operationen benötigen den `If-Match` Header!**\n\nPlanner verwendet Optimistic Concurrency Control. Ohne ETag schlägt die Anfrage fehl.\n\n**Beispiel Delete:**\n```javascript\n// Falsch ❌\nawait client.api(`/planner/tasks/${taskId}`).delete();\n\n// Richtig ✅\nconst task = await client.api(`/planner/tasks/${taskId}`).get();\nawait client.api(`/planner/tasks/${taskId}`)\n    .headers({ 'If-Match': task['@odata.etag'] })\n    .delete();\n```\n\n**Beispiel Update:**\n```javascript\nconst task = await client.api(`/planner/tasks/${taskId}`).get();\nawait client.api(`/planner/tasks/${taskId}`)\n    .headers({ 'If-Match': task['@odata.etag'] })\n    .update({ percentComplete: 50 });\n```\n\n### Group-Based API Endpoints\n\n**Nicht verwenden:**\n```\nGET /planner/plans  ❌ (braucht komplexen Filter)\n```\n\n**Verwenden:**\n```\nGET /groups/{group-id}/planner/plans  ✅\n```\n\n**Beispiel:**\n```javascript\nconst plans = await client.api(`/groups/${groupId}/planner/plans`).get();\n```\n\n### Recurring Tasks (Wiederkehrende Aufgaben)\n\n**Microsoft Planner unterstützt native wiederkehrende Tasks!**\n\nIn der Planner Web-UI oder Mobile App:\n1. Task öffnen\n2. \"Repeat\" / \"Wiederholen\" klicken\n3. Frequenz wählen: Täglich, Wöchentlich, Monatlich, Jährlich, Benutzerdefiniert\n\n**Beispiel:**\n- \"Domain-Verlängerung example.com\" → Jährlich wiederholen\n- \"Backup prüfen\" → Wöchentlich wiederholen\n\n⚠️ **API-Limit:** Die Graph API unterstützt das Erstellen von recurring Tasks nicht direkt. \nWiederkehrende Tasks müssen über die Planner UI eingerichtet werden.\n\n## Common Operations\n\n### Plans\n\n| Operation | Script |\n|-----------|--------|\n| List all plans | `node scripts/list_plans.js` |\n| Create plan | `node scripts/create_plan.js <name> <group-id>` |\n| Delete plan | `node scripts/delete_plan.js <plan-id>` |\n\n### Buckets\n\n| Operation | Script |\n|-----------|--------|\n| List buckets | In `list_plans.js` integriert |\n| Create bucket | `node scripts/create_bucket.js <plan-id> <name>` |\n| Delete bucket | `node scripts/delete_bucket.js <bucket-id>` |\n\n### Tasks\n\n| Operation | Script |\n|-----------|--------|\n| List tasks | In `list_plans.js` integriert |\n| Create task | `node scripts/create_task.js <plan-id> <bucket-id> <title>` |\n| Update task | `node scripts/update_task.js <task-id> --percent-complete 50` |\n| Delete task | `node scripts/delete_task.js <task-id>` |\n| Cleanup | `node scripts/cleanup_verlaengerungen.js <group-id> \"<plan-name>\" \"<bucket-name>\"` |\n\n## Helper Scripts\n\n### test-connection.js\nTestet die Verbindung zu Microsoft Graph:\n- Access Token anfordern\n- Tenant-Informationen anzeigen\n- Verfügbare M365 Groups auflisten\n- Planner-Fähigkeit prüfen\n\n```bash\nnode scripts/test-connection.js\n```\n\n### list_plans.js\nZeigt alle Pläne einer M365 Group mit:\n- Buckets und deren Tasks\n- Task-Status (erledigt/in Arbeit/offen)\n- Prozentuale Fortschrittsanzeige\n\n```bash\n# Ohne Argument: Zeigt alle verfügbaren Gruppen\nnode scripts/list_plans.js\n\n# Mit Group ID: Zeigt Pläne der spezifischen Gruppe\nnode scripts/list_plans.js <group-id>\n```\n\n### create_plan.js\nErstellt einen neuen Plan mit Standard-Buckets:\n- To Do\n- In Progress  \n- Done\n\n```bash\nnode scripts/create_plan.js \"Project Alpha\" <group-id>\n```\n\n### cleanup_verlaengerungen.js\nBereinigt abgeschlossene Tasks aus einem Bucket:\n- Löscht Tasks mit 100% Fortschritt\n- Behält offene Tasks\n- Korrekte If-Match Header Behandlung\n\n```bash\nnode scripts/cleanup_verlaengerungen.js <group-id> \"<plan-name>\" \"<bucket-name>\"\n```\n\n**Beispiel:**\n```bash\nnode scripts/cleanup_verlaengerungen.js abc-123 \"My Project\" \"Completed\"\n```\n\n## Troubleshooting\n\n### Error: Insufficient privileges\n\n**Ursache:** Admin Consent nicht erteilt\n\n**Lösung:**\n```bash\naz ad app permission admin-consent --id <app-id>\n```\nOder im Azure Portal: API permissions → Grant admin consent\n\n### Error: Group not found\n\n**Ursache:** Planner funktioniert nur mit M365 Groups\n\n**Lösung:**\n1. Prüfe ob es eine M365 Group ist (hat Mail-Attribut)\n2. Security Groups/Distribution Lists funktionieren nicht\n3. Neue M365 Group erstellen (Teams oder Admin Center)\n\n### Error: The If-Match header must be specified\n\n**Ursache:** Update/Delete ohne ETag\n\n**Lösung:**\n```javascript\n// Erst Task holen für ETag\nconst task = await client.api(`/planner/tasks/${id}`).get();\n// Dann mit If-Match Header updaten/löschen\nawait client.api(`/planner/tasks/${id}`)\n    .headers({ 'If-Match': task['@odata.etag'] })\n    .delete();\n```\n\n### Error: This entity set must be queried with a filter\n\n**Ursache:** `/planner/plans` Endpoint braucht Filter\n\n**Lösung:** Group-basierten Endpoint verwenden:\n```javascript\n// Falsch ❌\nconst plans = await client.api('/planner/plans').get();\n\n// Richtig ✅\nconst plans = await client.api(`/groups/${groupId}/planner/plans`).get();\n```\n\n### Error: Cannot find module '@microsoft/microsoft-graph-client'\n\n**Ursache:** Node.js Pakete nicht installiert\n\n**Lösung:**\n```bash\ncd ~/.openclaw/workspace/skills/m365-planner\nnpm install\n```\n\n## Dependencies\n\nPakete lokal im Skill-Verzeichnis installieren:\n\n```bash\ncd ~/.openclaw/workspace/skills/m365-planner\nnpm install @microsoft/microsoft-graph-client axios\n```\n\n## References\n\n- [Planner API Overview](references/planner-api.md)\n- [Setup Guide](references/setup-guide.md)\n- [Common Patterns](references/common-patterns.md)\n- [Microsoft Graph API Docs](https://docs.microsoft.com/en-us/graph/api/overview)\n- [Planner REST API Reference](https://docs.microsoft.com/en-us/graph/api/resources/planner-overview)\n\n## Changelog\n\n### v1.2.1 (2026-04-18)\n- ✅ **Generische Skripte** – Keine hardcoded Group-IDs oder Plan-Namen mehr\n- ✅ **Command-Line Parameter** – Alle Skripte akzeptieren IDs als Argumente\n- ✅ **List Plans verbessert** – Zeigt alle Gruppen wenn keine ID angegeben\n- ✅ **Cleanup Script flexibel** – Funktioniert mit beliebigen Plans/Buckets\n- ✅ **ClawHub-ready** – Keine projektspezifischen Daten mehr enthalten\n\n### v1.1.0 (2026-04-17)\n- ✅ Node.js Scripts statt mgc CLI\n- ✅ If-Match Header Support für Updates/Löschungen\n- ✅ Group-based API Endpoints\n- ✅ Test-Connection Script mit M365 Group Detection\n- ✅ List Plans Script mit Bucket/Task-Übersicht\n- ✅ Cleanup Script für abgeschlossene Tasks\n- ✅ Dokumentation zu recurring Tasks (native Planner Feature)\n- ✅ Troubleshooting Section erweitert\n\n### v1.0.0 (2023-01-19)\n- Initiale Version mit mgc CLI\n- Azure AD Setup Guide\n- Grundlegende CRUD-Operationen\n\nFile v1.2.2:_meta.json\n\n{\n  \"ownerId\": \"kn73k7k4tnef2q480xd4y7dnkx82nhzj\",\n  \"slug\": \"m365-planner-v2\",\n  \"version\": \"1.2.2\",\n  \"publishedAt\": 1776517447030\n}\n\nFile v1.2.2:references/common-patterns.md\n\n# Common Patterns for M365 Planner\n\n## Pattern 1: Create Project Structure\n\nCreate a complete project with predefined buckets:\n\n```bash\n# 1. Create or get group\nGROUP_ID=$(az ad group list --query \"[?displayName=='Project Team'].id\" -o tsv)\n\n# 2. Create plan with buckets (using helper script)\n./scripts/create_plan.sh \"Website Redesign\" \"$GROUP_ID\"\n```\n\n## Pattern 2: Bulk Task Import\n\nCreate multiple tasks from a list:\n\n```bash\nBUCKET_ID=\"your-bucket-id\"\n\ncat tasks.txt | while read -r TASK; do\n    mgc planner tasks create \\\n        --title \"$TASK\" \\\n        --bucket-id \"$BUCKET_ID\" \\\n        --output none\n    echo \"Created: $TASK\"\ndone\n```\n\n## Pattern 3: Task Status Update\n\nUpdate task progress:\n\n```bash\nTASK_ID=\"your-task-id\"\n\n# Mark as in progress (50%)\nmgc planner tasks patch \\\n    --planner-task-id \"$TASK_ID\" \\\n    --percent-complete 50\n\n# Mark as complete (100%)\nmgc planner tasks patch \\\n    --planner-task-id \"$TASK_ID\" \\\n    --percent-complete 100\n```\n\n## Pattern 4: Weekly Report\n\nGenerate a task summary:\n\n```bash\nPLAN_ID=\"your-plan-id\"\n\n# Get all tasks\necho \"Weekly Planner Report\"\necho \"====================\"\n./scripts/list_tasks.sh \"$PLAN_ID\"\n```\n\n## Pattern 5: Assign Tasks to Team\n\nAssign tasks to multiple users:\n\n```bash\n# Get user IDs\nUSER1=$(az ad user show --id \"alice@company.com\" --query id -o tsv)\nUSER2=$(az ad user show --id \"bob@company.com\" --query id -o tsv)\n\n# Assign tasks\n./scripts/assign_task.sh \"task-id-1\" \"$USER1\"\n./scripts/assign_task.sh \"task-id-2\" \"$USER2\"\n```\n\n## JSON Output Processing\n\nMany commands support `--output json` for automation:\n\n```bash\n# Extract specific fields\nmgc planner plans list --output json | \\\n    jq -r '.value[] | select(.title | contains(\"Project\")) | .id'\n\n# Save to file\nmgc planner tasks list --planner-bucket-id \"$BUCKET\" --output json > tasks.json\n```\n\nFile v1.2.2:references/planner-api.md\n\n# Microsoft Planner API Reference\n\n## Core Resources\n\n### plannerPlan\nRepresents a plan in Planner. Always associated with a Microsoft 365 group.\n\n**Key Properties:**\n- `id` – Unique identifier\n- `title` – Plan name\n- `owner` – Group ID that owns the plan\n- `createdDateTime` – Creation timestamp\n\n**Relationships:**\n- `buckets` – Collection of buckets in the plan\n- `tasks` – Collection of tasks in the plan\n\n### plannerBucket\nContainer for tasks within a plan. Represents stages or categories.\n\n**Key Properties:**\n- `id` – Unique identifier\n- `name` – Bucket name\n- `planId` – Parent plan ID\n- `orderHint` – Sorting hint\n\n### plannerTask\nIndividual work item in Planner.\n\n**Key Properties:**\n- `id` – Unique identifier\n- `title` – Task title\n- `bucketId` – Parent bucket ID\n- `planId` – Parent plan ID\n- `percentComplete` – Progress (0, 50, or 100)\n- `assignedTo` – User assignment\n- `dueDateTime` – Due date\n- `priority` – Priority (1=urgent, 3=normal, 5=low)\n\n## API Endpoints\n\n### Plans\n```\nGET    /planner/plans\nPOST   /planner/plans\nGET    /planner/plans/{id}\nPATCH  /planner/plans/{id}\nDELETE /planner/plans/{id}\n```\n\n### Buckets\n```\nGET    /planner/buckets\nPOST   /planner/buckets\nGET    /planner/buckets/{id}\nDELETE /planner/buckets/{id}\n```\n\n### Tasks\n```\nGET    /planner/tasks\nPOST   /planner/tasks\nGET    /planner/tasks/{id}\nPATCH  /planner/tasks/{id}\nDELETE /planner/tasks/{id}\n```\n\n## Required Permissions\n\n| Permission Type | Needed |\n|----------------|--------|\n| Delegated (work/school) | Group.ReadWrite.All, Tasks.ReadWrite |\n| Application | Group.ReadWrite.All, Tasks.ReadWrite |\n\n## Constraints\n\n- Plans require M365 Groups (no standalone plans)\n- Maximum 10 buckets per plan\n- Maximum 200 active tasks per plan\n- Plan names: max 64 characters\n\nFile v1.2.2:references/setup-guide.md\n\n# Detailed Setup Guide\n\n## Azure AD App Registration - Step by Step\n\n### 1. Portal Method (Browser)\n\n1. Go to https://portal.azure.com → Azure Active Directory → App registrations\n2. Click \"New registration\"\n3. Enter:\n   - Name: `M365-Planner-Integration`\n   - Supported account types: `Accounts in this organizational directory only`\n   - Redirect URI: None (for client credentials flow)\n4. Click \"Register\"\n5. Note the **Application (client) ID** and **Directory (tenant) ID**\n\n### 2. Add API Permissions\n\n1. Go to \"API permissions\" → \"Add a permission\"\n2. Select \"Microsoft Graph\" → \"Application permissions\"\n3. Add:\n   - `Group.ReadWrite.All`\n   - `Tasks.ReadWrite`\n4. Click \"Grant admin consent for [tenant]\"\n\n### 3. Create Client Secret\n\n1. Go to \"Certificates & secrets\" → \"Client secrets\" → \"New client secret\"\n2. Description: `OpenClaw Integration`\n3. Expires: Select duration (24 months max)\n4. Copy the **Value** (shown only once!)\n\n### 4. Environment Configuration\n\nCreate `~/.openclaw/.env`:\n\n```bash\n# M365 Planner Integration\nM365_CLIENT_ID=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\nM365_CLIENT_SECRET=\"your-secret-value\"\nM365_TENANT_ID=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\n```\n\n### 5. Test Authentication\n\n```bash\n# Using mgc with client credentials\nmgc login --strategy ClientSecret \\\n  --client-id $M365_CLIENT_ID \\\n  --client-secret $M365_CLIENT_SECRET \\\n  --tenant-id $M365_TENANT_ID\n\n# Verify access\nmgc me get\n```\n\n## Finding Group IDs\n\nPlanner plans require M365 groups. Find your groups:\n\n```bash\n# List all groups\nmgc groups list --output table --select displayName,id\n\n# Or use Azure CLI\naz ad group list --query \"[].{Name:displayName, ID:id}\" -o table\n```\n\n## Common Issues\n\n### \"Insufficient privileges\"\nSolution: Grant admin consent in Azure Portal → API permissions → Grant admin consent\n\n### \"Group not found\"\nSolution: Ensure you're using an M365 group, not a security group or distribution list\n\n### \"Invalid authentication token\"\nSolution: Token expired. Re-run `mgc login`\n\nFile v1.2.2:CHANGELOG.md\n\n# Changelog - m365-planner Skill\n\nAlle wesentlichen Änderungen am m365-planner Skill werden in dieser Datei dokumentiert.\n\n## [1.2.2] - 2026-04-18\n\n### 🔧 Geändert\n\n**Portabilität verbessert:**\n- Env-Pfad in allen Scripts von hardcoded `/home/claw/.openclaw/.env` zu `path.join(os.homedir(), '.openclaw', '.env')` geändert\n- Skill funktioniert jetzt auf jedem System ohne Anpassungen\n- ClawHub-ready: Keine systemspezifischen Pfade mehr\n\n### 🧹 Bereinigt\n\n**Security & Privacy:**\n- Vollständiger Check auf hardcoded sensible Daten (Group-IDs, Tenant-IDs, Client-IDs, Domains, Namen)\n- Keine projektspezifischen Daten mehr enthalten\n- Alle Scripts verwenden jetzt generische, portabel Pfade\n\n### 📦 Packaging\n\n**Für ClawHub vorbereitet:**\n- Tarball erstellt (`m365-planner-v1.2.2.tar.gz`)\n- Nur notwendige Dateien enthalten (SKILL.md, Scripts, References, Package-Files)\n- node_modules ausgeschlossen (wird separat installiert)\n\n---\n\n## [1.2.1] - 2026-04-18\n\n### 🎉 Hinzugefügt\n\n**Node.js Scripts (ersetzen mgc CLI Abhängigkeit):**\n- `scripts/test-connection.js` – Verbindungstest mit M365 Group Detection\n- `scripts/list_plans.js` – Vollständige Plan/Bucket/Task Übersicht\n- `scripts/create_plan.js` – Plan-Erstellung mit Standard-Buckets\n- `scripts/cleanup_verlaengerungen.js` – Automatisierte Bereinigung abgeschlossener Tasks\n\n**Dokumentation:**\n- If-Match Header / ETag Behandlung für Updates und Löschungen\n- Group-based API Endpoints (`/groups/{id}/planner/plans`)\n- M365 Groups vs. Security Groups Erklärung\n- Native Planner Recurring Tasks Dokumentation\n- Erweiterte Troubleshooting Section\n\n### 🔧 Geändert\n\n**Setup-Prozess:**\n- Keine `mgc` CLI mehr erforderlich\n- Node.js Pakete (`@microsoft/microsoft-graph-client`, `axios`) ausreichend\n- Credentials in `~/.openclaw/.env` (nicht im Script)\n- Admin Consent explizit dokumentiert\n\n**API Usage:**\n- Von `/planner/plans` zu `/groups/{id}/planner/plans` gewechselt\n- Automatische ETag-Behandlung in allen Scripts\n- Bessere Fehlermeldungen bei Permissions-Problemen\n\n### 🐛 Behoben\n\n- **If-Match Header Error** – Alle Delete/Update Operations senden jetzt korrekten ETag\n- **Group Filter Error** – Plans werden jetzt über Group-ID abgefragt\n- **Module Not Found** – Lokale npm Installation im Skill-Verzeichnis\n\n### 📝 Technical Notes\n\n**Wichtige Erkenntnisse aus der Implementierung:**\n\n1. **If-Match Header ist zwingend erforderlich**\n   - Planner verwendet Optimistic Concurrency Control\n   - Ohne `If-Match: <etag>` Header schlagen DELETE/PATCH Requests fehl\n   - Lösung: Immer zuerst Resource holen, dann ETag verwenden\n\n2. **Nur M365 Groups unterstützen Planner**\n   - Security Groups ❌\n   - Distribution Lists ❌\n   - M365 Groups (mit Exchange Postfach) ✅\n   - Erkennung: `mail` Attribut oder `resourceProvisioningOptions` enthält \"Team\"\n\n3. **Recurring Tasks nur über UI**\n   - Microsoft Graph API unterstützt keine Erstellung von recurring tasks\n   - Wiederholung muss in Planner Web/Mobile UI eingerichtet werden\n   - Frequenzen: Täglich, Wöchentlich, Monatlich, Jährlich, Benutzerdefiniert\n\n4. **Credentials sicher speichern**\n   - `.env` Datei mit chmod 600 schützen\n   - Client Secret wird nur einmal angezeigt\n   - Bei Kompromittierung: Sofort im Azure Portal widerrufen\n\n### 📦 Dependencies\n\n```json\n{\n  \"@microsoft/microsoft-graph-client\": \"^3.0.7\",\n  \"axios\": \"^1.x\"\n}\n```\n\n### 🔐 Required Azure Permissions\n\n- `Group.Read.All` (Application)\n- `Tasks.ReadWrite.All` (Application)\n- Admin Consent erforderlich!\n\n---\n\n## [1.0.0] - 2023-01-19\n\n### 🎉 Initiale Version\n\n- Microsoft Graph CLI (`mgc`) Integration\n- Azure AD App Registration Setup Guide\n- CRUD Operationen für Plans, Buckets, Tasks\n- Bash Scripts für Workflows\n- Troubleshooting Guide\n\n### 📦 Dependencies\n\n- `mgc` CLI (Microsoft Graph CLI)\n- Azure CLI (`az`)\n\n---\n\n## Migration Guide: v1.0.0 → v1.1.0\n\n### Was sich ändert\n\n| v1.0.0 | v1.1.0 |\n|--------|--------|\n| `mgc` CLI erforderlich | Node.js Scripts (kein mgc) |\n| Globale CLI Installation | Lokale npm Pakete im Skill |\n| Manuelle ETag Behandlung | Automatisch in Scripts |\n| `/planner/plans` Endpoint | `/groups/{id}/planner/plans` |\n\n### Update-Schritte\n\n1. **Node.js Pakete installieren:**\n   ```bash\n   cd ~/.openclaw/workspace/skills/m365-planner\n   npm install\n   ```\n\n2. **Credentials prüfen:**\n   ```bash\n   # In ~/.openclaw/.env sicherstellen:\n   M365_CLIENT_ID=\"...\"\n   M365_CLIENT_SECRET=\"...\"\n   M365_TENANT_ID=\"...\"\n   ```\n\n3. **Verbindung testen:**\n   ```bash\n   node scripts/test-connection.js\n   ```\n\n4. **Alte Scripts (optional) archivieren:**\n   ```bash\n   mv scripts/*.sh scripts/archive/\n   ```\n\n### Breaking Changes\n\n- ❌ `mgc` CLI wird nicht mehr verwendet\n- ❌ Alte Bash Scripts sind veraltet (aber noch funktionsfähig)\n- ✅ Alle Features sind in Node.js Scripts verfügbar\n\n---\n\n## Bekannte Einschränkungen\n\n1. **Recurring Tasks** können nicht per API erstellt werden\n   - Workaround: In Planner UI einrichten\n   - Oder: Cron-Job für Task-Neuerstellung\n\n2. **Task Assignments** erfordern User-IDs\n   - User-ID muss bekannt sein (über `/users` Endpoint ermittelbar)\n\n3. **Planner Plan Löschung** löscht alle enthaltenen Tasks\n   - Vorher Backup erwägen\n\n---\n\n## Support\n\nBei Fragen oder Problemen:\n- OpenClaw Discord: https://discord.com/invite/clawd\n- ClawHub: https://clawhub.ai\n- Microsoft Graph Docs: https://docs.microsoft.com/graph\n\nFile v1.2.2:package-lock.json\n\n{\n  \"name\": \"m365-planner\",\n  \"version\": \"1.0.0\",\n  \"lockfileVersion\": 3,\n  \"requires\": true,\n  \"packages\": {\n    \"\": {\n      \"name\": \"m365-planner\",\n      \"version\": \"1.0.0\",\n      \"license\": \"ISC\",\n      \"dependencies\": {\n        \"@microsoft/microsoft-graph-client\": \"^3.0.7\",\n        \"axios\": \"^1.15.0\"\n      }\n    },\n    \"node_modules/@babel/runtime\": {\n      \"version\": \"7.29.2\",\n      \"resolved\": \"https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz\",\n      \"integrity\": \"sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=6.9.0\"\n      }\n    },\n    \"node_modules/@microsoft/microsoft-graph-client\": {\n      \"version\": \"3.0.7\",\n      \"resolved\": \"https://registry.npmjs.org/@microsoft/microsoft-graph-client/-/microsoft-graph-client-3.0.7.tgz\",\n      \"integrity\": \"sha512-/AazAV/F+HK4LIywF9C+NYHcJo038zEnWkteilcxC1FM/uK/4NVGDKGrxx7nNq1ybspAroRKT4I1FHfxQzxkUw==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@babel/runtime\": \"^7.12.5\",\n        \"tslib\": \"^2.2.0\"\n      },\n      \"engines\": {\n        \"node\": \">=12.0.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"@azure/identity\": {\n          \"optional\": true\n        },\n        \"@azure/msal-browser\": {\n          \"optional\": true\n        },\n        \"buffer\": {\n          \"optional\": true\n        },\n        \"stream-browserify\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/asynckit\": {\n      \"version\": \"0.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz\",\n      \"integrity\": \"sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==\",\n      \"license\": \"MIT\"\n    },\n    \"node_modules/axios\": {\n      \"version\": \"1.15.0\",\n      \"resolved\": \"https://registry.npmjs.org/axios/-/axios-1.15.0.tgz\",\n      \"integrity\": \"sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"follow-redirects\": \"^1.15.11\",\n        \"form-data\": \"^4.0.5\",\n        \"proxy-from-env\": \"^2.1.0\"\n      }\n    },\n    \"node_modules/call-bind-apply-helpers\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz\",\n      \"integrity\": \"sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"es-errors\": \"^1.3.0\",\n        \"function-bind\": \"^1.1.2\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/combined-stream\": {\n      \"version\": \"1.0.8\",\n      \"resolved\": \"https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz\",\n      \"integrity\": \"sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"delayed-stream\": \"~1.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.8\"\n      }\n    },\n    \"node_modules/delayed-stream\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz\",\n      \"integrity\": \"sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=0.4.0\"\n      }\n    },\n    \"node_modules/dunder-proto\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz\",\n      \"integrity\": \"sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"call-bind-apply-helpers\": \"^1.0.1\",\n        \"es-errors\": \"^1.3.0\",\n        \"gopd\": \"^1.2.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/es-define-property\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz\",\n      \"integrity\": \"sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/es-errors\": {\n      \"version\": \"1.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz\",\n      \"integrity\": \"sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/es-object-atoms\": {\n      \"version\": \"1.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz\",\n      \"integrity\": \"sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"es-errors\": \"^1.3.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/es-set-tostringtag\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz\",\n      \"integrity\": \"sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"es-errors\": \"^1.3.0\",\n        \"get-intrinsic\": \"^1.2.6\",\n        \"has-tostringtag\": \"^1.0.2\",\n        \"hasown\": \"^2.0.2\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/follow-redirects\": {\n      \"version\": \"1.16.0\",\n      \"resolved\": \"https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz\",\n      \"integrity\": \"sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==\",\n      \"funding\": [\n        {\n          \"type\": \"individual\",\n          \"url\": \"https://github.com/sponsors/RubenVerborgh\"\n        }\n      ],\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=4.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"debug\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/form-data\": {\n      \"version\": \"4.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz\",\n      \"integrity\": \"sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"asynckit\": \"^0.4.0\",\n        \"combined-stream\": \"^1.0.8\",\n        \"es-set-tostringtag\": \"^2.1.0\",\n        \"hasown\": \"^2.0.2\",\n        \"mime-types\": \"^2.1.12\"\n      },\n      \"engines\": {\n        \"node\": \">= 6\"\n      }\n    },\n    \"node_modules/function-bind\": {\n      \"version\": \"1.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz\",\n      \"integrity\": \"sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==\",\n      \"license\": \"MIT\",\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/ljharb\"\n      }\n    },\n    \"node_modules/get-intrinsic\": {\n      \"version\": \"1.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz\",\n      \"integrity\": \"sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"call-bind-apply-helpers\": \"^1.0.2\",\n        \"es-define-property\": \"^1.0.1\",\n        \"es-errors\": \"^1.3.0\",\n        \"es-object-atoms\": \"^1.1.1\",\n        \"function-bind\": \"^1.1.2\",\n        \"get-proto\": \"^1.0.1\",\n        \"gopd\": \"^1.2.0\",\n        \"has-symbols\": \"^1.1.0\",\n        \"hasown\": \"^2.0.2\",\n        \"math-intrinsics\": \"^1.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/ljharb\"\n      }\n    },\n    \"node_modules/get-proto\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz\",\n      \"integrity\": \"sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"dunder-proto\": \"^1.0.1\",\n        \"es-object-atoms\": \"^1.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/gopd\": {\n      \"version\": \"1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz\",\n      \"integrity\": \"sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/ljharb\"\n      }\n    },\n    \"node_modules/has-symbols\": {\n      \"version\": \"1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz\",\n      \"integrity\": \"sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/ljharb\"\n      }\n    },\n    \"node_modules/has-tostringtag\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz\",\n      \"integrity\": \"sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"has-symbols\": \"^1.0.3\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/ljharb\"\n      }\n    },\n    \"node_modules/hasown\": {\n      \"version\": \"2.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz\",\n      \"integrity\": \"sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"function-bind\": \"^1.1.2\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/math-intrinsics\": {\n      \"version\": \"1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz\",\n      \"integrity\": \"sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/mime-db\": {\n      \"version\": \"1.52.0\",\n      \"resolved\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz\",\n      \"integrity\": \"sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 0.6\"\n      }\n    },\n    \"node_modules/mime-types\": {\n      \"version\": \"2.1.35\",\n      \"resolved\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz\",\n      \"integrity\": \"sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"mime-db\": \"1.52.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.6\"\n      }\n    },\n    \"node_modules/proxy-from-env\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz\",\n      \"integrity\": \"sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/tslib\": {\n      \"version\": \"2.8.1\",\n      \"resolved\": \"https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz\",\n      \"integrity\": \"sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==\",\n      \"license\": \"0BSD\"\n    }\n  }\n}\n\nFile v1.2.2:package.json\n\n{\n  \"name\": \"m365-planner\",\n  \"version\": \"1.2.2\",\n  \"description\": \"Microsoft 365 Planner Skill for OpenClaw - Manage plans, buckets, and tasks via Graph API\",\n  \"main\": \"scripts/test-connection.js\",\n  \"scripts\": {\n    \"test\": \"node scripts/test-connection.js\",\n    \"list\": \"node scripts/list_plans.js\",\n    \"cleanup\": \"node scripts/cleanup_verlaengerungen.js\"\n  },\n  \"keywords\": [\n    \"microsoft\",\n    \"planner\",\n    \"m365\",\n    \"graph-api\",\n    \"openclaw\",\n    \"skill\"\n  ],\n  \"author\": \"OpenClaw Community\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"@microsoft/microsoft-graph-client\": \"^3.0.7\",\n    \"axios\": \"^1.15.0\"\n  }\n}\n\nArchive v1.2.1: 17 files, 24465 bytes\n\nFiles: package-lock.json (11786b), package.json (630b), references/common-patterns.md (1834b), references/planner-api.md (1803b), references/setup-guide.md (2023b), scripts/assign_task.sh (756b), scripts/cleanup_verlaengerungen.js (5036b), scripts/create_plan.js (3264b), scripts/create_plan.sh (965b), scripts/create_task.js (2782b), scripts/delete_task.js (2617b), scripts/list_plans.js (4843b), scripts/list_tasks.sh (867b), scripts/test_connection.js (3618b), scripts/test-connection.js (3696b), SKILL.md (11587b), _meta.json (134b)\n\nFile v1.2.1:SKILL.md\n\n---\nname: m365-planner\ndescription: Manage Microsoft 365 Planner plans, buckets, and tasks via Microsoft Graph API. Use when creating, listing, updating, or deleting Planner resources. Supports group-based plan management, task assignment, progress tracking, and recurring tasks. Requires Azure AD app registration with Group.Read.All and Tasks.ReadWrite.All permissions.\nlicense: MIT\nversion: 1.2.1\n---\n\n# M365 Planner Skill\n\nManage Microsoft 365 Planner through Microsoft Graph API.\n\n## What's New in v1.2.1\n\n- ✅ **Generische Skripte** – Keine hardcoded Group-IDs oder Plan-Namen mehr\n- ✅ **Command-Line Parameter** – Alle Skripte akzeptieren IDs als Argumente\n- ✅ **List Plans verbessert** – Zeigt alle Gruppen wenn keine ID angegeben\n- ✅ **Cleanup Script flexibel** – Funktioniert mit beliebigen Plans/Buckets\n- ✅ **ClawHub-ready** – Keine projektspezifischen Daten mehr enthalten\n\n## What's New in v1.1.0\n\n- ✅ **Node.js Scripts** – Standalone scripts ohne `mgc` CLI\n- ✅ **If-Match Header Support** – Korrekte ETag-Behandlung für Updates/Löschungen\n- ✅ **Group-Based API** – Direkter Zugriff über M365 Group-ID\n- ✅ **Recurring Tasks** – Hinweis auf native Planner-Wiederholungsfunktion\n- ✅ **Cleanup Scripts** – Automatisierte Bereinigung von Tasks\n\n## Prerequisites\n\n1. Azure AD App Registration (see Setup below)\n2. Node.js v18+ mit `@microsoft/microsoft-graph-client` und `axios`\n3. M365 Group (kein Security Group oder Distribution List!)\n\n## Quick Start\n\n```bash\n# Connection testen\nnode scripts/test-connection.js\n\n# Alle Pläne anzeigen\nnode scripts/list_plans.js\n\n# Pläne einer spezifischen Gruppe anzeigen\nnode scripts/list_plans.js <group-id>\n\n# Plan erstellen\nnode scripts/create_plan.js \"Project Name\" <group-id>\n\n# Task erstellen\nnode scripts/create_task.js <plan-id> <bucket-id> \"Task Title\"\n\n# Abgeschlossene Tasks löschen\nnode scripts/cleanup_verlaengerungen.js <group-id> \"<plan-name>\" \"<bucket-name>\"\n```\n\n## Setup: Azure AD App Registration\n\n### Schritt 1: App Registration erstellen\n\n**Azure Portal:**\n1. https://portal.azure.com → Azure Active Directory → App registrations\n2. \"New registration\"\n3. Name: `M365-Planner-Integration`\n4. Supported account types: `Accounts in this organizational directory only`\n5. Redirect URI: None (Client Credentials Flow)\n\n**Oder per Azure CLI:**\n```bash\naz login\naz ad app create --display-name \"M365-Planner-Integration\" --sign-in-audience \"AzureADMyOrg\"\n```\nNotiere die **Application (client) ID** aus der Ausgabe.\n\n### Schritt 2: API Permissions hinzufügen\n\n**Wichtig:** Verwende **Application Permissions** (nicht Delegated)!\n\n**Azure Portal:**\n1. App → API permissions → Add a permission\n2. Microsoft Graph → Application permissions\n3. Hinzufügen:\n   - `Group.Read.All` (nicht Group.ReadWrite.All – reicht für Planner)\n   - `Tasks.ReadWrite.All`\n4. **Admin Consent erteilen:** \"Grant admin consent for [Tenant]\" klicken!\n\n**Oder per Azure CLI:**\n```bash\nAPP_ID=\"deine-app-id\"\n\n# Group.Read.All\naz ad app permission add \\\n  --id $APP_ID \\\n  --api 00000003-0000-0000-c000-000000000000 \\\n  --api-permissions 5b567253-7703-48e2-861c-caed61531407=Role\n\n# Tasks.ReadWrite.All\naz ad app permission add \\\n  --id $APP_ID \\\n  --api 00000003-0000-0000-c000-000000000000 \\\n  --api-permissions bdfbf15f-ee85-495a-99a9-ef9b2abb1dcb=Role\n\n# Admin Consent\naz ad app permission admin-consent --id $APP_ID\n```\n\n### Schritt 3: Client Secret erstellen\n\n**Azure Portal:**\n1. App → Certificates & secrets → Client secrets → New client secret\n2. Description: `OpenClaw Integration`\n3. Expires: 24 Monate (Maximum)\n4. **Werte sofort kopieren!** – Wird nur einmal angezeigt\n\n**Oder per Azure CLI:**\n```bash\naz ad app credential reset \\\n  --id $APP_ID \\\n  --append \\\n  --display-name \"OpenClaw Integration\"\n```\n\n### Schritt 4: Environment konfigurieren\n\nCredentials in `~/.openclaw/.env` speichern:\n\n```bash\n# Microsoft 365 Planner Credentials\nM365_CLIENT_ID=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\nM365_CLIENT_SECRET=\"your-secret-value\"\nM365_TENANT_ID=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\n```\n\n**Berechtigungen sichern:**\n```bash\nchmod 600 ~/.openclaw/.env\n```\n\n### Schritt 5: Verbindung testen\n\n```bash\nnode scripts/test-connection.js\n```\n\nErwartete Ausgabe:\n```\n✅ Access Token erfolgreich erhalten!\n📋 Test: M365 Groups...\n   3 Gruppen gefunden:\n   - My Team ✅ M365/Planner-fähig\n✅ Verbindung erfolgreich!\n```\n\n## Wichtige Hinweise\n\n### M365 Groups vs. Security Groups\n\n**Planner funktioniert NUR mit M365 Groups!**\n\n- ✅ **M365 Group** – Hat Exchange-Postfach, Teams, Planner (erkennbar an Mail-Attribut)\n- ❌ **Security Group** – Nur für Berechtigungen, kein Planner\n- ❌ **Distribution List** – Nur für E-Mail-Verteiler, kein Planner\n\n**Gruppen prüfen:**\n```bash\nnode scripts/test-connection.js\n```\nZeigt alle Gruppen mit Status \"✅ M365/Planner-fähig\" an.\n\n**M365 Group erstellen (falls keine existiert):**\n- Microsoft 365 Admin Center → Groups → Add a group\n- Oder Teams: Neues Team erstellen (erstellt automatisch M365 Group)\n\n### If-Match Header (ETag)\n\n**Alle Update- und Lösch-Operationen benötigen den `If-Match` Header!**\n\nPlanner verwendet Optimistic Concurrency Control. Ohne ETag schlägt die Anfrage fehl.\n\n**Beispiel Delete:**\n```javascript\n// Falsch ❌\nawait client.api(`/planner/tasks/${taskId}`).delete();\n\n// Richtig ✅\nconst task = await client.api(`/planner/tasks/${taskId}`).get();\nawait client.api(`/planner/tasks/${taskId}`)\n    .headers({ 'If-Match': task['@odata.etag'] })\n    .delete();\n```\n\n**Beispiel Update:**\n```javascript\nconst task = await client.api(`/planner/tasks/${taskId}`).get();\nawait client.api(`/planner/tasks/${taskId}`)\n    .headers({ 'If-Match': task['@odata.etag'] })\n    .update({ percentComplete: 50 });\n```\n\n### Group-Based API Endpoints\n\n**Nicht verwenden:**\n```\nGET /planner/plans  ❌ (braucht komplexen Filter)\n```\n\n**Verwenden:**\n```\nGET /groups/{group-id}/planner/plans  ✅\n```\n\n**Beispiel:**\n```javascript\nconst plans = await client.api(`/groups/${groupId}/planner/plans`).get();\n```\n\n### Recurring Tasks (Wiederkehrende Aufgaben)\n\n**Microsoft Planner unterstützt native wiederkehrende Tasks!**\n\nIn der Planner Web-UI oder Mobile App:\n1. Task öffnen\n2. \"Repeat\" / \"Wiederholen\" klicken\n3. Frequenz wählen: Täglich, Wöchentlich, Monatlich, Jährlich, Benutzerdefiniert\n\n**Beispiel:**\n- \"Domain-Verlängerung example.com\" → Jährlich wiederholen\n- \"Backup prüfen\" → Wöchentlich wiederholen\n\n⚠️ **API-Limit:** Die Graph API unterstützt das Erstellen von recurring Tasks nicht direkt. \nWiederkehrende Tasks müssen über die Planner UI eingerichtet werden.\n\n## Common Operations\n\n### Plans\n\n| Operation | Script |\n|-----------|--------|\n| List all plans | `node scripts/list_plans.js` |\n| Create plan | `node scripts/create_plan.js <name> <group-id>` |\n| Delete plan | `node scripts/delete_plan.js <plan-id>` |\n\n### Buckets\n\n| Operation | Script |\n|-----------|--------|\n| List buckets | In `list_plans.js` integriert |\n| Create bucket | `node scripts/create_bucket.js <plan-id> <name>` |\n| Delete bucket | `node scripts/delete_bucket.js <bucket-id>` |\n\n### Tasks\n\n| Operation | Script |\n|-----------|--------|\n| List tasks | In `list_plans.js` integriert |\n| Create task | `node scripts/create_task.js <plan-id> <bucket-id> <title>` |\n| Update task | `node scripts/update_task.js <task-id> --percent-complete 50` |\n| Delete task | `node scripts/delete_task.js <task-id>` |\n| Cleanup | `node scripts/cleanup_verlaengerungen.js <group-id> \"<plan-name>\" \"<bucket-name>\"` |\n\n## Helper Scripts\n\n### test-connection.js\nTestet die Verbindung zu Microsoft Graph:\n- Access Token anfordern\n- Tenant-Informationen anzeigen\n- Verfügbare M365 Groups auflisten\n- Planner-Fähigkeit prüfen\n\n```bash\nnode scripts/test-connection.js\n```\n\n### list_plans.js\nZeigt alle Pläne einer M365 Group mit:\n- Buckets und deren Tasks\n- Task-Status (erledigt/in Arbeit/offen)\n- Prozentuale Fortschrittsanzeige\n\n```bash\n# Ohne Argument: Zeigt alle verfügbaren Gruppen\nnode scripts/list_plans.js\n\n# Mit Group ID: Zeigt Pläne der spezifischen Gruppe\nnode scripts/list_plans.js <group-id>\n```\n\n### create_plan.js\nErstellt einen neuen Plan mit Standard-Buckets:\n- To Do\n- In Progress  \n- Done\n\n```bash\nnode scripts/create_plan.js \"Project Alpha\" <group-id>\n```\n\n### cleanup_verlaengerungen.js\nBereinigt abgeschlossene Tasks aus einem Bucket:\n- Löscht Tasks mit 100% Fortschritt\n- Behält offene Tasks\n- Korrekte If-Match Header Behandlung\n\n```bash\nnode scripts/cleanup_verlaengerungen.js <group-id> \"<plan-name>\" \"<bucket-name>\"\n```\n\n**Beispiel:**\n```bash\nnode scripts/cleanup_verlaengerungen.js abc-123 \"My Project\" \"Completed\"\n```\n\n## Troubleshooting\n\n### Error: Insufficient privileges\n\n**Ursache:** Admin Consent nicht erteilt\n\n**Lösung:**\n```bash\naz ad app permission admin-consent --id <app-id>\n```\nOder im Azure Portal: API permissions → Grant admin consent\n\n### Error: Group not found\n\n**Ursache:** Planner funktioniert nur mit M365 Groups\n\n**Lösung:**\n1. Prüfe ob es eine M365 Group ist (hat Mail-Attribut)\n2. Security Groups/Distribution Lists funktionieren nicht\n3. Neue M365 Group erstellen (Teams oder Admin Center)\n\n### Error: The If-Match header must be specified\n\n**Ursache:** Update/Delete ohne ETag\n\n**Lösung:**\n```javascript\n// Erst Task holen für ETag\nconst task = await client.api(`/planner/tasks/${id}`).get();\n// Dann mit If-Match Header updaten/löschen\nawait client.api(`/planner/tasks/${id}`)\n    .headers({ 'If-Match': task['@odata.etag'] })\n    .delete();\n```\n\n### Error: This entity set must be queried with a filter\n\n**Ursache:** `/planner/plans` Endpoint braucht Filter\n\n**Lösung:** Group-basierten Endpoint verwenden:\n```javascript\n// Falsch ❌\nconst plans = await client.api('/planner/plans').get();\n\n// Richtig ✅\nconst plans = await client.api(`/groups/${groupId}/planner/plans`).get();\n```\n\n### Error: Cannot find module '@microsoft/microsoft-graph-client'\n\n**Ursache:** Node.js Pakete nicht installiert\n\n**Lösung:**\n```bash\ncd ~/.openclaw/workspace/skills/m365-planner\nnpm install\n```\n\n## Dependencies\n\nPakete lokal im Skill-Verzeichnis installieren:\n\n```bash\ncd ~/.openclaw/workspace/skills/m365-planner\nnpm install @microsoft/microsoft-graph-client axios\n```\n\n## References\n\n- [Planner API Overview](references/planner-api.md)\n- [Setup Guide](references/setup-guide.md)\n- [Common Patterns](references/common-patterns.md)\n- [Microsoft Graph API Docs](https://docs.microsoft.com/en-us/graph/api/overview)\n- [Planner REST API Reference](https://docs.microsoft.com/en-us/graph/api/resources/planner-overview)\n\n## Changelog\n\n### v1.2.1 (2026-04-18)\n- ✅ **Generische Skripte** – Keine hardcoded Group-IDs oder Plan-Namen mehr\n- ✅ **Command-Line Parameter** – Alle Skripte akzeptieren IDs als Argumente\n- ✅ **List Plans verbessert** – Zeigt alle Gruppen wenn keine ID angegeben\n- ✅ **Cleanup Script flexibel** – Funktioniert mit beliebigen Plans/Buckets\n- ✅ **ClawHub-ready** – Keine projektspezifischen Daten mehr enthalten\n\n### v1.1.0 (2026-04-17)\n- ✅ Node.js Scripts statt mgc CLI\n- ✅ If-Match Header Support für Updates/Löschungen\n- ✅ Group-based API Endpoints\n- ✅ Test-Connection Script mit M365 Group Detection\n- ✅ List Plans Script mit Bucket/Task-Übersicht\n- ✅ Cleanup Script für abgeschlossene Tasks\n- ✅ Dokumentation zu recurring Tasks (native Planner Feature)\n- ✅ Troubleshooting Section erweitert\n\n### v1.0.0 (2023-01-19)\n- Initiale Version mit mgc CLI\n- Azure AD Setup Guide\n- Grundlegende CRUD-Operationen\n\nFile v1.2.1:_meta.json\n\n{\n  \"ownerId\": \"kn73k7k4tnef2q480xd4y7dnkx82nhzj\",\n  \"slug\": \"m365-planner-v2\",\n  \"version\": \"1.2.1\",\n  \"publishedAt\": 1776511031896\n}\n\nFile v1.2.1:references/common-patterns.md\n\n# Common Patterns for M365 Planner\n\n## Pattern 1: Create Project Structure\n\nCreate a complete project with predefined buckets:\n\n```bash\n# 1. Create or get group\nGROUP_ID=$(az ad group list --query \"[?displayName=='Project Team'].id\" -o tsv)\n\n# 2. Create plan with buckets (using helper script)\n./scripts/create_plan.sh \"Website Redesign\" \"$GROUP_ID\"\n```\n\n## Pattern 2: Bulk Task Import\n\nCreate multiple tasks from a list:\n\n```bash\nBUCKET_ID=\"your-bucket-id\"\n\ncat tasks.txt | while read -r TASK; do\n    mgc planner tasks create \\\n        --title \"$TASK\" \\\n        --bucket-id \"$BUCKET_ID\" \\\n        --output none\n    echo \"Created: $TASK\"\ndone\n```\n\n## Pattern 3: Task Status Update\n\nUpdate task progress:\n\n```bash\nTASK_ID=\"your-task-id\"\n\n# Mark as in progress (50%)\nmgc planner tasks patch \\\n    --planner-task-id \"$TASK_ID\" \\\n    --percent-complete 50\n\n# Mark as complete (100%)\nmgc planner tasks patch \\\n    --planner-task-id \"$TASK_ID\" \\\n    --percent-complete 100\n```\n\n## Pattern 4: Weekly Report\n\nGenerate a task summary:\n\n```bash\nPLAN_ID=\"your-plan-id\"\n\n# Get all tasks\necho \"Weekly Planner Report\"\necho \"====================\"\n./scripts/list_tasks.sh \"$PLAN_ID\"\n```\n\n## Pattern 5: Assign Tasks to Team\n\nAssign tasks to multiple users:\n\n```bash\n# Get user IDs\nUSER1=$(az ad user show --id \"alice@company.com\" --query id -o tsv)\nUSER2=$(az ad user show --id \"bob@company.com\" --query id -o tsv)\n\n# Assign tasks\n./scripts/assign_task.sh \"task-id-1\" \"$USER1\"\n./scripts/assign_task.sh \"task-id-2\" \"$USER2\"\n```\n\n## JSON Output Processing\n\nMany commands support `--output json` for automation:\n\n```bash\n# Extract specific fields\nmgc planner plans list --output json | \\\n    jq -r '.value[] | select(.title | contains(\"Project\")) | .id'\n\n# Save to file\nmgc planner tasks list --planner-bucket-id \"$BUCKET\" --output json > tasks.json\n```\n\nFile v1.2.1:references/planner-api.md\n\n# Microsoft Planner API Reference\n\n## Core Resources\n\n### plannerPlan\nRepresents a plan in Planner. Always associated with a Microsoft 365 group.\n\n**Key Properties:**\n- `id` – Unique identifier\n- `title` – Plan name\n- `owner` – Group ID that owns the plan\n- `createdDateTime` – Creation timestamp\n\n**Relationships:**\n- `buckets` – Collection of buckets in the plan\n- `tasks` – Collection of tasks in the plan\n\n### plannerBucket\nContainer for tasks within a plan. Represents stages or categories.\n\n**Key Properties:**\n- `id` – Unique identifier\n- `name` – Bucket name\n- `planId` – Parent plan ID\n- `orderHint` – Sorting hint\n\n### plannerTask\nIndividual work item in Planner.\n\n**Key Properties:**\n- `id` – Unique identifier\n- `title` – Task title\n- `bucketId` – Parent bucket ID\n- `planId` – Parent plan ID\n- `percentComplete` – Progress (0, 50, or 100)\n- `assignedTo` – User assignment\n- `dueDateTime` – Due date\n- `priority` – Priority (1=urgent, 3=normal, 5=low)\n\n## API Endpoints\n\n### Plans\n```\nGET    /planner/plans\nPOST   /planner/plans\nGET    /planner/plans/{id}\nPATCH  /planner/plans/{id}\nDELETE /planner/plans/{id}\n```\n\n### Buckets\n```\nGET    /planner/buckets\nPOST   /planner/buckets\nGET    /planner/buckets/{id}\nDELETE /planner/buckets/{id}\n```\n\n### Tasks\n```\nGET    /planner/tasks\nPOST   /planner/tasks\nGET    /planner/tasks/{id}\nPATCH  /planner/tasks/{id}\nDELETE /planner/tasks/{id}\n```\n\n## Required Permissions\n\n| Permission Type | Needed |\n|----------------|--------|\n| Delegated (work/school) | Group.ReadWrite.All, Tasks.ReadWrite |\n| Application | Group.ReadWrite.All, Tasks.ReadWrite |\n\n## Constraints\n\n- Plans require M365 Groups (no standalone plans)\n- Maximum 10 buckets per plan\n- Maximum 200 active tasks per plan\n- Plan names: max 64 characters\n\nFile v1.2.1:references/setup-guide.md\n\n# Detailed Setup Guide\n\n## Azure AD App Registration - Step by Step\n\n### 1. Portal Method (Browser)\n\n1. Go to https://portal.azure.com → Azure Active Directory → App registrations\n2. Click \"New registration\"\n3. Enter:\n   - Name: `M365-Planner-Integration`\n   - Supported account types: `Accounts in this organizational directory only`\n   - Redirect URI: None (for client credentials flow)\n4. Click \"Register\"\n5. Note the **Application (client) ID** and **Directory (tenant) ID**\n\n### 2. Add API Permissions\n\n1. Go to \"API permissions\" → \"Add a permission\"\n2. Select \"Microsoft Graph\" → \"Application permissions\"\n3. Add:\n   - `Group.ReadWrite.All`\n   - `Tasks.ReadWrite`\n4. Click \"Grant admin consent for [tenant]\"\n\n### 3. Create Client Secret\n\n1. Go to \"Certificates & secrets\" → \"Client secrets\" → \"New client secret\"\n2. Description: `OpenClaw Integration`\n3. Expires: Select duration (24 months max)\n4. Copy the **Value** (shown only once!)\n\n### 4. Environment Configuration\n\nCreate `~/.openclaw/.env`:\n\n```bash\n# M365 Planner Integration\nM365_CLIENT_ID=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\nM365_CLIENT_SECRET=\"your-secret-value\"\nM365_TENANT_ID=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\n```\n\n### 5. Test Authentication\n\n```bash\n# Using mgc with client credentials\nmgc login --strategy ClientSecret \\\n  --client-id $M365_CLIENT_ID \\\n  --client-secret $M365_CLIENT_SECRET \\\n  --tenant-id $M365_TENANT_ID\n\n# Verify access\nmgc me get\n```\n\n## Finding Group IDs\n\nPlanner plans require M365 groups. Find your groups:\n\n```bash\n# List all groups\nmgc groups list --output table --select displayName,id\n\n# Or use Azure CLI\naz ad group list --query \"[].{Name:displayName, ID:id}\" -o table\n```\n\n## Common Issues\n\n### \"Insufficient privileges\"\nSolution: Grant admin consent in Azure Portal → API permissions → Grant admin consent\n\n### \"Group not found\"\nSolution: Ensure you're using an M365 group, not a security group or distribution list\n\n### \"Invalid authentication token\"\nSolution: Token expired. Re-run `mgc login`\n\nFile v1.2.1:package-lock.json\n\n{\n  \"name\": \"m365-planner\",\n  \"version\": \"1.0.0\",\n  \"lockfileVersion\": 3,\n  \"requires\": true,\n  \"packages\": {\n    \"\": {\n      \"name\": \"m365-planner\",\n      \"version\": \"1.0.0\",\n      \"license\": \"ISC\",\n      \"dependencies\": {\n        \"@microsoft/microsoft-graph-client\": \"^3.0.7\",\n        \"axios\": \"^1.15.0\"\n      }\n    },\n    \"node_modules/@babel/runtime\": {\n      \"version\": \"7.29.2\",\n      \"resolved\": \"https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz\",\n      \"integrity\": \"sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=6.9.0\"\n      }\n    },\n    \"node_modules/@microsoft/microsoft-graph-client\": {\n      \"version\": \"3.0.7\",\n      \"resolved\": \"https://registry.npmjs.org/@microsoft/microsoft-graph-client/-/microsoft-graph-client-3.0.7.tgz\",\n      \"integrity\": \"sha512-/AazAV/F+HK4LIywF9C+NYHcJo038zEnWkteilcxC1FM/uK/4NVGDKGrxx7nNq1ybspAroRKT4I1FHfxQzxkUw==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"@babel/runtime\": \"^7.12.5\",\n        \"tslib\": \"^2.2.0\"\n      },\n      \"engines\": {\n        \"node\": \">=12.0.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"@azure/identity\": {\n          \"optional\": true\n        },\n        \"@azure/msal-browser\": {\n          \"optional\": true\n        },\n        \"buffer\": {\n          \"optional\": true\n        },\n        \"stream-browserify\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/asynckit\": {\n      \"version\": \"0.4.0\",\n      \"resolved\": \"https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz\",\n      \"integrity\": \"sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==\",\n      \"license\": \"MIT\"\n    },\n    \"node_modules/axios\": {\n      \"version\": \"1.15.0\",\n      \"resolved\": \"https://registry.npmjs.org/axios/-/axios-1.15.0.tgz\",\n      \"integrity\": \"sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"follow-redirects\": \"^1.15.11\",\n        \"form-data\": \"^4.0.5\",\n        \"proxy-from-env\": \"^2.1.0\"\n      }\n    },\n    \"node_modules/call-bind-apply-helpers\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz\",\n      \"integrity\": \"sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"es-errors\": \"^1.3.0\",\n        \"function-bind\": \"^1.1.2\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/combined-stream\": {\n      \"version\": \"1.0.8\",\n      \"resolved\": \"https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz\",\n      \"integrity\": \"sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"delayed-stream\": \"~1.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.8\"\n      }\n    },\n    \"node_modules/delayed-stream\": {\n      \"version\": \"1.0.0\",\n      \"resolved\": \"https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz\",\n      \"integrity\": \"sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=0.4.0\"\n      }\n    },\n    \"node_modules/dunder-proto\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz\",\n      \"integrity\": \"sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"call-bind-apply-helpers\": \"^1.0.1\",\n        \"es-errors\": \"^1.3.0\",\n        \"gopd\": \"^1.2.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/es-define-property\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz\",\n      \"integrity\": \"sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/es-errors\": {\n      \"version\": \"1.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz\",\n      \"integrity\": \"sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/es-object-atoms\": {\n      \"version\": \"1.1.1\",\n      \"resolved\": \"https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz\",\n      \"integrity\": \"sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"es-errors\": \"^1.3.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/es-set-tostringtag\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz\",\n      \"integrity\": \"sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"es-errors\": \"^1.3.0\",\n        \"get-intrinsic\": \"^1.2.6\",\n        \"has-tostringtag\": \"^1.0.2\",\n        \"hasown\": \"^2.0.2\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/follow-redirects\": {\n      \"version\": \"1.16.0\",\n      \"resolved\": \"https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz\",\n      \"integrity\": \"sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==\",\n      \"funding\": [\n        {\n          \"type\": \"individual\",\n          \"url\": \"https://github.com/sponsors/RubenVerborgh\"\n        }\n      ],\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=4.0\"\n      },\n      \"peerDependenciesMeta\": {\n        \"debug\": {\n          \"optional\": true\n        }\n      }\n    },\n    \"node_modules/form-data\": {\n      \"version\": \"4.0.5\",\n      \"resolved\": \"https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz\",\n      \"integrity\": \"sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"asynckit\": \"^0.4.0\",\n        \"combined-stream\": \"^1.0.8\",\n        \"es-set-tostringtag\": \"^2.1.0\",\n        \"hasown\": \"^2.0.2\",\n        \"mime-types\": \"^2.1.12\"\n      },\n      \"engines\": {\n        \"node\": \">= 6\"\n      }\n    },\n    \"node_modules/function-bind\": {\n      \"version\": \"1.1.2\",\n      \"resolved\": \"https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz\",\n      \"integrity\": \"sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==\",\n      \"license\": \"MIT\",\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/ljharb\"\n      }\n    },\n    \"node_modules/get-intrinsic\": {\n      \"version\": \"1.3.0\",\n      \"resolved\": \"https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz\",\n      \"integrity\": \"sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"call-bind-apply-helpers\": \"^1.0.2\",\n        \"es-define-property\": \"^1.0.1\",\n        \"es-errors\": \"^1.3.0\",\n        \"es-object-atoms\": \"^1.1.1\",\n        \"function-bind\": \"^1.1.2\",\n        \"get-proto\": \"^1.0.1\",\n        \"gopd\": \"^1.2.0\",\n        \"has-symbols\": \"^1.1.0\",\n        \"hasown\": \"^2.0.2\",\n        \"math-intrinsics\": \"^1.1.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/ljharb\"\n      }\n    },\n    \"node_modules/get-proto\": {\n      \"version\": \"1.0.1\",\n      \"resolved\": \"https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz\",\n      \"integrity\": \"sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"dunder-proto\": \"^1.0.1\",\n        \"es-object-atoms\": \"^1.0.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/gopd\": {\n      \"version\": \"1.2.0\",\n      \"resolved\": \"https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz\",\n      \"integrity\": \"sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/ljharb\"\n      }\n    },\n    \"node_modules/has-symbols\": {\n      \"version\": \"1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz\",\n      \"integrity\": \"sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/ljharb\"\n      }\n    },\n    \"node_modules/has-tostringtag\": {\n      \"version\": \"1.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz\",\n      \"integrity\": \"sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"has-symbols\": \"^1.0.3\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      },\n      \"funding\": {\n        \"url\": \"https://github.com/sponsors/ljharb\"\n      }\n    },\n    \"node_modules/hasown\": {\n      \"version\": \"2.0.2\",\n      \"resolved\": \"https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz\",\n      \"integrity\": \"sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"function-bind\": \"^1.1.2\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/math-intrinsics\": {\n      \"version\": \"1.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz\",\n      \"integrity\": \"sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 0.4\"\n      }\n    },\n    \"node_modules/mime-db\": {\n      \"version\": \"1.52.0\",\n      \"resolved\": \"https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz\",\n      \"integrity\": \"sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">= 0.6\"\n      }\n    },\n    \"node_modules/mime-types\": {\n      \"version\": \"2.1.35\",\n      \"resolved\": \"https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz\",\n      \"integrity\": \"sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==\",\n      \"license\": \"MIT\",\n      \"dependencies\": {\n        \"mime-db\": \"1.52.0\"\n      },\n      \"engines\": {\n        \"node\": \">= 0.6\"\n      }\n    },\n    \"node_modules/proxy-from-env\": {\n      \"version\": \"2.1.0\",\n      \"resolved\": \"https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz\",\n      \"integrity\": \"sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==\",\n      \"license\": \"MIT\",\n      \"engines\": {\n        \"node\": \">=10\"\n      }\n    },\n    \"node_modules/tslib\": {\n      \"version\": \"2.8.1\",\n      \"resolved\": \"https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz\",\n      \"integrity\": \"sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==\",\n      \"license\": \"0BSD\"\n    }\n  }\n}\n\nFile v1.2.1:package.json\n\n{\n  \"name\": \"m365-planner\",\n  \"version\": \"1.2.1\",\n  \"description\": \"Microsoft 365 Planner Skill for OpenClaw - Manage plans, buckets, and tasks via Graph API\",\n  \"main\": \"scripts/test-connection.js\",\n  \"scripts\": {\n    \"test\": \"node scripts/test-connection.js\",\n    \"list\": \"node scripts/list_plans.js\",\n    \"cleanup\": \"node scripts/cleanup_verlaengerungen.js\"\n  },\n  \"keywords\": [\n    \"microsoft\",\n    \"planner\",\n    \"m365\",\n    \"graph-api\",\n    \"openclaw\",\n    \"skill\"\n  ],\n  \"author\": \"OpenClaw Community\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"@microsoft/microsoft-graph-client\": \"^3.0.7\",\n    \"axios\": \"^1.15.0\"\n  }\n}","readmeExcerpt":"Skill: M365 Planner Owner: felox63 Summary: Manage Microsoft 365 Planner plans, buckets, and tasks via Microsoft Graph API. Use when creating, listing, updating, or deleting Planner resources. Supports... Tags: latest:1.2.3 Version history: v1.2.3 | 2026-04-18T13:08:24.799Z | user v1.2.3 is a major documentation update for international users. - Full documentation translated to English for worldwide ClawHub access - ","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"# Test connection\nnode scripts/test-connection.js\n\n# List all plans\nnode scripts/list_plans.js\n\n# List plans for specific group\nnode scripts/list_plans.js <group-id>\n\n# Create plan\nnode scripts/create_plan.js \"Project Name\" <group-id>\n\n# Create task\nnode scripts/create_task.js <plan-id> <bucket-id> \"Task Title\"\n\n# Delete completed tasks\nnode scripts/cleanup_verlaengerungen.js <group-id> \"<plan-name>\" \"<bucket-name>\""},{"language":"bash","snippet":"az login\naz ad app create --display-name \"M365-Planner-Integration\" --sign-in-audience \"AzureADMyOrg\""},{"language":"bash","snippet":"APP_ID=\"your-app-id\"\n\n# Group.Read.All\naz ad app permission add \\\n  --id $APP_ID \\\n  --api 00000003-0000-0000-c000-000000000000 \\\n  --api-permissions 5b567253-7703-48e2-861c-caed61531407=Role\n\n# Tasks.ReadWrite.All\naz ad app permission add \\\n  --id $APP_ID \\\n  --api 00000003-0000-0000-c000-000000000000 \\\n  --api-permissions bdfbf15f-ee85-495a-99a9-ef9b2abb1dcb=Role\n\n# Admin Consent\naz ad app permission admin-consent --id $APP_ID"},{"language":"bash","snippet":"az ad app credential reset \\\n  --id $APP_ID \\\n  --append \\\n  --display-name \"OpenClaw Integration\""},{"language":"bash","snippet":"# Microsoft 365 Planner Credentials\nM365_CLIENT_ID=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\nM365_CLIENT_SECRET=\"your-secret-value\"\nM365_TENANT_ID=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\""},{"language":"bash","snippet":"chmod 600 ~/.openclaw/.env"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: m365-planner\ndescription: Manage Microsoft 365 Planner plans, buckets, and tasks via Microsoft Graph API. Use when creating, listing, updating, or deleting Planner resources. Supports group-based plan management, task assignment, progress tracking, and recurring tasks. Requires Azure AD app registration with Group.Read.All and Tasks.ReadWrite.All permissions.\nlicense: MIT\nversion: 1.2.3\n---\n\n# M365 Planner Skill\n\nManage Microsoft 365 Planner through Microsoft Graph API.\n\n## What's New in v1.2.3\n\n- 🌍 **English Documentation** – Complete translation for international ClawHub availability\n- 🔧 **Portability** – Env path now uses `os.homedir()` instead of hardcoded paths\n- 🧹 **Security Cleanup** – Full audit for sensitive data (no IDs, names, domains)\n- 📦 **ClawHub-ready** – Tarball created, node_modules excluded\n\n## What's New in v1.2.2\n\n- 🔧 **Portability** – Env path now uses `os.homedir()` instead of hardcoded `/home/claw/.openclaw/.env`\n- 🧹 **Security Cleanup** – Full audit for sensitive data (no IDs, names, domains)\n- 📦 **ClawHub-ready** – Tarball created, node_modules excluded\n\n## What's New in v1.2.1\n\n- ✅ **Generic Scripts** – No hardcoded Group-IDs or Plan names anymore\n- ✅ **Command-Line Parameters** – All scripts accept IDs as arguments\n- ✅ **List Plans Improved** – Shows all groups when no ID provided\n- ✅ **Flexible Cleanup** – Works with any plans/buckets\n- ✅ **ClawHub-ready** – No project-specific data included\n\n## What's New in v1.1.0\n\n- ✅ **Node.js Scripts** – Standalone scripts without `mgc` CLI\n- ✅ **If-Match Header Support** – Correct ETag handling for updates/deletes\n- ✅ **Group-Based API** – Direct access via M365 Group-ID\n- ✅ **Recurring Tasks** – Note about native Planner recurrence feature\n- ✅ **Cleanup Scripts** – Automated task cleanup\n\n## Prerequisites\n\n1. Azure AD App Registration (see Setup below)\n2. Node.js v18+ with `@microsoft/microsoft-graph-client` and `axios`\n3. M365 Group (not Security Group or Distribution List!)\n\n## Quick Start\n\n```bash\n# Test connection\nnode scripts/test-connection.js\n\n# List all plans\nnode scripts/list_plans.js\n\n# List plans for specific group\nnode scripts/list_plans.js <group-id>\n\n# Create plan\nnode scripts/create_plan.js \"Project Name\" <group-id>\n\n# Create task\nnode scripts/create_task.js <plan-id> <bucket-id> \"Task Title\"\n\n# Delete completed tasks\nnode scripts/cleanup_verlaengerungen.js <group-id> \"<plan-name>\" \"<bucket-name>\"\n```\n\n## Setup: Azure AD App Registration\n\n### Step 1: Create App Registration\n\n**Azure Portal:**\n1. https://portal.azure.com → Azure Active Directory → App registrations\n2. \"New registration\"\n3. Name: `M365-Planner-Integration`\n4. Supported account types: `Accounts in this organizational directory only`\n5. Redirect URI: None (Client Credentials Flow)\n\n**Or via Azure CLI:**\n```bash\naz login\naz ad app create --display-name \"M365-Planner-Integration\" --sign-in-audience \"AzureADMyOrg\"\n```\nNote the **Application (client) ID** from the output.\n\n### Step 2: Add"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn73k7k4tnef2q480xd4y7dnkx82nhzj\",\n  \"slug\": \"m365-planner-v2\",\n  \"version\": \"1.2.3\",\n  \"publishedAt\": 1776517704799\n}"},{"path":"references/common-patterns.md","content":"# Common Patterns for M365 Planner\n\n## Pattern 1: Create Project Structure\n\nCreate a complete project with predefined buckets:\n\n```bash\n# 1. Create or get group\nGROUP_ID=$(az ad group list --query \"[?displayName=='Project Team'].id\" -o tsv)\n\n# 2. Create plan with buckets (using helper script)\n./scripts/create_plan.sh \"Website Redesign\" \"$GROUP_ID\"\n```\n\n## Pattern 2: Bulk Task Import\n\nCreate multiple tasks from a list:\n\n```bash\nBUCKET_ID=\"your-bucket-id\"\n\ncat tasks.txt | while read -r TASK; do\n    mgc planner tasks create \\\n        --title \"$TASK\" \\\n        --bucket-id \"$BUCKET_ID\" \\\n        --output none\n    echo \"Created: $TASK\"\ndone\n```\n\n## Pattern 3: Task Status Update\n\nUpdate task progress:\n\n```bash\nTASK_ID=\"your-task-id\"\n\n# Mark as in progress (50%)\nmgc planner tasks patch \\\n    --planner-task-id \"$TASK_ID\" \\\n    --percent-complete 50\n\n# Mark as complete (100%)\nmgc planner tasks patch \\\n    --planner-task-id \"$TASK_ID\" \\\n    --percent-complete 100\n```\n\n## Pattern 4: Weekly Report\n\nGenerate a task summary:\n\n```bash\nPLAN_ID=\"your-plan-id\"\n\n# Get all tasks\necho \"Weekly Planner Report\"\necho \"====================\"\n./scripts/list_tasks.sh \"$PLAN_ID\"\n```\n\n## Pattern 5: Assign Tasks to Team\n\nAssign tasks to multiple users:\n\n```bash\n# Get user IDs\nUSER1=$(az ad user show --id \"alice@company.com\" --query id -o tsv)\nUSER2=$(az ad user show --id \"bob@company.com\" --query id -o tsv)\n\n# Assign tasks\n./scripts/assign_task.sh \"task-id-1\" \"$USER1\"\n./scripts/assign_task.sh \"task-id-2\" \"$USER2\"\n```\n\n## JSON Output Processing\n\nMany commands support `--output json` for automation:\n\n```bash\n# Extract specific fields\nmgc planner plans list --output json | \\\n    jq -r '.value[] | select(.title | contains(\"Project\")) | .id'\n\n# Save to file\nmgc planner tasks list --planner-bucket-id \"$BUCKET\" --output json > tasks.json\n```"},{"path":"references/planner-api.md","content":"# Microsoft Planner API Reference\n\n## Core Resources\n\n### plannerPlan\nRepresents a plan in Planner. Always associated with a Microsoft 365 group.\n\n**Key Properties:**\n- `id` – Unique identifier\n- `title` – Plan name\n- `owner` – Group ID that owns the plan\n- `createdDateTime` – Creation timestamp\n\n**Relationships:**\n- `buckets` – Collection of buckets in the plan\n- `tasks` – Collection of tasks in the plan\n\n### plannerBucket\nContainer for tasks within a plan. Represents stages or categories.\n\n**Key Properties:**\n- `id` – Unique identifier\n- `name` – Bucket name\n- `planId` – Parent plan ID\n- `orderHint` – Sorting hint\n\n### plannerTask\nIndividual work item in Planner.\n\n**Key Properties:**\n- `id` – Unique identifier\n- `title` – Task title\n- `bucketId` – Parent bucket ID\n- `planId` – Parent plan ID\n- `percentComplete` – Progress (0, 50, or 100)\n- `assignedTo` – User assignment\n- `dueDateTime` – Due date\n- `priority` – Priority (1=urgent, 3=normal, 5=low)\n\n## API Endpoints\n\n### Plans\n```\nGET    /planner/plans\nPOST   /planner/plans\nGET    /planner/plans/{id}\nPATCH  /planner/plans/{id}\nDELETE /planner/plans/{id}\n```\n\n### Buckets\n```\nGET    /planner/buckets\nPOST   /planner/buckets\nGET    /planner/buckets/{id}\nDELETE /planner/buckets/{id}\n```\n\n### Tasks\n```\nGET    /planner/tasks\nPOST   /planner/tasks\nGET    /planner/tasks/{id}\nPATCH  /planner/tasks/{id}\nDELETE /planner/tasks/{id}\n```\n\n## Required Permissions\n\n| Permission Type | Needed |\n|----------------|--------|\n| Delegated (work/school) | Group.ReadWrite.All, Tasks.ReadWrite |\n| Application | Group.ReadWrite.All, Tasks.ReadWrite |\n\n## Constraints\n\n- Plans require M365 Groups (no standalone plans)\n- Maximum 10 buckets per plan\n- Maximum 200 active tasks per plan\n- Plan names: max 64 characters"},{"path":"references/setup-guide.md","content":"# Detailed Setup Guide\n\n## Azure AD App Registration - Step by Step\n\n### 1. Portal Method (Browser)\n\n1. Go to https://portal.azure.com → Azure Active Directory → App registrations\n2. Click \"New registration\"\n3. Enter:\n   - Name: `M365-Planner-Integration`\n   - Supported account types: `Accounts in this organizational directory only`\n   - Redirect URI: None (for client credentials flow)\n4. Click \"Register\"\n5. Note the **Application (client) ID** and **Directory (tenant) ID**\n\n### 2. Add API Permissions\n\n1. Go to \"API permissions\" → \"Add a permission\"\n2. Select \"Microsoft Graph\" → \"Application permissions\"\n3. Add:\n   - `Group.ReadWrite.All`\n   - `Tasks.ReadWrite`\n4. Click \"Grant admin consent for [tenant]\"\n\n### 3. Create Client Secret\n\n1. Go to \"Certificates & secrets\" → \"Client secrets\" → \"New client secret\"\n2. Description: `OpenClaw Integration`\n3. Expires: Select duration (24 months max)\n4. Copy the **Value** (shown only once!)\n\n### 4. Environment Configuration\n\nCreate `~/.openclaw/.env`:\n\n```bash\n# M365 Planner Integration\nM365_CLIENT_ID=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\nM365_CLIENT_SECRET=\"your-secret-value\"\nM365_TENANT_ID=\"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"\n```\n\n### 5. Test Authentication\n\n```bash\n# Using mgc with client credentials\nmgc login --strategy ClientSecret \\\n  --client-id $M365_CLIENT_ID \\\n  --client-secret $M365_CLIENT_SECRET \\\n  --tenant-id $M365_TENANT_ID\n\n# Verify access\nmgc me get\n```\n\n## Finding Group IDs\n\nPlanner plans require M365 groups. Find your groups:\n\n```bash\n# List all groups\nmgc groups list --output table --select displayName,id\n\n# Or use Azure CLI\naz ad group list --query \"[].{Name:displayName, ID:id}\" -o table\n```\n\n## Common Issues\n\n### \"Insufficient privileges\"\nSolution: Grant admin consent in Azure Portal → API permissions → Grant admin consent\n\n### \"Group not found\"\nSolution: Ensure you're using an M365 group, not a security group or distribution list\n\n### \"Invalid authentication token\"\nSolution: Token expired. Re-run `mgc login`"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"Manage Microsoft 365 Planner plans, buckets, and tasks via Microsoft Graph API. Use when creating, listing, updating, or deleting Planner resources. Supports... Skill: M365 Planner Owner: felox63 Summary: Manage Microsoft 365 Planner plans, buckets, and tasks via Microsoft Graph API. Use when creating, listing, updating, or deleting Planner resources. Supports... Tags: latest:1.2.3 Version history: v1.2.3 | 2026-04-18T13:08:24.799Z | user v1.2.3 is a major documentation update for international users. - Full documentation translated to English for worldwide ClawHub access -","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1256,"uniquenessScore":46,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T15:44:44.374Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-11T15:44:44.374Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-11T17:45:00.490Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}