Jekt™ Specification

Last Updated: 2026-06-12

Copyright © 2026 GlobalMentor, Inc.

This work is licensed under the Creative Commons Attribution 4.0 International License (CC BY 4.0).

"Jekt" is a trademark of GlobalMentor, Inc.

1. Introduction

1.1 Purpose

This document specifies Jekt, a context architecture for software projects that uses the file system as its storage substrate. The specification defines the terminology, structural conceptual model, repository structure, naming conventions, identifiers, references, metadata vocabulary, storage formats, and coordination protocols that constitute a Jekt-conformant repository, together with the conformance criteria for tools that read or write such repositories.

The worldview that motivates this design, the principles that constrain its evolution, and the conceptual frame within which the structural model sits are specified in the companion document Jekt Design Principles. This specification confines itself to mechanical definitions and operational rules.

1.2 Scope

This specification covers:

This specification does not cover:

1.3 Document Status

This is a living document. Sections marked (provisional) describe positions that are settled in direction but whose exact contours may still shift. Sections marked (TBD) describe areas not yet sufficiently settled to specify.

1.4 Document Conventions

The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, NOT RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in BCP 14 (RFC 2119, RFC 8174) when, and only when, they appear in all capitals.

Sections and individual passages labeled (non-normative) are informational and do not create requirements. Examples in this specification are (non-normative).

1.5 Relationship to Other Jekt Documents

This specification is one of two foundational Jekt documents. The other is the Jekt Design Principles. Together they carry the full content of Jekt: this specification defines what Jekt is mechanically and normatively; the Jekt Design Principles defines what Jekt is as an idea and what it should remain as it evolves. Worldview material, comparative positioning against adjacent systems, and the conceptual frame that motivates the structural model live in the Jekt Design Principles, not here.

The Jekt Primer and Jekt User Guide are derived non-normative projections of the foundational pair. The Primer orients newcomers, deriving every statement of what Jekt is, why it exists, and what makes it different from claims in the foundational pair. The User Guide gives task-oriented usage guidance derived from this specification and from the tools built on it.

2. Terminology

The following terms have specific meanings in this specification.

Artifact. Any file or directory inside a .jekt/ directory that represents project tracking content or semantic working context.

Chunk. A coherent grouping of work, typically within a plan or within a sequence of commits. A chunk is a workflow concept, not a stored artifact; Jekt does not define a chunks/ directory. (provisional)

Comment. (provisional) A timestamped observation, update, or discussion entry attached to a ticket, stored as a file in the ticket's comments/ directory. Comments occupy a narrower role in Jekt than in traditional issue trackers: where a system such as Jira has only one free-form append-only artifact and therefore accumulates minutes, summaries, designs, investigations, and conversations under "comments," Jekt provides semantically appropriate artifacts for most of those purposes. Comments therefore serve primarily for team interaction and discussion around the ticket.

Description. The prose and metadata that establish an entity's scope and intent. Materialized for an entity (ticket, release, or project) as up to two files in the entity's directory: a Markdown prose file named description - {Label}.md and a YAML metadata file named description.yaml. Both files are optional; their absence asserts no description rather than an empty description.

Design. A document that captures durable reasoning about why a system is shaped as it is. Stored in the ticket's designs/ subdirectory. A design document is identified by topic, not by time.

Identifier. A machine-readable handle that uniquely names an entity within a defined scope. Ticket identifiers, release identifiers, project slugs, and timestamp-based comment identifiers are all identifiers in Jekt.

Jekt repository. A working directory containing a .jekt/ directory at its root.

Label. A short, human-readable string that serves as an entity's or document's lexical handle for use in filenames, links, displays, and other contexts where an identifier alone is insufficient. A label is distinct from an identifier (which is a stable machine handle), from a heading title (which may be longer and richer), and from any stored metadata property. See §5.3 for the label form and character constraints.

Minutes. A curated chronological record of significant events and realizations in the evolution of work on a ticket — the mental-state diff, not the code diff. Minutes preserve the knowledge that would otherwise be lost when conversations are summarized or when work is continued by another contributor weeks or months later. Stored as minutes.md at the ticket directory root.

Plan. An execution-oriented working document that captures the approach to a unit of implementation work. Stored in the ticket's plans/ subdirectory. Plans are ephemeral semantic working context.

Project. (provisional) The scope within which Jekt artifacts are organized. In the typical case a project corresponds to one Jekt repository and is declared by a directory under .jekt/projects/ (§4.4). Multiple project declarations within a single repository are supported structurally; whether they represent multiple projects, components of one project, imported tracker projects, or some other relationship is not defined by this specification.

Project slug. (provisional) The slug portion of a ticket identifier (e.g., foo in foo-123) and, equivalently, the name of a project directory under .jekt/projects/ when the project is declared. The slug scopes ticket numbering: ticket numbers under one slug are independent of ticket numbers under any other slug. A project slug is normally lowercase (see §5.1). A slug is declared when .jekt/projects/{slug}/ exists and in use when any ticket directory matches {slug}-{number}; declaration is optional (§4.4).

Reference. A textual citation of a Jekt entity, typically using the Markdown shortcut reference link syntax [FOO-123].

Release. A grouping of tickets associated with a delivery milestone. Releases are identified by strings used as directory names under .jekt/releases/; common forms are version strings (e.g., 2.0.3) and, in multi-project repositories, slug-prefixed version strings (e.g., foo-2.0.3). See §6.3.

Story. (provisional) A pre-ticket entity for exploratory, conversational, decomposition-oriented work, as in user story mapping. A story facility is not yet specified.

Summary. A retrospective synthesis of what was accomplished in a ticket, produced near ticket completion. Stored as summary.md at the ticket directory root.

Tag. A categorical classifier attached to a ticket — a short keyword used for grouping, filtering, and discovery. Stored as a value in tags.lst at the ticket directory root (§8.4).

Ticket. An identified, assignable tracker for a unit of work. Each ticket has a unique identifier and a corresponding directory under .jekt/tickets/.

TODO. (provisional) A low-ceremony capture of deferred work, recorded near its provenance. A TODO is not yet a ticket and may never become one; it may be promoted to a ticket when its scope is clear, promoted to a story when it warrants decomposition conversation, or discarded.

Vocabulary. The set of metadata property names and value conventions defined by Jekt. As currently specified, the Jekt metadata layer is a vocabulary in this sense: properties carry prose definitions and lightweight value conventions, not formal axioms. This characterization is scoped to the current metadata layer and does not preclude future Jekt layers that adopt richer semantic mechanisms.

3. Structural Conceptual Model

This section defines the mechanical model of Jekt's entities, their relationships, and their lifecycles. It says what the entities are and how they relate. The worldview-level conceptual frame within which this structural model sits — why the model takes this shape — is specified in the Jekt Design Principles.

3.1 Entity Hierarchy

A Jekt repository contains a .jekt/ directory whose top-level subdirectories define the entity types Jekt recognizes:

Project (the repository as a whole)
  ├── Tickets       (units of work)
  ├── Releases      (delivery groupings)
  └── Stories       (pre-ticket exploration) — provisional

Tickets are the primary entity. Releases group tickets for delivery. Stories, when specified, are pre-ticket exploratory entities.

3.2 Artifact Roles and Relationships

Within a ticket, artifacts fall into role categories:

Identity by ticket implies the artifact is a singleton, one per ticket. Identity by time implies the artifact is append-only and ordered chronologically. Identity by topic implies the artifact is a living document, refined over time. Identity by date + topic implies the artifact is chronologically positioned yet a living document.

3.3 Lifecycle and Summarization Boundaries

Jekt organizes work as layered semantic units. Each layer is a natural summarization boundary:

Project
  └── Tickets (committed units of work)
        ├── Description, Minutes, Designs, Comments, Plans, TODOs, Summary
        └── Commits (accepted changes; recorded in Git, not Jekt)

Commits summarize code changes. Tickets summarize coherent units of work. The project summarizes its current state through the aggregate of its tickets.

Plans serve as ephemeral semantic working context between conversation and durable artifacts. They help carry working semantics from conversation toward durable, role-bearing records: a plan produces commits, may yield design documents and minutes entries, and may surface TODOs.

4. Repository Structure

4.1 The .jekt/ Directory

A Jekt repository contains a directory named .jekt/ at the root of the working tree. The presence of this directory marks the repository as Jekt-enabled.

A Jekt repository MUST contain a .jekt/ directory at its root.

4.2 Tickets Directory

Ticket directories live under .jekt/tickets/. Each ticket is a directory whose name is the ticket identifier in canonical (lowercase) form. When multiple project slugs coexist in a single repository, all ticket directories sit as siblings under this single .jekt/tickets/ directory; there is no per-slug subdivision (provisional).

.jekt/
  tickets/
    foo-123/
      description - Auth Token Refresh.md
      description.yaml
      minutes.md
      summary.md
      tags.lst
      jekt/
        releases.lst
      todo - Extract Byte Utils.md
      plans/
        2026-02-04-token-rotation.md
      designs/
        Token Rotation Strategy.md
      comments/
        2026-02-03T21-45-00Z.md

4.3 Releases Directory

Release directories live under .jekt/releases/. Each release is a directory whose name is the release identifier (§6.3).

.jekt/
  releases/
    2.0.3/
      description - Spring Stability.md
      description.yaml

A release directory holds release-specific content (description prose and metadata, release notes, and any ad-hoc work products) following the same conventions as other entity descriptions (§5.4, §9.2). Tickets assigned to a release record their assignment in their own jekt/releases.lst file; the release directory does not list its tickets.

4.4 Projects Directory

Project declarations live under .jekt/projects/. Each declared project is a directory whose name is the project slug (§5.1, §6.2).

.jekt/
  projects/
    foo/
      description - Foobar Framework.md
      description.yaml

A project directory holds the project's own description prose and metadata, following the same conventions as other entity descriptions (§5.4, §9.2).

A project slug is declared when .jekt/projects/{slug}/ exists. A project slug is in use when any ticket directory under .jekt/tickets/ matches {slug}-{number} (§6.1). A slug MAY be in use without being declared; declaration is OPTIONAL and adds project-level metadata and prose rather than authorizing the slug's use. A repository with no .jekt/projects/ directory at all is a legal state; the active project slug, if any, is then inferred from existing ticket directories.

For new ticket creation in a repository that declares exactly one project, the declared slug is the active slug. For a repository with multiple declared projects, the active slug for a given ticket is determined by the subject matter of the ticket or by explicit input from the caller; this specification does not prescribe a default-project mechanism.

The vast majority of Jekt repositories are expected to declare a single project. Multiple project declarations within a single repository are supported structurally; the operational details (drop-down listings of declared projects, project-scoped release identifiers, project-level configuration interactions) are deferred pending real-world experience.

Status: (provisional) The .jekt/projects/{slug}/ form is the current working convention. The relationship between a project slug and the broader notion of “project” (which may span repositories, components, or organizational boundaries) is undefined by this specification (§2).

4.5 Other Project-Level Locations

The following additional project-level locations are defined:

4.6 Required vs. Optional Elements

A Jekt repository MUST contain .jekt/.

All subdirectories of .jekt/, including tickets/, releases/, and projects/, are OPTIONAL until they contain content.

Within any entity directory (ticket, release, or project), no individual artifact file is REQUIRED. An entity directory MAY exist with no contents beyond its name; metadata and prose accrue as they become meaningful. In particular, an entity directory containing only an empty description.yaml is a valid state asserting that the entity exists with no properties yet recorded and no prose description yet written (§9.2).

Tools MUST tolerate the presence of files and directories within .jekt/ that this specification does not recognize.

5. Naming Conventions

5.1 Casing Rules

A Jekt ticket identifier has a canonical lowercase form. In that form, the project slug is lowercase.

The canonical form SHOULD be used wherever a ticket identifier appears as a machine identifier, including:

Human-facing references MAY use an uppercase project slug for readability, including in:

As an exception, a repository migrated from an external tracker MAY retain uppercase project slugs in machine-identifier contexts where the original casing has documentary value. Such a repository SHOULD declare the project under .jekt/projects/ using the slug as actually used (for example, .jekt/projects/FOO/), so the intended casing is explicit. Retained uppercase casing is a repository convention and does not make differently cased identifiers equivalent.

CommonMark reference-label resolution is case-insensitive, so a Markdown reference of the form [FOO-123] resolves to a definition with the label [foo-123] regardless of case. This is a Markdown link-resolution rule only; Jekt identifiers themselves are caseful.

5.2 Prescribed Filenames

A prescribed filename is one whose exact name is defined by this specification. Prescribed filenames use lowercase, kebab-case:

Prescribed filenames within a jekt/ namespace subdirectory follow the same convention:

5.3 Labels

A label is a short, human-readable string that serves as an entity's or document's lexical handle for use in filesystem paths, links, displays, and any other context where an identifier alone is insufficient. The label is distinct from the entity's identifier (a stable machine handle), from the heading title of the description document (which may be longer and richer; see §7.5), and from any metadata stored as a property (a label is not stored as a property in description.yaml).

A label SHOULD be in Title Case and SHOULD be short — approximately 40 characters as a soft cap, ideally two to four words. The label captures the central concept; when more is needed, the additional material belongs in the heading title or in the prose, not in the label.

A label SHOULD use a conservative character set so that the same string flows unmodified through filenames, URLs, shell arguments, and display surfaces without escaping or transformation:

Labels appear in filenames in two positions:

The label is materialized in the filesystem today, but the concept is general: future Jekt surfaces — cross-reference autocomplete, drop-down listings, breadcrumb chrome, or any other display of a short handle for an entity — are expected to draw on the same label.

Status: (provisional) The character constraints reflect cross-context safety across the contexts Jekt currently uses or is likely to use; a future revision may tighten or relax them as field experience accumulates.

5.4 Prefixed Filenames

A prefixed filename combines a Jekt-prescribed role prefix in lowercase with the file's label (§5.3), separated by - (space, hyphen, space):

The prefix identifies the file's role within the entity directory; the label identifies its subject. The description - {Label}.md form applies uniformly across all entity descriptions — tickets, releases, and projects — so that the convention generalizes without per-entity-type special cases.

The prose description file is OPTIONAL. An entity directory containing only a description.yaml (which itself MAY be empty; see §9.2) without a description - {Label}.md file is a valid state, asserting that the entity exists with no prose description yet recorded. When a prose description is added, it MUST carry a label; the bare form description.md is not used. This preserves the filesystem affordance the label provides and avoids per-entity inconsistency about whether the label is present.

Ad-hoc files at an entity root often carry self-describing prefixes (e.g., report - {Label}.md, analysis - {Label}.md) following the same prefix-plus-label pattern when the role naturally admits multiple instances. Singleton ad-hoc files whose role is fully self-evident from the filename alone may use bare names (e.g., readme.md, migration.md). The open-ended set of such filenames is by convention, not specification.

Status: (provisional) The labeled-description form is the current working convention. Retaining it instead of the simpler description.md form reflects the value of surfacing a short identifying handle in plain file listings, file pickers, IDE tabs, and abbreviated file listings shown to LLMs — a native-tooling affordance aligned with Jekt's foundational commitments. Deterministic identification is preserved by the description - prefix, with glob-prefix access (description - *.md) used when needed.

5.5 Labeled Filenames

A labeled filename uses the document's label (§5.3) as the entire filename, with no role prefix. Labeled filenames appear in subdirectories whose role establishes the file's category:

The label follows the form and character constraints of §5.3.

5.6 Dated and Timestamped Filenames

Plans use a date prefix and a kebab-case slug:

plans/2026-02-04-module-reorg.md

The date is in YYYY-MM-DD form. The slug describes the plan's subject.

Comments use a UTC timestamp in filesystem-safe ISO 8601 form:

comments/2026-02-03T21-45-00Z.md

Colons in the time portion are replaced with hyphens. The trailing Z denotes UTC. A date-only form (comments/2026-02-12.md) MAY be used when the precise time is not known; both forms sort correctly together. When a date-only filename would collide with an existing comment on the same day, the new comment MUST supply a time to disambiguate.

Comment filenames carry no descriptive suffix beyond the timestamp. Comments are inherently sequential and the first content line of the file conveys the topic.

5.7 Subdirectory Conventions

The ticket directory is organized by artifact role: subdirectories house collections of Jekt-defined artifact types; the ticket root houses singletons and ad-hoc work products. This places each multi-instance artifact type in its own subdirectory while keeping singleton artifacts (description, minutes, summary) and ad-hoc work products immediately visible at the root.

Subdirectory names are plural and lowercase:

Ad-hoc files at the ticket root often carry self-describing prefixes (e.g., report -, analysis -) following the same prefix-plus-label pattern as description - and todo -; singleton ad-hoc files may also use bare names (e.g., readme.md, migration.md). The open-ended set of such filenames is by convention, not specification.

6. Identifiers

6.1 Ticket Identifier Grammar

A ticket identifier has the form:

ticket-id    = project-slug "-" number
project-slug = slug
number       = 1*DIGIT

The boundary between the project slug and the number is the last hyphen followed by an all-decimal suffix. A regex such as ^(.+)-(\d+)$ parses the form reliably even when the project slug contains internal hyphens.

Examples:

foo-123
my-lib-42

The number is decimal only. Hexadecimal and other alphanumeric bases are not used.

6.2 Project Slug Constraints

A project slug:

Project slugs are compact project keys, not URL slugs of full labels; when chosen from a label, prefer a short mnemonic from the central product, component, or domain word.

A project slug is declared by the existence of .jekt/projects/{slug}/ (§4.4) and is in use whenever any ticket directory matches {slug}-{number}. A slug MAY be in use without being declared; declaration is OPTIONAL.

Status: Exact length bounds and reserved-name policy are (provisional).

6.3 Release Identifiers

Release identifiers are strings used as directory names under .jekt/releases/. The most common form is a version string (e.g., 2.0.3), used directly in single-project repositories where uniqueness is naturally guaranteed by the version sequence.

In repositories declaring multiple projects (§4.4), the convention is to prefix the release identifier with the project slug (e.g., foo-2.0.3, bar-4.0.5), mirroring the slug-prefix pattern used for ticket identifiers. The prefix is a convention for disambiguation, not a structural requirement of this specification; the ticket-identifier grammar (§6.1) is naturally distinct from a version-style release identifier because it requires an all-decimal suffix, which a dotted version (such as 2.0.3) does not satisfy.

Unlike ticket identifiers, a release identifier does not structurally encode its project. The version-string convention does the work of identification in the single-project case; the slug-prefix convention extends that work to the multi-project case. A future revision may complement these conventions with an explicit release-version (or similar) property in the release's description.yaml; such a property would coexist with the directory-name convention rather than replace it, consistent with the open-world stance of §8.

Status: A normative grammar for release identifiers is (TBD). The conventions above describe the recommended forms.

6.4 Other Identifiers

6.5 Parsing Rules

Tools parsing ticket identifiers:

6.6 Case Handling

For machine operations (file system paths, Git branches, Git refs, URIs), tools SHOULD use the canonical lowercase form.

For textual references in Markdown body content, headings, and commit messages, tools SHOULD recognize ticket-ID-shaped text regardless of project-slug casing and SHOULD preserve the case the author used. CommonMark reference-label resolution is case-insensitive (see §7.2); Jekt identifier comparison is not.

For Git log searches by ticket identifier, tools SHOULD use case-insensitive search (e.g., git log --grep -i) to accommodate either case.

7. References

7.1 Reference Syntax

A Jekt reference uses the CommonMark shortcut reference link syntax:

See [FOO-123] for context.

With a corresponding definition anywhere in the same document. The link target is expressed relative to the document making the link (the same convention as HTML href). A reference from one ticket's file to another ticket directory is typically a sibling traversal:

[FOO-123]: ../foo-123/

The reference renders as a hyperlink when a definition is present and as literal bracketed text otherwise. The literal-bracket fallback remains visually distinct and is recognizable to humans, search tooling, and LLMs.

7.2 Resolution Rules

CommonMark reference-label resolution is case-insensitive. A reference of the form [FOO-123] resolves to a definition of the form [foo-123]: … and vice versa. This rule governs Markdown links; it does not make differently cased Jekt identifiers equal.

A reference link target for a Jekt ticket SHOULD point to the ticket directory, not to a specific file within it. The path SHOULD be expressed relative to the document making the link (as in HTML href):

[FOO-123]: ../foo-123/

Reference link targets to repository content MUST remain within the repository. Absolute file system paths and paths that traverse outside the repository (e.g., paths beginning with /, paths beginning with a drive letter, or .. segments that escape the repository root) MUST NOT be used, as they leak host system structure and are not portable across clones.

External-system references (see §7.4) are URLs and are exempt from the repository-relative requirement.

Multiple definitions for the same label are permitted by CommonMark; the first wins. Tools and LLMs MAY append definitions across editing sessions without coordination.

7.3 Self-References

Within a ticket's own artifacts, the ticket's own identifier needs no definition. A reference to [FOO-123] inside artifacts under tickets/foo-123/ is an identity marker, not a cross-reference. Tools SHOULD NOT warn about missing definitions for a ticket's own identifier within its own directory.

7.4 External References

Identifiers from external systems are structurally distinct from Jekt identifiers (e.g., uppercase Jira-style keys, GitHub owner/repo#number form). They coexist in the same reference namespace:

[AUTH-456]: https://jira.example.com/browse/AUTH-456
[acme/widget#789]: https://github.com/acme/widget/issues/789

Mapping between an external system's identifier and a Jekt ticket is metadata on the ticket (see §8), not a reference-format concern.

7.5 Heading and Commit-Subject Conventions

Ticket-owned files SHOULD begin with a level-one heading containing the bracketed ticket identifier. Git commit subject lines SHOULD begin with the bracketed ticket identifier followed by the commit subject in free form:

# [FOO-123] Auth Token Refresh
[FOO-123] Fix token refresh logic

The bracketed identifier is a prefixing qualifier, not part of the heading or subject grammar. It is never followed by a colon. When a colon appears in a heading or commit subject, it separates an artifact-kind token from a free-form elaboration of that artifact.

The brackets already delimit the identifier; an additional : would duplicate the delimiter and resemble Markdown reference-definition syntax ([label]: target). The colon then serves its remaining role inside the heading or subject: separating a kind token from its elaboration (Summary: Token Rotation Strategy).

A kind token appears only when needed to disambiguate the document's role when viewed in isolation. The description and commit subjects carry no kind token because the bracketed identifier combined with the rest of the heading or subject is already self-identifying: the description's content is the heading title of the ticket; a commit subject's content is the change being made. Minutes and summary carry a kind token because they have no distinct topic of their own; the kind word is itself the heading content.

Plans and designs use the topic as the heading content. An optional kind prefix (# [FOO-123] Plan: Module Reorganization) MAY be used when the document might be viewed detached from its containing directory.

Markdown reference link definitions SHOULD NOT appear in commit messages.

The Git branch name for work on a ticket follows the form tickets/{ticket-id} (see §10.7).

8. Metadata Vocabulary

(non-normative) Several prescribed files in an entity directory can be understood as values of metadata properties on the entity. The prose description file (description - {Label}.md) corresponds to a description property; minutes.md corresponds to a minutes property; summary.md corresponds to a summary property. The jekt/ subdirectory holds .lst files whose paths mirror the names of namespaced properties (jekt/releases.lst corresponds to jekt/releases). This file-as-property model explains several storage decisions in §9.

(non-normative) The choice between storing a list-valued property as a YAML list inside description.yaml versus as a .lst file at the entity root or in a namespaced subdirectory is driven by the property's edit characteristics. Properties whose values change frequently and independently of the rest of the entity's metadata, such as release assignments, tags, and future assignee lists, benefit from .lst storage because each value is a separate line, supporting independent edit and clean Git merges. Properties bound tightly to the entity's identity and edited together with other metadata may use YAML lists in description.yaml. Specific properties are designated YAML or .lst by this specification on a per-property basis.

8.1 Property Naming and Namespacing

Metadata property names use the slash convention for namespacing:

prefix/name

Property names without a prefix denote intrinsic properties. Properties with a jekt/ prefix denote Jekt-defined system properties. Other prefixes denote extensions.

The local part of a property name uses camelCase:

jekt/kind: feature
jekt/assignee: alice@example.com
acme/team: platform

The defining test for intrinsic vs. system-defined: would this property exist, with the same meaning, if Jekt did not exist? If yes, it is intrinsic (bare name). If no, it is namespaced (jekt/ prefix).

Prefixes resolve to namespace identifiers via a system-declared context, analogous to RDFa's initial context model. Metadata files do not carry in-file @context declarations; the binding from prefix to namespace is established by this specification (for the jekt/ prefix) and by convention or external agreement for extension prefixes. (provisional) Full URI binding (TBD).

8.2 Cardinality Discipline

Each property has a fixed cardinality declared by the vocabulary:

Polymorphic "scalar-or-list-depending-on-count" forms are not permitted.

YAML serializers SHOULD emit list properties in block form (one item per line). Both block and flow forms are accepted on input.

8.3 Open-World Semantics and Defaults

Absence of a property is absence of assertion, not a value. There is no null sentinel, no unknown value.

Defaults are not stored in files. The vocabulary documents an operational default for each property; tools resolve absent properties to these defaults when displaying or querying. This is analogous to CSS specified vs. computed values.

8.4 Intrinsic Property Catalog

The entity's label (the short human-readable handle materialized in description filenames; §5.3) and heading title (the level-one heading of the description prose; §7.5) are not metadata properties. They are filesystem and document affordances and are not stored as properties in description.yaml.

Temporal properties such as created are not stored as properties in the initial vocabulary; they are derived from Git history (see §8.7). Explicit storage is deferred pending broader vocabulary work covering temporal properties uniformly.

Status: (provisional) The intrinsic property catalog is minimal. Additional intrinsic properties (e.g., author, reporter) are deferred pending broader vocabulary work.

8.5 Jekt-Defined Property Catalog

jekt/kind

Scalar. Open vocabulary. Suggested values:

jekt/status

Scalar. Optional. Denotes the stage a ticket has reached in some workflow. The conventional values below are drawn from stages common to existing issue trackers, in the spirit of convention over configuration (Jekt Design Principles §4.1). They are suggested rather than required: teams MAY use additional values, omit any of these, adopt a different terminal value, or define their own workflows — including formal state machines with explicit transitions — and the property remains usable without any formal workflow definition.

Because the values name workflow stages, the conventional vocabulary carries default correspondences between actions and stages: starting work brings a ticket to started, resolving it (which sets jekt/resolution) to resolved, and closing it to closed. These are conventions for interpreting the vocabulary, not transitions Jekt requires or enforces.

Each value carries a suggested operational implication: a property of the ticket that can be inferred when the value is used according to its convention.

jekt/resolution is not bound to any particular workflow stage and persists across status transitions unless explicitly changed.

jekt/priority

Scalar. Default medium.

jekt/resolution

Scalar. Indicates the disposition of the ticket — how its underlying matter has been or will be decided.

jekt/resolution is most commonly set in conjunction with moving jekt/status to resolved or closed, but the property describes the disposition independently of any specific workflow stage. It MAY be set or remain set on a ticket whose status is not resolved or closed (see the persistence note in jekt/status above).

jekt/assignee

Scalar. Value is a Git author email. Provisionally single-assignee. (provisional)

jekt/releases

List. Stored as jekt/releases.lst (one release identifier per line) at the ticket directory root.

Relation properties

List-valued per-relation-type properties:

Relation values are bare ticket identifiers (e.g., foo-123), not type-prefixed forms. Per-relation-type properties are used in preference to a single structured jekt/relations list so that each relation type can be read, queried, and merged independently.

Inverse relations are not stored; "what depends on this ticket" is answered by querying other tickets, not by maintaining reciprocal back-references.

Status: (provisional) Relation properties are deferred in the initial vocabulary pending real-world experimentation. Storage format (YAML list in description.yaml vs. .lst files in the jekt/ subdirectory) is not finalized.

8.6 Extension Properties

Properties defined by organizations or external systems use the same slash-namespace convention:

acme/team: platform
github/state: open
jira/priority: Major

There is no extensions: wrapper and no x- prefix. Tools MUST tolerate unknown properties.

8.7 Derived Properties

Some metadata is derived from the file system rather than stored as properties:

When the Jekt repository is a Git working tree, the following additional properties are derived from Git history rather than stored as Jekt properties:

When the Jekt repository is not under version control, the Git-derived properties above are absent in the open-world sense (§8); tools MUST NOT substitute sentinel values.

Tools MAY surface derived properties as if they were stored properties; doing so does not require storing them.

8.8 Import from External Systems

Status: (TBD). Import from external tracking systems (e.g., Jira, GitHub Issues) has been discussed only in related early-design contexts and requires separate treatment in a future revision.

Directions under early consideration, all highly (provisional):

9. Storage Formats

Line endings in Jekt files SHOULD follow the repository's Git configuration (e.g., core.autocrlf and .gitattributes). This specification does not impose a line-ending convention.

9.1 Markdown Artifacts

Prose artifacts (description prose file, minutes, summary, design documents, comments, plans, TODOs, ad-hoc work products) are CommonMark Markdown.

Files SHOULD end with a single trailing newline.

Files SHOULD begin with a level-one ATX heading per §7.5.

YAML frontmatter is not used in Markdown artifacts. Metadata lives in dedicated metadata files (see §9.2). (provisional)

Plans are ephemeral semantic working context and MAY be excluded from version control (e.g., by adding .jekt/tickets/*/plans/ to .gitignore) according to team preference. Their primary value is stable working-session context, not durable history; durable reasoning surfaced during planning should be extracted to a design document (see §3.2).

9.2 YAML Metadata (description.yaml)

Entity metadata is stored in a file named description.yaml at the entity directory root (ticket, release, or project). Its contents are a YAML mapping whose keys are property names per §8 and whose values follow each property's declared cardinality.

Example:

jekt/kind: feature
jekt/status: closed
jekt/resolution: completed
jekt/priority: high
jekt/assignee: jdoe@example.com

description.yaml is OPTIONAL. Absence indicates no assertions; defaults apply at the tool layer. An empty description.yaml (a zero-byte file, or one containing only {} or comments) is permitted and asserts the existence of the entity without asserting any properties; this is the open-world zero-assertion state in which an entity may be declared before any metadata is recorded.

Absent properties are omitted from the file. The values null, ~, and empty strings MUST NOT be used as sentinels for absence (see §8.3).

Property mapping key order is not semantically meaningful and is not prescribed.

9.3 List Files (.lst)

List-valued properties whose values are commonly searched, edited, or merged independently are stored as .lst files: plain text, one value per line, no trailing whitespace, terminated by a final newline.

Namespaced .lst files live in a subdirectory matching the namespace (jekt/), so that the file path mirrors the property name. (provisional)

Blank lines and lines beginning with # are reserved for future use (comments) and SHOULD NOT appear in current files.

9.4 Heading and Structural Conventions

The minutes file (minutes.md) begins with:

# [{TICKET-ID}] Minutes

<!-- Categories: Pivot | Insight | Decision | Finding | Lesson | Milestone | Open | Resolved -->

Each minutes entry is a single bullet of the form:

- YYYY-MM-DD **Category**: Description.

Minutes are append-only. Earlier entries are not removed or modified when understanding changes. Supersession is recorded as a new entry referencing the prior one.

The category is drawn from the following recommended vocabulary (provisional):

The vocabulary is open; teams MAY add categories appropriate to their work.

An entry records a significant event in the evolution of the work — a decision, a pivot, an insight, a discovery — that shifted the understanding behind it. Its measure is what a contributor resuming the work cold would otherwise have to reconstruct: the reasoning that lived in the conversation and was never made explicit in the result. Writing the entry is what draws that reasoning into the durable record.

Other artifact-specific structural conventions are (TBD).

10. Coordination Protocols

The protocols in this section apply to Jekt repositories that are Git working trees. They do not apply to Jekt repositories outside Git; in such repositories, distributed coordination is not available and ticket number allocation reduces to local mechanisms (see §10.2).

10.1 Ticket Number Coordination

In a distributed Git workflow, two contributors creating tickets concurrently on separate branches can collide on ticket numbers. Jekt separates candidate selection from coordinated claiming: candidate selection chooses a number to try, and coordinated claiming, when available, uses Git-native mechanisms to reserve that number atomically.

10.2 Candidate Selection and Claiming

For automatic ticket-number allocation, a tool selects the next candidate number by finding the highest existing number for the active project slug and adding one. The observed set includes local ticket directories under .jekt/tickets/ and, when coordinated claiming is available, existing remote claim refs for that slug.

When the Jekt management branch (§10.4) exists on origin and the remote is reachable, a tool attempts to claim the candidate by creating refs/jekt/ticket-claims/{ticket-id} atomically on origin. A non-fast-forward rejection indicates another claimant reserved the number first; the tool retries with the next candidate number.

When coordinated claiming is unavailable, a tool may use the next-highest local candidate without remote collision prevention, and should report that the number is uncoordinated. Numbers issued with and without coordinated claims use the same {project-slug}-{number} format and coexist freely.

Status: A randomized local candidate-selection strategy has been considered but is not specified in this revision.

10.3 Git Ref Namespace

Coordinated claims occupy the Git ref namespace refs/jekt/. Ticket claims live under:

refs/jekt/ticket-claims/{ticket-id}

Refs in refs/jekt/ are not branches. They are not under refs/heads/, do not appear in git branch output or typical forge branch UIs, are not fetched by the default refspec, and are not transferred by git push --all. Migration between forges requires an explicit refspec such as refs/jekt/*:refs/jekt/*. Precedent for custom ref namespaces includes git-bug (refs/bugs/) and Gerrit (refs/changes/).

Because refs/jekt/* does not propagate by default, coordination data created against one remote does not appear on other remotes without an explicit push.

10.4 The Jekt Management Branch

The presence of a branch named jekt on origin — the Jekt management branch — is the signal that coordinated mode is enabled for the repository. The branch is created as an orphan branch (no shared history with main) and serves as the commit anchor from which claim commits are derived.

The management branch tip MAY move as future Jekt configuration commits are added to it. The branch SHOULD NOT be force-pushed; doing so orphans the parent commits of existing claim refs.

The management branch SHOULD be protected against force-push and deletion in forges that support branch protection.

10.5 Claim Procedure

To claim ticket number N for project slug K, a tool:

  1. Constructs a unique commit anchored on origin/jekt whose message identifies the claim:

    git commit-tree "origin/jekt^{tree}" -p origin/jekt -m "Claim ticket ID K-N"
    

    commit-tree produces a commit whose SHA varies with author and timestamp, so concurrent attempts produce distinct commits.

  2. Pushes the resulting commit to refs/jekt/ticket-claims/K-N on origin:

    git push origin <commit-sha>:refs/jekt/ticket-claims/K-N
    
  3. Treats a successful push as a successful claim. A non-fast-forward rejection indicates another claim succeeded first; the tool retries with the next candidate number.

10.6 Failure Modes and Recovery

A git push to a claim ref may fail for several reasons:

Tools MUST distinguish non-fast-forward rejection from other failures.

--force-with-lease is insufficient for this protocol because Git short-circuits before performing the lease check when the ref already points to the same commit. Distinct commits per attempt (achieved via commit-tree with varying author/timestamp) are required.

Status: Claim ref lifecycle (pruning post-merge, abandoned-claim cleanup) is (TBD).

10.7 Branch Naming

The Git branch on which work for a ticket is performed follows the form:

tickets/{ticket-id}

Examples:

tickets/foo-123
tickets/my-lib-42

This convention namespaces ticket branches, aligns with the .jekt/tickets/ directory path, and allows tools to infer the current ticket from the current branch.

11. Versioning and Compatibility

11.1 Jekt Version Identification

Status: (TBD). A mechanism for declaring the Jekt version a repository conforms to has not been specified. Candidates include a file at .jekt/version, a property in a project-level metadata file, or omission (with version inferred from feature usage).

11.2 Forward and Backward Compatibility Expectations

Status: (TBD).

11.3 Handling of Unknown Properties, Files, and Directories

Tools MUST tolerate unknown properties in YAML metadata files and SHOULD preserve them on round-trip.

Tools MUST tolerate unknown files and directories within .jekt/ and within ticket directories. Such files are typically ad-hoc work products (see §3.2) and are not Jekt-managed.

Tools SHOULD NOT delete or rewrite unknown content without explicit user action.

12. Conformance

All conformance criteria should currently be considered (provisional), representing one reasonable approach based on the initial Jekt design. Full conformance specification is (TBD).

12.1 Conformance Terminology

A conformant repository is one whose Jekt artifacts satisfy the requirements of this specification.

A conformant tool is one that produces, modifies, or consumes Jekt artifacts in a manner consistent with this specification.

An extension is a property, file, or convention not defined by this specification but compatible with its open-world model.

12.2 Repository Conformance

A conformant repository:

12.3 Tool Conformance

A conformant tool:

12.4 Tools Outside a Jekt Repository

A tool MAY perform operations in a working directory that is not a Jekt repository (§2) when those operations do not depend on Jekt artifacts. A common case is composing a Git commit message from staged changes when no ticket context is available.

When operating in this mode, a tool:

This mode lies outside the repository-conformance requirements of §12.2; the tool-conformance requirements of §12.3 continue to apply to whatever Jekt-defined behavior the tool does perform.

12.5 Extension Conformance

An extension:

12.6 LLM-Agent Conformance

LLM-agent behavior is (non-normative); see Appendix C. A normative LLM-agent conformance profile may be added in a later revision.

13. Security and Privacy Considerations

Git ref visibility. Refs under refs/jekt/ are not fetched by the default refspec but are visible via git ls-remote. Anyone with read access to the repository can enumerate ticket-claim refs and thereby learn the set of issued ticket numbers and (from claim commit messages) the project slugs in use.

Forge behavior. Custom refs under refs/jekt/ are not displayed in typical forge branch UIs, but forges may surface them in tag lists, ref browsers, or webhooks. Tools and adopters SHOULD verify their forge's handling of custom refs before relying on visibility properties.

Comment authorship. Comment authorship is derived from the Git commit author. The Git author email is therefore exposed in the same way as in any other commit. Authors who require pseudonymity SHOULD configure their Git identity accordingly.

Filename leakage. Ticket identifiers, labels, and heading titles appear in filenames, branch names, and commit messages. Where a project's ticket labels or heading titles contain sensitive content (e.g., security issue descriptions), the file system, branch listings, and commit logs leak that content to anyone with read access. Such content SHOULD be kept out of labels and heading titles.

Export and synchronization. Synchronization with external systems (e.g., Jira, GitHub Issues) is out of scope for this specification. Adopters implementing synchronization MUST consider the privacy implications of exporting Jekt comment authorship, ticket content, and metadata to external systems with different access controls.

.jekt/ history. Because Jekt artifacts are stored in Git, the full edit history of ticket content (descriptions, comments, minutes) is preserved indefinitely. Removal of content (e.g., for compliance reasons) requires Git history rewriting, with all the operational consequences that entails.

14. Open Issues

(non-normative)

This section aggregates (provisional) and (TBD) items for cross-cutting visibility. Inline markers at the point of use take precedence.

14.1 Identifier and Reference

14.2 Repository Structure

14.3 Metadata Vocabulary

14.4 Coordination

14.5 Versioning and Compatibility

14.6 Conformance

14.7 Workflow and Process

14.8 Cross-System Integration

Appendix A. Examples

(non-normative)

A.1 Minimal Ticket Directory

.jekt/
  tickets/
    foo-123/
      description - Auth Token Refresh.md

description - Auth Token Refresh.md:

# [FOO-123] Auth Token Refresh

We need to rotate auth tokens on each use to limit replay window.

No description.yaml is present. No properties are asserted. jekt/status is absent (operationally open); jekt/priority resolves to its default of medium; other Jekt-defined properties are absent.

A.2 Fully Populated Ticket Directory

.jekt/
  tickets/
    foo-123/
      description - Auth Token Refresh.md
      description.yaml
      minutes.md
      summary.md
      tags.lst
      jekt/
        releases.lst
      todo - Extract Byte Utils.md
      plans/
        2026-02-04-token-rotation.md
      designs/
        Token Rotation Strategy.md
      comments/
        2026-02-03T21-45-00Z.md

description.yaml:

jekt/kind: feature
jekt/status: closed
jekt/resolution: completed
jekt/priority: high
jekt/assignee: alice@example.com

tags.lst:

security
backend

jekt/releases.lst:

2.0.3

minutes.md:

# [FOO-123] Minutes

<!-- Categories: Pivot | Insight | Decision | Finding | Lesson | Milestone | Open | Resolved -->

- 2026-02-01 **Decision**: Use JWT with 24-hour expiry; rotate refresh tokens on each use.
- 2026-02-03 **Insight**: Replay-window analysis shows rotation-on-use covers all observed attack patterns.
- 2026-02-04 **Milestone**: Token rotation implemented and tested.

A.3 Reference Definitions

The auth refactor in [FOO-123] depends on [FOO-100] and relates to [AUTH-456].

[FOO-100]: ../foo-100/
[FOO-123]: ../foo-123/
[AUTH-456]: https://jira.example.com/browse/AUTH-456

A.4 Commit Subject Lines

[FOO-123] Implement token rotation
[FOO-123] [FOO-124] Refactor shared crypto helpers

A.5 Coordinated Claim

Claim ticket foo-42:

git push origin \
  $(git commit-tree "origin/jekt^{tree}" -p origin/jekt -m "Claim ticket ID foo-42"):refs/jekt/ticket-claims/foo-42

A successful push indicates the claim succeeded. Non-fast-forward rejection indicates a concurrent claim won; retry with foo-43.

List current claims:

git ls-remote origin "refs/jekt/ticket-claims/*"

Appendix B. Rationale

(non-normative)

B.1 Lowercase Canonical, Uppercase Representational

File systems and Git refs are not reliably case-sensitive across platforms; lowercase canonical form avoids portability bugs. Uppercase representational form preserves the visual scannability that Jira-style identifiers established in developer culture and that many teams want to retain. CommonMark's case-insensitive reference-label resolution makes prose links forgiving without changing the caseful identity of Jekt identifiers.

B.2 Reference Link Targets to the Directory

A reference target pointing at a ticket's directory (e.g., ../foo-123/ from a sibling ticket's own file) survives renames of files within the ticket directory. The directory is the stable identity; individual filenames — especially labeled filenames (§5.5) and the labeled portion of prefixed filenames (§5.4) — may change. The exact relative path depends on the location of the document making the reference, per the relative-to-document rule in §7.2.

B.3 Cardinality Discipline

Polymorphic scalar-or-list forms (as in package.json's author field) require every consumer to type-check before processing and produce inconsistent diffs. Fixing cardinality per property eliminates an entire class of parser bugs and produces uniform diffs.

B.4 Open-World Semantics

Sentinel values (null, unknown) propagate through logical operations in ways that produce subtle bugs (SQL NULL, JavaScript null != null, IEEE 754 NaN). Treating absence as absence of assertion eliminates this class of problems and aligns with how Jekt artifacts naturally accrue over a ticket's life.

B.5 The Jekt Management Branch as Coordination Anchor

The presence of a single named branch — the Jekt management branch (§10.4) — is a low-cost, Git-native enable signal. Anchoring claim commits on this branch's tree allows commit-tree to produce content-stable commit objects whose SHA varies only with author and timestamp, which in turn allows the push to act as an atomic compare-and-swap.

B.6 Distinct Commits per Claim Attempt

Without distinct commits per attempt, two contributors invoking the same commit-tree arguments could produce the same SHA, and the second push would be accepted as a no-op rather than rejected. Varying author and timestamp metadata via the default behavior of commit-tree ensures distinct commits without additional coordination.

B.7 Initial jekt/kind Vocabulary

The four values (bug, feature, improvement, task) are deliberately minimal. feature and improvement are kept distinct because the additive-versus-transformative distinction matters in change communication; conflating them under a single enhancement value would lose information that release notes and team conversation routinely depend on. epic is not a kind value because an epic-shaped ticket is not a different kind of ticket but a ticket with decomposition children, observable through the jekt/partOf relation graph rather than by a flag on the parent.

B.8 No Colon After the Bracketed Identifier

The single-delimiter form [ID] … matches the use of delimited identifiers in other citation systems ([Smith 2003] notes that …, [RFC 2119] is the source …), where one set of delimiters is sufficient and a following colon is not used. Reserving the ]: adjacency for Markdown reference-link definitions avoids visual ambiguity and leaves the colon available within the heading or subject to separate an artifact-kind token from a free-form elaboration.

Appendix C. LLM Agent Guidance

(non-normative)

LLM agents operating on Jekt artifacts are expected to behave consistently with the following guidance.

C.1 File-First Authoring

When asked to produce a substantive artifact (plan, design, summary), the agent should write the artifact directly to the appropriate file and present a discussion-oriented summary in conversation. Generating the artifact in conversation and transcribing it to a file afterward can produce unintentional divergence between the conversation and the file.

C.2 Current Ticket Inference

The agent should infer the current ticket from the Git branch name when it matches the form tickets/{ticket-id}. If the branch does not encode a ticket, the agent should ask rather than guess.

C.3 Reference Definitions

The agent may append reference link definitions to a Markdown document without coordination; duplicate definitions are harmless under CommonMark. The agent should target the ticket directory, not specific files within it.

C.4 Minutes Maintenance

When prompted to update minutes, the agent should produce entries focused on conceptual shifts, not implementation actions.

C.5 Preservation of Unknown Content

When editing Jekt artifacts, the agent should preserve unknown files, properties, and directories. Ad-hoc work products at the ticket root (e.g., report - …, analysis - …, or bare-name singletons such as readme.md or migration.md) are valid and should be left in place.

C.6 Casing

When writing identifiers to file system paths, Git refs, or Git branches, the agent should use canonical lowercase form. When writing identifiers in Markdown body content, headings, or commit messages, the agent may use either case and should preserve the case the user has been using.

Appendix D. Change History

(non-normative)

How significant changes to this living document are recorded is (TBD).