exonous 0.0.0-stage → 2.10.4
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/README.md +100 -2
- package/assets/THIRD-PARTY-NOTICES.md +29 -0
- package/assets/adapters/opencode/exonous.js +54 -0
- package/assets/agents/exo-backend.md +22 -0
- package/assets/agents/exo-cto.md +22 -0
- package/assets/agents/exo-data-ai.md +22 -0
- package/assets/agents/exo-designer.md +22 -0
- package/assets/agents/exo-devops.md +22 -0
- package/assets/agents/exo-frontend.md +22 -0
- package/assets/agents/exo-infra.md +22 -0
- package/assets/agents/exo-mobile.md +22 -0
- package/assets/agents/exo-pm.md +22 -0
- package/assets/agents/exo-qa.md +22 -0
- package/assets/agents/exo-researcher.md +22 -0
- package/assets/agents/exo-security.md +22 -0
- package/assets/agents/roster.json +209 -0
- package/assets/agents/taxis.js +189 -0
- package/assets/editors/cursor/frontend-skills.mdc +27 -0
- package/assets/editors/hooks/cursor/hooks.json +11 -0
- package/assets/machine/PR-TEMPLATE.md +21 -0
- package/assets/machine/hooks/anamnesis.cjs +61 -0
- package/assets/machine/hooks/ethos.cjs +48 -0
- package/assets/machine/hooks/kairos.cjs +46 -0
- package/assets/machine/hooks/lib/cli-options.cjs +133 -0
- package/assets/machine/hooks/lib/memory.cjs +488 -0
- package/assets/machine/hooks/lib/metron.cjs +52 -0
- package/assets/machine/hooks/lib/paths.cjs +99 -0
- package/assets/machine/hooks/lib/payload.cjs +81 -0
- package/assets/machine/hooks/lib/pr-template-validate.cjs +103 -0
- package/assets/machine/hooks/lib/release.cjs +58 -0
- package/assets/machine/hooks/lib/repo.cjs +138 -0
- package/assets/machine/hooks/lib/sanitize.cjs +37 -0
- package/assets/machine/hooks/lib/selfupdate.cjs +354 -0
- package/assets/machine/hooks/lib/shell.cjs +722 -0
- package/assets/machine/hooks/lib/template.cjs +70 -0
- package/assets/machine/hooks/lib/token.cjs +110 -0
- package/assets/machine/hooks/lib/validate-pr-body.cjs +21 -0
- package/assets/machine/hooks/pyle.cjs +302 -0
- package/assets/rules/nomos.md +59 -0
- package/assets/rules/praxis.md +38 -0
- package/assets/skills/code-review/SKILL.md +124 -0
- package/assets/skills/commit-changes/SKILL.md +49 -0
- package/assets/skills/deliver/SKILL.md +114 -0
- package/assets/skills/deliver/references/parallel.md +37 -0
- package/assets/skills/doc/SKILL.md +140 -0
- package/assets/skills/doc/doc.mjs +277 -0
- package/assets/skills/issue-board/SKILL.md +84 -0
- package/assets/skills/issue-board/board.mjs +389 -0
- package/assets/skills/issue-board/config.example.json +9 -0
- package/assets/skills/issue-board/render.py +189 -0
- package/assets/skills/make-pr/SKILL.md +24 -0
- package/assets/skills/native-ui/SKILL.md +67 -0
- package/assets/skills/native-ui/reference/apple.md +180 -0
- package/assets/skills/native-ui/reference/mobile-feel.md +221 -0
- package/assets/skills/native-ui/reference/swift.md +289 -0
- package/assets/skills/project-memory/SKILL.md +59 -0
- package/assets/skills/project-memory/config.example.json +4 -0
- package/assets/skills/project-memory/project-memory.mjs +478 -0
- package/assets/skills/security-review/SKILL.md +102 -0
- package/assets/skills/session-handoff/SKILL.md +23 -0
- package/assets/skills/session-handoff/config.example.json +3 -0
- package/assets/skills/ui-design/SKILL.md +75 -0
- package/assets/skills/ui-design/reference/adapt.md +151 -0
- package/assets/skills/ui-design/reference/adapt.native.md +35 -0
- package/assets/skills/ui-design/reference/android.md +50 -0
- package/assets/skills/ui-design/reference/animate.md +87 -0
- package/assets/skills/ui-design/reference/audit.md +76 -0
- package/assets/skills/ui-design/reference/audit.native.md +126 -0
- package/assets/skills/ui-design/reference/bolder.md +33 -0
- package/assets/skills/ui-design/reference/clarify.md +84 -0
- package/assets/skills/ui-design/reference/colorize.md +86 -0
- package/assets/skills/ui-design/reference/craft-floor.md +25 -0
- package/assets/skills/ui-design/reference/critique.md +345 -0
- package/assets/skills/ui-design/reference/degraded/asset-producer.md +35 -0
- package/assets/skills/ui-design/reference/degraded/documenter.md +23 -0
- package/assets/skills/ui-design/reference/degraded/finish-reviewer.md +43 -0
- package/assets/skills/ui-design/reference/degraded/manual-edit-applier.md +56 -0
- package/assets/skills/ui-design/reference/delight.md +63 -0
- package/assets/skills/ui-design/reference/distill.md +98 -0
- package/assets/skills/ui-design/reference/doctor.md +49 -0
- package/assets/skills/ui-design/reference/document.md +273 -0
- package/assets/skills/ui-design/reference/extract.md +52 -0
- package/assets/skills/ui-design/reference/harden.md +122 -0
- package/assets/skills/ui-design/reference/hooks.md +114 -0
- package/assets/skills/ui-design/reference/init.md +47 -0
- package/assets/skills/ui-design/reference/ios.md +55 -0
- package/assets/skills/ui-design/reference/layout.md +81 -0
- package/assets/skills/ui-design/reference/live-setup.md +75 -0
- package/assets/skills/ui-design/reference/live.md +326 -0
- package/assets/skills/ui-design/reference/new-work.md +350 -0
- package/assets/skills/ui-design/reference/onboard.md +85 -0
- package/assets/skills/ui-design/reference/operate.md +29 -0
- package/assets/skills/ui-design/reference/optimize.md +101 -0
- package/assets/skills/ui-design/reference/overdrive.md +83 -0
- package/assets/skills/ui-design/reference/polish.md +77 -0
- package/assets/skills/ui-design/reference/quieter.md +95 -0
- package/assets/skills/ui-design/reference/routing.md +37 -0
- package/assets/skills/ui-design/reference/shape.md +43 -0
- package/assets/skills/ui-design/reference/styles/brutalist.md +45 -0
- package/assets/skills/ui-design/reference/styles/design-md.md +70 -0
- package/assets/skills/ui-design/reference/styles/direction.md +95 -0
- package/assets/skills/ui-design/reference/styles/full-output.md +42 -0
- package/assets/skills/ui-design/reference/styles/minimalist.md +64 -0
- package/assets/skills/ui-design/reference/styles/premium.md +65 -0
- package/assets/skills/ui-design/reference/styles/redesign.md +59 -0
- package/assets/skills/ui-design/reference/typeset.md +73 -0
- package/assets/skills/ui-design/reference/visualize.md +156 -0
- package/assets/skills/ui-design/scripts/ENGINE-LICENSE +191 -0
- package/assets/skills/ui-design/scripts/VERSION +1 -0
- package/assets/skills/ui-design/scripts/bin/darwin-arm64/impeccable +0 -0
- package/assets/skills/ui-design/scripts/command-metadata.json +94 -0
- package/assets/skills/ui-design/scripts/data/font-index-failures.json +121 -0
- package/assets/skills/ui-design/scripts/data/font-index.json +1 -0
- package/assets/skills/ui-design/scripts/impeccable +206 -0
- package/assets/skills/ui-design/scripts/impeccable.cmd +214 -0
- package/assets/skills/ui-design/scripts/live-browser-dom.js +167 -0
- package/assets/skills/ui-design/scripts/live-browser-ignores.js +242 -0
- package/assets/skills/ui-design/scripts/live-browser-session.js +144 -0
- package/assets/skills/ui-design/scripts/live-browser.js +12990 -0
- package/assets/skills/ui-design/scripts/modern-screenshot.umd.js +14 -0
- package/assets/skills/ui-design/scripts/ui-design +6 -0
- package/assets/skills/ui-design/scripts/ui-design.cmd +3 -0
- package/assets/skills/ui-design/scripts/ui-design.mjs +124 -0
- package/assets/skills/ui-mockup/SKILL.md +68 -0
- package/assets/skills/ui-mockup/reference/brandkit.md +101 -0
- package/assets/skills/ui-mockup/reference/image-to-code.md +83 -0
- package/assets/skills/ui-mockup/reference/mobile-comps.md +94 -0
- package/assets/skills/ui-mockup/reference/web-comps.md +83 -0
- package/assets/skills/ui-motion/SKILL.md +112 -0
- package/assets/skills/ui-motion/reference/expo.md +224 -0
- package/assets/skills/ui-motion/reference/opportunities.md +81 -0
- package/assets/skills/ui-motion/reference/prototype.md +238 -0
- package/assets/skills/ui-motion/reference/review.md +163 -0
- package/assets/skills/ui-motion/reference/toasts.md +144 -0
- package/assets/skills/ui-motion/reference/ui-libraries.md +71 -0
- package/assets/skills/ui-motion/reference/vocabulary.md +130 -0
- package/assets/skills/ui-motion/reference/web.md +294 -0
- package/assets/skills/ui-patterns/SKILL.md +105 -0
- package/assets/skills/ui-patterns/references/stacks/html-tailwind.md +40 -0
- package/assets/skills/ui-patterns/references/stacks/nextjs.md +52 -0
- package/assets/skills/ui-patterns/references/stacks/nuxt.md +100 -0
- package/assets/skills/ui-patterns/references/stacks/react-native.md +48 -0
- package/assets/skills/ui-patterns/references/stacks/react.md +49 -0
- package/assets/skills/ui-patterns/references/stacks/shadcn.md +57 -0
- package/assets/skills/ui-patterns/references/stacks/vue.md +37 -0
- package/assets/techne/.claude-plugin/marketplace.json +31 -0
- package/assets/techne/.claude-plugin/plugin.json +24 -0
- package/assets/techne/.mcp.json +8 -0
- package/assets/techne/commands/build-fix.md +48 -0
- package/assets/techne/commands/refactor-clean.md +46 -0
- package/assets/techne/commands/test-coverage.md +42 -0
- package/assets/techne/hooks/hooks.json +49 -0
- package/assets/techne/rules/angular/coding-style.md +49 -0
- package/assets/techne/rules/angular/hooks.md +23 -0
- package/assets/techne/rules/angular/patterns.md +48 -0
- package/assets/techne/rules/angular/security.md +26 -0
- package/assets/techne/rules/angular/testing.md +46 -0
- package/assets/techne/rules/arkts/coding-style.md +63 -0
- package/assets/techne/rules/arkts/hooks.md +38 -0
- package/assets/techne/rules/arkts/patterns.md +42 -0
- package/assets/techne/rules/arkts/security.md +35 -0
- package/assets/techne/rules/arkts/testing.md +39 -0
- package/assets/techne/rules/common/agents.md +6 -0
- package/assets/techne/rules/common/code-review.md +15 -0
- package/assets/techne/rules/common/coding-style.md +13 -0
- package/assets/techne/rules/common/development-workflow.md +5 -0
- package/assets/techne/rules/common/git-workflow.md +30 -0
- package/assets/techne/rules/common/hooks.md +7 -0
- package/assets/techne/rules/common/patterns.md +3 -0
- package/assets/techne/rules/common/performance.md +3 -0
- package/assets/techne/rules/common/security.md +5 -0
- package/assets/techne/rules/common/testing.md +3 -0
- package/assets/techne/rules/cpp/coding-style.md +31 -0
- package/assets/techne/rules/cpp/hooks.md +26 -0
- package/assets/techne/rules/cpp/patterns.md +31 -0
- package/assets/techne/rules/cpp/security.md +37 -0
- package/assets/techne/rules/cpp/testing.md +31 -0
- package/assets/techne/rules/csharp/coding-style.md +30 -0
- package/assets/techne/rules/csharp/hooks.md +24 -0
- package/assets/techne/rules/csharp/patterns.md +28 -0
- package/assets/techne/rules/csharp/security.md +32 -0
- package/assets/techne/rules/csharp/testing.md +27 -0
- package/assets/techne/rules/dart/coding-style.md +47 -0
- package/assets/techne/rules/dart/hooks.md +26 -0
- package/assets/techne/rules/dart/patterns.md +38 -0
- package/assets/techne/rules/dart/security.md +44 -0
- package/assets/techne/rules/dart/testing.md +39 -0
- package/assets/techne/rules/fsharp/coding-style.md +34 -0
- package/assets/techne/rules/fsharp/hooks.md +25 -0
- package/assets/techne/rules/fsharp/patterns.md +43 -0
- package/assets/techne/rules/fsharp/security.md +32 -0
- package/assets/techne/rules/fsharp/testing.md +27 -0
- package/assets/techne/rules/golang/coding-style.md +30 -0
- package/assets/techne/rules/golang/hooks.md +17 -0
- package/assets/techne/rules/golang/patterns.md +43 -0
- package/assets/techne/rules/golang/security.md +33 -0
- package/assets/techne/rules/golang/testing.md +20 -0
- package/assets/techne/rules/java/coding-style.md +51 -0
- package/assets/techne/rules/java/hooks.md +18 -0
- package/assets/techne/rules/java/patterns.md +55 -0
- package/assets/techne/rules/java/security.md +33 -0
- package/assets/techne/rules/java/testing.md +33 -0
- package/assets/techne/rules/kotlin/coding-style.md +50 -0
- package/assets/techne/rules/kotlin/hooks.md +17 -0
- package/assets/techne/rules/kotlin/patterns.md +44 -0
- package/assets/techne/rules/kotlin/security.md +34 -0
- package/assets/techne/rules/kotlin/testing.md +38 -0
- package/assets/techne/rules/nuxt/coding-style.md +20 -0
- package/assets/techne/rules/nuxt/hooks.md +16 -0
- package/assets/techne/rules/nuxt/patterns.md +46 -0
- package/assets/techne/rules/nuxt/security.md +19 -0
- package/assets/techne/rules/nuxt/testing.md +15 -0
- package/assets/techne/rules/perl/coding-style.md +33 -0
- package/assets/techne/rules/perl/hooks.md +22 -0
- package/assets/techne/rules/perl/patterns.md +43 -0
- package/assets/techne/rules/perl/security.md +39 -0
- package/assets/techne/rules/perl/testing.md +42 -0
- package/assets/techne/rules/php/coding-style.md +30 -0
- package/assets/techne/rules/php/hooks.md +24 -0
- package/assets/techne/rules/php/patterns.md +26 -0
- package/assets/techne/rules/php/security.md +27 -0
- package/assets/techne/rules/php/testing.md +28 -0
- package/assets/techne/rules/python/coding-style.md +38 -0
- package/assets/techne/rules/python/fastapi.md +57 -0
- package/assets/techne/rules/python/hooks.md +19 -0
- package/assets/techne/rules/python/patterns.md +37 -0
- package/assets/techne/rules/python/security.md +26 -0
- package/assets/techne/rules/python/testing.md +32 -0
- package/assets/techne/rules/react/coding-style.md +24 -0
- package/assets/techne/rules/react/hooks.md +62 -0
- package/assets/techne/rules/react/patterns.md +48 -0
- package/assets/techne/rules/react/security.md +45 -0
- package/assets/techne/rules/react/testing.md +42 -0
- package/assets/techne/rules/react-native/accessibility.md +14 -0
- package/assets/techne/rules/react-native/coding-style.md +16 -0
- package/assets/techne/rules/react-native/hooks.md +16 -0
- package/assets/techne/rules/react-native/patterns.md +18 -0
- package/assets/techne/rules/react-native/performance.md +14 -0
- package/assets/techne/rules/react-native/production-readiness.md +16 -0
- package/assets/techne/rules/react-native/security.md +16 -0
- package/assets/techne/rules/react-native/testing.md +14 -0
- package/assets/techne/rules/ruby/coding-style.md +40 -0
- package/assets/techne/rules/ruby/hooks.md +33 -0
- package/assets/techne/rules/ruby/patterns.md +33 -0
- package/assets/techne/rules/ruby/security.md +39 -0
- package/assets/techne/rules/ruby/testing.md +35 -0
- package/assets/techne/rules/rust/coding-style.md +41 -0
- package/assets/techne/rules/rust/hooks.md +16 -0
- package/assets/techne/rules/rust/patterns.md +42 -0
- package/assets/techne/rules/rust/security.md +33 -0
- package/assets/techne/rules/rust/testing.md +30 -0
- package/assets/techne/rules/swift/coding-style.md +30 -0
- package/assets/techne/rules/swift/hooks.md +20 -0
- package/assets/techne/rules/swift/patterns.md +30 -0
- package/assets/techne/rules/swift/security.md +22 -0
- package/assets/techne/rules/swift/testing.md +28 -0
- package/assets/techne/rules/typescript/coding-style.md +38 -0
- package/assets/techne/rules/typescript/hooks.md +14 -0
- package/assets/techne/rules/typescript/patterns.md +12 -0
- package/assets/techne/rules/typescript/security.md +14 -0
- package/assets/techne/rules/typescript/testing.md +12 -0
- package/assets/techne/rules/vue/coding-style.md +19 -0
- package/assets/techne/rules/vue/hooks.md +13 -0
- package/assets/techne/rules/vue/patterns.md +29 -0
- package/assets/techne/rules/vue/security.md +11 -0
- package/assets/techne/rules/vue/testing.md +11 -0
- package/assets/techne/rules/web/coding-style.md +25 -0
- package/assets/techne/rules/web/design-quality.md +21 -0
- package/assets/techne/rules/web/hooks.md +39 -0
- package/assets/techne/rules/web/patterns.md +23 -0
- package/assets/techne/rules/web/performance.md +25 -0
- package/assets/techne/rules/web/security.md +23 -0
- package/assets/techne/rules/web/testing.md +21 -0
- package/assets/techne/scripts/hooks/config-guard.js +50 -0
- package/assets/techne/scripts/hooks/edit-tracker.js +26 -0
- package/assets/techne/scripts/hooks/lib/shell.js +204 -0
- package/assets/techne/scripts/hooks/no-verify-guard.js +205 -0
- package/assets/techne/scripts/hooks/run.js +92 -0
- package/assets/techne/scripts/hooks/stop-checks.js +136 -0
- package/assets/techne/skills/angular/SKILL.md +34 -0
- package/assets/techne/skills/angular/reference/components-and-templates.md +63 -0
- package/assets/techne/skills/angular/reference/dependency-injection.md +44 -0
- package/assets/techne/skills/angular/reference/forms.md +97 -0
- package/assets/techne/skills/angular/reference/routing.md +50 -0
- package/assets/techne/skills/angular/reference/signals-and-state.md +59 -0
- package/assets/techne/skills/angular/reference/styling-motion-a11y.md +54 -0
- package/assets/techne/skills/angular/reference/testing.md +52 -0
- package/assets/techne/skills/angular/reference/tooling.md +31 -0
- package/assets/techne/skills/cpp/SKILL.md +27 -0
- package/assets/techne/skills/cpp/reference/coding-standards.md +160 -0
- package/assets/techne/skills/databases/SKILL.md +35 -0
- package/assets/techne/skills/databases/reference/clickhouse.md +102 -0
- package/assets/techne/skills/databases/reference/migrations.md +94 -0
- package/assets/techne/skills/databases/reference/mysql.md +101 -0
- package/assets/techne/skills/databases/reference/postgres.md +72 -0
- package/assets/techne/skills/databases/reference/prisma.md +105 -0
- package/assets/techne/skills/databases/reference/redis.md +108 -0
- package/assets/techne/skills/delivery/SKILL.md +35 -0
- package/assets/techne/skills/delivery/reference/deployment-patterns.md +58 -0
- package/assets/techne/skills/delivery/reference/docker-patterns.md +77 -0
- package/assets/techne/skills/delivery/reference/git-workflow.md +64 -0
- package/assets/techne/skills/delivery/reference/github-ops.md +67 -0
- package/assets/techne/skills/delivery/reference/jira-integration.md +53 -0
- package/assets/techne/skills/delivery/reference/kubernetes-patterns.md +67 -0
- package/assets/techne/skills/dotnet/SKILL.md +27 -0
- package/assets/techne/skills/dotnet/reference/dotnet-core.md +131 -0
- package/assets/techne/skills/flutter/SKILL.md +29 -0
- package/assets/techne/skills/flutter/reference/code-review.md +76 -0
- package/assets/techne/skills/flutter/reference/patterns.md +201 -0
- package/assets/techne/skills/go/SKILL.md +28 -0
- package/assets/techne/skills/go/reference/patterns.md +87 -0
- package/assets/techne/skills/go/reference/testing.md +142 -0
- package/assets/techne/skills/java/SKILL.md +29 -0
- package/assets/techne/skills/java/reference/java-standards.md +117 -0
- package/assets/techne/skills/java/reference/springboot.md +108 -0
- package/assets/techne/skills/kotlin/SKILL.md +35 -0
- package/assets/techne/skills/kotlin/reference/android-clean-architecture.md +115 -0
- package/assets/techne/skills/kotlin/reference/compose-multiplatform-patterns.md +113 -0
- package/assets/techne/skills/kotlin/reference/kotlin-coroutines-flows.md +93 -0
- package/assets/techne/skills/kotlin/reference/kotlin-patterns.md +74 -0
- package/assets/techne/skills/kotlin/reference/kotlin-testing.md +115 -0
- package/assets/techne/skills/ml/SKILL.md +34 -0
- package/assets/techne/skills/ml/reference/ai-regression-testing.md +99 -0
- package/assets/techne/skills/ml/reference/cost-aware-llm-pipeline.md +133 -0
- package/assets/techne/skills/ml/reference/eval-harness.md +94 -0
- package/assets/techne/skills/ml/reference/mle-workflow.md +177 -0
- package/assets/techne/skills/ml/reference/prompt-optimizer.md +107 -0
- package/assets/techne/skills/ml/reference/pytorch-patterns.md +164 -0
- package/assets/techne/skills/php/SKILL.md +27 -0
- package/assets/techne/skills/php/reference/laravel.md +142 -0
- package/assets/techne/skills/python/SKILL.md +33 -0
- package/assets/techne/skills/python/reference/django.md +104 -0
- package/assets/techne/skills/python/reference/fastapi.md +118 -0
- package/assets/techne/skills/python/reference/python-core.md +88 -0
- package/assets/techne/skills/python/reference/python-testing.md +105 -0
- package/assets/techne/skills/quality/SKILL.md +34 -0
- package/assets/techne/skills/quality/reference/benchmark.md +55 -0
- package/assets/techne/skills/quality/reference/browser-qa.md +60 -0
- package/assets/techne/skills/quality/reference/coding-standards.md +88 -0
- package/assets/techne/skills/quality/reference/e2e-testing.md +99 -0
- package/assets/techne/skills/quality/reference/tdd-workflow.md +89 -0
- package/assets/techne/skills/quality/reference/verification-loop.md +80 -0
- package/assets/techne/skills/react/SKILL.md +30 -0
- package/assets/techne/skills/react/reference/nextjs-turbopack.md +42 -0
- package/assets/techne/skills/react/reference/react-patterns.md +139 -0
- package/assets/techne/skills/react/reference/react-performance.md +101 -0
- package/assets/techne/skills/react/reference/react-testing.md +139 -0
- package/assets/techne/skills/react-native/SKILL.md +28 -0
- package/assets/techne/skills/react-native/reference/expo-patterns.md +196 -0
- package/assets/techne/skills/research/SKILL.md +35 -0
- package/assets/techne/skills/research/reference/architecture-decision-records.md +65 -0
- package/assets/techne/skills/research/reference/codebase-onboarding.md +44 -0
- package/assets/techne/skills/research/reference/deep-research.md +50 -0
- package/assets/techne/skills/research/reference/iterative-retrieval.md +62 -0
- package/assets/techne/skills/research/reference/product-lens.md +38 -0
- package/assets/techne/skills/research/reference/search-first.md +50 -0
- package/assets/techne/skills/rust/SKILL.md +28 -0
- package/assets/techne/skills/rust/reference/patterns.md +108 -0
- package/assets/techne/skills/rust/reference/testing.md +142 -0
- package/assets/techne/skills/services/SKILL.md +32 -0
- package/assets/techne/skills/services/reference/api-contracts.md +139 -0
- package/assets/techne/skills/services/reference/backend-layers.md +95 -0
- package/assets/techne/skills/services/reference/errors-and-resilience.md +146 -0
- package/assets/techne/skills/services/reference/hexagonal-boundaries.md +93 -0
- package/assets/techne/skills/services/reference/mcp-servers.md +50 -0
- package/assets/techne/skills/services/reference/nestjs.md +96 -0
- package/assets/techne/skills/swift/SKILL.md +29 -0
- package/assets/techne/skills/swift/reference/concurrency.md +83 -0
- package/assets/techne/skills/swift/reference/swiftui.md +139 -0
- package/assets/techne/skills/vue/SKILL.md +29 -0
- package/assets/techne/skills/vue/reference/nuxt4-patterns.md +90 -0
- package/assets/techne/skills/vue/reference/ui-to-vue.md +90 -0
- package/assets/techne/skills/vue/reference/vue-patterns.md +151 -0
- package/assets/techne/skills/web/SKILL.md +30 -0
- package/assets/techne/skills/web/reference/bun-runtime.md +55 -0
- package/assets/techne/skills/web/reference/frontend-patterns.md +54 -0
- package/assets/techne/skills/web/reference/seo.md +77 -0
- package/assets/techne/skills/web/reference/vite-patterns.md +96 -0
- package/bin/native.cjs +30 -0
- package/native/aarch64-apple-darwin/exonous +0 -0
- package/native/aarch64-unknown-linux-gnu/exonous +0 -0
- package/native/x86_64-apple-darwin/exonous +0 -0
- package/native/x86_64-pc-windows-msvc/exonous.exe +0 -0
- package/native/x86_64-unknown-linux-gnu/exonous +0 -0
- package/package.json +1 -6
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Self-contained: copied to ~/.claude/exonous/hooks/lib/, node builtins only. One state dir serves every tool.
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const { execFileSync } = require('child_process');
|
|
8
|
+
const { exoDir, stateDir, redirectedHome, testMode, foreignOwner } = require('./paths.cjs');
|
|
9
|
+
const { RELEASE_REF, compareVersions, listReleases } = require('./release.cjs');
|
|
10
|
+
const repo = require('./repo.cjs');
|
|
11
|
+
|
|
12
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
13
|
+
const LOCK_STALE_MS = 30 * 60 * 1000;
|
|
14
|
+
const LOG_MAX = 64 * 1024;
|
|
15
|
+
const NOTE_MAX = 200;
|
|
16
|
+
// Fixed on purpose: install.json `source` is informational and never executed.
|
|
17
|
+
const SOURCE = 'https://github.com/zaqueu-1/exonous.git';
|
|
18
|
+
const SLUG = 'zaqueu-1/exonous';
|
|
19
|
+
const PMS = ['npm', 'pnpm', 'bun'];
|
|
20
|
+
const SHA = /^[0-9a-f]{40}$/;
|
|
21
|
+
const VERSION = /^\d+\.\d+\.\d+$/;
|
|
22
|
+
|
|
23
|
+
const NOTES = {
|
|
24
|
+
updated: (from, to) => `exonous updated v${from} → v${to} (restart to load new hooks)`,
|
|
25
|
+
failed: (to) => `exonous update to v${to} failed — run \`exonous update\` to see why`,
|
|
26
|
+
major: (version) => `exonous v${version} is a new major — run \`exonous update --major\``,
|
|
27
|
+
tagMoved: (version) => `exonous: release tag v${version} moved since install — run \`exonous doctor\``,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const statePath = (name) => path.join(stateDir(), name);
|
|
31
|
+
// Another uid (root in a user's session) owns the exonous dir: read nothing, write nothing.
|
|
32
|
+
const notOwner = () => foreignOwner(exoDir()) !== null || foreignOwner(stateDir()) !== null;
|
|
33
|
+
const parts = (version) => String(version).split('.').map(Number);
|
|
34
|
+
|
|
35
|
+
function readJson(file) {
|
|
36
|
+
try {
|
|
37
|
+
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function writeState(name, content) {
|
|
44
|
+
fs.mkdirSync(stateDir(), { recursive: true, mode: 0o700 });
|
|
45
|
+
fs.writeFileSync(statePath(name), content, { mode: 0o600 });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Detailed errors stay in state/update.log (64 KB, one rotation), never in the note. */
|
|
49
|
+
function logLine(text) {
|
|
50
|
+
try {
|
|
51
|
+
fs.mkdirSync(stateDir(), { recursive: true, mode: 0o700 });
|
|
52
|
+
const file = statePath('update.log');
|
|
53
|
+
const line = `${new Date().toISOString()} ${flatten(text).slice(0, 4096)}\n`;
|
|
54
|
+
let size = 0;
|
|
55
|
+
try {
|
|
56
|
+
size = fs.statSync(file).size;
|
|
57
|
+
} catch {
|
|
58
|
+
// first line
|
|
59
|
+
}
|
|
60
|
+
if (size + Buffer.byteLength(line) > LOG_MAX) fs.renameSync(file, `${file}.1`);
|
|
61
|
+
fs.appendFileSync(file, line, { mode: 0o600 });
|
|
62
|
+
} catch {
|
|
63
|
+
// logging must never break an update
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const installFile = () => path.join(exoDir(), 'install.json');
|
|
68
|
+
const readInstall = () => readJson(installFile());
|
|
69
|
+
|
|
70
|
+
function patchInstall(fields) {
|
|
71
|
+
const file = installFile();
|
|
72
|
+
const tmp = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
73
|
+
fs.writeFileSync(tmp, `${JSON.stringify({ ...readInstall(), ...fields }, null, 2)}\n`, { mode: 0o600, flag: 'wx' });
|
|
74
|
+
fs.renameSync(tmp, file);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** @returns {string | null} why automatic updates are off */
|
|
78
|
+
function optedOut(env = process.env) {
|
|
79
|
+
if (env.EXONOUS_NO_UPDATE && env.EXONOUS_NO_UPDATE !== '0') return 'EXONOUS_NO_UPDATE';
|
|
80
|
+
if (env.CI || env.CONTINUOUS_INTEGRATION) return 'CI';
|
|
81
|
+
if (readJson(path.join(exoDir(), 'config.json'))?.autoUpdate === false) return 'config.json autoUpdate:false';
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** @returns {number | null} ms timestamp of the last update check */
|
|
86
|
+
function lastCheck() {
|
|
87
|
+
try {
|
|
88
|
+
return fs.statSync(statePath('last-check')).mtimeMs;
|
|
89
|
+
} catch {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// A last-check in the future (clock moved back) counts as due.
|
|
95
|
+
function due({ now = Date.now() } = {}) {
|
|
96
|
+
const last = lastCheck();
|
|
97
|
+
return last === null || now - last >= DAY_MS || now < last;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function markChecked({ now = Date.now() } = {}) {
|
|
101
|
+
if (notOwner()) return false;
|
|
102
|
+
writeState('last-check', `${now}\n`);
|
|
103
|
+
const t = now / 1000;
|
|
104
|
+
fs.utimesSync(statePath('last-check'), t, t);
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** One printable line: whitespace collapsed, control and bidi characters dropped. */
|
|
109
|
+
const flatten = (text) => String(text)
|
|
110
|
+
.replace(/[\u0000-\u001f\u007f-\u009f]+/g, ' ')
|
|
111
|
+
.replace(/[\u200b-\u200f\u202a-\u202e\u2066-\u2069\ufeff]/g, '')
|
|
112
|
+
.replace(/\s+/g, ' ')
|
|
113
|
+
.trim();
|
|
114
|
+
|
|
115
|
+
function cleanNote(text) {
|
|
116
|
+
const flat = flatten(text);
|
|
117
|
+
return flat.length > NOTE_MAX ? `${flat.slice(0, NOTE_MAX - 1)}…` : flat;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function writeNote(text) {
|
|
121
|
+
writeState('note', `${cleanNote(text)}\n`);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Note left for the next session start, removed once read. */
|
|
125
|
+
function takeNote() {
|
|
126
|
+
if (notOwner()) return '';
|
|
127
|
+
try {
|
|
128
|
+
const note = cleanNote(fs.readFileSync(statePath('note'), 'utf8'));
|
|
129
|
+
fs.rmSync(statePath('note'), { force: true });
|
|
130
|
+
return note;
|
|
131
|
+
} catch {
|
|
132
|
+
return '';
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** @returns {{ version: string, expected: string, actual: string } | null} set when an installed release tag moved */
|
|
137
|
+
function tagWarning() {
|
|
138
|
+
return readJson(statePath('tag-moved.json'));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Compares install.json with the release tags; changes nothing.
|
|
143
|
+
* @param {{ major?: boolean }} [options] major: also consider a newer major.
|
|
144
|
+
*/
|
|
145
|
+
function check({ major = false } = {}) {
|
|
146
|
+
const info = readInstall();
|
|
147
|
+
if (!info?.version) return { status: 'not-installed' };
|
|
148
|
+
if (info.ref && !RELEASE_REF.test(info.ref)) return { status: 'pinned', from: info.version, ref: info.ref };
|
|
149
|
+
const from = info.version;
|
|
150
|
+
// Repo mode follows the repo's own dependency spec (source and ref), never install.json.
|
|
151
|
+
const source = repo.repoSource(info);
|
|
152
|
+
if (source && (repo.pinned(source.ref) || !source.url)) return { status: 'pinned', from, ref: `${source.dep.name}@${source.dep.spec} in ${source.root}`, repo: source.root };
|
|
153
|
+
const releases = listReleases(source ? source.url : SOURCE).filter((r) => SHA.test(r.sha));
|
|
154
|
+
const sameMajor = releases.filter((r) => r.parts[0] === parts(from)[0]).pop();
|
|
155
|
+
const top = releases[releases.length - 1];
|
|
156
|
+
const result = { status: 'current', from };
|
|
157
|
+
const newer = (r) => r && compareVersions(r.parts, parts(from)) > 0;
|
|
158
|
+
if (newer(top) && top.parts[0] !== parts(from)[0]) result.newMajor = top.version;
|
|
159
|
+
const installedTag = releases.find((r) => r.version === from);
|
|
160
|
+
if (installedTag && info.tagSha && installedTag.sha !== info.tagSha) {
|
|
161
|
+
result.tagMoved = { version: from, expected: info.tagSha, actual: installedTag.sha };
|
|
162
|
+
}
|
|
163
|
+
if (installedTag && !info.tagSha) result.tagSha = installedTag.sha;
|
|
164
|
+
const target = major && result.newMajor ? top : sameMajor;
|
|
165
|
+
if (!releases.length) return { ...result, status: 'no-release' };
|
|
166
|
+
if (newer(target)) return { ...result, status: 'available', to: target.version, sha: target.sha };
|
|
167
|
+
return { ...result, to: from };
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const lockFile = () => statePath('update.lock');
|
|
171
|
+
|
|
172
|
+
function lockAcquire() {
|
|
173
|
+
fs.mkdirSync(stateDir(), { recursive: true, mode: 0o700 });
|
|
174
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
175
|
+
try {
|
|
176
|
+
fs.closeSync(fs.openSync(lockFile(), 'wx', 0o600));
|
|
177
|
+
fs.writeFileSync(lockFile(), `${process.pid}\n`);
|
|
178
|
+
return true;
|
|
179
|
+
} catch (err) {
|
|
180
|
+
if (err.code !== 'EEXIST') throw err;
|
|
181
|
+
try {
|
|
182
|
+
if (Date.now() - fs.statSync(lockFile()).mtimeMs < LOCK_STALE_MS) return false;
|
|
183
|
+
fs.rmSync(lockFile(), { force: true });
|
|
184
|
+
} catch {
|
|
185
|
+
// gone between the open and the stat: retry
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Keeps a long update from looking stale to a concurrent session.
|
|
193
|
+
function lockTouch() {
|
|
194
|
+
try {
|
|
195
|
+
const t = Date.now() / 1000;
|
|
196
|
+
fs.utimesSync(lockFile(), t, t);
|
|
197
|
+
} catch {
|
|
198
|
+
// lock removed underneath: the update still finishes
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** The only spec ever installed: the fixed repo at the tag's commit. */
|
|
203
|
+
function spec(sha) {
|
|
204
|
+
if (!SHA.test(sha)) throw new Error(`refusing to install: "${sha}" is not a commit sha`);
|
|
205
|
+
return `github:${SLUG}#${sha}`;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/** pm binary recorded at install when it still looks like that pm; else the name on PATH. */
|
|
209
|
+
function pmCommand(info) {
|
|
210
|
+
const pm = PMS.includes(info.pm) ? info.pm : 'npm';
|
|
211
|
+
const recorded = info.pmPath;
|
|
212
|
+
const ok = typeof recorded === 'string' && path.isAbsolute(recorded) && !/["%]/.test(recorded)
|
|
213
|
+
&& path.basename(recorded).replace(/\.(cmd|exe)$/i, '') === pm && fs.existsSync(recorded);
|
|
214
|
+
return { pm, bin: ok ? recorded : pm };
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// win32 needs a shell for .cmd shims: command quoted, args are fixed literals or a validated sha spec.
|
|
218
|
+
function pmRun({ bin }, args) {
|
|
219
|
+
const win = process.platform === 'win32';
|
|
220
|
+
return execFileSync(win ? `"${bin}"` : bin, args, {
|
|
221
|
+
encoding: 'utf8', timeout: 10 * 60 * 1000, stdio: ['ignore', 'pipe', 'pipe'], shell: win, windowsHide: true,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function globalRoot(cmd) {
|
|
226
|
+
if (cmd.pm === 'bun') return path.join(process.env.BUN_INSTALL || path.join(os.homedir(), '.bun'), 'install', 'global', 'node_modules', 'exonous');
|
|
227
|
+
const out = pmRun(cmd, ['root', '-g']).trim().split(/\r?\n/).pop();
|
|
228
|
+
if (!path.isAbsolute(out)) throw new Error(`${cmd.pm} root -g gave no absolute path`);
|
|
229
|
+
return path.join(out, 'exonous');
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Checks the installed package is the release: name, version, and the commit wherever the pm records it.
|
|
234
|
+
* npm: <global>/node_modules/.package-lock.json; pnpm: <global>/pnpm-lock.yaml; bun: <global>/bun.lock. None → name + version only.
|
|
235
|
+
*/
|
|
236
|
+
function verifyPackage(root, { to, sha }) {
|
|
237
|
+
const pkg = readJson(path.join(root, 'package.json'));
|
|
238
|
+
if (pkg?.name !== 'exonous') throw new Error(`${root} is not the exonous package`);
|
|
239
|
+
if (pkg.version !== to) throw new Error(`${root} holds v${pkg.version || '?'}, expected v${to}`);
|
|
240
|
+
if (pkg.gitHead && pkg.gitHead !== sha) throw new Error(`${root} was built from ${pkg.gitHead}, expected ${sha}`);
|
|
241
|
+
const nm = path.dirname(root);
|
|
242
|
+
const locks = [path.join(nm, '.package-lock.json'), path.join(path.dirname(nm), 'pnpm-lock.yaml'), path.join(path.dirname(nm), 'bun.lock')]
|
|
243
|
+
.map((file) => {
|
|
244
|
+
try {
|
|
245
|
+
return fs.readFileSync(file, 'utf8');
|
|
246
|
+
} catch {
|
|
247
|
+
return '';
|
|
248
|
+
}
|
|
249
|
+
})
|
|
250
|
+
.filter((text) => text.includes(SLUG));
|
|
251
|
+
if (locks.length && !locks.some((text) => text.includes(sha))) throw new Error(`the ${path.basename(nm)} lockfile does not pin exonous to ${sha}`);
|
|
252
|
+
return { commitVerified: locks.length > 0 };
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// A redirected home must not reach the real global pm prefix; only test mode may use its PATH shims.
|
|
256
|
+
const globalAllowed = () => !redirectedHome() || (testMode() && process.env.EXONOUS_UPDATE_TEST_PM === '1');
|
|
257
|
+
|
|
258
|
+
const devCheckout = (info) => typeof info.packageRoot === 'string' && fs.existsSync(path.join(info.packageRoot, '.git'));
|
|
259
|
+
|
|
260
|
+
const detail = (err) => flatten(`${err.message || err}${err.stderr ? ` | ${err.stderr}` : ''}`).slice(0, 4000);
|
|
261
|
+
|
|
262
|
+
/** Global mode: the fixed source at the tag's commit, through the recorded pm. Returns the new package root. */
|
|
263
|
+
function installGlobal(info, decision) {
|
|
264
|
+
const cmd = pmCommand(info);
|
|
265
|
+
const target = spec(decision.sha);
|
|
266
|
+
pmRun(cmd, cmd.pm === 'npm' ? ['i', '-g', '--no-audit', '--no-fund', target] : ['add', '-g', target]);
|
|
267
|
+
return globalRoot(cmd);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/** @returns {{ warnings: string[], commitVerified: boolean }} */
|
|
271
|
+
function apply(info, decision) {
|
|
272
|
+
if (!VERSION.test(decision.to)) throw new Error(`invalid release version ${decision.to}`);
|
|
273
|
+
const source = repo.repoSource(info);
|
|
274
|
+
const root = source ? repo.bumpRepo(source, decision.to) : installGlobal(info, decision);
|
|
275
|
+
lockTouch();
|
|
276
|
+
const { commitVerified } = verifyPackage(root, decision);
|
|
277
|
+
lockTouch();
|
|
278
|
+
// The hooks under ~/.claude/exonous only change if this install succeeds; `setup` from a repo copy keeps repo mode.
|
|
279
|
+
const out = execFileSync(process.execPath, [path.join(root, 'bin', 'exonous.js'), source ? 'setup' : 'install', '--quiet'], {
|
|
280
|
+
cwd: source ? source.root : undefined,
|
|
281
|
+
env: source ? { ...process.env, INIT_CWD: source.root } : process.env,
|
|
282
|
+
encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], timeout: 10 * 60 * 1000, windowsHide: true,
|
|
283
|
+
});
|
|
284
|
+
const warnings = String(out).split('\n').filter((l) => l.includes('WARN'));
|
|
285
|
+
if (!warnings.length) patchInstall({ ref: `v${decision.to}`, tagSha: decision.sha });
|
|
286
|
+
return { warnings, commitVerified };
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function recordTag(decision) {
|
|
290
|
+
if (decision.tagMoved) {
|
|
291
|
+
writeState('tag-moved.json', `${JSON.stringify(decision.tagMoved)}\n`);
|
|
292
|
+
logLine(`release tag v${decision.tagMoved.version} moved: installed ${decision.tagMoved.expected}, now ${decision.tagMoved.actual}`);
|
|
293
|
+
writeNote(NOTES.tagMoved(decision.tagMoved.version));
|
|
294
|
+
} else if (decision.status !== 'pinned') {
|
|
295
|
+
fs.rmSync(statePath('tag-moved.json'), { force: true });
|
|
296
|
+
}
|
|
297
|
+
if (decision.tagSha) patchInstall({ tagSha: decision.tagSha });
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function announceMajor(version) {
|
|
301
|
+
if (readJson(statePath('major-seen.json'))?.version === version) return;
|
|
302
|
+
writeState('major-seen.json', `${JSON.stringify({ version })}\n`);
|
|
303
|
+
writeNote(NOTES.major(version));
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Checks and, when a newer release exists, reinstalls through the recorded pm. Never throws in background mode.
|
|
308
|
+
* @param {{ background?: boolean, major?: boolean }} [options] background: honor opt-outs and report through state/note.
|
|
309
|
+
*/
|
|
310
|
+
function run({ background = false, major = false } = {}) {
|
|
311
|
+
if (notOwner()) return { status: 'not-owner' };
|
|
312
|
+
if (background) {
|
|
313
|
+
const reason = optedOut();
|
|
314
|
+
if (reason) return { status: 'disabled', reason };
|
|
315
|
+
}
|
|
316
|
+
let decision;
|
|
317
|
+
try {
|
|
318
|
+
decision = check({ major });
|
|
319
|
+
recordTag(decision);
|
|
320
|
+
} catch (err) {
|
|
321
|
+
markChecked();
|
|
322
|
+
logLine(`check failed: ${detail(err)}`);
|
|
323
|
+
if (!background) throw err;
|
|
324
|
+
return { status: 'error', error: detail(err) };
|
|
325
|
+
}
|
|
326
|
+
if (decision.status !== 'available') {
|
|
327
|
+
if (background && decision.newMajor) announceMajor(decision.newMajor);
|
|
328
|
+
return decision;
|
|
329
|
+
}
|
|
330
|
+
const info = readInstall();
|
|
331
|
+
if (devCheckout(info)) return { ...decision, status: 'pinned', ref: `dev checkout ${info.packageRoot}` };
|
|
332
|
+
if (!globalAllowed()) return { ...decision, status: 'isolated' };
|
|
333
|
+
if (!lockAcquire()) return { ...decision, status: 'busy' };
|
|
334
|
+
try {
|
|
335
|
+
const { warnings, commitVerified } = apply(info, decision);
|
|
336
|
+
for (const w of warnings) logLine(`install v${decision.to}: ${cleanNote(w)}`);
|
|
337
|
+
if (!commitVerified) logLine(`v${decision.to}: no pm lockfile records the commit; verified by name and version only`);
|
|
338
|
+
if (background) writeNote(NOTES.updated(decision.from, decision.to));
|
|
339
|
+
return { ...decision, status: 'updated', warnings: warnings.length };
|
|
340
|
+
} catch (err) {
|
|
341
|
+
markChecked();
|
|
342
|
+
const error = detail(err);
|
|
343
|
+
logLine(`update to v${decision.to} failed: ${error}`);
|
|
344
|
+
if (background) writeNote(NOTES.failed(decision.to));
|
|
345
|
+
return { ...decision, status: 'failed', error };
|
|
346
|
+
} finally {
|
|
347
|
+
fs.rmSync(lockFile(), { force: true });
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
module.exports = {
|
|
352
|
+
DAY_MS, LOCK_STALE_MS, SOURCE, notOwner, optedOut, due, lastCheck, markChecked, cleanNote, takeNote, tagWarning, check, run, spec,
|
|
353
|
+
pmCommand, pmRun, globalRoot, globalAllowed, verifyPackage,
|
|
354
|
+
};
|