@warpgogol/werkstatt-shared 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -13
- package/README.uk.md +25 -15
- package/package.json +519 -762
- package/src/{share/agent → agent}/ard-catalog.ts +6 -1
- package/src/{share/agent → agent}/dns-aid.test.ts +2 -2
- package/src/{share/agent → agent}/manifest.ts +15 -1
- package/src/{share/agent → agent}/search.ts +6 -1
- package/src/{share → agent}/tests/api-catalog.test.ts +2 -2
- package/src/{share → agent}/tests/ard-catalog.test.ts +2 -2
- package/src/{share → agent}/tests/capability.test.ts +1 -1
- package/src/{share → agent}/tests/fleet-catalog.test.ts +1 -1
- package/src/{share → agent}/tests/knowledge.test.ts +2 -2
- package/src/{share → agent}/tests/manifest.test.ts +1 -1
- package/src/{share → agent}/tests/mcp-card.test.ts +2 -2
- package/src/agent/tests/omit-empty.test.ts +33 -0
- package/src/{share → agent}/tests/openapi.test.ts +2 -2
- package/src/{share → agent}/tests/proof.test.ts +1 -1
- package/src/{share → attribution}/material-credits.ts +4 -4
- package/src/{share → checks}/check-hints.ts +6 -1
- package/src/checks/index.ts +4 -1
- package/src/checks/lib/astro-site-url.ts +6 -1
- package/src/checks/lib/i18n.ts +14 -0
- package/src/checks/result-helpers.ts +22 -5
- package/src/checks/tests/remediation-auto-populate.test.ts +83 -0
- package/src/{share → client-scripts}/counter-utils.ts +6 -2
- package/src/{share/scripts → client-scripts}/external-link-qr.ts +11 -16
- package/src/{share/scripts → client-scripts}/external-links.ts +12 -1
- package/src/{share/scripts → client-scripts}/gsap-counter.ts +8 -3
- package/src/client-scripts/index.ts +35 -0
- package/src/{share/scripts → client-scripts}/inline-number-animation.ts +1 -1
- package/src/{share/scripts → client-scripts}/lenis.ts +6 -1
- package/src/{share/scripts → client-scripts}/lordicon.ts +6 -1
- package/src/{share/scripts → client-scripts}/orchestrator.ts +10 -1
- package/src/{share/scripts → client-scripts}/scheduler.ts +6 -1
- package/src/client-scripts/scroll-spy.ts +106 -0
- package/src/client-scripts/tests/external-link-qr.test.ts +8 -0
- package/src/client-scripts/tests/external-links.test.ts +25 -0
- package/src/client-scripts/tests/gsap-counter.test.ts +8 -0
- package/src/client-scripts/tests/gsap-mountain-journey.test.ts +8 -0
- package/src/client-scripts/tests/gsap-parallax.test.ts +8 -0
- package/src/client-scripts/tests/gsap-reveal.test.ts +8 -0
- package/src/client-scripts/tests/gsap-stagger.test.ts +8 -0
- package/src/client-scripts/tests/inline-number-animation.test.ts +8 -0
- package/src/client-scripts/tests/lenis.test.ts +8 -0
- package/src/client-scripts/tests/live-photos.test.ts +8 -0
- package/src/client-scripts/tests/lordicon.test.ts +8 -0
- package/src/client-scripts/tests/orchestrator.test.ts +47 -0
- package/src/client-scripts/tests/scheduler.test.ts +23 -0
- package/src/client-scripts/tests/scroll-spy.test.ts +204 -0
- package/src/{share/scripts → client-scripts/tests}/video-player.test.ts +51 -31
- package/src/component/contracts.ts +206 -0
- package/src/component/index.ts +11 -0
- package/src/{share → content}/content-reference.ts +3 -3
- package/src/{share/content → content}/entity-id.ts +6 -3
- package/src/content/index.ts +3 -0
- package/src/{share/content → content}/merge.ts +6 -1
- package/src/content/system-manifest.test.ts +107 -0
- package/src/content/system-manifest.ts +12 -94
- package/src/{share → content}/tests/resolve-field-path.test.ts +1 -1
- package/src/{share → content}/tests/substitute-deep.test.ts +1 -1
- package/src/content-discipline/index.ts +19 -0
- package/src/{share/content-discipline → content-discipline}/parsers.ts +2 -2
- package/src/{share/env.d.ts → env.d.ts} +6 -3
- package/src/fingerprint/canonical-json.ts +731 -0
- package/src/fingerprint/index.ts +12 -0
- package/src/fingerprint/primitives.ts +72 -0
- package/src/{share/i18n → i18n}/localization.ts +6 -2
- package/src/integration/adapters.ts +10 -71
- package/src/integration/dispatch.ts +1 -1
- package/src/integration/funnel.ts +6 -1
- package/src/integration/index.ts +101 -4
- package/src/integration/lagebild-destination-adapter.ts +108 -0
- package/src/integration/lagebild-ingress.ts +7 -12
- package/src/integration/orchestration.ts +11 -10
- package/src/integration/tests/deliver-event.test.ts +1 -1
- package/src/integration/tests/dispatch.test.ts +4 -4
- package/src/integration/tests/hub-runtime.test.ts +22 -14
- package/src/integration/vitest.config.ts +8 -0
- package/src/kernel/desired-state.ts +227 -0
- package/src/kernel/diagnostic.ts +289 -0
- package/src/kernel/fs-atomic.ts +131 -0
- package/src/kernel/index.ts +15 -0
- package/src/kernel/tests/fs-atomic.test.ts +150 -0
- package/src/kernel/tests/workspace-io.test.ts +187 -0
- package/src/kernel/types.ts +459 -0
- package/src/kernel/workspace-io.ts +248 -0
- package/src/{share → knowledge}/tests/claim.test.ts +1 -1
- package/src/{share → knowledge}/tests/derivation.test.ts +1 -1
- package/src/{share → knowledge}/tests/freshness.test.ts +1 -1
- package/src/{share → knowledge}/tests/ledger.test.ts +1 -1
- package/src/{share → knowledge}/tests/plan.test.ts +1 -1
- package/src/{share → knowledge}/tests/source.test.ts +1 -1
- package/src/legal/index.ts +15 -0
- package/src/{share/middleware → middleware}/access-protection.ts +8 -8
- package/src/{share → node}/dev-props-validator.ts +6 -1
- package/src/{share → node}/import-scan.ts +23 -3
- package/src/{share → node}/semantic/derived-prices-loader.ts +4 -2
- package/src/{share → node}/semantic/markdown-twin-provenance.ts +1 -1
- package/src/node/tests/derived-prices-loader.test.ts +59 -0
- package/src/node/tests/markdown-twin-provenance.test.ts +152 -0
- package/src/observability/env-resolver.ts +6 -1
- package/src/observability/index.ts +6 -1
- package/src/observability/otlp-converter.ts +6 -1
- package/src/observability/otlp-transport.ts +6 -1
- package/src/observability/pusher.ts +6 -1
- package/src/observability/redact.ts +6 -1
- package/src/observability/typed-refs.ts +6 -2
- package/src/observability/vitest.config.ts +1 -0
- package/src/{share → offers}/formula-eval.ts +3 -3
- package/src/{share → offers}/tests/formula-eval.test.ts +2 -2
- package/src/onboarding/index.ts +1 -0
- package/src/{share → onboarding}/tests/onboarding-yaml.test.ts +1 -1
- package/src/ontology/archetype-registry.ts +6 -1
- package/src/ontology/archetypes/index.json +33 -1
- package/src/ontology/archetypes/index.yaml +27 -1
- package/src/ontology/archetypes/sections/entity-grid.yaml +46 -0
- package/src/ontology/archetypes/sections/exit-diagram.yaml +43 -0
- package/src/ontology/biome-token-projection.ts +6 -1
- package/src/ontology/cosmic/index.ts +6 -1
- package/src/ontology/cosmic/moon-catalog.ts +6 -1
- package/src/ontology/cosmic/planet-catalog.ts +6 -1
- package/src/ontology/cosmic/star-catalog.ts +6 -1
- package/src/ontology/enums.ts +6 -1
- package/src/ontology/external-surfaces/index.ts +1 -1
- package/src/ontology/index.ts +6 -2
- package/src/ontology/manifest.ts +26 -4
- package/src/ontology/operations/artifact-store.ts +45 -0
- package/src/ontology/operations/dht.ts +98 -0
- package/src/ontology/operations/handoff.ts +92 -0
- package/src/ontology/operations/index.ts +187 -1
- package/src/ontology/operations/leitstand.ts +99 -0
- package/src/ontology/operations/materialization.ts +90 -0
- package/src/ontology/operations/mission.ts +111 -0
- package/src/ontology/operations/naming-policy.ts +132 -0
- package/src/ontology/operations/notausgang.ts +64 -0
- package/src/ontology/operations/release.ts +121 -0
- package/src/ontology/operations/sternsystem.ts +192 -0
- package/src/ontology/operations/werkstatt.ts +48 -0
- package/src/ontology/schemas/biome.ts +7 -2
- package/src/ontology/schemas/capability.ts +1 -1
- package/src/ontology/schemas/constellation.ts +6 -1
- package/src/ontology/schemas/index.ts +6 -2
- package/src/ontology/schemas/manifest-resolver.ts +6 -1
- package/src/ontology/schemas/page-entry.ts +9 -5
- package/src/ontology/schemas/system/growth.ts +6 -1
- package/src/ontology/schemas/system/manifest.ts +40 -1
- package/src/ontology/schemas/system/page-output.ts +7 -6
- package/src/ontology/schemas/system/tests/growth.test.ts +22 -0
- package/src/ontology/schemas/system/tests/integrations.test.ts +12 -0
- package/src/ontology/schemas/system/tests/manifest.test.ts +22 -0
- package/src/ontology/schemas/system/tests/page-output.test.ts +13 -0
- package/src/ontology/schemas/system/tests/release.test.ts +22 -0
- package/src/ontology/schemas/system/tests/text.test.ts +18 -0
- package/src/ontology/schemas/system/tests/verification.test.ts +12 -0
- package/src/ontology/schemas/system/text.ts +15 -0
- package/src/ontology/schemas/system.ts +6 -2
- package/src/ontology/schemas/tests/biome.test.ts +19 -0
- package/src/ontology/schemas/tests/capability.test.ts +22 -0
- package/src/ontology/schemas/tests/constellation.test.ts +22 -0
- package/src/ontology/schemas/tests/dns-records.test.ts +13 -0
- package/src/ontology/schemas/tests/manifest-resolver.test.ts +13 -0
- package/src/ontology/schemas/tests/page-entry.test.ts +22 -0
- package/src/ontology/schemas/tests/section-archetype.test.ts +12 -0
- package/src/ontology/schemas/tests/site-family.test.ts +18 -0
- package/src/ontology/schemas/tests/system.test.ts +20 -0
- package/src/ontology/shared-section-props/body-fragments.ts +2 -0
- package/src/ontology/tests/sternsystem-owner.test.ts +1 -1
- package/src/ontology/vitest.config.ts +1 -0
- package/src/{share → page}/page.ts +13 -9
- package/src/{share → page}/tests/dev-props-validator.test.ts +1 -1
- package/src/{share → page}/tests/hero-section-numbering-parity.test.ts +1 -1
- package/src/passport/index.ts +6 -1
- package/src/passport/key-rotate.ts +10 -2
- package/src/passport/schema.ts +6 -1
- package/src/passport/sign.ts +8 -3
- package/src/passport/vitest.config.ts +1 -0
- package/src/pbt/index.test.ts +95 -0
- package/src/pbt/index.ts +251 -0
- package/src/plugin/plugin-contract.ts +1 -1
- package/src/{share → policy}/entitlement.ts +24 -4
- package/src/{share → policy}/feature-policy.ts +8 -3
- package/src/{share → policy}/visibility.ts +7 -2
- package/src/redirects/redirects.ts +117 -0
- package/src/{share → redirects/tests}/redirects.test.ts +1 -1
- package/src/remediation/remediation-catalog.ts +316 -0
- package/src/{share/routes → routes}/template-filter.ts +1 -1
- package/src/{share → runtime}/runtime-context.ts +7 -2
- package/src/{share → runtime}/shared-context.ts +1 -1
- package/src/{share/schemas → schemas}/claims.ts +2 -2
- package/src/{share/schemas → schemas}/effects.ts +6 -1
- package/src/{share/schemas → schemas}/features.ts +1 -1
- package/src/{share/schemas → schemas}/index.ts +3 -3
- package/src/{share/schemas → schemas}/navigation.ts +6 -1
- package/src/{share/schemas → schemas}/page-base.ts +6 -2
- package/src/{share/schemas → schemas}/person.ts +1 -1
- package/src/{share/schemas → schemas}/standard-list-item.ts +1 -1
- package/src/schemas/tests/claim-records.test.ts +52 -0
- package/src/schemas/tests/claims.test.ts +23 -0
- package/src/schemas/tests/effects.test.ts +116 -0
- package/src/schemas/tests/features.test.ts +61 -0
- package/src/schemas/tests/horizontal-align.test.ts +16 -0
- package/src/schemas/tests/icon-color.test.ts +16 -0
- package/src/schemas/tests/live-photo.test.ts +40 -0
- package/src/schemas/tests/material-credit.test.ts +51 -0
- package/src/schemas/tests/media.test.ts +26 -0
- package/src/schemas/tests/navigation.test.ts +58 -0
- package/src/schemas/tests/page-base.test.ts +19 -0
- package/src/schemas/tests/participant.test.ts +26 -0
- package/src/schemas/tests/person.test.ts +12 -0
- package/src/schemas/tests/print.test.ts +30 -0
- package/src/schemas/tests/section-background.test.ts +31 -0
- package/src/schemas/tests/section-body.test.ts +16 -0
- package/src/schemas/tests/section-cards.test.ts +17 -0
- package/src/schemas/tests/section-cta.test.ts +41 -0
- package/src/schemas/tests/section-header.test.ts +31 -0
- package/src/schemas/tests/section-image.test.ts +24 -0
- package/src/schemas/tests/section-motion.test.ts +29 -0
- package/src/schemas/tests/section-shell.test.ts +42 -0
- package/src/schemas/tests/section-stats.test.ts +17 -0
- package/src/schemas/tests/site-background.test.ts +33 -0
- package/src/schemas/tests/standard-list-item.test.ts +16 -0
- package/src/{share → sections}/rfc0042-utils.ts +1 -1
- package/src/{share/semantic → semantic}/block-extractors/index.ts +20 -1
- package/src/{share/semantic → semantic}/business-projection.ts +95 -1
- package/src/semantic/canonical-uri.ts +54 -0
- package/src/{share/semantic → semantic}/extract.ts +100 -1
- package/src/semantic/fact-extraction.test.ts +47 -0
- package/src/semantic/fact-extraction.ts +46 -0
- package/src/semantic/freshness.ts +67 -0
- package/src/{share/semantic → semantic}/ids.ts +6 -1
- package/src/{share/semantic → semantic}/index.ts +9 -2
- package/src/{share/semantic → semantic}/jsonld/breadcrumb.ts +6 -2
- package/src/{share/semantic → semantic}/jsonld/context.ts +6 -2
- package/src/{share/semantic → semantic}/jsonld/faq.ts +6 -2
- package/src/{share/semantic → semantic}/jsonld/initiative.ts +6 -1
- package/src/{share/semantic → semantic}/jsonld/organization.ts +6 -1
- package/src/{share/semantic → semantic}/jsonld/person.ts +6 -2
- package/src/{share/semantic → semantic}/jsonld/service.ts +6 -2
- package/src/semantic/jsonld/shared.ts +36 -0
- package/src/semantic/jsonld/tests/article.test.ts +89 -0
- package/src/semantic/jsonld/tests/breadcrumb.test.ts +62 -0
- package/src/semantic/jsonld/tests/collection-list.test.ts +39 -0
- package/src/semantic/jsonld/tests/faq.test.ts +60 -0
- package/src/semantic/jsonld/tests/initiative.test.ts +56 -0
- package/src/semantic/jsonld/tests/organization.test.ts +123 -0
- package/src/semantic/jsonld/tests/person.test.ts +89 -0
- package/src/semantic/jsonld/tests/service.test.ts +65 -0
- package/src/semantic/jsonld/tests/shared.test.ts +41 -0
- package/src/semantic/jsonld/tests/video.test.ts +84 -0
- package/src/semantic/jsonld/tests/webpage.test.ts +93 -0
- package/src/semantic/jsonld/tests/website.test.ts +27 -0
- package/src/semantic/jsonld/types.ts +24 -0
- package/src/{share/semantic → semantic}/jsonld/webpage.ts +6 -1
- package/src/semantic/jsonld/website.ts +32 -0
- package/src/{share/semantic → semantic}/jsonld.ts +6 -1
- package/src/{share/semantic → semantic}/llms.ts +41 -3
- package/src/{share/semantic → semantic}/models.ts +27 -38
- package/src/{share/semantic → semantic}/organization-profile.ts +3 -0
- package/src/{share/semantic → semantic}/page-builders/markdown-page.ts +6 -3
- package/src/{share/semantic → semantic}/page-utils.ts +6 -3
- package/src/semantic/tests/ai.test.ts +55 -0
- package/src/semantic/tests/block-extraction.test.ts +34 -0
- package/src/{share/tests/breadcrumbs.test.ts → semantic/tests/breadcrumbs-0229.test.ts} +1 -1
- package/src/semantic/tests/breadcrumbs.test.ts +127 -0
- package/src/{share → semantic}/tests/build-page-price-markers.test.ts +2 -2
- package/src/semantic/tests/build-page.test.ts +122 -0
- package/src/semantic/tests/business-projection.test.ts +367 -0
- package/src/semantic/tests/canonical-uri.test.ts +56 -0
- package/src/semantic/tests/extract.test.ts +209 -0
- package/src/semantic/tests/feed.test.ts +113 -0
- package/src/semantic/tests/freshness.pbt.test.ts +108 -0
- package/src/semantic/tests/helpers.ts +32 -0
- package/src/semantic/tests/ids.test.ts +118 -0
- package/src/{share/tests/image-sitemap.test.ts → semantic/tests/image-sitemap-0150.test.ts} +1 -1
- package/src/semantic/tests/image-sitemap.test.ts +109 -0
- package/src/{share → semantic}/tests/jsonld-service.test.ts +2 -2
- package/src/{share → semantic}/tests/jsonld-video.test.ts +3 -3
- package/src/{share → semantic}/tests/jsonld-webpage.test.ts +3 -3
- package/src/semantic/tests/jsonld.test.ts +61 -0
- package/src/{share → semantic}/tests/llms-0789.test.ts +2 -2
- package/src/semantic/tests/llms-policy.test.ts +60 -0
- package/src/semantic/tests/llms.test.ts +164 -0
- package/src/semantic/tests/markdown-hygiene.test.ts +72 -0
- package/src/semantic/tests/markdown-page.test.ts +97 -0
- package/src/{share → semantic}/tests/organization-jsonld.test.ts +3 -3
- package/src/semantic/tests/organization-profile.test.ts +107 -0
- package/src/{share/tests/output-projection.test.ts → semantic/tests/output-projection-0143.test.ts} +1 -1
- package/src/semantic/tests/output-projection.test.ts +77 -0
- package/src/semantic/tests/page-markdown.test.ts +98 -0
- package/src/semantic/tests/page-utils.test.ts +88 -0
- package/src/{share/tests/price-marker-resolver.test.ts → semantic/tests/price-marker-resolver-0767.test.ts} +2 -2
- package/src/semantic/tests/price-marker-resolver.test.ts +90 -0
- package/src/semantic/tests/project-claims.pbt.test.ts +60 -0
- package/src/semantic/tests/robots.test.ts +70 -0
- package/src/{share/semantic → semantic}/tests/split-sentences.test.ts +1 -1
- package/src/{share → semantic}/tests/twin-path.test.ts +1 -1
- package/src/semantic/tests/update-stamp.test.ts +102 -0
- package/src/signing/index.ts +13 -0
- package/src/signing/key.ts +139 -0
- package/src/signing/sign.ts +66 -0
- package/src/signing/types.ts +29 -0
- package/src/{share/slug → slug}/slug-url.ts +4 -1
- package/src/stack/run-tool.ts +108 -0
- package/src/stack/stack-checks.ts +124 -0
- package/src/stack/tests/run-tool.test.ts +138 -0
- package/src/stack/tests/stack-checks.test.ts +141 -0
- package/src/stack/tests/walk-files.test.ts +131 -0
- package/src/stack/walk-files.ts +114 -0
- package/src/surface/blueprint.ts +342 -66
- package/src/surface/decision-composer.ts +6 -1
- package/src/surface/geo.ts +6 -1
- package/src/surface/index.ts +11 -7
- package/src/surface/types.ts +2 -2
- package/src/surface/vitest.config.ts +1 -0
- package/src/tests/signing-core.test.ts +129 -0
- package/src/{share → text}/css-value-normalize.ts +6 -1
- package/src/text/string-utils.ts +24 -0
- package/src/{share → text}/tests/text-normalize.test.ts +5 -0
- package/src/{share → text}/text-normalize.ts +4 -3
- package/src/{share → text}/wrap-inline-numbers.ts +1 -1
- package/src/types/axiom-study.d.ts +36 -0
- package/src/types/hls-js-light.d.ts +21 -0
- package/src/types/qrcode-browser.d.ts +23 -0
- package/src/typography/fix.pbt.test.ts +208 -0
- package/src/typography/fix.ts +148 -0
- package/src/typography/index.ts +54 -0
- package/src/typography/locale-defaults.ts +97 -0
- package/src/typography/rules-tier1.test.ts +459 -0
- package/src/typography/rules-tier1.ts +925 -0
- package/src/typography/rules-tier2-locale.pbt.test.ts +190 -0
- package/src/typography/rules-tier2-locale.test.ts +286 -0
- package/src/typography/rules-tier2-locale.ts +399 -0
- package/src/typography/rules-tier2-structure.test.ts +330 -0
- package/src/typography/rules-tier2-structure.ts +378 -0
- package/src/typography/rules-tier3-advisory.test.ts +290 -0
- package/src/typography/rules-tier3-advisory.ts +239 -0
- package/src/typography/text-surface.test.ts +244 -0
- package/src/typography/text-surface.ts +448 -0
- package/src/index.ts +0 -14
- package/src/integration/port-barrel.ts +0 -105
- package/src/share/content/index.ts +0 -16
- package/src/share/content-discipline/index.ts +0 -14
- package/src/share/index.ts +0 -86
- package/src/share/legal/index.ts +0 -1
- package/src/share/redirects.ts +0 -54
- package/src/share/scripts/index.ts +0 -26
- package/src/share/semantic/jsonld/shared.ts +0 -31
- package/src/share/semantic/jsonld/types.ts +0 -18
- package/src/share/semantic/jsonld/website.ts +0 -27
- package/src/share/string-utils.ts +0 -19
- package/src/share/types/axiom-study.d.ts +0 -22
- package/src/share/types/hls-js-light.d.ts +0 -16
- package/src/share/types/qrcode-browser.d.ts +0 -18
- package/src/share/utility-registry.yaml +0 -36
- package/src/share/vitest.config.ts +0 -8
- package/src/surface/blueprint-schema.ts +0 -314
- package/src/surface/blueprint-types.ts +0 -256
- /package/src/{share/agent → agent}/api-catalog.ts +0 -0
- /package/src/{share/agent → agent}/capability.ts +0 -0
- /package/src/{share/agent → agent}/dns-aid.ts +0 -0
- /package/src/{share/agent → agent}/fleet-catalog.ts +0 -0
- /package/src/{share/agent → agent}/index.ts +0 -0
- /package/src/{share/agent → agent}/knowledge.ts +0 -0
- /package/src/{share/agent → agent}/mcp-card.ts +0 -0
- /package/src/{share/agent → agent}/omit-empty.ts +0 -0
- /package/src/{share/agent → agent}/openapi.ts +0 -0
- /package/src/{share/agent → agent}/proof.ts +0 -0
- /package/src/{share/agent → agent}/search.test.ts +0 -0
- /package/src/{share → attribution}/attribution-display.ts +0 -0
- /package/src/{share/scripts → client-scripts}/gsap-mountain-journey.ts +0 -0
- /package/src/{share/scripts → client-scripts}/gsap-parallax.ts +0 -0
- /package/src/{share/scripts → client-scripts}/gsap-reveal.ts +0 -0
- /package/src/{share/scripts → client-scripts}/gsap-stagger.ts +0 -0
- /package/src/{share/scripts → client-scripts}/live-photos.ts +0 -0
- /package/src/{share/scripts → client-scripts}/video-player.ts +0 -0
- /package/src/{share/content → content}/resolve-field-path.ts +0 -0
- /package/src/{share/content → content}/substitute-deep.ts +0 -0
- /package/src/{share → content}/tests/content-ref-index.test.ts +0 -0
- /package/src/{share/content-discipline → content-discipline}/types.ts +0 -0
- /package/src/{share → image-provider}/image-provider.ts +0 -0
- /package/src/{share/knowledge → knowledge}/claim.ts +0 -0
- /package/src/{share/knowledge → knowledge}/derivation.ts +0 -0
- /package/src/{share/knowledge → knowledge}/freshness.ts +0 -0
- /package/src/{share/knowledge → knowledge}/index.ts +0 -0
- /package/src/{share/knowledge → knowledge}/ledger.ts +0 -0
- /package/src/{share/knowledge → knowledge}/plan.ts +0 -0
- /package/src/{share/knowledge → knowledge}/source.ts +0 -0
- /package/src/{share/legal → legal}/translation-policy.ts +0 -0
- /package/src/{share/middleware → middleware}/language-redirect.ts +0 -0
- /package/src/{share/middleware → middleware}/tests/access-protection.test.ts +0 -0
- /package/src/{share → node}/fs/index.ts +0 -0
- /package/src/{share/tests/markdown-twin-provenance.test.ts → node/tests/markdown-twin-provenance-0613.test.ts} +0 -0
- /package/src/{share → offers}/offer-capacity.ts +0 -0
- /package/src/{share/onboarding-yaml/index.ts → onboarding/yaml.ts} +0 -0
- /package/src/{share → ontology}/tests/ontology-role-by-cosmic-name.test.ts +0 -0
- /package/src/{share/routes → routes}/tests/template-filter.test.ts +0 -0
- /package/src/{share/schemas → schemas}/claim-records.ts +0 -0
- /package/src/{share/schemas → schemas}/horizontal-align.ts +0 -0
- /package/src/{share/schemas → schemas}/icon-color.ts +0 -0
- /package/src/{share/schemas → schemas}/live-photo.ts +0 -0
- /package/src/{share/schemas → schemas}/material-credit.ts +0 -0
- /package/src/{share/schemas → schemas}/media.ts +0 -0
- /package/src/{share/schemas → schemas}/participant.ts +0 -0
- /package/src/{share/schemas → schemas}/print.ts +0 -0
- /package/src/{share/schemas → schemas}/section-background.ts +0 -0
- /package/src/{share/schemas → schemas}/section-body.ts +0 -0
- /package/src/{share/schemas → schemas}/section-cards.ts +0 -0
- /package/src/{share/schemas → schemas}/section-cta.ts +0 -0
- /package/src/{share/schemas → schemas}/section-header.ts +0 -0
- /package/src/{share/schemas → schemas}/section-image.ts +0 -0
- /package/src/{share/schemas → schemas}/section-motion.ts +0 -0
- /package/src/{share/schemas → schemas}/section-shell.ts +0 -0
- /package/src/{share/schemas → schemas}/section-stats.ts +0 -0
- /package/src/{share/schemas → schemas}/site-background.ts +0 -0
- /package/src/{share/semantic → semantic}/ai.ts +0 -0
- /package/src/{share/semantic → semantic}/block-extraction.ts +0 -0
- /package/src/{share/semantic → semantic}/breadcrumbs.ts +0 -0
- /package/src/{share/semantic → semantic}/build-page.ts +0 -0
- /package/src/{share/semantic → semantic}/feed.ts +0 -0
- /package/src/{share/semantic → semantic}/image-sitemap.ts +0 -0
- /package/src/{share/semantic → semantic}/jsonld/article.ts +0 -0
- /package/src/{share/semantic → semantic}/jsonld/collection-list.ts +0 -0
- /package/src/{share/semantic → semantic}/jsonld/video.ts +0 -0
- /package/src/{share/semantic → semantic}/llms-policy.ts +0 -0
- /package/src/{share/semantic → semantic}/markdown-hygiene.ts +0 -0
- /package/src/{share/semantic → semantic}/output-projection.ts +0 -0
- /package/src/{share/semantic → semantic}/page-markdown.ts +0 -0
- /package/src/{share/semantic → semantic}/price-marker-resolver.ts +0 -0
- /package/src/{share/semantic → semantic}/robots.ts +0 -0
- /package/src/{share/semantic → semantic}/update-stamp.ts +0 -0
- /package/src/{share/slug → slug}/heading-slugger.ts +0 -0
- /package/src/{share/slug → slug}/index.ts +0 -0
- /package/src/{share/slug → slug}/slug-id.ts +0 -0
- /package/src/{share/slug → slug}/strategies.ts +0 -0
- /package/src/{share/slug → slug}/tests/slug.test.ts +0 -0
- /package/src/{share → text}/tests/text-normalize.pbt.test.ts +0 -0
- /package/src/{share → text}/text-position.ts +0 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/*
|
|
2
|
+
<MODULE_CONTRACT>
|
|
3
|
+
<purpose>
|
|
4
|
+
RFC-0267: the WorkspaceIO port — the single seam through which kernel commands
|
|
5
|
+
touch the filesystem and spawn processes. `KernelRuntimeContext.io` carries an
|
|
6
|
+
adapter chosen by the executor: the default fs-backed adapter, a recording
|
|
7
|
+
adapter (universal `--dry-run`: intercepts writes/deletes, records intents,
|
|
8
|
+
touches nothing), or a read-only adapter (used for `mutatesState: false`
|
|
9
|
+
commands; throws KERNEL-META-01 on any attempted mutation). Adoption is
|
|
10
|
+
ratcheted — ambient `node:fs` imports keep working in unmigrated modules;
|
|
11
|
+
`kernel.io.lint` (IO-01) only gates new/migrated modules.
|
|
12
|
+
|
|
13
|
+
RFC-0326: `createDefaultIO` now returns `{ io, intents }` — the io writes to
|
|
14
|
+
real disk AND records every mutation as a `WriteIntent` for execution-report
|
|
15
|
+
surfacing (`filesModified`). This unifies the dry-run and real-run paths: both
|
|
16
|
+
capture intents, just from different adapters.
|
|
17
|
+
</purpose>
|
|
18
|
+
<non-goals>
|
|
19
|
+
<item>Do not abstract network access — filesystem and process execution only.</item>
|
|
20
|
+
<item>Do not enforce IO at the module-import level — that is kernel.io.lint's static check.</item>
|
|
21
|
+
</non-goals>
|
|
22
|
+
</MODULE_CONTRACT>
|
|
23
|
+
<KEY_DECISIONS>
|
|
24
|
+
<item>WorkspaceIO is the single filesystem seam — kernel commands never touch fs directly.</item>
|
|
25
|
+
</KEY_DECISIONS>
|
|
26
|
+
<CHANGE_SUMMARY>
|
|
27
|
+
<item>RFC-0267: initial implementation.</item>
|
|
28
|
+
<item>RFC-0267 follow-up: add readdir(path): Promise<DirEntry[]> to complete the port so directory-listing commands (e.g. sitemap.generate) migrate mechanically without importing node:fs for Dirent.</item>
|
|
29
|
+
<item>RFC-0326: createDefaultIO returns { io, intents } — writes touch real disk AND record WriteIntent[] for filesModified reporting.</item>
|
|
30
|
+
<item>RFC-1097: step 6 — compass.migrate codemod run
|
|
31
|
+
|
|
32
|
+
Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
|
|
33
|
+
<item>RFC-1097: sweep — werkstatt-engine clean
|
|
34
|
+
|
|
35
|
+
Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
|
|
36
|
+
</CHANGE_SUMMARY>
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
import {
|
|
40
|
+
readFile as fsReadFile,
|
|
41
|
+
mkdir as fsMkdir,
|
|
42
|
+
rm as fsRm,
|
|
43
|
+
readdir as fsReaddir,
|
|
44
|
+
stat,
|
|
45
|
+
} from "node:fs/promises";
|
|
46
|
+
import { glob as fsGlob } from "node:fs/promises";
|
|
47
|
+
import { spawn } from "node:child_process";
|
|
48
|
+
import { dirname } from "node:path";
|
|
49
|
+
import { writeFileAtomic } from "./fs-atomic.ts";
|
|
50
|
+
|
|
51
|
+
export interface ExecOptions {
|
|
52
|
+
cwd?: string;
|
|
53
|
+
timeoutMs?: number;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface ExecResult {
|
|
57
|
+
exitCode: number | null;
|
|
58
|
+
stdout: string;
|
|
59
|
+
stderr: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* A directory entry in a port-neutral shape — no `node:fs` `Dirent` leaks
|
|
64
|
+
* through the port, so command modules never need to import `node:fs` just to
|
|
65
|
+
* type a listing. `isFile`/`isDirectory` are plain booleans (not methods).
|
|
66
|
+
*/
|
|
67
|
+
export interface DirEntry {
|
|
68
|
+
name: string;
|
|
69
|
+
isFile: boolean;
|
|
70
|
+
isDirectory: boolean;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface WorkspaceIO {
|
|
74
|
+
readFile(path: string): Promise<string>;
|
|
75
|
+
readFileBytes(path: string): Promise<Uint8Array>;
|
|
76
|
+
exists(path: string): Promise<boolean>;
|
|
77
|
+
glob(pattern: string, opts?: { cwd?: string }): Promise<string[]>;
|
|
78
|
+
/** List a directory's immediate entries. Read-only; throws if the path is not a directory. */
|
|
79
|
+
readdir(path: string): Promise<DirEntry[]>;
|
|
80
|
+
/** Atomic by contract (rfc-0258). */
|
|
81
|
+
writeFile(path: string, content: string | Uint8Array): Promise<void>;
|
|
82
|
+
mkdir(path: string): Promise<void>;
|
|
83
|
+
rm(path: string, opts?: { recursive?: boolean }): Promise<void>;
|
|
84
|
+
exec(command: string, args: string[], opts?: ExecOptions): Promise<ExecResult>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function execImpl(command: string, args: string[], opts?: ExecOptions): Promise<ExecResult> {
|
|
88
|
+
return new Promise((resolve, reject) => {
|
|
89
|
+
const child = spawn(command, args, { cwd: opts?.cwd });
|
|
90
|
+
let stdout = "";
|
|
91
|
+
let stderr = "";
|
|
92
|
+
child.stdout?.on("data", (chunk) => {
|
|
93
|
+
stdout += chunk;
|
|
94
|
+
});
|
|
95
|
+
child.stderr?.on("data", (chunk) => {
|
|
96
|
+
stderr += chunk;
|
|
97
|
+
});
|
|
98
|
+
const timer = opts?.timeoutMs
|
|
99
|
+
? setTimeout(() => {
|
|
100
|
+
child.kill();
|
|
101
|
+
}, opts.timeoutMs)
|
|
102
|
+
: undefined;
|
|
103
|
+
timer?.unref?.();
|
|
104
|
+
child.on("close", (exitCode) => {
|
|
105
|
+
if (timer) clearTimeout(timer);
|
|
106
|
+
resolve({ exitCode, stdout, stderr });
|
|
107
|
+
});
|
|
108
|
+
child.on("error", (error) => {
|
|
109
|
+
if (timer) clearTimeout(timer);
|
|
110
|
+
reject(error);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* RFC-0326: the default, real fs-backed adapter. `writeFile` is atomic
|
|
117
|
+
* (rfc-0258). Now returns `{ io, intents }` matching `createRecordingIO`'s
|
|
118
|
+
* shape — the io writes to real disk; intents captures every mutation for
|
|
119
|
+
* `filesModified` reporting on execution reports.
|
|
120
|
+
*/
|
|
121
|
+
export function createDefaultIO(): { io: WorkspaceIO; intents: WriteIntent[] } {
|
|
122
|
+
const intents: WriteIntent[] = [];
|
|
123
|
+
const io: WorkspaceIO = {
|
|
124
|
+
async readFile(path) {
|
|
125
|
+
return fsReadFile(path, "utf8");
|
|
126
|
+
},
|
|
127
|
+
async readFileBytes(path) {
|
|
128
|
+
return fsReadFile(path);
|
|
129
|
+
},
|
|
130
|
+
async exists(path) {
|
|
131
|
+
try {
|
|
132
|
+
await stat(path);
|
|
133
|
+
return true;
|
|
134
|
+
} catch {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
async glob(pattern, opts) {
|
|
139
|
+
const results: string[] = [];
|
|
140
|
+
for await (const entry of fsGlob(pattern, { cwd: opts?.cwd })) {
|
|
141
|
+
results.push(entry);
|
|
142
|
+
}
|
|
143
|
+
return results;
|
|
144
|
+
},
|
|
145
|
+
async readdir(path) {
|
|
146
|
+
const entries = await fsReaddir(path, { withFileTypes: true });
|
|
147
|
+
return entries.map((entry) => ({
|
|
148
|
+
name: entry.name,
|
|
149
|
+
isFile: entry.isFile(),
|
|
150
|
+
isDirectory: entry.isDirectory(),
|
|
151
|
+
}));
|
|
152
|
+
},
|
|
153
|
+
async writeFile(path, content) {
|
|
154
|
+
await fsMkdir(dirname(path), { recursive: true });
|
|
155
|
+
await writeFileAtomic(path, content);
|
|
156
|
+
const bytes =
|
|
157
|
+
typeof content === "string" ? Buffer.byteLength(content, "utf8") : content.byteLength;
|
|
158
|
+
intents.push({ kind: "write", path, bytes });
|
|
159
|
+
},
|
|
160
|
+
async mkdir(path) {
|
|
161
|
+
await fsMkdir(path, { recursive: true });
|
|
162
|
+
intents.push({ kind: "mkdir", path });
|
|
163
|
+
},
|
|
164
|
+
async rm(path, opts) {
|
|
165
|
+
await fsRm(path, { recursive: opts?.recursive ?? false, force: true });
|
|
166
|
+
intents.push({ kind: "rm", path });
|
|
167
|
+
},
|
|
168
|
+
exec: execImpl,
|
|
169
|
+
};
|
|
170
|
+
return { io, intents };
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export interface WriteIntent {
|
|
174
|
+
kind: "write" | "mkdir" | "rm";
|
|
175
|
+
path: string;
|
|
176
|
+
bytes?: number;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Wraps a base adapter for universal `--dry-run`: reads pass through to the
|
|
181
|
+
* base adapter (so a command can still make write decisions based on real
|
|
182
|
+
* state), but writes/mkdir/rm are intercepted, recorded, and never touch disk.
|
|
183
|
+
*/
|
|
184
|
+
export function createRecordingIO(base: WorkspaceIO): { io: WorkspaceIO; intents: WriteIntent[] } {
|
|
185
|
+
const intents: WriteIntent[] = [];
|
|
186
|
+
const io: WorkspaceIO = {
|
|
187
|
+
readFile: base.readFile.bind(base),
|
|
188
|
+
readFileBytes: base.readFileBytes.bind(base),
|
|
189
|
+
exists: base.exists.bind(base),
|
|
190
|
+
glob: base.glob.bind(base),
|
|
191
|
+
readdir: base.readdir.bind(base),
|
|
192
|
+
async writeFile(path, content) {
|
|
193
|
+
const bytes =
|
|
194
|
+
typeof content === "string" ? Buffer.byteLength(content, "utf8") : content.byteLength;
|
|
195
|
+
intents.push({ kind: "write", path, bytes });
|
|
196
|
+
},
|
|
197
|
+
async mkdir(path) {
|
|
198
|
+
intents.push({ kind: "mkdir", path });
|
|
199
|
+
},
|
|
200
|
+
async rm(path) {
|
|
201
|
+
intents.push({ kind: "rm", path });
|
|
202
|
+
},
|
|
203
|
+
async exec() {
|
|
204
|
+
throw new Error("createRecordingIO: exec() is not supported under --dry-run.");
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
return { io, intents };
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export class KernelMetaError extends Error {
|
|
211
|
+
constructor(
|
|
212
|
+
readonly commandName: string,
|
|
213
|
+
readonly attemptedPath: string,
|
|
214
|
+
) {
|
|
215
|
+
super(
|
|
216
|
+
`KERNEL-META-01: command "${commandName}" declares mutatesState: false but attempted to write "${attemptedPath}". ` +
|
|
217
|
+
`Fix the command, or if the write is legitimate, set mutatesState: true and declare the path in writes (RFC-0266).`,
|
|
218
|
+
);
|
|
219
|
+
this.name = "KernelMetaError";
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Wraps a base adapter so every mutation throws KERNEL-META-01 naming the
|
|
225
|
+
* command and the attempted path. Used for every `mutatesState: false`
|
|
226
|
+
* command (proves the metadata trustworthy) and by the test harness.
|
|
227
|
+
*/
|
|
228
|
+
export function createReadOnlyIO(base: WorkspaceIO, commandName: string): WorkspaceIO {
|
|
229
|
+
return {
|
|
230
|
+
readFile: base.readFile.bind(base),
|
|
231
|
+
readFileBytes: base.readFileBytes.bind(base),
|
|
232
|
+
exists: base.exists.bind(base),
|
|
233
|
+
glob: base.glob.bind(base),
|
|
234
|
+
readdir: base.readdir.bind(base),
|
|
235
|
+
async writeFile(path) {
|
|
236
|
+
throw new KernelMetaError(commandName, path);
|
|
237
|
+
},
|
|
238
|
+
async mkdir(path) {
|
|
239
|
+
throw new KernelMetaError(commandName, path);
|
|
240
|
+
},
|
|
241
|
+
async rm(path) {
|
|
242
|
+
throw new KernelMetaError(commandName, path);
|
|
243
|
+
},
|
|
244
|
+
async exec(command, args) {
|
|
245
|
+
throw new KernelMetaError(commandName, `${command} ${args.join(" ")}`);
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
}
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
formatClaimSubject,
|
|
18
18
|
claimSubjectsEqual,
|
|
19
19
|
ClaimSubjectParseError,
|
|
20
|
-
} from "../
|
|
20
|
+
} from "../claim.ts";
|
|
21
21
|
|
|
22
22
|
test("parse: lang-scoped subject with simple field", () => {
|
|
23
23
|
const s = parseClaimSubject("business/de/location#residents");
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { test, expect } from "vitest";
|
|
11
|
-
import { normalizeForHash, hashSourceValue, derivedState } from "../
|
|
11
|
+
import { normalizeForHash, hashSourceValue, derivedState } from "../derivation.ts";
|
|
12
12
|
|
|
13
13
|
test("normalize: whitespace and markdown are insensitive", () => {
|
|
14
14
|
expect(normalizeForHash("Hello world")).toBe("Hello world");
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { test, expect } from "vitest";
|
|
11
|
-
import { addDuration, evaluateFreshness } from "../
|
|
11
|
+
import { addDuration, evaluateFreshness } from "../freshness.ts";
|
|
12
12
|
|
|
13
13
|
test("addDuration: months and years are calendar-correct", () => {
|
|
14
14
|
expect(addDuration("2026-01-15", "P1Y")).toBe("2027-01-15");
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
projectGraph,
|
|
19
19
|
projectTemporalSeo,
|
|
20
20
|
type ClaimEvent,
|
|
21
|
-
} from "../
|
|
21
|
+
} from "../ledger.ts";
|
|
22
22
|
|
|
23
23
|
function evt(partial: Partial<ClaimEvent>): ClaimEvent {
|
|
24
24
|
const subject = partial.subject ?? "business/de/location#residents";
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
defaultCriticality,
|
|
19
19
|
isRedTask,
|
|
20
20
|
type MaintenanceTask,
|
|
21
|
-
} from "../
|
|
21
|
+
} from "../plan.ts";
|
|
22
22
|
|
|
23
23
|
test("stableTaskId: idempotent for the same (subject, trigger)", () => {
|
|
24
24
|
const a = stableTaskId("business/de/offer#price.monthly", "expired");
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
<MODULE_CONTRACT>
|
|
3
|
+
<purpose>Legal share index — re-export the translation-policy surface for legal content consumers.</purpose>
|
|
4
|
+
<non-goals>
|
|
5
|
+
<item>Do not implement legal policy logic here — the policy lives in translation-policy.ts.</item>
|
|
6
|
+
</non-goals>
|
|
7
|
+
</MODULE_CONTRACT>
|
|
8
|
+
<CHANGE_SUMMARY>
|
|
9
|
+
<item>RFC-1097: sweep — tail packages clean
|
|
10
|
+
|
|
11
|
+
Sweep batch 3: rewrote ~95 purposes across werkstatt-knowledge, werkstatt-shared, godot-game, phaser-game, lifecycle-core, projektarchiv-*, portal-*, billing-*, typescript (CONTRACT-02/PURPOSE-02). Real KEY_DECISIONS on 5 godot utils, non-goals on 5 CONTRACT-03 files, headers on 4 headerless files, CS-07 history literal fix on 2 files. Policy: vitest.config.ts + test-fixtures testPatterns, worker-configuration.d.ts excludedPath. All non-site/engine packages now 0 diagnostics.</item>
|
|
12
|
+
</CHANGE_SUMMARY>
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export * from "./translation-policy.ts";
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
/*
|
|
2
2
|
<MODULE_CONTRACT>
|
|
3
3
|
<purpose>RFC-0899: Runtime access protection middleware for dev/alt subdomains. Checks Host header and requires Basic Auth with a 4-digit PIN for dev.* and alt.* hosts. Sets X-Robots-Tag headers to prevent indexing.</purpose>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<item>Check Host header against dev.* and alt.* patterns — pass through for main domain.</item>
|
|
7
|
-
<item>Require Basic Auth (username: warp, password: ACCESS_PIN env var) for dev/alt hosts.</item>
|
|
8
|
-
<item>Set X-Robots-Tag: noindex, nofollow, noai, noimageai on ALL dev/alt responses (including 401).</item>
|
|
9
|
-
<item>Use constant-time string comparison for auth check to prevent timing attacks.</item>
|
|
10
|
-
<item>Pass through when ACCESS_PIN is unset (allows new sites before protection is configured).</item>
|
|
11
|
-
</responsibilities>
|
|
4
|
+
|
|
5
|
+
|
|
12
6
|
<non-goals>
|
|
13
7
|
<item>Do not modify the HTML response body — only headers and access gating.</item>
|
|
14
8
|
<item>Do not activate for the main/production domain, even if the PIN secret is set on the main Worker.</item>
|
|
@@ -17,6 +11,12 @@
|
|
|
17
11
|
</MODULE_CONTRACT>
|
|
18
12
|
<CHANGE_SUMMARY>
|
|
19
13
|
<item>RFC-0899: Initial access protection middleware for dev/alt subdomains.</item>
|
|
14
|
+
<item>RFC-1097: step 6 — compass.migrate codemod run
|
|
15
|
+
|
|
16
|
+
Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
|
|
17
|
+
<item>RFC-1097: sweep — werkstatt-engine clean
|
|
18
|
+
|
|
19
|
+
Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
|
|
20
20
|
</CHANGE_SUMMARY>
|
|
21
21
|
*/
|
|
22
22
|
|
|
@@ -17,7 +17,12 @@ never crash rendering for a reason unrelated to the author's actual props.
|
|
|
17
17
|
</MODULE_CONTRACT>
|
|
18
18
|
<CHANGE_SUMMARY>
|
|
19
19
|
<item>RFC-0262: initial implementation.</item>
|
|
20
|
-
<item>
|
|
20
|
+
<item>RFC-1097: step 6 — compass.migrate codemod run
|
|
21
|
+
|
|
22
|
+
Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
|
|
23
|
+
<item>RFC-1097: sweep — werkstatt-engine clean
|
|
24
|
+
|
|
25
|
+
Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
|
|
21
26
|
</CHANGE_SUMMARY>
|
|
22
27
|
*/
|
|
23
28
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<purpose>Shared utility for scanning TypeScript source files for import specifiers
|
|
4
4
|
matching a pattern. Used by werkstatt.autonomy.validate, werkstatt.shared.validate,
|
|
5
5
|
and forge.autonomy.validate to avoid code duplication (Fowler: Duplicated Code).</purpose>
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
<non-goals>
|
|
8
8
|
<item>Does not define what is forbidden or exempt — callers provide the pattern and filter.</item>
|
|
9
9
|
<item>Does not scan test files — .test.ts and .spec.ts are always excluded.</item>
|
|
@@ -12,6 +12,13 @@ and forge.autonomy.validate to avoid code duplication (Fowler: Duplicated Code).
|
|
|
12
12
|
<CHANGE_SUMMARY>
|
|
13
13
|
<item>RFC-0868: extract shared directory-scanning utility from autonomy-validate and shared-validate.</item>
|
|
14
14
|
<item>RFC-0940: move to @warpgogol/werkstatt-shared so forge can import without depending on @warpgogol/werkstatt-engine.</item>
|
|
15
|
+
<item>RFC-1097: step 6 — compass.migrate codemod run
|
|
16
|
+
|
|
17
|
+
Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
|
|
18
|
+
<item>RFC-1099: export EXCLUDE_DIRS + EXCLUDE_SUFFIXES; extend EXCLUDE_DIRS with cache/build/test dirs (.turbo, .astro, .wrangler, .cache, .stryker-tmp, coverage, __tests__) so the werkstatt-typescript workspace model and all import-scan consumers share one canonical exclusion set.</item>
|
|
19
|
+
<item>RFC-1097: sweep — werkstatt-engine clean
|
|
20
|
+
|
|
21
|
+
Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
|
|
15
22
|
</CHANGE_SUMMARY>
|
|
16
23
|
*/
|
|
17
24
|
|
|
@@ -23,8 +30,21 @@ export interface ImportViolation {
|
|
|
23
30
|
specifier: string;
|
|
24
31
|
}
|
|
25
32
|
|
|
26
|
-
const EXCLUDE_DIRS = new Set([
|
|
27
|
-
|
|
33
|
+
export const EXCLUDE_DIRS = new Set([
|
|
34
|
+
"node_modules",
|
|
35
|
+
"tests",
|
|
36
|
+
"tests-handoff",
|
|
37
|
+
"dist",
|
|
38
|
+
"templates",
|
|
39
|
+
".turbo",
|
|
40
|
+
".astro",
|
|
41
|
+
".wrangler",
|
|
42
|
+
".cache",
|
|
43
|
+
".stryker-tmp",
|
|
44
|
+
"coverage",
|
|
45
|
+
"__tests__",
|
|
46
|
+
]);
|
|
47
|
+
export const EXCLUDE_SUFFIXES = [".test.ts", ".spec.ts"];
|
|
28
48
|
|
|
29
49
|
const IMPORT_PATTERN =
|
|
30
50
|
/(?:^|\n)\s*(?:import\s+(?:type\s+)?[^;]+?\s+from\s+|require\s*\(\s*)["'`]([^"'`]+)["'`]/g;
|
|
@@ -8,12 +8,13 @@
|
|
|
8
8
|
</MODULE_CONTRACT>
|
|
9
9
|
<CHANGE_SUMMARY>
|
|
10
10
|
<item>RFC-0767: relocated loadDerivedPrices from packages/ui to packages/share to break circular dependency. Node-only subpath export.</item>
|
|
11
|
+
<item>RFC-1074: return null for empty {} content — semantically equivalent to "no derived prices".</item>
|
|
11
12
|
</CHANGE_SUMMARY>
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
15
|
import { readFileSync } from "node:fs";
|
|
15
16
|
import { join } from "node:path";
|
|
16
|
-
import type { DerivedPriceEntry } from "
|
|
17
|
+
import type { DerivedPriceEntry } from "../../semantic/price-marker-resolver.ts";
|
|
17
18
|
|
|
18
19
|
export function loadDerivedPrices(
|
|
19
20
|
cwd: string = process.cwd(),
|
|
@@ -32,5 +33,6 @@ export function loadDerivedPrices(
|
|
|
32
33
|
}
|
|
33
34
|
throw err;
|
|
34
35
|
}
|
|
35
|
-
|
|
36
|
+
const parsed = JSON.parse(raw) as Record<string, DerivedPriceEntry[]>;
|
|
37
|
+
return Object.keys(parsed).length > 0 ? parsed : null;
|
|
36
38
|
}
|
|
@@ -19,7 +19,7 @@ over the normalized Markdown body (excluding frontmatter).
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
import { createHash } from "node:crypto";
|
|
22
|
-
import type { SemanticPageType } from "
|
|
22
|
+
import type { SemanticPageType } from "../../semantic/models.ts";
|
|
23
23
|
|
|
24
24
|
export interface MarkdownTwinSemanticMeta {
|
|
25
25
|
id: string;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { loadDerivedPrices } from "../semantic/derived-prices-loader.ts";
|
|
6
|
+
|
|
7
|
+
describe("loadDerivedPrices", () => {
|
|
8
|
+
it("returns null when file does not exist", () => {
|
|
9
|
+
const tmpDir = mkdtempSync(join(tmpdir(), "test-prices-"));
|
|
10
|
+
try {
|
|
11
|
+
const result = loadDerivedPrices(tmpDir);
|
|
12
|
+
expect(result).toBeNull();
|
|
13
|
+
} finally {
|
|
14
|
+
rmSync(tmpDir, { recursive: true });
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("returns null for empty {} content (RFC-1074)", () => {
|
|
19
|
+
const tmpDir = mkdtempSync(join(tmpdir(), "test-prices-"));
|
|
20
|
+
try {
|
|
21
|
+
const srcDir = join(tmpDir, "src");
|
|
22
|
+
mkdirSync(srcDir, { recursive: true });
|
|
23
|
+
writeFileSync(join(srcDir, "derived-prices.generated.json"), "{}\n");
|
|
24
|
+
const result = loadDerivedPrices(tmpDir);
|
|
25
|
+
expect(result).toBeNull();
|
|
26
|
+
} finally {
|
|
27
|
+
rmSync(tmpDir, { recursive: true });
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("loads and parses JSON when file exists", () => {
|
|
32
|
+
const tmpDir = mkdtempSync(join(tmpdir(), "test-prices-"));
|
|
33
|
+
try {
|
|
34
|
+
const srcDir = join(tmpDir, "src");
|
|
35
|
+
mkdirSync(srcDir, { recursive: true });
|
|
36
|
+
writeFileSync(
|
|
37
|
+
join(srcDir, "derived-prices.generated.json"),
|
|
38
|
+
JSON.stringify({
|
|
39
|
+
"https://warpgogol.com/id/offerings/hosting": [
|
|
40
|
+
{
|
|
41
|
+
chargeRef: "monthly",
|
|
42
|
+
targetCurrency: "USD",
|
|
43
|
+
amount: { value: "15", currency: "USD" },
|
|
44
|
+
trace: {
|
|
45
|
+
source: { amount: "10", currency: "EUR" },
|
|
46
|
+
rate: { value: "0.9", pair: "EUR/USD" },
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
}),
|
|
51
|
+
);
|
|
52
|
+
const result = loadDerivedPrices(tmpDir);
|
|
53
|
+
expect(result).not.toBeNull();
|
|
54
|
+
expect(Object.keys(result!)).toContain("https://warpgogol.com/id/offerings/hosting");
|
|
55
|
+
} finally {
|
|
56
|
+
rmSync(tmpDir, { recursive: true });
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
AUDIENCE_BY_PAGE_TYPE,
|
|
4
|
+
buildMarkdownTwin,
|
|
5
|
+
buildMarkdownTwinFrontmatter,
|
|
6
|
+
computeContentHash,
|
|
7
|
+
parseMarkdownTwinFrontmatter,
|
|
8
|
+
verifyMarkdownTwinHash,
|
|
9
|
+
type MarkdownTwinProvenance,
|
|
10
|
+
} from "../semantic/markdown-twin-provenance.ts";
|
|
11
|
+
|
|
12
|
+
const baseProvenance: MarkdownTwinProvenance = {
|
|
13
|
+
canonical: "https://example.com/de/page",
|
|
14
|
+
language: "de",
|
|
15
|
+
lastModified: "2024-01-15",
|
|
16
|
+
license: "CC-BY-4.0",
|
|
17
|
+
generator: "test",
|
|
18
|
+
sourceKind: "authored",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
describe("computeContentHash", () => {
|
|
22
|
+
it("produces sha256: prefix", () => {
|
|
23
|
+
expect(computeContentHash("body text").startsWith("sha256:")).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("is deterministic for same input", () => {
|
|
27
|
+
expect(computeContentHash("body")).toBe(computeContentHash("body"));
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("normalizes trailing whitespace", () => {
|
|
31
|
+
expect(computeContentHash("body\n\n")).toBe(computeContentHash("body"));
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("normalizes CRLF to LF", () => {
|
|
35
|
+
expect(computeContentHash("a\r\nb")).toBe(computeContentHash("a\nb"));
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe("buildMarkdownTwinFrontmatter", () => {
|
|
40
|
+
it("includes all core provenance fields", () => {
|
|
41
|
+
const fm = buildMarkdownTwinFrontmatter(baseProvenance, "sha256:abc");
|
|
42
|
+
expect(fm).toContain('canonical: "https://example.com/de/page"');
|
|
43
|
+
expect(fm).toContain('language: "de"');
|
|
44
|
+
expect(fm).toContain('lastModified: "2024-01-15"');
|
|
45
|
+
expect(fm).toContain('contentHash: "sha256:abc"');
|
|
46
|
+
expect(fm).toContain('license: "CC-BY-4.0"');
|
|
47
|
+
expect(fm).toContain('generator: "test"');
|
|
48
|
+
expect(fm).toContain('sourceKind: "authored"');
|
|
49
|
+
expect(fm).toContain('schema: "gogol.markdown-twin@2"');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("emits null for lastModified when null", () => {
|
|
53
|
+
const fm = buildMarkdownTwinFrontmatter(
|
|
54
|
+
{ ...baseProvenance, lastModified: null },
|
|
55
|
+
"sha256:abc",
|
|
56
|
+
);
|
|
57
|
+
expect(fm).toContain("lastModified: null");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("includes pageId when provided", () => {
|
|
61
|
+
const fm = buildMarkdownTwinFrontmatter(
|
|
62
|
+
{ ...baseProvenance, pageId: "about" },
|
|
63
|
+
"sha256:abc",
|
|
64
|
+
);
|
|
65
|
+
expect(fm).toContain('pageId: "about"');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("includes sourceInputs when provided", () => {
|
|
69
|
+
const fm = buildMarkdownTwinFrontmatter(
|
|
70
|
+
{ ...baseProvenance, sourceInputs: ["file1.md", "file2.md"] },
|
|
71
|
+
"sha256:abc",
|
|
72
|
+
);
|
|
73
|
+
expect(fm).toContain('sourceInputs:');
|
|
74
|
+
expect(fm).toContain('"file1.md"');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("includes semantic meta when provided", () => {
|
|
78
|
+
const fm = buildMarkdownTwinFrontmatter(
|
|
79
|
+
{
|
|
80
|
+
...baseProvenance,
|
|
81
|
+
semantic: {
|
|
82
|
+
id: "page-1",
|
|
83
|
+
route: "/de/page",
|
|
84
|
+
title: "Page",
|
|
85
|
+
type: "content",
|
|
86
|
+
domain: "content",
|
|
87
|
+
audience: "general",
|
|
88
|
+
lang: "de",
|
|
89
|
+
metaDescription: "A page",
|
|
90
|
+
priority: 0.7,
|
|
91
|
+
tags: ["tag1"],
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
"sha256:abc",
|
|
95
|
+
);
|
|
96
|
+
expect(fm).toContain('id: "page-1"');
|
|
97
|
+
expect(fm).toContain('type: "content"');
|
|
98
|
+
expect(fm).toContain("priority: 0.7");
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe("buildMarkdownTwin", () => {
|
|
103
|
+
it("produces frontmatter + body", () => {
|
|
104
|
+
const twin = buildMarkdownTwin("# Hello\n\nWorld", baseProvenance);
|
|
105
|
+
expect(twin.startsWith("---\n")).toBe(true);
|
|
106
|
+
expect(twin).toContain("# Hello");
|
|
107
|
+
expect(twin).toContain("World");
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe("parseMarkdownTwinFrontmatter", () => {
|
|
112
|
+
it("round-trips buildMarkdownTwin output", () => {
|
|
113
|
+
const body = "# Hello\n\nWorld";
|
|
114
|
+
const twin = buildMarkdownTwin(body, baseProvenance);
|
|
115
|
+
const parsed = parseMarkdownTwinFrontmatter(twin);
|
|
116
|
+
expect(parsed).not.toBeNull();
|
|
117
|
+
expect(parsed!.frontmatter.canonical).toBe("https://example.com/de/page");
|
|
118
|
+
expect(parsed!.frontmatter.language).toBe("de");
|
|
119
|
+
expect(parsed!.body).toBe("# Hello\n\nWorld\n");
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it("returns null for no frontmatter", () => {
|
|
123
|
+
expect(parseMarkdownTwinFrontmatter("just text")).toBeNull();
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
describe("verifyMarkdownTwinHash", () => {
|
|
128
|
+
it("verifies correct hash", () => {
|
|
129
|
+
const twin = buildMarkdownTwin("# Hello", baseProvenance);
|
|
130
|
+
expect(verifyMarkdownTwinHash(twin)).toBe(true);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it("fails for tampered body", () => {
|
|
134
|
+
const twin = buildMarkdownTwin("# Hello", baseProvenance);
|
|
135
|
+
const tampered = twin.replace("# Hello", "# Tampered");
|
|
136
|
+
expect(verifyMarkdownTwinHash(tampered)).toBe(false);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
describe("AUDIENCE_BY_PAGE_TYPE", () => {
|
|
141
|
+
it("maps home to general", () => {
|
|
142
|
+
expect(AUDIENCE_BY_PAGE_TYPE.home).toBe("general");
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("maps projects to developer", () => {
|
|
146
|
+
expect(AUDIENCE_BY_PAGE_TYPE.projects).toBe("developer");
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it("maps legal to business_owner", () => {
|
|
150
|
+
expect(AUDIENCE_BY_PAGE_TYPE.legal).toBe("business_owner");
|
|
151
|
+
});
|
|
152
|
+
});
|