Skip to content

feat(spec): add Lifecycle official extension (resolves #65) - #97

Open
marianogonzalez wants to merge 1 commit into
Agent-Card:mainfrom
marianogonzalez:feat/lifecycle
Open

feat(spec): add Lifecycle official extension (resolves #65)#97
marianogonzalez wants to merge 1 commit into
Agent-Card:mainfrom
marianogonzalez:feat/lifecycle

Conversation

@marianogonzalez

Copy link
Copy Markdown

Summary

This PR resolves #65
(communicate an artifact's software-lifecycle state at discovery time) by
adding an official extension
https://ai-catalog.org/extensions/lifecycle — rather than a native
lifecycle field on the Catalog Entry as the original issue proposed.

A Catalog Entry carries version (which revision this is) and updatedAt
(when the entry last changed), but nothing that expresses where that
revision sits in its lifecycle
: whether it is a preview, generally
available, deprecated with a scheduled end-of-life, or already retired —
nor how a consumer should move off it. Agents evolve: a v1 is superseded by
a breaking v2, an endpoint is scheduled for shutdown, a successor ships with
a migration guide. The extension lets a publisher advertise that state on a
per-version entry so a consumer — an agent planner or a governance tool
— can filter deprecated or retired artifacts at discovery, plan around a
known end-of-life, and follow a producer-supplied migration path to a
successor before committing to an integration.

Because the extension is additive and unrecognized extensions keys are
ignored, it needs no specVersion change — a catalog carrying it
remains a conformant 1.0 document.

Changes Included

  1. adr/0023-lifecycle-metadata-extension.md (new) — records the
    decision to implement Spec Proposal: No Lifecycle or Deprecation Model #65 as an official extension rather than a native
    entry field, consistent with the closed-core philosophy of
    ADR-0012; documents the
    open-text status rationale, the replacedBy naming rule, and the
    interpret-then-fail-safe rule for unrecognized values.
  2. specification/ai-catalog.md:
    • Registered the extension in the Official Extensions list alongside
      metadata.
    • Added the Lifecycle Metadata Extension section: value structure
      (status, releaseDate, and a deprecated object carrying
      replacedBy, deprecationDate, endOfLifeDate, breakingChanges,
      migrationGuide), the per-version scoping rule, an example, and a
      Consumer behavior paragraph.
    • Added an informative CDDL block for the extension value.
    • Added a Privacy Considerations note on disclosing unreleased
      successors / retirement schedules and on unsigned producer assertions.
  3. Developer docs — a new annotated example
    (docs/examples/lifecycle-metadata.md), an authoring section in
    Creating a Catalog, a filtering section in Consuming Catalogs, plus
    cross-links and a nav entry.

Reconciling the original proposal

The proposal in #65 predates several current conventions; the extension
uses today's forms:

Proposal (outdated) This PR (current)
urn:ai:… urn:air:{publisher}:{namespace}:{name} (ADR-0015)
native lifecycle field on the entry official extensions entry (keeps the core schema closed)
replacedBy pointing at the deprecated artifact's own identifier replacedBy pointing at the distinct successor identifier
lifecycle attached to the logical artifact lifecycle scoped to the version the entry identifies (a deprecated v1 alongside an active v2)

Design notes

  • Per-version, not per-artifact. Lifecycle describes the version the
    entry identifies; within a multi-version listing each versioned entry may
    carry its own status.
  • status is open text, not a closed enum. RECOMMENDED values are
    preview, active, deprecated, and retired — each a state a consumer
    can actually reach. A not-yet-released "planned" state is deliberately
    excluded: a catalog entry exists because the artifact is discoverable, and
    an unreleased version has no consumable endpoint to list.
  • Unrecognized status fails safe, not open. A consumer MUST NOT reject
    an entry solely because its status is unrecognized, but MUST NOT
    silently discard the value either — a value such as sunset may signal a
    retirement a consumer would then miss. A consumer SHOULD interpret it
    against the recommended states (an agent consumer can do so semantically)
    and, when it cannot, treat the artifact conservatively rather than assume
    it is active. This mirrors the spec's open-text treatment of type and
    identifier while keeping unrecognized values safe.
  • replacedBy follows the core identifier rule. It is an artifact
    identifier, so the urn:air structure is HIGHLY RECOMMENDED and MUST be
    used for open or federated systems — the same rule as a Catalog Entry
    identifier.
  • Lifecycle metadata is not a support guarantee. The dates and the
    successor reference are unsigned producer assertions unless carried in a
    signed Trust Manifest; a consumer that needs a supported-until guarantee
    corroborates them out of band, not via this extension.

Interoperability impact

No change to interoperability expectations for existing catalogs. The core
schema, CDDL for core types, conformance levels, and specVersion are all
unchanged; a consumer that does not implement the extension ignores it
without error, exactly as for any unrecognized extensions key.

Non-goals

  • A lifecycle enforcement mechanism or support SLA — this is advisory
    discovery metadata only.
  • Promoting lifecycle to a core field — deliberately kept an extension
    per ADR-0012 / ADR-0023.
  • A closed status enum — rejected as less flexible and misaligned with the
    spec's open-text fields.

Validation

  • uv run --locked python tools/build_spec.py specification/ai-catalog.md dist/index.html --config specification/respec-config.json — passes.
  • uv run --python 3.12 --locked --group docs mkdocs build --strict — passes, no broken links.
  • All lifecycle-bearing JSON examples validated.

Resolves Agent-Card#65 by adding an official extension —
https://ai-catalog.org/extensions/lifecycle — rather than a native
`lifecycle` field on the Catalog Entry as the original issue proposed.

An entry carries `version` (which revision this is) and `updatedAt` (when
the entry last changed) but nothing that expresses where that revision
sits in its lifecycle: whether it is a preview, generally available,
deprecated with a scheduled end-of-life, or already retired — nor how a
consumer should migrate off it. The extension lets a publisher advertise
that state on a per-version entry so a consumer can filter deprecated or
retired artifacts at discovery, plan around a known end-of-life, and
follow a producer-supplied migration path to a successor.

Because the extension is additive and unrecognized `extensions` keys are
ignored, it needs no `specVersion` change — a catalog carrying it remains
a conformant 1.0 document.

Changes:
- adr/0023-lifecycle-metadata-extension.md (new): records the
  official-extension decision (consistent with the closed-core philosophy
  of ADR-0012), the open-text `status` rationale, the `replacedBy` naming
  rule, and the interpret-then-fail-safe rule for unrecognized values.
- specification/ai-catalog.md: registers the extension in the Official
  Extensions list; adds the Lifecycle Metadata Extension section (status,
  releaseDate, deprecated object, rules, example, consumer behavior); adds
  an informative CDDL block; adds a Privacy Considerations note.
- Developer docs: a new annotated example (docs/examples/
  lifecycle-metadata.md), authoring guidance in Creating a Catalog, a
  filtering section in Consuming Catalogs, cross-links, and a nav entry.

`status` is open text with RECOMMENDED values `preview`, `active`,
`deprecated`, and `retired` — each a state a consumer can actually reach
(a not-yet-released "planned" state is deliberately excluded). An
unrecognized status is neither rejected nor silently discarded: a consumer
SHOULD interpret it against the recommended states (an agent consumer can
do so semantically) and, when it cannot, treat the artifact conservatively
rather than assume it is `active` — failing safe, not open.

`replacedBy` is an artifact identifier and follows the same naming rule as
a Catalog Entry `identifier`: the `urn:air` structure is HIGHLY RECOMMENDED
and MUST be used for open or federated systems.

Signed-off-by: marianogonzalez <mariano.gonzalez@salesforce.com>
@marianogonzalez
marianogonzalez requested a review from a team as a code owner August 6, 2026 17:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Spec Proposal: No Lifecycle or Deprecation Model

1 participant