@evalops/maestro 0.10.50 → 0.10.51
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/dist/agent/agent-outcome.d.ts +54 -0
- package/dist/agent/agent-outcome.d.ts.map +1 -0
- package/dist/agent/agent-outcome.js +142 -0
- package/dist/agent/agent-outcome.js.map +1 -0
- package/dist/agent/agent-resume.d.ts.map +1 -1
- package/dist/agent/agent-resume.js +3 -3
- package/dist/agent/agent-resume.js.map +1 -1
- package/dist/agent/agent-run-summary.d.ts +37 -0
- package/dist/agent/agent-run-summary.d.ts.map +1 -0
- package/dist/agent/agent-run-summary.js +15 -0
- package/dist/agent/agent-run-summary.js.map +1 -0
- package/dist/agent/agent-work-board.d.ts +82 -0
- package/dist/agent/agent-work-board.d.ts.map +1 -0
- package/dist/agent/agent-work-board.js +312 -0
- package/dist/agent/agent-work-board.js.map +1 -0
- package/dist/agent/auto-compaction.d.ts +7 -2
- package/dist/agent/auto-compaction.d.ts.map +1 -1
- package/dist/agent/auto-compaction.js +23 -10
- package/dist/agent/auto-compaction.js.map +1 -1
- package/dist/agent/mission-artifacts.d.ts +62 -0
- package/dist/agent/mission-artifacts.d.ts.map +1 -0
- package/dist/agent/mission-artifacts.js +438 -0
- package/dist/agent/mission-artifacts.js.map +1 -0
- package/dist/agent/mission-manifest.d.ts +139 -3
- package/dist/agent/mission-manifest.d.ts.map +1 -1
- package/dist/agent/mission-manifest.js +549 -3
- package/dist/agent/mission-manifest.js.map +1 -1
- package/dist/agent/mission-store.d.ts +80 -0
- package/dist/agent/mission-store.d.ts.map +1 -0
- package/dist/agent/mission-store.js +603 -0
- package/dist/agent/mission-store.js.map +1 -0
- package/dist/agent/modes.d.ts +2 -2
- package/dist/agent/modes.d.ts.map +1 -1
- package/dist/agent/modes.js +10 -3
- package/dist/agent/modes.js.map +1 -1
- package/dist/agent/providers/codex-app-server.d.ts.map +1 -1
- package/dist/agent/providers/codex-app-server.js +1 -3
- package/dist/agent/providers/codex-app-server.js.map +1 -1
- package/dist/agent/providers/google-gemini-cli.js +203 -107
- package/dist/agent/providers/google.js +100 -41
- package/dist/agent/providers/scripted.d.ts.map +1 -1
- package/dist/agent/providers/scripted.js +1 -3
- package/dist/agent/providers/scripted.js.map +1 -1
- package/dist/agent/providers/validation.d.ts.map +1 -1
- package/dist/agent/providers/validation.js +1 -3
- package/dist/agent/providers/validation.js.map +1 -1
- package/dist/agent/providers/vertex.js +203 -107
- package/dist/agent/snapshot-store.d.ts +32 -0
- package/dist/agent/snapshot-store.d.ts.map +1 -0
- package/dist/agent/snapshot-store.js +195 -0
- package/dist/agent/snapshot-store.js.map +1 -0
- package/dist/agent/specialist-profiles.d.ts +36 -0
- package/dist/agent/specialist-profiles.d.ts.map +1 -0
- package/dist/agent/specialist-profiles.js +159 -0
- package/dist/agent/specialist-profiles.js.map +1 -0
- package/dist/agent/subagent-specs.d.ts +4 -1
- package/dist/agent/subagent-specs.d.ts.map +1 -1
- package/dist/agent/subagent-specs.js +81 -8
- package/dist/agent/subagent-specs.js.map +1 -1
- package/dist/agent/swarm/coverage-gate.d.ts +37 -0
- package/dist/agent/swarm/coverage-gate.d.ts.map +1 -0
- package/dist/agent/swarm/coverage-gate.js +48 -0
- package/dist/agent/swarm/coverage-gate.js.map +1 -0
- package/dist/agent/swarm/executor.d.ts +1 -0
- package/dist/agent/swarm/executor.d.ts.map +1 -1
- package/dist/agent/swarm/executor.js +151 -15
- package/dist/agent/swarm/executor.js.map +1 -1
- package/dist/agent/swarm/orchestrator-prompt.d.ts +25 -0
- package/dist/agent/swarm/orchestrator-prompt.d.ts.map +1 -0
- package/dist/agent/swarm/orchestrator-prompt.js +48 -0
- package/dist/agent/swarm/orchestrator-prompt.js.map +1 -0
- package/dist/agent/swarm/plan-parser.d.ts.map +1 -1
- package/dist/agent/swarm/plan-parser.js +27 -2
- package/dist/agent/swarm/plan-parser.js.map +1 -1
- package/dist/agent/swarm/types.d.ts +17 -0
- package/dist/agent/swarm/types.d.ts.map +1 -1
- package/dist/agent/swarm/types.js.map +1 -1
- package/dist/agent/swarm/validation-directive.d.ts +21 -0
- package/dist/agent/swarm/validation-directive.d.ts.map +1 -0
- package/dist/agent/swarm/validation-directive.js +25 -0
- package/dist/agent/swarm/validation-directive.js.map +1 -0
- package/dist/agent/transport/tool-execution-bridge.d.ts.map +1 -1
- package/dist/agent/transport/tool-execution-bridge.js +4 -1
- package/dist/agent/transport/tool-execution-bridge.js.map +1 -1
- package/dist/api/enterprise-routes.d.ts.map +1 -1
- package/dist/api/enterprise-routes.js +87 -10
- package/dist/api/enterprise-routes.js.map +1 -1
- package/dist/api/org-settings-merge.d.ts +12 -0
- package/dist/api/org-settings-merge.d.ts.map +1 -0
- package/dist/api/org-settings-merge.js +38 -0
- package/dist/api/org-settings-merge.js.map +1 -0
- package/dist/api/user-settings-merge.d.ts +16 -0
- package/dist/api/user-settings-merge.d.ts.map +1 -0
- package/dist/api/user-settings-merge.js +37 -0
- package/dist/api/user-settings-merge.js.map +1 -0
- package/dist/app-server/daemon-lifecycle-api.d.ts.map +1 -1
- package/dist/app-server/daemon-lifecycle-api.js +1 -3
- package/dist/app-server/daemon-lifecycle-api.js.map +1 -1
- package/dist/app-server/external-agent-import-api.d.ts.map +1 -1
- package/dist/app-server/external-agent-import-api.js +1 -3
- package/dist/app-server/external-agent-import-api.js.map +1 -1
- package/dist/app-server/network-governance-api.d.ts.map +1 -1
- package/dist/app-server/network-governance-api.js +1 -3
- package/dist/app-server/network-governance-api.js.map +1 -1
- package/dist/app-server/plugin-bundle-api.d.ts.map +1 -1
- package/dist/app-server/plugin-bundle-api.js +1 -3
- package/dist/app-server/plugin-bundle-api.js.map +1 -1
- package/dist/app-server/policy-control-api.d.ts.map +1 -1
- package/dist/app-server/policy-control-api.js +1 -3
- package/dist/app-server/policy-control-api.js.map +1 -1
- package/dist/app-server/protocol-modes-api.d.ts.map +1 -1
- package/dist/app-server/protocol-modes-api.js +1 -3
- package/dist/app-server/protocol-modes-api.js.map +1 -1
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +15 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/commands/a2a.d.ts.map +1 -1
- package/dist/cli/commands/a2a.js +1 -3
- package/dist/cli/commands/a2a.js.map +1 -1
- package/dist/cli/commands/agents.d.ts +4 -0
- package/dist/cli/commands/agents.d.ts.map +1 -1
- package/dist/cli/commands/agents.js +149 -0
- package/dist/cli/commands/agents.js.map +1 -1
- package/dist/cli/commands/mission.d.ts +4 -0
- package/dist/cli/commands/mission.d.ts.map +1 -0
- package/dist/cli/commands/mission.js +196 -0
- package/dist/cli/commands/mission.js.map +1 -0
- package/dist/cli/commands/value.d.ts +10 -0
- package/dist/cli/commands/value.d.ts.map +1 -0
- package/dist/cli/commands/value.js +33 -0
- package/dist/cli/commands/value.js.map +1 -0
- package/dist/cli/headless-protocol.d.ts.map +1 -1
- package/dist/cli/headless-protocol.js +1 -3
- package/dist/cli/headless-protocol.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +10 -0
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/system-prompt.d.ts.map +1 -1
- package/dist/cli/system-prompt.js +38 -7
- package/dist/cli/system-prompt.js.map +1 -1
- package/dist/cli-runtime.js +7756 -2800
- package/dist/cli-tui/client-tools/client-tool-controller.d.ts.map +1 -1
- package/dist/cli-tui/client-tools/client-tool-controller.js +1 -3
- package/dist/cli-tui/client-tools/client-tool-controller.js.map +1 -1
- package/dist/cli-tui/commands/undo-handlers.d.ts.map +1 -1
- package/dist/cli-tui/commands/undo-handlers.js +7 -2
- package/dist/cli-tui/commands/undo-handlers.js.map +1 -1
- package/dist/cli-tui/tui-renderer/skills-controller.d.ts +3 -0
- package/dist/cli-tui/tui-renderer/skills-controller.d.ts.map +1 -1
- package/dist/cli-tui/tui-renderer/skills-controller.js +77 -33
- package/dist/cli-tui/tui-renderer/skills-controller.js.map +1 -1
- package/dist/codex/app-server-client.d.ts.map +1 -1
- package/dist/codex/app-server-client.js +1 -3
- package/dist/codex/app-server-client.js.map +1 -1
- package/dist/codex/compatibility.d.ts.map +1 -1
- package/dist/codex/compatibility.js +1 -3
- package/dist/codex/compatibility.js.map +1 -1
- package/dist/codex/subagent-dispatch-table.d.ts +8 -0
- package/dist/codex/subagent-dispatch-table.d.ts.map +1 -1
- package/dist/codex/subagent-dispatch-table.js +23 -0
- package/dist/codex/subagent-dispatch-table.js.map +1 -1
- package/dist/context/manifest.d.ts.map +1 -1
- package/dist/context/manifest.js +1 -3
- package/dist/context/manifest.js.map +1 -1
- package/dist/conversation/render-model.d.ts +0 -36
- package/dist/conversation/render-model.d.ts.map +1 -1
- package/dist/conversation/render-model.js +1 -3
- package/dist/conversation/render-model.js.map +1 -1
- package/dist/customer-value/ambient-learning.d.ts +75 -0
- package/dist/customer-value/ambient-learning.d.ts.map +1 -0
- package/dist/customer-value/ambient-learning.js +472 -0
- package/dist/customer-value/ambient-learning.js.map +1 -0
- package/dist/customer-value/internal-helpers.d.ts +13 -0
- package/dist/customer-value/internal-helpers.d.ts.map +1 -0
- package/dist/customer-value/internal-helpers.js +70 -0
- package/dist/customer-value/internal-helpers.js.map +1 -0
- package/dist/customer-value/report.d.ts +282 -0
- package/dist/customer-value/report.d.ts.map +1 -0
- package/dist/customer-value/report.js +2085 -0
- package/dist/customer-value/report.js.map +1 -0
- package/dist/db/schema.d.ts +5 -1
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js.map +1 -1
- package/dist/evalops/agent-bootstrap.d.ts.map +1 -1
- package/dist/evalops/agent-bootstrap.js +1 -3
- package/dist/evalops/agent-bootstrap.js.map +1 -1
- package/dist/evalops/agent-mcp-metadata.d.ts.map +1 -1
- package/dist/evalops/agent-mcp-metadata.js +1 -3
- package/dist/evalops/agent-mcp-metadata.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/installers/maestro-review-workflow.d.ts +38 -0
- package/dist/installers/maestro-review-workflow.d.ts.map +1 -0
- package/dist/installers/maestro-review-workflow.js +163 -0
- package/dist/installers/maestro-review-workflow.js.map +1 -0
- package/dist/load-env.d.ts.map +1 -1
- package/dist/load-env.js +2 -1
- package/dist/load-env.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +92 -3
- package/dist/main.js.map +1 -1
- package/dist/mcp/config.d.ts.map +1 -1
- package/dist/mcp/config.js +1 -3
- package/dist/mcp/config.js.map +1 -1
- package/dist/mcp/elicitation.d.ts.map +1 -1
- package/dist/mcp/elicitation.js +1 -3
- package/dist/mcp/elicitation.js.map +1 -1
- package/dist/mcp/official-registry.d.ts.map +1 -1
- package/dist/mcp/official-registry.js +1 -3
- package/dist/mcp/official-registry.js.map +1 -1
- package/dist/mcp/workspace-trust.d.ts.map +1 -1
- package/dist/mcp/workspace-trust.js +1 -3
- package/dist/mcp/workspace-trust.js.map +1 -1
- package/dist/memory/service-client.d.ts.map +1 -1
- package/dist/memory/service-client.js +1 -3
- package/dist/memory/service-client.js.map +1 -1
- package/dist/models/config-loader.d.ts.map +1 -1
- package/dist/models/config-loader.js +1 -3
- package/dist/models/config-loader.js.map +1 -1
- package/dist/node_modules/@evalops/contracts/dist/index.d.ts +1 -0
- package/dist/node_modules/@evalops/contracts/dist/index.d.ts.map +1 -1
- package/dist/node_modules/@evalops/contracts/dist/index.js +1 -0
- package/dist/node_modules/@evalops/contracts/dist/index.js.map +1 -1
- package/dist/node_modules/@evalops/contracts/dist/maestro-settings.d.ts +61 -0
- package/dist/node_modules/@evalops/contracts/dist/maestro-settings.d.ts.map +1 -0
- package/dist/node_modules/@evalops/contracts/dist/maestro-settings.js +183 -0
- package/dist/node_modules/@evalops/contracts/dist/maestro-settings.js.map +1 -0
- package/dist/node_modules/@evalops/contracts/package.json +1 -1
- package/dist/node_modules/@evalops/tui/package.json +1 -1
- package/dist/oauth/connectors.d.ts.map +1 -1
- package/dist/oauth/connectors.js +1 -3
- package/dist/oauth/connectors.js.map +1 -1
- package/dist/oauth/evalops.d.ts.map +1 -1
- package/dist/oauth/evalops.js +1 -3
- package/dist/oauth/evalops.js.map +1 -1
- package/dist/platform/a2a-client.d.ts.map +1 -1
- package/dist/platform/a2a-client.js +1 -3
- package/dist/platform/a2a-client.js.map +1 -1
- package/dist/platform/a2a-cockpit.d.ts +1 -0
- package/dist/platform/a2a-cockpit.d.ts.map +1 -1
- package/dist/platform/a2a-cockpit.js +42 -11
- package/dist/platform/a2a-cockpit.js.map +1 -1
- package/dist/platform/a2a-completion-audit.d.ts +1 -1
- package/dist/platform/a2a-completion-audit.d.ts.map +1 -1
- package/dist/platform/a2a-completion-audit.js +7 -11
- package/dist/platform/a2a-completion-audit.js.map +1 -1
- package/dist/platform/a2a-maestro-peer.js +16 -0
- package/dist/platform/a2a-maestro-peer.js.map +1 -1
- package/dist/platform/a2a-peer-pairing.d.ts.map +1 -1
- package/dist/platform/a2a-peer-pairing.js +1 -3
- package/dist/platform/a2a-peer-pairing.js.map +1 -1
- package/dist/platform/a2a-peer-registry.d.ts.map +1 -1
- package/dist/platform/a2a-peer-registry.js +1 -3
- package/dist/platform/a2a-peer-registry.js.map +1 -1
- package/dist/platform/a2a-task-ledger.d.ts +20 -0
- package/dist/platform/a2a-task-ledger.d.ts.map +1 -1
- package/dist/platform/a2a-task-ledger.js +207 -11
- package/dist/platform/a2a-task-ledger.js.map +1 -1
- package/dist/platform/a2a-work-graph.d.ts.map +1 -1
- package/dist/platform/a2a-work-graph.js +1 -3
- package/dist/platform/a2a-work-graph.js.map +1 -1
- package/dist/platform/operating-layer.d.ts.map +1 -1
- package/dist/platform/operating-layer.js +14 -8
- package/dist/platform/operating-layer.js.map +1 -1
- package/dist/platform/tool-execution-client.d.ts.map +1 -1
- package/dist/platform/tool-execution-client.js +19 -2
- package/dist/platform/tool-execution-client.js.map +1 -1
- package/dist/providers/auth.d.ts.map +1 -1
- package/dist/providers/auth.js +1 -3
- package/dist/providers/auth.js.map +1 -1
- package/dist/runtime/env.d.ts +9 -1
- package/dist/runtime/env.d.ts.map +1 -1
- package/dist/runtime/env.js +63 -1
- package/dist/runtime/env.js.map +1 -1
- package/dist/safety/policy.d.ts.map +1 -1
- package/dist/safety/policy.js +1 -4
- package/dist/safety/policy.js.map +1 -1
- package/dist/sandbox/docker-sandbox.d.ts.map +1 -1
- package/dist/sandbox/docker-sandbox.js +6 -1
- package/dist/sandbox/docker-sandbox.js.map +1 -1
- package/dist/server/handlers/hosted-runner-drain.d.ts.map +1 -1
- package/dist/server/handlers/hosted-runner-drain.js +1 -3
- package/dist/server/handlers/hosted-runner-drain.js.map +1 -1
- package/dist/server/handlers/platform-a2a-push.d.ts.map +1 -1
- package/dist/server/handlers/platform-a2a-push.js +53 -2
- package/dist/server/handlers/platform-a2a-push.js.map +1 -1
- package/dist/server/handlers/runtime-app-server-ws.d.ts.map +1 -1
- package/dist/server/handlers/runtime-app-server-ws.js +1 -3
- package/dist/server/handlers/runtime-app-server-ws.js.map +1 -1
- package/dist/server/headless-runtime-service.d.ts +16 -0
- package/dist/server/headless-runtime-service.d.ts.map +1 -1
- package/dist/server/headless-runtime-service.js +232 -206
- package/dist/server/headless-runtime-service.js.map +1 -1
- package/dist/server/hosted-agent-runtime-progress.d.ts.map +1 -1
- package/dist/server/hosted-agent-runtime-progress.js +12 -3
- package/dist/server/hosted-agent-runtime-progress.js.map +1 -1
- package/dist/server/pending-request-payload.d.ts.map +1 -1
- package/dist/server/pending-request-payload.js +1 -3
- package/dist/server/pending-request-payload.js.map +1 -1
- package/dist/server/route-auth.d.ts.map +1 -1
- package/dist/server/route-auth.js +2 -0
- package/dist/server/route-auth.js.map +1 -1
- package/dist/server/session-serialization.d.ts.map +1 -1
- package/dist/server/session-serialization.js +1 -3
- package/dist/server/session-serialization.js.map +1 -1
- package/dist/services/compliance/normalize.d.ts.map +1 -1
- package/dist/services/compliance/normalize.js +1 -3
- package/dist/services/compliance/normalize.js.map +1 -1
- package/dist/services/intelligent-router/normalize.d.ts.map +1 -1
- package/dist/services/intelligent-router/normalize.js +1 -3
- package/dist/services/intelligent-router/normalize.js.map +1 -1
- package/dist/services/revenue-attribution/normalize.d.ts.map +1 -1
- package/dist/services/revenue-attribution/normalize.js +1 -3
- package/dist/services/revenue-attribution/normalize.js.map +1 -1
- package/dist/services/traces/normalize.d.ts.map +1 -1
- package/dist/services/traces/normalize.js +1 -3
- package/dist/services/traces/normalize.js.map +1 -1
- package/dist/services/workspace-config/normalize.d.ts.map +1 -1
- package/dist/services/workspace-config/normalize.js +1 -3
- package/dist/services/workspace-config/normalize.js.map +1 -1
- package/dist/skills/composer.d.ts.map +1 -1
- package/dist/skills/composer.js +13 -1
- package/dist/skills/composer.js.map +1 -1
- package/dist/skills/index.d.ts +1 -0
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +1 -0
- package/dist/skills/index.js.map +1 -1
- package/dist/skills/learned-guidelines.d.ts +33 -0
- package/dist/skills/learned-guidelines.d.ts.map +1 -0
- package/dist/skills/learned-guidelines.js +291 -0
- package/dist/skills/learned-guidelines.js.map +1 -0
- package/dist/skills/linter.d.ts.map +1 -1
- package/dist/skills/linter.js +1 -3
- package/dist/skills/linter.js.map +1 -1
- package/dist/skills/runtime-activation.d.ts +1 -0
- package/dist/skills/runtime-activation.d.ts.map +1 -1
- package/dist/skills/runtime-activation.js +2 -3
- package/dist/skills/runtime-activation.js.map +1 -1
- package/dist/skills/tool.d.ts.map +1 -1
- package/dist/skills/tool.js +26 -21
- package/dist/skills/tool.js.map +1 -1
- package/dist/skills/trust-cache.d.ts +7 -0
- package/dist/skills/trust-cache.d.ts.map +1 -1
- package/dist/skills/trust-cache.js +16 -0
- package/dist/skills/trust-cache.js.map +1 -1
- package/dist/telemetry/agent-workforce-native-event.d.ts.map +1 -1
- package/dist/telemetry/agent-workforce-native-event.js +1 -3
- package/dist/telemetry/agent-workforce-native-event.js.map +1 -1
- package/dist/telemetry/maestro-event-bus.d.ts.map +1 -1
- package/dist/telemetry/maestro-event-bus.js +42 -81
- package/dist/telemetry/maestro-event-bus.js.map +1 -1
- package/dist/telemetry/maestro-platform-replay-fixture.d.ts.map +1 -1
- package/dist/telemetry/maestro-platform-replay-fixture.js +1 -3
- package/dist/telemetry/maestro-platform-replay-fixture.js.map +1 -1
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +54 -43
- package/dist/telemetry.js.map +1 -1
- package/dist/theme/theme-loader.d.ts.map +1 -1
- package/dist/theme/theme-loader.js +1 -3
- package/dist/theme/theme-loader.js.map +1 -1
- package/dist/tools/apply-patch.d.ts.map +1 -1
- package/dist/tools/apply-patch.js +76 -8
- package/dist/tools/apply-patch.js.map +1 -1
- package/dist/tools/diff-preview.d.ts.map +1 -1
- package/dist/tools/diff-preview.js +10 -1
- package/dist/tools/diff-preview.js.map +1 -1
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +17 -0
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js +9 -0
- package/dist/tools/write.js.map +1 -1
- package/dist/undo/tracker.d.ts +5 -0
- package/dist/undo/tracker.d.ts.map +1 -1
- package/dist/undo/tracker.js +13 -0
- package/dist/undo/tracker.js.map +1 -1
- package/dist/utils/fs.d.ts +1 -1
- package/dist/utils/fs.d.ts.map +1 -1
- package/dist/utils/fs.js +29 -2
- package/dist/utils/fs.js.map +1 -1
- package/dist/utils/git-stash.d.ts.map +1 -1
- package/dist/utils/git-stash.js +15 -8
- package/dist/utils/git-stash.js.map +1 -1
- package/dist/utils/json.d.ts +11 -0
- package/dist/utils/json.d.ts.map +1 -1
- package/dist/utils/json.js +9 -0
- package/dist/utils/json.js.map +1 -1
- package/dist/utils/shell-env.d.ts.map +1 -1
- package/dist/utils/shell-env.js +2 -0
- package/dist/utils/shell-env.js.map +1 -1
- package/dist/utils/url-extractor-git.d.ts +26 -0
- package/dist/utils/url-extractor-git.d.ts.map +1 -0
- package/dist/utils/url-extractor-git.js +259 -0
- package/dist/utils/url-extractor-git.js.map +1 -0
- package/dist/utils/url-extractor.d.ts.map +1 -1
- package/dist/utils/url-extractor.js +23 -251
- package/dist/utils/url-extractor.js.map +1 -1
- package/dist/version.json +2 -2
- package/package.json +310 -306
- package/skills/incident-triage/SKILL.md +19 -1
- package/skills/install-code-review/SKILL.md +69 -0
- package/skills/security-review/SKILL.md +68 -0
- package/skills/security-review/reference/rubric.md +85 -0
package/dist/skills/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/skills/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAIN,SAAS,EACT,WAAW,EACX,uBAAuB,EACvB,mBAAmB,EACnB,uBAAuB,EACvB,2BAA2B,EAC3B,gBAAgB,EAChB,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,WAAW,EACX,cAAc,EACd,gBAAgB,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAGN,qBAAqB,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAClE,OAAO,EASN,2BAA2B,GAC3B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAIN,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,6BAA6B,EAC7B,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,gCAAgC,EAChC,2BAA2B,GAC3B,MAAM,aAAa,CAAC;AAErB,OAAO,EAMN,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,GACpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,uBAAuB,EACvB,6BAA6B,EAC7B,6BAA6B,EAK7B,gCAAgC,EAChC,+BAA+B,EAC/B,iCAAiC,GACjC,MAAM,uBAAuB,CAAC","sourcesContent":["/**\n * Skills System - Dynamic skill discovery and loading.\n *\n * Skills are domain-specific instruction sets that can be loaded\n * dynamically by the agent when it recognizes a matching task.\n *\n * ## Progressive Skill Disclosure (#857)\n *\n * Skills use a two-phase loading system for context efficiency:\n *\n * 1. **System Prompt**: Only inject metadata (name + description) using\n * `formatSkillsForSystemPrompt()` - ~10 tokens per skill\n * 2. **On-Demand**: Agent uses `read` tool to load full SKILL.md when needed\n * - ~500+ tokens per skill, only when relevant\n *\n * This scales to 20+ skills without degrading conversation quality.\n *\n * @example\n * ```typescript\n * import { loadSkills, formatSkillsForSystemPrompt } from \"./skills\";\n *\n * // Load all available skills\n * const { skills } = loadSkills(process.cwd());\n *\n * // Get lightweight metadata for system prompt (progressive disclosure)\n * const systemPromptSkills = formatSkillsForSystemPrompt(skills);\n *\n * // Or use legacy full-content approach (not recommended)\n * const summary = getSkillsSummary(skills);\n * ```\n */\n\nexport {\n\ttype LoadedSkill,\n\ttype SkillDefinition,\n\ttype SkillResource,\n\tfindSkill,\n\tfindSkillMd,\n\tformatSkillForInjection,\n\tformatSkillListItem,\n\tformatSkillMetadataOnly,\n\tformatSkillsForSystemPrompt,\n\tgetSkillsSummary,\n\tloadSkills,\n\tparseFrontmatter,\n\tsearchSkills,\n\tskillToDict,\n\tskillToJson,\n\tskillsToPrompt,\n\tstringArrayValue,\n} from \"./loader.js\";\n\nexport { composeSkill } from \"./composer.js\";\nexport {\n\ttype ScaffoldSkillOptions,\n\ttype ScaffoldSkillResult,\n\tscaffoldSkillWithBody,\n} from \"./scaffolder.js\";\nexport { createSkillTool, invalidateSkillCache } from \"./tool.js\";\nexport {\n\ttype SkillRuntimeActivation,\n\ttype SkillRuntimeActivationOptions,\n\ttype SkillRuntimeMcpActivation,\n\ttype SkillRuntimeMcpServer,\n\ttype SkillRuntimeResource,\n\ttype SkillRuntimeResourceDirectories,\n\ttype SkillRuntimeToolboxActivation,\n\ttype SkillRuntimeToolboxEntry,\n\tbuildSkillRuntimeActivation,\n} from \"./runtime-activation.js\";\nexport {\n\ttype SkillLintIssue,\n\ttype SkillLintResult,\n\ttype SkillScaffoldOptions,\n\tSKILL_BODY_MAX_CHARS,\n\tSKILL_BODY_MAX_LINES,\n\tformatSkillLintText,\n\thasSkillLintErrors,\n\tisWindowsRunnableToolboxEntry,\n\tlintSkillDirectory,\n\tlintSkillPaths,\n\tscaffoldSkill,\n\tshouldUseShellForToolboxDescribe,\n\ttoolboxDescribeSpawnCommand,\n} from \"./linter.js\";\n\nexport {\n\ttype SkillEvalAssertion,\n\ttype SkillEvalCase,\n\ttype SkillEvalOutcome,\n\ttype SkillEvalReport,\n\ttype SkillEvalResult,\n\tevaluateSkillPackages,\n\tformatSkillEvalText,\n\thasSkillEvalFailures,\n} from \"./eval-harness.js\";\nexport {\n\tMAESTRO_PACKAGE_KEYWORD,\n\tMAESTRO_SKILL_PACKAGE_KEYWORD,\n\tSKILL_PACKAGE_CONTRACT_SCHEMA,\n\ttype BuildSkillPackagePublishContractOptions,\n\ttype SkillPackageContractIssue,\n\ttype SkillPackageInstallCommandSet,\n\ttype SkillPackagePublishContract,\n\tbuildSkillPackagePublishContract,\n\tformatSkillPackageInstallSource,\n\tformatSkillPackagePublishContract,\n} from \"./package-contract.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/skills/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAIN,SAAS,EACT,WAAW,EACX,uBAAuB,EACvB,mBAAmB,EACnB,uBAAuB,EACvB,2BAA2B,EAC3B,gBAAgB,EAChB,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,WAAW,EACX,cAAc,EACd,gBAAgB,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EACN,sBAAsB,EACtB,oBAAoB,EACpB,gCAAgC,EAChC,wBAAwB,EACxB,qBAAqB,GACrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAGN,qBAAqB,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAClE,OAAO,EASN,2BAA2B,GAC3B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAIN,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,6BAA6B,EAC7B,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,gCAAgC,EAChC,2BAA2B,GAC3B,MAAM,aAAa,CAAC;AAErB,OAAO,EAMN,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,GACpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,uBAAuB,EACvB,6BAA6B,EAC7B,6BAA6B,EAK7B,gCAAgC,EAChC,+BAA+B,EAC/B,iCAAiC,GACjC,MAAM,uBAAuB,CAAC","sourcesContent":["/**\n * Skills System - Dynamic skill discovery and loading.\n *\n * Skills are domain-specific instruction sets that can be loaded\n * dynamically by the agent when it recognizes a matching task.\n *\n * ## Progressive Skill Disclosure (#857)\n *\n * Skills use a two-phase loading system for context efficiency:\n *\n * 1. **System Prompt**: Only inject metadata (name + description) using\n * `formatSkillsForSystemPrompt()` - ~10 tokens per skill\n * 2. **On-Demand**: Agent uses `read` tool to load full SKILL.md when needed\n * - ~500+ tokens per skill, only when relevant\n *\n * This scales to 20+ skills without degrading conversation quality.\n *\n * @example\n * ```typescript\n * import { loadSkills, formatSkillsForSystemPrompt } from \"./skills\";\n *\n * // Load all available skills\n * const { skills } = loadSkills(process.cwd());\n *\n * // Get lightweight metadata for system prompt (progressive disclosure)\n * const systemPromptSkills = formatSkillsForSystemPrompt(skills);\n *\n * // Or use legacy full-content approach (not recommended)\n * const summary = getSkillsSummary(skills);\n * ```\n */\n\nexport {\n\ttype LoadedSkill,\n\ttype SkillDefinition,\n\ttype SkillResource,\n\tfindSkill,\n\tfindSkillMd,\n\tformatSkillForInjection,\n\tformatSkillListItem,\n\tformatSkillMetadataOnly,\n\tformatSkillsForSystemPrompt,\n\tgetSkillsSummary,\n\tloadSkills,\n\tparseFrontmatter,\n\tsearchSkills,\n\tskillToDict,\n\tskillToJson,\n\tskillsToPrompt,\n\tstringArrayValue,\n} from \"./loader.js\";\n\nexport { composeSkill } from \"./composer.js\";\nexport {\n\tappendLearnedGuideline,\n\tdefaultUserSkillsDir,\n\tformatLearnedGuidelinesForPrompt,\n\tgetLearnedGuidelinesPath,\n\tloadLearnedGuidelines,\n} from \"./learned-guidelines.js\";\nexport {\n\ttype ScaffoldSkillOptions,\n\ttype ScaffoldSkillResult,\n\tscaffoldSkillWithBody,\n} from \"./scaffolder.js\";\nexport { createSkillTool, invalidateSkillCache } from \"./tool.js\";\nexport {\n\ttype SkillRuntimeActivation,\n\ttype SkillRuntimeActivationOptions,\n\ttype SkillRuntimeMcpActivation,\n\ttype SkillRuntimeMcpServer,\n\ttype SkillRuntimeResource,\n\ttype SkillRuntimeResourceDirectories,\n\ttype SkillRuntimeToolboxActivation,\n\ttype SkillRuntimeToolboxEntry,\n\tbuildSkillRuntimeActivation,\n} from \"./runtime-activation.js\";\nexport {\n\ttype SkillLintIssue,\n\ttype SkillLintResult,\n\ttype SkillScaffoldOptions,\n\tSKILL_BODY_MAX_CHARS,\n\tSKILL_BODY_MAX_LINES,\n\tformatSkillLintText,\n\thasSkillLintErrors,\n\tisWindowsRunnableToolboxEntry,\n\tlintSkillDirectory,\n\tlintSkillPaths,\n\tscaffoldSkill,\n\tshouldUseShellForToolboxDescribe,\n\ttoolboxDescribeSpawnCommand,\n} from \"./linter.js\";\n\nexport {\n\ttype SkillEvalAssertion,\n\ttype SkillEvalCase,\n\ttype SkillEvalOutcome,\n\ttype SkillEvalReport,\n\ttype SkillEvalResult,\n\tevaluateSkillPackages,\n\tformatSkillEvalText,\n\thasSkillEvalFailures,\n} from \"./eval-harness.js\";\nexport {\n\tMAESTRO_PACKAGE_KEYWORD,\n\tMAESTRO_SKILL_PACKAGE_KEYWORD,\n\tSKILL_PACKAGE_CONTRACT_SCHEMA,\n\ttype BuildSkillPackagePublishContractOptions,\n\ttype SkillPackageContractIssue,\n\ttype SkillPackageInstallCommandSet,\n\ttype SkillPackagePublishContract,\n\tbuildSkillPackagePublishContract,\n\tformatSkillPackageInstallSource,\n\tformatSkillPackagePublishContract,\n} from \"./package-contract.js\";\n"]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Learned guidelines for skills
|
|
3
|
+
*
|
|
4
|
+
* A skill can accumulate durable, plain-text guidance across runs — for
|
|
5
|
+
* example, incident-triage learning which tools and interfaces a given alert
|
|
6
|
+
* type needs. Learnings are stored as markdown at
|
|
7
|
+
* `<userSkillsDir>/<skill>/guidelines.md` (default `~/.maestro/skills`), so a
|
|
8
|
+
* later run of the same skill can load what earlier runs discovered.
|
|
9
|
+
*
|
|
10
|
+
* The file is markdown, not settings, and every function takes the skills root
|
|
11
|
+
* as a parameter (defaulting to the sanctioned PATHS.MAESTRO_HOME), so this
|
|
12
|
+
* module reads no environment directly and writes atomically.
|
|
13
|
+
*/
|
|
14
|
+
/** Default per-user skills root (`~/.maestro/skills`). */
|
|
15
|
+
export declare function defaultUserSkillsDir(): string;
|
|
16
|
+
/** Absolute path to a skill's learned-guidelines file. */
|
|
17
|
+
export declare function getLearnedGuidelinesPath(skillName: string, userSkillsDir?: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Load a skill's learned guidelines, or null when none have been recorded.
|
|
20
|
+
*/
|
|
21
|
+
export declare function loadLearnedGuidelines(skillName: string, userSkillsDir?: string): string | null;
|
|
22
|
+
/**
|
|
23
|
+
* Render a skill's learned guidelines as a prompt-ready block, or null when
|
|
24
|
+
* there are none. Suitable for injection alongside the skill's own content.
|
|
25
|
+
*/
|
|
26
|
+
export declare function formatLearnedGuidelinesForPrompt(skillName: string, userSkillsDir?: string): string | null;
|
|
27
|
+
/**
|
|
28
|
+
* Append a learned-guideline entry to a skill's guidelines file, creating it on
|
|
29
|
+
* first use. Entries are separated by a horizontal rule so the file stays a
|
|
30
|
+
* readable, append-only log.
|
|
31
|
+
*/
|
|
32
|
+
export declare function appendLearnedGuideline(skillName: string, entry: string, userSkillsDir?: string): string;
|
|
33
|
+
//# sourceMappingURL=learned-guidelines.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"learned-guidelines.d.ts","sourceRoot":"","sources":["../../src/skills/learned-guidelines.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAgCH,0DAA0D;AAC1D,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AASD,0DAA0D;AAC1D,wBAAgB,wBAAwB,CACvC,SAAS,EAAE,MAAM,EACjB,aAAa,GAAE,MAA+B,GAC5C,MAAM,CAKR;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACpC,SAAS,EAAE,MAAM,EACjB,aAAa,GAAE,MAA+B,GAC5C,MAAM,GAAG,IAAI,CAKf;AAED;;;GAGG;AACH,wBAAgB,gCAAgC,CAC/C,SAAS,EAAE,MAAM,EACjB,aAAa,GAAE,MAA+B,GAC5C,MAAM,GAAG,IAAI,CAaf;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACrC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,aAAa,GAAE,MAA+B,GAC5C,MAAM,CAcR"}
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Learned guidelines for skills
|
|
3
|
+
*
|
|
4
|
+
* A skill can accumulate durable, plain-text guidance across runs — for
|
|
5
|
+
* example, incident-triage learning which tools and interfaces a given alert
|
|
6
|
+
* type needs. Learnings are stored as markdown at
|
|
7
|
+
* `<userSkillsDir>/<skill>/guidelines.md` (default `~/.maestro/skills`), so a
|
|
8
|
+
* later run of the same skill can load what earlier runs discovered.
|
|
9
|
+
*
|
|
10
|
+
* The file is markdown, not settings, and every function takes the skills root
|
|
11
|
+
* as a parameter (defaulting to the sanctioned PATHS.MAESTRO_HOME), so this
|
|
12
|
+
* module reads no environment directly and writes atomically.
|
|
13
|
+
*/
|
|
14
|
+
import { randomUUID } from "node:crypto";
|
|
15
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, statSync } from "node:fs";
|
|
16
|
+
import { dirname, join, resolve, sep } from "node:path";
|
|
17
|
+
import { PATHS } from "../config/constants.js";
|
|
18
|
+
import { isProcessAlive } from "../tools/process-tree.js";
|
|
19
|
+
import { writeTextFileAtomic } from "../utils/fs.js";
|
|
20
|
+
const GUIDELINES_FILENAME = "guidelines.md";
|
|
21
|
+
const SKILL_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
22
|
+
const GUIDELINES_LOCK_RETRY_MS = 25;
|
|
23
|
+
const GUIDELINES_LOCK_STALE_MS = 30_000;
|
|
24
|
+
const GUIDELINES_LOCK_TIMEOUT_MS = GUIDELINES_LOCK_STALE_MS + GUIDELINES_LOCK_RETRY_MS;
|
|
25
|
+
const GUIDELINES_LOCK_OWNER_FILE = "owner.json";
|
|
26
|
+
const MAX_GUIDELINES_BYTES = 64 * 1024;
|
|
27
|
+
const GUIDELINE_ENTRY_SEPARATOR = "\n\n---\n\n";
|
|
28
|
+
const GUIDELINE_ENTRY_MARKER = "<!-- maestro-learned-guideline-entry -->";
|
|
29
|
+
const GUIDELINE_ENTRY_JSON_MARKER = "<!-- maestro-learned-guideline-entry-json -->";
|
|
30
|
+
const GUIDELINE_TRUNCATION_NOTICE = "\n\n[learned guideline truncated to fit byte cap]";
|
|
31
|
+
const SLEEP_BUFFER = new SharedArrayBuffer(4);
|
|
32
|
+
const SLEEP_VIEW = new Int32Array(SLEEP_BUFFER);
|
|
33
|
+
/** Default per-user skills root (`~/.maestro/skills`). */
|
|
34
|
+
export function defaultUserSkillsDir() {
|
|
35
|
+
return join(PATHS.MAESTRO_HOME, "skills");
|
|
36
|
+
}
|
|
37
|
+
function validateSkillName(skillName) {
|
|
38
|
+
if (!SKILL_NAME_PATTERN.test(skillName)) {
|
|
39
|
+
throw new Error(`Invalid skill name for learned guidelines: ${skillName}`);
|
|
40
|
+
}
|
|
41
|
+
return skillName;
|
|
42
|
+
}
|
|
43
|
+
/** Absolute path to a skill's learned-guidelines file. */
|
|
44
|
+
export function getLearnedGuidelinesPath(skillName, userSkillsDir = defaultUserSkillsDir()) {
|
|
45
|
+
return join(resolveSkillDirectory(skillName, userSkillsDir), GUIDELINES_FILENAME);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Load a skill's learned guidelines, or null when none have been recorded.
|
|
49
|
+
*/
|
|
50
|
+
export function loadLearnedGuidelines(skillName, userSkillsDir = defaultUserSkillsDir()) {
|
|
51
|
+
const content = formatGuidelineEntries(loadDisplayGuidelineEntries(skillName, userSkillsDir, MAX_GUIDELINES_BYTES));
|
|
52
|
+
return content.length > 0 ? content : null;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Render a skill's learned guidelines as a prompt-ready block, or null when
|
|
56
|
+
* there are none. Suitable for injection alongside the skill's own content.
|
|
57
|
+
*/
|
|
58
|
+
export function formatLearnedGuidelinesForPrompt(skillName, userSkillsDir = defaultUserSkillsDir()) {
|
|
59
|
+
const promptPrefix = learnedGuidelinesPromptPrefix(skillName);
|
|
60
|
+
const content = formatGuidelineEntries(loadDisplayGuidelineEntries(skillName, userSkillsDir, MAX_GUIDELINES_BYTES - byteLength(promptPrefix)));
|
|
61
|
+
if (!content) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
return `${promptPrefix}${content}`;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Append a learned-guideline entry to a skill's guidelines file, creating it on
|
|
68
|
+
* first use. Entries are separated by a horizontal rule so the file stays a
|
|
69
|
+
* readable, append-only log.
|
|
70
|
+
*/
|
|
71
|
+
export function appendLearnedGuideline(skillName, entry, userSkillsDir = defaultUserSkillsDir()) {
|
|
72
|
+
const trimmed = entry.trim();
|
|
73
|
+
if (trimmed.length === 0) {
|
|
74
|
+
throw new Error("appendLearnedGuideline requires a non-empty entry");
|
|
75
|
+
}
|
|
76
|
+
const path = getLearnedGuidelinesPath(skillName, userSkillsDir);
|
|
77
|
+
return withLearnedGuidelinesLock(path, () => {
|
|
78
|
+
const existing = existsSync(path) ? readFileSync(path, "utf-8").trim() : "";
|
|
79
|
+
const next = buildGuidelinesContent(existing, trimmed);
|
|
80
|
+
if (next !== null) {
|
|
81
|
+
writeTextFileAtomic(path, next, { createDirs: true });
|
|
82
|
+
}
|
|
83
|
+
return path;
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
function buildGuidelinesContent(existing, entry) {
|
|
87
|
+
const entries = parseGuidelineEntries(existing);
|
|
88
|
+
if (byteLength(serializeGuidelineEntries([entry])) > MAX_GUIDELINES_BYTES) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
entries.push(entry);
|
|
92
|
+
return formatGuidelinesContent(pruneGuidelineEntries(entries));
|
|
93
|
+
}
|
|
94
|
+
function loadDisplayGuidelineEntries(skillName, userSkillsDir, maxBytes) {
|
|
95
|
+
const path = getLearnedGuidelinesPath(skillName, userSkillsDir);
|
|
96
|
+
if (!existsSync(path)) {
|
|
97
|
+
return [];
|
|
98
|
+
}
|
|
99
|
+
return fitGuidelineEntriesForDisplay(parseGuidelineEntries(readFileSync(path, "utf-8")), maxBytes);
|
|
100
|
+
}
|
|
101
|
+
function pruneGuidelineEntries(entries) {
|
|
102
|
+
while (entries.length > 0 &&
|
|
103
|
+
byteLength(serializeGuidelineEntries(entries)) > MAX_GUIDELINES_BYTES) {
|
|
104
|
+
entries.shift();
|
|
105
|
+
}
|
|
106
|
+
return entries;
|
|
107
|
+
}
|
|
108
|
+
function formatGuidelinesContent(entries) {
|
|
109
|
+
const content = serializeGuidelineEntries(entries);
|
|
110
|
+
return content.length > 0 ? `${content}\n` : "";
|
|
111
|
+
}
|
|
112
|
+
function formatGuidelineEntries(entries) {
|
|
113
|
+
return normalizeGuidelineEntries(entries).join(GUIDELINE_ENTRY_SEPARATOR);
|
|
114
|
+
}
|
|
115
|
+
function parseGuidelineEntries(content) {
|
|
116
|
+
const trimmed = content
|
|
117
|
+
.replace(/^\uFEFF/, "")
|
|
118
|
+
.replace(/\r\n?/g, "\n")
|
|
119
|
+
.trim();
|
|
120
|
+
if (trimmed.length === 0) {
|
|
121
|
+
return [];
|
|
122
|
+
}
|
|
123
|
+
if (trimmed.startsWith(GUIDELINE_ENTRY_JSON_MARKER)) {
|
|
124
|
+
return parseJsonGuidelineEntries(trimmed);
|
|
125
|
+
}
|
|
126
|
+
if (!trimmed.startsWith(GUIDELINE_ENTRY_MARKER)) {
|
|
127
|
+
return normalizeGuidelineEntries(trimmed.split(GUIDELINE_ENTRY_SEPARATOR));
|
|
128
|
+
}
|
|
129
|
+
const markerLine = `${GUIDELINE_ENTRY_MARKER}\n`;
|
|
130
|
+
return normalizeGuidelineEntries(trimmed
|
|
131
|
+
.slice(markerLine.length)
|
|
132
|
+
.split(`${GUIDELINE_ENTRY_SEPARATOR}${markerLine}`));
|
|
133
|
+
}
|
|
134
|
+
function parseJsonGuidelineEntries(content) {
|
|
135
|
+
const markerLine = `${GUIDELINE_ENTRY_JSON_MARKER}\n`;
|
|
136
|
+
return normalizeGuidelineEntries(content
|
|
137
|
+
.slice(markerLine.length)
|
|
138
|
+
.split(`${GUIDELINE_ENTRY_SEPARATOR}${markerLine}`)
|
|
139
|
+
.map((entry) => {
|
|
140
|
+
try {
|
|
141
|
+
const parsed = JSON.parse(entry);
|
|
142
|
+
return typeof parsed === "string" ? parsed : "";
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return "";
|
|
146
|
+
}
|
|
147
|
+
}));
|
|
148
|
+
}
|
|
149
|
+
function serializeGuidelineEntries(entries) {
|
|
150
|
+
return normalizeGuidelineEntries(entries)
|
|
151
|
+
.map((entry) => `${GUIDELINE_ENTRY_JSON_MARKER}\n${JSON.stringify(entry)}`)
|
|
152
|
+
.join(GUIDELINE_ENTRY_SEPARATOR);
|
|
153
|
+
}
|
|
154
|
+
function normalizeGuidelineEntries(entries) {
|
|
155
|
+
return entries.map((entry) => entry.trim()).filter(Boolean);
|
|
156
|
+
}
|
|
157
|
+
function fitGuidelineEntriesForDisplay(entries, maxBytes) {
|
|
158
|
+
const fitted = normalizeGuidelineEntries(entries);
|
|
159
|
+
while (fitted.length > 0 &&
|
|
160
|
+
byteLength(formatGuidelineEntries(fitted)) > maxBytes) {
|
|
161
|
+
if (fitted.length === 1) {
|
|
162
|
+
const truncated = truncateEntryToBytes(fitted[0] ?? "", maxBytes);
|
|
163
|
+
return truncated ? [truncated] : [];
|
|
164
|
+
}
|
|
165
|
+
fitted.shift();
|
|
166
|
+
}
|
|
167
|
+
return fitted;
|
|
168
|
+
}
|
|
169
|
+
function truncateEntryToBytes(entry, maxBytes) {
|
|
170
|
+
if (maxBytes <= byteLength(GUIDELINE_TRUNCATION_NOTICE)) {
|
|
171
|
+
return "";
|
|
172
|
+
}
|
|
173
|
+
let truncated = "";
|
|
174
|
+
for (const char of Array.from(entry)) {
|
|
175
|
+
const next = `${truncated}${char}`;
|
|
176
|
+
if (byteLength(`${next}${GUIDELINE_TRUNCATION_NOTICE}`) > maxBytes) {
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
truncated = next;
|
|
180
|
+
}
|
|
181
|
+
return `${truncated}${GUIDELINE_TRUNCATION_NOTICE}`.trim();
|
|
182
|
+
}
|
|
183
|
+
function byteLength(value) {
|
|
184
|
+
return Buffer.byteLength(value, "utf-8");
|
|
185
|
+
}
|
|
186
|
+
function learnedGuidelinesPromptPrefix(skillName) {
|
|
187
|
+
return `# Learned guidelines (${skillName})\n\nAccumulated from earlier runs of this skill. Treat as priors to verify, not as ground truth.\n\n`;
|
|
188
|
+
}
|
|
189
|
+
function resolveSkillDirectory(skillName, userSkillsDir) {
|
|
190
|
+
const validatedSkillName = validateSkillName(skillName);
|
|
191
|
+
const skillDirectory = resolve(userSkillsDir, validatedSkillName);
|
|
192
|
+
if (!isPathWithinDirectory(skillDirectory, userSkillsDir)) {
|
|
193
|
+
throw new Error(`Invalid skill name for learned guidelines: ${skillName}`);
|
|
194
|
+
}
|
|
195
|
+
return skillDirectory;
|
|
196
|
+
}
|
|
197
|
+
function isPathWithinDirectory(candidatePath, directoryPath) {
|
|
198
|
+
const normalizedDir = `${resolve(directoryPath)}${sep}`;
|
|
199
|
+
const normalizedCandidate = resolve(candidatePath);
|
|
200
|
+
return normalizedCandidate.startsWith(normalizedDir);
|
|
201
|
+
}
|
|
202
|
+
function withLearnedGuidelinesLock(path, operation) {
|
|
203
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
204
|
+
const lockPath = `${path}.lock`;
|
|
205
|
+
const ownerToken = randomUUID();
|
|
206
|
+
const startedAt = Date.now();
|
|
207
|
+
while (true) {
|
|
208
|
+
try {
|
|
209
|
+
mkdirSync(lockPath);
|
|
210
|
+
writeGuidelinesLockOwner(lockPath, ownerToken);
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
const code = error.code;
|
|
215
|
+
if (code !== "EEXIST")
|
|
216
|
+
throw error;
|
|
217
|
+
if (recoverStaleGuidelinesLock(lockPath))
|
|
218
|
+
continue;
|
|
219
|
+
if (Date.now() - startedAt > GUIDELINES_LOCK_TIMEOUT_MS) {
|
|
220
|
+
throw new Error(`timed out waiting for learned guidelines lock: ${path}`);
|
|
221
|
+
}
|
|
222
|
+
sleepSync(GUIDELINES_LOCK_RETRY_MS);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
try {
|
|
226
|
+
return operation();
|
|
227
|
+
}
|
|
228
|
+
finally {
|
|
229
|
+
releaseGuidelinesLock(lockPath, ownerToken);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
function writeGuidelinesLockOwner(lockPath, ownerToken) {
|
|
233
|
+
const owner = {
|
|
234
|
+
pid: process.pid,
|
|
235
|
+
token: ownerToken,
|
|
236
|
+
createdAt: new Date().toISOString(),
|
|
237
|
+
};
|
|
238
|
+
try {
|
|
239
|
+
writeTextFileAtomic(join(lockPath, GUIDELINES_LOCK_OWNER_FILE), `${JSON.stringify(owner)}\n`, { createDirs: true });
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
rmSync(lockPath, { recursive: true, force: true });
|
|
243
|
+
throw error;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
function releaseGuidelinesLock(lockPath, ownerToken) {
|
|
247
|
+
const owner = readGuidelinesLockOwner(lockPath);
|
|
248
|
+
if (owner?.token === ownerToken) {
|
|
249
|
+
rmSync(lockPath, { recursive: true, force: true });
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
function recoverStaleGuidelinesLock(lockPath) {
|
|
253
|
+
try {
|
|
254
|
+
const stats = statSync(lockPath);
|
|
255
|
+
if (Date.now() - stats.mtimeMs <= GUIDELINES_LOCK_STALE_MS) {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
const owner = readGuidelinesLockOwner(lockPath);
|
|
259
|
+
if (typeof owner?.pid === "number" && isProcessAlive(owner.pid)) {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
rmSync(lockPath, { recursive: true, force: true });
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
catch {
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
function readGuidelinesLockOwner(lockPath) {
|
|
270
|
+
try {
|
|
271
|
+
const raw = readFileSync(join(lockPath, GUIDELINES_LOCK_OWNER_FILE), "utf-8");
|
|
272
|
+
const parsed = JSON.parse(raw);
|
|
273
|
+
if (typeof parsed.pid === "number" &&
|
|
274
|
+
typeof parsed.token === "string" &&
|
|
275
|
+
typeof parsed.createdAt === "string") {
|
|
276
|
+
return {
|
|
277
|
+
pid: parsed.pid,
|
|
278
|
+
token: parsed.token,
|
|
279
|
+
createdAt: parsed.createdAt,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
// Missing or malformed ownership metadata is treated as unowned.
|
|
285
|
+
}
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
function sleepSync(ms) {
|
|
289
|
+
Atomics.wait(SLEEP_VIEW, 0, 0, ms);
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=learned-guidelines.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"learned-guidelines.js","sourceRoot":"","sources":["../../src/skills/learned-guidelines.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Learned guidelines for skills\n *\n * A skill can accumulate durable, plain-text guidance across runs — for\n * example, incident-triage learning which tools and interfaces a given alert\n * type needs. Learnings are stored as markdown at\n * `<userSkillsDir>/<skill>/guidelines.md` (default `~/.maestro/skills`), so a\n * later run of the same skill can load what earlier runs discovered.\n *\n * The file is markdown, not settings, and every function takes the skills root\n * as a parameter (defaulting to the sanctioned PATHS.MAESTRO_HOME), so this\n * module reads no environment directly and writes atomically.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, rmSync, statSync } from \"node:fs\";\nimport { dirname, join, resolve, sep } from \"node:path\";\nimport { PATHS } from \"../config/constants.js\";\nimport { isProcessAlive } from \"../tools/process-tree.js\";\nimport { writeTextFileAtomic } from \"../utils/fs.js\";\n\nconst GUIDELINES_FILENAME = \"guidelines.md\";\nconst SKILL_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;\nconst GUIDELINES_LOCK_RETRY_MS = 25;\nconst GUIDELINES_LOCK_STALE_MS = 30_000;\nconst GUIDELINES_LOCK_TIMEOUT_MS =\n\tGUIDELINES_LOCK_STALE_MS + GUIDELINES_LOCK_RETRY_MS;\nconst GUIDELINES_LOCK_OWNER_FILE = \"owner.json\";\nconst MAX_GUIDELINES_BYTES = 64 * 1024;\nconst GUIDELINE_ENTRY_SEPARATOR = \"\\n\\n---\\n\\n\";\nconst GUIDELINE_ENTRY_MARKER = \"<!-- maestro-learned-guideline-entry -->\";\nconst GUIDELINE_ENTRY_JSON_MARKER =\n\t\"<!-- maestro-learned-guideline-entry-json -->\";\nconst GUIDELINE_TRUNCATION_NOTICE =\n\t\"\\n\\n[learned guideline truncated to fit byte cap]\";\nconst SLEEP_BUFFER = new SharedArrayBuffer(4);\nconst SLEEP_VIEW = new Int32Array(SLEEP_BUFFER);\n\ninterface GuidelinesLockOwner {\n\tpid: number;\n\ttoken: string;\n\tcreatedAt: string;\n}\n\n/** Default per-user skills root (`~/.maestro/skills`). */\nexport function defaultUserSkillsDir(): string {\n\treturn join(PATHS.MAESTRO_HOME, \"skills\");\n}\n\nfunction validateSkillName(skillName: string): string {\n\tif (!SKILL_NAME_PATTERN.test(skillName)) {\n\t\tthrow new Error(`Invalid skill name for learned guidelines: ${skillName}`);\n\t}\n\treturn skillName;\n}\n\n/** Absolute path to a skill's learned-guidelines file. */\nexport function getLearnedGuidelinesPath(\n\tskillName: string,\n\tuserSkillsDir: string = defaultUserSkillsDir(),\n): string {\n\treturn join(\n\t\tresolveSkillDirectory(skillName, userSkillsDir),\n\t\tGUIDELINES_FILENAME,\n\t);\n}\n\n/**\n * Load a skill's learned guidelines, or null when none have been recorded.\n */\nexport function loadLearnedGuidelines(\n\tskillName: string,\n\tuserSkillsDir: string = defaultUserSkillsDir(),\n): string | null {\n\tconst content = formatGuidelineEntries(\n\t\tloadDisplayGuidelineEntries(skillName, userSkillsDir, MAX_GUIDELINES_BYTES),\n\t);\n\treturn content.length > 0 ? content : null;\n}\n\n/**\n * Render a skill's learned guidelines as a prompt-ready block, or null when\n * there are none. Suitable for injection alongside the skill's own content.\n */\nexport function formatLearnedGuidelinesForPrompt(\n\tskillName: string,\n\tuserSkillsDir: string = defaultUserSkillsDir(),\n): string | null {\n\tconst promptPrefix = learnedGuidelinesPromptPrefix(skillName);\n\tconst content = formatGuidelineEntries(\n\t\tloadDisplayGuidelineEntries(\n\t\t\tskillName,\n\t\t\tuserSkillsDir,\n\t\t\tMAX_GUIDELINES_BYTES - byteLength(promptPrefix),\n\t\t),\n\t);\n\tif (!content) {\n\t\treturn null;\n\t}\n\treturn `${promptPrefix}${content}`;\n}\n\n/**\n * Append a learned-guideline entry to a skill's guidelines file, creating it on\n * first use. Entries are separated by a horizontal rule so the file stays a\n * readable, append-only log.\n */\nexport function appendLearnedGuideline(\n\tskillName: string,\n\tentry: string,\n\tuserSkillsDir: string = defaultUserSkillsDir(),\n): string {\n\tconst trimmed = entry.trim();\n\tif (trimmed.length === 0) {\n\t\tthrow new Error(\"appendLearnedGuideline requires a non-empty entry\");\n\t}\n\tconst path = getLearnedGuidelinesPath(skillName, userSkillsDir);\n\treturn withLearnedGuidelinesLock(path, () => {\n\t\tconst existing = existsSync(path) ? readFileSync(path, \"utf-8\").trim() : \"\";\n\t\tconst next = buildGuidelinesContent(existing, trimmed);\n\t\tif (next !== null) {\n\t\t\twriteTextFileAtomic(path, next, { createDirs: true });\n\t\t}\n\t\treturn path;\n\t});\n}\n\nfunction buildGuidelinesContent(\n\texisting: string,\n\tentry: string,\n): string | null {\n\tconst entries = parseGuidelineEntries(existing);\n\tif (byteLength(serializeGuidelineEntries([entry])) > MAX_GUIDELINES_BYTES) {\n\t\treturn null;\n\t}\n\tentries.push(entry);\n\treturn formatGuidelinesContent(pruneGuidelineEntries(entries));\n}\n\nfunction loadDisplayGuidelineEntries(\n\tskillName: string,\n\tuserSkillsDir: string,\n\tmaxBytes: number,\n): string[] {\n\tconst path = getLearnedGuidelinesPath(skillName, userSkillsDir);\n\tif (!existsSync(path)) {\n\t\treturn [];\n\t}\n\treturn fitGuidelineEntriesForDisplay(\n\t\tparseGuidelineEntries(readFileSync(path, \"utf-8\")),\n\t\tmaxBytes,\n\t);\n}\n\nfunction pruneGuidelineEntries(entries: string[]): string[] {\n\twhile (\n\t\tentries.length > 0 &&\n\t\tbyteLength(serializeGuidelineEntries(entries)) > MAX_GUIDELINES_BYTES\n\t) {\n\t\tentries.shift();\n\t}\n\treturn entries;\n}\n\nfunction formatGuidelinesContent(entries: string[]): string {\n\tconst content = serializeGuidelineEntries(entries);\n\treturn content.length > 0 ? `${content}\\n` : \"\";\n}\n\nfunction formatGuidelineEntries(entries: string[]): string {\n\treturn normalizeGuidelineEntries(entries).join(GUIDELINE_ENTRY_SEPARATOR);\n}\n\nfunction parseGuidelineEntries(content: string): string[] {\n\tconst trimmed = content\n\t\t.replace(/^\\uFEFF/, \"\")\n\t\t.replace(/\\r\\n?/g, \"\\n\")\n\t\t.trim();\n\tif (trimmed.length === 0) {\n\t\treturn [];\n\t}\n\tif (trimmed.startsWith(GUIDELINE_ENTRY_JSON_MARKER)) {\n\t\treturn parseJsonGuidelineEntries(trimmed);\n\t}\n\tif (!trimmed.startsWith(GUIDELINE_ENTRY_MARKER)) {\n\t\treturn normalizeGuidelineEntries(trimmed.split(GUIDELINE_ENTRY_SEPARATOR));\n\t}\n\tconst markerLine = `${GUIDELINE_ENTRY_MARKER}\\n`;\n\treturn normalizeGuidelineEntries(\n\t\ttrimmed\n\t\t\t.slice(markerLine.length)\n\t\t\t.split(`${GUIDELINE_ENTRY_SEPARATOR}${markerLine}`),\n\t);\n}\n\nfunction parseJsonGuidelineEntries(content: string): string[] {\n\tconst markerLine = `${GUIDELINE_ENTRY_JSON_MARKER}\\n`;\n\treturn normalizeGuidelineEntries(\n\t\tcontent\n\t\t\t.slice(markerLine.length)\n\t\t\t.split(`${GUIDELINE_ENTRY_SEPARATOR}${markerLine}`)\n\t\t\t.map((entry) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst parsed = JSON.parse(entry) as unknown;\n\t\t\t\t\treturn typeof parsed === \"string\" ? parsed : \"\";\n\t\t\t\t} catch {\n\t\t\t\t\treturn \"\";\n\t\t\t\t}\n\t\t\t}),\n\t);\n}\n\nfunction serializeGuidelineEntries(entries: string[]): string {\n\treturn normalizeGuidelineEntries(entries)\n\t\t.map((entry) => `${GUIDELINE_ENTRY_JSON_MARKER}\\n${JSON.stringify(entry)}`)\n\t\t.join(GUIDELINE_ENTRY_SEPARATOR);\n}\n\nfunction normalizeGuidelineEntries(entries: string[]): string[] {\n\treturn entries.map((entry) => entry.trim()).filter(Boolean);\n}\n\nfunction fitGuidelineEntriesForDisplay(\n\tentries: string[],\n\tmaxBytes: number,\n): string[] {\n\tconst fitted = normalizeGuidelineEntries(entries);\n\twhile (\n\t\tfitted.length > 0 &&\n\t\tbyteLength(formatGuidelineEntries(fitted)) > maxBytes\n\t) {\n\t\tif (fitted.length === 1) {\n\t\t\tconst truncated = truncateEntryToBytes(fitted[0] ?? \"\", maxBytes);\n\t\t\treturn truncated ? [truncated] : [];\n\t\t}\n\t\tfitted.shift();\n\t}\n\treturn fitted;\n}\n\nfunction truncateEntryToBytes(entry: string, maxBytes: number): string {\n\tif (maxBytes <= byteLength(GUIDELINE_TRUNCATION_NOTICE)) {\n\t\treturn \"\";\n\t}\n\tlet truncated = \"\";\n\tfor (const char of Array.from(entry)) {\n\t\tconst next = `${truncated}${char}`;\n\t\tif (byteLength(`${next}${GUIDELINE_TRUNCATION_NOTICE}`) > maxBytes) {\n\t\t\tbreak;\n\t\t}\n\t\ttruncated = next;\n\t}\n\treturn `${truncated}${GUIDELINE_TRUNCATION_NOTICE}`.trim();\n}\n\nfunction byteLength(value: string): number {\n\treturn Buffer.byteLength(value, \"utf-8\");\n}\n\nfunction learnedGuidelinesPromptPrefix(skillName: string): string {\n\treturn `# Learned guidelines (${skillName})\\n\\nAccumulated from earlier runs of this skill. Treat as priors to verify, not as ground truth.\\n\\n`;\n}\n\nfunction resolveSkillDirectory(\n\tskillName: string,\n\tuserSkillsDir: string,\n): string {\n\tconst validatedSkillName = validateSkillName(skillName);\n\tconst skillDirectory = resolve(userSkillsDir, validatedSkillName);\n\tif (!isPathWithinDirectory(skillDirectory, userSkillsDir)) {\n\t\tthrow new Error(`Invalid skill name for learned guidelines: ${skillName}`);\n\t}\n\treturn skillDirectory;\n}\n\nfunction isPathWithinDirectory(\n\tcandidatePath: string,\n\tdirectoryPath: string,\n): boolean {\n\tconst normalizedDir = `${resolve(directoryPath)}${sep}`;\n\tconst normalizedCandidate = resolve(candidatePath);\n\treturn normalizedCandidate.startsWith(normalizedDir);\n}\n\nfunction withLearnedGuidelinesLock<T>(path: string, operation: () => T): T {\n\tmkdirSync(dirname(path), { recursive: true });\n\tconst lockPath = `${path}.lock`;\n\tconst ownerToken = randomUUID();\n\tconst startedAt = Date.now();\n\twhile (true) {\n\t\ttry {\n\t\t\tmkdirSync(lockPath);\n\t\t\twriteGuidelinesLockOwner(lockPath, ownerToken);\n\t\t\tbreak;\n\t\t} catch (error) {\n\t\t\tconst code = (error as NodeJS.ErrnoException).code;\n\t\t\tif (code !== \"EEXIST\") throw error;\n\t\t\tif (recoverStaleGuidelinesLock(lockPath)) continue;\n\t\t\tif (Date.now() - startedAt > GUIDELINES_LOCK_TIMEOUT_MS) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`timed out waiting for learned guidelines lock: ${path}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tsleepSync(GUIDELINES_LOCK_RETRY_MS);\n\t\t}\n\t}\n\ttry {\n\t\treturn operation();\n\t} finally {\n\t\treleaseGuidelinesLock(lockPath, ownerToken);\n\t}\n}\n\nfunction writeGuidelinesLockOwner(lockPath: string, ownerToken: string): void {\n\tconst owner: GuidelinesLockOwner = {\n\t\tpid: process.pid,\n\t\ttoken: ownerToken,\n\t\tcreatedAt: new Date().toISOString(),\n\t};\n\ttry {\n\t\twriteTextFileAtomic(\n\t\t\tjoin(lockPath, GUIDELINES_LOCK_OWNER_FILE),\n\t\t\t`${JSON.stringify(owner)}\\n`,\n\t\t\t{ createDirs: true },\n\t\t);\n\t} catch (error) {\n\t\trmSync(lockPath, { recursive: true, force: true });\n\t\tthrow error;\n\t}\n}\n\nfunction releaseGuidelinesLock(lockPath: string, ownerToken: string): void {\n\tconst owner = readGuidelinesLockOwner(lockPath);\n\tif (owner?.token === ownerToken) {\n\t\trmSync(lockPath, { recursive: true, force: true });\n\t}\n}\n\nfunction recoverStaleGuidelinesLock(lockPath: string): boolean {\n\ttry {\n\t\tconst stats = statSync(lockPath);\n\t\tif (Date.now() - stats.mtimeMs <= GUIDELINES_LOCK_STALE_MS) {\n\t\t\treturn false;\n\t\t}\n\t\tconst owner = readGuidelinesLockOwner(lockPath);\n\t\tif (typeof owner?.pid === \"number\" && isProcessAlive(owner.pid)) {\n\t\t\treturn false;\n\t\t}\n\t\trmSync(lockPath, { recursive: true, force: true });\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction readGuidelinesLockOwner(lockPath: string): GuidelinesLockOwner | null {\n\ttry {\n\t\tconst raw = readFileSync(\n\t\t\tjoin(lockPath, GUIDELINES_LOCK_OWNER_FILE),\n\t\t\t\"utf-8\",\n\t\t);\n\t\tconst parsed = JSON.parse(raw) as Partial<GuidelinesLockOwner>;\n\t\tif (\n\t\t\ttypeof parsed.pid === \"number\" &&\n\t\t\ttypeof parsed.token === \"string\" &&\n\t\t\ttypeof parsed.createdAt === \"string\"\n\t\t) {\n\t\t\treturn {\n\t\t\t\tpid: parsed.pid,\n\t\t\t\ttoken: parsed.token,\n\t\t\t\tcreatedAt: parsed.createdAt,\n\t\t\t};\n\t\t}\n\t} catch {\n\t\t// Missing or malformed ownership metadata is treated as unowned.\n\t}\n\treturn null;\n}\n\nfunction sleepSync(ms: number): void {\n\tAtomics.wait(SLEEP_VIEW, 0, 0, ms);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linter.d.ts","sourceRoot":"","sources":["../../src/skills/linter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"linter.d.ts","sourceRoot":"","sources":["../../src/skills/linter.ts"],"names":[],"mappings":"AAmBA,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,SAAS,CAAC;AAEpD,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,cAAc,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,KAAK,gBAAgB,GAAG;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CAC3B,CAAC;AAEF,eAAO,MAAM,oBAAoB,MAAM,CAAC;AACxC,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAyS3C,wBAAgB,6BAA6B,CAC5C,IAAI,EAAE,MAAM,EACZ,OAAO,qBAAsB,GAC3B,OAAO,CAKT;AAsBD,wBAAgB,gCAAgC,CAC/C,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC1C,OAAO,CAET;AAED,wBAAgB,2BAA2B,CAC1C,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC1C,MAAM,CAER;AA4FD,wBAAsB,kBAAkB,CACvC,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,gBAAqB,GAC5B,OAAO,CAAC,eAAe,CAAC,CA+F1B;AAED,wBAAsB,cAAc,CACnC,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,GAAE,gBAAqB,GAC5B,OAAO,CAAC,eAAe,EAAE,CAAC,CA6C5B;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,CA6BtE;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,OAAO,CAItE;AAED,wBAAgB,aAAa,CAC5B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,oBAAyB,GAChC,mBAAmB,CAgFrB"}
|
package/dist/skills/linter.js
CHANGED
|
@@ -3,6 +3,7 @@ import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, } from "nod
|
|
|
3
3
|
import { constants, access } from "node:fs/promises";
|
|
4
4
|
import { basename, extname, join, resolve } from "node:path";
|
|
5
5
|
import { writeTextFileAtomic } from "../utils/fs.js";
|
|
6
|
+
import { isRecord } from "../utils/json.js";
|
|
6
7
|
import { SKILL_FRONTMATTER_FIELDS, findSkillMd, parseFrontmatter, stringArrayValue, } from "./loader.js";
|
|
7
8
|
export const SKILL_BODY_MAX_LINES = 500;
|
|
8
9
|
export const SKILL_BODY_MAX_CHARS = 20_000;
|
|
@@ -11,9 +12,6 @@ const SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
|
11
12
|
function issue(code, severity, path, message) {
|
|
12
13
|
return { code, severity, path, message };
|
|
13
14
|
}
|
|
14
|
-
function isRecord(value) {
|
|
15
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16
|
-
}
|
|
17
15
|
function validateSkillName(value, dirName, path) {
|
|
18
16
|
if (typeof value !== "string" || value.trim().length === 0) {
|
|
19
17
|
return [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linter.js","sourceRoot":"","sources":["../../src/skills/linter.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport {\n\texistsSync,\n\tmkdirSync,\n\treadFileSync,\n\treaddirSync,\n\tstatSync,\n} from \"node:fs\";\nimport { constants, access } from \"node:fs/promises\";\nimport { basename, extname, join, resolve } from \"node:path\";\nimport { writeTextFileAtomic } from \"../utils/fs.js\";\nimport {\n\tSKILL_FRONTMATTER_FIELDS,\n\tfindSkillMd,\n\tparseFrontmatter,\n\tstringArrayValue,\n} from \"./loader.js\";\n\nexport type SkillLintSeverity = \"error\" | \"warning\";\n\nexport interface SkillLintIssue {\n\tcode: string;\n\tseverity: SkillLintSeverity;\n\tmessage: string;\n\tpath: string;\n}\n\nexport interface SkillLintResult {\n\tpath: string;\n\tissues: SkillLintIssue[];\n}\n\nexport interface SkillScaffoldOptions {\n\tdescription?: string;\n\tforce?: boolean;\n}\n\nexport interface SkillScaffoldResult {\n\tname: string;\n\tdirectory: string;\n\tfiles: string[];\n}\n\ntype SkillLintOptions = {\n\tdescribeToolbox?: boolean;\n\tplatform?: NodeJS.Platform;\n};\n\nexport const SKILL_BODY_MAX_LINES = 500;\nexport const SKILL_BODY_MAX_CHARS = 20_000;\n\nconst FIELD_SET = new Set<string>(SKILL_FRONTMATTER_FIELDS);\nconst SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\nfunction issue(\n\tcode: string,\n\tseverity: SkillLintSeverity,\n\tpath: string,\n\tmessage: string,\n): SkillLintIssue {\n\treturn { code, severity, path, message };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction validateSkillName(\n\tvalue: unknown,\n\tdirName: string,\n\tpath: string,\n): SkillLintIssue[] {\n\tif (typeof value !== \"string\" || value.trim().length === 0) {\n\t\treturn [\n\t\t\tissue(\"missing_name\", \"error\", path, \"Skill frontmatter requires name.\"),\n\t\t];\n\t}\n\n\tconst issues: SkillLintIssue[] = [];\n\tif (value.length > 64) {\n\t\tissues.push(\n\t\t\tissue(\"name_too_long\", \"error\", path, \"Skill name must be <= 64 chars.\"),\n\t\t);\n\t}\n\tif (!SKILL_NAME_PATTERN.test(value)) {\n\t\tissues.push(\n\t\t\tissue(\n\t\t\t\t\"invalid_name\",\n\t\t\t\t\"error\",\n\t\t\t\tpath,\n\t\t\t\t\"Skill name must use lowercase letters, numbers, and single hyphens.\",\n\t\t\t),\n\t\t);\n\t}\n\tif (dirName !== \"skills\" && value !== dirName) {\n\t\tissues.push(\n\t\t\tissue(\n\t\t\t\t\"name_mismatch\",\n\t\t\t\t\"error\",\n\t\t\t\tpath,\n\t\t\t\t`Skill name '${value}' must match directory '${dirName}'.`,\n\t\t\t),\n\t\t);\n\t}\n\treturn issues;\n}\n\nfunction validateDescription(value: unknown, path: string): SkillLintIssue[] {\n\tif (typeof value !== \"string\" || value.trim().length === 0) {\n\t\treturn [\n\t\t\tissue(\n\t\t\t\t\"missing_description\",\n\t\t\t\t\"error\",\n\t\t\t\tpath,\n\t\t\t\t\"Skill frontmatter requires description.\",\n\t\t\t),\n\t\t];\n\t}\n\n\tconst issues: SkillLintIssue[] = [];\n\tif (value.length > 1024) {\n\t\tissues.push(\n\t\t\tissue(\n\t\t\t\t\"description_too_long\",\n\t\t\t\t\"error\",\n\t\t\t\tpath,\n\t\t\t\t\"Skill description must be <= 1024 chars.\",\n\t\t\t),\n\t\t);\n\t}\n\tif (!/\\b(use|when)\\b/i.test(value)) {\n\t\tissues.push(\n\t\t\tissue(\n\t\t\t\t\"description_missing_when\",\n\t\t\t\t\"warning\",\n\t\t\t\tpath,\n\t\t\t\t'Description should include when to use the skill, for example \"Use when ...\".',\n\t\t\t),\n\t\t);\n\t}\n\treturn issues;\n}\n\nfunction validateStringArrayField(\n\tfrontmatter: Record<string, unknown>,\n\tfield: string,\n\tpath: string,\n): SkillLintIssue[] {\n\tconst value = frontmatter[field];\n\tif (value === undefined) return [];\n\tif (Array.isArray(value)) {\n\t\tif (\n\t\t\tvalue.length === 0 ||\n\t\t\tvalue.some((entry) => typeof entry !== \"string\" || entry.trim() === \"\")\n\t\t) {\n\t\t\treturn [\n\t\t\t\tissue(\n\t\t\t\t\t\"invalid_string_list\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tpath,\n\t\t\t\t\t`${field} entries must all be non-empty strings.`,\n\t\t\t\t),\n\t\t\t];\n\t\t}\n\t\treturn [];\n\t}\n\tconst normalized = stringArrayValue(value);\n\tif (!normalized || normalized.length === 0) {\n\t\treturn [\n\t\t\tissue(\n\t\t\t\t\"invalid_string_list\",\n\t\t\t\t\"error\",\n\t\t\t\tpath,\n\t\t\t\t`${field} must be a non-empty string or list of strings.`,\n\t\t\t),\n\t\t];\n\t}\n\treturn [];\n}\n\nfunction isBooleanFrontmatterValue(value: unknown): boolean {\n\tif (typeof value === \"boolean\") return true;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.toLowerCase();\n\t\treturn normalized === \"true\" || normalized === \"false\";\n\t}\n\treturn false;\n}\n\nfunction validateBody(body: string, path: string): SkillLintIssue[] {\n\tconst issues: SkillLintIssue[] = [];\n\tconst lines = body.split(\"\\n\").length;\n\tif (lines > SKILL_BODY_MAX_LINES) {\n\t\tissues.push(\n\t\t\tissue(\n\t\t\t\t\"skill_oversize\",\n\t\t\t\t\"error\",\n\t\t\t\tpath,\n\t\t\t\t`SKILL.md body has ${lines} lines; maximum is ${SKILL_BODY_MAX_LINES}.`,\n\t\t\t),\n\t\t);\n\t}\n\tif (body.length > SKILL_BODY_MAX_CHARS) {\n\t\tissues.push(\n\t\t\tissue(\n\t\t\t\t\"skill_oversize\",\n\t\t\t\t\"error\",\n\t\t\t\tpath,\n\t\t\t\t`SKILL.md body has ${body.length} chars; maximum is ${SKILL_BODY_MAX_CHARS}.`,\n\t\t\t),\n\t\t);\n\t}\n\treturn issues;\n}\n\nfunction validateMcpJson(skillDir: string): SkillLintIssue[] {\n\tconst path = join(skillDir, \"mcp.json\");\n\tif (!existsSync(path)) return [];\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(readFileSync(path, \"utf8\"));\n\t} catch (error) {\n\t\treturn [\n\t\t\tissue(\n\t\t\t\t\"invalid_mcp_json\",\n\t\t\t\t\"error\",\n\t\t\t\tpath,\n\t\t\t\t`mcp.json must be valid JSON: ${\n\t\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\t\t}`,\n\t\t\t),\n\t\t];\n\t}\n\n\tif (!isRecord(parsed)) {\n\t\treturn [\n\t\t\tissue(\n\t\t\t\t\"invalid_mcp_json\",\n\t\t\t\t\"error\",\n\t\t\t\tpath,\n\t\t\t\t\"mcp.json must be an object keyed by server name.\",\n\t\t\t),\n\t\t];\n\t}\n\n\tconst issues: SkillLintIssue[] = [];\n\tfor (const [serverName, server] of Object.entries(parsed)) {\n\t\tconst serverPath = `${path}#${serverName}`;\n\t\tif (!isRecord(server)) {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"invalid_mcp_server\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tserverPath,\n\t\t\t\t\t\"MCP server config must be an object.\",\n\t\t\t\t),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof server.command !== \"string\" || server.command.trim() === \"\") {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"invalid_mcp_command\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tserverPath,\n\t\t\t\t\t\"MCP server requires a non-empty command.\",\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\t!Array.isArray(server.includeTools) ||\n\t\t\tserver.includeTools.length === 0\n\t\t) {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"mcp_tools_unfiltered\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tserverPath,\n\t\t\t\t\t\"MCP server must declare includeTools with at least one tool.\",\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (\n\t\t\tserver.includeTools.some(\n\t\t\t\t(tool) => typeof tool !== \"string\" || tool.trim() === \"\",\n\t\t\t)\n\t\t) {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"invalid_mcp_include_tools\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tserverPath,\n\t\t\t\t\t\"includeTools entries must be non-empty strings.\",\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\tserver.args !== undefined &&\n\t\t\t(!Array.isArray(server.args) ||\n\t\t\t\tserver.args.some((arg) => typeof arg !== \"string\"))\n\t\t) {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"invalid_mcp_args\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tserverPath,\n\t\t\t\t\t\"MCP args must be a list of strings.\",\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tif (server.env !== undefined && !isRecord(server.env)) {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"invalid_mcp_env\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tserverPath,\n\t\t\t\t\t\"MCP env must be an object of string values.\",\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\tisRecord(server.env) &&\n\t\t\tObject.values(server.env).some((value) => typeof value !== \"string\")\n\t\t) {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"invalid_mcp_env\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tserverPath,\n\t\t\t\t\t\"MCP env values must be strings.\",\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\treturn issues;\n}\n\nconst DEFAULT_WINDOWS_EXECUTABLE_EXTENSIONS = \".COM;.EXE;.BAT;.CMD;.PS1\";\n\nfunction windowsExecutableExtensions(\n\tpathExt = process.env.PATHEXT,\n): Set<string> {\n\treturn new Set(\n\t\t(pathExt || DEFAULT_WINDOWS_EXECUTABLE_EXTENSIONS)\n\t\t\t.split(\";\")\n\t\t\t.map((entry) => entry.trim().toUpperCase())\n\t\t\t.filter(Boolean),\n\t);\n}\n\nexport function isWindowsRunnableToolboxEntry(\n\tpath: string,\n\tpathExt = process.env.PATHEXT,\n): boolean {\n\tconst extension = extname(path).toUpperCase();\n\treturn Boolean(\n\t\textension && windowsExecutableExtensions(pathExt).has(extension),\n\t);\n}\n\nfunction hasWindowsRunnableToolboxCompanion(\n\tentry: string,\n\tdirectoryEntries: string[],\n\tpathExt = process.env.PATHEXT,\n): boolean {\n\tif (isWindowsRunnableToolboxEntry(entry, pathExt)) {\n\t\treturn false;\n\t}\n\tconst entryStem = basename(entry, extname(entry)).toLowerCase();\n\treturn directoryEntries.some((candidate) => {\n\t\tif (candidate === entry) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!isWindowsRunnableToolboxEntry(candidate, pathExt)) {\n\t\t\treturn false;\n\t\t}\n\t\treturn basename(candidate, extname(candidate)).toLowerCase() === entryStem;\n\t});\n}\n\nexport function shouldUseShellForToolboxDescribe(\n\tplatform: NodeJS.Platform = process.platform,\n): boolean {\n\treturn platform === \"win32\";\n}\n\nexport function toolboxDescribeSpawnCommand(\n\tpath: string,\n\tplatform: NodeJS.Platform = process.platform,\n): string {\n\treturn platform === \"win32\" ? `\"${path}\"` : path;\n}\n\nasync function isExecutable(\n\tpath: string,\n\tplatform: NodeJS.Platform = process.platform,\n): Promise<boolean> {\n\tif (platform === \"win32\") {\n\t\treturn isWindowsRunnableToolboxEntry(path);\n\t}\n\ttry {\n\t\tawait access(path, constants.X_OK);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function validateToolbox(\n\tskillDir: string,\n\toptions: SkillLintOptions = {},\n): Promise<SkillLintIssue[]> {\n\tconst toolboxDir = join(skillDir, \"toolbox\");\n\tif (!existsSync(toolboxDir) || !statSync(toolboxDir).isDirectory()) return [];\n\n\tconst issues: SkillLintIssue[] = [];\n\tconst directoryEntries = readdirSync(toolboxDir);\n\tconst platform = options.platform ?? process.platform;\n\tlet toolboxEntryCount = 0;\n\tlet runnableEntryCount = 0;\n\tfor (const entry of directoryEntries) {\n\t\tif (entry.startsWith(\".\") || entry.toLowerCase() === \"readme.md\") continue;\n\t\tconst path = join(toolboxDir, entry);\n\t\tif (!statSync(path).isFile()) continue;\n\t\ttoolboxEntryCount += 1;\n\t\tif (platform !== \"win32\" && isWindowsRunnableToolboxEntry(path)) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (\n\t\t\tplatform === \"win32\" &&\n\t\t\t!isWindowsRunnableToolboxEntry(path) &&\n\t\t\thasWindowsRunnableToolboxCompanion(entry, directoryEntries)\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (!(await isExecutable(path, platform))) {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"toolbox_not_executable\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tpath,\n\t\t\t\t\t\"Toolbox entries must be executable files.\",\n\t\t\t\t),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\trunnableEntryCount += 1;\n\t\tif (options.describeToolbox) {\n\t\t\tconst result = spawnSync(toolboxDescribeSpawnCommand(path, platform), {\n\t\t\t\tenv: { ...process.env, MAESTRO_TOOLBOX_ACTION: \"describe\" },\n\t\t\t\tencoding: \"utf8\",\n\t\t\t\tshell: shouldUseShellForToolboxDescribe(platform),\n\t\t\t\ttimeout: 5000,\n\t\t\t});\n\t\t\tif (result.status !== 0) {\n\t\t\t\tissues.push(\n\t\t\t\t\tissue(\n\t\t\t\t\t\t\"toolbox_describe_failed\",\n\t\t\t\t\t\t\"error\",\n\t\t\t\t\t\tpath,\n\t\t\t\t\t\t`Toolbox describe failed: ${result.stderr || result.stdout || \"non-zero exit\"}`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\tif (\n\t\ttoolboxEntryCount > 0 &&\n\t\trunnableEntryCount === 0 &&\n\t\tissues.length === 0\n\t) {\n\t\tissues.push(\n\t\t\tissue(\n\t\t\t\t\"toolbox_no_runnable_entries\",\n\t\t\t\t\"error\",\n\t\t\t\ttoolboxDir,\n\t\t\t\t\"Toolbox must include at least one executable entry runnable on the target platform.\",\n\t\t\t),\n\t\t);\n\t}\n\treturn issues;\n}\n\nexport async function lintSkillDirectory(\n\tskillDir: string,\n\toptions: SkillLintOptions = {},\n): Promise<SkillLintResult> {\n\tconst resolvedDir = resolve(skillDir);\n\tconst skillFile = findSkillMd(resolvedDir);\n\tconst issues: SkillLintIssue[] = [];\n\tif (!skillFile) {\n\t\treturn {\n\t\t\tpath: resolvedDir,\n\t\t\tissues: [\n\t\t\t\tissue(\n\t\t\t\t\t\"missing_skill_md\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tresolvedDir,\n\t\t\t\t\t\"Skill package requires SKILL.md.\",\n\t\t\t\t),\n\t\t\t],\n\t\t};\n\t}\n\n\ttry {\n\t\tconst { frontmatter, body } = parseFrontmatter(\n\t\t\treadFileSync(skillFile, \"utf8\"),\n\t\t);\n\t\tfor (const key of Object.keys(frontmatter)) {\n\t\t\tif (!FIELD_SET.has(key)) {\n\t\t\t\tissues.push(\n\t\t\t\t\tissue(\n\t\t\t\t\t\t\"unexpected_field\",\n\t\t\t\t\t\t\"error\",\n\t\t\t\t\t\tskillFile,\n\t\t\t\t\t\t`Unexpected frontmatter field '${key}'.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tissues.push(\n\t\t\t...validateSkillName(frontmatter.name, basename(resolvedDir), skillFile),\n\t\t);\n\t\tissues.push(...validateDescription(frontmatter.description, skillFile));\n\t\tfor (const field of [\"allowed-tools\", \"builtin-tools\"]) {\n\t\t\tissues.push(...validateStringArrayField(frontmatter, field, skillFile));\n\t\t}\n\t\tif (\n\t\t\tfrontmatter.compatibility !== undefined &&\n\t\t\ttypeof frontmatter.compatibility !== \"string\"\n\t\t) {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"invalid_compatibility\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tskillFile,\n\t\t\t\t\t\"compatibility must be a string.\",\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\tfrontmatter.isolatedContext !== undefined &&\n\t\t\t!isBooleanFrontmatterValue(frontmatter.isolatedContext)\n\t\t) {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"invalid_isolated_context\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tskillFile,\n\t\t\t\t\t\"isolatedContext must be a boolean.\",\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tissues.push(...validateBody(body, skillFile));\n\t} catch (error) {\n\t\tissues.push(\n\t\t\tissue(\n\t\t\t\t\"invalid_skill_md\",\n\t\t\t\t\"error\",\n\t\t\t\tskillFile,\n\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t),\n\t\t);\n\t}\n\n\tif (\n\t\texistsSync(join(resolvedDir, \"reference\")) &&\n\t\texistsSync(join(resolvedDir, \"references\"))\n\t) {\n\t\tissues.push(\n\t\t\tissue(\n\t\t\t\t\"duplicate_reference_dirs\",\n\t\t\t\t\"warning\",\n\t\t\t\tresolvedDir,\n\t\t\t\t\"Use either reference/ or references/; reference/ is preferred.\",\n\t\t\t),\n\t\t);\n\t}\n\tissues.push(...validateMcpJson(resolvedDir));\n\tissues.push(...(await validateToolbox(resolvedDir, options)));\n\treturn { path: resolvedDir, issues };\n}\n\nexport async function lintSkillPaths(\n\tpaths: string[],\n\toptions: SkillLintOptions = {},\n): Promise<SkillLintResult[]> {\n\tconst results: SkillLintResult[] = [];\n\tfor (const path of paths) {\n\t\tconst resolved = resolve(path);\n\t\tif (!existsSync(resolved)) {\n\t\t\tresults.push({\n\t\t\t\tpath: resolved,\n\t\t\t\tissues: [\n\t\t\t\t\tissue(\n\t\t\t\t\t\t\"missing_path\",\n\t\t\t\t\t\t\"error\",\n\t\t\t\t\t\tresolved,\n\t\t\t\t\t\t\"Skill path does not exist.\",\n\t\t\t\t\t),\n\t\t\t\t],\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tconst stat = statSync(resolved);\n\t\tif (!stat.isDirectory()) {\n\t\t\tresults.push({\n\t\t\t\tpath: resolved,\n\t\t\t\tissues: [\n\t\t\t\t\tissue(\n\t\t\t\t\t\t\"invalid_path\",\n\t\t\t\t\t\t\"error\",\n\t\t\t\t\t\tresolved,\n\t\t\t\t\t\t\"Skill path must be a directory.\",\n\t\t\t\t\t),\n\t\t\t\t],\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (findSkillMd(resolved)) {\n\t\t\tresults.push(await lintSkillDirectory(resolved, options));\n\t\t\tcontinue;\n\t\t}\n\t\tfor (const entry of readdirSync(resolved)) {\n\t\t\tconst child = join(resolved, entry);\n\t\t\tif (statSync(child).isDirectory()) {\n\t\t\t\tresults.push(await lintSkillDirectory(child, options));\n\t\t\t}\n\t\t}\n\t}\n\treturn results;\n}\n\nexport function formatSkillLintText(results: SkillLintResult[]): string {\n\tconst lines: string[] = [];\n\tlet errorCount = 0;\n\tlet warningCount = 0;\n\tfor (const result of results) {\n\t\tconst issues = result.issues;\n\t\tif (issues.length === 0) {\n\t\t\tlines.push(`OK ${result.path}`);\n\t\t\tcontinue;\n\t\t}\n\t\tlines.push(result.path);\n\t\tfor (const item of issues) {\n\t\t\tif (item.severity === \"error\") errorCount++;\n\t\t\tif (item.severity === \"warning\") warningCount++;\n\t\t\tlines.push(\n\t\t\t\t` ${item.severity.toUpperCase()} ${item.code}: ${item.message}`,\n\t\t\t);\n\t\t\tif (item.path !== result.path) {\n\t\t\t\tlines.push(` ${item.path}`);\n\t\t\t}\n\t\t}\n\t}\n\tlines.push(\"\");\n\tlines.push(\n\t\t`${errorCount} error${errorCount === 1 ? \"\" : \"s\"}, ${warningCount} warning${\n\t\t\twarningCount === 1 ? \"\" : \"s\"\n\t\t}`,\n\t);\n\treturn lines.join(\"\\n\");\n}\n\nexport function hasSkillLintErrors(results: SkillLintResult[]): boolean {\n\treturn results.some((result) =>\n\t\tresult.issues.some((item) => item.severity === \"error\"),\n\t);\n}\n\nexport function scaffoldSkill(\n\tbaseDir: string,\n\tname: string,\n\toptions: SkillScaffoldOptions = {},\n): SkillScaffoldResult {\n\tif (!SKILL_NAME_PATTERN.test(name) || name.length > 64) {\n\t\tthrow new Error(\n\t\t\t\"Skill name must use lowercase letters, numbers, and single hyphens.\",\n\t\t);\n\t}\n\tconst directory = resolve(baseDir, name);\n\tif (existsSync(directory) && !options.force) {\n\t\tthrow new Error(`Skill already exists at ${directory}`);\n\t}\n\n\tconst description =\n\t\toptions.description ??\n\t\t`${name.replace(/-/g, \" \")}. Use when a task needs this packaged workflow.`;\n\tconst files: string[] = [];\n\tmkdirSync(join(directory, \"reference\"), { recursive: true });\n\tmkdirSync(join(directory, \"scripts\"), { recursive: true });\n\tmkdirSync(join(directory, \"toolbox\"), { recursive: true });\n\n\tconst skillMd = join(directory, \"SKILL.md\");\n\tconst escapedDescription = description\n\t\t.replace(/\\\\/g, \"\\\\\\\\\")\n\t\t.replace(/\"/g, '\\\\\"');\n\twriteTextFileAtomic(\n\t\tskillMd,\n\t\t[\n\t\t\t\"---\",\n\t\t\t`name: ${name}`,\n\t\t\t`description: \"${escapedDescription}\"`,\n\t\t\t\"allowed-tools:\",\n\t\t\t\" - read\",\n\t\t\t\"builtin-tools:\",\n\t\t\t\" - read\",\n\t\t\t\"---\",\n\t\t\t\"\",\n\t\t\t`# ${name}`,\n\t\t\t\"\",\n\t\t\t\"## Workflow\",\n\t\t\t\"\",\n\t\t\t\"1. State the task-specific outcome.\",\n\t\t\t\"2. Load only the reference files needed for the request.\",\n\t\t\t\"3. Use bundled scripts or toolbox executables when they are more reliable than retyping long commands.\",\n\t\t\t\"\",\n\t\t\t\"## References\",\n\t\t\t\"\",\n\t\t\t\"- Read `reference/overview.md` when the user asks for implementation detail.\",\n\t\t\t\"\",\n\t\t].join(\"\\n\"),\n\t);\n\tfiles.push(skillMd);\n\n\tconst reference = join(directory, \"reference\", \"overview.md\");\n\twriteTextFileAtomic(\n\t\treference,\n\t\t`# ${name} Reference\\n\\nAdd deeper examples, protocol notes, and troubleshooting details here. Keep this out of SKILL.md until needed.\\n`,\n\t);\n\tfiles.push(reference);\n\n\tconst scriptsReadme = join(directory, \"scripts\", \"README.md\");\n\twriteTextFileAtomic(\n\t\tscriptsReadme,\n\t\t\"# Scripts\\n\\nPut deterministic helper scripts here. Agents should run these instead of retyping long workflows.\\n\",\n\t);\n\tfiles.push(scriptsReadme);\n\n\tconst toolboxReadme = join(directory, \"toolbox\", \"README.md\");\n\twriteTextFileAtomic(\n\t\ttoolboxReadme,\n\t\t\"# Toolbox\\n\\nPut executable Toolbox protocol commands here. Each executable should support `MAESTRO_TOOLBOX_ACTION=describe`.\\n\",\n\t);\n\tfiles.push(toolboxReadme);\n\n\tconst mcpJson = join(directory, \"mcp.json.example\");\n\twriteTextFileAtomic(\n\t\tmcpJson,\n\t\t'{\\n \"example-server\": {\\n \"command\": \"npx\",\\n \"args\": [\"-y\", \"example-mcp-server\"],\\n \"includeTools\": [\"example_tool\"]\\n }\\n}\\n',\n\t);\n\tfiles.push(mcpJson);\n\n\treturn { name, directory, files };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"linter.js","sourceRoot":"","sources":["../../src/skills/linter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EACN,UAAU,EACV,SAAS,EACT,YAAY,EACZ,WAAW,EACX,QAAQ,GACR,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EACN,wBAAwB,EACxB,WAAW,EACX,gBAAgB,EAChB,gBAAgB,GAChB,MAAM,aAAa,CAAC;AAgCrB,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,CAAC;AACxC,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAE3C,MAAM,SAAS,GAAG,IAAI,GAAG,CAAS,wBAAwB,CAAC,CAAC;AAC5D,MAAM,kBAAkB,GAAG,4BAA4B,CAAC;AAExD,SAAS,KAAK,CACb,IAAY,EACZ,QAA2B,EAC3B,IAAY,EACZ,OAAe;IAEf,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC1C,CAAC;AAED,SAAS,iBAAiB,CACzB,KAAc,EACd,OAAe,EACf,IAAY;IAEZ,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5D,OAAO;YACN,KAAK,CAAC,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,kCAAkC,CAAC;SACxE,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAqB,EAAE,CAAC;IACpC,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACvB,MAAM,CAAC,IAAI,CACV,KAAK,CAAC,eAAe,EAAE,OAAO,EAAE,IAAI,EAAE,iCAAiC,CAAC,CACxE,CAAC;IACH,CAAC;IACD,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,cAAc,EACd,OAAO,EACP,IAAI,EACJ,qEAAqE,CACrE,CACD,CAAC;IACH,CAAC;IACD,IAAI,OAAO,KAAK,QAAQ,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;QAC/C,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,eAAe,EACf,OAAO,EACP,IAAI,EACJ,eAAe,KAAK,2BAA2B,OAAO,IAAI,CAC1D,CACD,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAc,EAAE,IAAY;IACxD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5D,OAAO;YACN,KAAK,CACJ,qBAAqB,EACrB,OAAO,EACP,IAAI,EACJ,yCAAyC,CACzC;SACD,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAqB,EAAE,CAAC;IACpC,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;QACzB,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,sBAAsB,EACtB,OAAO,EACP,IAAI,EACJ,0CAA0C,CAC1C,CACD,CAAC;IACH,CAAC;IACD,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACpC,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,0BAA0B,EAC1B,SAAS,EACT,IAAI,EACJ,+EAA+E,CAC/E,CACD,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED,SAAS,wBAAwB,CAChC,WAAoC,EACpC,KAAa,EACb,IAAY;IAEZ,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACnC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,IACC,KAAK,CAAC,MAAM,KAAK,CAAC;YAClB,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EACtE,CAAC;YACF,OAAO;gBACN,KAAK,CACJ,qBAAqB,EACrB,OAAO,EACP,IAAI,EACJ,GAAG,KAAK,yCAAyC,CACjD;aACD,CAAC;QACH,CAAC;QACD,OAAO,EAAE,CAAC;IACX,CAAC;IACD,MAAM,UAAU,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC3C,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5C,OAAO;YACN,KAAK,CACJ,qBAAqB,EACrB,OAAO,EACP,IAAI,EACJ,GAAG,KAAK,iDAAiD,CACzD;SACD,CAAC;IACH,CAAC;IACD,OAAO,EAAE,CAAC;AACX,CAAC;AAED,SAAS,yBAAyB,CAAC,KAAc;IAChD,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QACvC,OAAO,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,OAAO,CAAC;IACxD,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,IAAY;IAC/C,MAAM,MAAM,GAAqB,EAAE,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IACtC,IAAI,KAAK,GAAG,oBAAoB,EAAE,CAAC;QAClC,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,gBAAgB,EAChB,OAAO,EACP,IAAI,EACJ,qBAAqB,KAAK,sBAAsB,oBAAoB,GAAG,CACvE,CACD,CAAC;IACH,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,GAAG,oBAAoB,EAAE,CAAC;QACxC,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,gBAAgB,EAChB,OAAO,EACP,IAAI,EACJ,qBAAqB,IAAI,CAAC,MAAM,sBAAsB,oBAAoB,GAAG,CAC7E,CACD,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED,SAAS,eAAe,CAAC,QAAgB;IACxC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACxC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IAEjC,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACJ,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,OAAO;YACN,KAAK,CACJ,kBAAkB,EAClB,OAAO,EACP,IAAI,EACJ,gCACC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACtD,EAAE,CACF;SACD,CAAC;IACH,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,OAAO;YACN,KAAK,CACJ,kBAAkB,EAClB,OAAO,EACP,IAAI,EACJ,kDAAkD,CAClD;SACD,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAqB,EAAE,CAAC;IACpC,KAAK,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3D,MAAM,UAAU,GAAG,GAAG,IAAI,IAAI,UAAU,EAAE,CAAC;QAC3C,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACvB,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,oBAAoB,EACpB,OAAO,EACP,UAAU,EACV,sCAAsC,CACtC,CACD,CAAC;YACF,SAAS;QACV,CAAC;QACD,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACxE,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,qBAAqB,EACrB,OAAO,EACP,UAAU,EACV,0CAA0C,CAC1C,CACD,CAAC;QACH,CAAC;QACD,IACC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC;YACnC,MAAM,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,EAC/B,CAAC;YACF,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,sBAAsB,EACtB,OAAO,EACP,UAAU,EACV,8DAA8D,CAC9D,CACD,CAAC;QACH,CAAC;aAAM,IACN,MAAM,CAAC,YAAY,CAAC,IAAI,CACvB,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CACxD,EACA,CAAC;YACF,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,2BAA2B,EAC3B,OAAO,EACP,UAAU,EACV,iDAAiD,CACjD,CACD,CAAC;QACH,CAAC;QACD,IACC,MAAM,CAAC,IAAI,KAAK,SAAS;YACzB,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;gBAC3B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,EACnD,CAAC;YACF,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,kBAAkB,EAClB,OAAO,EACP,UAAU,EACV,qCAAqC,CACrC,CACD,CAAC;QACH,CAAC;QACD,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YACvD,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,iBAAiB,EACjB,OAAO,EACP,UAAU,EACV,6CAA6C,CAC7C,CACD,CAAC;QACH,CAAC;QACD,IACC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC;YACpB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,EACnE,CAAC;YACF,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,iBAAiB,EACjB,OAAO,EACP,UAAU,EACV,iCAAiC,CACjC,CACD,CAAC;QACH,CAAC;IACF,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,qCAAqC,GAAG,0BAA0B,CAAC;AAEzE,SAAS,2BAA2B,CACnC,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO;IAE7B,OAAO,IAAI,GAAG,CACb,CAAC,OAAO,IAAI,qCAAqC,CAAC;SAChD,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;SAC1C,MAAM,CAAC,OAAO,CAAC,CACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,6BAA6B,CAC5C,IAAY,EACZ,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO;IAE7B,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAC9C,OAAO,OAAO,CACb,SAAS,IAAI,2BAA2B,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAChE,CAAC;AACH,CAAC;AAED,SAAS,kCAAkC,CAC1C,KAAa,EACb,gBAA0B,EAC1B,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO;IAE7B,IAAI,6BAA6B,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC;QACnD,OAAO,KAAK,CAAC;IACd,CAAC;IACD,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAChE,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE;QAC1C,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC;QACd,CAAC;QACD,IAAI,CAAC,6BAA6B,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC;YACxD,OAAO,KAAK,CAAC;QACd,CAAC;QACD,OAAO,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,SAAS,CAAC;IAC5E,CAAC,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gCAAgC,CAC/C,WAA4B,OAAO,CAAC,QAAQ;IAE5C,OAAO,QAAQ,KAAK,OAAO,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,2BAA2B,CAC1C,IAAY,EACZ,WAA4B,OAAO,CAAC,QAAQ;IAE5C,OAAO,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC;AAED,KAAK,UAAU,YAAY,CAC1B,IAAY,EACZ,WAA4B,OAAO,CAAC,QAAQ;IAE5C,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QAC1B,OAAO,6BAA6B,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC;IACD,IAAI,CAAC;QACJ,MAAM,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAC;IACd,CAAC;AACF,CAAC;AAED,KAAK,UAAU,eAAe,CAC7B,QAAgB,EAChB,UAA4B,EAAE;IAE9B,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC7C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE;QAAE,OAAO,EAAE,CAAC;IAE9E,MAAM,MAAM,GAAqB,EAAE,CAAC;IACpC,MAAM,gBAAgB,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;IACtD,IAAI,iBAAiB,GAAG,CAAC,CAAC;IAC1B,IAAI,kBAAkB,GAAG,CAAC,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;QACtC,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,WAAW,EAAE,KAAK,WAAW;YAAE,SAAS;QAC3E,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACrC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE;YAAE,SAAS;QACvC,iBAAiB,IAAI,CAAC,CAAC;QACvB,IAAI,QAAQ,KAAK,OAAO,IAAI,6BAA6B,CAAC,IAAI,CAAC,EAAE,CAAC;YACjE,SAAS;QACV,CAAC;QACD,IACC,QAAQ,KAAK,OAAO;YACpB,CAAC,6BAA6B,CAAC,IAAI,CAAC;YACpC,kCAAkC,CAAC,KAAK,EAAE,gBAAgB,CAAC,EAC1D,CAAC;YACF,SAAS;QACV,CAAC;QACD,IAAI,CAAC,CAAC,MAAM,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC;YAC3C,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,wBAAwB,EACxB,OAAO,EACP,IAAI,EACJ,2CAA2C,CAC3C,CACD,CAAC;YACF,SAAS;QACV,CAAC;QACD,kBAAkB,IAAI,CAAC,CAAC;QACxB,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,SAAS,CAAC,2BAA2B,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE;gBACrE,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,sBAAsB,EAAE,UAAU,EAAE;gBAC3D,QAAQ,EAAE,MAAM;gBAChB,KAAK,EAAE,gCAAgC,CAAC,QAAQ,CAAC;gBACjD,OAAO,EAAE,IAAI;aACb,CAAC,CAAC;YACH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,yBAAyB,EACzB,OAAO,EACP,IAAI,EACJ,4BAA4B,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,IAAI,eAAe,EAAE,CAC/E,CACD,CAAC;YACH,CAAC;QACF,CAAC;IACF,CAAC;IACD,IACC,iBAAiB,GAAG,CAAC;QACrB,kBAAkB,KAAK,CAAC;QACxB,MAAM,CAAC,MAAM,KAAK,CAAC,EAClB,CAAC;QACF,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,6BAA6B,EAC7B,OAAO,EACP,UAAU,EACV,qFAAqF,CACrF,CACD,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACvC,QAAgB,EAChB,UAA4B,EAAE;IAE9B,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACtC,MAAM,SAAS,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAqB,EAAE,CAAC;IACpC,IAAI,CAAC,SAAS,EAAE,CAAC;QAChB,OAAO;YACN,IAAI,EAAE,WAAW;YACjB,MAAM,EAAE;gBACP,KAAK,CACJ,kBAAkB,EAClB,OAAO,EACP,WAAW,EACX,kCAAkC,CAClC;aACD;SACD,CAAC;IACH,CAAC;IAED,IAAI,CAAC;QACJ,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,gBAAgB,CAC7C,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAC/B,CAAC;QACF,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YAC5C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACzB,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,kBAAkB,EAClB,OAAO,EACP,SAAS,EACT,iCAAiC,GAAG,IAAI,CACxC,CACD,CAAC;YACH,CAAC;QACF,CAAC;QACD,MAAM,CAAC,IAAI,CACV,GAAG,iBAAiB,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,CAAC,CACxE,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,GAAG,mBAAmB,CAAC,WAAW,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC;QACxE,KAAK,MAAM,KAAK,IAAI,CAAC,eAAe,EAAE,eAAe,CAAC,EAAE,CAAC;YACxD,MAAM,CAAC,IAAI,CAAC,GAAG,wBAAwB,CAAC,WAAW,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC;QACzE,CAAC;QACD,IACC,WAAW,CAAC,aAAa,KAAK,SAAS;YACvC,OAAO,WAAW,CAAC,aAAa,KAAK,QAAQ,EAC5C,CAAC;YACF,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,uBAAuB,EACvB,OAAO,EACP,SAAS,EACT,iCAAiC,CACjC,CACD,CAAC;QACH,CAAC;QACD,IACC,WAAW,CAAC,eAAe,KAAK,SAAS;YACzC,CAAC,yBAAyB,CAAC,WAAW,CAAC,eAAe,CAAC,EACtD,CAAC;YACF,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,0BAA0B,EAC1B,OAAO,EACP,SAAS,EACT,oCAAoC,CACpC,CACD,CAAC;QACH,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,kBAAkB,EAClB,OAAO,EACP,SAAS,EACT,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CACtD,CACD,CAAC;IACH,CAAC;IAED,IACC,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QAC1C,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,EAC1C,CAAC;QACF,MAAM,CAAC,IAAI,CACV,KAAK,CACJ,0BAA0B,EAC1B,SAAS,EACT,WAAW,EACX,gEAAgE,CAChE,CACD,CAAC;IACH,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC;IAC7C,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,eAAe,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAC9D,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CACnC,KAAe,EACf,UAA4B,EAAE;IAE9B,MAAM,OAAO,GAAsB,EAAE,CAAC;IACtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE;oBACP,KAAK,CACJ,cAAc,EACd,OAAO,EACP,QAAQ,EACR,4BAA4B,CAC5B;iBACD;aACD,CAAC,CAAC;YACH,SAAS;QACV,CAAC;QACD,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,QAAQ;gBACd,MAAM,EAAE;oBACP,KAAK,CACJ,cAAc,EACd,OAAO,EACP,QAAQ,EACR,iCAAiC,CACjC;iBACD;aACD,CAAC,CAAC;YACH,SAAS;QACV,CAAC;QACD,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,MAAM,kBAAkB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;YAC1D,SAAS;QACV,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACpC,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;gBACnC,OAAO,CAAC,IAAI,CAAC,MAAM,kBAAkB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;YACxD,CAAC;QACF,CAAC;IACF,CAAC;IACD,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAA0B;IAC7D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC7B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YAChC,SAAS;QACV,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACxB,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,IAAI,CAAC,QAAQ,KAAK,OAAO;gBAAE,UAAU,EAAE,CAAC;YAC5C,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;gBAAE,YAAY,EAAE,CAAC;YAChD,KAAK,CAAC,IAAI,CACT,KAAK,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,OAAO,EAAE,CAChE,CAAC;YACF,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC/B,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAChC,CAAC;QACF,CAAC;IACF,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CACT,GAAG,UAAU,SAAS,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,YAAY,WACjE,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAC3B,EAAE,CACF,CAAC;IACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAA0B;IAC5D,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAC9B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,OAAO,CAAC,CACvD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAC5B,OAAe,EACf,IAAY,EACZ,UAAgC,EAAE;IAElC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CACd,qEAAqE,CACrE,CAAC;IACH,CAAC;IACD,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IACzC,IAAI,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CAAC,2BAA2B,SAAS,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,WAAW,GAChB,OAAO,CAAC,WAAW;QACnB,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,iDAAiD,CAAC;IAC7E,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7D,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3D,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE3D,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAC5C,MAAM,kBAAkB,GAAG,WAAW;SACpC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACvB,mBAAmB,CAClB,OAAO,EACP;QACC,KAAK;QACL,SAAS,IAAI,EAAE;QACf,iBAAiB,kBAAkB,GAAG;QACtC,gBAAgB;QAChB,UAAU;QACV,gBAAgB;QAChB,UAAU;QACV,KAAK;QACL,EAAE;QACF,KAAK,IAAI,EAAE;QACX,EAAE;QACF,aAAa;QACb,EAAE;QACF,qCAAqC;QACrC,0DAA0D;QAC1D,wGAAwG;QACxG,EAAE;QACF,eAAe;QACf,EAAE;QACF,8EAA8E;QAC9E,EAAE;KACF,CAAC,IAAI,CAAC,IAAI,CAAC,CACZ,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAEpB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;IAC9D,mBAAmB,CAClB,SAAS,EACT,KAAK,IAAI,gIAAgI,CACzI,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAEtB,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IAC9D,mBAAmB,CAClB,aAAa,EACb,mHAAmH,CACnH,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAE1B,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;IAC9D,mBAAmB,CAClB,aAAa,EACb,iIAAiI,CACjI,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAE1B,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;IACpD,mBAAmB,CAClB,OAAO,EACP,4IAA4I,CAC5I,CAAC;IACF,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAEpB,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AACnC,CAAC","sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport {\n\texistsSync,\n\tmkdirSync,\n\treadFileSync,\n\treaddirSync,\n\tstatSync,\n} from \"node:fs\";\nimport { constants, access } from \"node:fs/promises\";\nimport { basename, extname, join, resolve } from \"node:path\";\nimport { writeTextFileAtomic } from \"../utils/fs.js\";\nimport { isRecord } from \"../utils/json.js\";\nimport {\n\tSKILL_FRONTMATTER_FIELDS,\n\tfindSkillMd,\n\tparseFrontmatter,\n\tstringArrayValue,\n} from \"./loader.js\";\n\nexport type SkillLintSeverity = \"error\" | \"warning\";\n\nexport interface SkillLintIssue {\n\tcode: string;\n\tseverity: SkillLintSeverity;\n\tmessage: string;\n\tpath: string;\n}\n\nexport interface SkillLintResult {\n\tpath: string;\n\tissues: SkillLintIssue[];\n}\n\nexport interface SkillScaffoldOptions {\n\tdescription?: string;\n\tforce?: boolean;\n}\n\nexport interface SkillScaffoldResult {\n\tname: string;\n\tdirectory: string;\n\tfiles: string[];\n}\n\ntype SkillLintOptions = {\n\tdescribeToolbox?: boolean;\n\tplatform?: NodeJS.Platform;\n};\n\nexport const SKILL_BODY_MAX_LINES = 500;\nexport const SKILL_BODY_MAX_CHARS = 20_000;\n\nconst FIELD_SET = new Set<string>(SKILL_FRONTMATTER_FIELDS);\nconst SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\nfunction issue(\n\tcode: string,\n\tseverity: SkillLintSeverity,\n\tpath: string,\n\tmessage: string,\n): SkillLintIssue {\n\treturn { code, severity, path, message };\n}\n\nfunction validateSkillName(\n\tvalue: unknown,\n\tdirName: string,\n\tpath: string,\n): SkillLintIssue[] {\n\tif (typeof value !== \"string\" || value.trim().length === 0) {\n\t\treturn [\n\t\t\tissue(\"missing_name\", \"error\", path, \"Skill frontmatter requires name.\"),\n\t\t];\n\t}\n\n\tconst issues: SkillLintIssue[] = [];\n\tif (value.length > 64) {\n\t\tissues.push(\n\t\t\tissue(\"name_too_long\", \"error\", path, \"Skill name must be <= 64 chars.\"),\n\t\t);\n\t}\n\tif (!SKILL_NAME_PATTERN.test(value)) {\n\t\tissues.push(\n\t\t\tissue(\n\t\t\t\t\"invalid_name\",\n\t\t\t\t\"error\",\n\t\t\t\tpath,\n\t\t\t\t\"Skill name must use lowercase letters, numbers, and single hyphens.\",\n\t\t\t),\n\t\t);\n\t}\n\tif (dirName !== \"skills\" && value !== dirName) {\n\t\tissues.push(\n\t\t\tissue(\n\t\t\t\t\"name_mismatch\",\n\t\t\t\t\"error\",\n\t\t\t\tpath,\n\t\t\t\t`Skill name '${value}' must match directory '${dirName}'.`,\n\t\t\t),\n\t\t);\n\t}\n\treturn issues;\n}\n\nfunction validateDescription(value: unknown, path: string): SkillLintIssue[] {\n\tif (typeof value !== \"string\" || value.trim().length === 0) {\n\t\treturn [\n\t\t\tissue(\n\t\t\t\t\"missing_description\",\n\t\t\t\t\"error\",\n\t\t\t\tpath,\n\t\t\t\t\"Skill frontmatter requires description.\",\n\t\t\t),\n\t\t];\n\t}\n\n\tconst issues: SkillLintIssue[] = [];\n\tif (value.length > 1024) {\n\t\tissues.push(\n\t\t\tissue(\n\t\t\t\t\"description_too_long\",\n\t\t\t\t\"error\",\n\t\t\t\tpath,\n\t\t\t\t\"Skill description must be <= 1024 chars.\",\n\t\t\t),\n\t\t);\n\t}\n\tif (!/\\b(use|when)\\b/i.test(value)) {\n\t\tissues.push(\n\t\t\tissue(\n\t\t\t\t\"description_missing_when\",\n\t\t\t\t\"warning\",\n\t\t\t\tpath,\n\t\t\t\t'Description should include when to use the skill, for example \"Use when ...\".',\n\t\t\t),\n\t\t);\n\t}\n\treturn issues;\n}\n\nfunction validateStringArrayField(\n\tfrontmatter: Record<string, unknown>,\n\tfield: string,\n\tpath: string,\n): SkillLintIssue[] {\n\tconst value = frontmatter[field];\n\tif (value === undefined) return [];\n\tif (Array.isArray(value)) {\n\t\tif (\n\t\t\tvalue.length === 0 ||\n\t\t\tvalue.some((entry) => typeof entry !== \"string\" || entry.trim() === \"\")\n\t\t) {\n\t\t\treturn [\n\t\t\t\tissue(\n\t\t\t\t\t\"invalid_string_list\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tpath,\n\t\t\t\t\t`${field} entries must all be non-empty strings.`,\n\t\t\t\t),\n\t\t\t];\n\t\t}\n\t\treturn [];\n\t}\n\tconst normalized = stringArrayValue(value);\n\tif (!normalized || normalized.length === 0) {\n\t\treturn [\n\t\t\tissue(\n\t\t\t\t\"invalid_string_list\",\n\t\t\t\t\"error\",\n\t\t\t\tpath,\n\t\t\t\t`${field} must be a non-empty string or list of strings.`,\n\t\t\t),\n\t\t];\n\t}\n\treturn [];\n}\n\nfunction isBooleanFrontmatterValue(value: unknown): boolean {\n\tif (typeof value === \"boolean\") return true;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.toLowerCase();\n\t\treturn normalized === \"true\" || normalized === \"false\";\n\t}\n\treturn false;\n}\n\nfunction validateBody(body: string, path: string): SkillLintIssue[] {\n\tconst issues: SkillLintIssue[] = [];\n\tconst lines = body.split(\"\\n\").length;\n\tif (lines > SKILL_BODY_MAX_LINES) {\n\t\tissues.push(\n\t\t\tissue(\n\t\t\t\t\"skill_oversize\",\n\t\t\t\t\"error\",\n\t\t\t\tpath,\n\t\t\t\t`SKILL.md body has ${lines} lines; maximum is ${SKILL_BODY_MAX_LINES}.`,\n\t\t\t),\n\t\t);\n\t}\n\tif (body.length > SKILL_BODY_MAX_CHARS) {\n\t\tissues.push(\n\t\t\tissue(\n\t\t\t\t\"skill_oversize\",\n\t\t\t\t\"error\",\n\t\t\t\tpath,\n\t\t\t\t`SKILL.md body has ${body.length} chars; maximum is ${SKILL_BODY_MAX_CHARS}.`,\n\t\t\t),\n\t\t);\n\t}\n\treturn issues;\n}\n\nfunction validateMcpJson(skillDir: string): SkillLintIssue[] {\n\tconst path = join(skillDir, \"mcp.json\");\n\tif (!existsSync(path)) return [];\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(readFileSync(path, \"utf8\"));\n\t} catch (error) {\n\t\treturn [\n\t\t\tissue(\n\t\t\t\t\"invalid_mcp_json\",\n\t\t\t\t\"error\",\n\t\t\t\tpath,\n\t\t\t\t`mcp.json must be valid JSON: ${\n\t\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\t\t}`,\n\t\t\t),\n\t\t];\n\t}\n\n\tif (!isRecord(parsed)) {\n\t\treturn [\n\t\t\tissue(\n\t\t\t\t\"invalid_mcp_json\",\n\t\t\t\t\"error\",\n\t\t\t\tpath,\n\t\t\t\t\"mcp.json must be an object keyed by server name.\",\n\t\t\t),\n\t\t];\n\t}\n\n\tconst issues: SkillLintIssue[] = [];\n\tfor (const [serverName, server] of Object.entries(parsed)) {\n\t\tconst serverPath = `${path}#${serverName}`;\n\t\tif (!isRecord(server)) {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"invalid_mcp_server\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tserverPath,\n\t\t\t\t\t\"MCP server config must be an object.\",\n\t\t\t\t),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof server.command !== \"string\" || server.command.trim() === \"\") {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"invalid_mcp_command\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tserverPath,\n\t\t\t\t\t\"MCP server requires a non-empty command.\",\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\t!Array.isArray(server.includeTools) ||\n\t\t\tserver.includeTools.length === 0\n\t\t) {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"mcp_tools_unfiltered\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tserverPath,\n\t\t\t\t\t\"MCP server must declare includeTools with at least one tool.\",\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (\n\t\t\tserver.includeTools.some(\n\t\t\t\t(tool) => typeof tool !== \"string\" || tool.trim() === \"\",\n\t\t\t)\n\t\t) {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"invalid_mcp_include_tools\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tserverPath,\n\t\t\t\t\t\"includeTools entries must be non-empty strings.\",\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\tserver.args !== undefined &&\n\t\t\t(!Array.isArray(server.args) ||\n\t\t\t\tserver.args.some((arg) => typeof arg !== \"string\"))\n\t\t) {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"invalid_mcp_args\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tserverPath,\n\t\t\t\t\t\"MCP args must be a list of strings.\",\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tif (server.env !== undefined && !isRecord(server.env)) {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"invalid_mcp_env\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tserverPath,\n\t\t\t\t\t\"MCP env must be an object of string values.\",\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\tisRecord(server.env) &&\n\t\t\tObject.values(server.env).some((value) => typeof value !== \"string\")\n\t\t) {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"invalid_mcp_env\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tserverPath,\n\t\t\t\t\t\"MCP env values must be strings.\",\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\treturn issues;\n}\n\nconst DEFAULT_WINDOWS_EXECUTABLE_EXTENSIONS = \".COM;.EXE;.BAT;.CMD;.PS1\";\n\nfunction windowsExecutableExtensions(\n\tpathExt = process.env.PATHEXT,\n): Set<string> {\n\treturn new Set(\n\t\t(pathExt || DEFAULT_WINDOWS_EXECUTABLE_EXTENSIONS)\n\t\t\t.split(\";\")\n\t\t\t.map((entry) => entry.trim().toUpperCase())\n\t\t\t.filter(Boolean),\n\t);\n}\n\nexport function isWindowsRunnableToolboxEntry(\n\tpath: string,\n\tpathExt = process.env.PATHEXT,\n): boolean {\n\tconst extension = extname(path).toUpperCase();\n\treturn Boolean(\n\t\textension && windowsExecutableExtensions(pathExt).has(extension),\n\t);\n}\n\nfunction hasWindowsRunnableToolboxCompanion(\n\tentry: string,\n\tdirectoryEntries: string[],\n\tpathExt = process.env.PATHEXT,\n): boolean {\n\tif (isWindowsRunnableToolboxEntry(entry, pathExt)) {\n\t\treturn false;\n\t}\n\tconst entryStem = basename(entry, extname(entry)).toLowerCase();\n\treturn directoryEntries.some((candidate) => {\n\t\tif (candidate === entry) {\n\t\t\treturn false;\n\t\t}\n\t\tif (!isWindowsRunnableToolboxEntry(candidate, pathExt)) {\n\t\t\treturn false;\n\t\t}\n\t\treturn basename(candidate, extname(candidate)).toLowerCase() === entryStem;\n\t});\n}\n\nexport function shouldUseShellForToolboxDescribe(\n\tplatform: NodeJS.Platform = process.platform,\n): boolean {\n\treturn platform === \"win32\";\n}\n\nexport function toolboxDescribeSpawnCommand(\n\tpath: string,\n\tplatform: NodeJS.Platform = process.platform,\n): string {\n\treturn platform === \"win32\" ? `\"${path}\"` : path;\n}\n\nasync function isExecutable(\n\tpath: string,\n\tplatform: NodeJS.Platform = process.platform,\n): Promise<boolean> {\n\tif (platform === \"win32\") {\n\t\treturn isWindowsRunnableToolboxEntry(path);\n\t}\n\ttry {\n\t\tawait access(path, constants.X_OK);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function validateToolbox(\n\tskillDir: string,\n\toptions: SkillLintOptions = {},\n): Promise<SkillLintIssue[]> {\n\tconst toolboxDir = join(skillDir, \"toolbox\");\n\tif (!existsSync(toolboxDir) || !statSync(toolboxDir).isDirectory()) return [];\n\n\tconst issues: SkillLintIssue[] = [];\n\tconst directoryEntries = readdirSync(toolboxDir);\n\tconst platform = options.platform ?? process.platform;\n\tlet toolboxEntryCount = 0;\n\tlet runnableEntryCount = 0;\n\tfor (const entry of directoryEntries) {\n\t\tif (entry.startsWith(\".\") || entry.toLowerCase() === \"readme.md\") continue;\n\t\tconst path = join(toolboxDir, entry);\n\t\tif (!statSync(path).isFile()) continue;\n\t\ttoolboxEntryCount += 1;\n\t\tif (platform !== \"win32\" && isWindowsRunnableToolboxEntry(path)) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (\n\t\t\tplatform === \"win32\" &&\n\t\t\t!isWindowsRunnableToolboxEntry(path) &&\n\t\t\thasWindowsRunnableToolboxCompanion(entry, directoryEntries)\n\t\t) {\n\t\t\tcontinue;\n\t\t}\n\t\tif (!(await isExecutable(path, platform))) {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"toolbox_not_executable\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tpath,\n\t\t\t\t\t\"Toolbox entries must be executable files.\",\n\t\t\t\t),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\t\trunnableEntryCount += 1;\n\t\tif (options.describeToolbox) {\n\t\t\tconst result = spawnSync(toolboxDescribeSpawnCommand(path, platform), {\n\t\t\t\tenv: { ...process.env, MAESTRO_TOOLBOX_ACTION: \"describe\" },\n\t\t\t\tencoding: \"utf8\",\n\t\t\t\tshell: shouldUseShellForToolboxDescribe(platform),\n\t\t\t\ttimeout: 5000,\n\t\t\t});\n\t\t\tif (result.status !== 0) {\n\t\t\t\tissues.push(\n\t\t\t\t\tissue(\n\t\t\t\t\t\t\"toolbox_describe_failed\",\n\t\t\t\t\t\t\"error\",\n\t\t\t\t\t\tpath,\n\t\t\t\t\t\t`Toolbox describe failed: ${result.stderr || result.stdout || \"non-zero exit\"}`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\tif (\n\t\ttoolboxEntryCount > 0 &&\n\t\trunnableEntryCount === 0 &&\n\t\tissues.length === 0\n\t) {\n\t\tissues.push(\n\t\t\tissue(\n\t\t\t\t\"toolbox_no_runnable_entries\",\n\t\t\t\t\"error\",\n\t\t\t\ttoolboxDir,\n\t\t\t\t\"Toolbox must include at least one executable entry runnable on the target platform.\",\n\t\t\t),\n\t\t);\n\t}\n\treturn issues;\n}\n\nexport async function lintSkillDirectory(\n\tskillDir: string,\n\toptions: SkillLintOptions = {},\n): Promise<SkillLintResult> {\n\tconst resolvedDir = resolve(skillDir);\n\tconst skillFile = findSkillMd(resolvedDir);\n\tconst issues: SkillLintIssue[] = [];\n\tif (!skillFile) {\n\t\treturn {\n\t\t\tpath: resolvedDir,\n\t\t\tissues: [\n\t\t\t\tissue(\n\t\t\t\t\t\"missing_skill_md\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tresolvedDir,\n\t\t\t\t\t\"Skill package requires SKILL.md.\",\n\t\t\t\t),\n\t\t\t],\n\t\t};\n\t}\n\n\ttry {\n\t\tconst { frontmatter, body } = parseFrontmatter(\n\t\t\treadFileSync(skillFile, \"utf8\"),\n\t\t);\n\t\tfor (const key of Object.keys(frontmatter)) {\n\t\t\tif (!FIELD_SET.has(key)) {\n\t\t\t\tissues.push(\n\t\t\t\t\tissue(\n\t\t\t\t\t\t\"unexpected_field\",\n\t\t\t\t\t\t\"error\",\n\t\t\t\t\t\tskillFile,\n\t\t\t\t\t\t`Unexpected frontmatter field '${key}'.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tissues.push(\n\t\t\t...validateSkillName(frontmatter.name, basename(resolvedDir), skillFile),\n\t\t);\n\t\tissues.push(...validateDescription(frontmatter.description, skillFile));\n\t\tfor (const field of [\"allowed-tools\", \"builtin-tools\"]) {\n\t\t\tissues.push(...validateStringArrayField(frontmatter, field, skillFile));\n\t\t}\n\t\tif (\n\t\t\tfrontmatter.compatibility !== undefined &&\n\t\t\ttypeof frontmatter.compatibility !== \"string\"\n\t\t) {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"invalid_compatibility\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tskillFile,\n\t\t\t\t\t\"compatibility must be a string.\",\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tif (\n\t\t\tfrontmatter.isolatedContext !== undefined &&\n\t\t\t!isBooleanFrontmatterValue(frontmatter.isolatedContext)\n\t\t) {\n\t\t\tissues.push(\n\t\t\t\tissue(\n\t\t\t\t\t\"invalid_isolated_context\",\n\t\t\t\t\t\"error\",\n\t\t\t\t\tskillFile,\n\t\t\t\t\t\"isolatedContext must be a boolean.\",\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\tissues.push(...validateBody(body, skillFile));\n\t} catch (error) {\n\t\tissues.push(\n\t\t\tissue(\n\t\t\t\t\"invalid_skill_md\",\n\t\t\t\t\"error\",\n\t\t\t\tskillFile,\n\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t),\n\t\t);\n\t}\n\n\tif (\n\t\texistsSync(join(resolvedDir, \"reference\")) &&\n\t\texistsSync(join(resolvedDir, \"references\"))\n\t) {\n\t\tissues.push(\n\t\t\tissue(\n\t\t\t\t\"duplicate_reference_dirs\",\n\t\t\t\t\"warning\",\n\t\t\t\tresolvedDir,\n\t\t\t\t\"Use either reference/ or references/; reference/ is preferred.\",\n\t\t\t),\n\t\t);\n\t}\n\tissues.push(...validateMcpJson(resolvedDir));\n\tissues.push(...(await validateToolbox(resolvedDir, options)));\n\treturn { path: resolvedDir, issues };\n}\n\nexport async function lintSkillPaths(\n\tpaths: string[],\n\toptions: SkillLintOptions = {},\n): Promise<SkillLintResult[]> {\n\tconst results: SkillLintResult[] = [];\n\tfor (const path of paths) {\n\t\tconst resolved = resolve(path);\n\t\tif (!existsSync(resolved)) {\n\t\t\tresults.push({\n\t\t\t\tpath: resolved,\n\t\t\t\tissues: [\n\t\t\t\t\tissue(\n\t\t\t\t\t\t\"missing_path\",\n\t\t\t\t\t\t\"error\",\n\t\t\t\t\t\tresolved,\n\t\t\t\t\t\t\"Skill path does not exist.\",\n\t\t\t\t\t),\n\t\t\t\t],\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tconst stat = statSync(resolved);\n\t\tif (!stat.isDirectory()) {\n\t\t\tresults.push({\n\t\t\t\tpath: resolved,\n\t\t\t\tissues: [\n\t\t\t\t\tissue(\n\t\t\t\t\t\t\"invalid_path\",\n\t\t\t\t\t\t\"error\",\n\t\t\t\t\t\tresolved,\n\t\t\t\t\t\t\"Skill path must be a directory.\",\n\t\t\t\t\t),\n\t\t\t\t],\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (findSkillMd(resolved)) {\n\t\t\tresults.push(await lintSkillDirectory(resolved, options));\n\t\t\tcontinue;\n\t\t}\n\t\tfor (const entry of readdirSync(resolved)) {\n\t\t\tconst child = join(resolved, entry);\n\t\t\tif (statSync(child).isDirectory()) {\n\t\t\t\tresults.push(await lintSkillDirectory(child, options));\n\t\t\t}\n\t\t}\n\t}\n\treturn results;\n}\n\nexport function formatSkillLintText(results: SkillLintResult[]): string {\n\tconst lines: string[] = [];\n\tlet errorCount = 0;\n\tlet warningCount = 0;\n\tfor (const result of results) {\n\t\tconst issues = result.issues;\n\t\tif (issues.length === 0) {\n\t\t\tlines.push(`OK ${result.path}`);\n\t\t\tcontinue;\n\t\t}\n\t\tlines.push(result.path);\n\t\tfor (const item of issues) {\n\t\t\tif (item.severity === \"error\") errorCount++;\n\t\t\tif (item.severity === \"warning\") warningCount++;\n\t\t\tlines.push(\n\t\t\t\t` ${item.severity.toUpperCase()} ${item.code}: ${item.message}`,\n\t\t\t);\n\t\t\tif (item.path !== result.path) {\n\t\t\t\tlines.push(` ${item.path}`);\n\t\t\t}\n\t\t}\n\t}\n\tlines.push(\"\");\n\tlines.push(\n\t\t`${errorCount} error${errorCount === 1 ? \"\" : \"s\"}, ${warningCount} warning${\n\t\t\twarningCount === 1 ? \"\" : \"s\"\n\t\t}`,\n\t);\n\treturn lines.join(\"\\n\");\n}\n\nexport function hasSkillLintErrors(results: SkillLintResult[]): boolean {\n\treturn results.some((result) =>\n\t\tresult.issues.some((item) => item.severity === \"error\"),\n\t);\n}\n\nexport function scaffoldSkill(\n\tbaseDir: string,\n\tname: string,\n\toptions: SkillScaffoldOptions = {},\n): SkillScaffoldResult {\n\tif (!SKILL_NAME_PATTERN.test(name) || name.length > 64) {\n\t\tthrow new Error(\n\t\t\t\"Skill name must use lowercase letters, numbers, and single hyphens.\",\n\t\t);\n\t}\n\tconst directory = resolve(baseDir, name);\n\tif (existsSync(directory) && !options.force) {\n\t\tthrow new Error(`Skill already exists at ${directory}`);\n\t}\n\n\tconst description =\n\t\toptions.description ??\n\t\t`${name.replace(/-/g, \" \")}. Use when a task needs this packaged workflow.`;\n\tconst files: string[] = [];\n\tmkdirSync(join(directory, \"reference\"), { recursive: true });\n\tmkdirSync(join(directory, \"scripts\"), { recursive: true });\n\tmkdirSync(join(directory, \"toolbox\"), { recursive: true });\n\n\tconst skillMd = join(directory, \"SKILL.md\");\n\tconst escapedDescription = description\n\t\t.replace(/\\\\/g, \"\\\\\\\\\")\n\t\t.replace(/\"/g, '\\\\\"');\n\twriteTextFileAtomic(\n\t\tskillMd,\n\t\t[\n\t\t\t\"---\",\n\t\t\t`name: ${name}`,\n\t\t\t`description: \"${escapedDescription}\"`,\n\t\t\t\"allowed-tools:\",\n\t\t\t\" - read\",\n\t\t\t\"builtin-tools:\",\n\t\t\t\" - read\",\n\t\t\t\"---\",\n\t\t\t\"\",\n\t\t\t`# ${name}`,\n\t\t\t\"\",\n\t\t\t\"## Workflow\",\n\t\t\t\"\",\n\t\t\t\"1. State the task-specific outcome.\",\n\t\t\t\"2. Load only the reference files needed for the request.\",\n\t\t\t\"3. Use bundled scripts or toolbox executables when they are more reliable than retyping long commands.\",\n\t\t\t\"\",\n\t\t\t\"## References\",\n\t\t\t\"\",\n\t\t\t\"- Read `reference/overview.md` when the user asks for implementation detail.\",\n\t\t\t\"\",\n\t\t].join(\"\\n\"),\n\t);\n\tfiles.push(skillMd);\n\n\tconst reference = join(directory, \"reference\", \"overview.md\");\n\twriteTextFileAtomic(\n\t\treference,\n\t\t`# ${name} Reference\\n\\nAdd deeper examples, protocol notes, and troubleshooting details here. Keep this out of SKILL.md until needed.\\n`,\n\t);\n\tfiles.push(reference);\n\n\tconst scriptsReadme = join(directory, \"scripts\", \"README.md\");\n\twriteTextFileAtomic(\n\t\tscriptsReadme,\n\t\t\"# Scripts\\n\\nPut deterministic helper scripts here. Agents should run these instead of retyping long workflows.\\n\",\n\t);\n\tfiles.push(scriptsReadme);\n\n\tconst toolboxReadme = join(directory, \"toolbox\", \"README.md\");\n\twriteTextFileAtomic(\n\t\ttoolboxReadme,\n\t\t\"# Toolbox\\n\\nPut executable Toolbox protocol commands here. Each executable should support `MAESTRO_TOOLBOX_ACTION=describe`.\\n\",\n\t);\n\tfiles.push(toolboxReadme);\n\n\tconst mcpJson = join(directory, \"mcp.json.example\");\n\twriteTextFileAtomic(\n\t\tmcpJson,\n\t\t'{\\n \"example-server\": {\\n \"command\": \"npx\",\\n \"args\": [\"-y\", \"example-mcp-server\"],\\n \"includeTools\": [\"example_tool\"]\\n }\\n}\\n',\n\t);\n\tfiles.push(mcpJson);\n\n\treturn { name, directory, files };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-activation.d.ts","sourceRoot":"","sources":["../../src/skills/runtime-activation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runtime-activation.d.ts","sourceRoot":"","sources":["../../src/skills/runtime-activation.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAI9D,MAAM,WAAW,sBAAsB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE;QACR,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,KAAK,EAAE;QACN,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,OAAO,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC;IACF,SAAS,EAAE;QACV,KAAK,EAAE,oBAAoB,EAAE,CAAC;QAC9B,WAAW,EAAE,+BAA+B,CAAC;KAC7C,CAAC;IACF,WAAW,EAAE;QACZ,OAAO,CAAC,EAAE,6BAA6B,CAAC;QACxC,GAAG,CAAC,EAAE,yBAAyB,CAAC;KAChC,CAAC;CACF;AAED,MAAM,WAAW,oBAAoB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAC5B;AAED,MAAM,WAAW,+BAA+B;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,6BAA6B;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,wBAAwB,EAAE,CAAC;IACpC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,yBAAyB;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,6BAA6B;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CAC3B;AA4ND;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAC1C,KAAK,EAAE,WAAW,EAClB,OAAO,GAAE,6BAAkC,GACzC,sBAAsB,CAsCxB"}
|