@owlmeans/viable-common 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -0
- package/agent-meta/manifest.json +16 -0
- package/agent-meta/skills/viable-common/SKILL.md +179 -0
- package/build/agent/index.d.ts +4 -0
- package/build/agent/index.d.ts.map +1 -0
- package/build/agent/index.js +3 -0
- package/build/agent/index.js.map +1 -0
- package/build/agent/memory.d.ts +12 -0
- package/build/agent/memory.d.ts.map +1 -0
- package/build/agent/memory.js +11 -0
- package/build/agent/memory.js.map +1 -0
- package/build/agent/spectator/consts.d.ts +9 -0
- package/build/agent/spectator/consts.d.ts.map +1 -0
- package/build/agent/spectator/consts.js +10 -0
- package/build/agent/spectator/consts.js.map +1 -0
- package/build/agent/spectator/index.d.ts +3 -0
- package/build/agent/spectator/index.d.ts.map +1 -0
- package/build/agent/spectator/index.js +2 -0
- package/build/agent/spectator/index.js.map +1 -0
- package/build/agent/spectator/types.d.ts +13 -0
- package/build/agent/spectator/types.d.ts.map +1 -0
- package/build/agent/spectator/types.js +2 -0
- package/build/agent/spectator/types.js.map +1 -0
- package/build/agent/types.d.ts +10 -0
- package/build/agent/types.d.ts.map +1 -0
- package/build/agent/types.js +2 -0
- package/build/agent/types.js.map +1 -0
- package/build/areas/consts.d.ts +88 -0
- package/build/areas/consts.d.ts.map +1 -0
- package/build/areas/consts.js +106 -0
- package/build/areas/consts.js.map +1 -0
- package/build/areas/index.d.ts +3 -0
- package/build/areas/index.d.ts.map +1 -0
- package/build/areas/index.js +2 -0
- package/build/areas/index.js.map +1 -0
- package/build/areas/types.d.ts +28 -0
- package/build/areas/types.d.ts.map +1 -0
- package/build/areas/types.js +2 -0
- package/build/areas/types.js.map +1 -0
- package/build/ba/consts.d.ts +38 -0
- package/build/ba/consts.d.ts.map +1 -0
- package/build/ba/consts.js +41 -0
- package/build/ba/consts.js.map +1 -0
- package/build/ba/helpers.d.ts +41 -0
- package/build/ba/helpers.d.ts.map +1 -0
- package/build/ba/helpers.js +79 -0
- package/build/ba/helpers.js.map +1 -0
- package/build/ba/index.d.ts +5 -0
- package/build/ba/index.d.ts.map +1 -0
- package/build/ba/index.js +4 -0
- package/build/ba/index.js.map +1 -0
- package/build/ba/schemas.d.ts +13 -0
- package/build/ba/schemas.d.ts.map +1 -0
- package/build/ba/schemas.js +181 -0
- package/build/ba/schemas.js.map +1 -0
- package/build/ba/types.d.ts +113 -0
- package/build/ba/types.d.ts.map +1 -0
- package/build/ba/types.js +2 -0
- package/build/ba/types.js.map +1 -0
- package/build/blueprint/case.d.ts +73 -0
- package/build/blueprint/case.d.ts.map +1 -0
- package/build/blueprint/case.js +244 -0
- package/build/blueprint/case.js.map +1 -0
- package/build/blueprint/consts.d.ts +11 -0
- package/build/blueprint/consts.d.ts.map +1 -0
- package/build/blueprint/consts.js +11 -0
- package/build/blueprint/consts.js.map +1 -0
- package/build/blueprint/index.d.ts +6 -0
- package/build/blueprint/index.d.ts.map +1 -0
- package/build/blueprint/index.js +6 -0
- package/build/blueprint/index.js.map +1 -0
- package/build/blueprint/resolve.d.ts +51 -0
- package/build/blueprint/resolve.d.ts.map +1 -0
- package/build/blueprint/resolve.js +108 -0
- package/build/blueprint/resolve.js.map +1 -0
- package/build/blueprint/schemas.d.ts +41 -0
- package/build/blueprint/schemas.d.ts.map +1 -0
- package/build/blueprint/schemas.js +27 -0
- package/build/blueprint/schemas.js.map +1 -0
- package/build/blueprint/types.d.ts +186 -0
- package/build/blueprint/types.d.ts.map +1 -0
- package/build/blueprint/types.js +32 -0
- package/build/blueprint/types.js.map +1 -0
- package/build/branding.d.ts +19 -0
- package/build/branding.d.ts.map +1 -0
- package/build/branding.js +32 -0
- package/build/branding.js.map +1 -0
- package/build/connect/consts.d.ts +378 -0
- package/build/connect/consts.d.ts.map +1 -0
- package/build/connect/consts.js +425 -0
- package/build/connect/consts.js.map +1 -0
- package/build/connect/entrypoints.d.ts +41 -0
- package/build/connect/entrypoints.d.ts.map +1 -0
- package/build/connect/entrypoints.js +141 -0
- package/build/connect/entrypoints.js.map +1 -0
- package/build/connect/errors.d.ts +50 -0
- package/build/connect/errors.d.ts.map +1 -0
- package/build/connect/errors.js +77 -0
- package/build/connect/errors.js.map +1 -0
- package/build/connect/index.d.ts +8 -0
- package/build/connect/index.d.ts.map +1 -0
- package/build/connect/index.js +6 -0
- package/build/connect/index.js.map +1 -0
- package/build/connect/ops.d.ts +192 -0
- package/build/connect/ops.d.ts.map +1 -0
- package/build/connect/ops.js +2 -0
- package/build/connect/ops.js.map +1 -0
- package/build/connect/references.d.ts +194 -0
- package/build/connect/references.d.ts.map +1 -0
- package/build/connect/references.js +62 -0
- package/build/connect/references.js.map +1 -0
- package/build/connect/schemas.d.ts +59 -0
- package/build/connect/schemas.d.ts.map +1 -0
- package/build/connect/schemas.js +346 -0
- package/build/connect/schemas.js.map +1 -0
- package/build/connect/types.d.ts +428 -0
- package/build/connect/types.d.ts.map +1 -0
- package/build/connect/types.js +2 -0
- package/build/connect/types.js.map +1 -0
- package/build/consts.d.ts +9 -0
- package/build/consts.d.ts.map +1 -0
- package/build/consts.js +31 -0
- package/build/consts.js.map +1 -0
- package/build/convert/consts.d.ts +539 -0
- package/build/convert/consts.d.ts.map +1 -0
- package/build/convert/consts.js +630 -0
- package/build/convert/consts.js.map +1 -0
- package/build/convert/helpers.d.ts +91 -0
- package/build/convert/helpers.d.ts.map +1 -0
- package/build/convert/helpers.js +301 -0
- package/build/convert/helpers.js.map +1 -0
- package/build/convert/index.d.ts +11 -0
- package/build/convert/index.d.ts.map +1 -0
- package/build/convert/index.js +4 -0
- package/build/convert/index.js.map +1 -0
- package/build/convert/schemas.d.ts +62 -0
- package/build/convert/schemas.d.ts.map +1 -0
- package/build/convert/schemas.js +626 -0
- package/build/convert/schemas.js.map +1 -0
- package/build/convert/types.d.ts +683 -0
- package/build/convert/types.d.ts.map +1 -0
- package/build/convert/types.js +2 -0
- package/build/convert/types.js.map +1 -0
- package/build/design/consts.d.ts +25 -0
- package/build/design/consts.d.ts.map +1 -0
- package/build/design/consts.js +26 -0
- package/build/design/consts.js.map +1 -0
- package/build/design/helpers.d.ts +60 -0
- package/build/design/helpers.d.ts.map +1 -0
- package/build/design/helpers.js +221 -0
- package/build/design/helpers.js.map +1 -0
- package/build/design/index.d.ts +6 -0
- package/build/design/index.d.ts.map +1 -0
- package/build/design/index.js +5 -0
- package/build/design/index.js.map +1 -0
- package/build/design/runtime.d.ts +126 -0
- package/build/design/runtime.d.ts.map +1 -0
- package/build/design/runtime.js +65 -0
- package/build/design/runtime.js.map +1 -0
- package/build/design/schemas.d.ts +21 -0
- package/build/design/schemas.d.ts.map +1 -0
- package/build/design/schemas.js +369 -0
- package/build/design/schemas.js.map +1 -0
- package/build/design/types.d.ts +199 -0
- package/build/design/types.d.ts.map +1 -0
- package/build/design/types.js +2 -0
- package/build/design/types.js.map +1 -0
- package/build/dev/consts.d.ts +32 -0
- package/build/dev/consts.d.ts.map +1 -0
- package/build/dev/consts.js +33 -0
- package/build/dev/consts.js.map +1 -0
- package/build/dev/index.d.ts +4 -0
- package/build/dev/index.d.ts.map +1 -0
- package/build/dev/index.js +3 -0
- package/build/dev/index.js.map +1 -0
- package/build/dev/schemas.d.ts +15 -0
- package/build/dev/schemas.d.ts.map +1 -0
- package/build/dev/schemas.js +116 -0
- package/build/dev/schemas.js.map +1 -0
- package/build/dev/types.d.ts +42 -0
- package/build/dev/types.d.ts.map +1 -0
- package/build/dev/types.js +2 -0
- package/build/dev/types.js.map +1 -0
- package/build/execution/consts.d.ts +36 -0
- package/build/execution/consts.d.ts.map +1 -0
- package/build/execution/consts.js +37 -0
- package/build/execution/consts.js.map +1 -0
- package/build/execution/index.d.ts +3 -0
- package/build/execution/index.d.ts.map +1 -0
- package/build/execution/index.js +2 -0
- package/build/execution/index.js.map +1 -0
- package/build/execution/types.d.ts +50 -0
- package/build/execution/types.d.ts.map +1 -0
- package/build/execution/types.js +2 -0
- package/build/execution/types.js.map +1 -0
- package/build/index.d.ts +22 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +21 -0
- package/build/index.js.map +1 -0
- package/build/integrity/consts.d.ts +226 -0
- package/build/integrity/consts.d.ts.map +1 -0
- package/build/integrity/consts.js +401 -0
- package/build/integrity/consts.js.map +1 -0
- package/build/integrity/index.d.ts +4 -0
- package/build/integrity/index.d.ts.map +1 -0
- package/build/integrity/index.js +3 -0
- package/build/integrity/index.js.map +1 -0
- package/build/integrity/types.d.ts +35 -0
- package/build/integrity/types.d.ts.map +1 -0
- package/build/integrity/types.js +2 -0
- package/build/integrity/types.js.map +1 -0
- package/build/integrity/verify.d.ts +23 -0
- package/build/integrity/verify.d.ts.map +1 -0
- package/build/integrity/verify.js +198 -0
- package/build/integrity/verify.js.map +1 -0
- package/build/metadata/consts.d.ts +101 -0
- package/build/metadata/consts.d.ts.map +1 -0
- package/build/metadata/consts.js +104 -0
- package/build/metadata/consts.js.map +1 -0
- package/build/metadata/index.d.ts +3 -0
- package/build/metadata/index.d.ts.map +1 -0
- package/build/metadata/index.js +3 -0
- package/build/metadata/index.js.map +1 -0
- package/build/metadata/types.d.ts +286 -0
- package/build/metadata/types.d.ts.map +1 -0
- package/build/metadata/types.js +39 -0
- package/build/metadata/types.js.map +1 -0
- package/build/moderation/consts.d.ts +58 -0
- package/build/moderation/consts.d.ts.map +1 -0
- package/build/moderation/consts.js +60 -0
- package/build/moderation/consts.js.map +1 -0
- package/build/moderation/index.d.ts +5 -0
- package/build/moderation/index.d.ts.map +1 -0
- package/build/moderation/index.js +4 -0
- package/build/moderation/index.js.map +1 -0
- package/build/moderation/schemas.d.ts +19 -0
- package/build/moderation/schemas.d.ts.map +1 -0
- package/build/moderation/schemas.js +26 -0
- package/build/moderation/schemas.js.map +1 -0
- package/build/moderation/types.d.ts +64 -0
- package/build/moderation/types.d.ts.map +1 -0
- package/build/moderation/types.js +2 -0
- package/build/moderation/types.js.map +1 -0
- package/build/moderation/utils.d.ts +21 -0
- package/build/moderation/utils.d.ts.map +1 -0
- package/build/moderation/utils.js +31 -0
- package/build/moderation/utils.js.map +1 -0
- package/build/preview/consts.d.ts +10 -0
- package/build/preview/consts.d.ts.map +1 -0
- package/build/preview/consts.js +11 -0
- package/build/preview/consts.js.map +1 -0
- package/build/preview/index.d.ts +3 -0
- package/build/preview/index.d.ts.map +1 -0
- package/build/preview/index.js +2 -0
- package/build/preview/index.js.map +1 -0
- package/build/preview/types.d.ts +60 -0
- package/build/preview/types.d.ts.map +1 -0
- package/build/preview/types.js +2 -0
- package/build/preview/types.js.map +1 -0
- package/build/scaffold/consts.d.ts +25 -0
- package/build/scaffold/consts.d.ts.map +1 -0
- package/build/scaffold/consts.js +26 -0
- package/build/scaffold/consts.js.map +1 -0
- package/build/scaffold/helpers.d.ts +35 -0
- package/build/scaffold/helpers.d.ts.map +1 -0
- package/build/scaffold/helpers.js +54 -0
- package/build/scaffold/helpers.js.map +1 -0
- package/build/scaffold/index.d.ts +5 -0
- package/build/scaffold/index.d.ts.map +1 -0
- package/build/scaffold/index.js +4 -0
- package/build/scaffold/index.js.map +1 -0
- package/build/scaffold/schemas.d.ts +5 -0
- package/build/scaffold/schemas.d.ts.map +1 -0
- package/build/scaffold/schemas.js +273 -0
- package/build/scaffold/schemas.js.map +1 -0
- package/build/scaffold/types.d.ts +144 -0
- package/build/scaffold/types.d.ts.map +1 -0
- package/build/scaffold/types.js +2 -0
- package/build/scaffold/types.js.map +1 -0
- package/build/skills/catalogue.d.ts +47 -0
- package/build/skills/catalogue.d.ts.map +1 -0
- package/build/skills/catalogue.js +1566 -0
- package/build/skills/catalogue.js.map +1 -0
- package/build/skills/consts.d.ts +104 -0
- package/build/skills/consts.d.ts.map +1 -0
- package/build/skills/consts.js +170 -0
- package/build/skills/consts.js.map +1 -0
- package/build/skills/index.d.ts +4 -0
- package/build/skills/index.d.ts.map +1 -0
- package/build/skills/index.js +4 -0
- package/build/skills/index.js.map +1 -0
- package/build/skills/roles.d.ts +52 -0
- package/build/skills/roles.d.ts.map +1 -0
- package/build/skills/roles.js +256 -0
- package/build/skills/roles.js.map +1 -0
- package/build/slot/consts.d.ts +305 -0
- package/build/slot/consts.d.ts.map +1 -0
- package/build/slot/consts.js +376 -0
- package/build/slot/consts.js.map +1 -0
- package/build/slot/helpers.d.ts +25 -0
- package/build/slot/helpers.d.ts.map +1 -0
- package/build/slot/helpers.js +27 -0
- package/build/slot/helpers.js.map +1 -0
- package/build/slot/index.d.ts +6 -0
- package/build/slot/index.d.ts.map +1 -0
- package/build/slot/index.js +5 -0
- package/build/slot/index.js.map +1 -0
- package/build/slot/layout.d.ts +72 -0
- package/build/slot/layout.d.ts.map +1 -0
- package/build/slot/layout.js +82 -0
- package/build/slot/layout.js.map +1 -0
- package/build/slot/schemas.d.ts +12 -0
- package/build/slot/schemas.d.ts.map +1 -0
- package/build/slot/schemas.js +43 -0
- package/build/slot/schemas.js.map +1 -0
- package/build/slot/types.d.ts +147 -0
- package/build/slot/types.d.ts.map +1 -0
- package/build/slot/types.js +2 -0
- package/build/slot/types.js.map +1 -0
- package/build/topology/card.d.ts +23 -0
- package/build/topology/card.d.ts.map +1 -0
- package/build/topology/card.js +95 -0
- package/build/topology/card.js.map +1 -0
- package/build/topology/consts.d.ts +32 -0
- package/build/topology/consts.d.ts.map +1 -0
- package/build/topology/consts.js +55 -0
- package/build/topology/consts.js.map +1 -0
- package/build/topology/helpers.d.ts +44 -0
- package/build/topology/helpers.d.ts.map +1 -0
- package/build/topology/helpers.js +112 -0
- package/build/topology/helpers.js.map +1 -0
- package/build/topology/index.d.ts +5 -0
- package/build/topology/index.d.ts.map +1 -0
- package/build/topology/index.js +4 -0
- package/build/topology/index.js.map +1 -0
- package/build/topology/types.d.ts +83 -0
- package/build/topology/types.d.ts.map +1 -0
- package/build/topology/types.js +2 -0
- package/build/topology/types.js.map +1 -0
- package/build/types.d.ts +88 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/build/ux/consts.d.ts +5 -0
- package/build/ux/consts.d.ts.map +1 -0
- package/build/ux/consts.js +6 -0
- package/build/ux/consts.js.map +1 -0
- package/build/ux/index.d.ts +4 -0
- package/build/ux/index.d.ts.map +1 -0
- package/build/ux/index.js +3 -0
- package/build/ux/index.js.map +1 -0
- package/build/ux/schemas.d.ts +8 -0
- package/build/ux/schemas.d.ts.map +1 -0
- package/build/ux/schemas.js +91 -0
- package/build/ux/schemas.js.map +1 -0
- package/build/ux/types.d.ts +21 -0
- package/build/ux/types.d.ts.map +1 -0
- package/build/ux/types.js +2 -0
- package/build/ux/types.js.map +1 -0
- package/package.json +71 -0
- package/src/agent/index.ts +4 -0
- package/src/agent/memory.ts +16 -0
- package/src/agent/spectator/consts.ts +10 -0
- package/src/agent/spectator/index.ts +3 -0
- package/src/agent/spectator/types.ts +14 -0
- package/src/agent/types.ts +10 -0
- package/src/areas/consts.ts +112 -0
- package/src/areas/index.ts +3 -0
- package/src/areas/types.ts +29 -0
- package/src/ba/consts.ts +40 -0
- package/src/ba/helpers.ts +93 -0
- package/src/ba/index.ts +5 -0
- package/src/ba/schemas.ts +196 -0
- package/src/ba/types.ts +125 -0
- package/src/blueprint/case.ts +272 -0
- package/src/blueprint/consts.ts +11 -0
- package/src/blueprint/index.ts +6 -0
- package/src/blueprint/resolve.ts +133 -0
- package/src/blueprint/schemas.ts +44 -0
- package/src/blueprint/types.ts +204 -0
- package/src/branding.ts +34 -0
- package/src/connect/consts.ts +441 -0
- package/src/connect/entrypoints.ts +291 -0
- package/src/connect/errors.ts +91 -0
- package/src/connect/index.ts +7 -0
- package/src/connect/ops.ts +208 -0
- package/src/connect/references.ts +89 -0
- package/src/connect/schemas.ts +384 -0
- package/src/connect/types.ts +456 -0
- package/src/consts.ts +34 -0
- package/src/convert/consts.ts +672 -0
- package/src/convert/helpers.ts +340 -0
- package/src/convert/index.ts +10 -0
- package/src/convert/schemas.ts +663 -0
- package/src/convert/types.ts +741 -0
- package/src/design/consts.ts +26 -0
- package/src/design/helpers.ts +255 -0
- package/src/design/index.ts +5 -0
- package/src/design/runtime.ts +142 -0
- package/src/design/schemas.ts +384 -0
- package/src/design/types.ts +191 -0
- package/src/dev/consts.ts +35 -0
- package/src/dev/index.ts +4 -0
- package/src/dev/schemas.ts +124 -0
- package/src/dev/types.ts +47 -0
- package/src/execution/consts.ts +37 -0
- package/src/execution/index.ts +3 -0
- package/src/execution/types.ts +55 -0
- package/src/index.ts +22 -0
- package/src/integrity/consts.ts +477 -0
- package/src/integrity/index.ts +3 -0
- package/src/integrity/types.ts +37 -0
- package/src/integrity/verify.ts +221 -0
- package/src/metadata/consts.ts +118 -0
- package/src/metadata/index.ts +3 -0
- package/src/metadata/types.ts +310 -0
- package/src/moderation/consts.ts +59 -0
- package/src/moderation/index.ts +4 -0
- package/src/moderation/schemas.ts +28 -0
- package/src/moderation/types.ts +68 -0
- package/src/moderation/utils.ts +35 -0
- package/src/preview/consts.ts +9 -0
- package/src/preview/index.ts +3 -0
- package/src/preview/types.ts +79 -0
- package/src/scaffold/consts.ts +26 -0
- package/src/scaffold/helpers.ts +84 -0
- package/src/scaffold/index.ts +4 -0
- package/src/scaffold/schemas.ts +283 -0
- package/src/scaffold/types.ts +118 -0
- package/src/skills/catalogue.ts +1617 -0
- package/src/skills/consts.ts +183 -0
- package/src/skills/index.ts +4 -0
- package/src/skills/roles.ts +299 -0
- package/src/slot/consts.ts +393 -0
- package/src/slot/helpers.ts +34 -0
- package/src/slot/index.ts +5 -0
- package/src/slot/layout.ts +141 -0
- package/src/slot/schemas.ts +46 -0
- package/src/slot/types.ts +164 -0
- package/src/topology/card.ts +106 -0
- package/src/topology/consts.ts +59 -0
- package/src/topology/helpers.ts +138 -0
- package/src/topology/index.ts +5 -0
- package/src/topology/types.ts +86 -0
- package/src/types.ts +104 -0
- package/src/ux/consts.ts +5 -0
- package/src/ux/index.ts +4 -0
- package/src/ux/schemas.ts +97 -0
- package/src/ux/types.ts +25 -0
- package/tests/connect-convert.spec.ts +161 -0
- package/tests/convert.spec.ts +318 -0
- package/tests/design.spec.ts +136 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { SubProject } from '../slot/consts.js'
|
|
2
|
+
import { ViableSkill } from '../skills/consts.js'
|
|
3
|
+
import { ViablePersona } from '../skills/roles.js'
|
|
4
|
+
import { aiLibraryList, gameLibraryList } from '../skills/catalogue.js'
|
|
5
|
+
import type { BlueprintPatch } from './types.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* WHICH KIND of product is being built on a blueprint.
|
|
9
|
+
*
|
|
10
|
+
* A blueprint says what the STACK is — the language, the framework, the topology, the seeds. A
|
|
11
|
+
* case says what is being built ON it, and that is a different question with different consumers:
|
|
12
|
+
* the analyst framing the brief, the architect deciding whether a story needs a queue, the coder
|
|
13
|
+
* choosing which packages it may import.
|
|
14
|
+
*
|
|
15
|
+
* Deliberately NOT a second blueprint. Everything a case has to say is already a blueprint field,
|
|
16
|
+
* so a case is a PATCH and the resolution order stays base → case → per-run overrides. That is
|
|
17
|
+
* also why adding one is a data change: nothing reads `BlueprintCase` except the table below and
|
|
18
|
+
* the prompt that classifies a project into it.
|
|
19
|
+
*/
|
|
20
|
+
export enum BlueprintCase {
|
|
21
|
+
/** A web application whose every feature fits inside a request. No queue, no worker, no agents. */
|
|
22
|
+
Web = 'web',
|
|
23
|
+
/** A web application with work that genuinely belongs off the request path. */
|
|
24
|
+
Scalable = 'scalable',
|
|
25
|
+
/** The product's value comes from ordered, deterministic model-driven steps. */
|
|
26
|
+
AiPipeline = 'ai-pipeline',
|
|
27
|
+
/** The product's value comes from an agent that decides its own path through tools. */
|
|
28
|
+
AiAgent = 'ai-agent',
|
|
29
|
+
/** A browser game: a three.js scene with an ordinary React interface over it. */
|
|
30
|
+
Game = 'game',
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* How a game is played, which decides who owns its state.
|
|
35
|
+
*
|
|
36
|
+
* Recorded beside the case rather than folded into it, because it changes nothing about the
|
|
37
|
+
* dependencies and everything about where the logic goes. `OnlineTurn` is the default for
|
|
38
|
+
* anything multiplayer unless the brief plainly asks for live play — it is the shape that
|
|
39
|
+
* actually builds, and it needs no socket, no tick loop and no reconciliation.
|
|
40
|
+
*/
|
|
41
|
+
export enum GameKind {
|
|
42
|
+
Casual = 'casual',
|
|
43
|
+
OnlineTurn = 'online-turn',
|
|
44
|
+
OnlineLive = 'online-live',
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface BlueprintCaseDefinition {
|
|
48
|
+
id: BlueprintCase
|
|
49
|
+
title: string
|
|
50
|
+
/**
|
|
51
|
+
* What this case is FOR, as the classifier prompt reads it.
|
|
52
|
+
*
|
|
53
|
+
* A pure constant, like every skill body: it lands in a cached prompt region, and one
|
|
54
|
+
* interpolated byte invalidates the prefix for every project classified after it.
|
|
55
|
+
*/
|
|
56
|
+
when: string
|
|
57
|
+
/** Applied between the base blueprint and the run's own overrides. A case is nothing else. */
|
|
58
|
+
patch: BlueprintPatch
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** What every AI case installs. The langchain peers are declared here, at ONE range. */
|
|
62
|
+
const AI_DEPS = {
|
|
63
|
+
[SubProject.Backend]: {
|
|
64
|
+
'@owlmeans/llm': '^0.1.18-rc.13',
|
|
65
|
+
'@owlmeans/agent': '^0.1.18-rc.16',
|
|
66
|
+
'@langchain/core': '^1.2.9',
|
|
67
|
+
'@langchain/anthropic': '^1.5.8',
|
|
68
|
+
'@langchain/openai': '^1.5.10',
|
|
69
|
+
'@langchain/langgraph': '^1.4.13',
|
|
70
|
+
'@langchain/langgraph-checkpoint': '^1.1.5',
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** The library allow-list a backend persona gets once the AI packages are installed. */
|
|
75
|
+
const AI_LIBRARIES = {
|
|
76
|
+
[SubProject.Backend]: aiLibraryList,
|
|
77
|
+
[SubProject.Api]: aiLibraryList,
|
|
78
|
+
[SubProject.Worker]: aiLibraryList,
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Skills every AI case adds on top of the blueprint's own. */
|
|
82
|
+
const AI_SKILLS = [
|
|
83
|
+
ViableSkill.AgenticChoice,
|
|
84
|
+
ViableSkill.TargetLlm,
|
|
85
|
+
ViableSkill.LibrariesAi,
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* What the analysis stage is told about a product whose value is a model.
|
|
90
|
+
*
|
|
91
|
+
* The pairing rule is the load-bearing one: an agent holds no permissions and owns no screen, so
|
|
92
|
+
* a story that is the AGENT's work is invisible unless a human story starts it and watches it.
|
|
93
|
+
*/
|
|
94
|
+
/**
|
|
95
|
+
* What the API side is told once a project may have a queue.
|
|
96
|
+
*
|
|
97
|
+
* The endpoint that starts slow work is the PRODUCER, and it is generated by a persona that
|
|
98
|
+
* otherwise has no reason to know a broker exists. Its job alias is declared before it runs
|
|
99
|
+
* (`runtime-declare`), so by the time this coder writes the handler there is something to enqueue
|
|
100
|
+
* onto — and this is what tells it to, instead of doing the work inline behind a request the user
|
|
101
|
+
* is waiting on.
|
|
102
|
+
*/
|
|
103
|
+
const PRODUCER_PERSONA_SKILLS = {
|
|
104
|
+
[ViablePersona.ApiArchitect]: [ViableSkill.QueueDiscipline, ViableSkill.WorkerJobs],
|
|
105
|
+
[ViablePersona.ApiCoder]: [ViableSkill.WorkerJobs],
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const AI_PERSONA_SKILLS = {
|
|
109
|
+
...PRODUCER_PERSONA_SKILLS,
|
|
110
|
+
[ViablePersona.BusinessAnalyst]: [ViableSkill.AgenticChoice],
|
|
111
|
+
[ViablePersona.UxDesigner]: [ViableSkill.AgenticChoice],
|
|
112
|
+
[ViablePersona.RuntimeArchitect]: [ViableSkill.AgenticChoice, ViableSkill.TargetLlm],
|
|
113
|
+
[ViablePersona.WorkerCoder]: [
|
|
114
|
+
ViableSkill.AgenticChoice, ViableSkill.TargetLlm, ViableSkill.LibrariesAi,
|
|
115
|
+
],
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const GAME_PERSONA_SKILLS = {
|
|
119
|
+
[ViablePersona.BusinessAnalyst]: [ViableSkill.GameDesign],
|
|
120
|
+
[ViablePersona.UxDesigner]: [ViableSkill.GameDesign, ViableSkill.GameUi],
|
|
121
|
+
[ViablePersona.VisualDesigner]: [ViableSkill.GameUi],
|
|
122
|
+
[ViablePersona.ComponentArchitect]: [ViableSkill.GameScene, ViableSkill.GameUi],
|
|
123
|
+
[ViablePersona.LayoutArchitect]: [ViableSkill.GameScene, ViableSkill.GameUi],
|
|
124
|
+
[ViablePersona.UiViewCoder]: [
|
|
125
|
+
ViableSkill.GameScene, ViableSkill.GameUi, ViableSkill.LibrariesGame,
|
|
126
|
+
],
|
|
127
|
+
[ViablePersona.RuntimeArchitect]: [ViableSkill.GameNetworking],
|
|
128
|
+
[ViablePersona.WorkerCoder]: [ViableSkill.GameNetworking],
|
|
129
|
+
[ViablePersona.ApiArchitect]: [ViableSkill.GameNetworking],
|
|
130
|
+
[ViablePersona.ApiCoder]: [ViableSkill.GameNetworking],
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* The cases the platform ships.
|
|
135
|
+
*
|
|
136
|
+
* Read as a table: the left column is what a prompt has to look like, the right column is what
|
|
137
|
+
* that costs the generated application. Nothing here turns a capability on without also
|
|
138
|
+
* installing what makes it real — a blueprint that promises `agents` over a manifest with no
|
|
139
|
+
* `@owlmeans/agent` in it produces a story that reports success and a library that will not
|
|
140
|
+
* compile.
|
|
141
|
+
*/
|
|
142
|
+
export const BLUEPRINT_CASES: Record<BlueprintCase, BlueprintCaseDefinition> = {
|
|
143
|
+
[BlueprintCase.Web]: {
|
|
144
|
+
id: BlueprintCase.Web,
|
|
145
|
+
title: 'Web application',
|
|
146
|
+
when: `
|
|
147
|
+
Everything the product does fits inside a request: forms, lists, records, search, reports a
|
|
148
|
+
person waits a second for. Nothing has to survive the tab closing, nothing calls a slow third
|
|
149
|
+
party, nothing walks an unbounded set, nothing is scheduled. Most products are this.
|
|
150
|
+
`.trim(),
|
|
151
|
+
patch: {
|
|
152
|
+
packages: {
|
|
153
|
+
capabilities: { postgres: true, kv: false, queue: false, worker: false, agents: false, validation: true },
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
[BlueprintCase.Scalable]: {
|
|
159
|
+
id: BlueprintCase.Scalable,
|
|
160
|
+
title: 'Web application with background work',
|
|
161
|
+
when: `
|
|
162
|
+
Like a web application, except that some named part of it genuinely cannot run inside a request:
|
|
163
|
+
it walks every row a user owns, talks to a slow or rate-limited third party, is scheduled or
|
|
164
|
+
repeated, must survive the tab closing, or must be retried without the user doing anything.
|
|
165
|
+
Choose this only when you can NAME that part; "it might get slow" is not it.
|
|
166
|
+
|
|
167
|
+
NOT this when the slow part is a MODEL. Background work whose content comes out of a language
|
|
168
|
+
model is one of the two AI kinds below, and choosing this one for it leaves the application unable
|
|
169
|
+
to call a model at all.
|
|
170
|
+
`.trim(),
|
|
171
|
+
patch: {
|
|
172
|
+
packages: {
|
|
173
|
+
capabilities: { postgres: true, kv: true, queue: true, worker: true, agents: false, validation: true },
|
|
174
|
+
personaSkills: PRODUCER_PERSONA_SKILLS,
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
[BlueprintCase.AiPipeline]: {
|
|
180
|
+
id: BlueprintCase.AiPipeline,
|
|
181
|
+
title: 'AI pipeline',
|
|
182
|
+
when: `
|
|
183
|
+
The product's value comes from a language model, and the work it does is a KNOWN sequence:
|
|
184
|
+
transcribe then summarise then file; extract then validate then store; draft then check then send.
|
|
185
|
+
You can name the steps before it runs. The application decides the order; the model performs each
|
|
186
|
+
step.
|
|
187
|
+
|
|
188
|
+
Any product whose OUTPUT is written by a model is this kind or the one below — never a plain web
|
|
189
|
+
application, and never merely a scalable one.
|
|
190
|
+
`.trim(),
|
|
191
|
+
patch: {
|
|
192
|
+
packages: {
|
|
193
|
+
capabilities: { postgres: true, kv: true, queue: true, worker: true, agents: true, validation: true },
|
|
194
|
+
deps: AI_DEPS,
|
|
195
|
+
libraries: AI_LIBRARIES,
|
|
196
|
+
skills: AI_SKILLS,
|
|
197
|
+
personaSkills: AI_PERSONA_SKILLS,
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
[BlueprintCase.AiAgent]: {
|
|
203
|
+
id: BlueprintCase.AiAgent,
|
|
204
|
+
title: 'AI agent',
|
|
205
|
+
when: `
|
|
206
|
+
The product's value comes from a model that decides its own path: how many steps the work takes
|
|
207
|
+
cannot be predicted, and which tool to reach for next is a judgement rather than a rule anyone
|
|
208
|
+
could write down. Choose this over an AI pipeline only when the order genuinely cannot be fixed
|
|
209
|
+
in advance.
|
|
210
|
+
`.trim(),
|
|
211
|
+
patch: {
|
|
212
|
+
packages: {
|
|
213
|
+
capabilities: { postgres: true, kv: true, queue: true, worker: true, agents: true, validation: true },
|
|
214
|
+
deps: {
|
|
215
|
+
[SubProject.Backend]: {
|
|
216
|
+
...AI_DEPS[SubProject.Backend],
|
|
217
|
+
'@owlmeans/agent-skills': '^0.1.18-rc.12',
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
libraries: AI_LIBRARIES,
|
|
221
|
+
skills: [...AI_SKILLS, ViableSkill.TargetAgentTools],
|
|
222
|
+
personaSkills: {
|
|
223
|
+
...AI_PERSONA_SKILLS,
|
|
224
|
+
[ViablePersona.WorkerCoder]: [
|
|
225
|
+
...AI_PERSONA_SKILLS[ViablePersona.WorkerCoder], ViableSkill.TargetAgentTools,
|
|
226
|
+
],
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
|
|
232
|
+
[BlueprintCase.Game]: {
|
|
233
|
+
id: BlueprintCase.Game,
|
|
234
|
+
title: 'Browser game',
|
|
235
|
+
when: `
|
|
236
|
+
The person asked for a GAME, in those words or unmistakably — something played rather than used,
|
|
237
|
+
with a loop, a score or a win condition. Never infer this from "gamified", "playful", "fun" or a
|
|
238
|
+
leaderboard attached to an ordinary product. If the prompt does not plainly ask for a game, this
|
|
239
|
+
is not it.
|
|
240
|
+
`.trim(),
|
|
241
|
+
patch: {
|
|
242
|
+
packages: {
|
|
243
|
+
capabilities: { postgres: true, kv: true, queue: true, worker: true, agents: false, validation: true },
|
|
244
|
+
deps: {
|
|
245
|
+
[SubProject.Web]: { three: '^0.186.0', '@types/three': '^0.185.4' },
|
|
246
|
+
},
|
|
247
|
+
libraries: { [SubProject.Web]: gameLibraryList, 'ui-state': gameLibraryList },
|
|
248
|
+
skills: [ViableSkill.GameScene, ViableSkill.GameUi, ViableSkill.LibrariesGame],
|
|
249
|
+
personaSkills: { ...PRODUCER_PERSONA_SKILLS, ...GAME_PERSONA_SKILLS },
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* The case a reference names, or `undefined`.
|
|
257
|
+
*
|
|
258
|
+
* Total over anything: an unknown name, a name from a deploy this one does not have, and an
|
|
259
|
+
* absent one all read the same way — no patch, which is the base blueprint. That is the only
|
|
260
|
+
* answer that cannot take a capability away from a project that already has it.
|
|
261
|
+
*/
|
|
262
|
+
export const blueprintCaseOf = (name?: string): BlueprintCaseDefinition | undefined =>
|
|
263
|
+
name == null ? undefined : (BLUEPRINT_CASES as Record<string, BlueprintCaseDefinition>)[name]
|
|
264
|
+
|
|
265
|
+
/** Every case the platform ships, in the order a classifier should weigh them. */
|
|
266
|
+
export const BLUEPRINT_CASE_ORDER: BlueprintCase[] = [
|
|
267
|
+
BlueprintCase.Web,
|
|
268
|
+
BlueprintCase.Scalable,
|
|
269
|
+
BlueprintCase.AiPipeline,
|
|
270
|
+
BlueprintCase.AiAgent,
|
|
271
|
+
BlueprintCase.Game,
|
|
272
|
+
]
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The blueprint the platform ships and every project uses until something says otherwise.
|
|
3
|
+
*
|
|
4
|
+
* A string rather than an enum: a blueprint may be registered by a consumer, and an enum would
|
|
5
|
+
* make the platform's own list the closed set of everything that can exist — which is the shape
|
|
6
|
+
* this whole abstraction was introduced to remove.
|
|
7
|
+
*/
|
|
8
|
+
export const DEFAULT_BLUEPRINT_ID = 'owlmeans-fullstack-ts'
|
|
9
|
+
|
|
10
|
+
/** Recorded on a project so a later run knows which blueprint drew it. */
|
|
11
|
+
export const BLUEPRINT_META_KEY = 'blueprint'
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { ViablePersona } from '../skills/roles.js'
|
|
2
|
+
import type { ViableSkill } from '../skills/consts.js'
|
|
3
|
+
import { blueprintCaseOf } from './case.js'
|
|
4
|
+
import type { Blueprint, BlueprintPatch } from './types.js'
|
|
5
|
+
|
|
6
|
+
const isPlainObject = (value: unknown): value is Record<string, unknown> =>
|
|
7
|
+
value != null && typeof value === 'object' && !Array.isArray(value)
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Merge one layer's override over a resolved value.
|
|
11
|
+
*
|
|
12
|
+
* Objects merge key by key; ARRAYS REPLACE. That asymmetry is deliberate and is the difference
|
|
13
|
+
* between an override and an addition: a blueprint that narrows a library allow-list to three
|
|
14
|
+
* entries means those three, and a concatenating merge would hand the coder back the very imports
|
|
15
|
+
* the override existed to forbid. A layer that wants to add spreads the base itself.
|
|
16
|
+
*/
|
|
17
|
+
export const mergeBlueprintValue = <T>(base: T, patch: unknown): T => {
|
|
18
|
+
if (patch === undefined) return base
|
|
19
|
+
if (!isPlainObject(base) || !isPlainObject(patch)) return patch as T
|
|
20
|
+
|
|
21
|
+
const out: Record<string, unknown> = { ...base }
|
|
22
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
23
|
+
if (value === undefined) continue
|
|
24
|
+
out[key] = mergeBlueprintValue(out[key], value)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return out as T
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Apply an override patch to a blueprint, layer by layer.
|
|
32
|
+
*
|
|
33
|
+
* Frozen on the way out — shallowly at each layer, which is enough to make the accidental
|
|
34
|
+
* `blueprint.packages.capabilities.worker = true` a visible failure rather than a change every
|
|
35
|
+
* later helper silently inherits.
|
|
36
|
+
*/
|
|
37
|
+
export const applyBlueprintPatch = (base: Blueprint, patch?: BlueprintPatch): Blueprint => {
|
|
38
|
+
if (patch == null) return base
|
|
39
|
+
|
|
40
|
+
const merged = mergeBlueprintValue(
|
|
41
|
+
base as unknown as Record<string, unknown>, patch
|
|
42
|
+
) as unknown as Blueprint
|
|
43
|
+
|
|
44
|
+
return freezeBlueprint(merged)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const freezeBlueprint = (blueprint: Blueprint): Blueprint => Object.freeze({
|
|
48
|
+
...blueprint,
|
|
49
|
+
technology: Object.freeze({ ...blueprint.technology }),
|
|
50
|
+
stack: Object.freeze({ ...blueprint.stack }),
|
|
51
|
+
template: Object.freeze({ ...blueprint.template }),
|
|
52
|
+
createApp: Object.freeze({ ...blueprint.createApp }),
|
|
53
|
+
packages: Object.freeze({
|
|
54
|
+
...blueprint.packages,
|
|
55
|
+
capabilities: Object.freeze({ ...blueprint.packages.capabilities }),
|
|
56
|
+
}),
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
/** Every skill the blueprint asks for, stack first, deduped, order preserved. */
|
|
60
|
+
export const blueprintSkills = (blueprint: Blueprint): Blueprint['stack']['skills'] =>
|
|
61
|
+
[...new Set([...blueprint.stack.skills, ...blueprint.packages.skills])]
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
const union = <T>(base: readonly T[] = [], extra: readonly T[] = []): T[] =>
|
|
65
|
+
[...new Set([...base, ...extra])]
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Apply a CASE to a blueprint — which kind of product is being built on this stack.
|
|
69
|
+
*
|
|
70
|
+
* A case is an ordinary {@link BlueprintPatch} and follows every rule an override does, with two
|
|
71
|
+
* deliberate exceptions: `skills` and `personaSkills` are UNIONED with the base rather than
|
|
72
|
+
* replacing it.
|
|
73
|
+
*
|
|
74
|
+
* The asymmetry is the difference between the two things a patch can be. An override is written
|
|
75
|
+
* by somebody looking at the resolved value and narrowing it — "these three libraries and no
|
|
76
|
+
* others" — and a concatenating merge would hand back the very imports it existed to forbid. A
|
|
77
|
+
* case is written once, in a table, by somebody who cannot see the blueprint it will be applied
|
|
78
|
+
* to; it says what this KIND of product needs IN ADDITION, and replacing there would silently
|
|
79
|
+
* drop every rule the stack itself established. A case that genuinely needs to take a skill away
|
|
80
|
+
* does it by narrowing a capability, which is what stops the prompt being asked at all.
|
|
81
|
+
*
|
|
82
|
+
* Unknown, absent and unregistered case names all resolve to the blueprint unchanged. A project
|
|
83
|
+
* records the case it was drawn with, that record outlives the deploy that knew the name, and
|
|
84
|
+
* "built against the stack as it stands" is a far better answer than a project that cannot open.
|
|
85
|
+
*/
|
|
86
|
+
export const applyBlueprintCase = (base: Blueprint, name?: string): Blueprint => {
|
|
87
|
+
const cased = blueprintCaseOf(name)
|
|
88
|
+
if (cased == null) return base
|
|
89
|
+
|
|
90
|
+
const merged = applyBlueprintPatch(base, cased.patch)
|
|
91
|
+
const patch = cased.patch
|
|
92
|
+
|
|
93
|
+
const personaSkills = patch.packages?.personaSkills
|
|
94
|
+
const stackSkills = patch.stack?.skills as ViableSkill[] | undefined
|
|
95
|
+
const packageSkills = patch.packages?.skills as ViableSkill[] | undefined
|
|
96
|
+
|
|
97
|
+
return freezeBlueprint({
|
|
98
|
+
...merged,
|
|
99
|
+
stack: { ...merged.stack, skills: union(base.stack.skills, stackSkills) },
|
|
100
|
+
packages: {
|
|
101
|
+
...merged.packages,
|
|
102
|
+
skills: union(base.packages.skills, packageSkills),
|
|
103
|
+
...(personaSkills != null || base.packages.personaSkills != null
|
|
104
|
+
? {
|
|
105
|
+
personaSkills: mergePersonaSkills(base.packages.personaSkills, personaSkills),
|
|
106
|
+
}
|
|
107
|
+
: {}),
|
|
108
|
+
},
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const mergePersonaSkills = (
|
|
113
|
+
base?: Partial<Record<ViablePersona, ViableSkill[]>>,
|
|
114
|
+
extra?: Partial<Record<ViablePersona, ViableSkill[]>>,
|
|
115
|
+
): Partial<Record<ViablePersona, ViableSkill[]>> => {
|
|
116
|
+
const out: Partial<Record<ViablePersona, ViableSkill[]>> = { ...base }
|
|
117
|
+
for (const [persona, skills] of Object.entries(extra ?? {})) {
|
|
118
|
+
const key = persona as ViablePersona
|
|
119
|
+
out[key] = union(out[key], skills as ViableSkill[])
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return out
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* The skills ONE persona gets from the blueprint, beyond its own.
|
|
127
|
+
*
|
|
128
|
+
* Total, and empty for every persona a blueprint says nothing about — which is every one of them
|
|
129
|
+
* on the blueprint the platform ships. `withPersona` unions this into the policy it composes.
|
|
130
|
+
*/
|
|
131
|
+
export const personaSkillsOf = (
|
|
132
|
+
blueprint: Blueprint, persona: ViablePersona
|
|
133
|
+
): ViableSkill[] => blueprint.packages.personaSkills?.[persona] ?? []
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { BlueprintCase, GameKind } from './case.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* What kind of product a prompt describes.
|
|
5
|
+
*
|
|
6
|
+
* A schema rather than a free answer because the value is a KEY: it is written onto the project
|
|
7
|
+
* record, resolved into a blueprint patch on every run afterwards, and decides which dependencies
|
|
8
|
+
* the tree is staged with. A model that answered "an AI-powered agent app" in prose would leave
|
|
9
|
+
* the caller matching strings, and a miss there is silent — the project simply builds as the
|
|
10
|
+
* default and nobody can say why.
|
|
11
|
+
*/
|
|
12
|
+
export interface BlueprintCaseChoice {
|
|
13
|
+
case: BlueprintCase
|
|
14
|
+
/** Only meaningful for the game case; ignored everywhere else. */
|
|
15
|
+
gameKind?: GameKind
|
|
16
|
+
/** One sentence, from the prompt. Recorded so a later run can disagree with it. */
|
|
17
|
+
rationale: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const BlueprintCaseChoiceSchema = {
|
|
21
|
+
type: 'object',
|
|
22
|
+
title: 'BlueprintCaseChoice',
|
|
23
|
+
description: 'Which kind of application the described product is',
|
|
24
|
+
properties: {
|
|
25
|
+
case: {
|
|
26
|
+
type: 'string',
|
|
27
|
+
enum: Object.values(BlueprintCase),
|
|
28
|
+
description: 'The least capable kind that can deliver what was asked for.',
|
|
29
|
+
},
|
|
30
|
+
gameKind: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
enum: Object.values(GameKind),
|
|
33
|
+
description: 'Only when the case is `game`. `casual` for one player in one browser, '
|
|
34
|
+
+ '`online-turn` for players acting one after another, `online-live` only when the brief '
|
|
35
|
+
+ 'plainly asks for players acting at the same moment.',
|
|
36
|
+
},
|
|
37
|
+
rationale: {
|
|
38
|
+
type: 'string',
|
|
39
|
+
description: 'One sentence naming what in the prompt decided it.',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
required: ['case', 'rationale'],
|
|
43
|
+
additionalProperties: false,
|
|
44
|
+
} as const
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import type { SubProject } from '../slot/consts.js'
|
|
2
|
+
import type { ViableSkill } from '../skills/consts.js'
|
|
3
|
+
import type { ViablePersona } from '../skills/roles.js'
|
|
4
|
+
import type { TopologyDescriptor } from '../topology/types.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A BLUEPRINT is everything that decides what kind of project the pipeline is building — the
|
|
8
|
+
* language, the framework, the scaffolder, the seed files and the dependencies — as one named,
|
|
9
|
+
* layered value carried on an execution.
|
|
10
|
+
*
|
|
11
|
+
* Before it, each of those was a constant somewhere: one template directory, one hardwired set of
|
|
12
|
+
* five package names, one `VIABLE_SKILLS` catalogue, one `Libraries*` allow-list per area. Nothing
|
|
13
|
+
* was wrong with any of them individually; what was wrong is that they could not be ANSWERED — a
|
|
14
|
+
* helper could not ask "which stack am I generating for", because there was only ever one.
|
|
15
|
+
*
|
|
16
|
+
* Deliberately NOT called a preset: `presets/` in the agent library already means the LLM
|
|
17
|
+
* model/provider configurations, and the two are asked at different moments about different
|
|
18
|
+
* things.
|
|
19
|
+
*/
|
|
20
|
+
export interface Blueprint {
|
|
21
|
+
id: string
|
|
22
|
+
title: string
|
|
23
|
+
technology: TechnologyLayer
|
|
24
|
+
stack: StackLayer
|
|
25
|
+
template: TemplateLayer
|
|
26
|
+
createApp: CreateAppLayer
|
|
27
|
+
packages: PackagesLayer
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The layers, lowest first. A higher layer's value replaces the same key from a lower one.
|
|
32
|
+
*
|
|
33
|
+
* The ordering is the point: `technology` overrides everything, because a change of language
|
|
34
|
+
* invalidates every template, prompt and package below it. Nothing today has more than one
|
|
35
|
+
* technology — the ladder exists so that adding one is a data change.
|
|
36
|
+
*/
|
|
37
|
+
export enum BlueprintLayer {
|
|
38
|
+
Technology = 'technology',
|
|
39
|
+
Stack = 'stack',
|
|
40
|
+
Template = 'template',
|
|
41
|
+
CreateApp = 'create-app',
|
|
42
|
+
Packages = 'packages',
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const BLUEPRINT_LAYER_ORDER: BlueprintLayer[] = [
|
|
46
|
+
BlueprintLayer.Technology,
|
|
47
|
+
BlueprintLayer.Stack,
|
|
48
|
+
BlueprintLayer.Template,
|
|
49
|
+
BlueprintLayer.CreateApp,
|
|
50
|
+
BlueprintLayer.Packages,
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
/** Language and toolchain. Overrides everything below it. */
|
|
54
|
+
export interface TechnologyLayer {
|
|
55
|
+
id: string
|
|
56
|
+
language: string
|
|
57
|
+
runtime: string
|
|
58
|
+
/** Extensions a source file may carry, most specific first. Used by the location ladder. */
|
|
59
|
+
extensions: string[]
|
|
60
|
+
/** What a package's manifest must declare, per package kind. */
|
|
61
|
+
buildScripts: Record<string, string>
|
|
62
|
+
packageManager: string
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Framework family — what the generated code is written AGAINST. */
|
|
66
|
+
export interface StackLayer {
|
|
67
|
+
id: string
|
|
68
|
+
framework: string
|
|
69
|
+
/** The arrangement a new project of this stack is created with. */
|
|
70
|
+
topology: TopologyDescriptor
|
|
71
|
+
/** The skills every prompt of this stack carries, before any per-helper persona. */
|
|
72
|
+
skills: ViableSkill[]
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* The seed: what is laid over the scaffolder's output, and what is then patched.
|
|
77
|
+
*
|
|
78
|
+
* `overlay` is a REFERENCE, never a path — the host resolves it, because the same blueprint is
|
|
79
|
+
* read in an agent container, in a test and (eventually) from a published package, and a path
|
|
80
|
+
* baked in here would be right in exactly one of them.
|
|
81
|
+
*/
|
|
82
|
+
export interface TemplateLayer {
|
|
83
|
+
id: string
|
|
84
|
+
overlay: string
|
|
85
|
+
/**
|
|
86
|
+
* Paths the scaffolder writes that this overlay SUPERSEDES — deleted after the overlay lands.
|
|
87
|
+
*
|
|
88
|
+
* Not tidiness. The two seeds are both complete, opinionated projects, and where they disagree
|
|
89
|
+
* the loser's file does not become inert: it stays in the workspace, is compiled by `tsc`, and
|
|
90
|
+
* imports packages the winner's manifest never declared. The scaffolder's Vite entry, its
|
|
91
|
+
* `vite.config.ts` and its shell layout each name a dependency or an export the overlay's own
|
|
92
|
+
* wiring does not have, and every one of them fails the type check of a project that is
|
|
93
|
+
* otherwise perfectly correct.
|
|
94
|
+
*
|
|
95
|
+
* A directory takes its whole subtree. A path that is not there is a no-op, because the two
|
|
96
|
+
* seeds move independently and an overlay must not break when the scaffolder stops shipping
|
|
97
|
+
* something it used to supersede.
|
|
98
|
+
*/
|
|
99
|
+
remove?: string[]
|
|
100
|
+
/** Deterministic patches applied after the overlay, in order. */
|
|
101
|
+
patches: BlueprintPatchSpec[]
|
|
102
|
+
/** Overlay subtrees that belong to one role only — the per-package half of a template. */
|
|
103
|
+
perRole?: Partial<Record<SubProject, string>>
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface BlueprintPatchSpec {
|
|
107
|
+
/** Target path, relative to the project root. */
|
|
108
|
+
path: string
|
|
109
|
+
kind: BlueprintPatchKind
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export enum BlueprintPatchKind {
|
|
113
|
+
/** Deep-merge a JSON document — the manifests, the tsconfigs. */
|
|
114
|
+
JsonMerge = 'json-merge',
|
|
115
|
+
/** Rewrite the `<head>` of an HTML document from the project's identity. */
|
|
116
|
+
HtmlHead = 'html-head',
|
|
117
|
+
/** Write a document composed from the project's identity. */
|
|
118
|
+
Compose = 'compose',
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Which scaffolder runs first, and how. */
|
|
122
|
+
export interface CreateAppLayer {
|
|
123
|
+
id: string
|
|
124
|
+
/** The npm name, for the record. The template itself is always resolved as DATA. */
|
|
125
|
+
package: string
|
|
126
|
+
/** Scaffold the shell without the example/demo code. Always true for a generated target. */
|
|
127
|
+
bare: boolean
|
|
128
|
+
/** A reference the host resolves to the scaffolder's template directory. */
|
|
129
|
+
template: string
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* The dependency choices — and therefore the prompts and skills those choices imply.
|
|
134
|
+
*
|
|
135
|
+
* This is the layer that makes "postgres or mongo" a blueprint question rather than a hardwired
|
|
136
|
+
* catalogue. `capabilities` is what a design stage gates on; `libraries` is what a coder prompt is
|
|
137
|
+
* allowed to import; `skills` is what gets loaded on top of the stack's.
|
|
138
|
+
*/
|
|
139
|
+
export interface PackagesLayer {
|
|
140
|
+
id: string
|
|
141
|
+
capabilities: BlueprintCapabilities
|
|
142
|
+
/** Per-topic allow-lists, rendered verbatim into coder prompts. */
|
|
143
|
+
libraries: Record<string, string[]>
|
|
144
|
+
skills: ViableSkill[]
|
|
145
|
+
/**
|
|
146
|
+
* Skills added to ONE persona, rather than to every prompt of the blueprint.
|
|
147
|
+
*
|
|
148
|
+
* The additive twin of {@link skillsForBlueprint}, which subtracts. `skills` above is what is
|
|
149
|
+
* true of the whole stack; this is what is true of one performer — the analyst who has to know
|
|
150
|
+
* that a game brief is a core loop rather than a numbered flow, the architect who has to know
|
|
151
|
+
* when a tool loop is warranted. Without it a case could only change what a CODER is told, and
|
|
152
|
+
* a case changes the product analysis first.
|
|
153
|
+
*/
|
|
154
|
+
personaSkills?: Partial<Record<ViablePersona, ViableSkill[]>>
|
|
155
|
+
/** Extra dependencies a role's manifest carries, beyond what the overlay ships. */
|
|
156
|
+
deps?: Partial<Record<SubProject, Record<string, string>>>
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* What a target of this blueprint is ABLE to do — read by the design stage before it decides
|
|
161
|
+
* whether a story needs any of it.
|
|
162
|
+
*
|
|
163
|
+
* A capability being on never means a story uses it. It means the question may be asked.
|
|
164
|
+
*/
|
|
165
|
+
export interface BlueprintCapabilities {
|
|
166
|
+
/** Relational persistence — the default resource kind. */
|
|
167
|
+
postgres: boolean
|
|
168
|
+
/** A pod-local key/value store: TTL, locks, counters, fan-out. */
|
|
169
|
+
kv: boolean
|
|
170
|
+
/** A broker, and therefore the possibility of work off the request path. */
|
|
171
|
+
queue: boolean
|
|
172
|
+
/** A separate process consuming that broker. */
|
|
173
|
+
worker: boolean
|
|
174
|
+
/** LLM agents and pipelines generated INTO the target. */
|
|
175
|
+
agents: boolean
|
|
176
|
+
/** Request-body validation from generated AJV schemas. */
|
|
177
|
+
validation: boolean
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** A partial override of a blueprint, deep-merged over the resolved value. */
|
|
181
|
+
export type BlueprintPatch = {
|
|
182
|
+
[K in keyof Blueprint]?: Blueprint[K] extends string ? Blueprint[K] : Partial<Blueprint[K]>
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* What an EXECUTION carries — an id and an override patch, never the resolved blueprint.
|
|
187
|
+
*
|
|
188
|
+
* An execution state is serialized into a pipeline run row at every step boundary, and that row
|
|
189
|
+
* holds keys, never artifacts. A resolved blueprint is an artifact: it embeds a whole topology, a
|
|
190
|
+
* patch list and two skill sets, and it is reconstructible from these two fields at any time.
|
|
191
|
+
*/
|
|
192
|
+
export interface BlueprintRef {
|
|
193
|
+
id: string
|
|
194
|
+
/**
|
|
195
|
+
* WHICH KIND of product is being built on that blueprint — the case.
|
|
196
|
+
*
|
|
197
|
+
* A key like the id beside it, resolved into a patch on demand, so a run row still holds no
|
|
198
|
+
* artifact and a case the platform has since corrected reaches a resumed run. Absent applies no
|
|
199
|
+
* patch at all: every project created before cases existed keeps exactly the blueprint it had,
|
|
200
|
+
* which is the only reading that cannot silently take a capability away from a live project.
|
|
201
|
+
*/
|
|
202
|
+
case?: string
|
|
203
|
+
overrides?: BlueprintPatch
|
|
204
|
+
}
|