gennady 0.6.0 → 0.7.0
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 +2 -15
- package/ai/agents/agent-resolve-conflicts.xml +6 -0
- package/ai/agents/agent-review-verifier.xml +6 -0
- package/ai/directives/architecture/README.md +21 -0
- package/ai/directives/coding/README.md +23 -0
- package/ai/directives/coding/result-conventions.xml +55 -0
- package/ai/directives/coding/svelte5-runes.xml +248 -0
- package/ai/directives/coding/sveltekit-rules.xml +247 -0
- package/ai/directives/coding/typescript-rules.xml +589 -0
- package/ai/directives/coding/uikit-component-storybook.xml +347 -0
- package/ai/directives/coding/uikit-component-svelte.xml +344 -0
- package/ai/directives/coding/uikit-spec-drafting.xml +243 -0
- package/ai/directives/dbc-audit.directive.xml +131 -0
- package/ai/directives/dev-review.directive.xml +148 -0
- package/ai/directives/infra/README.md +11 -0
- package/ai/directives/infra/eslint-setup.xml +467 -0
- package/ai/directives/infra/git-setup.xml +261 -0
- package/ai/directives/infra/nodejs-npm-setup.xml +354 -0
- package/ai/directives/infra/storybook-setup.xml +153 -0
- package/ai/directives/knowledge.xml +206 -0
- package/ai/directives/perf-auditor/perf-auditor.directive.xml +75 -0
- package/ai/directives/perf-auditor/rules/async-latency.xml +101 -0
- package/ai/directives/perf-auditor/rules/data-structures.xml +103 -0
- package/ai/directives/perf-auditor/rules/iteration-fusion.xml +96 -0
- package/ai/directives/perf-auditor/rules/memory-gc.xml +102 -0
- package/ai/directives/sdd/README.md +49 -0
- package/ai/directives/sdd/audit.directive.xml +543 -0
- package/ai/directives/sdd/discovery.directive.xml +824 -0
- package/ai/directives/sdd/fix.directive.xml +249 -0
- package/ai/directives/sdd/module-decomposition.directive.xml +666 -0
- package/ai/directives/sdd/phase-execution-protocol.xml +339 -0
- package/ai/directives/sdd/scaffold.directive.xml +717 -0
- package/ai/directives/sdd/setup.directive.xml +213 -0
- package/ai/directives/sdd/svelte-ui-discovery.directive.xml +263 -0
- package/ai/directives/semantic-change-extractor.directive.xml +99 -0
- package/ai/directives/testing/README.md +25 -0
- package/ai/directives/testing/common.xml +234 -0
- package/ai/directives/testing/node-test.xml +288 -0
- package/ai/directives/testing/playwright-cli.xml +199 -0
- package/ai/directives/testing/playwright-e2e.xml +292 -0
- package/ai/directives/testing/storybook-usage.xml +173 -0
- package/ai/directives/testing/svelte-testing.xml +237 -0
- package/ai/directives/testing/vitest-rules.xml +326 -0
- package/ai/docs/README.md +17 -0
- package/ai/docs/ai-icl.md +538 -0
- package/ai/docs/ai-priming.md +548 -0
- package/ai/docs/ai-prompt-formats.md +406 -0
- package/ai/docs/ai-promting.md +572 -0
- package/ai/drafts/DRAFT.md +120 -0
- package/ai/drafts/agent-devgen-class-from-description.rules.xml +123 -0
- package/ai/drafts/agent-typescript-devgen.v1.xml +303 -0
- package/ai/drafts/d.md +65 -0
- package/ai/drafts/music-posts.md +105 -0
- package/ai/fw/v1/architecture/blueprint-factory.xml +77 -0
- package/ai/fw/v1/core/mental-model.xml +50 -0
- package/ai/fw/v1/discovery/intent-reactor.xml +92 -0
- package/ai/fw/v1/production/swarm-protocol.xml +122 -0
- package/ai/fw/v1/review/quality-pipeline.xml +102 -0
- package/ai/fw/v2/arch-universal.xml +73 -0
- package/ai/fw-draft/README.md +79 -0
- package/ai/fw-draft/bin/discovery.sh +116 -0
- package/ai/fw-draft/gennady.xml +58 -0
- package/ai/fw-draft/provider/claude.xml +16 -0
- package/ai/fw-draft/provider/cursor.xml +23 -0
- package/ai/fw-draft/provider/default.xml +12 -0
- package/ai/fw-draft/roles/developer.xml +18 -0
- package/ai/fw-draft/router.xml +39 -0
- package/ai/fw-draft/routes/development.xml +32 -0
- package/ai/fw-draft/routes/universal.xml +58 -0
- package/ai/fw-draft/rules/dev/base/file-structure-rules.xml +89 -0
- package/ai/fw-draft/rules/dev/typescript/contacts.xml +194 -0
- package/dist/ai/agents/agent-resolve-conflicts.xml +6 -0
- package/dist/ai/agents/agent-review-verifier.xml +6 -0
- package/dist/ai/directives/architecture/README.md +21 -0
- package/dist/ai/directives/coding/README.md +23 -0
- package/dist/ai/directives/coding/result-conventions.xml +55 -0
- package/dist/ai/directives/coding/svelte5-runes.xml +248 -0
- package/dist/ai/directives/coding/sveltekit-rules.xml +247 -0
- package/dist/ai/directives/coding/typescript-rules.xml +589 -0
- package/dist/ai/directives/coding/uikit-component-storybook.xml +347 -0
- package/dist/ai/directives/coding/uikit-component-svelte.xml +344 -0
- package/dist/ai/directives/coding/uikit-spec-drafting.xml +243 -0
- package/dist/ai/directives/dbc-audit.directive.xml +131 -0
- package/dist/ai/directives/dev-review.directive.xml +148 -0
- package/dist/ai/directives/infra/README.md +11 -0
- package/dist/ai/directives/infra/eslint-setup.xml +467 -0
- package/dist/ai/directives/infra/git-setup.xml +261 -0
- package/dist/ai/directives/infra/nodejs-npm-setup.xml +354 -0
- package/dist/ai/directives/infra/storybook-setup.xml +153 -0
- package/dist/ai/directives/knowledge.xml +206 -0
- package/dist/ai/directives/perf-auditor/perf-auditor.directive.xml +75 -0
- package/dist/ai/directives/perf-auditor/rules/async-latency.xml +101 -0
- package/dist/ai/directives/perf-auditor/rules/data-structures.xml +103 -0
- package/dist/ai/directives/perf-auditor/rules/iteration-fusion.xml +96 -0
- package/dist/ai/directives/perf-auditor/rules/memory-gc.xml +102 -0
- package/dist/ai/directives/sdd/README.md +49 -0
- package/dist/ai/directives/sdd/audit.directive.xml +543 -0
- package/dist/ai/directives/sdd/discovery.directive.xml +824 -0
- package/dist/ai/directives/sdd/fix.directive.xml +249 -0
- package/dist/ai/directives/sdd/module-decomposition.directive.xml +666 -0
- package/dist/ai/directives/sdd/phase-execution-protocol.xml +339 -0
- package/dist/ai/directives/sdd/scaffold.directive.xml +717 -0
- package/dist/ai/directives/sdd/setup.directive.xml +213 -0
- package/dist/ai/directives/sdd/svelte-ui-discovery.directive.xml +263 -0
- package/dist/ai/directives/semantic-change-extractor.directive.xml +99 -0
- package/dist/ai/directives/testing/README.md +25 -0
- package/dist/ai/directives/testing/common.xml +234 -0
- package/dist/ai/directives/testing/node-test.xml +288 -0
- package/dist/ai/directives/testing/playwright-cli.xml +199 -0
- package/dist/ai/directives/testing/playwright-e2e.xml +292 -0
- package/dist/ai/directives/testing/storybook-usage.xml +173 -0
- package/dist/ai/directives/testing/svelte-testing.xml +237 -0
- package/dist/ai/directives/testing/vitest-rules.xml +326 -0
- package/dist/ai/docs/README.md +17 -0
- package/dist/ai/docs/ai-icl.md +538 -0
- package/dist/ai/docs/ai-priming.md +548 -0
- package/dist/ai/docs/ai-prompt-formats.md +406 -0
- package/dist/ai/docs/ai-promting.md +572 -0
- package/dist/ai/drafts/DRAFT.md +120 -0
- package/dist/ai/drafts/agent-devgen-class-from-description.rules.xml +123 -0
- package/dist/ai/drafts/agent-typescript-devgen.v1.xml +303 -0
- package/dist/ai/drafts/d.md +65 -0
- package/dist/ai/drafts/music-posts.md +105 -0
- package/dist/ai/fw/v1/architecture/blueprint-factory.xml +77 -0
- package/dist/ai/fw/v1/core/mental-model.xml +50 -0
- package/dist/ai/fw/v1/discovery/intent-reactor.xml +92 -0
- package/dist/ai/fw/v1/production/swarm-protocol.xml +122 -0
- package/dist/ai/fw/v1/review/quality-pipeline.xml +102 -0
- package/dist/ai/fw/v2/arch-universal.xml +73 -0
- package/dist/ai/fw-draft/README.md +79 -0
- package/dist/ai/fw-draft/bin/discovery.sh +116 -0
- package/dist/ai/fw-draft/gennady.xml +58 -0
- package/dist/ai/fw-draft/provider/claude.xml +16 -0
- package/dist/ai/fw-draft/provider/cursor.xml +23 -0
- package/dist/ai/fw-draft/provider/default.xml +12 -0
- package/dist/ai/fw-draft/roles/developer.xml +18 -0
- package/dist/ai/fw-draft/router.xml +39 -0
- package/dist/ai/fw-draft/routes/development.xml +32 -0
- package/dist/ai/fw-draft/routes/universal.xml +58 -0
- package/dist/ai/fw-draft/rules/dev/base/file-structure-rules.xml +89 -0
- package/dist/ai/fw-draft/rules/dev/typescript/contacts.xml +194 -0
- package/dist/chunks/devtools-B-7ugZhF.js +79 -0
- package/dist/chunks/{help.cmd-CWasx25o.js → help.cmd-B_G7EWzF.js} +9 -2
- package/dist/chunks/{index-B63fYXL2.js → index-BeL1Zcbg.js} +1 -1
- package/dist/chunks/index-CVR66voe.js +26963 -0
- package/dist/chunks/index-CXuhZzS3.js +16979 -0
- package/dist/chunks/{index-B5bA2T7A.js → index-CaahtXiM.js} +33 -9
- package/dist/chunks/{index-iqg0w_pE.js → index-CiEM-8nJ.js} +35 -19
- package/dist/chunks/{index-B4m0-PAT.js → index-D1qsi0Uc.js} +57 -33
- package/dist/chunks/index-D9ceRUyB.js +443 -0
- package/dist/chunks/index-DJpVmyp2.js +176 -0
- package/dist/chunks/{index-C0andxna.js → index-DU6jD7SS.js} +1 -1
- package/dist/chunks/index-KxSZKmZn.js +540 -0
- package/dist/chunks/{index-Dqe1TdW4.js → index-UbHoePfr.js} +12 -12
- package/dist/chunks/{index-5xIgwwKx.js → index-g1LXlp77.js} +2 -2
- package/dist/chunks/index-zBnnuvLA.js +3788 -0
- package/dist/chunks/{run-review-command.logic-a_M3CkeZ.js → run-review-command.logic-DpkRoEi8.js} +2 -2
- package/dist/chunks/services-CaLOhuLV.js +2889 -0
- package/dist/chunks/shared-Bjy30TeM.js +665 -0
- package/dist/cli/cmd/_shared/prompt/io/load-agent-template.io.d.ts +3 -3
- package/dist/cli/cmd/_shared/prompt/logic/build-ai-first-knowledge-block.logic.d.ts +3 -3
- package/dist/cli/cmd/_shared/prompt/logic/build-ai-verify-placeholders.logic.d.ts +7 -4
- package/dist/cli/cmd/_shared/prompt/logic/verify-commands/resolve-verify-commands.logic.d.ts +5 -0
- package/dist/cli/cmd/_shared/update-check-worker.d.ts +1 -0
- package/dist/cli/cmd/_shared/update-check.d.ts +38 -0
- package/dist/cli/cmd/agent-mon/cmd/create-providers.d.ts +15 -0
- package/dist/cli/cmd/agent-mon/cmd/index.d.ts +1 -0
- package/dist/cli/cmd/agent-mon/cmd/run.d.ts +12 -0
- package/dist/cli/cmd/agent-mon/state/create-state-manager.d.ts +32 -0
- package/dist/cli/cmd/agent-mon/state/group-by-provider.d.ts +14 -0
- package/dist/cli/cmd/agent-mon/state/index.d.ts +5 -0
- package/dist/cli/cmd/agent-mon/state/is-waiting.d.ts +9 -0
- package/dist/cli/cmd/agent-mon/state/view-model.type.d.ts +74 -0
- package/dist/cli/cmd/agent-mon/ui/app.d.ts +16 -0
- package/dist/cli/cmd/agent-mon/ui/column-view.d.ts +14 -0
- package/dist/cli/cmd/agent-mon/ui/index.d.ts +10 -0
- package/dist/cli/cmd/agent-mon/ui/provider-column.d.ts +14 -0
- package/dist/cli/cmd/agent-mon/ui/session-card.d.ts +12 -0
- package/dist/cli/cmd/agent-mon/ui/status-badge.d.ts +10 -0
- package/dist/cli/cmd/alt-opinion/alt-opinion-parser.d.ts +18 -0
- package/dist/cli/cmd/alt-opinion/alt-opinion-runner.d.ts +32 -0
- package/dist/cli/cmd/alt-opinion/alt-opinion.cmd.d.ts +34 -0
- package/dist/cli/cmd/alt-opinion/alt-opinion.types.d.ts +88 -0
- package/dist/cli/cmd/alt-opinion/index.d.ts +1 -0
- package/dist/cli/cmd/cat/cat-url.fn.d.ts +19 -0
- package/dist/cli/cmd/lint/checks/anchor.check.d.ts +11 -0
- package/dist/cli/cmd/lint/checks/dbc-contract.check.d.ts +16 -0
- package/dist/cli/cmd/lint/checks/disables.check.d.ts +12 -0
- package/dist/cli/cmd/lint/checks/file-header.check.d.ts +10 -0
- package/dist/cli/cmd/lint/checks/language.check.d.ts +11 -0
- package/dist/cli/cmd/lint/index.d.ts +1 -0
- package/dist/cli/cmd/lint/lint.cmd.d.ts +18 -0
- package/dist/cli/cmd/lint/lint.types.d.ts +72 -0
- package/dist/cli/cmd/lint/utils/resolve-references.fn.d.ts +32 -0
- package/dist/cli/cmd/remote-console/index.d.ts +2 -0
- package/dist/cli/cmd/remote-console/remote-console.cmd.d.ts +55 -0
- package/dist/cli/cmd/resolve-conflicts/_core/io/resolve-conflicts-template-load.io.d.ts +2 -2
- package/dist/cli/cmd/resolve-conflicts/_core/logic/resolve-conflicts-command-args-parse.logic.d.ts +3 -3
- package/dist/cli/cmd/resolve-conflicts/_core/logic/resolve-conflicts-command-run.logic.d.ts +3 -3
- package/dist/cli/cmd/resolve-conflicts/_core/logic/resolve-conflicts-context-git-build.logic.d.ts +4 -4
- package/dist/cli/cmd/resolve-conflicts/_core/types/resolve-conflicts-artifact.type.d.ts +3 -1
- package/dist/cli/cmd/resolve-conflicts/_core/types/resolve-conflicts-command-args.type.d.ts +3 -1
- package/dist/cli/cmd/resolve-conflicts/_core/types/resolve-conflicts-command-result.type.d.ts +5 -1
- package/dist/cli/cmd/resolve-conflicts/_core/types/resolve-conflicts-context-git.type.d.ts +18 -2
- package/dist/cli/cmd/resolve-conflicts/_core/xml/resolve-conflicts-artifact-build.xml.d.ts +6 -6
- package/dist/cli/cmd/resolve-conflicts/_core/xml/resolve-conflicts-render.xml.d.ts +4 -4
- package/dist/cli/cmd/review/_core/io/load-review-verify-template.io.d.ts +2 -2
- package/dist/cli/cmd/review/_core/logic/build-review-context-git.logic.d.ts +3 -3
- package/dist/cli/cmd/review/_core/logic/build-review-context-vcs.logic.d.ts +2 -2
- package/dist/cli/cmd/review/_core/logic/load-review-context-mr.logic.d.ts +5 -5
- package/dist/cli/cmd/review/_core/logic/parse-review-command-args.logic.d.ts +3 -3
- package/dist/cli/cmd/review/_core/logic/resolve-review-intent.logic.d.ts +3 -3
- package/dist/cli/cmd/review/_core/logic/run-review-command.logic.d.ts +3 -3
- package/dist/cli/cmd/review/_core/types/review-artifact.type.d.ts +4 -1
- package/dist/cli/cmd/review/_core/types/review-command-args.type.d.ts +7 -1
- package/dist/cli/cmd/review/_core/types/review-command-mode.type.d.ts +1 -1
- package/dist/cli/cmd/review/_core/types/review-command-options.type.d.ts +3 -1
- package/dist/cli/cmd/review/_core/types/review-command-result.type.d.ts +5 -1
- package/dist/cli/cmd/review/_core/types/review-context-git.type.d.ts +3 -1
- package/dist/cli/cmd/review/_core/types/review-context-mr.type.d.ts +22 -3
- package/dist/cli/cmd/review/_core/types/review-context-vcs.type.d.ts +4 -1
- package/dist/cli/cmd/review/_core/types/review-intent.type.d.ts +1 -1
- package/dist/cli/cmd/review/_core/xml/build-review-artifact.xml.d.ts +10 -10
- package/dist/cli/cmd/review/_core/xml/render-review-issues.xml.d.ts +3 -3
- package/dist/cli/cmd/review/_core/xml/render-review-verify.xml.d.ts +4 -4
- package/dist/cli/cmd/sync/index.d.ts +1 -0
- package/dist/cli/cmd/sync/sync-core.d.ts +65 -0
- package/dist/cli/cmd/sync/sync-formatter.d.ts +12 -0
- package/dist/cli/cmd/sync/sync.cmd.d.ts +33 -0
- package/dist/cli/cmd/sync/sync.types.d.ts +50 -0
- package/dist/cli/cmd/vcs-reply/vcs-reply.cmd.d.ts +4 -4
- package/dist/cli/utils/ai-legacy/ai-legacy-agent.d.ts +12 -11
- package/dist/cli/utils/ai-legacy/ai-legacy-core.d.ts +33 -17
- package/dist/cli/utils/ai-legacy/ai-legacy-model.d.ts +42 -23
- package/dist/cli/utils/cat-gen/cat-gen.d.ts +19 -8
- package/dist/cli/utils/commit-gen/commit-gen.d.ts +39 -15
- package/dist/cli/utils/prompts/index.d.ts +6 -6
- package/dist/cli/utils/review-gen/review-gen.d.ts +33 -9
- package/dist/gennady.js +30 -10
- package/dist/index.d.ts +1 -0
- package/dist/index.js +44 -23
- package/dist/services/agent-mon/diff/diff.d.ts +9 -0
- package/dist/services/agent-mon/diff/index.d.ts +1 -0
- package/dist/services/agent-mon/index.d.ts +10 -0
- package/dist/services/agent-mon/model/agent-provider.type.d.ts +20 -0
- package/dist/services/agent-mon/model/agent-session.type.d.ts +49 -0
- package/dist/services/agent-mon/model/errors.d.ts +20 -0
- package/dist/services/agent-mon/model/index.d.ts +7 -0
- package/dist/services/agent-mon/model/observe-opts.type.d.ts +7 -0
- package/dist/services/agent-mon/model/scan-opts.type.d.ts +7 -0
- package/dist/services/agent-mon/model/session-changes.type.d.ts +10 -0
- package/dist/services/agent-mon/monitor/agent-monitor.d.ts +44 -0
- package/dist/services/agent-mon/monitor/create-monitor.d.ts +6 -0
- package/dist/services/agent-mon/monitor/index.d.ts +2 -0
- package/dist/services/agent-mon/observe/index.d.ts +1 -0
- package/dist/services/agent-mon/observe/observe.d.ts +12 -0
- package/dist/services/agent-mon/providers/claude/claude-provider.d.ts +50 -0
- package/dist/services/agent-mon/providers/claude/index.d.ts +5 -0
- package/dist/services/agent-mon/providers/claude/ps.d.ts +36 -0
- package/dist/services/agent-mon/providers/claude/session-json.d.ts +37 -0
- package/dist/services/agent-mon/providers/opencode/db.d.ts +41 -0
- package/dist/services/agent-mon/providers/opencode/index.d.ts +3 -0
- package/dist/services/agent-mon/providers/opencode/model-parser.d.ts +6 -0
- package/dist/services/agent-mon/providers/opencode/opencode-provider.d.ts +45 -0
- package/dist/services/ai-client/providers/ai-model.type.d.ts +14 -0
- package/dist/services/ai-client/providers/open-router/open-router-model.type.d.ts +1 -4
- package/dist/services/ai-client/providers/open-router/open-router-provider.d.ts +17 -0
- package/dist/services/ai-client/providers/openai-like-provider.d.ts +1 -0
- package/dist/services/data-ore/telegram/telegram-data-ore.d.ts +17 -0
- package/dist/services/data-ore/telegram/telegram-data-ore.types.d.ts +4 -0
- package/dist/services/data-ore/telegram/telegram-demo-music-helper.d.ts +1 -0
- package/dist/services/data-ore/telegram/telegram-demo.d.ts +1 -0
- package/dist/services/dbc/linter/dbc-ast-adapter.types.d.ts +82 -0
- package/dist/services/dbc/linter/dbc-linter.types.d.ts +95 -0
- package/dist/services/dbc/linter/implementations/ts/dbc-ts-ast-adapter.d.ts +183 -0
- package/dist/services/dbc/linter/implementations/ts/dbc-ts-linter.d.ts +152 -0
- package/dist/services/dbc/parser/dbc-parser.types.d.ts +16 -16
- package/dist/services/dbc/parser/implementations/jsdoc/dbc-jsdoc-parser.d.ts +14 -4
- package/dist/services/logger/logger.d.ts +26 -6
- package/dist/services/remote-console/client/remote-console-client-serializer.d.ts +7 -0
- package/dist/services/remote-console/client/remote-console-client.d.ts +20 -0
- package/dist/services/remote-console/client/remote-console-client.types.d.ts +88 -0
- package/dist/services/remote-console/remote-console.d.ts +6 -0
- package/dist/services/remote-console/server/remote-console-server.d.ts +10 -0
- package/dist/services/remote-console/server/remote-console-server.types.d.ts +44 -0
- package/dist/services/remote-console/server/remote-console-stdout-writer.d.ts +26 -0
- package/dist/services/vcs-client/abstract/vcs-client-merge-discussions.d.ts +22 -14
- package/dist/services/vcs-client/abstract/vcs-client-merge-requests.d.ts +31 -14
- package/dist/services/vcs-client/abstract/vcs-client-repository-files.d.ts +16 -0
- package/dist/services/vcs-client/abstract/vcs-client.d.ts +9 -5
- package/dist/services/vcs-client/entities/vcs-file-content.type.d.ts +24 -0
- package/dist/services/vcs-client/entities/vcs-merge-request-changes.type.d.ts +32 -0
- package/dist/services/vcs-client/entities/vcs-url.type.d.ts +14 -0
- package/dist/services/vcs-client/entities/vcs-user.type.d.ts +3 -0
- package/dist/services/vcs-client/github/vcs-github-client.d.ts +31 -0
- package/dist/services/vcs-client/github/vcs-github-merge-requests.d.ts +40 -0
- package/dist/services/vcs-client/github/vcs-github-repository-files.d.ts +27 -0
- package/dist/services/vcs-client/gitlab/vcs-gitlab-client.d.ts +13 -4
- package/dist/services/vcs-client/gitlab/vcs-gitlab-merge-discussions.d.ts +16 -5
- package/dist/services/vcs-client/gitlab/vcs-gitlab-merge-requests.d.ts +24 -5
- package/dist/services/vcs-client/gitlab/vcs-gitlab-repository-files.d.ts +27 -0
- package/dist/services/vcs-client/parse-vcs-url.d.ts +3 -0
- package/dist/shared/backend/git/git-core.d.ts +24 -22
- package/dist/shared/backend/git/git-diff.d.ts +16 -5
- package/dist/shared/backend/rc/rc-config.d.ts +27 -15
- package/dist/shared/common/exec.d.ts +4 -6
- package/dist/shared/common/files.d.ts +1 -3
- package/dist/shared/common/language.d.ts +3 -6
- package/dist/shared/common/parse-args.d.ts +1 -4
- package/dist/shared/common/style.d.ts +3 -3
- package/dist/shared/common/think.d.ts +1 -5
- package/dist/shared/common/tokens.d.ts +1 -5
- package/dist/shared/common/unguard.d.ts +4 -8
- package/dist/shared/common/xml.d.ts +16 -12
- package/package.json +20 -4
- package/dist/.ai/agents/agent-review-verifier.xml +0 -181
- package/dist/chunks/index-CNbmXK8M.js +0 -3548
- package/dist/chunks/services-Sb7TwLxt.js +0 -122
- package/dist/chunks/shared-BgLzFWMH.js +0 -577
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
<Svelte5RunesRules keywords="svelte5, runes, state, derived, effect, props, bindable, inspect, snippets" type="coding-rules" ver="2.0">
|
|
2
|
+
<Mission>
|
|
3
|
+
Canonical rules for writing Svelte 5 components using runes. Every execution-agent MUST use runes (`$state`, `$derived`, `$effect`, `$props`, `$bindable`, `$inspect`, `$effect.root`) as compiler keywords, not runtime function calls. Legacy Svelte 4 patterns (`export let`, `$:` reactive statements, `on:event` directives, `<slot>`, `createEventDispatcher`) are forbidden in new code.
|
|
4
|
+
|
|
5
|
+
**Base axiom:** runes are compile-time signals — the `$` prefix tells the Svelte compiler how to wire reactivity. They are not imports, not callable values, not React hooks. The component file is the only place a reading agent can recover this reactivity contract — so the file MUST stay self-describing: explicit runes, intent-named handlers, machine-friendly comments.
|
|
6
|
+
|
|
7
|
+
Scope: `.svelte`, `.svelte.js`, `.svelte.ts` files (compiler-aware). Out of scope: plain `.ts` modules (runes do not work there).
|
|
8
|
+
</Mission>
|
|
9
|
+
|
|
10
|
+
<Depends_On>
|
|
11
|
+
- ai/directives/coding/typescript-rules.xml
|
|
12
|
+
</Depends_On>
|
|
13
|
+
|
|
14
|
+
<Belief_State>
|
|
15
|
+
<Axiom id="AX_RUNES_ARE_COMPILER_KEYWORDS">
|
|
16
|
+
Runes are compiler directives prefixed with `$`, not runtime functions. They are never imported from any module, never assigned to variables, never passed as values. Reading `$state` / `$derived` / `$effect` as «function call» mental model leads to React-hook habits (dependency arrays, memoization wrappers) — none of which apply here.
|
|
17
|
+
|
|
18
|
+
Agent treating a rune as a value (`const s = $state; s(0)`) produces code that compiles to nothing useful and silently breaks reactivity.
|
|
19
|
+
</Axiom>
|
|
20
|
+
|
|
21
|
+
<Axiom id="AX_RUNES_LOCATION_RESTRICTION">
|
|
22
|
+
Runes appear ONLY inside Svelte compiler context: `.svelte` files, or `.svelte.js` / `.svelte.ts` modules. Using a rune in a plain `.ts` file produces a compile error; the rune does NOT silently degrade to a function call.
|
|
23
|
+
|
|
24
|
+
Cross-file shared reactive state belongs in a `.svelte.ts` module exporting runes-backed values, or in classic stores. Mixing the two for the same value is forbidden.
|
|
25
|
+
</Axiom>
|
|
26
|
+
|
|
27
|
+
<Axiom id="AX_LOCAL_RUNES_OVER_STORES_FOR_LOCAL_STATE">
|
|
28
|
+
Local component state uses `$state` / `$derived` / `$effect`. Classic stores (`writable`, `readable`, `derived` from `svelte/store`) remain available for cross-component shared state but MUST NOT be used as a substitute for local state when a rune suffices. A store introduces a subscription lifecycle that local runes do not need.
|
|
29
|
+
|
|
30
|
+
The `$store` auto-subscription syntax in templates is unchanged from Svelte 4 and remains supported.
|
|
31
|
+
</Axiom>
|
|
32
|
+
|
|
33
|
+
<Axiom id="AX_DERIVED_IS_PURE">
|
|
34
|
+
`$derived(expression)` and `$derived.by(() => ...)` MUST be pure: no side effects, no I/O, no logging, no mutation of other reactive state. Side effects belong in `$effect`. A `$derived` that mutates is a hidden cycle waiting to fire on every dependency change.
|
|
35
|
+
</Axiom>
|
|
36
|
+
|
|
37
|
+
<Axiom id="AX_EFFECT_OWNERSHIP_AND_CLEANUP">
|
|
38
|
+
`$effect(() => { ... })` runs after DOM updates; return a teardown function from the body when the effect allocates a resource (timer, subscription, listener, observer) — Svelte runs the teardown before the next run and on component destroy.
|
|
39
|
+
|
|
40
|
+
For effects outside a component context, use `$effect.root(() => { ... })` and dispose of its returned cleanup function explicitly. Forgetting the teardown function inside an effect that allocates is the classic source of leaked listeners and timers.
|
|
41
|
+
</Axiom>
|
|
42
|
+
|
|
43
|
+
<Axiom id="AX_PROPS_VIA_DESTRUCTURING">
|
|
44
|
+
Component props come from a SINGLE `$props()` destructuring call at the top of the script: `let { foo, bar = defaultValue, onSomething } = $props()`. Defaults inline in the destructuring. Optional callbacks declared as props, not via `createEventDispatcher`.
|
|
45
|
+
|
|
46
|
+
Multiple `$props()` calls in one component are forbidden — there is one props surface per component.
|
|
47
|
+
</Axiom>
|
|
48
|
+
|
|
49
|
+
<Axiom id="AX_BINDABLE_FOR_TWO_WAY">
|
|
50
|
+
Two-way bindable props are declared via `$bindable(initialValue)` inside the `$props()` destructuring (`let { value = $bindable('') } = $props()`). The parent then writes `bind:value={...}`. Without `$bindable` a prop is one-way and the parent cannot `bind:`.
|
|
51
|
+
</Axiom>
|
|
52
|
+
|
|
53
|
+
<Axiom id="AX_SNIPPETS_REPLACE_SLOTS">
|
|
54
|
+
Reusable template fragments use `{#snippet name(params)}...{/snippet}` and are invoked via `{@render name(params)}`. The Svelte 4 `<slot>` mechanism, `$$slots`, and slot props are forbidden in new components — they are removed concepts in the Svelte 5 mental model.
|
|
55
|
+
</Axiom>
|
|
56
|
+
|
|
57
|
+
<Axiom id="AX_EVENT_HANDLERS_AS_ATTRIBUTES">
|
|
58
|
+
DOM event handlers are written as attributes (`onclick={handler}`, `oninput={handler}`), NOT as `on:event` directives. Custom component events are passed as callback props (`onConfirm={...}`), NOT through `createEventDispatcher`.
|
|
59
|
+
|
|
60
|
+
`on:event` directives, `dispatch(...)`, and `createEventDispatcher` are forbidden — they belonged to the Svelte 4 event model.
|
|
61
|
+
</Axiom>
|
|
62
|
+
|
|
63
|
+
<Axiom id="AX_COMPONENT_STRUCTURE_FIXED">
|
|
64
|
+
A Svelte 5 component file has a fixed structure: an optional `<script module>` for module-scope exports (one max), an optional `<script>` for instance code (one max), the HTML template, and an optional `<style>`. Multiple instance scripts, top-level expressions outside `<script>`, and pre-script template content are forbidden.
|
|
65
|
+
</Axiom>
|
|
66
|
+
|
|
67
|
+
<Axiom id="AX_LEGACY_PATTERNS_FORBIDDEN">
|
|
68
|
+
Forbidden Svelte 4 patterns in new components: `export let prop`, `$:` reactive statements, `on:event` directives, `<slot>` and `$$slots`, `$$props` / `$$restProps`, `createEventDispatcher`, `dispatch`. Each has a Svelte 5 replacement (`$props()`, `$derived` / `$effect`, attribute handlers, `{#snippet}` + `{@render}`, callback props).
|
|
69
|
+
</Axiom>
|
|
70
|
+
|
|
71
|
+
<Axiom id="AX_INSPECT_IS_DEV_ONLY">
|
|
72
|
+
`$inspect(value)` is the debugging channel — it logs reactive changes during development and is stripped in production builds. It MUST NOT replace `logger.*` for runtime observability and MUST NOT be committed as the sole report channel for a contract-bearing state transition.
|
|
73
|
+
</Axiom>
|
|
74
|
+
</Belief_State>
|
|
75
|
+
|
|
76
|
+
<Definitions>
|
|
77
|
+
<Definition id="DEF_SVELTE_RUNE">
|
|
78
|
+
A Svelte 5 rune: a compiler directive prefixed with `$`. Recognized: `$state`, `$state.raw`, `$derived`, `$derived.by`, `$effect`, `$effect.pre`, `$effect.root`, `$effect.tracking`, `$props`, `$bindable`, `$inspect`, `$host`.
|
|
79
|
+
</Definition>
|
|
80
|
+
<Definition id="DEF_RUNES_FILE">
|
|
81
|
+
A file in which runes are valid syntax: `.svelte`, `.svelte.js`, `.svelte.ts`. Plain `.ts` is NOT a runes file.
|
|
82
|
+
</Definition>
|
|
83
|
+
</Definitions>
|
|
84
|
+
|
|
85
|
+
<Code_Patterns>
|
|
86
|
+
<Pattern id="PT_BASIC_COMPONENT_WITH_RUNES">
|
|
87
|
+
<Intent>Minimal component using `$props`, `$state`, `$derived`, `$effect`, and an attribute event handler.</Intent>
|
|
88
|
+
<Snippet language="svelte">
|
|
89
|
+
```svelte
|
|
90
|
+
<!-- @file: Counter component demonstrating the core rune set. -->
|
|
91
|
+
<script lang="ts">
|
|
92
|
+
let { initial = 0, label = 'Count', onChange } = $props();
|
|
93
|
+
let count = $state(initial);
|
|
94
|
+
let doubled = $derived(count * 2);
|
|
95
|
+
|
|
96
|
+
$effect(() => {
|
|
97
|
+
onChange?.(count);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
function increment() {
|
|
101
|
+
count += 1;
|
|
102
|
+
}
|
|
103
|
+
</script>
|
|
104
|
+
|
|
105
|
+
<button type="button" onclick={increment}>
|
|
106
|
+
{label}: {count} (x2: {doubled})
|
|
107
|
+
</button>
|
|
108
|
+
```
|
|
109
|
+
</Snippet>
|
|
110
|
+
<Why>One `$props()` destructure with defaults; `$state` for the mutable value; `$derived` pure; `$effect` mediates the outgoing side-channel; attribute `onclick`, not `on:click`.</Why>
|
|
111
|
+
</Pattern>
|
|
112
|
+
|
|
113
|
+
<Pattern id="PT_BINDABLE_PROP">
|
|
114
|
+
<Intent>Two-way bindable prop for a form input.</Intent>
|
|
115
|
+
<Snippet language="svelte">
|
|
116
|
+
```svelte
|
|
117
|
+
<script lang="ts">
|
|
118
|
+
let { value = $bindable(''), placeholder = '' } = $props();
|
|
119
|
+
</script>
|
|
120
|
+
|
|
121
|
+
<input bind:value placeholder={placeholder} />
|
|
122
|
+
```
|
|
123
|
+
</Snippet>
|
|
124
|
+
<Why>`$bindable` only inside `$props()` destructure; parent can now use `<TextInput bind:value={form.email} />`.</Why>
|
|
125
|
+
</Pattern>
|
|
126
|
+
|
|
127
|
+
<Pattern id="PT_SNIPPET_AND_RENDER">
|
|
128
|
+
<Intent>Reusable template fragment via `{#snippet}` and `{@render}` — the Svelte 5 replacement for slots.</Intent>
|
|
129
|
+
<Snippet language="svelte">
|
|
130
|
+
```svelte
|
|
131
|
+
{#snippet card(title, body)}
|
|
132
|
+
<article class="card">
|
|
133
|
+
<h2>{title}</h2>
|
|
134
|
+
<p>{body}</p>
|
|
135
|
+
</article>
|
|
136
|
+
{/snippet}
|
|
137
|
+
|
|
138
|
+
{@render card('Hello', 'World')}
|
|
139
|
+
```
|
|
140
|
+
</Snippet>
|
|
141
|
+
<Why>Snippets are reactive and re-render when arguments change. No `<slot>`, no `$$slots`.</Why>
|
|
142
|
+
</Pattern>
|
|
143
|
+
|
|
144
|
+
<Pattern id="PT_EFFECT_WITH_TEARDOWN">
|
|
145
|
+
<Intent>`$effect` allocating a resource MUST return a teardown.</Intent>
|
|
146
|
+
<Snippet language="svelte">
|
|
147
|
+
```svelte
|
|
148
|
+
<script lang="ts">
|
|
149
|
+
let { tickMs = 1000, onTick } = $props();
|
|
150
|
+
|
|
151
|
+
$effect(() => {
|
|
152
|
+
const handle = setInterval(() => onTick?.(), tickMs);
|
|
153
|
+
return () => clearInterval(handle);
|
|
154
|
+
});
|
|
155
|
+
</script>
|
|
156
|
+
```
|
|
157
|
+
</Snippet>
|
|
158
|
+
<Why>Return value is the teardown — runs before next effect invocation and on destroy. Forgetting it leaks the interval.</Why>
|
|
159
|
+
</Pattern>
|
|
160
|
+
</Code_Patterns>
|
|
161
|
+
|
|
162
|
+
<Anti_Patterns>
|
|
163
|
+
<Anti_Pattern id="AP_EXPORT_LET_LEGACY">
|
|
164
|
+
<Bad>`export let userId: string; export let onConfirm: () => void;` at the top of a `<script>`.</Bad>
|
|
165
|
+
<Why_Bad>Svelte 4 prop syntax. Forbidden by `AX_LEGACY_PATTERNS_FORBIDDEN` and `AX_PROPS_VIA_DESTRUCTURING`. Bypasses the single `$props()` destructure that is the only authoritative props surface in Svelte 5; mixing it with `$props()` in the same component is undefined behaviour.</Why_Bad>
|
|
166
|
+
<Good>`let { userId, onConfirm } = $props();` — single destructure at the top of the script, defaults inline if needed.</Good>
|
|
167
|
+
</Anti_Pattern>
|
|
168
|
+
|
|
169
|
+
<Anti_Pattern id="AP_REACTIVE_DOLLAR_COLON">
|
|
170
|
+
<Bad>`$: doubled = count * 2;` and `$: console.log(count);` inside a `<script>`.</Bad>
|
|
171
|
+
<Why_Bad>Svelte 4 reactive statements (`AX_LEGACY_PATTERNS_FORBIDDEN`). The first form is a derivation (belongs in `$derived`), the second is a side effect (belongs in `$effect`). Mixing the two intents under one syntax was exactly why `$:` was retired.</Why_Bad>
|
|
172
|
+
<Good>`let doubled = $derived(count * 2);` for the derivation; `$effect(() => { logger.debug('[Counter] [state-changed]', { count }); });` for the side effect.</Good>
|
|
173
|
+
</Anti_Pattern>
|
|
174
|
+
|
|
175
|
+
<Anti_Pattern id="AP_ON_EVENT_DIRECTIVE">
|
|
176
|
+
<Bad>`<button on:click={increment}>` in the template; `createEventDispatcher` + `dispatch('confirm', payload)` for component output.</Bad>
|
|
177
|
+
<Why_Bad>Svelte 4 event model (`AX_EVENT_HANDLERS_AS_ATTRIBUTES`). `on:click` and `dispatch` are removed concepts in the Svelte 5 mental model; keeping them in new components fragments the project's event syntax and confuses tooling that targets the new model.</Why_Bad>
|
|
178
|
+
<Good>`<button type="button" onclick={increment}>` for DOM; `onConfirm?.(payload)` callback prop for component output (declared in `$props()`).</Good>
|
|
179
|
+
</Anti_Pattern>
|
|
180
|
+
|
|
181
|
+
<Anti_Pattern id="AP_RUNES_IN_PLAIN_TS">
|
|
182
|
+
<Bad>`// utils.ts` containing `export const counter = $state(0);`.</Bad>
|
|
183
|
+
<Why_Bad>`utils.ts` is not a runes file (`AX_RUNES_LOCATION_RESTRICTION`). The Svelte compiler does not process it; `$state` is undefined at runtime and TypeScript reports it as an unknown identifier.</Why_Bad>
|
|
184
|
+
<Good>Rename to `utils.svelte.ts` so the compiler treats it as a runes module: `export const counter = $state(0);` then works. Importers stay unchanged.</Good>
|
|
185
|
+
</Anti_Pattern>
|
|
186
|
+
|
|
187
|
+
<Anti_Pattern id="AP_DERIVED_WITH_SIDE_EFFECT">
|
|
188
|
+
<Bad>`let label = $derived((() => { logger.info('recomputing'); return count > 0 ? 'positive' : 'non-positive'; })());`</Bad>
|
|
189
|
+
<Why_Bad>Side effect (logging) inside `$derived` (`AX_DERIVED_IS_PURE`). `$derived` re-runs whenever any tracked dependency changes; the side effect fires on every recomputation, producing log spam and obscuring real state transitions.</Why_Bad>
|
|
190
|
+
<Good>`let label = $derived(count > 0 ? 'positive' : 'non-positive');` for the pure derivation; `$effect(() => { logger.debug('[Component] [label-changed]', { label }); });` for the observability side effect.</Good>
|
|
191
|
+
</Anti_Pattern>
|
|
192
|
+
|
|
193
|
+
<Anti_Pattern id="AP_EFFECT_WITHOUT_TEARDOWN">
|
|
194
|
+
<Bad>`$effect(() => { const id = setInterval(poll, 1000); });` — no return value.</Bad>
|
|
195
|
+
<Why_Bad>Allocating effect without teardown (`AX_EFFECT_OWNERSHIP_AND_CLEANUP`). The interval keeps firing across re-runs and after component destroy, leaking handlers and producing ghost network traffic.</Why_Bad>
|
|
196
|
+
<Good>`$effect(() => { const id = setInterval(poll, 1000); return () => clearInterval(id); });` — the returned cleanup runs before the next effect invocation and on destroy.</Good>
|
|
197
|
+
</Anti_Pattern>
|
|
198
|
+
</Anti_Patterns>
|
|
199
|
+
|
|
200
|
+
<Verification_Hooks>
|
|
201
|
+
<Hook id="HOOK_SVELTE_CHECK">
|
|
202
|
+
<Purpose>Type-check Svelte components and `.svelte.ts` modules; flags legacy patterns the compiler refuses.</Purpose>
|
|
203
|
+
<Command>npx svelte-check --tsconfig ./tsconfig.json</Command>
|
|
204
|
+
<Expected>Exit 0; no errors or warnings.</Expected>
|
|
205
|
+
</Hook>
|
|
206
|
+
<Hook id="HOOK_NO_LEGACY_PROP_SYNTAX">
|
|
207
|
+
<Purpose>Smoke-grep for forbidden Svelte 4 prop syntax `export let` in `.svelte` files.</Purpose>
|
|
208
|
+
<Command>find . -name '*.svelte' -not -path '*/node_modules/*' -not -path '*/.svelte-kit/*' -print0 | xargs -0 grep -nE '^\s*export\s+let\s+' || true</Command>
|
|
209
|
+
<Expected>Empty output. Any match is a legacy prop declaration that must be migrated to `$props()` destructuring.</Expected>
|
|
210
|
+
</Hook>
|
|
211
|
+
<Hook id="HOOK_NO_LEGACY_REACTIVE">
|
|
212
|
+
<Purpose>Smoke-grep for forbidden `$:` reactive statements and `on:event` directives.</Purpose>
|
|
213
|
+
<Command>find . \( -name '*.svelte' -o -name '*.svelte.ts' -o -name '*.svelte.js' \) -not -path '*/node_modules/*' -not -path '*/.svelte-kit/*' -print0 | xargs -0 grep -nE '(^|\s)\$:\s|(\s|^)on:[a-z]+=' || true</Command>
|
|
214
|
+
<Expected>Empty output. Matches must migrate to `$derived` / `$effect` or attribute handlers.</Expected>
|
|
215
|
+
</Hook>
|
|
216
|
+
<Hook id="HOOK_NO_RUNES_IN_PLAIN_TS">
|
|
217
|
+
<Purpose>Detect runes used in plain `.ts` files (not `.svelte.ts`).</Purpose>
|
|
218
|
+
<Command>find . -name '*.ts' -not -name '*.svelte.ts' -not -name '*.d.ts' -not -path '*/node_modules/*' -not -path '*/.svelte-kit/*' -print0 | xargs -0 grep -nE '\$(state|derived|effect|props|bindable|inspect)\b' || true</Command>
|
|
219
|
+
<Expected>Empty output. Files containing runes must be renamed to `.svelte.ts`.</Expected>
|
|
220
|
+
</Hook>
|
|
221
|
+
<Hook id="HOOK_NO_CREATE_EVENT_DISPATCHER">
|
|
222
|
+
<Purpose>Detect forbidden `createEventDispatcher` imports.</Purpose>
|
|
223
|
+
<Command>find . \( -name '*.svelte' -o -name '*.ts' \) -not -path '*/node_modules/*' -not -path '*/.svelte-kit/*' -print0 | xargs -0 grep -n 'createEventDispatcher' || true</Command>
|
|
224
|
+
<Expected>Empty output. Replace with callback props declared through `$props()`.</Expected>
|
|
225
|
+
</Hook>
|
|
226
|
+
</Verification_Hooks>
|
|
227
|
+
|
|
228
|
+
<Reward_Criteria>
|
|
229
|
+
✅ All reactive primitives use runes (`$state`, `$derived`, `$effect`, `$props`, `$bindable`) as compiler keywords.
|
|
230
|
+
✅ Props consumed via a single `$props()` destructure at the top of the script; defaults inline; callback props for outgoing events.
|
|
231
|
+
✅ DOM event handlers use attribute form (`onclick={...}`); custom events use callback props.
|
|
232
|
+
✅ Reusable template fragments use `{#snippet}` + `{@render}`.
|
|
233
|
+
✅ Effects allocating resources return their teardown function.
|
|
234
|
+
✅ `$derived` expressions are pure — no logging, no mutation, no I/O.
|
|
235
|
+
✅ Runes only appear in `.svelte`, `.svelte.js`, `.svelte.ts` files; cross-file reactive values live in `.svelte.ts`.
|
|
236
|
+
✅ Classic stores reserved for genuine cross-component shared state; local state uses runes.
|
|
237
|
+
|
|
238
|
+
❌ `export let prop` for prop declarations in new components.
|
|
239
|
+
❌ `$:` reactive statements (derivation OR side effect).
|
|
240
|
+
❌ `on:event` directives or `createEventDispatcher` / `dispatch`.
|
|
241
|
+
❌ `<slot>`, `$$slots`, `$$props`, `$$restProps`.
|
|
242
|
+
❌ Rune used in a plain `.ts` file (must be `.svelte.ts`).
|
|
243
|
+
❌ Rune treated as a value (`const s = $state; s(0)`).
|
|
244
|
+
❌ Side effects inside `$derived`; allocating `$effect` without teardown.
|
|
245
|
+
❌ Multiple `$props()` destructures or multiple instance `<script>` blocks in one component.
|
|
246
|
+
❌ `$inspect` left in committed code as the only report channel for a contract-bearing state transition.
|
|
247
|
+
</Reward_Criteria>
|
|
248
|
+
</Svelte5RunesRules>
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
<SvelteKitRules keywords="sveltekit, fullstack, routing, load-functions, form-actions, server-client-boundary, hooks, adapters, ssr" type="coding-rules" ver="2.0">
|
|
2
|
+
<Mission>
|
|
3
|
+
Canonical rules for building SvelteKit fullstack applications. Every execution-agent MUST respect the server/client boundary, fetch data via `load` functions, mutate via form `actions`, and use file-based routing.
|
|
4
|
+
|
|
5
|
+
**Base axiom:** SvelteKit's value comes from a hard server/client boundary expressed through file naming (`+page.server.ts` is server-only; `+page.ts` is universal; `.svelte` is the client component). A file's name is its contract — leaking a secret across that boundary is a one-edit security failure that lints often do not catch. So every authoring decision starts from «which boundary owns this concern?», not from «where is this convenient?».
|
|
6
|
+
|
|
7
|
+
Scope: routing structure, data flow (load + actions), server hooks, page options, adapters. Out of scope: rune-level component authoring (covered by `svelte5-runes`) and TS-level conventions (covered by `typescript-rules`).
|
|
8
|
+
</Mission>
|
|
9
|
+
|
|
10
|
+
<Depends_On>
|
|
11
|
+
- ai/directives/coding/typescript-rules.xml
|
|
12
|
+
- ai/directives/coding/svelte5-runes.xml
|
|
13
|
+
</Depends_On>
|
|
14
|
+
|
|
15
|
+
<Belief_State>
|
|
16
|
+
<Axiom id="AX_SK_ROUTING_IS_FILE_BASED">
|
|
17
|
+
Routes are declared by directory structure under `src/routes/`. A path like `src/routes/user/[id]/+page.svelte` exposes `/user/:id`. Manual route tables, parallel router libraries, or imperative `Router` mounting are forbidden — they fork the source of truth for which URL renders what.
|
|
18
|
+
|
|
19
|
+
Layout wrappers via `+layout.svelte` / `+layout.server.ts` / `+layout.ts`. Nested layouts compose; siblings do not.
|
|
20
|
+
</Axiom>
|
|
21
|
+
|
|
22
|
+
<Axiom id="AX_SK_SERVER_CLIENT_BOUNDARY">
|
|
23
|
+
The file name decides where the code runs:
|
|
24
|
+
- `+page.server.ts`, `+layout.server.ts`, `hooks.server.ts`, anything under `$lib/server/` — **server-only**. Allowed to read filesystem, talk to databases, use private env.
|
|
25
|
+
- `+page.ts`, `+layout.ts`, `.svelte` (instance script + template) — **universal/client**. MUST be safe to ship to the browser.
|
|
26
|
+
|
|
27
|
+
Private secrets (`$env/static/private`, `$env/dynamic/private`) MUST NOT be imported from universal/client files. The toolchain refuses such imports at build time — agent's job is to keep the import graph clean from the start, not to rely on the compile error as the only guardrail.
|
|
28
|
+
</Axiom>
|
|
29
|
+
|
|
30
|
+
<Axiom id="AX_SK_DATA_VIA_LOAD">
|
|
31
|
+
Data needed to render a route is fetched in `load()` — universal in `+page.ts` / `+layout.ts`, server-only in `+page.server.ts` / `+layout.server.ts`. The return shape becomes `data` on the page (`let { data } = $props()`).
|
|
32
|
+
|
|
33
|
+
Forbidden as default: calling `fetch` from a component `<script>` to populate initial state. Component-level fetch loses SSR, breaks invalidation, and bypasses the server's privileged access. Reserved exception: client-only progressive updates that have NO server data dependency.
|
|
34
|
+
</Axiom>
|
|
35
|
+
|
|
36
|
+
<Axiom id="AX_SK_MUTATIONS_VIA_ACTIONS">
|
|
37
|
+
State mutations from the browser go through form `actions` in `+page.server.ts`: `export const actions = { default: async ({ request, cookies, locals, fetch }) => { ... } }`. The page submits `<form method="POST" use:enhance>` — progressive enhancement gives a working flow even without JavaScript.
|
|
38
|
+
|
|
39
|
+
`fetch('/api/...', { method: 'POST' })` from a component to mutate state is forbidden as the default path. It re-implements what actions already give (CSRF, redirect, validation result) and reintroduces the server/client boundary problem one route at a time.
|
|
40
|
+
</Axiom>
|
|
41
|
+
|
|
42
|
+
<Axiom id="AX_SK_VALIDATION_AT_ACTION_BOUNDARY">
|
|
43
|
+
Form actions validate request input synchronously at the top, return `fail(status, payload)` on rejection. The payload is exposed as `form` on the page (`let { form } = $props()`) and re-renders the form with the offending fields preserved. Throwing arbitrary errors from an action surfaces as a 500 with no recoverable UI state — `fail()` is the contract channel.
|
|
44
|
+
</Axiom>
|
|
45
|
+
|
|
46
|
+
<Axiom id="AX_SK_HOOKS_OWN_CROSS_CUTTING">
|
|
47
|
+
Cross-cutting server concerns (auth, request enrichment, error reporting) live in `src/hooks.server.ts` via `handle({ event, resolve })`. Auth context is attached to `event.locals` and read downstream by `load` / `actions`. `handleError({ error, event })` is the single point that maps unhandled exceptions to the user-facing shape.
|
|
48
|
+
|
|
49
|
+
Client-side cross-cutting goes in `src/hooks.client.ts`. Per-route boilerplate (re-checking auth in every `load`) is forbidden — `event.locals` is the contract for «who is the caller».
|
|
50
|
+
</Axiom>
|
|
51
|
+
|
|
52
|
+
<Axiom id="AX_SK_PAGE_OPTIONS_PER_ROUTE">
|
|
53
|
+
Page-level toggles (`export const ssr`, `export const prerender`, `export const csr`, `export const trailingSlash`) live in the route's `+page.ts` / `+page.server.ts` / `+layout.ts`. They are NOT global config in `svelte.config.js`.
|
|
54
|
+
|
|
55
|
+
Forcing `ssr = false` globally turns a SvelteKit app into a single-page app and discards most of the framework's value; doing it per-route documents the trade-off where it applies.
|
|
56
|
+
</Axiom>
|
|
57
|
+
|
|
58
|
+
<Axiom id="AX_SK_FETCH_FROM_LOAD_USES_SDK_FETCH">
|
|
59
|
+
Inside `load` / `actions`, use the `fetch` provided by SvelteKit's event (`async ({ fetch }) => ...`), not the global `fetch`. The event-provided `fetch` propagates credentials, runs in-process for internal API routes, and inherits the user's request context. Using global `fetch` from a server `load` is a silent loss of context.
|
|
60
|
+
</Axiom>
|
|
61
|
+
|
|
62
|
+
<Axiom id="AX_SK_TYPES_FROM_GENERATED">
|
|
63
|
+
Route-specific types come from generated `./$types` modules: `PageServerLoad`, `Actions`, `PageLoad`, `LayoutData`, etc. Hand-rolling these types is forbidden — they drift the first time the route signature changes. `App.Locals`, `App.PageData`, `App.Error`, `App.Platform` are declared in `src/app.d.ts` and are the only place to extend per-app surfaces.
|
|
64
|
+
</Axiom>
|
|
65
|
+
|
|
66
|
+
<Axiom id="AX_SK_ADAPTER_CHOSEN_NOT_DEFAULTED">
|
|
67
|
+
Production deployment requires an explicit adapter choice (`@sveltejs/adapter-node`, `@sveltejs/adapter-static`, platform-specific, etc.) configured in `svelte.config.js`. `adapter-auto` is acceptable only for greenfield prototypes; a production project that has not committed to an adapter has not committed to a deployment shape.
|
|
68
|
+
</Axiom>
|
|
69
|
+
|
|
70
|
+
<Axiom id="AX_SK_PROJECT_LAYOUT">
|
|
71
|
+
Canonical layout: `src/routes/` for routes, `src/lib/` for shared client+server code, `src/lib/server/` for server-only code, `src/hooks.server.ts` / `src/hooks.client.ts` for hooks, `src/app.html` for the HTML shell, `src/app.d.ts` for ambient types, `static/` for unprocessed assets. The `$lib` alias points to `src/lib`; `$lib/server` is automatically server-only.
|
|
72
|
+
</Axiom>
|
|
73
|
+
</Belief_State>
|
|
74
|
+
|
|
75
|
+
<Definitions>
|
|
76
|
+
<Definition id="DEF_UNIVERSAL_LOAD">
|
|
77
|
+
A `load` function exported from `+page.ts` / `+layout.ts`. Runs on the server during SSR AND in the client during navigation. MUST stay safe to bundle for the browser — no private env, no Node-only APIs.
|
|
78
|
+
</Definition>
|
|
79
|
+
<Definition id="DEF_SERVER_LOAD">
|
|
80
|
+
A `load` function exported from `+page.server.ts` / `+layout.server.ts`. Runs ONLY on the server. Has access to `cookies`, `locals`, private env, filesystem.
|
|
81
|
+
</Definition>
|
|
82
|
+
<Definition id="DEF_FORM_ACTION">
|
|
83
|
+
A handler exported under `actions` in `+page.server.ts`. Receives `request`, `cookies`, `locals`, `fetch`. Returns success payload or `fail(status, payload)`; may `redirect(status, location)`.
|
|
84
|
+
</Definition>
|
|
85
|
+
</Definitions>
|
|
86
|
+
|
|
87
|
+
<Code_Patterns>
|
|
88
|
+
<Pattern id="PT_SERVER_LOAD">
|
|
89
|
+
<Intent>Server-only data fetch with typed return surface.</Intent>
|
|
90
|
+
<Snippet language="typescript">
|
|
91
|
+
```typescript
|
|
92
|
+
// src/routes/products/[id]/+page.server.ts
|
|
93
|
+
import { error } from '@sveltejs/kit';
|
|
94
|
+
import type { PageServerLoad } from './$types';
|
|
95
|
+
|
|
96
|
+
export const load: PageServerLoad = async ({ params, fetch, locals }) => {
|
|
97
|
+
const response = await fetch(`/api/products/${params.id}`);
|
|
98
|
+
if (!response.ok) {
|
|
99
|
+
throw error(404, 'Product not found');
|
|
100
|
+
}
|
|
101
|
+
const product = await response.json();
|
|
102
|
+
return { product, viewer: locals.user };
|
|
103
|
+
};
|
|
104
|
+
```
|
|
105
|
+
</Snippet>
|
|
106
|
+
<Why>SDK-provided `fetch` preserves request context; `locals.user` populated by `hooks.server.ts`; `error()` returns the framework's recoverable error shape.</Why>
|
|
107
|
+
</Pattern>
|
|
108
|
+
|
|
109
|
+
<Pattern id="PT_FORM_ACTION_WITH_FAIL">
|
|
110
|
+
<Intent>Form action with synchronous validation and `fail()` for recoverable rejection.</Intent>
|
|
111
|
+
<Snippet language="typescript">
|
|
112
|
+
```typescript
|
|
113
|
+
// src/routes/checkout/+page.server.ts
|
|
114
|
+
import { fail, redirect } from '@sveltejs/kit';
|
|
115
|
+
import type { Actions } from './$types';
|
|
116
|
+
|
|
117
|
+
export const actions = {
|
|
118
|
+
default: async ({ request, locals }) => {
|
|
119
|
+
const data = await request.formData();
|
|
120
|
+
const email = data.get('email')?.toString().trim();
|
|
121
|
+
if (!email) {
|
|
122
|
+
return fail(400, { email: '', error: 'Email is required' });
|
|
123
|
+
}
|
|
124
|
+
await locals.checkout.placeOrder({ email });
|
|
125
|
+
throw redirect(303, '/checkout/done');
|
|
126
|
+
},
|
|
127
|
+
} satisfies Actions;
|
|
128
|
+
```
|
|
129
|
+
</Snippet>
|
|
130
|
+
<Why>`fail()` re-renders the page with `form` populated; `redirect()` is the success channel; validation is synchronous and at the top.</Why>
|
|
131
|
+
</Pattern>
|
|
132
|
+
|
|
133
|
+
<Pattern id="PT_SERVER_HOOK_AUTH">
|
|
134
|
+
<Intent>Server hook injecting auth context into `event.locals`.</Intent>
|
|
135
|
+
<Snippet language="typescript">
|
|
136
|
+
```typescript
|
|
137
|
+
// src/hooks.server.ts
|
|
138
|
+
import type { Handle } from '@sveltejs/kit';
|
|
139
|
+
import { decodeSession } from '$lib/server/session';
|
|
140
|
+
|
|
141
|
+
export const handle: Handle = async ({ event, resolve }) => {
|
|
142
|
+
const token = event.cookies.get('session');
|
|
143
|
+
event.locals.user = token ? await decodeSession(token) : null;
|
|
144
|
+
return resolve(event);
|
|
145
|
+
};
|
|
146
|
+
```
|
|
147
|
+
</Snippet>
|
|
148
|
+
<Why>`$lib/server/session` is automatically server-only; `event.locals.user` becomes the single contract for «who is the caller» downstream.</Why>
|
|
149
|
+
</Pattern>
|
|
150
|
+
|
|
151
|
+
<Pattern id="PT_PAGE_CONSUMING_LOAD">
|
|
152
|
+
<Intent>Route page reading `data` from a server load via `$props()`.</Intent>
|
|
153
|
+
<Snippet language="svelte">
|
|
154
|
+
```svelte
|
|
155
|
+
<!-- src/routes/products/[id]/+page.svelte -->
|
|
156
|
+
<script lang="ts">
|
|
157
|
+
import type { PageData } from './$types';
|
|
158
|
+
let { data }: { data: PageData } = $props();
|
|
159
|
+
</script>
|
|
160
|
+
|
|
161
|
+
<h1>{data.product.name}</h1>
|
|
162
|
+
<p>Viewer: {data.viewer?.email ?? 'anonymous'}</p>
|
|
163
|
+
```
|
|
164
|
+
</Snippet>
|
|
165
|
+
<Why>Component receives `data` via `$props()` (single Svelte 5 destructure); the `PageData` type is generated by SvelteKit from the matching server load.</Why>
|
|
166
|
+
</Pattern>
|
|
167
|
+
</Code_Patterns>
|
|
168
|
+
|
|
169
|
+
<Anti_Patterns>
|
|
170
|
+
<Anti_Pattern id="AP_SK_COMPONENT_FETCH_FOR_INITIAL_DATA">
|
|
171
|
+
<Bad>Inside `+page.svelte`: `$effect(() => { fetch('/api/products').then(r => r.json()).then(items => products = items); });` to populate the initial product list.</Bad>
|
|
172
|
+
<Why_Bad>Component-level fetch for initial data (`AX_SK_DATA_VIA_LOAD`). Loses SSR (page renders empty, then flickers), bypasses framework `invalidate()` / `depends()`, runs in the browser only — server-side rendering benefit gone. Cannot use private credentials or `locals`.</Why_Bad>
|
|
173
|
+
<Good>Move fetch into `+page.server.ts`: `export const load: PageServerLoad = async ({ fetch }) => ({ products: await (await fetch('/api/products')).json() });`. Component reads `data.products` via `$props()`.</Good>
|
|
174
|
+
</Anti_Pattern>
|
|
175
|
+
|
|
176
|
+
<Anti_Pattern id="AP_SK_PRIVATE_ENV_IN_CLIENT">
|
|
177
|
+
<Bad>`+page.ts` (universal) starts with `import { DATABASE_URL } from '$env/static/private';`.</Bad>
|
|
178
|
+
<Why_Bad>Private env imported into a universal/client module (`AX_SK_SERVER_CLIENT_BOUNDARY`). Build refuses to bundle it; even if it slipped through (e.g., via dynamic require), the secret would be shipped to the browser bundle. Boundary violation is a security failure, not a stylistic one.</Why_Bad>
|
|
179
|
+
<Good>Move the consumer to `+page.server.ts` or `$lib/server/...`; expose only the derived value the client legitimately needs through the load return.</Good>
|
|
180
|
+
</Anti_Pattern>
|
|
181
|
+
|
|
182
|
+
<Anti_Pattern id="AP_SK_THROW_INSTEAD_OF_FAIL">
|
|
183
|
+
<Bad>In a form action: `if (!email) throw new Error('Email required');`</Bad>
|
|
184
|
+
<Why_Bad>Action throws instead of returning `fail()` (`AX_SK_VALIDATION_AT_ACTION_BOUNDARY`). Surfaces as a 500 with the framework's error page; the form loses its inputs; the user has no recoverable UI state. `fail()` is the contract channel for recoverable validation rejection.</Why_Bad>
|
|
185
|
+
<Good>`return fail(400, { email: '', error: 'Email is required' });` — page re-renders with `form.error` visible and inputs preserved.</Good>
|
|
186
|
+
</Anti_Pattern>
|
|
187
|
+
|
|
188
|
+
<Anti_Pattern id="AP_SK_GLOBAL_FETCH_IN_LOAD">
|
|
189
|
+
<Bad>Inside `+page.server.ts`: `const res = await fetch('http://localhost:3000/api/products');` (the global `fetch`).</Bad>
|
|
190
|
+
<Why_Bad>Global `fetch` from a server load (`AX_SK_FETCH_FROM_LOAD_USES_SDK_FETCH`). Loses request context (cookies, headers), forces a real network hop for internal API routes that SvelteKit would have resolved in-process, and hard-codes the origin.</Why_Bad>
|
|
191
|
+
<Good>Destructure the SDK-provided `fetch`: `export const load: PageServerLoad = async ({ fetch }) => { const res = await fetch('/api/products'); ... };`. Relative URLs resolve to the current origin; cookies propagate.</Good>
|
|
192
|
+
</Anti_Pattern>
|
|
193
|
+
|
|
194
|
+
<Anti_Pattern id="AP_SK_PAGE_OPTIONS_GLOBALIZED">
|
|
195
|
+
<Bad>`svelte.config.js` sets `kit: { prerender: { entries: ['*'] }, csr: false }` to disable SSR/CSR project-wide.</Bad>
|
|
196
|
+
<Why_Bad>Page options globalized into framework config (`AX_SK_PAGE_OPTIONS_PER_ROUTE`). Discards per-route trade-offs — a marketing landing page that benefits from prerender forces the same on dynamic dashboards. Hidden behavior at the framework level surprises every later contributor.</Why_Bad>
|
|
197
|
+
<Good>Per-route in the relevant `+page.ts`: `export const prerender = true;` for static pages; leave dynamic routes default.</Good>
|
|
198
|
+
</Anti_Pattern>
|
|
199
|
+
</Anti_Patterns>
|
|
200
|
+
|
|
201
|
+
<Verification_Hooks>
|
|
202
|
+
<Hook id="HOOK_SK_TYPECHECK">
|
|
203
|
+
<Purpose>Generate route types and run Svelte-aware type-check; catches private-env-in-client violations.</Purpose>
|
|
204
|
+
<Command>npx svelte-kit sync && npx svelte-check --tsconfig ./tsconfig.json</Command>
|
|
205
|
+
<Expected>Exit 0; no errors.</Expected>
|
|
206
|
+
</Hook>
|
|
207
|
+
<Hook id="HOOK_SK_BUILD">
|
|
208
|
+
<Purpose>Production build verifies SSR, adapter, and boundary violations the dev server tolerates.</Purpose>
|
|
209
|
+
<Command>npm run build</Command>
|
|
210
|
+
<Expected>Exit 0.</Expected>
|
|
211
|
+
</Hook>
|
|
212
|
+
<Hook id="HOOK_SK_NO_PRIVATE_ENV_IN_CLIENT">
|
|
213
|
+
<Purpose>Smoke-grep for private env imported from universal/client files.</Purpose>
|
|
214
|
+
<Command>find src -type f \( -name '*.svelte' -o -name '+page.ts' -o -name '+layout.ts' \) -print0 | xargs -0 grep -nE "\\\$env/(static|dynamic)/private" || true</Command>
|
|
215
|
+
<Expected>Empty output. Matches must move to `+page.server.ts` / `+layout.server.ts` / `$lib/server/`.</Expected>
|
|
216
|
+
</Hook>
|
|
217
|
+
<Hook id="HOOK_SK_NO_GLOBAL_FETCH_IN_LOAD">
|
|
218
|
+
<Purpose>Smoke-grep for likely global `fetch(` in server load files (manual review of matches).</Purpose>
|
|
219
|
+
<Command>find src/routes -type f \( -name '+page.server.ts' -o -name '+layout.server.ts' \) -print0 | xargs -0 grep -nE '(^|[^.])fetch\(' || true</Command>
|
|
220
|
+
<Expected>For each match: confirm it is the SDK-provided `fetch` destructured from the load event, not the global `fetch`.</Expected>
|
|
221
|
+
</Hook>
|
|
222
|
+
<Hook id="HOOK_SK_NO_CLIENT_FETCH_IN_COMPONENT">
|
|
223
|
+
<Purpose>Detect direct `fetch('/api/...')` calls inside `.svelte` files used to populate initial data.</Purpose>
|
|
224
|
+
<Command>find src/routes -name '*.svelte' -print0 | xargs -0 grep -nE "fetch\(['\"]/" || true</Command>
|
|
225
|
+
<Expected>Each match must be either an explicit progressive-update path with no server data dependency, or migrated to a `load` function.</Expected>
|
|
226
|
+
</Hook>
|
|
227
|
+
</Verification_Hooks>
|
|
228
|
+
|
|
229
|
+
<Reward_Criteria>
|
|
230
|
+
✅ Data fetched via `load` (server or universal); component-level fetch reserved for genuine progressive updates.
|
|
231
|
+
✅ Mutations go through form `actions` with `<form method="POST" use:enhance>`; recoverable rejection via `fail()`; success via `redirect()`.
|
|
232
|
+
✅ Server/client boundary respected by file naming; private env imported only in server-only files.
|
|
233
|
+
✅ SDK-provided `fetch` used inside `load` / `actions`; global `fetch` not used for in-app routes.
|
|
234
|
+
✅ Cross-cutting auth/request enrichment in `hooks.server.ts`; downstream code reads `event.locals` only.
|
|
235
|
+
✅ Page options (`ssr`, `prerender`, `csr`) per-route, not globalized.
|
|
236
|
+
✅ Route types from `./$types`; ambient types in `src/app.d.ts`.
|
|
237
|
+
✅ Explicit adapter chosen for production builds.
|
|
238
|
+
|
|
239
|
+
❌ Component-level fetch to populate initial render data.
|
|
240
|
+
❌ Private env (`$env/static/private`, `$env/dynamic/private`) imported in `+page.ts` / `+layout.ts` / `.svelte`.
|
|
241
|
+
❌ Form action throwing arbitrary errors instead of returning `fail()`.
|
|
242
|
+
❌ Global `fetch` used inside a load / action when the SDK `fetch` is available.
|
|
243
|
+
❌ Page options globalized in `svelte.config.js`.
|
|
244
|
+
❌ Hand-rolled route types; bypassing `App.Locals` / `App.PageData` for ambient extensions.
|
|
245
|
+
❌ Production build relying on `adapter-auto`.
|
|
246
|
+
</Reward_Criteria>
|
|
247
|
+
</SvelteKitRules>
|