@fprad0/skill-master-mcp 0.0.9 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/README.md +43 -9
- package/VERSION.md +3 -3
- package/bin/lib/client-config.mjs +268 -0
- package/bin/lib/menu-core.mjs +678 -33
- package/bin/skill-master-bootstrap-global.mjs +15 -1
- package/bin/skill-master-doctor.mjs +181 -0
- package/bin/skill-master-install-global-skills.mjs +30 -10
- package/bin/skill-master-menu.mjs +184 -36
- package/bin/skill-master-register-clients.mjs +43 -99
- package/dist/index.js +30 -5
- package/dist/index.js.map +1 -1
- package/docs/operations/GUIA_MULTI_COMPUTADOR.md +255 -0
- package/docs/operations/GUIA_NPM_PUBLICO.md +147 -0
- package/docs/skill-candidates/v0.0.10/cli-creator/LICENSE.txt +201 -0
- package/docs/skill-candidates/v0.0.10/cli-creator/SKILL.md +160 -0
- package/docs/skill-candidates/v0.0.10/cli-creator/agents/openai.yaml +4 -0
- package/docs/skill-candidates/v0.0.10/cli-creator/references/agent-cli-patterns.md +154 -0
- package/docs/skill-candidates/v0.0.10/developer-workstation-ops/SKILL.md +32 -0
- package/docs/skill-candidates/v0.0.10/figma/LICENSE.txt +2 -0
- package/docs/skill-candidates/v0.0.10/figma/SKILL.md +42 -0
- package/docs/skill-candidates/v0.0.10/figma/agents/openai.yaml +14 -0
- package/docs/skill-candidates/v0.0.10/figma/assets/figma-small.svg +3 -0
- package/docs/skill-candidates/v0.0.10/figma/assets/figma.png +0 -0
- package/docs/skill-candidates/v0.0.10/figma/assets/icon.svg +28 -0
- package/docs/skill-candidates/v0.0.10/figma/references/figma-mcp-config.md +35 -0
- package/docs/skill-candidates/v0.0.10/figma/references/figma-tools-and-prompts.md +34 -0
- package/docs/skill-candidates/v0.0.10/figma-code-connect-components/LICENSE.TXT +2 -0
- package/docs/skill-candidates/v0.0.10/figma-code-connect-components/SKILL.md +349 -0
- package/docs/skill-candidates/v0.0.10/figma-code-connect-components/agents/openai.yaml +14 -0
- package/docs/skill-candidates/v0.0.10/figma-code-connect-components/assets/figma-small.svg +3 -0
- package/docs/skill-candidates/v0.0.10/figma-code-connect-components/assets/figma.png +0 -0
- package/docs/skill-candidates/v0.0.10/figma-code-connect-components/assets/icon.svg +28 -0
- package/docs/skill-candidates/v0.0.10/figma-code-connect-components/references/mapping-checklist.md +7 -0
- package/docs/skill-candidates/v0.0.10/figma-code-connect-components/scripts/normalize_node_id.py +25 -0
- package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/LICENSE.TXT +2 -0
- package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/SKILL.md +537 -0
- package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/agents/openai.yaml +14 -0
- package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/assets/figma-small.svg +3 -0
- package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/assets/figma.png +0 -0
- package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/assets/icon.svg +28 -0
- package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/references/rule-template.md +15 -0
- package/docs/skill-candidates/v0.0.10/figma-create-design-system-rules/scripts/check_agents_md.sh +9 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-design/LICENSE.TXT +2 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-design/SKILL.md +341 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-design/agents/openai.yaml +14 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-design/assets/figma-small.svg +3 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-design/assets/figma.png +0 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-design/assets/icon.svg +28 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-design/maintainers.yml +1 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/LICENSE.TXT +2 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/SKILL.md +314 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/agents/openai.yaml +14 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/assets/figma-small.svg +3 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/assets/figma.png +0 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/assets/icon.svg +28 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/maintainers.yml +3 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/references/code-connect-setup.md +260 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/references/component-creation.md +1014 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/references/discovery-phase.md +518 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/references/documentation-creation.md +834 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/references/error-recovery.md +540 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/references/naming-conventions.md +527 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/references/token-creation.md +962 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/bindVariablesToComponent.js +110 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/cleanupOrphans.js +127 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/createComponentWithVariants.js +148 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/createDocumentationPage.js +139 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/createSemanticTokens.js +108 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/createVariableCollection.js +49 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/inspectFileStructure.js +121 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/rehydrateState.js +92 -0
- package/docs/skill-candidates/v0.0.10/figma-generate-library/scripts/validateCreation.js +83 -0
- package/docs/skill-candidates/v0.0.10/figma-implement-design/LICENSE.txt +2 -0
- package/docs/skill-candidates/v0.0.10/figma-implement-design/SKILL.md +258 -0
- package/docs/skill-candidates/v0.0.10/figma-implement-design/agents/openai.yaml +14 -0
- package/docs/skill-candidates/v0.0.10/figma-implement-design/assets/figma-small.svg +3 -0
- package/docs/skill-candidates/v0.0.10/figma-implement-design/assets/figma.png +0 -0
- package/docs/skill-candidates/v0.0.10/figma-implement-design/assets/icon.svg +28 -0
- package/docs/skill-candidates/v0.0.10/figma-use/LICENSE.TXT +2 -0
- package/docs/skill-candidates/v0.0.10/figma-use/SKILL.md +233 -0
- package/docs/skill-candidates/v0.0.10/figma-use/agents/openai.yaml +14 -0
- package/docs/skill-candidates/v0.0.10/figma-use/assets/figma-small.svg +3 -0
- package/docs/skill-candidates/v0.0.10/figma-use/assets/figma.png +0 -0
- package/docs/skill-candidates/v0.0.10/figma-use/assets/icon.svg +28 -0
- package/docs/skill-candidates/v0.0.10/figma-use/maintainers.yml +1 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/api-reference.md +301 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/common-patterns.md +512 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/component-patterns.md +488 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/effect-style-patterns.md +123 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/gotchas.md +599 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/maintainers.yml +12 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/plugin-api-patterns.md +513 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/plugin-api-standalone.d.ts +11293 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/plugin-api-standalone.index.md +441 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/text-style-patterns.md +203 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/validation-and-recovery.md +109 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/variable-patterns.md +354 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/maintainers.yml +9 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-components--creating.md +17 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-components--using.md +17 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-components.md +50 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-effect-styles.md +52 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-text-styles.md +90 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-variables--creating.md +13 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-variables--using.md +13 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds-variables.md +64 -0
- package/docs/skill-candidates/v0.0.10/figma-use/references/working-with-design-systems/wwds.md +41 -0
- package/docs/skill-candidates/v0.0.10/frontend-design/LICENSE.txt +177 -0
- package/docs/skill-candidates/v0.0.10/frontend-design/SKILL.md +55 -0
- package/docs/skill-candidates/v0.0.10/frontend-ui-ux-systems/SKILL.md +32 -0
- package/docs/skill-candidates/v0.0.10/github/SKILL.md +74 -0
- package/docs/skill-candidates/v0.0.10/github/agents/openai.yaml +6 -0
- package/docs/skill-candidates/v0.0.10/github/assets/github-small.svg +3 -0
- package/docs/skill-candidates/v0.0.10/github/assets/github.png +0 -0
- package/docs/skill-candidates/v0.0.10/image-graphic-design-rendering/SKILL.md +28 -0
- package/docs/skill-candidates/v0.0.10/language-quality-pt-en-fr-it-ru/SKILL.md +28 -0
- package/docs/skill-candidates/v0.0.10/math-physics-reasoning/SKILL.md +28 -0
- package/docs/skill-candidates/v0.0.10/mcp-builder/LICENSE.txt +202 -0
- package/docs/skill-candidates/v0.0.10/mcp-builder/SKILL.md +236 -0
- package/docs/skill-candidates/v0.0.10/mcp-builder/reference/evaluation.md +602 -0
- package/docs/skill-candidates/v0.0.10/mcp-builder/reference/mcp_best_practices.md +249 -0
- package/docs/skill-candidates/v0.0.10/mcp-builder/reference/node_mcp_server.md +970 -0
- package/docs/skill-candidates/v0.0.10/mcp-builder/reference/python_mcp_server.md +719 -0
- package/docs/skill-candidates/v0.0.10/mcp-builder/scripts/connections.py +151 -0
- package/docs/skill-candidates/v0.0.10/mcp-builder/scripts/evaluation.py +373 -0
- package/docs/skill-candidates/v0.0.10/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/docs/skill-candidates/v0.0.10/mcp-builder/scripts/requirements.txt +2 -0
- package/docs/skill-candidates/v0.0.10/mcp-client-readiness/SKILL.md +31 -0
- package/docs/skill-candidates/v0.0.10/openai-docs/LICENSE.txt +201 -0
- package/docs/skill-candidates/v0.0.10/openai-docs/SKILL.md +161 -0
- package/docs/skill-candidates/v0.0.10/openai-docs/agents/openai.yaml +14 -0
- package/docs/skill-candidates/v0.0.10/openai-docs/assets/openai-small.svg +3 -0
- package/docs/skill-candidates/v0.0.10/openai-docs/assets/openai.png +0 -0
- package/docs/skill-candidates/v0.0.10/openai-docs/references/latest-model.md +37 -0
- package/docs/skill-candidates/v0.0.10/openai-docs/references/prompting-guide.md +244 -0
- package/docs/skill-candidates/v0.0.10/openai-docs/references/upgrade-guide.md +181 -0
- package/docs/skill-candidates/v0.0.10/openai-docs/scripts/fetch-codex-manual.mjs +598 -0
- package/docs/skill-candidates/v0.0.10/openai-docs/scripts/resolve-latest-model-info.js +147 -0
- package/docs/skill-candidates/v0.0.10/playwright/LICENSE.txt +201 -0
- package/docs/skill-candidates/v0.0.10/playwright/NOTICE.txt +14 -0
- package/docs/skill-candidates/v0.0.10/playwright/SKILL.md +147 -0
- package/docs/skill-candidates/v0.0.10/playwright/agents/openai.yaml +6 -0
- package/docs/skill-candidates/v0.0.10/playwright/assets/playwright-small.svg +3 -0
- package/docs/skill-candidates/v0.0.10/playwright/assets/playwright.png +0 -0
- package/docs/skill-candidates/v0.0.10/playwright/references/cli.md +116 -0
- package/docs/skill-candidates/v0.0.10/playwright/references/workflows.md +95 -0
- package/docs/skill-candidates/v0.0.10/playwright/scripts/playwright_cli.sh +25 -0
- package/docs/skill-candidates/v0.0.10/polyglot-backend-engineering/SKILL.md +32 -0
- package/docs/skill-candidates/v0.0.10/screenshot/LICENSE.txt +201 -0
- package/docs/skill-candidates/v0.0.10/screenshot/SKILL.md +267 -0
- package/docs/skill-candidates/v0.0.10/screenshot/agents/openai.yaml +6 -0
- package/docs/skill-candidates/v0.0.10/screenshot/assets/screenshot-small.svg +5 -0
- package/docs/skill-candidates/v0.0.10/screenshot/assets/screenshot.png +0 -0
- package/docs/skill-candidates/v0.0.10/screenshot/scripts/ensure_macos_permissions.sh +54 -0
- package/docs/skill-candidates/v0.0.10/screenshot/scripts/macos_display_info.swift +22 -0
- package/docs/skill-candidates/v0.0.10/screenshot/scripts/macos_permissions.swift +40 -0
- package/docs/skill-candidates/v0.0.10/screenshot/scripts/macos_window_info.swift +126 -0
- package/docs/skill-candidates/v0.0.10/screenshot/scripts/take_screenshot.ps1 +163 -0
- package/docs/skill-candidates/v0.0.10/screenshot/scripts/take_screenshot.py +585 -0
- package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/SKILL.md +62 -0
- package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/agents/openai.yaml +4 -0
- package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/references/activation-policy.md +77 -0
- package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/references/human-approval-policy.md +83 -0
- package/docs/skill-candidates/v0.0.10/skill-master-orchestrator/references/persona-dev-senior-master.md +46 -0
- package/docs/skill-candidates/v0.0.10/terminal-menu-operations/SKILL.md +30 -0
- package/docs/skill-candidates/v0.0.10/terminal-pixel-art-tui/SKILL.md +43 -0
- package/docs/skill-candidates/v0.0.10/webapp-testing/LICENSE.txt +202 -0
- package/docs/skill-candidates/v0.0.10/webapp-testing/SKILL.md +96 -0
- package/docs/skill-candidates/v0.0.10/webapp-testing/examples/console_logging.py +35 -0
- package/docs/skill-candidates/v0.0.10/webapp-testing/examples/element_discovery.py +40 -0
- package/docs/skill-candidates/v0.0.10/webapp-testing/examples/static_html_automation.py +33 -0
- package/docs/skill-candidates/v0.0.10/webapp-testing/scripts/with_server.py +106 -0
- package/docs/skill-candidates/v0.0.10/winui-app/LICENSE.txt +202 -0
- package/docs/skill-candidates/v0.0.10/winui-app/SKILL.md +94 -0
- package/docs/skill-candidates/v0.0.10/winui-app/agents/openai.yaml +5 -0
- package/docs/skill-candidates/v0.0.10/winui-app/assets/winui.png +0 -0
- package/docs/skill-candidates/v0.0.10/winui-app/config.yaml +50 -0
- package/docs/skill-candidates/v0.0.10/winui-app/references/_sections.md +96 -0
- package/docs/skill-candidates/v0.0.10/winui-app/references/accessibility-input-and-localization.md +51 -0
- package/docs/skill-candidates/v0.0.10/winui-app/references/build-run-and-launch-verification.md +72 -0
- package/docs/skill-candidates/v0.0.10/winui-app/references/community-toolkit-controls-and-helpers.md +57 -0
- package/docs/skill-candidates/v0.0.10/winui-app/references/controls-layout-and-adaptive-ui.md +84 -0
- package/docs/skill-candidates/v0.0.10/winui-app/references/foundation-environment-audit-and-remediation.md +82 -0
- package/docs/skill-candidates/v0.0.10/winui-app/references/foundation-setup-and-project-selection.md +67 -0
- package/docs/skill-candidates/v0.0.10/winui-app/references/foundation-template-first-recovery.md +62 -0
- package/docs/skill-candidates/v0.0.10/winui-app/references/foundation-winui-app-structure.md +62 -0
- package/docs/skill-candidates/v0.0.10/winui-app/references/motion-animations-and-polish.md +45 -0
- package/docs/skill-candidates/v0.0.10/winui-app/references/performance-diagnostics-and-responsiveness.md +46 -0
- package/docs/skill-candidates/v0.0.10/winui-app/references/sample-source-map.md +37 -0
- package/docs/skill-candidates/v0.0.10/winui-app/references/shell-navigation-and-windowing.md +67 -0
- package/docs/skill-candidates/v0.0.10/winui-app/references/styling-theming-materials-and-icons.md +71 -0
- package/docs/skill-candidates/v0.0.10/winui-app/references/testing-debugging-and-review-checklists.md +77 -0
- package/docs/skill-candidates/v0.0.10/winui-app/references/windows-app-sdk-lifecycle-notifications-and-deployment.md +52 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/SKILL.md +399 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/common-patterns.md +331 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/complete-examples.md +872 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/component-patterns.md +502 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/data-fetching.md +767 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/file-organization.md +502 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/loading-and-error-states.md +501 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/performance.md +406 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/routing-guide.md +364 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/styling-guide.md +428 -0
- package/docs/skill-candidates/v0.0.11/frontend-dev-guidelines/resources/typescript-standards.md +418 -0
- package/docs/skill-candidates/v0.0.11/git-version-control-ops/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/go-engineering/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/java-engineering/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/javascript-engineering/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/json-contract-design/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/multi-client-mcp-ops/SKILL.md +36 -0
- package/docs/skill-candidates/v0.0.11/nextjs/SKILL.md +745 -0
- package/docs/skill-candidates/v0.0.11/nextjs/agents/openai.yaml +3 -0
- package/docs/skill-candidates/v0.0.11/nextjs/references/app-router-files.md +94 -0
- package/docs/skill-candidates/v0.0.11/python-engineering/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/ruby-engineering/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/senior-fullstack/SKILL.md +209 -0
- package/docs/skill-candidates/v0.0.11/senior-fullstack/references/architecture_patterns.md +103 -0
- package/docs/skill-candidates/v0.0.11/senior-fullstack/references/development_workflows.md +103 -0
- package/docs/skill-candidates/v0.0.11/senior-fullstack/references/tech_stack_guide.md +103 -0
- package/docs/skill-candidates/v0.0.11/senior-fullstack/scripts/code_quality_analyzer.py +114 -0
- package/docs/skill-candidates/v0.0.11/senior-fullstack/scripts/fullstack_scaffolder.py +114 -0
- package/docs/skill-candidates/v0.0.11/senior-fullstack/scripts/project_scaffolder.py +114 -0
- package/docs/skill-candidates/v0.0.11/shadcn/SKILL.md +573 -0
- package/docs/skill-candidates/v0.0.11/shadcn/agents/openai.yaml +3 -0
- package/docs/skill-candidates/v0.0.11/sql-postgresql-engineering/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/terminal-shell-ops/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/typescript-expert/SKILL.md +429 -0
- package/docs/skill-candidates/v0.0.11/typescript-expert/references/tsconfig-strict.json +92 -0
- package/docs/skill-candidates/v0.0.11/typescript-expert/references/typescript-cheatsheet.md +383 -0
- package/docs/skill-candidates/v0.0.11/typescript-expert/references/utility-types.ts +335 -0
- package/docs/skill-candidates/v0.0.11/typescript-expert/scripts/ts_diagnostic.py +203 -0
- package/docs/skill-candidates/v0.0.11/ui-component-primitives/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/web-mobile-design-systems/SKILL.md +34 -0
- package/docs/skill-candidates/v0.0.11/windows-linux-platform-ops/SKILL.md +34 -0
- package/manifests/channels/beta.json +7 -7
- package/manifests/channels/stable.json +8 -8
- package/network/unapproved-skill-candidates.json +34 -1
- package/package.json +7 -2
- package/scripts/verify-menu-actions.mjs +115 -0
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
> Part of the [figma-generate-library skill](../SKILL.md).
|
|
2
|
+
|
|
3
|
+
# Error Recovery Reference
|
|
4
|
+
|
|
5
|
+
Protocol for handling failures, partial state, and incomplete runs across a 20–100+ call design system build.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Core Protocol: STOP → Inspect → Identify → Clean → Fix → Retry
|
|
10
|
+
|
|
11
|
+
**Never retry a failed script without cleanup first.** A failed script may have created partial state — frames, components, or variables that are half-built. Retrying on top of partial state compounds the problem and can make recovery impossible.
|
|
12
|
+
|
|
13
|
+
The mandatory recovery sequence:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
1. STOP — Do not run any more use_figma writes.
|
|
17
|
+
2. INSPECT — Call get_metadata on the current page. Optionally call get_screenshot.
|
|
18
|
+
3. IDENTIFY — Find artifacts from the failed attempt using dsb_run_id pluginData tags.
|
|
19
|
+
4. CLEAN — Run a targeted cleanup script to remove orphaned nodes (pluginData-based, never name-based).
|
|
20
|
+
5. VERIFY — Run get_metadata again to confirm cleanup was complete.
|
|
21
|
+
6. FIX — Correct the script that failed.
|
|
22
|
+
7. RETRY — Re-run the corrected script from the last clean checkpoint.
|
|
23
|
+
8. PERSIST — Update the state ledger with the outcome.
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Do not skip step 4 even if the failure seems minor. Partial frames and components accumulate and cause confusing results in later steps.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 2. `pluginData`-Based Cleanup: Why Name Matching is Dangerous
|
|
31
|
+
|
|
32
|
+
### Why name-prefix matching fails
|
|
33
|
+
|
|
34
|
+
A cleanup script that deletes "all nodes whose name starts with `Button`" will also delete nodes the user may have created manually with that name, or nodes from a previous approved phase. Name-based cleanup has no way to distinguish "orphan from a failed attempt" from "intentional user node."
|
|
35
|
+
|
|
36
|
+
Furthermore, variant names (`Size=Medium, Style=Primary, State=Default`) do not have consistent prefixes that are safe to target without also hitting legitimate nodes.
|
|
37
|
+
|
|
38
|
+
### How `setPluginData` / `getPluginData` works
|
|
39
|
+
|
|
40
|
+
`pluginData` is a key-value store attached to individual nodes. It persists across sessions and is invisible to the user in the Figma UI. Only plugins with the same `pluginId` can read/write data scoped to that plugin. Use three keys:
|
|
41
|
+
|
|
42
|
+
```javascript
|
|
43
|
+
node.setPluginData('dsb_run_id', 'ds-build-2024-001'); // identifies the build run
|
|
44
|
+
node.setPluginData('dsb_phase', 'phase3'); // which phase created this node
|
|
45
|
+
node.setPluginData('dsb_key', 'componentset/button');// unique logical key
|
|
46
|
+
|
|
47
|
+
// Reading:
|
|
48
|
+
const runId = node.getPluginData('dsb_run_id'); // returns '' if never set
|
|
49
|
+
const key = node.getPluginData('dsb_key');
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`getPluginData` returns `''` (empty string, not null) for unset keys. Always check for `!== ''`.
|
|
53
|
+
|
|
54
|
+
**Tag every created node immediately after creation** — before any further operations that might fail. If a failure happens between `createComponent()` and the tagging line, the node will be an untagged orphan. To minimize this window, tag in the same statement sequence as creation:
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
const comp = figma.createComponent();
|
|
58
|
+
comp.setPluginData('dsb_run_id', RUN_ID); // tag immediately
|
|
59
|
+
comp.setPluginData('dsb_key', key); // tag immediately
|
|
60
|
+
// ... then do the rest of the setup
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Complete `cleanupOrphans` script using `dsb_run_id`
|
|
64
|
+
|
|
65
|
+
This script finds all nodes tagged with a given `dsb_run_id` and optionally a `dsb_phase` filter, then removes them. Run it on the specific page where the failure occurred.
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
(async () => {
|
|
69
|
+
try {
|
|
70
|
+
const TARGET_RUN_ID = 'ds-build-2024-001'; // run ID to clean
|
|
71
|
+
const TARGET_PHASE = 'phase3'; // optionally filter by phase ('' = all phases)
|
|
72
|
+
const PAGE_NAME = 'Button'; // page to clean (or null for all pages)
|
|
73
|
+
|
|
74
|
+
const pagesToSearch = PAGE_NAME
|
|
75
|
+
? [figma.root.children.find(p => p.name === PAGE_NAME)].filter(Boolean)
|
|
76
|
+
: figma.root.children;
|
|
77
|
+
|
|
78
|
+
const removed = [];
|
|
79
|
+
const skipped = [];
|
|
80
|
+
|
|
81
|
+
for (const page of pagesToSearch) {
|
|
82
|
+
await figma.setCurrentPageAsync(page);
|
|
83
|
+
|
|
84
|
+
const orphans = page.findAll(node => {
|
|
85
|
+
const runId = node.getPluginData('dsb_run_id');
|
|
86
|
+
if (runId !== TARGET_RUN_ID) return false;
|
|
87
|
+
if (TARGET_PHASE && node.getPluginData('dsb_phase') !== TARGET_PHASE) return false;
|
|
88
|
+
return true;
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Remove leaf-first to avoid removing parents before children
|
|
92
|
+
// Sort by depth (deepest first) to avoid double-remove errors
|
|
93
|
+
const sorted = orphans.slice().sort((a, b) => {
|
|
94
|
+
let depthA = 0, depthB = 0;
|
|
95
|
+
let n = a; while (n.parent) { depthA++; n = n.parent; }
|
|
96
|
+
n = b; while (n.parent) { depthB++; n = n.parent; }
|
|
97
|
+
return depthB - depthA;
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
for (const node of sorted) {
|
|
101
|
+
try {
|
|
102
|
+
if (node.removed) continue; // already removed (was a child of removed parent)
|
|
103
|
+
node.remove();
|
|
104
|
+
removed.push({ id: node.id, name: node.name, key: node.getPluginData('dsb_key') });
|
|
105
|
+
} catch (e) {
|
|
106
|
+
skipped.push({ id: node.id, name: node.name, error: e.message });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
figma.closePlugin(JSON.stringify({ removed: removed.length, skipped: skipped.length, details: removed }));
|
|
112
|
+
} catch (e) { figma.closePluginWithFailure(e.toString()); }
|
|
113
|
+
})();
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
After running cleanup, call `get_metadata` on the target page to confirm the orphaned nodes are gone before retrying.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 3. Idempotency Patterns: Check-Before-Create
|
|
121
|
+
|
|
122
|
+
Run an idempotency check at the start of every create operation. If the entity already exists (tagged with the expected `dsb_key`), skip creation and return the existing ID.
|
|
123
|
+
|
|
124
|
+
### Check-before-create for a variable collection
|
|
125
|
+
|
|
126
|
+
```javascript
|
|
127
|
+
(async () => {
|
|
128
|
+
try {
|
|
129
|
+
const KEY = 'collection/color';
|
|
130
|
+
const RUN_ID = 'ds-build-2024-001';
|
|
131
|
+
const COLLECTION_NAME = 'Color';
|
|
132
|
+
|
|
133
|
+
// Check: does a collection tagged with this key already exist?
|
|
134
|
+
const allCollections = await figma.variables.getLocalVariableCollectionsAsync();
|
|
135
|
+
// Variables/collections support pluginData too — check by name as fallback
|
|
136
|
+
// Note: VariableCollection pluginData is set via collection.setPluginData(...)
|
|
137
|
+
const existing = allCollections.find(c =>
|
|
138
|
+
c.getPluginData('dsb_key') === KEY
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
if (existing) {
|
|
142
|
+
figma.closePlugin(JSON.stringify({
|
|
143
|
+
collectionId: existing.id,
|
|
144
|
+
modeIds: existing.modes.map(m => ({ name: m.name, id: m.modeId })),
|
|
145
|
+
alreadyExisted: true,
|
|
146
|
+
}));
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Create fresh
|
|
151
|
+
const collection = figma.variables.createVariableCollection(COLLECTION_NAME);
|
|
152
|
+
collection.setPluginData('dsb_run_id', RUN_ID);
|
|
153
|
+
collection.setPluginData('dsb_key', KEY);
|
|
154
|
+
|
|
155
|
+
// Rename default mode, add second mode
|
|
156
|
+
collection.renameMode(collection.modes[0].modeId, 'Light');
|
|
157
|
+
const darkModeId = collection.addMode('Dark');
|
|
158
|
+
|
|
159
|
+
figma.closePlugin(JSON.stringify({
|
|
160
|
+
collectionId: collection.id,
|
|
161
|
+
modeIds: [
|
|
162
|
+
{ name: 'Light', id: collection.modes[0].modeId },
|
|
163
|
+
{ name: 'Dark', id: darkModeId },
|
|
164
|
+
],
|
|
165
|
+
}));
|
|
166
|
+
} catch (e) { figma.closePluginWithFailure(e.toString()); }
|
|
167
|
+
})();
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Check-before-create for a page
|
|
171
|
+
|
|
172
|
+
```javascript
|
|
173
|
+
(async () => {
|
|
174
|
+
try {
|
|
175
|
+
const KEY = 'page/button';
|
|
176
|
+
const PAGE_NAME = 'Button';
|
|
177
|
+
const RUN_ID = 'ds-build-2024-001';
|
|
178
|
+
|
|
179
|
+
// Check by pluginData key first, then by name as fallback
|
|
180
|
+
let page = figma.root.children.find(p => p.getPluginData('dsb_key') === KEY);
|
|
181
|
+
if (!page) {
|
|
182
|
+
page = figma.root.children.find(p => p.name === PAGE_NAME);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (page) {
|
|
186
|
+
// Ensure it's tagged if it was found by name only
|
|
187
|
+
if (!page.getPluginData('dsb_key')) {
|
|
188
|
+
page.setPluginData('dsb_run_id', RUN_ID);
|
|
189
|
+
page.setPluginData('dsb_key', KEY);
|
|
190
|
+
}
|
|
191
|
+
figma.closePlugin(JSON.stringify({ pageId: page.id, alreadyExisted: true }));
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
page = figma.createPage();
|
|
196
|
+
page.name = PAGE_NAME;
|
|
197
|
+
page.setPluginData('dsb_run_id', RUN_ID);
|
|
198
|
+
page.setPluginData('dsb_key', KEY);
|
|
199
|
+
|
|
200
|
+
figma.closePlugin(JSON.stringify({ pageId: page.id, alreadyExisted: false }));
|
|
201
|
+
} catch (e) { figma.closePluginWithFailure(e.toString()); }
|
|
202
|
+
})();
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Check-before-create for a component set
|
|
206
|
+
|
|
207
|
+
```javascript
|
|
208
|
+
(async () => {
|
|
209
|
+
try {
|
|
210
|
+
const KEY = 'componentset/button';
|
|
211
|
+
const PAGE_ID = 'PAGE_ID_FROM_STATE';
|
|
212
|
+
const RUN_ID = 'ds-build-2024-001';
|
|
213
|
+
|
|
214
|
+
const page = await figma.getNodeByIdAsync(PAGE_ID);
|
|
215
|
+
await figma.setCurrentPageAsync(page);
|
|
216
|
+
|
|
217
|
+
const existing = page.findAll(n =>
|
|
218
|
+
n.type === 'COMPONENT_SET' && n.getPluginData('dsb_key') === KEY
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
if (existing.length > 0) {
|
|
222
|
+
figma.closePlugin(JSON.stringify({
|
|
223
|
+
componentSetId: existing[0].id,
|
|
224
|
+
alreadyExisted: true,
|
|
225
|
+
}));
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// ... proceed with creation
|
|
230
|
+
figma.closePlugin(JSON.stringify({ componentSetId: null, alreadyExisted: false }));
|
|
231
|
+
} catch (e) { figma.closePluginWithFailure(e.toString()); }
|
|
232
|
+
})();
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## 4. State Ledger
|
|
238
|
+
|
|
239
|
+
### JSON Schema
|
|
240
|
+
|
|
241
|
+
Maintain a state ledger in your context (not in the Figma file) across calls. This is your source of truth for node IDs, completed steps, and pending validations.
|
|
242
|
+
|
|
243
|
+
```json
|
|
244
|
+
{
|
|
245
|
+
"runId": "ds-build-2024-001",
|
|
246
|
+
"phase": "phase3",
|
|
247
|
+
"step": "component-button/combine-variants",
|
|
248
|
+
"completedSteps": [
|
|
249
|
+
"phase0",
|
|
250
|
+
"phase1/collections",
|
|
251
|
+
"phase1/primitives",
|
|
252
|
+
"phase1/semantics",
|
|
253
|
+
"phase2/pages",
|
|
254
|
+
"phase2/foundations-docs",
|
|
255
|
+
"phase3/component-avatar",
|
|
256
|
+
"phase3/component-icon"
|
|
257
|
+
],
|
|
258
|
+
"entities": {
|
|
259
|
+
"collections": {
|
|
260
|
+
"primitives": "VariableCollectionId:1234:5678",
|
|
261
|
+
"color": "VariableCollectionId:1234:5679",
|
|
262
|
+
"spacing": "VariableCollectionId:1234:5680"
|
|
263
|
+
},
|
|
264
|
+
"variables": {
|
|
265
|
+
"color/bg/primary": "VariableId:2345:1",
|
|
266
|
+
"color/bg/secondary": "VariableId:2345:2",
|
|
267
|
+
"color/bg/disabled": "VariableId:2345:3",
|
|
268
|
+
"color/text/on-primary": "VariableId:2345:4",
|
|
269
|
+
"color/text/on-secondary": "VariableId:2345:5",
|
|
270
|
+
"color/text/disabled": "VariableId:2345:6",
|
|
271
|
+
"spacing/sm": "VariableId:2345:7",
|
|
272
|
+
"spacing/md": "VariableId:2345:8",
|
|
273
|
+
"spacing/lg": "VariableId:2345:9",
|
|
274
|
+
"radius/md": "VariableId:2345:10"
|
|
275
|
+
},
|
|
276
|
+
"modes": {
|
|
277
|
+
"color/light": "2345:1",
|
|
278
|
+
"color/dark": "2345:2"
|
|
279
|
+
},
|
|
280
|
+
"pages": {
|
|
281
|
+
"Cover": "0:1",
|
|
282
|
+
"Foundations": "0:2",
|
|
283
|
+
"Button": "0:3"
|
|
284
|
+
},
|
|
285
|
+
"components": {
|
|
286
|
+
"Icon": "3456:1",
|
|
287
|
+
"Avatar": "3456:2",
|
|
288
|
+
"Button": "3456:3"
|
|
289
|
+
},
|
|
290
|
+
"componentSets": {
|
|
291
|
+
"Button": "4567:1"
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
"pendingValidations": [
|
|
295
|
+
"Button:metadata",
|
|
296
|
+
"Button:screenshot"
|
|
297
|
+
],
|
|
298
|
+
"userCheckpoints": {
|
|
299
|
+
"phase0": "approved-2024-01-15",
|
|
300
|
+
"phase1": "approved-2024-01-15",
|
|
301
|
+
"phase2": "approved-2024-01-15",
|
|
302
|
+
"component-avatar": "approved-2024-01-15"
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Persisting between calls
|
|
308
|
+
|
|
309
|
+
After every successful `use_figma` call:
|
|
310
|
+
1. Extract all IDs from the `closePlugin` return value
|
|
311
|
+
2. Add them to the appropriate `entities` section of the ledger
|
|
312
|
+
3. Add the completed step to `completedSteps`
|
|
313
|
+
4. Remove from `pendingValidations` if this call validated something
|
|
314
|
+
5. Update `phase` and `step` to the current position
|
|
315
|
+
|
|
316
|
+
### Rehydrating at session start
|
|
317
|
+
|
|
318
|
+
If a conversation is interrupted and resumed, read the state ledger and verify key entities still exist:
|
|
319
|
+
|
|
320
|
+
```javascript
|
|
321
|
+
(async () => {
|
|
322
|
+
try {
|
|
323
|
+
// Verify that critical nodes from the ledger still exist
|
|
324
|
+
const toVerify = {
|
|
325
|
+
'color-collection': 'VariableCollectionId:1234:5679',
|
|
326
|
+
'button-page': '0:3',
|
|
327
|
+
'button-componentset': '4567:1',
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
const results = {};
|
|
331
|
+
for (const [label, id] of Object.entries(toVerify)) {
|
|
332
|
+
const node = await figma.getNodeByIdAsync(id)
|
|
333
|
+
.catch(() => null);
|
|
334
|
+
results[label] = node ? { found: true, name: node.name } : { found: false };
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
figma.closePlugin(JSON.stringify(results));
|
|
338
|
+
} catch (e) { figma.closePluginWithFailure(e.toString()); }
|
|
339
|
+
})();
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
If any entity is missing, treat the phase that created it as incomplete and re-run from that checkpoint.
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## 5. Resume Protocol
|
|
347
|
+
|
|
348
|
+
### Step 1: Inspect the file for `dsb_run_id` tags
|
|
349
|
+
|
|
350
|
+
```javascript
|
|
351
|
+
(async () => {
|
|
352
|
+
try {
|
|
353
|
+
const TARGET_RUN_ID = 'ds-build-2024-001';
|
|
354
|
+
const inventory = { pages: [], variables: [], componentSets: [], frames: [] };
|
|
355
|
+
|
|
356
|
+
// Scan pages
|
|
357
|
+
for (const page of figma.root.children) {
|
|
358
|
+
if (page.getPluginData('dsb_run_id') === TARGET_RUN_ID) {
|
|
359
|
+
inventory.pages.push({ id: page.id, name: page.name, key: page.getPluginData('dsb_key') });
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Scan variables
|
|
364
|
+
const allVars = await figma.variables.getLocalVariablesAsync();
|
|
365
|
+
for (const v of allVars) {
|
|
366
|
+
if (v.getPluginData('dsb_run_id') === TARGET_RUN_ID) {
|
|
367
|
+
inventory.variables.push({ id: v.id, name: v.name, key: v.getPluginData('dsb_key') });
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Scan all component sets and frames on each page
|
|
372
|
+
for (const page of figma.root.children) {
|
|
373
|
+
await figma.setCurrentPageAsync(page);
|
|
374
|
+
const nodes = page.findAll(n => n.getPluginData('dsb_run_id') === TARGET_RUN_ID);
|
|
375
|
+
for (const n of nodes) {
|
|
376
|
+
if (n.type === 'COMPONENT_SET') {
|
|
377
|
+
inventory.componentSets.push({ id: n.id, name: n.name, key: n.getPluginData('dsb_key') });
|
|
378
|
+
} else if (n.type === 'FRAME') {
|
|
379
|
+
inventory.frames.push({ id: n.id, name: n.name, key: n.getPluginData('dsb_key') });
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
figma.closePlugin(JSON.stringify(inventory));
|
|
385
|
+
} catch (e) { figma.closePluginWithFailure(e.toString()); }
|
|
386
|
+
})();
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### Step 2: Reconstruct state from inventory
|
|
390
|
+
|
|
391
|
+
Map the inventory keys back to the state ledger schema. For each entity found with a `dsb_key`, add its ID to the appropriate section. Mark the corresponding step as `completedSteps`.
|
|
392
|
+
|
|
393
|
+
Example mapping:
|
|
394
|
+
```
|
|
395
|
+
key: 'collection/color' → entities.collections.color
|
|
396
|
+
key: 'variable/color/bg/primary' → entities.variables['color/bg/primary']
|
|
397
|
+
key: 'page/button' → entities.pages.Button
|
|
398
|
+
key: 'componentset/button' → entities.componentSets.Button
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### Step 3: Identify the resume point
|
|
402
|
+
|
|
403
|
+
The resume point is the first step in the workflow that is NOT in `completedSteps`. If the inventory shows the Button component set exists but the pending validations list shows `'Button:screenshot'`, the resume point is the screenshot validation call, not re-creation.
|
|
404
|
+
|
|
405
|
+
Use the checkpoint table from the workflow to determine which phase to continue from:
|
|
406
|
+
|
|
407
|
+
```
|
|
408
|
+
Phase 0 complete: all planned pages listed in entities.pages
|
|
409
|
+
Phase 1 complete: all planned variables listed in entities.variables with correct scopes
|
|
410
|
+
Phase 2 complete: all structural pages + foundations doc frames present
|
|
411
|
+
Phase 3 complete (per component): componentSet exists + no pending validations + user checkpoint recorded
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
---
|
|
415
|
+
|
|
416
|
+
## 6. Failure Taxonomy
|
|
417
|
+
|
|
418
|
+
### Recoverable Errors
|
|
419
|
+
|
|
420
|
+
These can be fixed and retried without affecting already-created entities:
|
|
421
|
+
|
|
422
|
+
| Category | Examples | Recovery |
|
|
423
|
+
|---|---|---|
|
|
424
|
+
| Layout errors | Variants stacked at (0,0), wrong padding values | Re-run the positioning step only |
|
|
425
|
+
| Naming issues | Typo in variant name, wrong casing | Find nodes by `dsb_key`, update `name` property |
|
|
426
|
+
| Missing property wiring | `componentPropertyReferences` not set | Find component set by ID, re-run the property wiring step |
|
|
427
|
+
| Variable binding omission | A fill was hardcoded instead of bound | Find nodes by `dsb_key`, re-bind the fill |
|
|
428
|
+
| Wrong variable bound | Bound to wrong variable ID | Re-bind with correct variable ID |
|
|
429
|
+
| Text not visible | Font not loaded before text write | Re-run text creation with `loadFontAsync` first |
|
|
430
|
+
| Partial variant creation | Only 12 of 18 variants created before timeout | Run cleanup for the partial set, re-run full variant creation |
|
|
431
|
+
|
|
432
|
+
### Structural Corruption (Requires Rollback or Restart)
|
|
433
|
+
|
|
434
|
+
These errors leave the file in a state where continuing forward is unreliable:
|
|
435
|
+
|
|
436
|
+
| Category | Examples | Recovery |
|
|
437
|
+
|---|---|---|
|
|
438
|
+
| Component cycle | A component instance was accidentally nested inside itself | Full cleanup of the affected component, restart that component from Call 1 |
|
|
439
|
+
| combineAsVariants with non-components | Mixed node types passed to combineAsVariants, causing unexpected merges | Remove the malformed component set, re-run from variant creation |
|
|
440
|
+
| Variable collection ID drift | Collection was deleted and re-created, old IDs in state ledger are stale | Re-run Phase 1 completely; update all IDs in state ledger |
|
|
441
|
+
| Page deletion | A page was deleted after component sets were created on it | Treat as Phase 2 incomplete; re-create the page + re-run affected component creations |
|
|
442
|
+
| Mode limit exceeded | `addMode` threw because the plan is Starter or Professional | Redesign variable collection architecture to fit mode limits, restart Phase 1 |
|
|
443
|
+
|
|
444
|
+
**Recovery from structural corruption**: run `cleanupOrphans` for the entire run ID, then restart from the affected phase. Do NOT attempt to patch corrupted structure in-place.
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
## 7. Common Error Table
|
|
449
|
+
|
|
450
|
+
| Error message | Likely cause | Fix |
|
|
451
|
+
|---|---|---|
|
|
452
|
+
| `"Cannot create component from node"` | Tried to call `createComponentFromNode` on a node inside a component | Create a fresh component instead: `figma.createComponent()` |
|
|
453
|
+
| `"in addMode: Limited to N modes only"` | Plan mode limit hit (Starter=1, Professional=4) | Redesign to use fewer modes or upgrade plan |
|
|
454
|
+
| `"setCurrentPageAsync: page does not exist"` | Page was deleted or wrong ID | Re-create the page using the idempotency pattern |
|
|
455
|
+
| `"Cannot read properties of null"` | `getNodeByIdAsync` returned null — node was deleted | Run the resume protocol to find what exists, update state ledger |
|
|
456
|
+
| `"Expected nodes to be component nodes"` | Passed a non-ComponentNode to `combineAsVariants` | Filter the array: `nodes.filter(n => n.type === 'COMPONENT')` |
|
|
457
|
+
| `"in createVariable: Cannot create variable"` | Collection was deleted or ID is wrong | Verify collection exists with `getVariableCollectionByIdAsync` |
|
|
458
|
+
| `"font not loaded"` | Called a text property setter without `loadFontAsync` first | Add `await figma.loadFontAsync({ family, style })` before the text operation |
|
|
459
|
+
| `"Cannot set properties of a read-only array"` | Tried to mutate fills/strokes in-place | Clone first: `const fills = JSON.parse(JSON.stringify(node.fills))` |
|
|
460
|
+
| `"Expected RGBA color"` | Color value out of 0–1 range | Divide RGB 0–255 values by 255: `{ r: 65/255, g: 85/255, b: 143/255 }` |
|
|
461
|
+
| `"Cannot add children to a non-parent node"` | Tried to append a child to a leaf node (text, rect) | Ensure the parent is a FrameNode, ComponentNode, or GroupNode |
|
|
462
|
+
| `"in combineAsVariants: nodes must be in the same parent"` | Components are on different pages | Move all components to the same page before combining |
|
|
463
|
+
| `"Script exceeded time limit"` | Loop creating too many nodes in one call | Split the work: create N/2 variants per call |
|
|
464
|
+
| Component set deletes itself | Tried to create a component set with no children | `combineAsVariants` requires at least 1 node — always pass 1+ |
|
|
465
|
+
| `addComponentProperty` returns unexpected name | This is normal — `BOOLEAN`/`TEXT`/`INSTANCE_SWAP` get `#id:id` suffix | Save the returned key immediately and use that, not the input name |
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
## 8. Per-Phase Recovery Guidance
|
|
470
|
+
|
|
471
|
+
### Phase 1 fails mid-execution (variable creation)
|
|
472
|
+
|
|
473
|
+
Symptoms: partial variable collections exist; some variables are missing; some have wrong values.
|
|
474
|
+
|
|
475
|
+
Recovery steps:
|
|
476
|
+
1. Run inspection script to find all variables tagged with your `dsb_run_id`
|
|
477
|
+
2. For each variable with `dsb_key` matching the plan, verify its `valuesByMode` and `scopes` are correct
|
|
478
|
+
3. If a variable is malformed, call `variable.remove()` and recreate it
|
|
479
|
+
4. If the collection itself is malformed, remove the entire collection and recreate from scratch
|
|
480
|
+
5. Do NOT proceed to Phase 2 until ALL planned variables exist with correct scopes and code syntax
|
|
481
|
+
|
|
482
|
+
**The most common Phase 1 failure:** running out of time in a single `use_figma` call when creating many variables. Fix: batch variable creation — create at most 20–30 variables per call.
|
|
483
|
+
|
|
484
|
+
### Phase 2 fails mid-execution (page/file structure)
|
|
485
|
+
|
|
486
|
+
Symptoms: some pages exist, others are missing; foundations doc frames are incomplete.
|
|
487
|
+
|
|
488
|
+
Recovery steps:
|
|
489
|
+
1. Identify which pages were successfully created (check for `dsb_key` tags)
|
|
490
|
+
2. Mark remaining pages as pending and create them in subsequent calls
|
|
491
|
+
3. If a foundations doc frame is malformed, run `cleanupOrphans` for `dsb_phase: 'phase2'` on that page, then recreate
|
|
492
|
+
|
|
493
|
+
Phase 2 failures rarely require Phase 1 rollback unless the page structure itself is corrupted (which is unusual).
|
|
494
|
+
|
|
495
|
+
### Phase 3 fails mid-execution (component creation)
|
|
496
|
+
|
|
497
|
+
This is the most common failure mode in long builds. Handle by component:
|
|
498
|
+
|
|
499
|
+
```
|
|
500
|
+
If failure in Call 1 (page creation):
|
|
501
|
+
→ Idempotency check will handle on retry. Safe to re-run.
|
|
502
|
+
|
|
503
|
+
If failure in Call 2 (doc frame):
|
|
504
|
+
→ cleanupOrphans for dsb_key='doc/{component}', then re-run.
|
|
505
|
+
|
|
506
|
+
If failure in Call 3 (base component):
|
|
507
|
+
→ Remove the partial base component node, re-run from Call 3.
|
|
508
|
+
|
|
509
|
+
If failure in Call 4 (variant creation):
|
|
510
|
+
→ cleanupOrphans for dsb_phase='phase3' on the component page (scoped by page).
|
|
511
|
+
→ Re-run from Call 3 (base) or Call 4 if base was successfully tagged.
|
|
512
|
+
|
|
513
|
+
If failure in Call 5 (combineAsVariants + layout):
|
|
514
|
+
→ Remove the malformed component set.
|
|
515
|
+
→ Remove all variant ComponentNodes for this component (by dsb_key pattern).
|
|
516
|
+
→ Re-run from Call 3.
|
|
517
|
+
|
|
518
|
+
If failure in Call 6 (component properties):
|
|
519
|
+
→ The component set already exists and is structurally sound.
|
|
520
|
+
→ Re-run Call 6 only — addComponentProperty is safe to retry if
|
|
521
|
+
you first check componentPropertyDefinitions for existing properties.
|
|
522
|
+
→ Idempotency check: if 'Label' property already exists, skip addComponentProperty.
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
**Idempotency for component properties (Call 6 retry):**
|
|
526
|
+
|
|
527
|
+
```javascript
|
|
528
|
+
const existingDefs = cs.componentPropertyDefinitions;
|
|
529
|
+
const labelKey = existingDefs['Label']
|
|
530
|
+
? Object.keys(existingDefs).find(k => k.startsWith('Label'))
|
|
531
|
+
: cs.addComponentProperty('Label', 'TEXT', 'Button');
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
### Phase 4 fails mid-execution (QA / Code Connect)
|
|
535
|
+
|
|
536
|
+
Phase 4 is non-destructive. Failures here do not corrupt Phase 3 work. Common failures:
|
|
537
|
+
|
|
538
|
+
- **Accessibility audit finds contrast failures:** do not attempt auto-fix. Report the specific variable IDs and token names that fail, then ask the user which value to update.
|
|
539
|
+
- **Naming audit finds duplicates:** list all duplicates with their `dsb_key` values, ask user which to keep, then remove the duplicates.
|
|
540
|
+
- **Code Connect mapping fails:** treat as incomplete, not broken. Continue and leave as pending.
|