packages feed

shikumi-okf-0.2.0.0: profile/shikumi.dhall

-- OKF profile for shikumi program documentation bundles.
--
-- A profile is a small Dhall descriptor that layers house conventions on top of
-- OKF: which `type` strings are allowed, which frontmatter keys are required, the
-- `resource:` URI scheme, and the file layout. `okf validate --profile` (and
-- mori, at register/observe time) check a generated bundle against it, so every
-- application's program documentation stays consistent. Profiles are NOT part of
-- the OKF standard; a bundle that deviates remains fully OKF-conformant.
--
-- This bundle layout is produced by the `shikumi-okf` package: one `Shikumi App`
-- concept at `apps/<app>` linking to one `Shikumi Program` concept per program at
-- `programs/<name>`, with `shikumi://` resource URIs.
--
-- The schema is imported through okf's published entry point (`package.dhall`) at
-- a pinned tag, protected by a Dhall integrity hash. It is deliberately NOT a
-- relative path into a sibling `okf` checkout: that spelling resolves against
-- whatever is in someone's working tree, so this descriptor silently stopped
-- type-checking when okf's schema moved ahead of the pinned `okf-core` release,
-- and it cannot work at all for anyone who installs this package from Hackage.
--
-- The hash covers the fully resolved, normalized expression, so it pins every
-- transitive `./Profile.dhall`, `./defaults/*`, and `./mk/*` the entry point
-- pulls in — not just the one file. Moving the tag therefore fails the load
-- loudly instead of changing the schema underneath this profile.
--
-- Dhall serves a hashed import from `~/.cache/dhall` when it is present, so only
-- the first resolution on a machine needs the network. To move to a new okf
-- release, bump the tag and refresh the hash with:
--
--     echo 'https://raw.githubusercontent.com/shinzui/okf/<tag>/okf-core/dhall/package.dhall' | dhall hash
--
-- Every record below is written with okf's record-completion defaults (`::`) and
-- `mk` constructors, so a future additive, defaulted schema field leaves this
-- descriptor working unchanged.
--
-- Types are closed (`allowUnknownTypes = False`): a shikumi bundle contains only
-- the two concept types `shikumi-okf` generates. Top-level frontmatter is closed
-- too (`allowUnknownFields = False`). That is safe because a closed key set still
-- always admits the six core OKF keys — `type`, `title`, `description`,
-- `timestamp`, `resource`, `tags` — and those six are exactly what the generator
-- emits: its frontmatter comes from three helpers (`okfCommon`, `setResource`,
-- `setTags`) and there is no mechanism for an author to inject other keys. So
-- closing the set cannot reject a generated document; what it catches is a
-- hand-added stray key in a bundle that is supposed to be generated. No `idField`
-- is declared, so document-handle checks stay off: shikumi concepts are addressed
-- by concept id and `shikumi://` resource, not by stable handles.
--
-- Value shapes are checked, not just key presence: every single-valued key is
-- declared `Cardinality.Scalar`, so `title: [a, b]` is a violation rather than a
-- silent pass.
--
-- This profile targets OKF v0.2 and requires its bundles to say so
-- (`requireBundleVersion = Some "0.2"`). The specification makes the root
-- `okf_version` declaration a MAY, so okf itself never asks for it — and an
-- undeclared bundle quietly opts out of every v0.2-only check, including the
-- report of concepts still carrying the superseded `timestamp`. `shikumi-okf`
-- writes the declaration on every bundle it generates, so requiring it here
-- costs a conformant producer nothing and catches a bundle that drifted back.
--
-- Provenance is the v0.2 `generated` family rather than the v0.1 `timestamp`
-- key, which this profile no longer declares at all: `allowUnknownFields` is
-- `False`, so a stray `timestamp` is now reported as an undeclared key on top of
-- whatever the core v0.2 checks say about it. `generated` sits under
-- `recommended` rather than `required` because a caller may pass
-- `generated = Nothing` to disclaim provenance rather than have the generator
-- invent it; the consequence is that `okf validate --strict` advises on such a
-- bundle while an ordinary run does not.
--
-- Rules that are true of one document kind only live in that kind's own
-- `frontmatter` record, which okf merges with the profile-wide one. `resource` is
-- declared there rather than profile-wide: the generator always emits it for both
-- kinds, so per-type `required` states the truth precisely, and declaring the same
-- key in both scopes would yield two overlapping presence clauses for no gain. Its
-- `UriWithScheme "shikumi"` format parses the value, so `resource: not-a-uri` is a
-- violation; that overlaps harmlessly with the `resourceScheme` check each type
-- rule already performs. `tags` is recommended on `Shikumi Program` only, as a
-- `List`, because only program documents carry it and only when the author
-- declared any.
let okf =
      https://raw.githubusercontent.com/shinzui/okf/v0.5.0.0/okf-core/dhall/package.dhall
        sha256:02a821061043976b0ec0d60745a792f5f536e5f5d0db43bc990890ab0f5af0e3

let field = okf.mk.FieldRule

let nested = okf.mk.NestedFieldRule

let scalarOf =
      \(name : Text) ->
      \(prose : Text) ->
      \(fmt : Optional okf.FieldFormat) ->
        okf.defaults.FieldRule::{
        , field = name
        , description = Some prose
        , cardinality = okf.Cardinality.Scalar
        , format = fmt
        }

-- OKF v0.2 §5.2: `by` is REQUIRED within the `generated` mapping, `at` is
-- optional. `at` is declared `optional` rather than `recommended` because
-- shikumi-okf omits it unless the caller supplies a time — that omission is what
-- keeps regenerating an unchanged manifest byte-identical — so demanding it
-- under `--strict` would advise against the generator's own determinism.
let generatedMembers =
      okf.defaults.NestedRules::{
      , required =
        [     nested.actor "by"
          //  { description = Some
                  "§7. The actor that produced this document: `<producer>/<version>`, `human:<id>`, or `process:<id>`."
              }
        ]
      , optional =
        [     nested.rfc3339Utc "at"
          //  { description = Some
                  "When the document was generated, if the caller supplied a time."
              }
        ]
      }

let appType =
      okf.defaults.TypeRule::{
      , type = "Shikumi App"
      , description = Some
          "One application that ships shikumi programs; links to every program it exposes."
      , frontmatter = okf.defaults.FrontmatterRules::{
        , required =
          [ scalarOf
              "resource"
              "The `shikumi://<namespace>/<app>` URI this concept documents."
              (Some (okf.FieldFormat.UriWithScheme "shikumi"))
          ]
        }
      , pathPattern = Some "apps/*"
      , resourceScheme = Some "shikumi"
      }

let programType =
      okf.defaults.TypeRule::{
      , type = "Shikumi Program"
      , description = Some
          "One shikumi program: its signature, adapter, and declared metadata."
      , frontmatter = okf.defaults.FrontmatterRules::{
        , required =
          [ scalarOf
              "resource"
              "The `shikumi://<namespace>/<app>/programs/<name>` URI this concept documents."
              (Some (okf.FieldFormat.UriWithScheme "shikumi"))
          ]
        , recommended = [ field.list "tags" ]
        }
      , pathPattern = Some "programs/*"
      , resourceScheme = Some "shikumi"
      }

in  okf.defaults.Profile::{
    , name = "shinzui-shikumi"
    , description = Some
        "House conventions for OKF bundles generated from shikumi programs by the shikumi-okf package."
    , okfVersion = "0.2"
    , requireBundleVersion = Some "0.2"
    , frontmatter = okf.defaults.FrontmatterRules::{
      , required =
        [ scalarOf
            "type"
            "The OKF concept type: `Shikumi App` or `Shikumi Program`."
            (None okf.FieldFormat)
        , scalarOf
            "title"
            "Human-readable name of the app or program."
            (None okf.FieldFormat)
        ]
      , recommended =
        [ scalarOf
            "description"
            "What the app or program is for, in one or two sentences."
            (None okf.FieldFormat)
        ,     field.record "generated" generatedMembers
          //  { description = Some
                  "OKF v0.2 §5.2. How this document was produced. `shikumi-okf` writes `by: process:shikumi-okf` on every concept it generates. Supersedes the v0.1 `timestamp` key, which this profile no longer declares: a bundle declaring `okf_version: \"0.2\"` that still carried `timestamp` would be reported as retaining a superseded key."
              }
        ]
      }
    , allowUnknownTypes = False
    , allowUnknownFields = False
    , types = [ appType, programType ]
    }