[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6HXBYRP9TZ2E5MRQ2NB28VB":3,"skill-same:01M6HXBYRP9TZ2E5MRQ2NB28VB":72},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":39,"linkOnly":40,"markdownContent":41,"markdownBody":42,"frontMatter":43,"refName":44,"commitSha":45,"skillDirectory":46,"forksCount":47,"repositoryHtmlUrl":48,"repositoryHomepageUrl":6,"ownerHtmlUrl":49,"ownerBlogUrl":50,"ownerDescription":6,"updatedAt":51,"install":52,"resources":65},"01M6HXBYRP9TZ2E5MRQ2NB28VB","push-based-widget-module-pattern",null,"How to implement sidebar\u002Fwidget UI components that receive pushed data updates from a caller, using a singleton module pattern with exported factory and update functions plus module-level DOM refs for efficient partial re-renders.","HKUDS\u002FAgentPilot","HKUDS","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F118165258?v=4","01M6HW8VRNZP64G0P4MVJW2KKQ","✨Data Intelligence Lab@HKU✨","01M6HW8VWZVHBRHYH3T330PFWV",8024,"MIT","https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fopenspace\u002Fexamples\u002Fmy-daily-monitor\u002Fskills\u002Fpush-based-widget-module-pattern\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],"widget","push based widget module pattern","module","pattern","push","ui","data","how","factory","functions","implement","update","how to","ui components","with","re","dom","updates","for","components","2026-11-10 10:12:30",false,"---\nname: push-based-widget-module-pattern\ndescription: How to implement sidebar\u002Fwidget UI components that receive pushed data updates from a caller, using a singleton module pattern with exported factory and update functions plus module-level DOM refs for efficient partial re-renders.\n---\n\n# Push-Based Widget Module Pattern\n\nUse this pattern when a UI sidebar or widget component needs to be updated by its **caller** (push-based) rather than fetching data itself. Instead of a class or framework component, implement the widget as a plain module with singleton state, a factory function to create the DOM, and an update function to efficiently patch it.\n\n---\n\n## When to Use\n\n- A sidebar, panel, or widget is rendered once but updated frequently with new data.\n- The data source lives outside the component (e.g., a parent controller, event bus, or store).\n- You want lightweight partial re-renders without rebuilding the entire DOM tree.\n- You prefer a simple module interface over a class-based or framework-based component.\n\n---\n\n## Core Structure\n\n```\nwidgets\u002F\n  MyWidget.ts          # The module (singleton state + exports)\n  MyWidget.types.ts    # (Optional) Exported data interface\n```\n\n---\n\n## Step-by-Step Instructions\n\n### 1. Define the Data Interface\n\nExport a typed interface so callers know exactly what data to push.\n\n```typescript\n\u002F\u002F MyWidget.types.ts  (or inline at top of MyWidget.ts)\nexport interface MyWidgetData {\n  title: string;\n  items: string[];\n  status: \"idle\" | \"active\" | \"error\";\n  \u002F\u002F ... all fields the widget needs to render\n}\n```\n\n### 2. Declare Module-Level Singleton Refs\n\nAt module scope, keep references to the **container** and any **frequently updated child nodes**. This avoids querying the DOM on every update.\n\n```typescript\n\u002F\u002F MyWidget.ts\nimport type { MyWidgetData } from \".\u002FMyWidget.types\";\n\n\u002F\u002F Singleton DOM refs\nlet containerEl: HTMLElement | null = null;\nlet titleEl: HTMLElement | null = null;\nlet itemListEl: HTMLElement | null = null;\nlet statusEl: HTMLElement | null = null;\n\n\u002F\u002F Current state snapshot (optional — useful for diffing)\nlet currentData: MyWidgetData | null = null;\n```\n\n### 3. Export a Factory Function (`createMyWidget`)\n\nThe factory builds the full DOM tree **once**, stores refs to mutable nodes, and returns the root element to be mounted by the caller.\n\n```typescript\nexport function createMyWidget(): HTMLElement {\n  \u002F\u002F Build the container\n  containerEl = document.createElement(\"aside\");\n  containerEl.className = \"my-widget\";\n\n  \u002F\u002F Build static structure; keep refs to dynamic parts\n  titleEl = document.createElement(\"h2\");\n  titleEl.className = \"my-widget__title\";\n\n  itemListEl = document.createElement(\"ul\");\n  itemListEl.className = \"my-widget__list\";\n\n  statusEl = document.createElement(\"span\");\n  statusEl.className = \"my-widget__status\";\n\n  \u002F\u002F Compose the tree\n  const header = document.createElement(\"header\");\n  header.appendChild(titleEl);\n  header.appendChild(statusEl);\n\n  containerEl.appendChild(header);\n  containerEl.appendChild(itemListEl);\n\n  return containerEl;\n}\n```\n\n> **Rule:** `createMyWidget` should be callable only once per page. If called again, consider returning the existing `containerEl` (idempotent factory).\n\n### 4. Export an Update Function (`updateMyWidget`)\n\nThe update function receives the new data object and performs **surgical DOM mutations** on the stored refs. It does NOT rebuild the whole tree.\n\n```typescript\nexport function updateMyWidget(data: MyWidgetData): void {\n  if (!containerEl) {\n    console.warn(\"updateMyWidget called before createMyWidget\");\n    return;\n  }\n\n  currentData = data;\n\n  \u002F\u002F Update only what changed\n  if (titleEl) titleEl.textContent = data.title;\n  if (statusEl) {\n    statusEl.textContent = data.status;\n    statusEl.dataset.status = data.status; \u002F\u002F for CSS hooks\n  }\n\n  \u002F\u002F Rebuild only dynamic list items\n  if (itemListEl) {\n    itemListEl.innerHTML = \"\"; \u002F\u002F clear previous items\n    data.items.forEach((item) => {\n      const li = document.createElement(\"li\");\n      li.textContent = item;\n      itemListEl!.appendChild(li);\n    });\n  }\n}\n```\n\n> **Optimization tip:** For large lists, compare `currentData` to `data` before clearing and rebuilding, or use a keyed reconciliation approach.\n\n### 5. Caller Usage Pattern\n\nThe caller mounts the widget once and pushes updates whenever its data changes.\n\n```typescript\nimport { createMyWidget, updateMyWidget } from \".\u002Fwidgets\u002FMyWidget\";\nimport type { MyWidgetData } from \".\u002Fwidgets\u002FMyWidget.types\";\n\n\u002F\u002F Mount once\nconst sidebar = document.getElementById(\"sidebar\")!;\nsidebar.appendChild(createMyWidget());\n\n\u002F\u002F Push updates (e.g., from a store subscription, WebSocket, timer)\nfunction onDataChange(newData: MyWidgetData) {\n  updateMyWidget(newData);\n}\n\n\u002F\u002F Example: push an initial state immediately\nonDataChange({\n  title: \"Today's Focus\",\n  items: [\"Task A\", \"Task B\"],\n  status: \"active\",\n});\n```\n\n---\n\n## Full Module Template\n\n```typescript\n\u002F\u002F widgets\u002FMyWidget.ts\n\nexport interface MyWidgetData {\n  \u002F\u002F Define all fields here\n}\n\n\u002F\u002F --- Singleton state ---\nlet containerEl: HTMLElement | null = null;\n\u002F\u002F Add more refs as needed per section of the widget\n\n\u002F\u002F --- Factory ---\nexport function createMyWidget(): HTMLElement {\n  if (containerEl) return containerEl; \u002F\u002F idempotent\n\n  containerEl = document.createElement(\"aside\");\n  \u002F\u002F ... build DOM, store refs ...\n  return containerEl;\n}\n\n\u002F\u002F --- Update ---\nexport function updateMyWidget(data: MyWidgetData): void {\n  if (!containerEl) return;\n  \u002F\u002F ... patch DOM refs with new data ...\n}\n```\n\n---\n\n## Guidelines & Best Practices\n\n| Concern | Recommendation |\n|---|---|\n| **Idempotent factory** | Return existing `containerEl` if called twice to avoid duplicate mounts. |\n| **Null guards** | Always check refs before mutating — the update fn may be called before mount in some flows. |\n| **Granular refs** | Store refs for every section that updates independently. Avoid `querySelector` in the update path. |\n| **Interface exports** | Always export the data interface so callers can type their push calls. |\n| **No internal fetching** | The module must never fetch or subscribe to external data — that is the caller's responsibility. |\n| **CSS hooks** | Use `data-*` attributes or CSS classes on refs to let stylesheets react to state changes. |\n| **Cleanup** | Optionally export a `destroyMyWidget()` that nulls all refs for SPA teardown scenarios. |\n\n---\n\n## Anti-Patterns to Avoid\n\n- ❌ **Class with constructor** — adds instantiation overhead and prevents the clean factory\u002Fupdate split.\n- ❌ **Querying the DOM in the update function** (`document.querySelector(...)`) — slow and fragile.\n- ❌ **Rebuilding the entire tree on every update** — defeats the purpose of the module-level refs.\n- ❌ **Mixing data-fetching into the widget module** — breaks the push-based contract.","# Push-Based Widget Module Pattern\n\nUse this pattern when a UI sidebar or widget component needs to be updated by its **caller** (push-based) rather than fetching data itself. Instead of a class or framework component, implement the widget as a plain module with singleton state, a factory function to create the DOM, and an update function to efficiently patch it.\n\n---\n\n## When to Use\n\n- A sidebar, panel, or widget is rendered once but updated frequently with new data.\n- The data source lives outside the component (e.g., a parent controller, event bus, or store).\n- You want lightweight partial re-renders without rebuilding the entire DOM tree.\n- You prefer a simple module interface over a class-based or framework-based component.\n\n---\n\n## Core Structure\n\n```\nwidgets\u002F\n  MyWidget.ts          # The module (singleton state + exports)\n  MyWidget.types.ts    # (Optional) Exported data interface\n```\n\n---\n\n## Step-by-Step Instructions\n\n### 1. Define the Data Interface\n\nExport a typed interface so callers know exactly what data to push.\n\n```typescript\n\u002F\u002F MyWidget.types.ts  (or inline at top of MyWidget.ts)\nexport interface MyWidgetData {\n  title: string;\n  items: string[];\n  status: \"idle\" | \"active\" | \"error\";\n  \u002F\u002F ... all fields the widget needs to render\n}\n```\n\n### 2. Declare Module-Level Singleton Refs\n\nAt module scope, keep references to the **container** and any **frequently updated child nodes**. This avoids querying the DOM on every update.\n\n```typescript\n\u002F\u002F MyWidget.ts\nimport type { MyWidgetData } from \".\u002FMyWidget.types\";\n\n\u002F\u002F Singleton DOM refs\nlet containerEl: HTMLElement | null = null;\nlet titleEl: HTMLElement | null = null;\nlet itemListEl: HTMLElement | null = null;\nlet statusEl: HTMLElement | null = null;\n\n\u002F\u002F Current state snapshot (optional — useful for diffing)\nlet currentData: MyWidgetData | null = null;\n```\n\n### 3. Export a Factory Function (`createMyWidget`)\n\nThe factory builds the full DOM tree **once**, stores refs to mutable nodes, and returns the root element to be mounted by the caller.\n\n```typescript\nexport function createMyWidget(): HTMLElement {\n  \u002F\u002F Build the container\n  containerEl = document.createElement(\"aside\");\n  containerEl.className = \"my-widget\";\n\n  \u002F\u002F Build static structure; keep refs to dynamic parts\n  titleEl = document.createElement(\"h2\");\n  titleEl.className = \"my-widget__title\";\n\n  itemListEl = document.createElement(\"ul\");\n  itemListEl.className = \"my-widget__list\";\n\n  statusEl = document.createElement(\"span\");\n  statusEl.className = \"my-widget__status\";\n\n  \u002F\u002F Compose the tree\n  const header = document.createElement(\"header\");\n  header.appendChild(titleEl);\n  header.appendChild(statusEl);\n\n  containerEl.appendChild(header);\n  containerEl.appendChild(itemListEl);\n\n  return containerEl;\n}\n```\n\n> **Rule:** `createMyWidget` should be callable only once per page. If called again, consider returning the existing `containerEl` (idempotent factory).\n\n### 4. Export an Update Function (`updateMyWidget`)\n\nThe update function receives the new data object and performs **surgical DOM mutations** on the stored refs. It does NOT rebuild the whole tree.\n\n```typescript\nexport function updateMyWidget(data: MyWidgetData): void {\n  if (!containerEl) {\n    console.warn(\"updateMyWidget called before createMyWidget\");\n    return;\n  }\n\n  currentData = data;\n\n  \u002F\u002F Update only what changed\n  if (titleEl) titleEl.textContent = data.title;\n  if (statusEl) {\n    statusEl.textContent = data.status;\n    statusEl.dataset.status = data.status; \u002F\u002F for CSS hooks\n  }\n\n  \u002F\u002F Rebuild only dynamic list items\n  if (itemListEl) {\n    itemListEl.innerHTML = \"\"; \u002F\u002F clear previous items\n    data.items.forEach((item) => {\n      const li = document.createElement(\"li\");\n      li.textContent = item;\n      itemListEl!.appendChild(li);\n    });\n  }\n}\n```\n\n> **Optimization tip:** For large lists, compare `currentData` to `data` before clearing and rebuilding, or use a keyed reconciliation approach.\n\n### 5. Caller Usage Pattern\n\nThe caller mounts the widget once and pushes updates whenever its data changes.\n\n```typescript\nimport { createMyWidget, updateMyWidget } from \".\u002Fwidgets\u002FMyWidget\";\nimport type { MyWidgetData } from \".\u002Fwidgets\u002FMyWidget.types\";\n\n\u002F\u002F Mount once\nconst sidebar = document.getElementById(\"sidebar\")!;\nsidebar.appendChild(createMyWidget());\n\n\u002F\u002F Push updates (e.g., from a store subscription, WebSocket, timer)\nfunction onDataChange(newData: MyWidgetData) {\n  updateMyWidget(newData);\n}\n\n\u002F\u002F Example: push an initial state immediately\nonDataChange({\n  title: \"Today's Focus\",\n  items: [\"Task A\", \"Task B\"],\n  status: \"active\",\n});\n```\n\n---\n\n## Full Module Template\n\n```typescript\n\u002F\u002F widgets\u002FMyWidget.ts\n\nexport interface MyWidgetData {\n  \u002F\u002F Define all fields here\n}\n\n\u002F\u002F --- Singleton state ---\nlet containerEl: HTMLElement | null = null;\n\u002F\u002F Add more refs as needed per section of the widget\n\n\u002F\u002F --- Factory ---\nexport function createMyWidget(): HTMLElement {\n  if (containerEl) return containerEl; \u002F\u002F idempotent\n\n  containerEl = document.createElement(\"aside\");\n  \u002F\u002F ... build DOM, store refs ...\n  return containerEl;\n}\n\n\u002F\u002F --- Update ---\nexport function updateMyWidget(data: MyWidgetData): void {\n  if (!containerEl) return;\n  \u002F\u002F ... patch DOM refs with new data ...\n}\n```\n\n---\n\n## Guidelines & Best Practices\n\n| Concern | Recommendation |\n|---|---|\n| **Idempotent factory** | Return existing `containerEl` if called twice to avoid duplicate mounts. |\n| **Null guards** | Always check refs before mutating — the update fn may be called before mount in some flows. |\n| **Granular refs** | Store refs for every section that updates independently. Avoid `querySelector` in the update path. |\n| **Interface exports** | Always export the data interface so callers can type their push calls. |\n| **No internal fetching** | The module must never fetch or subscribe to external data — that is the caller's responsibility. |\n| **CSS hooks** | Use `data-*` attributes or CSS classes on refs to let stylesheets react to state changes. |\n| **Cleanup** | Optionally export a `destroyMyWidget()` that nulls all refs for SPA teardown scenarios. |\n\n---\n\n## Anti-Patterns to Avoid\n\n- ❌ **Class with constructor** — adds instantiation overhead and prevents the clean factory\u002Fupdate split.\n- ❌ **Querying the DOM in the update function** (`document.querySelector(...)`) — slow and fragile.\n- ❌ **Rebuilding the entire tree on every update** — defeats the purpose of the module-level refs.\n- ❌ **Mixing data-fetching into the widget module** — breaks the push-based contract.",{"name":5,"description":7},"main","6b84b0689ca0d9e7b1e4061188ff6b60758e0f8a","openspace\u002Fexamples\u002Fmy-daily-monitor\u002Fskills\u002Fpush-based-widget-module-pattern",941,"https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot","https:\u002F\u002Fgithub.com\u002FHKUDS","https:\u002F\u002Fsites.google.com\u002Fview\u002Fchaoh","2026-11-12 22:26:39",{"source":8,"skillName":5,"commands":53,"prompt":63,"zipAvailable":64},[54,57,60],{"tool":55,"command":56},"npx","npx skills add HKUDS\u002FAgentPilot --skill push-based-widget-module-pattern",{"tool":58,"command":59},"bunx","bunx skills add HKUDS\u002FAgentPilot --skill push-based-widget-module-pattern",{"tool":61,"command":62},"pnpm","pnpm dlx skills add HKUDS\u002FAgentPilot --skill push-based-widget-module-pattern","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fopenspace\u002Fexamples\u002Fmy-daily-monitor\u002Fskills\u002Fpush-based-widget-module-pattern\u002FSKILL.md",true,[66],{"path":67,"resourceType":68,"resourceTypeDesc":69,"sizeBytes":70,"sourceHtmlUrl":71},".skill_id","OTHER","其他",46,"https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fopenspace\u002Fexamples\u002Fmy-daily-monitor\u002Fskills\u002Fpush-based-widget-module-pattern\u002F.skill_id",[73,92,111,136,159,182],{"skillNo":74,"name":75,"nameZh":6,"description":76,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":77,"categories":78,"keywords":79,"publishedAt":39},"01M6HYB297NDABRERJRVG0K8R0","agentpilot","Set up AgentPilot and use its single entry to prepare missing inputs and run configured RSI experiments. Use when the user requests AgentPilot installation or work with AgentPilot.","https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fplugins\u002Fagentpilot\u002Fskills\u002Fagentpilot\u002FSKILL.md",[],[75,80,81,33,82,83,84,85,86,87,88,89,90,91],"prepare","requests","missing","installation","rsi","up","use","user","work","SET","run","experiments",{"skillNo":93,"name":94,"nameZh":6,"description":95,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":96,"categories":97,"keywords":98,"publishedAt":39},"01M6HYAYWXTTE1J7DJM0MFNQ4H","remember","Review auto-memory entries and propose promotions to OPENSPACE.md, OPENSPACE.local.md, or retained auto-memory topics; detect duplicates, stale facts, conflicts, and ambiguous entries before making changes.","https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fopenspace\u002Fopenspace\u002Fskills\u002Fremember\u002FSKILL.md",[],[94,99,100,101,102,103,104,105,106,107,108,109,110],"memory","review","auto","openspace","changes","facts","detect","entries","local","conflicts","stale","duplicates",{"skillNo":112,"name":113,"nameZh":6,"description":114,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":115,"categories":116,"keywords":122,"publishedAt":39},"01M6HYAVMPM4SBDV60R2B5HPV8","skill-discovery","Search reusable OpenSpace skills locally, and browse cloud packages step by step when a cloud skill may help. Reusing proven skills saves tokens, improves reliability, and extends your capabilities beyond built-in tools.","https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fopenspace\u002Fopenspace\u002Fhost_skills\u002Fskill-discovery\u002FSKILL.md",[117],{"categoryNo":118,"categoryName":119,"taxonomyType":120,"taxonomyTypeDesc":121},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[123,124,125,102,126,127,128,129,130,131,132,133,134,135],"skill discovery","discovery","reusable","step by step","tokens","packages","help","cloud","reliability","capabilities","browse","search","Tools",{"skillNo":137,"name":138,"nameZh":6,"description":139,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":140,"categories":141,"keywords":143,"publishedAt":39},"01M6HYAR811B3RB0M50RBEDGN6","delegate-task","Delegate tasks to OpenSpace — a full-stack autonomous worker for coding, DevOps, web research, and desktop automation, backed by an extensive MCP tool and skill library. Skills auto-improve through use, reducing token consumption over time. A cloud community lets agents share and collectively evolve reusable skills.","https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fopenspace\u002Fopenspace\u002Fhost_skills\u002Fdelegate-task\u002FSKILL.md",[142],{"categoryNo":118,"categoryName":119,"taxonomyType":120,"taxonomyTypeDesc":121},[144,145,146,102,147,148,149,150,151,125,101,86,152,153,154,37,155,156,157,158],"delegate","task","delegate task","time","improve","desktop automation","worker","community","autonomous","tool","stack","share","tasks","automation","MCP",{"skillNo":160,"name":161,"nameZh":6,"description":162,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":163,"categories":164,"keywords":165,"publishedAt":39},"01M6HYAM9FSGV6E52AYENDQXYH","write-special-chars-ts-check","Workaround for write_file failures caused by special characters (apostrophes, backticks, template literals) using a Python heredoc script, plus a reliable TypeScript type-checking step that filters output to only the newly-written files to avoid being misled by pre-existing errors.","https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fopenspace\u002Flegacy\u002Fv1\u002Fshowcase\u002Fskills\u002Fwrite-special-chars-ts-check\u002FSKILL.md",[],[166,167,168,169,170,171,172,173,174,175,176,177,178,179,37,180,181],"write special chars ts check","write","check","type","files","filters","only","template","file","python","typescript","output","Existing","type-checking","errors","script",{"skillNo":183,"name":184,"nameZh":6,"description":185,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":186,"categories":187,"keywords":188,"publishedAt":39},"01M6HYAH05HGV7SVWSVR8PJRQD","write-special-chars-readback","Workaround for write_file failures caused by special characters (apostrophes, backticks, template literals) using a Python heredoc script, with mandatory post-write verification via read_file and cleanup of \u002Ftmp helper scripts.","https:\u002F\u002Fgithub.com\u002FHKUDS\u002FAgentPilot\u002Fblob\u002Fmain\u002Fopenspace\u002Flegacy\u002Fv1\u002Fshowcase\u002Fskills\u002Fwrite-special-chars-readback\u002FSKILL.md",[],[189,190,167,33,37,181,191,192,193,194,195,173,174,196,197,175],"write special chars readback","readback","helper","post","via","scripts","read","verification","cleanup"]