Shapes Specification
- Version:
- 0.1.0
- Status:
- Working Draft
- Date:
- March 2026
Abstract
Shapes is an open specification born from the need to give engineers a layer above code — a way to define the intent, structure, and constraints of a system so that agents can fill it. But the model is not specific to software. A Shape can describe anything with intent and structure: a product, a research program, a novel, an organization. Humans define and approve Shapes; agents handle the work that fills them. Each Shape connects to the artifacts that realize it, the evidence that validates it, and the provenance that records where it came from.
1. Motivation
Revision history tells you what changed, but not what the work means. Change logs, task lists, and review trails are useful records, but they don't capture intent, invariants, or ownership boundaries.
As agents multiply and run tasks in parallel, the volume of changes outpaces what humans can meaningfully review. Shapes gives practitioners control over the evolution of their work without reviewing every change.
Agents interact with Shapes in three ways:
- Build — propose changes that fill the Shape.
- Review — evaluate whether proposed changes match the Shape.
- Evolve — propose new Shapes or mutate existing ones as the project grows.
Shapes aims to:
- Let practitioners define project structure at any granularity — from a single component to an entire system.
- Enable agents to navigate from high-level concerns to concrete artifacts through explicit bindings.
Shapes does not replace version control, review workflows, or task tracking — it defines a semantic layer above them. It does not standardize storage or synchronization protocols or inline provenance records.
2. What is a Shape?
A Shape is a semantic unit that may represent a feature, component, workflow, boundary, or an entire project. Shapes compose into architectures that can span multiple projects and sources — internal and external. The best way to understand a Shape is to see one.
2.1 Example
Shapes originated from the need to give software engineers a semantic layer above code. The model itself is generic — use the toggle below to see how the same structure describes a software feature, a chapter in a novel, or a laboratory experiment. Each field is explained in the sections that follow — for now, read top to bottom to see how intent, constraints, realization, evidence, and provenance fit together in a single record.
Shape:
id: 1
name: Platform
description: Top-level system encompassing authentication and team management.
kind: system
version: 1.0.0
# → §3 Lifecycle
status:
canonical:
date: "2025-12-01"
# → §2.2 Intent
intent:
summary: >
Provide a unified platform for user identity, access control,
and team collaboration.
children:
- 2
- 3This example shows a standalone Shape. Shapes can also contain children and reference other Shapes, forming architectures that span project boundaries — see §7 Architecture.
2.2 Intent
Every first-class node in Shapes — Shapes, Amendments, and Constraints — carries an Intent. Intent captures the why behind a record: what it aims to achieve, what it deliberately excludes, and how success is measured. It is the semantic core that makes each record reviewable on its own terms, independent of the artifacts that realize it.
The uris list grounds the intent in external references — issue trackers, design documents, discussion threads. Beyond the core fields, Intent is an open map: projects add whatever fields suit their domain.
Intent:
summary: string
uris: [string]?
# open map — add any fields your project needs
<string>: anyintent:
summary: Allow administrators to invite users by email.
uris:
- https://github.com/acme/invitations/issues/42
- https://docs.example/design/invitations
rationale: Reduce onboarding friction for new teams.
goals:
- Reduce setup friction for new teams
- Keep invitation issuance restricted to trusted actors
non_goals:
- Guest access
success_criteria:
- Invitations accepted within 24h > 80%
tradeoffs:
- Simpler flow at the cost of no guest access2.3 The Shape Model
Inline children are Shapes owned by this parent. ShapeId children reference Shapes across boundaries. parents provides the inverse for bidirectional traversal. Because a Shape can appear as a child of multiple parents, the model supports DAG (directed acyclic graph) structures that can express any system topology.
The model should prefer explicitness at boundaries. A Shape should state what concern it represents, why it exists, what must remain true, and which concrete artifacts are expected to embody it.
Shape:
id: ShapeId
name: string
description: string
kind: string
version: semver
# Lineage → §3 Lifecycle
predecessors: [ShapeId]?
# → §3 Lifecycle
# one of:
status:
proposed | promoted | canonical | rejected | abandoned | reverted:
date: iso8601
reason: string?
uris: [string]?
superseded:
date: iso8601
reason: string?
uris: [string]?
successors: [ShapeId]
# → §2.2 Intent
intent: Intent
metadata:
<string>: any
constraints:
- Constraint | ConstraintId
# → §6.1 Realization Bindings
realization:
- RealizationBinding
# → §6.2 Evidence
evidence:
- EvidenceRef
# → §8 Boundaries and Extensibility
provenance:
- ProvenanceRef
# → §4 Amendments
amendment_log:
- AmendmentRef
# Composition
parents: [ShapeId]?
children:
- Shape | ShapeIdShapeId, AmendmentId, and ConstraintId are opaque identifiers. The specification prescribes no format, length, or generation strategy — implementations choose whatever suits their storage and coordination needs (UUIDs, integers, slugs, content hashes, etc.).
Versions follow semantic versioning (MAJOR.MINOR.PATCH). When an amendment canonicalizes, the Shape's version is bumped according to the amendment's semver_change field. The initial version for a newly proposed Shape is implementation-defined (e.g., 0.1.0 or 1.0.0).
3. Lifecycle
Every Shape, Amendment, and Constraint moves through a lifecycle. The first three states are progressive; the last three are terminal.
| Progressive | |
| Proposed | A candidate under consideration. |
| Promoted | Intent is established, realization may be incomplete. |
| Canonical | The authoritative state, fully realized with sufficient evidence. |
| Terminal | |
| Rejected | Not part of the current project state. |
| Superseded | No longer current; a successor owns the concern. |
| Abandoned | Incomplete and inactive. |
| Reverted | Previously progressive, now unwound. |
Status is a tagged union — the lifecycle state is the key, so each variant structurally defines only the fields valid for that state. The superseded variant carries successors because replacement only makes sense for that transition; other variants cannot.
Lifecycle state changes are governed by preconditions and postconditions. For example, promotion may require that all declared constraints have a plan for enforcement, and canonicalization may require that realization bindings and evidence references are present and sufficient. The spec does not prescribe a fixed set of preconditions in this draft, but every state change should be reviewable and justified.
Structural operations — splitting a Shape into multiple children, merging sibling Shapes, or superseding one Shape with another — are expressed by transitioning the original Shape(s) to a terminal state and proposing new ones. The predecessors field on the new Shape(s) references the originals, while the status.successors field on the superseded Shape(s) references their replacements. The operation type is derived from cardinality: one predecessor to one successor is a supersede, one to many is a split, and many to one is a merge. This keeps the lifecycle model simple while still supporting large-scale reorganization with machine-readable lineage.
When a Shape is superseded, successors should be non-empty. The lineage graph must be acyclic, and all referenced IDs should resolve to existing records.
# Original Shape, now superseded
Shape:
id: shape-auth-monolith
name: Unified Auth Module
version: 2.3.0
status:
superseded:
date: "2026-03-10"
reason: Split into separate authentication and authorization concerns
successors: [shape-authn, shape-authz]
# New Shapes
Shape:
id: shape-authn
name: Authentication
version: 0.1.0
predecessors: [shape-auth-monolith]
status:
proposed:
date: "2026-03-10"
Shape:
id: shape-authz
name: Authorization
version: 0.1.0
predecessors: [shape-auth-monolith]
status:
proposed:
date: "2026-03-10"
4. Amendments
Changes to a Shape while it is still in Proposed status are direct edits to the proposal. Once a Shape reaches promoted or canonical status, further semantic changes are recorded as amendments rather than new Shapes. Each amendment is an immutable record. Corrections are recorded as subsequent amendments, never edits to prior ones.
Amendments follow the same lifecycle as Shapes: Proposed, Promoted, and Canonical. A proposed amendment declares what should change and why. A promoted amendment is accepted in direction — implementation begins, and the amendment accumulates its own realization bindings and evidence as the work progresses. A canonical amendment is fully realized and proven: the artifacts exist, the verification passes, the evidence is sufficient.
Amendments carry the same semantic fields as Shapes — intent, constraints, realization bindings, and evidence — because those are what an amendment must earn to reach canonical status. Think of each amendment as a self-contained record of change: what was proposed, what was built, what proves it works, and why it was accepted.
An amendment goes through independent review without touching the base Shape. When it reaches canonical status, its fields are integrated into the base Shape so that the base always reflects the current effective state. The base Shape acts as a materialized view of current truth; amendment records are the immutable audit trail.
Amendment:
id: AmendmentId
name: string
description: string
# → §2 What is a Shape?
shape_id: ShapeId
# monotonic sequence number within the shape
seq: int
# → §3 Lifecycle
# one of:
status:
proposed | promoted | canonical | rejected | abandoned:
date: iso8601
reason: string?
uris: [string]?
semver_change: major | minor | patch
# which parts of the Shape were touched
# e.g. "intent.goals", "constraints"
affected_paths:
- string
# → §2.2 Intent
intent: Intent
constraints:
- Constraint | ConstraintId?
# → §6.1 Realization Bindings
realization:
- RealizationBinding?
# → §6.2 Evidence
evidence:
- EvidenceRef?
initiated_by:
type: human | agent | system
identity: string?
provenance_ref: string?When the amendment canonicalizes, its fields are merged into the base Shape and the Shape's version is bumped according to semver_change. The amendment record remains as the audit trail showing how each piece got there.
If an amendment is large enough to constitute a fundamental redesign, it may be more appropriate to supersede the Shape and propose a new one.
To see how amendments work in practice, here is the Team Invitations Shape from earlier — now showing the base Shape after an amendment has been applied, alongside the amendment record itself.
Shape:
id: 3
name: Invitations
description: Email-based team invitation workflow.
kind: feature
version: 1.1.0
# → §3 Lifecycle
status:
canonical:
date: "2026-01-15"
# → §2.2 Intent
intent:
summary: Allow administrators to invite users by email.
goals:
- Reduce setup friction for new teams
- Keep invitation issuance restricted to trusted actors
# applied from amendment 5
- Support Apple sign-in for invitation acceptance
non_goals:
- Guest access
constraints:
- id: 1
kind: invariant
rule: only admins may create invitations
enforcement: machine
# applied from amendment 5
- id: 2
kind: requirement
rule: invitation acceptance must support Apple sign-in
enforcement: machine
- 4
# → §6.1 Realization Bindings
realization:
- uris:
- https://github.com/acme/invitations/blob/a1b2c3d/src/service.rs#L40-L118
# applied from amendment 5
- https://github.com/acme/invitations/blob/a1b2c3d/src/apple_oauth.rs#L1-L95
role: primary
# → §6.2 Evidence
evidence:
- id: ci_123
type: test_report
uris:
- https://ci.example/123
trusted: true
# applied from amendment 5
- id: ci_456
type: test_report
uris:
- https://ci.example/456
trusted: true
# → §8 Boundaries
provenance:
- type: agent_trace
trace_record_id: 550e8400-e29b-41d4-a716-446655440000
# → §4 Amendments
amendment_log:
- 5Amendment:
id: 5
name: Apple Sign-In
description: Add Apple sign-in for invitation acceptance.
# → §2 What is a Shape?
shape_id: 3
seq: 1
# → §3 Lifecycle
status:
canonical:
date: "2026-02-14"
semver_change: minor
affected_paths:
- intent.goals
- constraints
- realization
- evidence
# → §2.2 Intent
intent:
summary: >
Add Apple sign-in as an accepted authentication method
for invitation acceptance, alongside existing Google support.
rationale: >
User research showed 34% of target users prefer Apple sign-in.
Restricting to Google-only created unnecessary friction during
team onboarding.
goals:
- Support Apple sign-in for invitation acceptance
constraints:
- id: 2
kind: requirement
rule: invitation acceptance must support Apple sign-in
enforcement: machine
# → §6.1 Realization Bindings
realization:
- uris:
- https://github.com/acme/invitations/blob/a1b2c3d/src/apple_oauth.rs#L1-L95
role: primary
# → §6.2 Evidence
evidence:
- id: ci_456
type: test_report
uris:
- https://ci.example/456
trusted: true
initiated_by:
type: human
identity: user.admin.jane5. Constraints
Shapes and Amendments embed constraints inline when a rule is specific to a single record. But many constraints are cross-cutting — they apply to multiple Shapes across a system. Defining the same rule inline in every Shape that must obey it creates duplication and drift.
A standalone Constraint is a first-class graph node: it has its own identity, lifecycle, intent, realization bindings, and evidence. Shapes reference it by ID rather than repeating its content. In standalone form, a Constraint relates to Shapes the same way an Amendment does — through explicit references rather than nesting.
The dual model is deliberate. Inline constraints remain for Shape-specific rules that have no reason to be shared. Standalone Constraints are for rules that span boundaries — organization-wide policies, cross-service invariants, or compliance requirements that many Shapes must satisfy.
Constraints have their own lifecycle because enforcement is proven incrementally. A proposed Constraint declares the rule. A promoted Constraint is accepted in direction — teams begin implementing enforcement. A canonical Constraint is backed by realization bindings and evidence proving the rule holds.
5.1 Standalone Constraints
A standalone Constraint record carries the same semantic weight as a Shape: it declares what must be true, why, and how to prove it. The schema mirrors Shapes in structure — intent, realization, evidence, provenance — because a Constraint must earn its canonical status through the same process.
Constraint:
id: ConstraintId
name: string
description: string
kind: invariant | requirement | policy | limit
rule: string
enforcement: machine | human | hybrid
version: semver
# Lineage → §3 Lifecycle
predecessors: [ConstraintId]?
# → §3 Lifecycle
# one of:
status:
proposed | promoted | canonical | rejected | abandoned | reverted:
date: iso8601
reason: string?
uris: [string]?
superseded:
date: iso8601
reason: string?
uris: [string]?
successors: [ConstraintId]
intent: Intent
# → §6.1 Realization Bindings
realization:
- RealizationBinding?
# → §6.2 Evidence
evidence:
- EvidenceRef?
# → §8 Boundaries and Extensibility
provenance:
- ProvenanceRef?
# → §4 Amendments
amendment_log:
- AmendmentRef?The kind field classifies the nature of the rule. Invariant is a property that must always hold. Requirement is something the system must do. Policy is an organizational rule. Limit is a quantitative bound. This list is intentionally open — projects may add their own kinds.
The enforcement field indicates how the rule is upheld: machine for automated enforcement (validators, automated checks, rule engines), human for review-based enforcement, or hybrid when both are needed.
Standalone Constraints can be amended just like Shapes. If a rule evolves — "only admins" becomes "admins and org owners" — that change is recorded as an amendment to the Constraint, not as a new Constraint. The amendment log preserves the history of how the rule evolved.
Constraint:
id: 4
name: Admin Guard
description: Only admin-role users may perform destructive actions.
kind: policy
rule: only users with the admin role may perform destructive actions
enforcement: machine
version: 1.0.0
# → §3 Lifecycle
status:
canonical:
date: "2025-11-20"
intent:
summary: >
Restrict destructive operations (delete, revoke, disable) to
admin-role users to prevent accidental or unauthorized data loss.
rationale: >
Incident INC-2024-031 traced to a member-role user accidentally
deleting a production dataset. Policy adopted org-wide.
# → §6.1 Realization Bindings
realization:
- uris:
- https://github.com/acme/platform/blob/main/src/middleware/admin_guard.rs#L12-L45
role: primary
# → §6.2 Evidence
evidence:
- id: ci_789
type: test_report
uris:
- https://ci.example/789
trusted: true5.2 Constraint References
Inline constraints define rules specific to a single Shape. ConstraintId references point to standalone Constraints defined elsewhere — shared, cross-cutting rules that apply to many Shapes. The Constraint record carries all semantic weight; the reference is a simple pointer.
Shape:
id: 3
name: Invitations
description: Email-based team invitation workflow.
kind: feature
version: 1.1.0
status:
canonical:
date: "2026-01-15"
intent:
summary: Allow administrators to invite users by email.
constraints:
# inline: specific to this Shape
- id: 1
kind: invariant
rule: only admins may create invitations
enforcement: machine
# shared: defined once, referenced by many Shapes
# → §5.1 Standalone Constraints
- 4When an Amendment adds a constraint — whether inline or a reference — it is integrated into the base Shape upon canonicalization, the same merge process used for all other amendment fields.
6. Connecting to Artifacts
Shapes are semantic declarations. They become useful when connected to concrete artifacts — or to other Shapes — and backed by evidence. Because bindings and evidence can reference Shapes as well as artifacts, the model extends beyond a tree into a graph that can describe systems of systems.
6.1 Realization Bindings
Realization bindings connect a Shape to the artifacts that embody it: documents, designs, deliverables, references, verifications, or other project surfaces. A binding can also reference another Shape, so that one Shape is realized by the existence or canonical status of another — enabling composition across project boundaries. Each binding groups related URIs under a single role.
RealizationBinding:
uris:
- string
role: primary | supporting | interface | verification | migration | docs
revision: string?6.2 Evidence
Evidence is distinct from realization. Realization answers, what artifacts embody this Shape? Evidence answers, why should the system believe the Shape is satisfied?
Evidence may include verification reports, automated check results, benchmarks, reviews, inspection records, or attestations. Evidence can also reference other Shapes — for example, a parent Shape may cite the canonical status of its child Shapes as proof of satisfaction. A Promoted Shape may accumulate evidence as work progresses toward canonicalization. The spec does not require a single trust model, but evidence references should be explicit enough for tools and reviewers to inspect them.
7. Boundaries and Extensibility
The Shapes specification records semantics and lifecycle management. Provenance systems record origin. That boundary is deliberate: a Shape may reference provenance, but it should not inline or redefine a separate provenance specification.
- Shapes owns intent, constraints, semantic status, and the canonical project model.
- Agent Trace or equivalent systems own contributor attribution, conversation lineage, and revision-scoped origin details.
- Shapes may keep a lightweight provenance reference when semantic review needs a pointer back to origin records.
Shapes is intentionally open at the edges. Different projects will need different field vocabularies, constraint types, evidence sources, and realization roles. The draft therefore standardizes the semantic frame before it standardizes every possible payload.
Extensions should preserve the core separation of concerns. New Shape kinds, binding roles, or evidence types are acceptable so long as they do not blur the distinction between semantics, embodiment, proof, and provenance.