Skip to content

Plan DSL reference ​

PlanQ DSL v1 is a UTF-8, EDN-shaped data language with one root map. It is not standard EDN and is never evaluated.

Syntax ​

FormPurpose
{ ... }Map for a Plan, work item, assignment, or resource object
[ ... ]Ordered vector
:fieldField name
plain-valueUnquoted scalar when unambiguous
"quoted value"Escaped single-line scalar
Backtick blockMultiline :description only
// commentLine comment; omitted from IR
@item-idExplicit work-item or person reference

Commas are optional separators and canonical formatting removes them. Parenthesized expressions, sets, reader macros, tagged literals, and interpolation are unsupported.

IDs, names, and dates ​

IDs match [a-z][a-z0-9]*(?:-[a-z0-9]+)* and are unique in their namespace. Plan, task, and milestone IDs are global within an entry include closure. Person keys use a separate project-resource namespace.

Dates are absolute ISO calendar dates in YYYY-MM-DD form. PlanQ never stores relative expressions such as today or +3d.

Names are non-empty single-line values. Quote names containing whitespace, structural punctuation, escapes, or //.

Plan and work-item fields ​

NodeRequiredOptional
Plan rootnone:id, :version, :title, :description, :items
Leaf task:task:id, :description, :start, :end, :deadline, :after, :to
Summary task:task, :items:id, :description, :start, :end, :deadline, :after, :to
Milestone:milestone:id, :description, :date, :state, :after
Include:include:after, :deadline
Assignment map:person, :loadnone

The current DSL version is 1.0. Missing root :id, :version, and :title may be derived from a valid source path and are materialized by formatting. Unknown and duplicate fields are errors.

Scheduling rules ​

  • A leaf task supplies both :start and :end, or neither.
  • Both dates are inclusive; equal dates represent one day.
  • :deadline is an inclusive hard deadline.
  • A milestone is a zero-duration event with optional :date.
  • Summary dates roll up from terminal descendants.
  • :after is an ordered vector of explicit @id finish-to-start dependencies.
  • A successor task starts after a predecessor finishes; a successor milestone may share the predecessor's finish date.

PlanQ validates constraints but does not automatically schedule work.

Includes ​

An include path is relative to the including file, uses /, ends in lowercase .plan, and remains inside the source root. The entry closure is limited to:

LimitValue
Include depth32
Files per entry256
Bytes per file2 MiB
Bytes per closure32 MiB

Included files may reference their own descendants, but cannot reference an includer, a sibling branch, or an entity outside the closure.

Resources ​

Ordinary .plan files cannot declare calendars or people. Those belong in project-root resources.plan, whose closed field set is:

NodeRequiredOptional
Resource document:version:calendar, :people
Calendarnone:workdays, :holidays
Person:name:id, :role, :leave, :overtime
Leave range:start, :endnone
Overtime map:date:capacity

Assignments reference a stable @person-key. Multiple assignments may use {:person @alice :load 0.5}. Each load and capacity is greater than zero and at most 1.0.

Formatting and versions ​

planq format operates on source syntax, not generated IR. It uses two-space indentation, stable field order, LF line endings, minimal safe quoting, and a single final newline. Reformatting canonical input is byte-idempotent.

DSL, IR, diagnostics, CLI envelope, and Bridge protocol versions evolve independently. Consumers must read each explicit version rather than infer one from another.

See Authoring Plans and Project Files.

PlanQ documentation