Skip to content

Promote lifecycle time to a first-class concept in change metadata (created/updated/archived timestamps) #1245

Description

@Gaubee

Problem

A change has no authoritative notion of time. Today the only temporal data attached to a change is:

  1. created in .openspec.yaml — a YYYY-MM-DD date (day granularity, optional). See src/core/change-metadata/schema.ts.
  2. The archive folder prefixYYYY-MM-DD-<name> — which is the archive date, again day-only, and is not persisted into any metadata field (src/core/archive.ts truncates new Date().toISOString() to the date for the folder name).
  3. lastModified surfaced by openspec list — which is the filesystem mtime, i.e. second-hand data.

There is no archived timestamp, and the existing created is day-granular only. The full lifecycle of a change (proposed → applied → archived) is therefore not recoverable from OpenSpec's own data.

Why this matters (downstream tooling)

I'm the author of openspecui (GitHub), where I build timeline views of changes across a project. To reconstruct when a change moved through its lifecycle, I currently have to fall back to git commit/repo timestamps. That's inaccurate and not first-hand data — git knows when files were committed, not when the change was proposed or archived within OpenSpec.

The key distinction: a git commit is an action, not a timestamp of the change itself. The moment a change transitions through its lifecycle is a fact that belongs to OpenSpec, and it must be objectively stored in the standard — not reverse-engineered from commit times, which are a proxy for something else entirely. Any tool that wants to render an accurate timeline (openspecui, dashboards, changelog generators, retro analysis) is in the same boat.

This is a gap that only OpenSpec itself can close authoritatively, because it owns the lifecycle transitions (/opsx:propose, /opsx:apply, /opsx:archive). Relying on git or filesystem mtime means every consumer re-derives an approximation of the same missing facts.

Proposal

Promote time to a first-class concept in the change metadata standard. Concretely, extend ChangeMetadata with lifecycle timestamps captured at the moment OpenSpec performs the transition:

# openspec/changes/<name>/.openspec.yaml
schema: spec-driven
created: 2026-06-24T09:12:33Z      # upgrade from YYYY-MM-DD to ISO 8601
updated: 2026-06-25T14:02:10Z      # last /opsx:apply or artifact edit
archived: 2026-06-26T18:30:00Z     # set on /opsx:archive (written into the archived copy)

Key points:

  • ISO 8601 with time + timezone (not day-only). Day-granularity is exactly what makes Feature request: Add intra-day ordering to archive folder names #1192 and Support numbered change names (NNNNN-slug) for sequencing #1169 necessary — intra-day ordering is lost. Capturing the full timestamp at the source removes the need for workarounds.
  • Capture at the transition, not derived. created on /opsx:propose/new, updated on artifact writes / /opsx:apply, archived on /opsx:archive. This is the first-hand data downstream tools need.
  • updated is more than "last apply time". More importantly, it serves as an anchor for git to track change evolution — a deterministic point the standard provides, so tooling can reason about what changed when without conflating the commit action with the change's own timeline.
  • archived should be written into the archived .openspec.yaml, so history is self-describing without parsing folder names.

Relationship to existing issues

I reviewed the related threads — this proposal is complementary but distinct in what it asks for:

I'd see the timestamp standard as the foundation; the naming/numbering proposals in #1192/#1169 can then layer on top (or become unnecessary for some use cases).

Backward compatibility considerations

  • created already exists; widening YYYY-MM-DD → full ISO is backward-compatible for parsing (the regex can accept both), though writers should emit ISO going forward.
  • New fields (updated, archived) are optional, so existing changes are unaffected.
  • openspec list could prefer updated/archived over filesystem mtime when present, degrading gracefully to mtime for legacy changes.

Happy to help scope a PR or a more detailed spec for this if there's interest. Primarily opening this to establish time as part of the standard rather than a per-tool workaround, since it unlocks accurate timelines for the ecosystem.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions