packstructspec v1
HomeSpecLintDocs
Menu
  • Home
  • Spec
  • Lint
  • Docs
  • GitHub
Legal
  • Terms
  • Privacy

Normative, frozen at schemaVersion 1

The spec

The long-form normative text is spec/SPEC.md in the repo (and mirrored at docs.creadev.org/packstruct). This page is the readable surface.

Directories

Packs live at packs/public/<pack-name>/, carrying a required pack.json plus the entry file it declares. That is the whole surface.

The manifest, v1

Drawn from what crashtest's eight production packs already ship - verified pack-by-pack, no fleet migration.

FieldTypeRules
schemaVersionintegerMUST be 1; bumps are additive-first (v2 adds optional fields; removals are a major bump with a migration note)
namestringkebab-case, MUST match its directory - mismatch is a load error, never a silent success
descriptionstringone line, human-readable
versionstringdotted semver-ish MAJOR.MINOR[.PATCH]
entrystringrelative path inside the pack, MUST exist - declaring a file that doesn't ship is an instant refusal, not a stack trace (crashtest#16)
armedByKeystring?OPTIONAL. Present = the host MAY require an arming key before activation. Absent = the host's own lifecycle governs

Host-owned keys the engine also recognizes (env, plugins, package) are acknowledged by name and never refused - the linter is strict against spec norms and only those norms.

Profiles (declared, not hidden)

  • scenario - crashtest: default export { register(ctx) }, hostile scenarios against a transport, so it requires the host's isolation guarantees (fake transport), and may use the armed-key ceremony
  • check - poststruct: default export { checks: [Check, ...] }, declarative pure-reading verifiers over files on disk; no transport, no network by default

A pack declares nothing about profiles - the host declares which profile it loads. The scenario contract links to crashtest's reference rather than copying it (doc drift beats indirection).

Lifecycle rules (spec-fixed everywhere)

  • Packs are explicit - a pack runs only because the host's config enumerates it; no implicit discovery
  • Ids are namespaced by pack slug inside the host's id space; cross-namespace collision at load = refuse to start
  • Local-path sources only in v1; remote/npm sources arrive as an explicit additive spec version, never silently
  • Self-audit fixtures ship with every pack - test/fixtures/ proving the pack does what it claims; engines adopt this first, the spec formalizes after

App-owned (declared in the app's README, not the spec): arming ceremony details, execution sandbox, scheduling, output formats.

Versioning

Each app pins the spec version it implements ("implements: "packstruct@1") in its README. Engine changes land as code first; the spec formalizes after - never the reverse.

Read SPEC.md

📦 packstruct - the shared /packs spec · part of the struct familyDocsGitHubTermsPrivacy© 2026 Creadev.org