@canonical/pragma-cli 0.33.0 → 0.35.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 +153 -30
- package/dist/.build-ok +0 -0
- package/dist/package.json +83 -0
- package/dist/pragma.conf.js +814 -0
- package/dist/pragma.conf.js.map +1 -0
- package/dist/src/bin.js +356 -0
- package/dist/src/bin.js.map +1 -0
- package/dist/src/capabilities/capabilities/capabilities.render.js +70 -0
- package/dist/src/capabilities/capabilities/capabilities.render.js.map +1 -0
- package/dist/src/capabilities/capabilities/capabilities.verb.js +59 -0
- package/dist/src/capabilities/capabilities/capabilities.verb.js.map +1 -0
- package/dist/src/capabilities/capabilities/catalog.js +130 -0
- package/dist/src/capabilities/capabilities/catalog.js.map +1 -0
- package/dist/src/capabilities/capabilities/hints.js +195 -0
- package/dist/src/capabilities/capabilities/hints.js.map +1 -0
- package/dist/src/capabilities/capabilities/index.js +11 -0
- package/dist/src/capabilities/capabilities/index.js.map +1 -0
- package/dist/src/capabilities/capabilities/types.js +11 -0
- package/dist/src/capabilities/capabilities/types.js.map +1 -0
- package/dist/src/capabilities/colophon/collectColophon.js +83 -0
- package/dist/src/capabilities/colophon/collectColophon.js.map +1 -0
- package/dist/src/capabilities/colophon/colophon.render.js +59 -0
- package/dist/src/capabilities/colophon/colophon.render.js.map +1 -0
- package/dist/src/capabilities/colophon/colophon.verb.js +43 -0
- package/dist/src/capabilities/colophon/colophon.verb.js.map +1 -0
- package/dist/src/capabilities/colophon/index.js +5 -0
- package/dist/src/capabilities/colophon/index.js.map +1 -0
- package/dist/src/capabilities/colophon/markdownTerminal.js +90 -0
- package/dist/src/capabilities/colophon/markdownTerminal.js.map +1 -0
- package/dist/src/capabilities/colophon/types.js +10 -0
- package/dist/src/capabilities/colophon/types.js.map +1 -0
- package/dist/src/capabilities/config/collectConfigShow.js +59 -0
- package/dist/src/capabilities/config/collectConfigShow.js.map +1 -0
- package/dist/src/capabilities/config/field.render.js +22 -0
- package/dist/src/capabilities/config/field.render.js.map +1 -0
- package/dist/src/capabilities/config/fields.js +46 -0
- package/dist/src/capabilities/config/fields.js.map +1 -0
- package/dist/src/capabilities/config/get.verb.js +61 -0
- package/dist/src/capabilities/config/get.verb.js.map +1 -0
- package/dist/src/capabilities/config/index.js +5 -0
- package/dist/src/capabilities/config/index.js.map +1 -0
- package/dist/src/capabilities/config/runField.js +59 -0
- package/dist/src/capabilities/config/runField.js.map +1 -0
- package/dist/src/capabilities/config/runGet.js +28 -0
- package/dist/src/capabilities/config/runGet.js.map +1 -0
- package/dist/src/capabilities/config/runSet.js +53 -0
- package/dist/src/capabilities/config/runSet.js.map +1 -0
- package/dist/src/capabilities/config/set.verb.js +66 -0
- package/dist/src/capabilities/config/set.verb.js.map +1 -0
- package/dist/src/capabilities/config/show.render.js +84 -0
- package/dist/src/capabilities/config/show.render.js.map +1 -0
- package/dist/src/capabilities/config/show.verb.js +44 -0
- package/dist/src/capabilities/config/show.verb.js.map +1 -0
- package/dist/src/capabilities/config/types.js +5 -0
- package/dist/src/capabilities/config/types.js.map +1 -0
- package/dist/src/capabilities/config/unset.verb.js +49 -0
- package/dist/src/capabilities/config/unset.verb.js.map +1 -0
- package/dist/src/capabilities/create/cliProjection.js +195 -0
- package/dist/src/capabilities/create/cliProjection.js.map +1 -0
- package/dist/src/capabilities/create/constants.js +47 -0
- package/dist/src/capabilities/create/constants.js.map +1 -0
- package/dist/src/capabilities/create/create.render.js +100 -0
- package/dist/src/capabilities/create/create.render.js.map +1 -0
- package/dist/src/capabilities/create/create.verb.js +438 -0
- package/dist/src/capabilities/create/create.verb.js.map +1 -0
- package/dist/src/capabilities/create/createHelp.js +47 -0
- package/dist/src/capabilities/create/createHelp.js.map +1 -0
- package/dist/src/capabilities/create/createSurface.generated.js +394 -0
- package/dist/src/capabilities/create/createSurface.generated.js.map +1 -0
- package/dist/src/capabilities/create/generatorToVerbSpec.js +106 -0
- package/dist/src/capabilities/create/generatorToVerbSpec.js.map +1 -0
- package/dist/src/capabilities/create/index.js +18 -0
- package/dist/src/capabilities/create/index.js.map +1 -0
- package/dist/src/capabilities/create/messages.js +16 -0
- package/dist/src/capabilities/create/messages.js.map +1 -0
- package/dist/src/capabilities/create/mount.js +293 -0
- package/dist/src/capabilities/create/mount.js.map +1 -0
- package/dist/src/capabilities/create/pathJail.js +65 -0
- package/dist/src/capabilities/create/pathJail.js.map +1 -0
- package/dist/src/capabilities/create/pickGenerator.js +53 -0
- package/dist/src/capabilities/create/pickGenerator.js.map +1 -0
- package/dist/src/capabilities/create/types.js +2 -0
- package/dist/src/capabilities/create/types.js.map +1 -0
- package/dist/src/capabilities/distribution.js +40 -0
- package/dist/src/capabilities/distribution.js.map +1 -0
- package/dist/src/capabilities/doctor/checks/checkKeStore.js +40 -0
- package/dist/src/capabilities/doctor/checks/checkKeStore.js.map +1 -0
- package/dist/src/capabilities/doctor/checks/checkNodeVersion.js +21 -0
- package/dist/src/capabilities/doctor/checks/checkNodeVersion.js.map +1 -0
- package/dist/src/capabilities/doctor/checks/checkPackageRefs.js +92 -0
- package/dist/src/capabilities/doctor/checks/checkPackageRefs.js.map +1 -0
- package/dist/src/capabilities/doctor/checks/checkPragmaVersion.js +19 -0
- package/dist/src/capabilities/doctor/checks/checkPragmaVersion.js.map +1 -0
- package/dist/src/capabilities/doctor/checks/checkShellCompletions.js +199 -0
- package/dist/src/capabilities/doctor/checks/checkShellCompletions.js.map +1 -0
- package/dist/src/capabilities/doctor/checks/index.js +27 -0
- package/dist/src/capabilities/doctor/checks/index.js.map +1 -0
- package/dist/src/capabilities/doctor/checks/mcpCommand.js +57 -0
- package/dist/src/capabilities/doctor/checks/mcpCommand.js.map +1 -0
- package/dist/src/capabilities/doctor/checks/targetHealth.js +205 -0
- package/dist/src/capabilities/doctor/checks/targetHealth.js.map +1 -0
- package/dist/src/capabilities/doctor/doctor.render.js +185 -0
- package/dist/src/capabilities/doctor/doctor.render.js.map +1 -0
- package/dist/src/capabilities/doctor/doctor.verb.js +45 -0
- package/dist/src/capabilities/doctor/doctor.verb.js.map +1 -0
- package/dist/src/capabilities/doctor/index.js +5 -0
- package/dist/src/capabilities/doctor/index.js.map +1 -0
- package/dist/src/capabilities/doctor/runChecks.js +83 -0
- package/dist/src/capabilities/doctor/runChecks.js.map +1 -0
- package/dist/src/capabilities/doctor/types.js +5 -0
- package/dist/src/capabilities/doctor/types.js.map +1 -0
- package/dist/src/capabilities/graph/index.js +19 -0
- package/dist/src/capabilities/graph/index.js.map +1 -0
- package/dist/src/capabilities/graph/inspect.render.js +76 -0
- package/dist/src/capabilities/graph/inspect.render.js.map +1 -0
- package/dist/src/capabilities/graph/inspect.verb.js +53 -0
- package/dist/src/capabilities/graph/inspect.verb.js.map +1 -0
- package/dist/src/capabilities/graph/query.render.js +73 -0
- package/dist/src/capabilities/graph/query.render.js.map +1 -0
- package/dist/src/capabilities/graph/query.verb.js +49 -0
- package/dist/src/capabilities/graph/query.verb.js.map +1 -0
- package/dist/src/capabilities/graph/runQuery.js +41 -0
- package/dist/src/capabilities/graph/runQuery.js.map +1 -0
- package/dist/src/capabilities/index.js +56 -0
- package/dist/src/capabilities/index.js.map +1 -0
- package/dist/src/capabilities/info/collectInfo.js +66 -0
- package/dist/src/capabilities/info/collectInfo.js.map +1 -0
- package/dist/src/capabilities/info/index.js +5 -0
- package/dist/src/capabilities/info/index.js.map +1 -0
- package/dist/src/capabilities/info/info.render.js +53 -0
- package/dist/src/capabilities/info/info.render.js.map +1 -0
- package/dist/src/capabilities/info/info.verb.js +42 -0
- package/dist/src/capabilities/info/info.verb.js.map +1 -0
- package/dist/src/capabilities/info/types.js +5 -0
- package/dist/src/capabilities/info/types.js.map +1 -0
- package/dist/src/capabilities/meta/complete.verb.js +43 -0
- package/dist/src/capabilities/meta/complete.verb.js.map +1 -0
- package/dist/src/capabilities/meta/index.js +13 -0
- package/dist/src/capabilities/meta/index.js.map +1 -0
- package/dist/src/capabilities/meta/mcp.verb.js +34 -0
- package/dist/src/capabilities/meta/mcp.verb.js.map +1 -0
- package/dist/src/capabilities/ontology/index.js +21 -0
- package/dist/src/capabilities/ontology/index.js.map +1 -0
- package/dist/src/capabilities/ontology/queries.js +123 -0
- package/dist/src/capabilities/ontology/queries.js.map +1 -0
- package/dist/src/capabilities/ontology/render.js +66 -0
- package/dist/src/capabilities/ontology/render.js.map +1 -0
- package/dist/src/capabilities/ontology/verbs.js +181 -0
- package/dist/src/capabilities/ontology/verbs.js.map +1 -0
- package/dist/src/capabilities/prompt/index.js +16 -0
- package/dist/src/capabilities/prompt/index.js.map +1 -0
- package/dist/src/capabilities/prompt/prompt.render.js +78 -0
- package/dist/src/capabilities/prompt/prompt.render.js.map +1 -0
- package/dist/src/capabilities/prompt/types.js +10 -0
- package/dist/src/capabilities/prompt/types.js.map +1 -0
- package/dist/src/capabilities/prompt/verbs.js +93 -0
- package/dist/src/capabilities/prompt/verbs.js.map +1 -0
- package/dist/src/capabilities/resources/index.js +10 -0
- package/dist/src/capabilities/resources/index.js.map +1 -0
- package/dist/src/capabilities/resources/provider.js +423 -0
- package/dist/src/capabilities/resources/provider.js.map +1 -0
- package/dist/src/capabilities/setup/buildPlan.js +168 -0
- package/dist/src/capabilities/setup/buildPlan.js.map +1 -0
- package/dist/src/capabilities/setup/index.js +5 -0
- package/dist/src/capabilities/setup/index.js.map +1 -0
- package/dist/src/capabilities/setup/mode.js +53 -0
- package/dist/src/capabilities/setup/mode.js.map +1 -0
- package/dist/src/capabilities/setup/operations/index.js +39 -0
- package/dist/src/capabilities/setup/operations/index.js.map +1 -0
- package/dist/src/capabilities/setup/operations/setupCompletions.js +160 -0
- package/dist/src/capabilities/setup/operations/setupCompletions.js.map +1 -0
- package/dist/src/capabilities/setup/operations/setupConfig.js +101 -0
- package/dist/src/capabilities/setup/operations/setupConfig.js.map +1 -0
- package/dist/src/capabilities/setup/operations/setupGenerator.js +343 -0
- package/dist/src/capabilities/setup/operations/setupGenerator.js.map +1 -0
- package/dist/src/capabilities/setup/operations/setupLsp.js +277 -0
- package/dist/src/capabilities/setup/operations/setupLsp.js.map +1 -0
- package/dist/src/capabilities/setup/operations/setupMcp.js +207 -0
- package/dist/src/capabilities/setup/operations/setupMcp.js.map +1 -0
- package/dist/src/capabilities/setup/operations/setupSkills.js +316 -0
- package/dist/src/capabilities/setup/operations/setupSkills.js.map +1 -0
- package/dist/src/capabilities/setup/plan.js +128 -0
- package/dist/src/capabilities/setup/plan.js.map +1 -0
- package/dist/src/capabilities/setup/plan.render.js +193 -0
- package/dist/src/capabilities/setup/plan.render.js.map +1 -0
- package/dist/src/capabilities/setup/setup.render.js +54 -0
- package/dist/src/capabilities/setup/setup.render.js.map +1 -0
- package/dist/src/capabilities/setup/setup.verb.js +334 -0
- package/dist/src/capabilities/setup/setup.verb.js.map +1 -0
- package/dist/src/capabilities/setup/shell.js +196 -0
- package/dist/src/capabilities/setup/shell.js.map +1 -0
- package/dist/src/capabilities/setup/targets.js +263 -0
- package/dist/src/capabilities/setup/targets.js.map +1 -0
- package/dist/src/capabilities/setup/types.js +5 -0
- package/dist/src/capabilities/setup/types.js.map +1 -0
- package/dist/src/capabilities/shared/assertExecOk.js +137 -0
- package/dist/src/capabilities/shared/assertExecOk.js.map +1 -0
- package/dist/src/capabilities/shared/bands.js +16 -0
- package/dist/src/capabilities/shared/bands.js.map +1 -0
- package/dist/src/capabilities/shared/index.js +26 -0
- package/dist/src/capabilities/shared/index.js.map +1 -0
- package/dist/src/capabilities/shared/packageManager.js +103 -0
- package/dist/src/capabilities/shared/packageManager.js.map +1 -0
- package/dist/src/capabilities/shared/registry.js +55 -0
- package/dist/src/capabilities/shared/registry.js.map +1 -0
- package/dist/src/capabilities/skill/discover.js +195 -0
- package/dist/src/capabilities/skill/discover.js.map +1 -0
- package/dist/src/capabilities/skill/index.js +10 -0
- package/dist/src/capabilities/skill/index.js.map +1 -0
- package/dist/src/capabilities/skill/render.js +49 -0
- package/dist/src/capabilities/skill/render.js.map +1 -0
- package/dist/src/capabilities/skill/verbs.js +83 -0
- package/dist/src/capabilities/skill/verbs.js.map +1 -0
- package/dist/src/capabilities/sources/collectStatus.js +103 -0
- package/dist/src/capabilities/sources/collectStatus.js.map +1 -0
- package/dist/src/capabilities/sources/index.js +13 -0
- package/dist/src/capabilities/sources/index.js.map +1 -0
- package/dist/src/capabilities/sources/installSkills.js +167 -0
- package/dist/src/capabilities/sources/installSkills.js.map +1 -0
- package/dist/src/capabilities/sources/runUpdate.js +394 -0
- package/dist/src/capabilities/sources/runUpdate.js.map +1 -0
- package/dist/src/capabilities/sources/status.render.js +64 -0
- package/dist/src/capabilities/sources/status.render.js.map +1 -0
- package/dist/src/capabilities/sources/status.verb.js +40 -0
- package/dist/src/capabilities/sources/status.verb.js.map +1 -0
- package/dist/src/capabilities/sources/types.js +6 -0
- package/dist/src/capabilities/sources/types.js.map +1 -0
- package/dist/src/capabilities/sources/update.render.js +34 -0
- package/dist/src/capabilities/sources/update.render.js.map +1 -0
- package/dist/src/capabilities/sources/update.verb.js +55 -0
- package/dist/src/capabilities/sources/update.verb.js.map +1 -0
- package/dist/src/capabilities/upgrade/index.js +5 -0
- package/dist/src/capabilities/upgrade/index.js.map +1 -0
- package/dist/src/capabilities/upgrade/runUpgrade.js +99 -0
- package/dist/src/capabilities/upgrade/runUpgrade.js.map +1 -0
- package/dist/src/capabilities/upgrade/types.js +5 -0
- package/dist/src/capabilities/upgrade/types.js.map +1 -0
- package/dist/src/capabilities/upgrade/upgrade.render.js +44 -0
- package/dist/src/capabilities/upgrade/upgrade.render.js.map +1 -0
- package/dist/src/capabilities/upgrade/upgrade.verb.js +52 -0
- package/dist/src/capabilities/upgrade/upgrade.verb.js.map +1 -0
- package/dist/src/capabilities/version/index.js +10 -0
- package/dist/src/capabilities/version/index.js.map +1 -0
- package/dist/src/capabilities/version/version.verb.js +36 -0
- package/dist/src/capabilities/version/version.verb.js.map +1 -0
- package/dist/src/constants.js +82 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/index.js +12 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/kernel/completion/complete.js +66 -0
- package/dist/src/kernel/completion/complete.js.map +1 -0
- package/dist/src/kernel/completion/emitScripts.js +92 -0
- package/dist/src/kernel/completion/emitScripts.js.map +1 -0
- package/dist/src/kernel/completion/entitySource.js +285 -0
- package/dist/src/kernel/completion/entitySource.js.map +1 -0
- package/dist/src/kernel/completion/index.js +14 -0
- package/dist/src/kernel/completion/index.js.map +1 -0
- package/dist/src/kernel/completion/model.js +301 -0
- package/dist/src/kernel/completion/model.js.map +1 -0
- package/dist/src/kernel/completion/parse.js +253 -0
- package/dist/src/kernel/completion/parse.js.map +1 -0
- package/dist/src/kernel/completion/rank.js +101 -0
- package/dist/src/kernel/completion/rank.js.map +1 -0
- package/dist/src/kernel/completion/resolve.js +100 -0
- package/dist/src/kernel/completion/resolve.js.map +1 -0
- package/dist/src/kernel/completion/templates/bash.js +209 -0
- package/dist/src/kernel/completion/templates/bash.js.map +1 -0
- package/dist/src/kernel/completion/templates/fish.js +214 -0
- package/dist/src/kernel/completion/templates/fish.js.map +1 -0
- package/dist/src/kernel/completion/templates/index.js +23 -0
- package/dist/src/kernel/completion/templates/index.js.map +1 -0
- package/dist/src/kernel/completion/templates/shared.js +98 -0
- package/dist/src/kernel/completion/templates/shared.js.map +1 -0
- package/dist/src/kernel/completion/templates/zsh.js +201 -0
- package/dist/src/kernel/completion/templates/zsh.js.map +1 -0
- package/dist/src/kernel/completion/types.js +13 -0
- package/dist/src/kernel/completion/types.js.map +1 -0
- package/dist/src/kernel/config/defaults.js +17 -0
- package/dist/src/kernel/config/defaults.js.map +1 -0
- package/dist/src/kernel/config/evaluateProjectConfig.js +126 -0
- package/dist/src/kernel/config/evaluateProjectConfig.js.map +1 -0
- package/dist/src/kernel/config/findProjectConfig.js +43 -0
- package/dist/src/kernel/config/findProjectConfig.js.map +1 -0
- package/dist/src/kernel/config/firstRun.js +34 -0
- package/dist/src/kernel/config/firstRun.js.map +1 -0
- package/dist/src/kernel/config/globalConfig.js +79 -0
- package/dist/src/kernel/config/globalConfig.js.map +1 -0
- package/dist/src/kernel/config/index.js +16 -0
- package/dist/src/kernel/config/index.js.map +1 -0
- package/dist/src/kernel/config/paths.js +35 -0
- package/dist/src/kernel/config/paths.js.map +1 -0
- package/dist/src/kernel/config/readConfig.js +78 -0
- package/dist/src/kernel/config/readConfig.js.map +1 -0
- package/dist/src/kernel/config/schema.js +130 -0
- package/dist/src/kernel/config/schema.js.map +1 -0
- package/dist/src/kernel/config/types.js +19 -0
- package/dist/src/kernel/config/types.js.map +1 -0
- package/dist/src/kernel/config/writeConfigField.js +59 -0
- package/dist/src/kernel/config/writeConfigField.js.map +1 -0
- package/dist/src/kernel/copy.js +43 -0
- package/dist/src/kernel/copy.js.map +1 -0
- package/dist/src/kernel/error/PragmaError.js +149 -0
- package/dist/src/kernel/error/PragmaError.js.map +1 -0
- package/dist/src/kernel/error/constants.js +40 -0
- package/dist/src/kernel/error/constants.js.map +1 -0
- package/dist/src/kernel/error/fromTaskError.js +96 -0
- package/dist/src/kernel/error/fromTaskError.js.map +1 -0
- package/dist/src/kernel/error/index.js +13 -0
- package/dist/src/kernel/error/index.js.map +1 -0
- package/dist/src/kernel/error/recovery.js +52 -0
- package/dist/src/kernel/error/recovery.js.map +1 -0
- package/dist/src/kernel/error/renderError.js +115 -0
- package/dist/src/kernel/error/renderError.js.map +1 -0
- package/dist/src/kernel/error/serialize.js +25 -0
- package/dist/src/kernel/error/serialize.js.map +1 -0
- package/dist/src/kernel/error/types.js +9 -0
- package/dist/src/kernel/error/types.js.map +1 -0
- package/dist/src/kernel/index.js +25 -0
- package/dist/src/kernel/index.js.map +1 -0
- package/dist/src/kernel/packs/collect.js +187 -0
- package/dist/src/kernel/packs/collect.js.map +1 -0
- package/dist/src/kernel/packs/compile.js +304 -0
- package/dist/src/kernel/packs/compile.js.map +1 -0
- package/dist/src/kernel/packs/disclosure.js +76 -0
- package/dist/src/kernel/packs/disclosure.js.map +1 -0
- package/dist/src/kernel/packs/glob.js +38 -0
- package/dist/src/kernel/packs/glob.js.map +1 -0
- package/dist/src/kernel/packs/graphql/buildLookupDocument.js +258 -0
- package/dist/src/kernel/packs/graphql/buildLookupDocument.js.map +1 -0
- package/dist/src/kernel/packs/graphql/fetchGraphqlLookup.js +157 -0
- package/dist/src/kernel/packs/graphql/fetchGraphqlLookup.js.map +1 -0
- package/dist/src/kernel/packs/graphql/index.js +20 -0
- package/dist/src/kernel/packs/graphql/index.js.map +1 -0
- package/dist/src/kernel/packs/graphql/nameMap.js +63 -0
- package/dist/src/kernel/packs/graphql/nameMap.js.map +1 -0
- package/dist/src/kernel/packs/index.js +34 -0
- package/dist/src/kernel/packs/index.js.map +1 -0
- package/dist/src/kernel/packs/iri.js +110 -0
- package/dist/src/kernel/packs/iri.js.map +1 -0
- package/dist/src/kernel/packs/renderPack.js +129 -0
- package/dist/src/kernel/packs/renderPack.js.map +1 -0
- package/dist/src/kernel/packs/resolveEntity.js +223 -0
- package/dist/src/kernel/packs/resolveEntity.js.map +1 -0
- package/dist/src/kernel/packs/runBodies.js +87 -0
- package/dist/src/kernel/packs/runBodies.js.map +1 -0
- package/dist/src/kernel/packs/sample.js +56 -0
- package/dist/src/kernel/packs/sample.js.map +1 -0
- package/dist/src/kernel/packs/schema.js +369 -0
- package/dist/src/kernel/packs/schema.js.map +1 -0
- package/dist/src/kernel/packs/sparql/applyFilters.js +68 -0
- package/dist/src/kernel/packs/sparql/applyFilters.js.map +1 -0
- package/dist/src/kernel/packs/sparql/applySearch.js +25 -0
- package/dist/src/kernel/packs/sparql/applySearch.js.map +1 -0
- package/dist/src/kernel/packs/sparql/buildLookupQuery.js +217 -0
- package/dist/src/kernel/packs/sparql/buildLookupQuery.js.map +1 -0
- package/dist/src/kernel/packs/sparql/escape.js +21 -0
- package/dist/src/kernel/packs/sparql/escape.js.map +1 -0
- package/dist/src/kernel/packs/sparql/index.js +31 -0
- package/dist/src/kernel/packs/sparql/index.js.map +1 -0
- package/dist/src/kernel/packs/sparql/runSelect.js +101 -0
- package/dist/src/kernel/packs/sparql/runSelect.js.map +1 -0
- package/dist/src/kernel/packs/types.js +30 -0
- package/dist/src/kernel/packs/types.js.map +1 -0
- package/dist/src/kernel/packs/uniqueness.js +30 -0
- package/dist/src/kernel/packs/uniqueness.js.map +1 -0
- package/dist/src/kernel/project/cli/buildProgram.js +263 -0
- package/dist/src/kernel/project/cli/buildProgram.js.map +1 -0
- package/dist/src/kernel/project/cli/constants.js +27 -0
- package/dist/src/kernel/project/cli/constants.js.map +1 -0
- package/dist/src/kernel/project/cli/dispatch.js +420 -0
- package/dist/src/kernel/project/cli/dispatch.js.map +1 -0
- package/dist/src/kernel/project/cli/exitCodes.js +66 -0
- package/dist/src/kernel/project/cli/exitCodes.js.map +1 -0
- package/dist/src/kernel/project/cli/globalFlags.js +216 -0
- package/dist/src/kernel/project/cli/globalFlags.js.map +1 -0
- package/dist/src/kernel/project/cli/helpFormat.js +59 -0
- package/dist/src/kernel/project/cli/helpFormat.js.map +1 -0
- package/dist/src/kernel/project/cli/index.js +14 -0
- package/dist/src/kernel/project/cli/index.js.map +1 -0
- package/dist/src/kernel/project/cli/rootHelp.js +197 -0
- package/dist/src/kernel/project/cli/rootHelp.js.map +1 -0
- package/dist/src/kernel/project/cli/suggest.js +75 -0
- package/dist/src/kernel/project/cli/suggest.js.map +1 -0
- package/dist/src/kernel/project/cli/suggestNames.js +96 -0
- package/dist/src/kernel/project/cli/suggestNames.js.map +1 -0
- package/dist/src/kernel/project/cli/verbHelp.js +131 -0
- package/dist/src/kernel/project/cli/verbHelp.js.map +1 -0
- package/dist/src/kernel/project/mcp/buildServer.js +67 -0
- package/dist/src/kernel/project/mcp/buildServer.js.map +1 -0
- package/dist/src/kernel/project/mcp/envelope.js +37 -0
- package/dist/src/kernel/project/mcp/envelope.js.map +1 -0
- package/dist/src/kernel/project/mcp/index.js +8 -0
- package/dist/src/kernel/project/mcp/index.js.map +1 -0
- package/dist/src/kernel/project/mcp/instructions.js +44 -0
- package/dist/src/kernel/project/mcp/instructions.js.map +1 -0
- package/dist/src/kernel/project/mcp/mcpError.js +42 -0
- package/dist/src/kernel/project/mcp/mcpError.js.map +1 -0
- package/dist/src/kernel/project/mcp/prompts/index.js +36 -0
- package/dist/src/kernel/project/mcp/prompts/index.js.map +1 -0
- package/dist/src/kernel/project/mcp/prompts/provider.js +98 -0
- package/dist/src/kernel/project/mcp/prompts/provider.js.map +1 -0
- package/dist/src/kernel/project/mcp/prompts/source.js +154 -0
- package/dist/src/kernel/project/mcp/prompts/source.js.map +1 -0
- package/dist/src/kernel/project/mcp/registerVerb.js +300 -0
- package/dist/src/kernel/project/mcp/registerVerb.js.map +1 -0
- package/dist/src/kernel/project/mcp/serve.js +35 -0
- package/dist/src/kernel/project/mcp/serve.js.map +1 -0
- package/dist/src/kernel/render/compactUri.js +24 -0
- package/dist/src/kernel/render/compactUri.js.map +1 -0
- package/dist/src/kernel/render/contracts.js +10 -0
- package/dist/src/kernel/render/contracts.js.map +1 -0
- package/dist/src/kernel/render/disclosure.js +34 -0
- package/dist/src/kernel/render/disclosure.js.map +1 -0
- package/dist/src/kernel/render/envelope.js +30 -0
- package/dist/src/kernel/render/envelope.js.map +1 -0
- package/dist/src/kernel/render/formatters.js +27 -0
- package/dist/src/kernel/render/formatters.js.map +1 -0
- package/dist/src/kernel/render/index.js +15 -0
- package/dist/src/kernel/render/index.js.map +1 -0
- package/dist/src/kernel/render/prefixes.js +46 -0
- package/dist/src/kernel/render/prefixes.js.map +1 -0
- package/dist/src/kernel/render/renderers.js +468 -0
- package/dist/src/kernel/render/renderers.js.map +1 -0
- package/dist/src/kernel/render/style.js +85 -0
- package/dist/src/kernel/render/style.js.map +1 -0
- package/dist/src/kernel/render/turtle.js +194 -0
- package/dist/src/kernel/render/turtle.js.map +1 -0
- package/dist/src/kernel/render/writeStdout.js +43 -0
- package/dist/src/kernel/render/writeStdout.js.map +1 -0
- package/dist/src/kernel/runtime/boot.js +49 -0
- package/dist/src/kernel/runtime/boot.js.map +1 -0
- package/dist/src/kernel/runtime/facade.js +39 -0
- package/dist/src/kernel/runtime/facade.js.map +1 -0
- package/dist/src/kernel/runtime/graphpack/build.js +122 -0
- package/dist/src/kernel/runtime/graphpack/build.js.map +1 -0
- package/dist/src/kernel/runtime/graphpack/buildIndex.js +303 -0
- package/dist/src/kernel/runtime/graphpack/buildIndex.js.map +1 -0
- package/dist/src/kernel/runtime/graphpack/embedded/pack.generated.js +6 -0
- package/dist/src/kernel/runtime/graphpack/embedded/pack.generated.js.map +1 -0
- package/dist/src/kernel/runtime/graphpack/embedded/pack.index.generated.js +4 -0
- package/dist/src/kernel/runtime/graphpack/embedded/pack.index.generated.js.map +1 -0
- package/dist/src/kernel/runtime/graphpack/embedded/pack.stories.generated.js +4 -0
- package/dist/src/kernel/runtime/graphpack/embedded/pack.stories.generated.js.map +1 -0
- package/dist/src/kernel/runtime/graphpack/embedded.js +82 -0
- package/dist/src/kernel/runtime/graphpack/embedded.js.map +1 -0
- package/dist/src/kernel/runtime/graphpack/hash.js +38 -0
- package/dist/src/kernel/runtime/graphpack/hash.js.map +1 -0
- package/dist/src/kernel/runtime/graphpack/index.js +11 -0
- package/dist/src/kernel/runtime/graphpack/index.js.map +1 -0
- package/dist/src/kernel/runtime/graphpack/manifest.js +145 -0
- package/dist/src/kernel/runtime/graphpack/manifest.js.map +1 -0
- package/dist/src/kernel/runtime/graphpack/read.js +92 -0
- package/dist/src/kernel/runtime/graphpack/read.js.map +1 -0
- package/dist/src/kernel/runtime/graphpack/schemas.js +70 -0
- package/dist/src/kernel/runtime/graphpack/schemas.js.map +1 -0
- package/dist/src/kernel/runtime/graphpack/stories.js +68 -0
- package/dist/src/kernel/runtime/graphpack/stories.js.map +1 -0
- package/dist/src/kernel/runtime/graphpack/types.js +55 -0
- package/dist/src/kernel/runtime/graphpack/types.js.map +1 -0
- package/dist/src/kernel/runtime/index.js +8 -0
- package/dist/src/kernel/runtime/index.js.map +1 -0
- package/dist/src/kernel/runtime/loadSession.js +34 -0
- package/dist/src/kernel/runtime/loadSession.js.map +1 -0
- package/dist/src/kernel/runtime/paths.js +78 -0
- package/dist/src/kernel/runtime/paths.js.map +1 -0
- package/dist/src/kernel/runtime/probe.js +37 -0
- package/dist/src/kernel/runtime/probe.js.map +1 -0
- package/dist/src/kernel/runtime/readEntity.js +363 -0
- package/dist/src/kernel/runtime/readEntity.js.map +1 -0
- package/dist/src/kernel/runtime/refs/gitOps.js +65 -0
- package/dist/src/kernel/runtime/refs/gitOps.js.map +1 -0
- package/dist/src/kernel/runtime/refs/index.js +29 -0
- package/dist/src/kernel/runtime/refs/index.js.map +1 -0
- package/dist/src/kernel/runtime/refs/parseRef.js +70 -0
- package/dist/src/kernel/runtime/refs/parseRef.js.map +1 -0
- package/dist/src/kernel/runtime/refs/resolve.js +332 -0
- package/dist/src/kernel/runtime/refs/resolve.js.map +1 -0
- package/dist/src/kernel/runtime/resolveSources.js +62 -0
- package/dist/src/kernel/runtime/resolveSources.js.map +1 -0
- package/dist/src/kernel/runtime/store.js +75 -0
- package/dist/src/kernel/runtime/store.js.map +1 -0
- package/dist/src/kernel/runtime/storeReadiness.js +51 -0
- package/dist/src/kernel/runtime/storeReadiness.js.map +1 -0
- package/dist/src/kernel/runtime/types.js +11 -0
- package/dist/src/kernel/runtime/types.js.map +1 -0
- package/dist/src/kernel/spec/asVerb.js +21 -0
- package/dist/src/kernel/spec/asVerb.js.map +1 -0
- package/dist/src/kernel/spec/emitReference.js +578 -0
- package/dist/src/kernel/spec/emitReference.js.map +1 -0
- package/dist/src/kernel/spec/emitSurface.js +202 -0
- package/dist/src/kernel/spec/emitSurface.js.map +1 -0
- package/dist/src/kernel/spec/index.js +11 -0
- package/dist/src/kernel/spec/index.js.map +1 -0
- package/dist/src/kernel/spec/surfaceConformance.js +103 -0
- package/dist/src/kernel/spec/surfaceConformance.js.map +1 -0
- package/dist/src/kernel/spec/types.js +14 -0
- package/dist/src/kernel/spec/types.js.map +1 -0
- package/dist/src/kernel/spec/validate.js +110 -0
- package/dist/src/kernel/spec/validate.js.map +1 -0
- package/dist/src/kernel/vocabulary.js +97 -0
- package/dist/src/kernel/vocabulary.js.map +1 -0
- package/dist/src/types.js +11 -0
- package/dist/src/types.js.map +1 -0
- package/package.json +25 -24
- package/pragma.conf.ts +853 -0
- package/src/bin.ts +276 -82
- package/src/capabilities/block.parity.test.ts +253 -0
- package/src/capabilities/capabilities/capabilities.render.ts +4 -3
- package/src/capabilities/capabilities/capabilities.verb.ts +32 -14
- package/src/capabilities/capabilities/catalog.ts +20 -12
- package/src/capabilities/capabilities/hints.ts +43 -24
- package/src/capabilities/capabilities/index.ts +1 -1
- package/src/capabilities/colophon/collectColophon.ts +50 -24
- package/src/capabilities/colophon/colophon.render.ts +25 -1
- package/src/capabilities/colophon/colophon.test.ts +42 -21
- package/src/capabilities/colophon/colophon.verb.ts +9 -5
- package/src/capabilities/colophon/types.ts +16 -7
- package/src/capabilities/config/collectConfigShow.test.ts +58 -0
- package/src/capabilities/config/collectConfigShow.ts +43 -6
- package/src/capabilities/config/field.render.ts +4 -5
- package/src/capabilities/config/fields.ts +17 -37
- package/src/capabilities/config/get.verb.ts +70 -0
- package/src/capabilities/config/getUnset.test.ts +264 -0
- package/src/capabilities/config/index.ts +5 -1
- package/src/capabilities/config/runField.ts +40 -22
- package/src/capabilities/config/runGet.ts +34 -0
- package/src/capabilities/config/runSet.ts +35 -9
- package/src/capabilities/config/set.test.ts +48 -14
- package/src/capabilities/config/set.verb.ts +14 -9
- package/src/capabilities/config/show.render.test.ts +77 -5
- package/src/capabilities/config/show.render.ts +8 -13
- package/src/capabilities/config/show.verb.ts +13 -9
- package/src/capabilities/config/types.ts +26 -4
- package/src/capabilities/config/unset.verb.ts +58 -0
- package/src/capabilities/create/byteEquality.subprocess.test.ts +2 -3
- package/src/capabilities/create/byteEquality.test.ts +95 -103
- package/src/capabilities/create/cliProjection.ts +227 -0
- package/src/capabilities/create/constants.ts +50 -0
- package/src/capabilities/create/create.mcp.test.ts +91 -7
- package/src/capabilities/create/create.render.ts +71 -7
- package/src/capabilities/create/create.test.ts +523 -162
- package/src/capabilities/create/create.verb.ts +361 -321
- package/src/capabilities/create/createGrammar.test.ts +865 -0
- package/src/capabilities/create/createHelp.ts +71 -0
- package/src/capabilities/create/createSurface.generated.ts +400 -0
- package/src/capabilities/create/crossCli.subprocess.test.ts +745 -0
- package/src/capabilities/create/cwdJail.test.ts +24 -5
- package/src/capabilities/create/generatorToVerbSpec.test.ts +186 -0
- package/src/capabilities/create/generatorToVerbSpec.ts +13 -11
- package/src/capabilities/create/index.ts +9 -14
- package/src/capabilities/create/messages.ts +18 -0
- package/src/capabilities/create/mount.ts +391 -0
- package/src/capabilities/create/pathJail.test.ts +90 -0
- package/src/capabilities/create/pathJail.ts +8 -5
- package/src/capabilities/create/pickGenerator.ts +40 -46
- package/src/capabilities/create/shippedCreate.subprocess.test.ts +164 -0
- package/src/capabilities/create/types.ts +29 -5
- package/src/capabilities/{standard/parity.test.ts → distribution.parity.test.ts} +24 -14
- package/src/capabilities/distribution.test.ts +122 -0
- package/src/capabilities/distribution.ts +54 -0
- package/src/capabilities/doctor/checks/checkKeStore.ts +9 -7
- package/src/capabilities/doctor/checks/checkPackageRefs.ts +82 -46
- package/src/capabilities/doctor/checks/checkPragmaVersion.ts +5 -4
- package/src/capabilities/doctor/checks/checkShellCompletions.test.ts +125 -30
- package/src/capabilities/doctor/checks/checkShellCompletions.ts +113 -27
- package/src/capabilities/doctor/checks/index.ts +27 -0
- package/src/capabilities/doctor/checks/mcpCommand.test.ts +100 -0
- package/src/capabilities/doctor/checks/mcpCommand.ts +69 -0
- package/src/capabilities/doctor/checks/targetHealth.ts +274 -0
- package/src/capabilities/doctor/doctor.render.test.ts +24 -13
- package/src/capabilities/doctor/doctor.render.ts +45 -20
- package/src/capabilities/doctor/doctor.test.ts +158 -40
- package/src/capabilities/doctor/doctor.verb.ts +9 -5
- package/src/capabilities/doctor/runChecks.ts +65 -66
- package/src/capabilities/doctor/types.ts +21 -5
- package/src/capabilities/emptyRecovery.test.ts +44 -22
- package/src/capabilities/graph/examples.exec.test.ts +107 -0
- package/src/capabilities/graph/index.ts +1 -1
- package/src/capabilities/graph/inspect.render.ts +70 -22
- package/src/capabilities/graph/inspect.test.ts +260 -5
- package/src/capabilities/graph/inspect.verb.ts +18 -5
- package/src/capabilities/graph/query.render.ts +15 -3
- package/src/capabilities/graph/query.verb.ts +5 -4
- package/src/capabilities/graph/runQuery.ts +9 -7
- package/src/capabilities/index.ts +25 -19
- package/src/capabilities/info/collectInfo.ts +15 -10
- package/src/capabilities/info/info.render.ts +4 -3
- package/src/capabilities/info/info.verb.ts +4 -3
- package/src/capabilities/lazy.test.ts +125 -2
- package/src/capabilities/meta/complete.verb.ts +1 -1
- package/src/capabilities/meta/index.ts +1 -1
- package/src/capabilities/meta/mcp.verb.ts +10 -8
- package/src/capabilities/ontology/index.ts +15 -11
- package/src/capabilities/ontology/ontology.test.ts +6 -55
- package/src/capabilities/ontology/queries.ts +2 -2
- package/src/capabilities/ontology/render.ts +3 -4
- package/src/capabilities/ontology/verbs.ts +42 -83
- package/src/capabilities/prompt/index.ts +2 -2
- package/src/capabilities/prompt/prompt.render.ts +6 -2
- package/src/capabilities/prompt/prompt.test.ts +12 -6
- package/src/capabilities/prompt/types.ts +1 -1
- package/src/capabilities/prompt/verbs.ts +26 -14
- package/src/capabilities/reference.test.ts +63 -0
- package/src/capabilities/resources/provider.ts +367 -91
- package/src/capabilities/resources/resources.test.ts +411 -59
- package/src/capabilities/setup/buildPlan.ts +236 -0
- package/src/capabilities/setup/index.ts +7 -7
- package/src/capabilities/setup/mode.ts +74 -0
- package/src/capabilities/setup/operations/index.ts +74 -0
- package/src/capabilities/setup/operations/setupCompletions.ts +97 -24
- package/src/capabilities/setup/operations/setupConfig.ts +124 -0
- package/src/capabilities/setup/operations/setupGenerator.ts +397 -320
- package/src/capabilities/setup/operations/setupLsp.ts +329 -68
- package/src/capabilities/setup/operations/setupMcp.ts +137 -97
- package/src/capabilities/setup/operations/setupSkills.ts +336 -108
- package/src/capabilities/setup/plan.render.ts +241 -0
- package/src/capabilities/setup/plan.ts +236 -0
- package/src/capabilities/setup/setup.mcp.correctness.test.ts +432 -0
- package/src/capabilities/setup/setup.render.test.ts +281 -73
- package/src/capabilities/setup/setup.render.ts +45 -77
- package/src/capabilities/setup/setup.test.ts +972 -209
- package/src/capabilities/setup/setup.verb.ts +233 -74
- package/src/capabilities/setup/shell.test.ts +86 -0
- package/src/capabilities/setup/shell.ts +166 -14
- package/src/capabilities/setup/targets.ts +367 -0
- package/src/capabilities/setup/types.ts +18 -57
- package/src/capabilities/shared/assertExecOk.ts +68 -10
- package/src/capabilities/shared/index.ts +32 -0
- package/src/capabilities/shared/packageManager.test.ts +55 -0
- package/src/capabilities/shared/packageManager.ts +62 -6
- package/src/capabilities/skill/discover.ts +47 -9
- package/src/capabilities/skill/index.ts +1 -1
- package/src/capabilities/skill/render.ts +14 -14
- package/src/capabilities/skill/skill.test.ts +7 -5
- package/src/capabilities/skill/verbs.ts +9 -10
- package/src/capabilities/sources/collectStatus.ts +61 -51
- package/src/capabilities/sources/index.ts +2 -2
- package/src/capabilities/sources/installSkills.ts +86 -9
- package/src/capabilities/sources/runUpdate.ts +164 -141
- package/src/capabilities/sources/sources.test.ts +265 -119
- package/src/capabilities/sources/status.render.test.ts +53 -24
- package/src/capabilities/sources/status.render.ts +25 -30
- package/src/capabilities/sources/status.verb.ts +16 -9
- package/src/capabilities/sources/types.ts +18 -25
- package/src/capabilities/sources/update.render.ts +10 -3
- package/src/capabilities/sources/update.verb.ts +13 -24
- package/src/capabilities/surface.test.ts +165 -25
- package/src/capabilities/tier.parity.test.ts +144 -0
- package/src/capabilities/upgrade/runUpgrade.ts +8 -8
- package/src/capabilities/upgrade/upgrade.render.ts +4 -5
- package/src/capabilities/upgrade/upgrade.test.ts +3 -3
- package/src/capabilities/upgrade/upgrade.verb.ts +8 -4
- package/src/capabilities/version/index.ts +12 -0
- package/src/capabilities/version/version.test.ts +66 -0
- package/src/capabilities/version/version.verb.ts +39 -0
- package/src/constants.test.ts +8 -6
- package/src/constants.ts +78 -22
- package/src/identity.test.ts +348 -0
- package/src/index.ts +2 -2
- package/src/kernel/completion/__snapshots__/emitScripts.test.ts.snap +20 -15
- package/src/kernel/completion/complete.test.ts +12 -2
- package/src/kernel/completion/complete.ts +1 -1
- package/src/kernel/completion/emitScripts.test.ts +1 -1
- package/src/kernel/completion/emitScripts.ts +5 -3
- package/src/kernel/completion/entitySource.test.ts +185 -41
- package/src/kernel/completion/entitySource.ts +133 -110
- package/src/kernel/completion/model.test.ts +165 -13
- package/src/kernel/completion/model.ts +105 -14
- package/src/kernel/completion/parse.test.ts +4 -7
- package/src/kernel/completion/parse.ts +15 -0
- package/src/kernel/completion/resolve.test.ts +0 -1
- package/src/kernel/completion/safety.test.ts +104 -50
- package/src/kernel/completion/shellDrive.test.ts +611 -0
- package/src/kernel/completion/templates/bash.ts +7 -2
- package/src/kernel/completion/templates/fish.ts +28 -6
- package/src/kernel/completion/templates/index.ts +23 -0
- package/src/kernel/completion/types.ts +10 -3
- package/src/kernel/config/defaults.test.ts +108 -0
- package/src/kernel/config/defaults.ts +13 -23
- package/src/kernel/config/evaluateProjectConfig.ts +33 -11
- package/src/kernel/config/findProjectConfig.ts +4 -3
- package/src/kernel/config/firstRun.test.ts +44 -38
- package/src/kernel/config/firstRun.ts +24 -81
- package/src/kernel/config/globalConfig.ts +2 -2
- package/src/kernel/config/index.ts +5 -6
- package/src/kernel/config/paths.ts +17 -17
- package/src/kernel/config/readConfig.test.ts +246 -7
- package/src/kernel/config/readConfig.ts +8 -8
- package/src/kernel/config/schema.test.ts +50 -0
- package/src/kernel/config/schema.ts +100 -11
- package/src/kernel/config/types.ts +75 -19
- package/src/kernel/copy.test.ts +483 -0
- package/src/kernel/copy.ts +54 -0
- package/src/kernel/error/PragmaError.test.ts +6 -3
- package/src/kernel/error/PragmaError.ts +4 -2
- package/src/kernel/error/constants.ts +7 -4
- package/src/kernel/error/fromTaskError.ts +28 -6
- package/src/kernel/error/index.ts +1 -1
- package/src/kernel/error/recovery.test.ts +22 -45
- package/src/kernel/error/recovery.ts +36 -27
- package/src/kernel/error/renderError.ts +42 -1
- package/src/kernel/error/types.ts +25 -4
- package/src/kernel/index.ts +26 -0
- package/src/kernel/packs/collect.test.ts +195 -11
- package/src/kernel/packs/collect.ts +212 -61
- package/src/kernel/packs/compile.test.ts +293 -8
- package/src/kernel/packs/compile.ts +108 -15
- package/src/kernel/packs/disclosure.test.ts +5 -2
- package/src/kernel/packs/disclosure.ts +2 -2
- package/src/kernel/packs/graphql/buildLookupDocument.ts +1 -1
- package/src/kernel/packs/graphql/fetchGraphqlLookup.ts +13 -13
- package/src/kernel/packs/graphql/index.ts +20 -0
- package/src/kernel/packs/graphqlSource.test.ts +6 -3
- package/src/kernel/packs/index.ts +40 -0
- package/src/kernel/packs/iri.test.ts +73 -0
- package/src/kernel/packs/iri.ts +70 -20
- package/src/kernel/packs/renderPack.ts +28 -7
- package/src/kernel/packs/resolveEntity.test.ts +213 -0
- package/src/kernel/packs/resolveEntity.ts +132 -34
- package/src/kernel/packs/runBodies.ts +16 -16
- package/src/kernel/packs/sample.ts +1 -1
- package/src/kernel/packs/schema.ts +114 -11
- package/src/kernel/packs/sparql/applyFilters.ts +16 -17
- package/src/kernel/packs/sparql/buildLookupQuery.ts +75 -3
- package/src/kernel/packs/sparql/index.ts +37 -0
- package/src/kernel/packs/sparql/runSelect.test.ts +104 -10
- package/src/kernel/packs/sparql/runSelect.ts +75 -37
- package/src/kernel/packs/toolDescription.test.ts +52 -5
- package/src/kernel/packs/types.ts +52 -4
- package/src/kernel/packs/uniqueness.ts +5 -5
- package/src/kernel/project/cli/buildProgram.test.ts +157 -17
- package/src/kernel/project/cli/buildProgram.ts +77 -18
- package/src/kernel/project/cli/constants.ts +34 -0
- package/src/kernel/project/cli/dispatch.test.ts +227 -3
- package/src/kernel/project/cli/dispatch.ts +250 -48
- package/src/kernel/project/cli/exitCodes.ts +1 -1
- package/src/kernel/project/cli/globalFlags.test.ts +117 -1
- package/src/kernel/project/cli/globalFlags.ts +130 -30
- package/src/kernel/project/cli/helpFormat.ts +14 -1
- package/src/kernel/project/cli/rootHelp.ts +140 -111
- package/src/kernel/project/cli/suggest.test.ts +33 -1
- package/src/kernel/project/cli/suggest.ts +25 -1
- package/src/kernel/project/cli/verbHelp.test.ts +30 -0
- package/src/kernel/project/cli/verbHelp.ts +23 -7
- package/src/kernel/project/mcp/buildServer.ts +18 -10
- package/src/kernel/project/mcp/envelope.ts +2 -2
- package/src/kernel/project/mcp/instructions.ts +12 -7
- package/src/kernel/project/mcp/mcpError.ts +1 -1
- package/src/kernel/project/mcp/parity.test.ts +42 -1
- package/src/kernel/project/mcp/prompts/index.ts +37 -0
- package/src/kernel/project/mcp/prompts/prompts.test.ts +120 -5
- package/src/kernel/project/mcp/prompts/provider.ts +22 -8
- package/src/kernel/project/mcp/prompts/source.ts +69 -68
- package/src/kernel/project/mcp/registerVerb.ts +56 -11
- package/src/kernel/project/mcp/serve.ts +13 -5
- package/src/kernel/project/mcp/toolDescriptions.test.ts +6 -2
- package/src/kernel/render/__snapshots__/renderers.test.ts.snap +7 -4
- package/src/kernel/render/contracts.ts +21 -0
- package/src/kernel/render/disclosure.ts +4 -2
- package/src/kernel/render/envelope.ts +2 -3
- package/src/kernel/render/formatters.ts +1 -1
- package/src/kernel/render/prefixes.test.ts +36 -0
- package/src/kernel/render/prefixes.ts +40 -13
- package/src/kernel/render/renderers.test.ts +244 -7
- package/src/kernel/render/renderers.ts +222 -20
- package/src/kernel/render/style.test.ts +75 -24
- package/src/kernel/render/style.ts +31 -1
- package/src/kernel/render/turtle.ts +222 -0
- package/src/kernel/runtime/graphpack/build.ts +29 -3
- package/src/kernel/runtime/graphpack/buildIndex.test.ts +46 -0
- package/src/kernel/runtime/graphpack/buildIndex.ts +53 -18
- package/src/kernel/runtime/graphpack/embedded/pack.generated.ts +5 -5
- package/src/kernel/runtime/graphpack/embedded/pack.index.generated.ts +3 -3
- package/src/kernel/runtime/graphpack/embedded/pack.stories.generated.ts +3 -0
- package/src/kernel/runtime/graphpack/embedded.ts +39 -13
- package/src/kernel/runtime/graphpack/graphpack.test.ts +205 -5
- package/src/kernel/runtime/graphpack/hash.ts +3 -2
- package/src/kernel/runtime/graphpack/index.ts +1 -1
- package/src/kernel/runtime/graphpack/manifest.ts +114 -12
- package/src/kernel/runtime/graphpack/read.ts +5 -11
- package/src/kernel/runtime/graphpack/schemas.ts +74 -0
- package/src/kernel/runtime/graphpack/stories.ts +84 -0
- package/src/kernel/runtime/graphpack/types.ts +61 -48
- package/src/kernel/runtime/loadSession.ts +1 -1
- package/src/kernel/runtime/paths.ts +64 -15
- package/src/kernel/runtime/probe.test.ts +8 -4
- package/src/kernel/runtime/probe.ts +6 -6
- package/src/kernel/runtime/readEntity.ts +477 -32
- package/src/kernel/runtime/refs/gitOps.ts +1 -19
- package/src/kernel/runtime/refs/index.ts +39 -0
- package/src/kernel/runtime/refs/parseRef.ts +8 -8
- package/src/kernel/runtime/refs/resolve.ts +82 -66
- package/src/kernel/runtime/resolveSources.test.ts +63 -24
- package/src/kernel/runtime/resolveSources.ts +36 -25
- package/src/kernel/runtime/storeReadiness.ts +10 -10
- package/src/kernel/runtime/storeless.test.ts +1 -1
- package/src/kernel/runtime/types.ts +15 -1
- package/src/kernel/runtime/wasmEmbed.test.ts +56 -55
- package/src/kernel/spec/emitReference.test.ts +3 -3
- package/src/kernel/spec/emitReference.ts +242 -34
- package/src/kernel/spec/emitSurface.ts +57 -11
- package/src/kernel/spec/surfaceConformance.test.ts +4 -2
- package/src/kernel/spec/surfaceConformance.ts +8 -0
- package/src/kernel/spec/types.ts +277 -13
- package/src/kernel/spec/validate.ts +2 -1
- package/src/kernel/vocabulary.test.ts +164 -0
- package/src/kernel/vocabulary.ts +146 -0
- package/src/testing/PARITY_GAPS.ts +8 -2
- package/src/testing/behavioral/README.md +3 -3
- package/src/testing/behavioral/completion.test.ts +19 -6
- package/src/testing/behavioral/docExamples.test.ts +14 -0
- package/src/testing/behavioral/errorMatrix.mcp.test.ts +6 -5
- package/src/testing/behavioral/errorMatrix.storeless.test.ts +1 -1
- package/src/testing/behavioral/exitCodes.e2e.test.ts +6 -5
- package/src/testing/behavioral/firstRun.e2e.test.ts +24 -24
- package/src/testing/behavioral/harness.foundation.test.ts +14 -5
- package/src/testing/behavioral/journeys.cli.test.ts +117 -76
- package/src/testing/behavioral/journeys.defaultPack.test.ts +88 -182
- package/src/testing/behavioral/journeys.firstInstall.test.ts +167 -0
- package/src/testing/behavioral/journeys.implementation.test.ts +206 -0
- package/src/testing/behavioral/journeys.interactiveTty.e2e.test.ts +2 -2
- package/src/testing/behavioral/journeys.mcpLifecycle.mcp.test.ts +9 -6
- package/src/testing/behavioral/journeys.packageStories.test.ts +188 -0
- package/src/testing/behavioral/liveReadSurface.ts +4 -3
- package/src/testing/behavioral/mcpServe.e2e.test.ts +57 -2
- package/src/testing/behavioral/mcpSurface.test.ts +10 -5
- package/src/testing/behavioral/rootCli.e2e.test.ts +26 -2
- package/src/testing/behavioral/staleCommands.test.ts +10 -0
- package/src/testing/eval/__snapshots__/eval.test.ts.snap +7 -7
- package/src/testing/eval/cases/assembly.ts +13 -6
- package/src/testing/eval/cases/effectful.ts +28 -15
- package/src/testing/eval/cases/readNouns.ts +22 -20
- package/src/testing/eval/cases/stable.ts +5 -1
- package/src/testing/eval/eval.test.ts +7 -1
- package/src/testing/fixtures/blockGraph.ts +79 -0
- package/src/testing/fixtures/fixtureCapability.ts +45 -1
- package/src/testing/fixtures/graph/canonical.ts +94 -5
- package/src/testing/fixtures/graph/defaultPack.ts +7 -6
- package/src/testing/fixtures/graph/owlExport.ts +7 -5
- package/src/testing/helpers/blankCanonicalRanges.ts +36 -0
- package/src/testing/helpers/fixtureGraph.ts +33 -16
- package/src/testing/helpers/packRuntime.ts +2 -3
- package/src/testing/helpers/projectCli.ts +2 -1
- package/src/testing/helpers/projectMcp.ts +38 -6
- package/src/testing/helpers/runCli.ts +35 -18
- package/src/testing/perf/budgets.test.ts +24 -9
- package/src/testing/perf/budgets.ts +76 -12
- package/src/testing/perf/codegen.test.ts +126 -0
- package/src/testing/perf/globalSetup.test.ts +286 -0
- package/src/testing/perf/globalSetup.ts +611 -14
- package/src/testing/perf/measure.test.ts +38 -0
- package/src/testing/perf/measure.ts +23 -4
- package/src/testing/setupXdgIsolation.ts +81 -21
- package/src/testing/tempRoot.globalSetup.ts +122 -0
- package/src/types.ts +2 -2
- package/dist/pragma +0 -0
- package/src/capabilities/block/blockList.test.ts +0 -79
- package/src/capabilities/block/blockList.verb.ts +0 -163
- package/src/capabilities/block/index.ts +0 -25
- package/src/capabilities/block/pack.ts +0 -166
- package/src/capabilities/block/parity.test.ts +0 -187
- package/src/capabilities/block/tierChain.ts +0 -78
- package/src/capabilities/colophon/pragmaColophon.ts +0 -66
- package/src/capabilities/create/compiledCreate.subprocess.test.ts +0 -152
- package/src/capabilities/create/templates.embedded.generated.ts +0 -53
- package/src/capabilities/doctor/checks/checkConfigFile.ts +0 -41
- package/src/capabilities/doctor/checks/checkMcpCommands.ts +0 -114
- package/src/capabilities/doctor/checks/checkMcpConfigured.ts +0 -67
- package/src/capabilities/doctor/checks/checkSkillsSymlinked.ts +0 -60
- package/src/capabilities/doctor/checks/deriveBand.test.ts +0 -42
- package/src/capabilities/doctor/checks/deriveBand.ts +0 -28
- package/src/capabilities/modifier/index.ts +0 -15
- package/src/capabilities/modifier/pack.ts +0 -64
- package/src/capabilities/standard/index.ts +0 -18
- package/src/capabilities/standard/pack.ts +0 -128
- package/src/capabilities/tier/index.ts +0 -19
- package/src/capabilities/tier/lookup.render.test.ts +0 -72
- package/src/capabilities/tier/lookup.render.ts +0 -59
- package/src/capabilities/tier/lookup.test.ts +0 -83
- package/src/capabilities/tier/lookup.verb.ts +0 -44
- package/src/capabilities/tier/pack.ts +0 -28
- package/src/capabilities/tier/runLookup.ts +0 -87
- package/src/capabilities/token/addConfig.render.ts +0 -27
- package/src/capabilities/token/addConfig.test.ts +0 -62
- package/src/capabilities/token/addConfig.verb.ts +0 -40
- package/src/capabilities/token/index.ts +0 -19
- package/src/capabilities/token/pack.ts +0 -58
- package/src/capabilities/token/runAddConfig.ts +0 -95
- package/src/kernel/completion/bashDrive.test.ts +0 -73
- package/src/kernel/config/__snapshots__/firstRun.test.ts.snap +0 -11
- package/src/kernel/runtime/graphpack/embedded/sample.ttl +0 -39
- package/src/kernel/runtime/lock.ts +0 -90
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
// AUTO-GENERATED by scripts/build.ts — do not edit by hand.
|
|
2
|
-
// Regenerate: `bun run scripts/build.ts`. Inlines the summon generators' .ejs
|
|
3
|
-
// templates as strings so `pragma create` works from the standalone --compile
|
|
4
|
-
// binary (the .ejs files are absent from the binary's virtual filesystem).
|
|
5
|
-
/** Directory-qualified template path → file contents. */
|
|
6
|
-
export const TEMPLATES: Record<string, string> = {
|
|
7
|
-
"application/.storybook/main.ts.ejs": "import { createConfig } from \"@canonical/storybook-config\";\n\nexport default createConfig(\"react\", {\n staticDirs: [\"../src/assets\", \"../public\"],\n<% if (relay) { -%>\n // Wraps stories that declare `parameters.relay` in a relay-test-utils mock\n // environment, so components using Relay hooks render without a server.\n extraAddons: [\"@canonical/storybook-addon-relay\"],\n<% } -%>\n});\n",
|
|
8
|
-
"application/README.md.ejs": "# <%= name %>\n\nA React application with server-side rendering and routing, generated by\n`@canonical/summon`. It is built on Canonical's shared design system, router, and\nSSR packages, and ships SSR on two runtimes (Bun and Node), file-based routing, a\ncomponent library wired to design tokens, and Storybook.\n\n## Quick start\n\n```bash\nbun install\nbun run dev:bun # SSR dev server with HMR, on http://localhost:5174\n```\n\nEdit anything under `src/` and the page hot-reloads. To check the production\nbuild before shipping, run `bun run preview:bun` instead.\n\n## Running the app\n\nThe server scripts form a **2×3 matrix** — two modes (development and preview)\nacross three targets (a client-only SPA, SSR on Bun, SSR on Node/Express):\n\n| | `dev` — transform, HMR | `preview` — compiled, production-faithful |\n| ---------------- | ---------------------- | ----------------------------------------- |\n| **SPA** (no SSR) | `bun run dev` | `bun run preview` |\n| **SSR · Bun** | `bun run dev:bun` | `bun run preview:bun` |\n| **SSR · Node** | `bun run dev:express` | `bun run preview:express` |\n\nThe naming is systematic: the bare name is the **SPA**, the `:bun` / `:express`\nsuffix selects the **SSR runtime**, and the `dev` / `preview` prefix selects the\n**mode**. Reach for `dev:*` while building — it is the fast inner loop, with HMR\nand no build step — and for `preview:*` when verifying that the production bundle\nbehaves before a deploy: `preview:*` builds the client and runs a compiled\nrenderer over the built assets, the same artifact that deploys.\n\n```bash\nbun run storybook # component workshop\n```\n<% if (relay) { -%>\n\nRelay's compiler artifacts are committed, not rebuilt on the fly:\n\n```bash\nbun run relay # regenerate src/relay/__generated__ after schema/query edits\nbun run relay:watch # the same, re-running on change — pair with dev:*\n```\n<% } -%>\n\n## Adding routes\n\n`summon` scaffolds the building blocks of the app so new features follow the\nestablished structure rather than diverging from it.\n\n```bash\nsummon domain billing # a new feature domain (routes + pages)\nsummon route billing/invoices # a route within a domain\nsummon wrapper sidebar # a layout wrapper\n```\n\n## Testing\n\n```bash\nbun run test # unit + component tests (Vitest, jsdom)\nbun run test:coverage # the same, with a coverage report\nbun run test:e2e # boots all six matrix servers and asserts each serves\n```\n\n`test:e2e` is an end-to-end test *of the build*: it runs each of the six server\nscripts — including the production builds that `preview:*` performs — and asserts\nthat every server returns a rendered document and serves its client assets with\nthe correct content type.\n\n## Project structure\n\n```\nsrc/\n├── client/ Client entry (hydration)\n├── server/ Server entry, compiled renderer, dev servers, sitemap\n├── domains/ Feature domains (each owns its routes and pages)\n├── lib/ Shared components\n<% if (relay) { -%>\n├── relay/ Relay environment factory, executable mock schema,\n│ and generated artifacts (__generated__/)\n<% } -%>\n├── styles/ Application CSS\n├── assets/ Assets imported in code (bundled and hashed by Vite)\n└── routes.tsx Root route map\npublic/ Files served verbatim at a fixed URL (favicon, robots.txt)\ntest/e2e/ The 2×3 server-matrix end-to-end suite\n```\n\nDomains are the unit of feature organisation: each owns its routes and pages, so\nadding a feature is adding a domain rather than threading changes through shared\nfiles. This app ships both `src/assets/` (assets imported in code) and `public/`\n(files served by fixed URL); either may be removed if the app uses only one.\n<% if (relay) { -%>\n\n## Data layer (Relay)\n\nThe `catalog` domain demonstrates the app's [Relay](https://relay.dev) data\nlayer: `ProductList` fetches a page of products with `useLazyLoadQuery`, and\neach `ProductCard` reads its own colocated `useFragment` — the component owns\nits field selection, the parent query just spreads it.\n\n**By default the app needs no backend.** `createEnvironment`\n(`src/relay/environment.ts`) resolves every GraphQL operation in-process\nagainst an executable mock schema (`src/relay/schema.ts`, built from the SDL\nin `src/relay/schema.graphql`) backed by a small deterministic catalog. Set\n`VITE_GRAPHQL_URL` (or pass `graphqlUrl` to `createEnvironment`) to switch the\nenvironment to posting operations to a real GraphQL endpoint instead — no code\nchanges needed.\n\n**Generated artifacts are committed.** The Vite plugin runs with\n`codegen: false`, so `src/relay/__generated__/` is not rebuilt on the fly:\nafter editing a `graphql` tag or the schema, run `bun run relay` (or keep\n`bun run relay:watch` running) to regenerate the artifacts, and commit them.\n\n**SSR ships no data yet.** `useLazyLoadQuery` fetches (and suspends) while\nrendering, and the server cannot serialize the fetched store for the client\nyet, so the catalog page wraps its query subtree in `ClientOnly`\n(`src/lib/ClientOnly/`): the server streams the fallback and the browser\nfetches after hydration.\n\n<% if (standalone) { -%>\n**Patched dependencies.** `patches/` carries three package patches applied via\n`patchedDependencies` in `package.json` (a bun feature — with another package\nmanager, apply the equivalent mechanism): `react-relay@21.0.1` needs a\ncjs-module-lexer export hint so named imports survive Node SSR,\n`relay-runtime@21.0.1` needs real runtime bindings for type-only names its\ncompiler artifacts import as values (`ConcreteRequest`, `ReaderFragment`,\n`FragmentRefs`), and `relay-runtime-network@0.1.0` ships a broken `imports`\nmap. The last patch is temporary until the fixed upstream release lands\n([advl/lit-relay#32](https://github.com/advl/lit-relay/pull/32)); drop it and\nits `patchedDependencies` entry once a fixed version is published.\n<% } else { -%>\n**Patched dependencies.** This app was scaffolded inside a bun workspace, so\ndependency patching is owned by the workspace root — bun resolves\n`patchedDependencies` paths from the root, which is why the scaffold emitted\nno app-local `patches/` directory or `patchedDependencies` block. The root's\n`patches/` must carry the `react-relay@21.0.1`, `relay-runtime@21.0.1` and\n`relay-runtime-network@0.1.0` patches (named imports under Node SSR, runtime\nbindings for type-only artifact imports, and a broken `imports` map,\nrespectively).\n<% } -%>\n\n**Not yet on npm.** `@canonical/storybook-addon-relay` and the fixed\n`relay-runtime-network` release have not been published yet, so a fresh\ninstall of this app will not fully resolve until they land on npm.\n<% } -%>\n",
|
|
9
|
-
"application/biome.json.ejs": "{\n \"extends\": [\"@canonical/biome-config\"],\n \"files\": {\n \"includes\": [\"src\", \"*.json\", \"vite.config.ts\"<% if (relay) { %>, \"!src/relay/__generated__\"<% } %>]\n }\n}\n",
|
|
10
|
-
"application/index.html.ejs": "<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <meta name=\"description\" content=\"<%= name %> — a React application built with the Canonical design system, router, and SSR packages.\" />\n <link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"https://assets.ubuntu.com/v1/be7e4cc6-COF-favicon-32x32.png\">\n <title><%= name %></title>\n </head>\n <body>\n <div id=\"root\"></div>\n <script type=\"module\" src=\"/src/client/entry.tsx\"></script>\n </body>\n</html>\n",
|
|
11
|
-
"application/package.json.ejs": "{\n \"name\": \"<%= name %>\",\n \"private\": true,\n \"version\": \"0.0.0\",\n \"type\": \"module\",\n \"license\": \"GPL-3.0-only\",\n \"imports\": {\n \"#lib/*\": \"./src/lib/*\",\n \"#domains/*\": \"./src/domains/*\",\n<% if (relay) { -%>\n \"#relay/*\": \"./src/relay/*\",\n<% } -%>\n \"#styles/*\": \"./src/styles/*\"\n },\n \"scripts\": {\n \"dev\": \"vite\",\n \"dev:express\": \"node --import tsx src/server/server.express.ts\",\n \"dev:bun\": \"bun src/server/server.bun.ts\",\n \"preview\": \"bun run build:client && vite preview --outDir dist/client\",\n \"preview:bun\": \"bun run build:client && bun run build:server && bun src/server/preview.bun.ts\",\n \"preview:express\": \"bun run build:client && bun run build:server && node --import tsx src/server/preview.express.ts\",\n \"build\": \"bun run build:client\",\n \"build:all\": \"bun run build:client && bun run build:storybook\",\n \"build:client\": \"vite build --ssrManifest --outDir dist/client\",\n \"build:server\": \"vite build --mode server\",\n \"build:storybook\": \"storybook build\",\n \"check\": \"bun run check:biome && bun run check:ts\",\n \"check:fix\": \"bun run check:biome:fix && bun run check:ts\",\n \"check:biome\": \"biome check\",\n \"check:biome:fix\": \"biome check --write\",\n \"check:ts\": \"tsc --noEmit\",\n<% if (relay) { -%>\n \"relay\": \"relay-compiler\",\n \"relay:watch\": \"relay-compiler --watch\",\n<% } -%>\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\",\n \"test:e2e\": \"vitest run --config vitest.e2e.config.ts\",\n \"storybook\": \"storybook dev -p 6010 --no-open --host 0.0.0.0\"\n },\n \"dependencies\": {\n \"@canonical/react-ds-global\": \"<%= pragmaVersion %>\",\n<% if (forms) { -%>\n \"@canonical/react-ds-global-form\": \"<%= pragmaVersion %>\",\n<% } -%>\n \"@canonical/react-head\": \"<%= pragmaVersion %>\",\n \"@canonical/react-hooks\": \"<%= pragmaVersion %>\",\n \"@canonical/react-ssr\": \"<%= pragmaVersion %>\",\n \"@canonical/router-core\": \"<%= pragmaVersion %>\",\n \"@canonical/router-react\": \"<%= pragmaVersion %>\",\n<% if (relay) { -%>\n \"@canonical/storybook-addon-relay\": \"<%= pragmaVersion %>\",\n<% } -%>\n \"@canonical/storybook-config\": \"<%= pragmaVersion %>\",\n \"@canonical/styles\": \"<%= pragmaVersion %>\",\n \"express\": \"^5.2.1\",\n<% if (relay) { -%>\n \"graphql\": \"^16.11.0\",\n<% } -%>\n \"react\": \"^19.2.4\",\n \"react-dom\": \"^19.2.4\"<% if (relay) { %>,\n \"react-relay\": \"^21.0.1\",\n \"relay-runtime\": \"^21.0.1\",\n \"relay-runtime-network\": \"^0.1.0\"<% } %>\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"2.4.9\",\n \"@canonical/biome-config\": \"<%= pragmaVersion %>\",\n \"@canonical/typescript-config-react\": \"<%= pragmaVersion %>\",\n \"@storybook/react-vite\": \"^10.3.1\",\n \"@testing-library/jest-dom\": \"^6.9.1\",\n \"@testing-library/react\": \"^16.3.2\",\n \"@types/express\": \"^5.0.6\",\n \"@types/node\": \"^24.12.0\",\n \"@types/react\": \"^19.2.14\",\n \"@types/react-dom\": \"^19.2.3\",\n<% if (relay) { -%>\n \"@types/react-relay\": \"^18.2.1\",\n \"@types/relay-runtime\": \"^20.1.1\",\n \"@types/relay-test-utils\": \"^19.0.0\",\n<% } -%>\n \"@vitejs/plugin-react\": \"^6.0.0\",\n \"@vitest/coverage-v8\": \"^4.0.18\",\n \"browserslist\": \"^4.28.1\",\n \"bun-types\": \"^1.3.9\",\n \"jsdom\": \"^28.1.0\",\n \"lightningcss\": \"^1.32.0\",\n<% if (relay) { -%>\n \"relay-compiler\": \"^21.0.1\",\n \"relay-test-utils\": \"^21.0.1\",\n<% } -%>\n \"storybook\": \"^10.3.1\",\n \"tsx\": \"^4.19.0\",\n \"typescript\": \"^5.9.3\",\n \"vite\": \"^8.0.1\",\n<% if (relay) { -%>\n \"vite-plugin-relay-lite\": \"^0.12.0\",\n<% } -%>\n \"vitest\": \"^4.0.18\"\n }<% if (relay && standalone) { %>,\n \"patchedDependencies\": {\n \"react-relay@21.0.1\": \"patches/react-relay@21.0.1.patch\",\n \"relay-runtime@21.0.1\": \"patches/relay-runtime@21.0.1.patch\",\n \"relay-runtime-network@0.1.0\": \"patches/relay-runtime-network@0.1.0.patch\"\n }<% } %>\n}\n",
|
|
12
|
-
"application/src/client/entry.tsx.ejs": "import { HeadProvider } from \"@canonical/react-head\";\nimport { createBrowserRouter } from \"@canonical/router-core\";\nimport { Outlet, RouterProvider } from \"@canonical/router-react\";\nimport { hydrateRoot } from \"react-dom/client\";\n<% if (relay) { -%>\nimport { RelayEnvironmentProvider } from \"react-relay\";\nimport { createEnvironment } from \"#relay/environment.js\";\n<% } -%>\nimport { appRoutes, middleware, notFoundRoute } from \"../routes.js\";\nimport \"#styles/index.css\";\n\nconst router = createBrowserRouter(appRoutes, {\n middleware: [...middleware],\n notFound: notFoundRoute,\n});\n<% if (relay) { -%>\n\n// One Relay environment (network + normalized store) for the whole browser\n// session — module scope, so client-side navigations share the cache.\nconst relayEnvironment = createEnvironment();\n<% } -%>\n\nconst root = document.getElementById(\"root\");\nif (!root) {\n throw new Error('Root element \"#root\" not found');\n}\n\n<% if (relay) { -%>\nhydrateRoot(\n root,\n <HeadProvider>\n <RelayEnvironmentProvider environment={relayEnvironment}>\n <RouterProvider router={router}>\n <Outlet fallback={<p>Loading…</p>} />\n </RouterProvider>\n </RelayEnvironmentProvider>\n </HeadProvider>,\n);\n<% } else { -%>\nhydrateRoot(\n root,\n <HeadProvider>\n <RouterProvider router={router}>\n <Outlet fallback={<p>Loading…</p>} />\n </RouterProvider>\n </HeadProvider>,\n);\n<% } -%>\n",
|
|
13
|
-
"application/src/lib/Navigation/Navigation.tsx.ejs": "import { Link } from \"@canonical/router-react\";\nimport type { ReactElement } from \"react\";\nimport ThemeSelector from \"../ThemeSelector/index.js\";\n\nexport default function Navigation(): ReactElement {\n return (\n <nav aria-label=\"Main\">\n <Link to=\"home\">Home</Link>\n <Link params={{ slug: \"router-core\" }} to=\"guide\">\n Guide\n </Link>\n<% if (relay) { -%>\n <Link to=\"catalog\">Catalog</Link>\n<% } -%>\n<% if (forms) { -%>\n <Link to=\"contact\">Contact</Link>\n<% } -%>\n <Link search={{ auth: \"1\" }} to=\"account\">\n Demo sign-in\n </Link>\n <ThemeSelector />\n </nav>\n );\n}\n",
|
|
14
|
-
"application/src/lib/index.ts.ejs": "<% if (relay) { -%>\nexport { default as ClientOnly } from \"./ClientOnly/index.js\";\n<% } -%>\nexport { ExampleComponent } from \"./ExampleComponent/index.js\";\nexport { default as LazyComponent } from \"./LazyComponent/index.js\";\nexport { default as Navigation } from \"./Navigation/index.js\";\nexport { default as ThemeSelector } from \"./ThemeSelector/index.js\";\n",
|
|
15
|
-
"application/src/routes.tsx.ejs": "import {\n type AnyRoute,\n group,\n type NavigationContext,\n type RouteMiddleware,\n type RouteParamValues,\n redirect,\n route,\n wrapper,\n} from \"@canonical/router-core\";\nimport type { ReactElement, ReactNode } from \"react\";\nimport accountRoutes from \"#domains/account/routes.js\";\n<% if (relay) { -%>\nimport catalogRoutes from \"#domains/catalog/routes.js\";\n<% } -%>\n<% if (forms) { -%>\nimport contactRoutes from \"#domains/contact/routes.js\";\n<% } -%>\nimport marketingRoutes from \"#domains/marketing/routes.js\";\nimport Navigation from \"#lib/Navigation/index.js\";\n\nconst protectedPaths = new Set([\"/account\"]);\n\nfunction hasDemoAuth(search: unknown): boolean {\n const authValue = (search as Record<string, unknown>)?.auth;\n\n return authValue === \"1\";\n}\n\nexport function getAuthRedirectHref(input: string | URL): string | null {\n // Absolute URLs are used as-is; relative paths resolve against a dummy base.\n const url =\n input instanceof URL ? input : new URL(input, \"https://router.local\");\n\n if (\n !protectedPaths.has(url.pathname) ||\n hasDemoAuth({ auth: url.searchParams.get(\"auth\") })\n ) {\n return null;\n }\n\n return `/login?from=${encodeURIComponent(url.pathname)}`;\n}\n\nexport function withAuth(loginPath: string): RouteMiddleware {\n return ((currentRoute: AnyRoute) => {\n if (!protectedPaths.has(currentRoute.url)) {\n return currentRoute;\n }\n\n const currentPrefetch = currentRoute.prefetch;\n\n return {\n ...currentRoute,\n prefetch: (\n params: unknown,\n search: unknown,\n context: NavigationContext,\n ) => {\n if (!hasDemoAuth(search)) {\n const from = currentRoute.render(\n (params ?? {}) as RouteParamValues | Record<string, never>,\n );\n\n redirect(`${loginPath}?from=${encodeURIComponent(from)}`, 302);\n }\n\n if (currentPrefetch) {\n return currentPrefetch(params, search, context);\n }\n },\n };\n }) as RouteMiddleware;\n}\n\nconst publicLayout = wrapper<ReactElement>({\n id: \"public-layout\",\n component: ({ children }: { children: ReactNode }) => (\n <div className=\"subgrid app-shell\">\n <header className=\"subgrid shell-header\">\n <Navigation />\n </header>\n <main className=\"subgrid\">{children}</main>\n </div>\n ),\n});\n\nconst notFoundRoute = route({\n url: \"/not-found\",\n content: () => (\n <section>\n <h1>Page not found</h1>\n <p>The page you are looking for does not exist.</p>\n </section>\n ),\n});\n\nconst [guide, home] = group(publicLayout, [\n marketingRoutes.guide,\n marketingRoutes.home,\n] as const);\n\nconst [account, login] = group(publicLayout, [\n accountRoutes.account,\n accountRoutes.login,\n] as const);\n\n<% if (forms) { -%>\nconst [contact] = group(publicLayout, [contactRoutes.contact] as const);\n\n<% } -%>\n<% if (relay) { -%>\nconst [catalog] = group(publicLayout, [catalogRoutes.catalog] as const);\n\n<% } -%>\nconst appRoutes = {\n guide,\n home,\n account,\n login,\n<% if (forms) { -%>\n contact,\n<% } -%>\n<% if (relay) { -%>\n catalog,\n<% } -%>\n} as const;\n\nexport type AppRoutes = typeof appRoutes;\n\ndeclare module \"@canonical/router-react\" {\n interface RouterRegister {\n routes: AppRoutes;\n }\n}\n\nexport const middleware = [withAuth(\"/login\")] as const;\n\nexport { appRoutes, notFoundRoute };\n",
|
|
16
|
-
"application/src/server/entry.tsx.ejs": "import { HeadProvider } from \"@canonical/react-head\";\nimport type { ServerEntrypointProps } from \"@canonical/react-ssr/renderer\";\nimport { createStaticRouter } from \"@canonical/router-core\";\nimport { Outlet, RouterProvider } from \"@canonical/router-react\";\n<% if (relay) { -%>\nimport { RelayEnvironmentProvider } from \"react-relay\";\nimport { createEnvironment } from \"#relay/environment.js\";\n<% } -%>\nimport { appRoutes, middleware, notFoundRoute } from \"../routes.js\";\nimport \"#styles/app.css\";\n\ninterface InitialData extends Record<string, unknown> {\n readonly url?: string;\n /** Colour-scheme preference resolved from the request cookie, if any. */\n readonly theme?: \"light\" | \"dark\";\n}\n\nexport default function EntryServer(props: ServerEntrypointProps<InitialData>) {\n const initialData = props.initialData ?? {};\n const url = initialData.url ?? \"/\";\n const router = createStaticRouter(appRoutes, url, {\n middleware: [...middleware],\n notFound: notFoundRoute,\n });\n<% if (relay) { -%>\n\n // A fresh Relay environment per server render, so no store state leaks\n // between requests. Nothing fetches through it yet: components that issue\n // queries are wrapped in `ClientOnly` (see CatalogPage) until data\n // serialization/hydration is supported; the provider is here so any\n // component touching Relay context renders without branching on runtime.\n const relayEnvironment = createEnvironment();\n<% } -%>\n\n // Paint the cookie-resolved theme on <html> for a flash-free first render —\n // the same element `usePreferredTheme` toggles on the client, and one React\n // does not hydrate (only `#root` is), so there is no mismatch to reconcile.\n<% if (relay) { -%>\n return (\n <html lang={props.lang} className={initialData.theme}>\n <head>\n {props.otherHeadElements}\n {props.scriptElements}\n {props.linkElements}\n </head>\n <body>\n <div id=\"root\">\n <HeadProvider>\n <RelayEnvironmentProvider environment={relayEnvironment}>\n <RouterProvider router={router}>\n <Outlet fallback={<p>Loading…</p>} />\n </RouterProvider>\n </RelayEnvironmentProvider>\n </HeadProvider>\n </div>\n </body>\n </html>\n );\n<% } else { -%>\n return (\n <html lang={props.lang} className={initialData.theme}>\n <head>\n {props.otherHeadElements}\n {props.scriptElements}\n {props.linkElements}\n </head>\n <body>\n <div id=\"root\">\n <HeadProvider>\n <RouterProvider router={router}>\n <Outlet fallback={<p>Loading…</p>} />\n </RouterProvider>\n </HeadProvider>\n </div>\n </body>\n </html>\n );\n<% } -%>\n}\n\nexport type { InitialData };\n",
|
|
17
|
-
"application/src/sitemap/getSitemapItems.ts.ejs": "import type { SitemapItem } from \"@canonical/react-ssr/renderer\";\n\n/**\n * Returns sitemap entries for all known routes.\n *\n * Update this list as you add domains and routes. For dynamic content\n * (blog posts, product pages), fetch entries from your data source.\n *\n * @example\n * const posts = await fetchPosts();\n * return [\n * ...staticEntries,\n * ...posts.map((post) => ({\n * loc: `/blog/${post.slug}`,\n * lastmod: post.updatedAt,\n * changefreq: \"weekly\" as const,\n * priority: 0.7,\n * })),\n * ];\n */\nexport default async function getSitemapItems(): Promise<SitemapItem[]> {\n return [\n { loc: \"/\", changefreq: \"weekly\", priority: 1.0 },\n { loc: \"/guides/router-core\", changefreq: \"monthly\", priority: 0.8 },\n<% if (relay) { -%>\n { loc: \"/catalog\", changefreq: \"weekly\", priority: 0.7 },\n<% } -%>\n<% if (forms) { -%>\n { loc: \"/contact\", changefreq: \"monthly\", priority: 0.7 },\n<% } -%>\n { loc: \"/account\", changefreq: \"monthly\", priority: 0.5 },\n { loc: \"/login\", changefreq: \"yearly\", priority: 0.3 },\n ];\n}\n",
|
|
18
|
-
"application/src/styles/index.css.ejs": "@import url(\"@canonical/styles\");\n<% if (forms) { -%>\n@import url(\"@canonical/react-ds-global-form/dist/esm/index.css\");\n<% } -%>\n@import url(\"./app.css\");\n",
|
|
19
|
-
"application/tsconfig.json.ejs": "{\n \"extends\": \"@canonical/typescript-config-react\",\n \"compilerOptions\": {\n \"baseUrl\": \"src\",\n \"skipLibCheck\": true,\n \"types\": [\n \"bun-types\",\n \"node\",\n \"react\",\n \"react-dom\",\n \"vitest/globals\",\n \"@testing-library/jest-dom\"\n ],\n \"noEmit\": true,\n \"paths\": {\n \"#lib/*\": [\"./lib/*\"],\n \"#domains/*\": [\"./domains/*\"],\n<% if (relay) { -%>\n \"#relay/*\": [\"./relay/*\"],\n<% } -%>\n \"#styles/*\": [\"./styles/*\"]\n }\n },\n \"include\": [\n \"src/**/*.ts\",\n \"src/**/*.tsx\",\n \".storybook/*.ts\",\n \".storybook/*.tsx\",\n \"vite.config.ts\",\n \"vitest.setup.ts\",\n \"vitest.config.ts\",\n \"vitest.e2e.config.ts\",\n \"test/**/*.ts\"\n ]\n}\n",
|
|
20
|
-
"application/vite.config.ts.ejs": "import react from \"@vitejs/plugin-react\";\nimport browserslist from \"browserslist\";\nimport { browserslistToTargets } from \"lightningcss\";\nimport { defineConfig } from \"vite\";\n<% if (relay) { -%>\nimport relay from \"vite-plugin-relay-lite\";\n<% } -%>\n\n// Path aliases (#lib, #domains, #styles) are declared as Node subpath imports\n// in package.json \"imports\" and resolved natively by Vite — no resolver plugin.\nconst PORT = Number(process.env.PORT) || undefined;\n\n// `build:server` runs `vite build --mode server` to compile the two server\n// renderers in a single pass. Each is a separate, individually-instantiated\n// Lego brick, so they are named Rollup inputs — the build emits\n// `dist/server/renderer.js` (the JSX app) + `dist/server/sitemap.js` (the XML\n// sitemap), which the preview servers import directly. Every other command\n// (`dev`, `build:client`, `preview`) uses the default mode and the SPA client\n// build (`--ssrManifest --outDir dist/client`).\nexport default defineConfig(({ mode }) => ({\n<% if (relay) { -%>\n // Relay's `graphql\\`...\\`` tags must be rewritten into imports of the\n // compiler-generated artifacts. `@vitejs/plugin-react` v6 is OXC-based (no\n // Babel), so the classic `babel-plugin-relay` route would need the\n // `@rolldown/plugin-babel` escape hatch; `vite-plugin-relay-lite` does the\n // same rewrite with its own parser and no Babel, and works on Vite 8 /\n // rolldown despite its peer range stopping at Vite 7 (bun installs it with\n // only a peer-version warning). Footgun: its tag scanner matches the word\n // \"graphql\" followed by a backtick even inside comments, so never\n // backtick-quote a graphql file name in a comment. `codegen: false` because\n // artifacts are committed and regenerated explicitly via the `relay` /\n // `relay:watch` scripts.\n plugins: [relay({ codegen: false }), react()],\n<% } else { -%>\n plugins: [react()],\n<% } -%>\n // Honour the PORT env var for `dev` (SPA) and `preview` so all server scripts\n // — including the SSR ones, which already read PORT — respond to it uniformly.\n server: { port: PORT },\n preview: { port: PORT },\n // CSS delivery is the app's job, not the libraries': @canonical/* packages\n // deliberately ship modern, uncompiled per-component CSS and take no stance\n // on browser support. Lightning CSS (already bundled with Vite 8) compiles\n // that CSS down to this app's declared browser floor — the browserslist\n // query in .browserslistrc, which is the one knob to turn when support\n // requirements change. Not everything can be downleveled: math functions\n // like `mod()` (used by the typography baseline grid) have no polyfillable\n // form, so that feature's effective Chromium ≥ 125 floor is unchanged.\n css: {\n transformer: \"lightningcss\",\n lightningcss: { targets: browserslistToTargets(browserslist()) },\n },\n build: {\n // Minify CSS with Lightning CSS too (instead of the esbuild default), so\n // a single tool owns both downleveling and minification — in the client\n // build and the server build alike.\n cssMinify: \"lightningcss\",\n ...(mode === \"server\"\n ? {\n ssr: true,\n outDir: \"dist/server\",\n rollupOptions: {\n input: {\n renderer: \"src/server/renderer.tsx\",\n sitemap: \"src/sitemap/renderer.ts\",\n },\n },\n }\n : undefined),\n },\n ssr: {\n // Bundle @canonical/* for SSR rather than externalising them, for two\n // reasons: (1) some packages declare only a \"module\" entry (no\n // \"main\"/\"exports\"), which Vite's SSR (Node-style) resolver ignores —\n // externalising them fails with ERR_RESOLVE_PACKAGE_ENTRY_FAIL; (2) their\n // built output imports CSS as a side effect (e.g. `import \"./x.css\"`),\n // which Node cannot load (ERR_UNKNOWN_FILE_EXTENSION) but Vite's SSR\n // transform no-ops. The regex covers the whole scope so any current or\n // future @canonical dependency is handled.\n<% if (relay) { -%>\n //\n // The Relay packages (react-relay, relay-runtime, relay-runtime-network,\n // graphql) stay externalised like react itself. Three packaging defects\n // made that possible and are fixed via `patchedDependencies` (app-local\n // patches/ for a standalone app; the workspace root's patches/ when the\n // app lives inside a bun workspace): react-relay's CJS exports are member\n // expressions cjs-module-lexer cannot detect (breaking named imports\n // under Node SSR and Vite's dev module runner), relay-runtime lacks\n // runtime bindings for type-only names its compiler artifacts import as\n // values (ConcreteRequest, ReaderFragment, FragmentRefs), and\n // relay-runtime-network@0.1.0 ships an `imports` map pointing at its\n // unpublished src/ directory.\n<% } -%>\n noExternal: [/^@canonical\\//],\n },\n}));\n",
|
|
21
|
-
"application/vitest.setup.ts.ejs": "import * as matchers from \"@testing-library/jest-dom/matchers\";\nimport { cleanup } from \"@testing-library/react\";\n<% if (relay) { -%>\nimport { afterEach, expect, vi } from \"vitest\";\n<% } else { -%>\nimport { afterEach, expect } from \"vitest\";\n<% } -%>\n\nexpect.extend(matchers as unknown as Parameters<typeof expect.extend>[0]);\n<% if (relay) { -%>\n\n// relay-test-utils' `createMockEnvironment` wraps environment methods in\n// `jest.fn` mocks whenever NODE_ENV === \"test\", reaching for a global `jest`\n// object. Vitest sets NODE_ENV=test but exposes `vi` instead, so alias it —\n// `vi.fn` is API-compatible with the `jest.fn` surface relay-test-utils uses\n// (`.mock`, `.mockClear`).\n(globalThis as { jest?: typeof vi }).jest = vi;\n<% } -%>\n\nafterEach(() => {\n cleanup();\n});\n",
|
|
22
|
-
"component/lit/component.ts.ejs": "import { html, LitElement } from \"lit\";\nimport { customElement } from \"lit/decorators.js\";\n<% if (withStyles) { -%>\nimport styles from \"./styles.css\";\n<% } -%>\nimport type { <%= name %>Props } from \"./types.js\";\n\nconst componentCssClassName = \"ds <%= kebabName %>\";\n\n/**\n * <%= name %> web component.\n *\n * @implements ds:global.component.<%= kebabName %>\n */\n@customElement(\"ds-<%= kebabName %>\")\nexport default class <%= name %> extends LitElement implements <%= name %>Props {\n<% if (withStyles) { -%>\n static styles = styles;\n\n<% } -%>\n render() {\n return html`\n <div class=\"${componentCssClassName}\">\n <slot></slot>\n </div>\n `;\n }\n}\n",
|
|
23
|
-
"component/lit/index.ts.ejs": "export { default as <%= name %> } from \"./<%= name %>.js\";\nexport type { <%= name %>Props } from \"./types.js\";\n",
|
|
24
|
-
"component/lit/stories.ts.ejs": "import type { Meta, StoryObj } from \"@storybook/web-components-vite\";\nimport { html } from \"lit\";\n\nimport \"./<%= name %>.js\";\nimport type <%= name %> from \"./<%= name %>.js\";\n\nconst meta = {\n title: \"Web Components/<%= name %>\",\n tags: [\"autodocs\"],\n} satisfies Meta<<%= name %>>;\n\nexport default meta;\ntype Story = StoryObj<<%= name %>>;\n\nexport const Default: Story = {\n render: () => html`<ds-<%= kebabName %>>Hello, <%= name %>!</ds-<%= kebabName %>>`,\n};\n",
|
|
25
|
-
"component/lit/styles.css.ejs": "/*\n * Lit Layout Primer\n * Delete this comment block when you're done implementing.\n *\n * Styles live in a shadow DOM, isolated from the page by default.\n *\n * Two layers:\n *\n * 1) :host — the outer shell, how this component presents to its parent layout.\n * display, width, height (always apply)\n * grid-column, grid-row, align-self, justify-self (parent must be grid/flex)\n *\n * 2) .ds.<%= kebabName %> — the inner shell, how this component arranges its shadow children.\n * display: grid/flex, gap, grid-template-columns, align-items, justify-content\n *\n * Subgrid pattern — use when the parent defines grid tracks you want to inherit:\n *\n * In the parent component:\n * .ds.parent { display: grid; grid-template-columns: repeat(4, 1fr); }\n *\n * In this component:\n * :host { display: grid; grid-column: span 2; }\n * .ds.<%= kebabName %> { display: grid; grid-template-columns: subgrid; }\n *\n * In this example, the parent establishes a 4-column grid.\n * This component claims 2 of those columns and inherits their widths via subgrid.\n *\n * Keep in mind:\n * - Custom elements are display: inline by default — always set display on :host.\n * - Flex/grid rules only affect direct children of the container, not deeper descendants.\n * - External CSS cannot pierce the shadow boundary — expose CSS custom properties for theming.\n */\n\n:host {\n /*\n * Host controls the outer layout role.\n * Declare component CSS variables here when needed.\n * Variables must be on :host to be accessible inside the shadow tree.\n *\n * Example:\n * --<%= kebabName %>-color-background: var(--color-background-default);\n * --<%= kebabName %>-color-text: var(--color-text-default);\n */\n display: inline-flex;\n}\n\n.ds.<%= kebabName %> {\n /* Inner layout and visual styles go here. */\n}\n",
|
|
26
|
-
"component/lit/tests.ts.ejs": "import { afterEach, beforeEach, describe, expect, it } from \"vitest\";\nimport \"./<%= name %>.js\";\nimport type <%= name %> from \"./<%= name %>.js\";\n\ndescribe(\"<%= name %> component\", () => {\n let elem: <%= name %>;\n\n beforeEach(() => {\n elem = document.createElement(\"ds-<%= kebabName %>\") as <%= name %>;\n document.body.appendChild(elem);\n });\n\n afterEach(() => {\n elem.remove();\n });\n\n it(\"should render component\", async () => {\n await customElements.whenDefined(\"ds-<%= kebabName %>\");\n\n const container = elem.shadowRoot?.querySelector(\".ds.<%= kebabName %>\");\n expect(container).toBeTruthy();\n });\n\n it(\"should have correct tag name\", () => {\n expect(elem.tagName.toLowerCase()).toBe(\"ds-<%= kebabName %>\");\n });\n});\n",
|
|
27
|
-
"component/lit/types.ts.ejs": "/**\n * Props for the <%= name %> component.\n */\nexport interface <%= name %>Props {\n // Define props specific to <%= name %> here\n}\n",
|
|
28
|
-
"component/react/component.tsx.ejs": "import type React from \"react\";\nimport type { <%= name %>Props } from \"./types.js\";\n<% if (withStyles) { -%>\nimport \"./styles.css\";\n<% } -%>\n\nconst componentCssClassName = \"ds <%= kebabName %>\";\n\n/**\n * <%= name %> component\n */\nconst <%= name %> = ({\n\tclassName,\n\tchildren,\n\t...props\n}: <%= name %>Props): React.ReactElement => {\n\treturn (\n\t\t<div\n\t\t\tclassName={[componentCssClassName, className].filter(Boolean).join(\" \")}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t</div>\n\t);\n};\n\nexport default <%= name %>;\n",
|
|
29
|
-
"component/react/index.ts.ejs": "export { default as <%= name %> } from \"./<%= name %>.js\";\nexport type * from \"./types.js\";\n",
|
|
30
|
-
"component/react/ssr.test.tsx.ejs": "import { describe, expect, it } from \"vitest\";\nimport { renderToString } from \"react-dom/server\";\nimport <%= name %> from \"./<%= name %>.js\";\n\ndescribe(\"<%= name %> SSR\", () => {\n\tit(\"renders without hydration errors\", () => {\n\t\tconst html = renderToString(<<%= name %>>Test content</<%= name %>>);\n\t\texpect(html).toContain(\"Test content\");\n\t\texpect(html).toContain(\"ds <%= kebabName %>\");\n\t});\n});\n",
|
|
31
|
-
"component/react/stories.tsx.ejs": "import type { Meta, StoryObj } from \"@storybook/react-vite\";\nimport <%= name %> from \"./<%= name %>.js\";\n\nconst meta: Meta<typeof <%= name %>> = {\n\ttitle: \"Components/<%= name %>\",\n\tcomponent: <%= name %>,\n\ttags: [\"autodocs\"],\n};\n\nexport default meta;\ntype Story = StoryObj<typeof <%= name %>>;\n\nexport const Default: Story = {\n\targs: {\n\t\tchildren: \"Hello, <%= name %>!\",\n\t},\n};\n\nexport const WithCustomClass: Story = {\n\targs: {\n\t\tchildren: \"Custom styled\",\n\t\tclassName: \"custom-class\",\n\t},\n};\n",
|
|
32
|
-
"component/react/test.tsx.ejs": "import { describe, expect, it } from \"vitest\";\nimport { render, screen } from \"@testing-library/react\";\nimport <%= name %> from \"./<%= name %>.js\";\n\ndescribe(\"<%= name %>\", () => {\n\tit(\"renders children\", () => {\n\t\trender(<<%= name %>>Test content</<%= name %>>);\n\t\texpect(screen.getByText(\"Test content\")).toBeInTheDocument();\n\t});\n\n\tit(\"applies custom className\", () => {\n\t\trender(<<%= name %> className=\"custom-class\">Content</<%= name %>>);\n\t\tconst element = screen.getByText(\"Content\");\n\t\texpect(element.className).toContain(\"ds <%= kebabName %>\");\n\t\texpect(element.className).toContain(\"custom-class\");\n\t});\n\n\tit(\"passes through additional props\", () => {\n\t\trender(<<%= name %> data-testid=\"test-component\">Content</<%= name %>>);\n\t\texpect(screen.getByTestId(\"test-component\")).toBeInTheDocument();\n\t});\n});\n",
|
|
33
|
-
"component/react/types.ts.ejs": "import type { HTMLAttributes, ReactNode } from \"react\";\n\nexport interface <%= name %>Props extends HTMLAttributes<HTMLDivElement> {\n\t/** Content to render inside the component */\n\tchildren?: ReactNode;\n}\n",
|
|
34
|
-
"component/shared/styles.css.ejs": ".ds.<%= kebabName %> {\n\t/* Component styles */\n}\n",
|
|
35
|
-
"component/svelte/component.svelte.ejs": "<script lang=\"ts\">\n\timport type { <%= name %>Props } from \"./types.js\";\n<% if (withStyles) { -%>\n\timport \"./styles.css\";\n<% } -%>\n\n\tconst componentCssClassName = \"ds <%= kebabName %>\";\n\n\tlet {\n\t\tclass: className,\n\t\tchildren,\n\t\t...rest\n\t}: <%= name %>Props = $props();\n</script>\n\n<div\n\tclass={[componentCssClassName, className]}\n\t{...rest}\n>\n\t{@render children?.()}\n</div>\n",
|
|
36
|
-
"component/svelte/index.ts.ejs": "export { default as <%= name %> } from \"./<%= name %>.svelte\";\nexport type { <%= name %>Props } from \"./types.js\";\n",
|
|
37
|
-
"component/svelte/ssr.test.ts.ejs": "import { render } from \"@canonical/svelte-ssr-test\";\nimport type { RenderResult } from \"@canonical/svelte-ssr-test\";\nimport { createRawSnippet } from \"svelte\";\nimport type { ComponentProps } from \"svelte\";\nimport { describe, expect, it } from \"vitest\";\nimport Component from \"./<%= name %>.svelte\";\n\ndescribe(\"<%= name %> SSR\", () => {\n\tconst baseProps = {\n\t\tchildren: createRawSnippet(() => ({\n\t\t\trender: () => `<span><%= name %></span>`,\n\t\t})),\n\t} satisfies ComponentProps<typeof Component>;\n\n\tdescribe(\"basics\", () => {\n\t\tit(\"doesn't throw\", () => {\n\t\t\texpect(() => {\n\t\t\t\trender(Component, { props: { ...baseProps } });\n\t\t\t}).not.toThrow();\n\t\t});\n\n\t\tit(\"renders\", () => {\n\t\t\tconst page = render(Component, { props: { ...baseProps } });\n\t\t\texpect(componentLocator(page)).toBeInstanceOf(page.window.HTMLDivElement);\n\t\t});\n\t});\n\n\tdescribe(\"attributes\", () => {\n\t\tit.each([\n\t\t\t[\"id\", \"test-id\"],\n\t\t\t[\"aria-label\", \"test-aria-label\"],\n\t\t])(\"applies %s\", (attribute, expected) => {\n\t\t\tconst page = render(Component, {\n\t\t\t\tprops: { ...baseProps, [attribute]: expected },\n\t\t\t});\n\t\t\texpect(componentLocator(page).getAttribute(attribute)).toBe(expected);\n\t\t});\n\n\t\tit(\"applies classes\", () => {\n\t\t\tconst page = render(Component, {\n\t\t\t\tprops: { class: \"test-class\", ...baseProps },\n\t\t\t});\n\t\t\texpect(componentLocator(page).classList).toContain(\"test-class\");\n<% if (withStyles) { _%>\n\t\t\texpect(componentLocator(page).classList).toContain(\"ds\");\n\t\t\texpect(componentLocator(page).classList).toContain(\"<%= kebabName %>\");<% } %>\n\t\t});\n\n\t\tit(\"applies style\", () => {\n\t\t\tconst page = render(Component, {\n\t\t\t\tprops: { style: \"color: orange;\", ...baseProps },\n\t\t\t});\n\t\t\texpect(componentLocator(page).style.color).toBe(\"orange\");\n\t\t});\n\t});\n});\n\n// Note: Prefer role/semantics-oriented ways of selecting elements (e.g., by role, label, etc.) not only for component roots but for all elements to enhance accessibility and maintainability.\n// To select the component's root element, use one of the available [Queries](https://testing-library.com/docs/queries/about/#priority).\nfunction componentLocator(page: RenderResult): HTMLElement {\n\t// 1. SEMANTIC ROLES (PREFERRED) - These the most closely resemble how assistive technologies interact with your component\n\t// return page.getByRole(\"link\", { name: \"Learn more\" });\n\n\t// 2. LABELS - To test the association between labels and form controls\n\t// return page.getByLabelText(\"Email address\");\n\n\t// 3. PLACEHOLDER TEXT - Useful for input fields with placeholders\n\t// return page.getByPlaceholderText(\"Enter your email\");\n\n\t// 4. TEXT CONTENT - Good for testing the presence of unique texts and selecting non-interactive elements\n\t// return page.getByText(\"<%= name %>\");\n\n\t// 5. DISPLAY VALUE - For selecting form elements by their current value\n\t// return page.getByDisplayValue(\"test value\");\n\n\t// 6. ALT TEXT - For images and visual elements\n\t// return page.getByAltText(\"Company logo\");\n\n\t// 7. TITLE ATTRIBUTE - For elements with title tooltips\n\t// return page.getByTitle(\"Close dialog\");\n\n\t// 8. TEST IDS (LAST RESORT) - When semantic options aren't available\n\t// return page.getByTestId(\"<%= kebabName %>\");\n}\n",
|
|
38
|
-
"component/svelte/stories.svelte.ejs": "<script lang=\"ts\" module>\n\timport { defineMeta } from \"@storybook/addon-svelte-csf\";\n\timport <%= name %> from \"./<%= name %>.svelte\";\n\n\tconst { Story } = defineMeta({\n\t\ttitle: \"Components/<%= name %>\",\n\t\tcomponent: <%= name %>,\n\t\ttags: [\"autodocs\"],\n\t});\n</script>\n\n<Story name=\"Default\">\n\tHello, <%= name %>!\n</Story>\n\n<Story\n name=\"WithCustomClass\"\n args={{\n class: \"custom-class\",\n id: \"custom-id\",\n style: \"background-color: tomato;\",\n }}\n>\n\tCustom styled\n</Story>\n",
|
|
39
|
-
"component/svelte/stories.ts.ejs": "import type { Meta, StoryObj } from \"@storybook/svelte\";\nimport <%= name %> from \"./<%= name %>.svelte\";\n\nconst meta: Meta<typeof <%= name %>> = {\n\ttitle: \"Components/<%= name %>\",\n\tcomponent: <%= name %>,\n\ttags: [\"autodocs\"],\n};\n\nexport default meta;\ntype Story = StoryObj<typeof <%= name %>>;\n\nexport const Default: Story = {};\n\nexport const WithCustomClass: Story = {\n\targs: {\n\t\tclass: \"custom-class\",\n\t},\n};\n",
|
|
40
|
-
"component/svelte/test.ts.ejs": "import type { Locator } from \"@vitest/browser/context\";\nimport { createRawSnippet } from \"svelte\";\nimport type { ComponentProps } from \"svelte\";\nimport { describe, expect, it } from \"vitest\";\nimport { render } from \"vitest-browser-svelte\";\nimport type { RenderResult } from \"vitest-browser-svelte\";\nimport Component from \"./<%= name %>.svelte\";\n\ndescribe(\"<%= name %> component\", () => {\n\tconst baseProps = {\n\t\tchildren: createRawSnippet(() => ({\n\t\t\trender: () => `<span><%= name %></span>`,\n\t\t})),\n\t} satisfies ComponentProps<typeof Component>;\n\n\tit(\"renders\", async () => {\n\t\tconst page = render(Component, { ...baseProps });\n\t\tawait expect.element(componentLocator(page)).toBeInTheDocument();\n\t\tawait expect.element(page.getByText(\"<%= name %>\")).toBeVisible();\n\t});\n\n\tdescribe(\"attributes\", () => {\n\t\tit.each([\n\t\t\t[\"id\", \"test-id\"],\n\t\t\t[\"aria-label\", \"test-aria-label\"],\n\t\t])(\"applies %s\", async (attribute, expected) => {\n\t\t\tconst page = render(Component, { ...baseProps, [attribute]: expected });\n\t\t\tawait expect\n\t\t\t\t.element(componentLocator(page))\n\t\t\t\t.toHaveAttribute(attribute, expected);\n\t\t});\n\n\t\tit(\"applies classes\", async () => {\n\t\t\tconst page = render(Component, { ...baseProps, class: \"test-class\" });\n\t\t\tawait expect.element(componentLocator(page)).toHaveClass(\"test-class\");\n<% if (withStyles) { _%>\n\t\t\tawait expect.element(componentLocator(page)).toHaveClass(\"ds\");\n\t\t\tawait expect\n\t\t\t\t.element(componentLocator(page))\n\t\t\t\t.toHaveClass(\"<%= kebabName %>\");<% } %>\n\t\t});\n\n\t\tit(\"applies style\", async () => {\n\t\t\tconst page = render(Component, {\n\t\t\t\t...baseProps,\n\t\t\t\tstyle: \"color: orange;\",\n\t\t\t});\n\t\t\tawait expect\n\t\t\t\t.element(componentLocator(page))\n\t\t\t\t.toHaveStyle({ color: \"orange\" });\n\t\t});\n\t});\n});\n\n// Note: Prefer role/semantics-oriented ways of selecting elements (e.g., by role, label, etc.) not only for component roots but for all elements to enhance accessibility and maintainability.\n// To select the component's root element, use one of the available [Locators](https://vitest.dev/guide/browser/locators.html).\nfunction componentLocator(page: RenderResult<typeof Component>): Locator {\n\t// 1. SEMANTIC ROLES (PREFERRED) - These the most closely resemble how assistive technologies interact with your component\n\t// return page.getByRole(\"link\", { name: \"Learn more\" });\n\n\t// 2. LABELS - To test the association between labels and form controls\n\t// return page.getByLabel(\"Email address\");\n\n\t// 3. PLACEHOLDER TEXT - Useful for input fields with placeholders\n\t// return page.getByPlaceholder(\"Enter your email\");\n\n\t// 4. TEXT CONTENT - Good for testing the presence of unique texts and selecting non-interactive elements\n\t// return page.getByText(\"<%= name %>\");\n\n\t// 5. ALT TEXT - For images and visual elements\n\t// return page.getByAltText(\"Company logo\");\n\n\t// 6. TITLE ATTRIBUTE - For elements with title tooltips\n\t// return page.getByTitle(\"Close dialog\");\n\n\t// 7. TEST IDS (LAST RESORT) - When semantic options aren't available\n\t// return page.getByTestId(\"<%= kebabName %>\");\n}\n",
|
|
41
|
-
"component/svelte/types.ts.ejs": "import type { Snippet } from \"svelte\";\nimport type { SvelteHTMLElements } from \"svelte/elements\";\n\n/*\n\tFor components that render specific HTML elements with extended prop sets,\n\tmake sure to change `\"div\"` to the appropriate HTML element type.\n*/\ntype BaseProps = SvelteHTMLElements[\"div\"];\n\nexport interface <%= name %>Props extends BaseProps {\n\t/** Content to render inside the component */\n\tchildren?: Snippet;\n\t// Define additional props specific to <%= name %> here\n}\n\n/*\n\t...or consider using appropriate interfaces directly exported from `svelte/elements`.\n\n\tFor example:\n\t- `HTMLButtonAttributes` (provides `disabled`, `type`, etc.)\n\t- `HTMLAnchorAttributes` (provides `href`, `target`, etc.)\n\t- `HTMLInputAttributes` (provides `type`, `checked`, `value`, etc.)\n\t- `HTMLFormAttributes` (provides `action`, `method`, etc.)\n\n\t```typescript\n\timport type { HTMLButtonAttributes } from \"svelte/elements\";\n\n\texport interface MyButtonProps extends HTMLButtonAttributes {\n\t\t// Your custom props here\n\t}\n\t```\n\n\tSee Svelte documentation on typing wrapper components:\n\thttps://svelte.dev/docs/svelte/typescript#Typing-wrapper-components\n*/\n",
|
|
42
|
-
"package/PULL_REQUEST_TEMPLATE.md.ejs": "## Summary\n\n[What this PR does and why]\n\n## QA\n\n- [Add QA steps]\n\n### Checklist\n\n- [ ] PR title follows [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) format\n- [ ] Code follows the [code standards](https://github.com/canonical/web-code-standards)\n- [ ] `check`, `test` pass locally\n",
|
|
43
|
-
"package/README.md.ejs": "# <%= name %>\n\n<%= description || 'TODO: Add description' %>\n\n## Installation\n\n```bash\nbun add <%= name %>\n```\n\n## Usage\n\n```typescript\nimport { } from \"<%= name %>\";\n```\n\n## Development\n\n```bash\n# Run checks\nbun run check\n\n# Run tests\nbun run test\n```\n\n## License\n\n<%= license %>\n",
|
|
44
|
-
"package/biome.json.ejs": "{\n \"extends\": [\"@canonical/biome-config\"],\n \"files\": {\n \"includes\": [\"src\", \"*.json\"]\n }\n}\n",
|
|
45
|
-
"package/cli.ts.ejs": "#!/usr/bin/env bun\n/**\n * <%= name %> CLI\n *\n * <%= description || 'TODO: Add description' %>\n */\n\nconsole.log(\"Hello from <%= shortName %>!\");\n",
|
|
46
|
-
"package/index.css.ejs": "/**\n * <%= name %>\n *\n * <%= description || 'TODO: Add description' %>\n */\n",
|
|
47
|
-
"package/index.ts.ejs": "/**\n * <%= name %>\n *\n * <%= description || 'TODO: Add description' %>\n */\n\nexport {};\n",
|
|
48
|
-
"package/package.json.ejs": "{\n \"name\": \"<%= name %>\",\n \"description\": \"<%= description %>\",\n \"version\": \"<%= version %>\",\n \"type\": \"module\",\n<% if (type === 'tool-ts') { -%>\n \"module\": \"src/index.ts\",\n \"types\": \"src/index.ts\",\n<% } else if (type === 'css') { -%>\n \"module\": \"src/index.css\",\n<% } else { -%>\n \"module\": \"dist/esm/index.js\",\n \"types\": \"dist/types/index.d.ts\",\n<% } -%>\n<% if (withCli && type !== 'css') { -%>\n \"bin\": {\n \"<%= shortName %>\": \"src/cli.ts\"\n },\n<% } -%>\n \"files\": [\n<% if (type === 'tool-ts' || type === 'css') { -%>\n \"src\"\n<% } else { -%>\n \"dist\"\n<% } -%>\n ],\n \"author\": {\n \"email\": \"webteam@canonical.com\",\n \"name\": \"Canonical Webteam\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/canonical/pragma\"\n },\n \"license\": \"<%= license %>\",\n \"bugs\": {\n \"url\": \"https://github.com/canonical/pragma/issues\"\n },\n \"homepage\": \"https://github.com/canonical/pragma#readme\",\n \"scripts\": {\n<% if (type === 'tool-ts' || type === 'css') { -%>\n \"build\": \"echo 'No build needed'\",\n<% } else { -%>\n \"build\": \"tsc -p tsconfig.build.json\",\n<% } -%>\n<% if (withStorybook) { -%>\n \"build:all\": \"bun run build && bun run build:storybook\",\n \"build:storybook\": \"storybook build\",\n<% } else { -%>\n \"build:all\": \"bun run build\",\n<% } -%>\n<% if (type === 'css') { -%>\n \"check\": \"bun run check:biome && bun run check:webarchitect\",\n \"check:fix\": \"bun run check:biome:fix\",\n<% } else { -%>\n \"check\": \"bun run check:biome && bun run check:ts && bun run check:webarchitect\",\n \"check:fix\": \"bun run check:biome:fix && bun run check:ts\",\n<% } -%>\n \"check:biome\": \"biome check\",\n \"check:biome:fix\": \"biome check --write\",\n<% if (type !== 'css') { -%>\n \"check:ts\": \"tsc --noEmit\",\n<% } -%>\n \"check:webarchitect\": \"webarchitect <%= ruleset %>\",\n<% if (withStorybook) { -%>\n \"storybook\": \"storybook dev -p 6006 --no-open --host 0.0.0.0\",\n<% } -%>\n<% if (type === 'css') { -%>\n \"test\": \"echo 'No tests for CSS package'\"\n<% } else { -%>\n \"test\": \"vitest run\"\n<% } -%>\n },\n<% if (type !== 'css') { -%>\n \"devDependencies\": {\n \"@biomejs/biome\": \"2.4.6\",\n \"@canonical/biome-config\": \"^<%= monorepoVersion || '0.1.0' %>\",\n<% if (withReact) { -%>\n \"@canonical/typescript-config-react\": \"^<%= monorepoVersion || '0.1.0' %>\",\n<% } else { -%>\n \"@canonical/typescript-config\": \"^<%= monorepoVersion || '0.1.0' %>\",\n<% } -%>\n<% if (withStorybook) { -%>\n \"@chromatic-com/storybook\": \"^5.0.0\",\n<% } -%>\n<% if (withReact) { -%>\n \"@types/react\": \"^19.0.0\",\n \"@types/react-dom\": \"^19.0.0\",\n<% } -%>\n \"bun-types\": \"^1.0.0\",\n<% if (withStorybook) { -%>\n \"storybook\": \"^10.1.11\",\n<% } -%>\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^3.2.4\"\n },\n \"dependencies\": {\n<% if (withStorybook) { -%>\n \"@canonical/storybook-config\": \"^<%= monorepoVersion || '0.1.0' %>\",\n<% } -%>\n<% if (withReact) { -%>\n \"react\": \"^19.0.0\",\n \"react-dom\": \"^19.0.0\"\n<% } -%>\n }\n<% } else { -%>\n \"devDependencies\": {\n \"@biomejs/biome\": \"2.4.6\",\n \"@canonical/biome-config\": \"^<%= monorepoVersion || '0.1.0' %>\"\n }\n<% } -%>\n}\n",
|
|
49
|
-
"package/storybook-main.ts.ejs": "import { createConfig } from \"@canonical/storybook-config\";\n\nexport default createConfig(\"react\", {\n staticDirs: [\"../src/assets\", \"../public\"],\n});\n",
|
|
50
|
-
"package/storybook-preview.ts.ejs": "import { withThemeByClassName } from \"@storybook/addon-themes\";\nimport type { Preview, ReactRenderer } from \"@storybook/react-vite\";\n\nimport \"index.css\";\nimport \"@canonical/styles-debug/baseline-grid\";\n\nconst preview: Preview = {\n tags: [\"autodocs\"],\n decorators: [\n withThemeByClassName<ReactRenderer>({\n themes: {\n light: \"is-light\",\n dark: \"dark\",\n paper: \"is-paper\",\n },\n defaultTheme: \"light\",\n }),\n ],\n parameters: {\n docs: {\n codePanel: true,\n },\n },\n};\n\nexport default preview;\n",
|
|
51
|
-
"package/tsconfig-react.json.ejs": "{\n \"extends\": \"@canonical/typescript-config-react\",\n \"compilerOptions\": {\n \"baseUrl\": \"src\",\n \"types\": [\"bun-types\"]\n },\n \"include\": [\"src/**/*.ts\", \"src/**/*.tsx\"]\n}\n",
|
|
52
|
-
"package/tsconfig.json.ejs": "{\n \"extends\": \"@canonical/typescript-config\",\n \"compilerOptions\": {\n \"baseUrl\": \"src\",\n \"types\": [\"bun-types\"]\n },\n \"include\": [\"src/**/*.ts\"]\n}\n",
|
|
53
|
-
};
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { readConfig } from "../../../kernel/config/readConfig.js";
|
|
2
|
-
import type { PragmaRuntime } from "../../../kernel/runtime/types.js";
|
|
3
|
-
import type { CheckResult } from "../types.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Check which config layer is active for the working directory.
|
|
7
|
-
*
|
|
8
|
-
* Passes when a project `pragma.config.ts` is found up the tree, or — pragma is
|
|
9
|
-
* global-first — when only the global XDG config exists. Fails only when
|
|
10
|
-
* neither layer is configured.
|
|
11
|
-
*
|
|
12
|
-
* @param rt - The per-invocation runtime (for `cwd`).
|
|
13
|
-
* @returns A CheckResult indicating the active layer, or fail with a remedy.
|
|
14
|
-
* @note Impure — reads the config layers from disk.
|
|
15
|
-
*/
|
|
16
|
-
export async function checkConfigFile(rt: PragmaRuntime): Promise<CheckResult> {
|
|
17
|
-
const layers = await readConfig(rt.cwd);
|
|
18
|
-
|
|
19
|
-
if (layers.project.exists) {
|
|
20
|
-
return {
|
|
21
|
-
name: "pragma config",
|
|
22
|
-
status: "pass",
|
|
23
|
-
detail: `project config active (${layers.project.path})`,
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (layers.global.exists) {
|
|
28
|
-
return {
|
|
29
|
-
name: "pragma config",
|
|
30
|
-
status: "pass",
|
|
31
|
-
detail: `no project config — global config active (${layers.global.path})`,
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return {
|
|
36
|
-
name: "pragma config",
|
|
37
|
-
status: "fail",
|
|
38
|
-
detail: "not found",
|
|
39
|
-
remedy: "pragma config set tier <path>",
|
|
40
|
-
};
|
|
41
|
-
}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
2
|
-
import { delimiter, isAbsolute, join } from "node:path";
|
|
3
|
-
import type { DetectedHarness } from "@canonical/harnesses";
|
|
4
|
-
import { detectHarnesses, readMcpConfig } from "@canonical/harnesses";
|
|
5
|
-
import { runTask } from "@canonical/task/node";
|
|
6
|
-
import type { CheckItem, CheckResult } from "../types.js";
|
|
7
|
-
import { deriveBand } from "./deriveBand.js";
|
|
8
|
-
|
|
9
|
-
const NAME = "MCP commands";
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Extract the stdio command from an MCP server config entry, if any. HTTP/SSE
|
|
13
|
-
* entries (`{ type: "http", url }`) have no command and are not checked.
|
|
14
|
-
*/
|
|
15
|
-
function commandOf(entry: unknown): string | undefined {
|
|
16
|
-
if (typeof entry !== "object" || entry === null) return undefined;
|
|
17
|
-
const command = (entry as { command?: unknown }).command;
|
|
18
|
-
return typeof command === "string" && command.length > 0
|
|
19
|
-
? command
|
|
20
|
-
: undefined;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Resolve a command the way a shell would: a path-bearing entry is checked as a
|
|
25
|
-
* file (relative to the project root), a bare name is searched across `PATH`.
|
|
26
|
-
*/
|
|
27
|
-
function commandResolves(command: string, cwd: string): boolean {
|
|
28
|
-
if (command.includes("/") || command.includes("\\")) {
|
|
29
|
-
return existsSync(isAbsolute(command) ? command : join(cwd, command));
|
|
30
|
-
}
|
|
31
|
-
return (process.env.PATH ?? "")
|
|
32
|
-
.split(delimiter)
|
|
33
|
-
.filter((dir) => dir.length > 0)
|
|
34
|
-
.some((dir) => existsSync(join(dir, command)));
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Check that every command-based MCP server entry in detected harness configs
|
|
39
|
-
* resolves to an executable. A dead entry makes every agent session try and
|
|
40
|
-
* fail to boot it, so it is flagged with its config path.
|
|
41
|
-
*
|
|
42
|
-
* @param cwd - The project root to detect harnesses against.
|
|
43
|
-
* @returns pass (all resolve), fail (listing broken entries), or skip (nothing
|
|
44
|
-
* to check).
|
|
45
|
-
* @note Impure — detects harnesses, reads configs, and probes PATH/the fs.
|
|
46
|
-
*/
|
|
47
|
-
export async function checkMcpCommands(cwd: string): Promise<CheckResult> {
|
|
48
|
-
let detected: DetectedHarness[];
|
|
49
|
-
try {
|
|
50
|
-
detected = await runTask(detectHarnesses(cwd));
|
|
51
|
-
} catch {
|
|
52
|
-
return { name: NAME, status: "skip", detail: "harness detection failed" };
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const withConfig = detected.filter((d) => d.configExists);
|
|
56
|
-
if (withConfig.length === 0) {
|
|
57
|
-
return { name: NAME, status: "skip", detail: "no MCP configs found" };
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Band the finding by the harnesses whose configs were actually examined, so
|
|
61
|
-
// a global-scope harness's broken command is reported under the global band.
|
|
62
|
-
const band = deriveBand(withConfig);
|
|
63
|
-
const broken: CheckItem[] = [];
|
|
64
|
-
let checked = 0;
|
|
65
|
-
|
|
66
|
-
for (const d of withConfig) {
|
|
67
|
-
let servers: Record<string, unknown>;
|
|
68
|
-
try {
|
|
69
|
-
servers = await runTask(readMcpConfig(d.harness, cwd));
|
|
70
|
-
} catch {
|
|
71
|
-
continue; // The "MCP configured" check reports on unreadable configs.
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
for (const [serverName, entry] of Object.entries(servers)) {
|
|
75
|
-
const command = commandOf(entry);
|
|
76
|
-
if (!command) continue;
|
|
77
|
-
checked += 1;
|
|
78
|
-
if (!commandResolves(command, cwd)) {
|
|
79
|
-
broken.push({
|
|
80
|
-
label: `"${serverName}"`,
|
|
81
|
-
status: "fail",
|
|
82
|
-
detail: `"${command}" not found · ${d.configPath}`,
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (checked === 0) {
|
|
89
|
-
return {
|
|
90
|
-
name: NAME,
|
|
91
|
-
status: "skip",
|
|
92
|
-
detail: "no command-based MCP servers configured",
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (broken.length === 0) {
|
|
97
|
-
return {
|
|
98
|
-
name: NAME,
|
|
99
|
-
status: "pass",
|
|
100
|
-
detail: `${checked} command${checked === 1 ? "" : "s"} resolve on PATH`,
|
|
101
|
-
band,
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return {
|
|
106
|
-
name: NAME,
|
|
107
|
-
status: "fail",
|
|
108
|
-
detail: `${broken.length} of ${checked} unresolvable`,
|
|
109
|
-
items: broken,
|
|
110
|
-
remedy:
|
|
111
|
-
"Install the missing command or remove the entry — every agent session tries and fails to boot it.",
|
|
112
|
-
band,
|
|
113
|
-
};
|
|
114
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import type { DetectedHarness } from "@canonical/harnesses";
|
|
2
|
-
import { detectHarnesses, readMcpConfig } from "@canonical/harnesses";
|
|
3
|
-
import { runTask } from "@canonical/task/node";
|
|
4
|
-
import type { CheckResult } from "../types.js";
|
|
5
|
-
import { deriveBand } from "./deriveBand.js";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Check that at least one AI harness has pragma configured as an MCP server. The
|
|
9
|
-
* result's band is derived from the harnesses actually found (Windsurf ⇒ global,
|
|
10
|
-
* Cursor ⇒ project), not the check name — so a global-scope harness is not
|
|
11
|
-
* mislabeled PROJECT.
|
|
12
|
-
*
|
|
13
|
-
* @param cwd - The project root to detect harnesses against.
|
|
14
|
-
* @returns A CheckResult listing configured harnesses, or fail with a remedy.
|
|
15
|
-
* @note Impure — detects harnesses and reads their MCP configs.
|
|
16
|
-
*/
|
|
17
|
-
export async function checkMcpConfigured(cwd: string): Promise<CheckResult> {
|
|
18
|
-
let detected: DetectedHarness[];
|
|
19
|
-
try {
|
|
20
|
-
detected = await runTask(detectHarnesses(cwd));
|
|
21
|
-
} catch {
|
|
22
|
-
return {
|
|
23
|
-
name: "MCP configured",
|
|
24
|
-
status: "fail",
|
|
25
|
-
detail: "harness detection failed",
|
|
26
|
-
remedy: "pragma setup mcp",
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (detected.length === 0) {
|
|
31
|
-
return {
|
|
32
|
-
name: "MCP configured",
|
|
33
|
-
status: "fail",
|
|
34
|
-
detail: "no AI harnesses detected",
|
|
35
|
-
remedy: "pragma setup mcp",
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const configured: DetectedHarness[] = [];
|
|
40
|
-
for (const d of detected) {
|
|
41
|
-
if (!d.configExists) continue;
|
|
42
|
-
try {
|
|
43
|
-
const servers = await runTask(readMcpConfig(d.harness, cwd));
|
|
44
|
-
if ("pragma" in servers) configured.push(d);
|
|
45
|
-
} catch {
|
|
46
|
-
// Config unreadable — skip.
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (configured.length > 0) {
|
|
51
|
-
return {
|
|
52
|
-
name: "MCP configured",
|
|
53
|
-
status: "pass",
|
|
54
|
-
detail: configured.map((d) => d.harness.name).join(", "),
|
|
55
|
-
band: deriveBand(configured),
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const names = detected.map((d) => d.harness.name).join(", ");
|
|
60
|
-
return {
|
|
61
|
-
name: "MCP configured",
|
|
62
|
-
status: "fail",
|
|
63
|
-
detail: `detected ${names} but pragma not configured`,
|
|
64
|
-
remedy: "pragma setup mcp",
|
|
65
|
-
band: deriveBand(detected),
|
|
66
|
-
};
|
|
67
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
2
|
-
import type { DetectedHarness } from "@canonical/harnesses";
|
|
3
|
-
import { detectHarnesses } from "@canonical/harnesses";
|
|
4
|
-
import { runTask } from "@canonical/task/node";
|
|
5
|
-
import type { CheckResult } from "../types.js";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Check that a skills directory exists for each detected AI harness. Skipped
|
|
9
|
-
* when no harnesses are detected.
|
|
10
|
-
*
|
|
11
|
-
* @param cwd - The project root to detect harnesses against.
|
|
12
|
-
* @returns A CheckResult indicating pass, fail (with a remedy), or skip.
|
|
13
|
-
* @note Impure — detects harnesses and probes the filesystem.
|
|
14
|
-
*/
|
|
15
|
-
export async function checkSkillsSymlinked(cwd: string): Promise<CheckResult> {
|
|
16
|
-
let detected: DetectedHarness[];
|
|
17
|
-
try {
|
|
18
|
-
detected = await runTask(detectHarnesses(cwd));
|
|
19
|
-
} catch {
|
|
20
|
-
return {
|
|
21
|
-
name: "Skills symlinked",
|
|
22
|
-
status: "fail",
|
|
23
|
-
detail: "harness detection failed",
|
|
24
|
-
remedy: "pragma setup skills",
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (detected.length === 0) {
|
|
29
|
-
return {
|
|
30
|
-
name: "Skills symlinked",
|
|
31
|
-
status: "skip",
|
|
32
|
-
detail: "no AI harnesses detected",
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const linked: string[] = [];
|
|
37
|
-
const missing: string[] = [];
|
|
38
|
-
for (const d of detected) {
|
|
39
|
-
if (existsSync(d.harness.skillsPath(cwd))) {
|
|
40
|
-
linked.push(d.harness.name);
|
|
41
|
-
} else {
|
|
42
|
-
missing.push(d.harness.name);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (missing.length === 0) {
|
|
47
|
-
return {
|
|
48
|
-
name: "Skills symlinked",
|
|
49
|
-
status: "pass",
|
|
50
|
-
detail: linked.join(", "),
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
name: "Skills symlinked",
|
|
56
|
-
status: "fail",
|
|
57
|
-
detail: `missing for ${missing.join(", ")}`,
|
|
58
|
-
remedy: "pragma setup skills",
|
|
59
|
-
};
|
|
60
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `deriveBand` — band a doctor check by the harnesses it actually found.
|
|
3
|
-
*
|
|
4
|
-
* Fixtures wrap REAL harness definitions (via `findHarnessById`, no casts), so
|
|
5
|
-
* the scope→band mapping is exercised against the true `scope` fields: the
|
|
6
|
-
* regression this guards is a global-scope harness (Windsurf) being mislabeled
|
|
7
|
-
* PROJECT by a static per-name guess.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import type { DetectedHarness } from "@canonical/harnesses";
|
|
11
|
-
import { findHarnessById } from "@canonical/harnesses";
|
|
12
|
-
import { describe, expect, it } from "vitest";
|
|
13
|
-
import { deriveBand } from "./deriveBand.js";
|
|
14
|
-
|
|
15
|
-
/** A minimal {@link DetectedHarness} over a real definition (no `as` casts). */
|
|
16
|
-
function detect(id: string): DetectedHarness {
|
|
17
|
-
const harness = findHarnessById(id);
|
|
18
|
-
if (!harness) throw new Error(`unknown harness fixture: ${id}`);
|
|
19
|
-
return { harness, confidence: "high", configExists: true, configPath: "x" };
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
describe("deriveBand", () => {
|
|
23
|
-
it("bands a project-scope harness (Cursor) as project", () => {
|
|
24
|
-
expect(deriveBand([detect("cursor")])).toBe("project");
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it("bands a global-scope harness (Windsurf) as global — the fixed mislabel", () => {
|
|
28
|
-
expect(deriveBand([detect("windsurf")])).toBe("global");
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it("bands a dual-scope harness (Claude Code) by its default band (project)", () => {
|
|
32
|
-
expect(deriveBand([detect("claude-code")])).toBe("project");
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it("leaves a set spanning BOTH bands unbanded (general, not mislabeled)", () => {
|
|
36
|
-
expect(deriveBand([detect("cursor"), detect("windsurf")])).toBeUndefined();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it("leaves an empty set unbanded", () => {
|
|
40
|
-
expect(deriveBand([])).toBeUndefined();
|
|
41
|
-
});
|
|
42
|
-
});
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Derive a doctor check's config band from the harnesses it actually found,
|
|
3
|
-
* rather than a static per-check-name guess. The aggregate MCP checks read each
|
|
4
|
-
* harness's DEFAULT-band file (`defaultBandOf` — the home config for a
|
|
5
|
-
* global-only harness like Windsurf, the project file otherwise), so the band a
|
|
6
|
-
* finding belongs to is exactly that default band.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { DetectedHarness } from "@canonical/harnesses";
|
|
10
|
-
import { defaultBandOf } from "@canonical/harnesses";
|
|
11
|
-
import type { ScopeBand } from "../types.js";
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* The single config band a set of detected harnesses shares, or `undefined` when
|
|
15
|
-
* the set is empty or genuinely spans BOTH bands. A two-band finding stays
|
|
16
|
-
* unbanded (rendered in the general section) instead of being mislabeled as one
|
|
17
|
-
* band — faithful to the two-band model: band by what was found, never a guess.
|
|
18
|
-
*
|
|
19
|
-
* @param harnesses - The detected harnesses the check reports on.
|
|
20
|
-
* @returns The shared {@link ScopeBand}, or `undefined` when none/mixed.
|
|
21
|
-
*/
|
|
22
|
-
export function deriveBand(
|
|
23
|
-
harnesses: readonly DetectedHarness[],
|
|
24
|
-
): ScopeBand | undefined {
|
|
25
|
-
const bands = new Set<ScopeBand>();
|
|
26
|
-
for (const detected of harnesses) bands.add(defaultBandOf(detected.harness));
|
|
27
|
-
return bands.size === 1 ? bands.values().next().value : undefined;
|
|
28
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The `modifier` capability module — the bundled pack (SPARQL list, GraphQL
|
|
3
|
-
* lookup) compiled to verbs.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { compilePack } from "../../kernel/packs/compile.js";
|
|
7
|
-
import { DEFAULT_PREFIX_MAP } from "../../kernel/render/prefixes.js";
|
|
8
|
-
import type { CapabilityModule } from "../../kernel/spec/types.js";
|
|
9
|
-
import { modifierPack } from "./pack.js";
|
|
10
|
-
|
|
11
|
-
/** The `modifier` capability module (`list`, `lookup`). */
|
|
12
|
-
export const modifierModule: CapabilityModule = {
|
|
13
|
-
name: "modifier",
|
|
14
|
-
verbs: compilePack(modifierPack, "bundled:modifier", DEFAULT_PREFIX_MAP),
|
|
15
|
-
};
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The bundled `modifier` pack — modifier families as data.
|
|
3
|
-
*
|
|
4
|
-
* `modifier list` is SPARQL (an alternation path collects values asserted in
|
|
5
|
-
* either direction); `modifier lookup` is GRAPHQL, where the compiled
|
|
6
|
-
* `ModifierFamily.modifiers` field is the declared-inverse union and resolves
|
|
7
|
-
* both directions in ONE generated document — exactly the case the GraphQL fetch
|
|
8
|
-
* path exists for.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type { PackDefinition } from "../../kernel/packs/types.js";
|
|
12
|
-
|
|
13
|
-
export const modifierPack: PackDefinition = {
|
|
14
|
-
noun: "modifier",
|
|
15
|
-
description: "List all modifier families.",
|
|
16
|
-
toolDescription:
|
|
17
|
-
"List all modifier families with their values. Use when browsing which modifier families exist and the values each allows. Example: modifier_list {}.",
|
|
18
|
-
list: {
|
|
19
|
-
query: [
|
|
20
|
-
"SELECT ?uri ?name",
|
|
21
|
-
' (GROUP_CONCAT(DISTINCT ?valueName; separator=", ") AS ?values)',
|
|
22
|
-
"WHERE {",
|
|
23
|
-
" ?uri a ds:ModifierFamily ;",
|
|
24
|
-
" ds:name ?name .",
|
|
25
|
-
" OPTIONAL {",
|
|
26
|
-
" ?uri (ds:hasModifier|^ds:modifierFamily) ?value .",
|
|
27
|
-
" ?value ds:name ?valueName .",
|
|
28
|
-
" }",
|
|
29
|
-
"}",
|
|
30
|
-
"GROUP BY ?uri ?name",
|
|
31
|
-
"ORDER BY ?name",
|
|
32
|
-
].join("\n"),
|
|
33
|
-
columns: [
|
|
34
|
-
{ field: "uri", label: "IRI" },
|
|
35
|
-
{ field: "name", label: "Name" },
|
|
36
|
-
{ field: "values", label: "Values" },
|
|
37
|
-
],
|
|
38
|
-
emptyRecovery: {
|
|
39
|
-
message:
|
|
40
|
-
"No modifier families in the store. Build it from the configured design-system packages.",
|
|
41
|
-
cli: "pragma sources update",
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
lookup: {
|
|
45
|
-
source: "graphql",
|
|
46
|
-
by: "ds:name",
|
|
47
|
-
type: "ds:ModifierFamily",
|
|
48
|
-
toolDescription:
|
|
49
|
-
'Get values and usage details for one or more modifier families by name. Use when you need the allowed values of specific families. Example: modifier_lookup { names: ["importance"] }.',
|
|
50
|
-
expand: [
|
|
51
|
-
{
|
|
52
|
-
name: "values",
|
|
53
|
-
heading: "Values",
|
|
54
|
-
relation: "ds:hasModifier",
|
|
55
|
-
select: [{ name: "name", property: "ds:name" }],
|
|
56
|
-
},
|
|
57
|
-
],
|
|
58
|
-
sample: {
|
|
59
|
-
fixedCount: true,
|
|
60
|
-
toolDescription:
|
|
61
|
-
"Return randomly selected complete modifier families (with value lists) as exemplars. Use BEFORE writing queries to see actual data shapes.",
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The `standard` capability module — the bundled pack compiled to verbs.
|
|
3
|
-
*
|
|
4
|
-
* Compiled at import (fast-path safe: compilePack is pure/zod-free) so the module
|
|
5
|
-
* is surface-deterministic. A config/package story for `standard` overrides it at
|
|
6
|
-
* dispatch (see kernel/packs/collect).
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { compilePack } from "../../kernel/packs/compile.js";
|
|
10
|
-
import { DEFAULT_PREFIX_MAP } from "../../kernel/render/prefixes.js";
|
|
11
|
-
import type { CapabilityModule } from "../../kernel/spec/types.js";
|
|
12
|
-
import { standardPack } from "./pack.js";
|
|
13
|
-
|
|
14
|
-
/** The `standard` capability module (list, categories, lookup, sample). */
|
|
15
|
-
export const standardModule: CapabilityModule = {
|
|
16
|
-
name: "standard",
|
|
17
|
-
verbs: compilePack(standardPack, "bundled:standard", DEFAULT_PREFIX_MAP),
|
|
18
|
-
};
|