@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,221 @@
|
|
|
1
|
+
import {
|
|
2
|
+
detectTargetLayout, IntegrityRule, TARGET_FORBIDDEN_SCRIPTS, TARGET_SLUG_PATTERN,
|
|
3
|
+
targetManifest, targetPackageName, targetRequiredDeps
|
|
4
|
+
} from './consts.js'
|
|
5
|
+
import type { IntegrityViolation, TargetFileMap, TargetIntegrityReport } from './types.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Decide whether a tree is the generated application, from its files alone.
|
|
9
|
+
*
|
|
10
|
+
* Pure and IO-free on purpose. The publisher reads the sandbox and calls this; a test reads
|
|
11
|
+
* the template and calls this; both then agree by construction. It is also why the check is
|
|
12
|
+
* cheap enough to sit in front of every spawn rather than only at the moments someone
|
|
13
|
+
* remembered to guard.
|
|
14
|
+
*
|
|
15
|
+
* The tree picks the manifest it is verified against. A slot holds the layout it was
|
|
16
|
+
* initialized with for the life of the project and nothing migrates it, so asserting the
|
|
17
|
+
* current layout unconditionally does not make the check stricter — it aims it at a tree that
|
|
18
|
+
* was never there, and every legacy slot answers with one `missing` violation per file it was
|
|
19
|
+
* never supposed to have. That refuses the application the platform itself generated.
|
|
20
|
+
*
|
|
21
|
+
* Every rule collects rather than short-circuits: a tree that fails is usually a person's
|
|
22
|
+
* repository, and telling them one thing at a time turns a fix into a dozen round trips
|
|
23
|
+
* through a pull that reverts itself each time.
|
|
24
|
+
*/
|
|
25
|
+
export const verifyTargetShape = (files: TargetFileMap): TargetIntegrityReport => {
|
|
26
|
+
const violations: IntegrityViolation[] = []
|
|
27
|
+
const layout = detectTargetLayout(files)
|
|
28
|
+
const manifest = targetManifest(layout)
|
|
29
|
+
|
|
30
|
+
// Only this layout's files. The caller reads the union of every layout's list so that the
|
|
31
|
+
// probes are in hand before the layout is known — reporting the other layout's paths as
|
|
32
|
+
// missing would refuse both trees at once.
|
|
33
|
+
for (const path of manifest.files) {
|
|
34
|
+
if (files[path] == null) {
|
|
35
|
+
violations.push({
|
|
36
|
+
path, rule: IntegrityRule.Missing,
|
|
37
|
+
detail: `${path} is missing — a Viable project always has it.`
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// The slug is read once, from the root, and every package name is checked against it. A
|
|
43
|
+
// project the user renamed is still the project; a package that does not carry the root's
|
|
44
|
+
// name is a different tree wearing the workspace layout.
|
|
45
|
+
const slug = checkRoot()
|
|
46
|
+
checkInstallConfig()
|
|
47
|
+
for (const pkg of manifest.packages) {
|
|
48
|
+
checkPackage(pkg, slug)
|
|
49
|
+
}
|
|
50
|
+
checkMarkers()
|
|
51
|
+
|
|
52
|
+
return { ok: violations.length === 0, violations, layout }
|
|
53
|
+
|
|
54
|
+
function checkRoot(): string | null {
|
|
55
|
+
const found = readJson('package.json')
|
|
56
|
+
if (found == null) return null
|
|
57
|
+
|
|
58
|
+
const name = typeof found.name === 'string' ? found.name : ''
|
|
59
|
+
if (!TARGET_SLUG_PATTERN.test(name)) {
|
|
60
|
+
violations.push({
|
|
61
|
+
path: 'package.json', rule: IntegrityRule.PackageName,
|
|
62
|
+
detail: `The root package name "${String(found.name)}" is not a project slug`
|
|
63
|
+
+ ` — lowercase letters, digits and inner hyphens, up to 32 characters.`
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
if (found.type !== 'module') {
|
|
67
|
+
violations.push({
|
|
68
|
+
path: 'package.json', rule: IntegrityRule.ModuleType,
|
|
69
|
+
detail: 'The root package must declare "type": "module".'
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// The workspace list is what makes the packages resolve to each other. Both spellings are
|
|
74
|
+
// the same tree: the glob `create-app` emits, or the entries written out.
|
|
75
|
+
const declared = Array.isArray(found.workspaces) ? found.workspaces as string[] : []
|
|
76
|
+
const isGlob = declared.length === 1 && declared[0] === manifest.workspaceGlob
|
|
77
|
+
const isExplicit = declared.length === manifest.workspaceEntries.length
|
|
78
|
+
&& manifest.workspaceEntries.every(entry => declared.includes(entry))
|
|
79
|
+
if (!isGlob && !isExplicit) {
|
|
80
|
+
violations.push({
|
|
81
|
+
path: 'package.json', rule: IntegrityRule.Workspaces,
|
|
82
|
+
detail: `The root package must declare the workspaces as ["${manifest.workspaceGlob}"]`
|
|
83
|
+
+ ` or as exactly ${manifest.workspaceEntries.join(', ')}.`
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
checkScripts('package.json', found)
|
|
88
|
+
|
|
89
|
+
return TARGET_SLUG_PATTERN.test(name) ? name : null
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* `bunfig.toml` decides where `bun install` fetches from and how it links.
|
|
94
|
+
*
|
|
95
|
+
* A registry line pointed elsewhere makes every dependency in the tree arbitrary code
|
|
96
|
+
* regardless of how well-formed the manifests are, so it is checked as a shape rather than
|
|
97
|
+
* a marker: nothing but the hoisted-linker install block belongs in it.
|
|
98
|
+
*/
|
|
99
|
+
function checkInstallConfig(): void {
|
|
100
|
+
const content = files['bunfig.toml']
|
|
101
|
+
if (content == null) return
|
|
102
|
+
|
|
103
|
+
const offending = content.split('\n')
|
|
104
|
+
.map(line => line.trim())
|
|
105
|
+
.filter(line => line.length > 0 && !line.startsWith('#'))
|
|
106
|
+
.filter(line => !/^\[install\]$/.test(line) && !/^linker\s*=/.test(line))
|
|
107
|
+
|
|
108
|
+
if (offending.length > 0) {
|
|
109
|
+
violations.push({
|
|
110
|
+
path: 'bunfig.toml', rule: IntegrityRule.InstallConfig,
|
|
111
|
+
detail: 'bunfig.toml may only declare the hoisted install linker.'
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function checkPackage(pkg: string, slug: string | null): void {
|
|
117
|
+
const path = `${manifest.dir}/${pkg}/package.json`
|
|
118
|
+
const found = readJson(path)
|
|
119
|
+
if (found == null) return
|
|
120
|
+
|
|
121
|
+
// With no readable slug the name and the workspace dependencies have nothing to be checked
|
|
122
|
+
// against; the root violation already says why, and repeating it per package is noise.
|
|
123
|
+
if (slug != null) {
|
|
124
|
+
const expected = targetPackageName(slug, pkg)
|
|
125
|
+
if (found.name !== expected) {
|
|
126
|
+
violations.push({
|
|
127
|
+
path, rule: IntegrityRule.PackageName,
|
|
128
|
+
detail: `Package must be named "${expected}", not "${String(found.name)}".`
|
|
129
|
+
})
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (found.type !== 'module') {
|
|
133
|
+
violations.push({
|
|
134
|
+
path, rule: IntegrityRule.ModuleType,
|
|
135
|
+
detail: `Package "${pkg}" must declare "type": "module".`
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const scripts = asRecord(found.scripts)
|
|
140
|
+
if (scripts.build !== manifest.buildScripts[pkg]) {
|
|
141
|
+
// The one the platform actually spawns.
|
|
142
|
+
violations.push({
|
|
143
|
+
path, rule: IntegrityRule.BuildScript,
|
|
144
|
+
detail: `The build script of "${pkg}" must be exactly \`${manifest.buildScripts[pkg]}\`.`
|
|
145
|
+
})
|
|
146
|
+
}
|
|
147
|
+
checkScripts(path, found)
|
|
148
|
+
|
|
149
|
+
if (slug == null) return
|
|
150
|
+
|
|
151
|
+
const deps = { ...asRecord(found.dependencies), ...asRecord(found.devDependencies) }
|
|
152
|
+
for (const dep of targetRequiredDeps(slug, pkg, layout)) {
|
|
153
|
+
if (deps[dep] == null) {
|
|
154
|
+
violations.push({
|
|
155
|
+
path, rule: IntegrityRule.RequiredDependency,
|
|
156
|
+
detail: `Package "${pkg}" must depend on ${dep}.`
|
|
157
|
+
})
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** Lifecycle hooks run on `bun install`, before anything else has a chance to refuse. */
|
|
163
|
+
function checkScripts(path: string, found: Record<string, unknown>): void {
|
|
164
|
+
const scripts = asRecord(found.scripts)
|
|
165
|
+
for (const hook of TARGET_FORBIDDEN_SCRIPTS) {
|
|
166
|
+
if (scripts[hook] != null) {
|
|
167
|
+
violations.push({
|
|
168
|
+
path, rule: IntegrityRule.LifecycleScript,
|
|
169
|
+
detail: `Lifecycle script "${hook}" is not allowed in a target project.`
|
|
170
|
+
})
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function checkMarkers(): void {
|
|
176
|
+
for (const [path, markers] of Object.entries(manifest.markers)) {
|
|
177
|
+
const content = files[path]
|
|
178
|
+
if (content == null) continue
|
|
179
|
+
|
|
180
|
+
const absent = markers.filter(marker => !content.includes(marker))
|
|
181
|
+
if (absent.length > 0) {
|
|
182
|
+
violations.push({
|
|
183
|
+
path, rule: IntegrityRule.EntryMarker,
|
|
184
|
+
detail: `${path} does not look like the generated app's entry: ${absent.join(', ')} not found.`
|
|
185
|
+
})
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function readJson(path: string): Record<string, unknown> | null {
|
|
191
|
+
const content = files[path]
|
|
192
|
+
if (content == null) return null
|
|
193
|
+
try {
|
|
194
|
+
const parsed: unknown = JSON.parse(content)
|
|
195
|
+
|
|
196
|
+
return typeof parsed === 'object' && parsed !== null
|
|
197
|
+
? parsed as Record<string, unknown>
|
|
198
|
+
: reportUnreadable(path)
|
|
199
|
+
} catch {
|
|
200
|
+
return reportUnreadable(path)
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function reportUnreadable(path: string): null {
|
|
205
|
+
violations.push({
|
|
206
|
+
path, rule: IntegrityRule.Unreadable, detail: `${path} is not a readable JSON object.`
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
return null
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function asRecord(value: unknown): Record<string, string> {
|
|
213
|
+
return typeof value === 'object' && value !== null
|
|
214
|
+
? value as Record<string, string>
|
|
215
|
+
: {}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** One line per violation — what goes into a log, `slot.lastError`, or a build diagnostic. */
|
|
220
|
+
export const formatIntegrityReport = (report: TargetIntegrityReport): string =>
|
|
221
|
+
report.violations.map(violation => `${violation.path}: ${violation.detail}`).join('\n')
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
|
|
2
|
+
import type { SpecCategory } from '../ba/consts.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Where the pipeline's markdown lives in a generated target.
|
|
6
|
+
*
|
|
7
|
+
* The tree follows the AGENTS.md / Agent Skills open standard rather than a private `.viable/`
|
|
8
|
+
* directory, because the target is an ordinary repository that people and other agents open: a
|
|
9
|
+
* brief belongs in `docs/`, and durable cross-run knowledge belongs in the agent memory graph
|
|
10
|
+
* every harness already reads. A directory only this pipeline understands is invisible to all of
|
|
11
|
+
* them, and a project the user takes home keeps none of it.
|
|
12
|
+
*
|
|
13
|
+
* The split is by AUDIENCE, not by writer. `docs/` is the product — read by a person, published
|
|
14
|
+
* with the repository, meaningful without the agent. `.agents/memory/` is working state — read by
|
|
15
|
+
* the next run to know what the last one allocated, decided and observed.
|
|
16
|
+
*/
|
|
17
|
+
export const HARNESS_DIR = '.agents'
|
|
18
|
+
export const MEMORY_DIR = `${HARNESS_DIR}/memory`
|
|
19
|
+
export const DOCS_DIR = 'docs'
|
|
20
|
+
|
|
21
|
+
export const STORIES_DIR = `${DOCS_DIR}/stories`
|
|
22
|
+
export const ENTITIES_DIR = `${DOCS_DIR}/entities`
|
|
23
|
+
|
|
24
|
+
/** Co-located specs keep their names and their place — beside the source file they describe. */
|
|
25
|
+
export const SPEC_SUFFIX = '.spec.md'
|
|
26
|
+
export const UX_SUFFIX = '.ux.md'
|
|
27
|
+
export const UI_SUFFIX = '.ui.md'
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Everything under `docs/` is plain markdown: the directory says what a file is, so the name
|
|
31
|
+
* does not have to. `docs/stories/CHK-1.md`, not `docs/stories/CHK-1.story.md`.
|
|
32
|
+
*/
|
|
33
|
+
export const STORY_SUFFIX = '.md'
|
|
34
|
+
export const ENTITY_SUFFIX = '.md'
|
|
35
|
+
|
|
36
|
+
/** The project brief — `docs/project.md`, the first file anyone opens. */
|
|
37
|
+
export const PROJECT_META_NAME = 'project'
|
|
38
|
+
export const PROJECT_META_FILE = `${DOCS_DIR}/${PROJECT_META_NAME}.md`
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The name registry — `.agents/memory/registry.md`.
|
|
42
|
+
*
|
|
43
|
+
* Project-level, not per-story: a resource alias is a physical table name and an entity directory
|
|
44
|
+
* is a repository-wide invariant, so a later story has to see what an earlier one allocated. Each
|
|
45
|
+
* entry records the story that introduced it, which keeps provenance without splitting the file.
|
|
46
|
+
*
|
|
47
|
+
* A memory node rather than a doc: it is what the NEXT run must not contradict, and it is
|
|
48
|
+
* meaningless to a reader of the product.
|
|
49
|
+
*/
|
|
50
|
+
export const REGISTRY_NAME = 'registry'
|
|
51
|
+
export const REGISTRY_FILE = `${MEMORY_DIR}/${REGISTRY_NAME}.md`
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The project's rolling history — `.agents/memory/history.md`.
|
|
55
|
+
*
|
|
56
|
+
* A file of its own rather than a section of `docs/project.md`, because `writeProject` rebuilds
|
|
57
|
+
* that file's whole body out of `AgentProject`: a history section there would be destroyed by the
|
|
58
|
+
* next brief update, silently and with nothing failing.
|
|
59
|
+
*
|
|
60
|
+
* It answers "where are we" for every model call that reads it, so it is folded under a ceiling
|
|
61
|
+
* rather than appended to.
|
|
62
|
+
*/
|
|
63
|
+
export const HISTORY_NAME = 'history'
|
|
64
|
+
export const HISTORY_FILE = `${MEMORY_DIR}/${HISTORY_NAME}.md`
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Recorded layout deviations — `.agents/memory/layout.md`.
|
|
68
|
+
*
|
|
69
|
+
* The generated target IS-A `@owlmeans/create-app` project, and the pipeline derives every path
|
|
70
|
+
* from that assumption. A repository the user has since reshaped by hand is still theirs, so a
|
|
71
|
+
* deviation is RECORDED here instead of being corrected: the next run reads it and addresses the
|
|
72
|
+
* tree that exists rather than re-deriving one that does not.
|
|
73
|
+
*/
|
|
74
|
+
export const LAYOUT_NAME = 'layout'
|
|
75
|
+
export const LAYOUT_FILE = `${MEMORY_DIR}/${LAYOUT_NAME}.md`
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The deployment topology — `.agents/memory/topology.md`.
|
|
79
|
+
*
|
|
80
|
+
* Which runtimes the project actually runs (api, web, worker), what each binds, and which queues
|
|
81
|
+
* carry work between them. A worker exists only once something needs one, so this is the record
|
|
82
|
+
* of that decision — the thing a later run must not silently re-decide.
|
|
83
|
+
*/
|
|
84
|
+
export const TOPOLOGY_NAME = 'topology'
|
|
85
|
+
export const TOPOLOGY_FILE = `${MEMORY_DIR}/${TOPOLOGY_NAME}.md`
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* The ceiling on the whole rendered history block, in characters.
|
|
89
|
+
*
|
|
90
|
+
* Enforced by truncation after the model answers, never by asking it to obey a limit. The parts
|
|
91
|
+
* below are budgeted to fit inside it with room for their separators.
|
|
92
|
+
*/
|
|
93
|
+
export const HISTORY_MAX_CHARS = 3000
|
|
94
|
+
export const HISTORY_LAST_EVENT_CHARS = 200
|
|
95
|
+
export const HISTORY_SUMMARY_CHARS = 1600
|
|
96
|
+
export const HISTORY_RECENT_CHARS = 140
|
|
97
|
+
/** How many events stay verbatim before older ones are folded into the prose. */
|
|
98
|
+
export const HISTORY_RECENT_MAX = 8
|
|
99
|
+
/** The heading the verbatim tail is written under. */
|
|
100
|
+
export const HISTORY_RECENT_HEADING = 'Recent'
|
|
101
|
+
|
|
102
|
+
export const METADATA_SUFFIX: Record<SpecCategory, string> = {
|
|
103
|
+
ba: SPEC_SUFFIX,
|
|
104
|
+
ux: UX_SUFFIX,
|
|
105
|
+
ui: UI_SUFFIX,
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Suffixes that mark a CO-LOCATED metadata file — one sitting beside the source it describes.
|
|
110
|
+
*
|
|
111
|
+
* Only these three, because everything else the pipeline writes now lives under a directory of
|
|
112
|
+
* its own: excluding pipeline markdown from a source listing is a question about the path, not
|
|
113
|
+
* about the tail. Adding `.md` here would hide every README in the project.
|
|
114
|
+
*/
|
|
115
|
+
export const METADATA_SUFFIXES = [SPEC_SUFFIX, UX_SUFFIX, UI_SUFFIX]
|
|
116
|
+
|
|
117
|
+
/** The trees the pipeline writes into — excluded wholesale when source files are enumerated. */
|
|
118
|
+
export const METADATA_DIRS = [HARNESS_DIR, DOCS_DIR]
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
|
|
2
|
+
import type { SpecCategory } from '../ba/consts.js'
|
|
3
|
+
|
|
4
|
+
export interface MetadataFile<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
5
|
+
path: string
|
|
6
|
+
data: T
|
|
7
|
+
body: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface MetadataWriteInput<T extends Record<string, unknown> = Record<string, unknown>> {
|
|
11
|
+
data?: Partial<T>
|
|
12
|
+
body: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export enum MetadataKind {
|
|
16
|
+
Project = 'project',
|
|
17
|
+
Story = 'story',
|
|
18
|
+
Source = 'source',
|
|
19
|
+
History = 'history',
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export enum MetadataListKind {
|
|
23
|
+
Stories = 'stories',
|
|
24
|
+
Meta = 'meta',
|
|
25
|
+
// All metadata: the docs/ and .agents/ trees + co-located *.spec/.ux/.ui.md beside sources
|
|
26
|
+
All = 'all',
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Identifies a single metadata document to read:
|
|
31
|
+
* - Project: kind=Project, no ref/category needed
|
|
32
|
+
* - Story: kind=Story, ref=story-code
|
|
33
|
+
* - Source: kind=Source, ref=source-path, category=SpecCategory
|
|
34
|
+
*/
|
|
35
|
+
export interface MetadataRef {
|
|
36
|
+
kind: MetadataKind
|
|
37
|
+
ref?: string
|
|
38
|
+
category?: SpecCategory
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Identifies a list of metadata documents to enumerate:
|
|
43
|
+
* - Stories: kind=Stories → returns story codes
|
|
44
|
+
* - Meta: kind=Meta → returns co-located *.spec/.ux/.ui.md paths;
|
|
45
|
+
* category narrows to one suffix
|
|
46
|
+
*/
|
|
47
|
+
export interface MetadataListRef {
|
|
48
|
+
kind: MetadataListKind
|
|
49
|
+
category?: SpecCategory
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ─── Typed frontmatter shapes (Platform: drives ProjectMetadataStore serialisation) ────
|
|
53
|
+
|
|
54
|
+
/** Frontmatter for docs/project.md */
|
|
55
|
+
export interface ProjectMeta extends Record<string, unknown> {
|
|
56
|
+
name: string
|
|
57
|
+
alias: string
|
|
58
|
+
/**
|
|
59
|
+
* The language every piece of generated UI text is written in — labels, headings, empty
|
|
60
|
+
* states, validation messages, i18n values.
|
|
61
|
+
*
|
|
62
|
+
* Recorded on the project rather than asked per pass, because a screen scaffolded in one
|
|
63
|
+
* language and extended in another is a mixed interface that nothing reports: the code
|
|
64
|
+
* compiles, the tests pass, and only a reader of the running app can see it. An IETF tag
|
|
65
|
+
* (`en`, `pl`, `pt-BR`).
|
|
66
|
+
*/
|
|
67
|
+
language: string
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Frontmatter for `.agents/memory/history.md`.
|
|
72
|
+
*
|
|
73
|
+
* `lastEvent` is written verbatim on every record and rendered as the first line of the history
|
|
74
|
+
* block. That is what makes "the summary always names the most recent event" a property of the
|
|
75
|
+
* file rather than a hope about the model that folded it.
|
|
76
|
+
*/
|
|
77
|
+
export interface HistoryMeta extends Record<string, unknown> {
|
|
78
|
+
version: number
|
|
79
|
+
updatedAt: string
|
|
80
|
+
lastEvent: string
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Frontmatter for docs/entities/<name>.md */
|
|
84
|
+
export interface EntityMeta extends Record<string, unknown> {
|
|
85
|
+
name: string
|
|
86
|
+
attributes: Array<{ name: string; description: string }>
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Ref to a screen inside a docs/stories/<code>.md index */
|
|
90
|
+
export interface StoryScreenRef {
|
|
91
|
+
name: string
|
|
92
|
+
path: string
|
|
93
|
+
/** Top-menu group this screen renders under. A label, never a URL segment. */
|
|
94
|
+
section?: string
|
|
95
|
+
components: StoryComponentRef[]
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Ref to a component inside a docs/stories/<code>.md index */
|
|
99
|
+
export interface StoryComponentRef {
|
|
100
|
+
name: string
|
|
101
|
+
path: string
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Frontmatter for docs/stories/<code>.md */
|
|
105
|
+
export interface StoryMeta extends Record<string, unknown> {
|
|
106
|
+
code: string
|
|
107
|
+
status: string
|
|
108
|
+
primary: boolean
|
|
109
|
+
/** The audience this story serves; its screens live under that area's entrypoint. */
|
|
110
|
+
area: string
|
|
111
|
+
/**
|
|
112
|
+
* The top-menu section the scaffold reserved for this story, inside its area.
|
|
113
|
+
*
|
|
114
|
+
* Assigned before any of the story's code exists, so that the stub screen drawn at
|
|
115
|
+
* initialization and the real screen developed later land in the SAME menu group — a story
|
|
116
|
+
* that moves section when it is implemented leaves its own dashboard behind.
|
|
117
|
+
*/
|
|
118
|
+
section?: string
|
|
119
|
+
entity: string
|
|
120
|
+
entities: string[]
|
|
121
|
+
screens: StoryScreenRef[]
|
|
122
|
+
transitions: Array<{
|
|
123
|
+
from: string
|
|
124
|
+
to: string
|
|
125
|
+
initiator: string
|
|
126
|
+
action: string
|
|
127
|
+
type: string
|
|
128
|
+
}>
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Frontmatter for co-located <screen>.spec.md */
|
|
132
|
+
export interface ScreenMeta extends Record<string, unknown> {
|
|
133
|
+
name: string
|
|
134
|
+
stories: string[]
|
|
135
|
+
area?: string
|
|
136
|
+
section?: string
|
|
137
|
+
components: string[]
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** Frontmatter for co-located <component>.spec.md */
|
|
141
|
+
export interface ComponentMeta extends Record<string, unknown> {
|
|
142
|
+
name: string
|
|
143
|
+
stories: string[]
|
|
144
|
+
entities: string[]
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Payload the agent passes to store.writeStory — all data the developer
|
|
149
|
+
* collected during one develop run.
|
|
150
|
+
*/
|
|
151
|
+
export interface StoryWriteInput {
|
|
152
|
+
code: string
|
|
153
|
+
narrative: string
|
|
154
|
+
status: string
|
|
155
|
+
primary: boolean
|
|
156
|
+
/** Carried through a develop run so the rewrite does not drop the scaffold's assignment. */
|
|
157
|
+
section?: string
|
|
158
|
+
/** Likewise the reserved screen name. */
|
|
159
|
+
screen?: string
|
|
160
|
+
userStory: import('../ba/types.js').UserStory
|
|
161
|
+
/** Each entry maps a StoryScreen to its source path in the target project */
|
|
162
|
+
screenPaths: Record<string, string>
|
|
163
|
+
/** Each entry maps a StoryComponent to its source path in the target project */
|
|
164
|
+
componentPaths: Record<string, string>
|
|
165
|
+
transitions: Array<{
|
|
166
|
+
from: string
|
|
167
|
+
to: string
|
|
168
|
+
initiator: string
|
|
169
|
+
action: string
|
|
170
|
+
type: string
|
|
171
|
+
}>
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// ─── Name registry (.agents/memory/registry.md) ───────────────────────────────────────
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* What a registry entry names.
|
|
178
|
+
*
|
|
179
|
+
* One entry per artifact the pipeline can generate, so that "where does this live" and "what is
|
|
180
|
+
* it called" have exactly one answer for the whole life of the project.
|
|
181
|
+
*/
|
|
182
|
+
export enum RegistryKind {
|
|
183
|
+
/** The single directory segment an entity owns across models/, resources/ and backend models/ */
|
|
184
|
+
EntityDir = 'entity-dir',
|
|
185
|
+
ModelType = 'model-type',
|
|
186
|
+
Resource = 'resource',
|
|
187
|
+
BackendModel = 'backend-model',
|
|
188
|
+
ApiHandlers = 'api-handlers',
|
|
189
|
+
Service = 'service',
|
|
190
|
+
Layout = 'layout',
|
|
191
|
+
Screen = 'screen',
|
|
192
|
+
Component = 'component',
|
|
193
|
+
ViewModel = 'view-model',
|
|
194
|
+
State = 'state',
|
|
195
|
+
/** Alias-only entry for one endpoint — carries no source path of its own */
|
|
196
|
+
ApiEntrypoint = 'api-entrypoint',
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* One allocated name.
|
|
201
|
+
*
|
|
202
|
+
* `name` is the lookup key — the entity name for entity-scoped kinds, the definition otherwise.
|
|
203
|
+
* Everything else is what generated code must use verbatim: a coder that writes a different
|
|
204
|
+
* directory, and a fixer that renames a reference instead of declaring the missing thing, are the
|
|
205
|
+
* two failure modes this record exists to make impossible.
|
|
206
|
+
*/
|
|
207
|
+
export interface RegistryAllocation extends Record<string, unknown> {
|
|
208
|
+
kind: RegistryKind
|
|
209
|
+
name: string
|
|
210
|
+
/** Repo-relative source path; empty for alias-only kinds */
|
|
211
|
+
path: string
|
|
212
|
+
/** Resource alias (also the physical table name) or entrypoint alias */
|
|
213
|
+
alias?: string
|
|
214
|
+
/** Dotted `app.*` reference the generated code uses to reach the alias */
|
|
215
|
+
appRef?: string
|
|
216
|
+
/** Exported symbol — screen/layout/component/handler */
|
|
217
|
+
symbol?: string
|
|
218
|
+
/**
|
|
219
|
+
* The FULL assembled route, recorded when an entrypoint is declared — area prefix included.
|
|
220
|
+
*
|
|
221
|
+
* The declaration that produces it carries only the tail, because a child path is appended to
|
|
222
|
+
* its parent's; `areaSegment` is what shortens this value when a declaration is written back.
|
|
223
|
+
*/
|
|
224
|
+
url?: string
|
|
225
|
+
/** Parent entrypoint alias — for a screen that is its AREA, for an endpoint its group */
|
|
226
|
+
parent?: string
|
|
227
|
+
/** The area a screen belongs to — one of the four {@link ProjectArea} values. */
|
|
228
|
+
area?: string
|
|
229
|
+
/** Top-menu group of a screen. A label, never a URL segment. */
|
|
230
|
+
section?: string
|
|
231
|
+
/**
|
|
232
|
+
* A SCAFFOLD placeholder — drawn at initialization, replaced or deleted later.
|
|
233
|
+
*
|
|
234
|
+
* The flag is what makes cleanup deterministic instead of a judgement call. It survives until
|
|
235
|
+
* either the story behind the artifact is implemented (the file is rewritten in place and the
|
|
236
|
+
* flag is cleared) or something else edits the file, which clears the flag as well: whoever
|
|
237
|
+
* edited it meant it, so nothing may delete it afterwards.
|
|
238
|
+
*/
|
|
239
|
+
stub?: boolean
|
|
240
|
+
/**
|
|
241
|
+
* SHA-256 of the file exactly as the scaffold wrote it.
|
|
242
|
+
*
|
|
243
|
+
* Compared against the file on disk before a stub is deleted. A mismatch means the file is no
|
|
244
|
+
* longer the placeholder that was written — free flight, the editor or a story implementation
|
|
245
|
+
* has been in it — so it is kept, and only the `stub` flag is dropped.
|
|
246
|
+
*/
|
|
247
|
+
hash?: string
|
|
248
|
+
/** This widget is on its area home's shortlist and renders there in `compact` mode too. */
|
|
249
|
+
home?: boolean
|
|
250
|
+
/** Story code that OWNS the allocation — the one its file is named after. */
|
|
251
|
+
story: string
|
|
252
|
+
/**
|
|
253
|
+
* Every story this one artifact stands in for, the owner included.
|
|
254
|
+
*
|
|
255
|
+
* A preview widget is drawn per user story only when each story genuinely needs its own; two
|
|
256
|
+
* steps of one flow that act on the same record through the same shape share ONE widget, and
|
|
257
|
+
* then the widget belongs to a SET. `story` stays the code the file is named after, because
|
|
258
|
+
* `widgetDefinition(code)` derives the filename from exactly one; this is what lets
|
|
259
|
+
* `byStory` answer to every member, and what stops a departing member from retiring an
|
|
260
|
+
* artifact the others still name.
|
|
261
|
+
*
|
|
262
|
+
* Absent on an artifact nobody shares — the ordinary case, and the shape every slot drawn
|
|
263
|
+
* before sharing existed carries.
|
|
264
|
+
*/
|
|
265
|
+
stories?: string[]
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/** Frontmatter for .agents/memory/registry.md */
|
|
269
|
+
export interface RegistryMeta extends Record<string, unknown> {
|
|
270
|
+
version: number
|
|
271
|
+
entries: RegistryAllocation[]
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// ─── Layout deviations (.agents/memory/layout.md) ─────────────────────────────────────
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* One place the repository no longer matches the layout the pipeline derives paths from.
|
|
278
|
+
*
|
|
279
|
+
* `expected` is what `naming.ts` would build; `actual` is what is on disk. Both are recorded
|
|
280
|
+
* because a later run has to do two different things with them — address the file where it is,
|
|
281
|
+
* and stop proposing to move it back.
|
|
282
|
+
*/
|
|
283
|
+
export interface LayoutDeviation {
|
|
284
|
+
/** What the pipeline would have derived — a repo-relative path or a directory. */
|
|
285
|
+
expected: string
|
|
286
|
+
/** Where the thing actually is. Empty when it was removed outright. */
|
|
287
|
+
actual: string
|
|
288
|
+
/** Why it moved, in one sentence, as the run that observed it understood it. */
|
|
289
|
+
reason: string
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Frontmatter for `.agents/memory/layout.md`.
|
|
294
|
+
*
|
|
295
|
+
* A generated target IS-A `@owlmeans/create-app` project, and every path the pipeline writes is
|
|
296
|
+
* derived from that. The volume is the user's, though: they rename, they move, they merge a pull
|
|
297
|
+
* request. Recording the divergence is what keeps the next run from fighting it — an agent that
|
|
298
|
+
* re-derives a path it was already told is wrong recreates the file in the old place, and the
|
|
299
|
+
* project then has two.
|
|
300
|
+
*
|
|
301
|
+
* `layout` is which of the two generated shapes the tree started as, so that a slot published
|
|
302
|
+
* before the `create-app` adoption is still addressed in its own vocabulary.
|
|
303
|
+
*/
|
|
304
|
+
export interface LayoutMeta extends Record<string, unknown> {
|
|
305
|
+
version: number
|
|
306
|
+
/** `v1` (packages/{common,backend,frontend}) or `v2` (sources/*). */
|
|
307
|
+
layout: string
|
|
308
|
+
updatedAt: string
|
|
309
|
+
deviations: LayoutDeviation[]
|
|
310
|
+
}
|