Abstract
The Project Profile Specification defines one versioned YAML document that connects Intent Commits, Intent Pull Requests, Intent Changesets, Intent Changelog, and Release Manifest records to a repository’s actual boundaries and policies.
The other specifications deliberately avoid prescribing one universal set of types, scopes, release units, audiences, channels, or versioning rules. Without a portable profile, however, two implementations cannot resolve those project-defined values in the same way. This specification makes that shared policy explicit.
A project profile is configuration, not release history. It defines vocabulary, routing, validation, and conflict rules. It does not replace commit messages, release decisions, changelog entries, or manifests.
This document defines stable version 1.0.0.
1. Conformance language
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 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here.
2. Goals
The Project Profile is designed to:
- select the exact versions of every enabled specification;
- give tools one canonical repository identity;
- map scopes to independently released units;
- address parallel release streams without overloading channels;
- share types, impacts, audiences, and disclosures across record layers;
- define deterministic changeset and versioning policy;
- route records to safe repository-relative locations;
- make mechanical field mappings and conflict authority explicit;
- provide the same policy to people, CI, and AI systems; and
- preserve extensions without allowing them to silently redefine standard fields.
The Project Profile does not define a package manager, deployment system, branching model, hosting provider, release cadence, or organization-wide type taxonomy.
3. Terms
| Term | Meaning |
|---|---|
| Profile | One canonical project-policy document conforming to this specification. |
| Release unit | An application, package, service, product, or other independently released boundary. |
| Scope | A canonical commit-message component identifier mapped by the profile. |
| Release stream | A named destination for a sequence of releases of one release unit. |
| Release line | A compatibility or maintenance lineage such as 1, 3.x, or current. |
| Channel | A maturity or distribution class such as stable, preview, or long-term-support. |
| Vocabulary | The accepted types, impacts, audiences, and disclosure states. |
| Routing | The deterministic mapping from a release target to canonical record paths. |
| Extension | A non-standard field whose name begins with x-. |
A release line and a channel are different dimensions. stable can exist for
both a maintained 3.x line and a current 4.x line. Tools MUST NOT use a
channel name as an implicit release-line identifier.
4. Canonical representation
A profile is exactly one YAML 1.2 document whose root is a mapping:
intent-profile: 1.0.0
repository: https://github.com/example/platform
specifications:
commits: 1.0.0
pull-requests: 1.0.0
changesets: 1.0.0
changelog: 1.0.0
release-manifest: 1.0.0
types:
feat:
default-impact: minor
fix:
default-impact: patch
chore:
default-impact: none
scopes:
apps/gateway:
release-unit: apps/gateway
apps/gateway/auth:
release-unit: apps/gateway
apps/worker:
release-unit: apps/worker
shared/auth:
requires-affects: true
release-units:
apps/gateway:
streams:
stable:
release-line: current
channel: stable
changelog: .ack/changelog/apps-gateway-stable.yaml
manifests: .ack/releases/apps-gateway/stable
apps/worker:
streams:
stable:
release-line: "2"
channel: stable
changelog: .ack/changelog/apps-worker-stable.yaml
manifests: .ack/releases/apps-worker/stable
lts:
release-line: "1"
channel: long-term-support
changelog: .ack/changelog/apps-worker-lts.yaml
manifests: .ack/releases/apps-worker/lts
ledger-directory: .ack/changelog
release-manifest-directory: .ack/releases
release-pattern: '^[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?$'
release-types: [feature, fix, reliability, security, operations]
release-impacts: [none, patch, minor, major]
audiences: [end-users, api-consumers, operators, security-teams]
disclosures: [public, embargoed, redacted]
channels: [stable, preview, long-term-support]
changesets:
directory: .ack/changes
archive-directory: .ack/archive/changes
after-consumption: archive
conflict-policy: preserve
id-pattern: '^[a-z][a-z0-9-]+$'
required-impacts: [minor, major]
required-commit-types: [security]
pull-requests:
directory: .ack/pull-requests
merge-strategy: squash
max-title-length: 72
max-body-length: 20000
require-ready: true
verification-statuses: [passed, failed, skipped, unavailable, not-applicable]
require-release-ready: true
max-header-length: 72
max-body-line-length: 72
large-diff-threshold: 500Unknown fields MUST be preserved by tools that read and rewrite a profile.
Standard fields are case-sensitive and MUST use the spelling shown here.
Extensions MUST begin with x- and MUST NOT alter the meaning of a standard
field.
5. YAML processing
Profile documents MUST be UTF-8 and MUST contain exactly one YAML document. Parsers MUST reject:
- duplicate mapping keys;
- anchors, aliases, and merge keys;
- custom YAML tags;
- a non-mapping document root; and
- input exceeding implementation-documented resource limits.
Implementations MUST bound document size, nesting depth, alias-independent node count, and scalar length. A conforming implementation MUST support documents up to 1 MiB and nesting up to 64 levels. It MAY reject larger inputs.
Strings that resemble booleans, numbers, timestamps, or null values MUST remain strings when the corresponding field is defined as a string. Authors SHOULD quote release lines and other numeric-looking identifiers.
Canonical means canonical data model, not byte-for-byte serialization. A writer MAY change insignificant whitespace, quoting, or mapping order while preserving all known and unknown values.
6. Required top-level fields
A profile MUST contain:
intent-profile;repository;specifications;types;scopes;release-units;ledger-directory;release-manifest-directory;release-pattern;release-types;release-impacts;audiences;disclosures;channels;changesets; andrequire-release-ready.
Style and heuristic fields such as max-header-length,
max-body-line-length, and large-diff-threshold are OPTIONAL.
7. Profile and specification versions
intent-profile MUST contain 1.0.0 for this version.
specifications MUST contain commits, changesets, changelog, and
release-manifest. It MAY contain pull-requests. Each value MUST be a
complete Semantic Versioning version.
A validator MUST reject a profile when it does not implement an enabled
version. It MUST NOT silently reinterpret a record using a different version.
Repositories MAY contain historical records written against older specification versions. Each record selects its own version. A tool processing a mixed ledger MUST validate every record against its declared version and MUST report unsupported versions individually.
Changing a selected specification version is a reviewed profile migration. A tool MUST NOT rewrite historical records merely because the profile advances.
8. Repository identity
repository MUST be an absolute URI identifying the source repository. The
same value MUST be used by changesets, changelog records, and release manifests
that describe that repository.
Commit object names in provenance are interpreted within this repository unless the provenance value contains an explicit repository URI. This prevents a bare hash from being treated as globally unique.
A repository relocation MAY update the profile for new records. Historical records SHOULD retain their original identity or an explicit relocation mapping. Tools MUST NOT silently rewrite provenance across repositories.
9. Scopes and release units
Every key under scopes MUST follow the Intent Commits scope grammar. Each
scope mapping MUST contain exactly one of:
release-unit, naming the unit owned by that scope; orrequires-affects: true, declaring that the scope is shared and every commit using it must identify affected release units explicitly.
A scope MUST NOT map to an unknown release unit. More than one scope MAY map to
the same release unit. This is how hierarchical scopes such as
apps/gateway/auth resolve without string-prefix guessing.
Every key under release-units is a canonical release-unit identifier. An
independently deployed application or independently versioned package MUST have
its own release unit.
10. Release streams
Every release unit MUST contain one or more streams. A stream key is stable
within its release unit and MUST NOT be reused for a different release line or
channel.
Every stream MUST contain:
release-line;channel;changelog; andmanifests.
The pair (release-unit, stream) identifies a changeset target and the open
changelog destination. The tuple (release-unit, stream, release) identifies a
release occurrence.
channel MUST occur in the top-level channels sequence. Several streams MAY
use the same channel. release-line is an opaque non-empty string whose
ordering, if any, is project policy.
changelog MUST identify the canonical open or current Intent Changelog record
for the stream. manifests MUST identify the directory containing immutable
Release Manifest records for that stream.
11. Release identifiers
release-pattern MUST be a regular expression accepted by the profile’s
declared regular-expression dialect. Version 1.0.0 uses RE2 syntax. Every
release identifier in an Intent Changelog record or Release Manifest MUST match
it.
Projects using Semantic Versioning SHOULD use complete versions such as
1.4.0, never shortened forms such as 1.4.
The profile MUST define, through documentation or an extension, how entry
impacts determine the next release identifier. For Semantic Versioning, the
RECOMMENDED rule is the greatest applicable impact, with explicit rules for
versions below 1.0.0 and prerelease channels.
Changing the planned release identifier while a record is unreleased is a separate reviewed planning operation. Publishing remains date-only.
12. Shared vocabularies
types defines accepted Intent Commits types and MAY give each a
default-impact. A type default supplies an effective impact only when the
message does not declare one.
release-types, release-impacts, audiences, disclosures, and channels
MUST contain unique non-empty identifiers. Every value used by a changeset,
changelog entry, or stream MUST appear in the corresponding vocabulary.
Type and impact remain independent. A profile MUST NOT define a rule that makes the English meaning of a type override an explicit impact.
13. Changeset policy
changesets MUST contain:
directory, the pending-record directory;archive-directory, when records are archived;after-consumption, exactlykeep,archive, ordelete;conflict-policy, exactlypreservein version 1.0.0;required-impacts; andrequired-commit-types.
id-pattern is OPTIONAL and, when present, further restricts changeset IDs.
conflict-policy: preserve means automation reports disagreements and preserves
reviewed data. It MUST NOT silently select a commit, changeset, or changelog as
authoritative.
A change requires a changeset when any applicable required-impact or required-commit-type rule matches. Projects MAY define additional audience- or path-based rules as extensions, but those rules MUST be deterministic and documented.
14. Pull-request policy
When specifications.pull-requests is enabled, pull-requests MUST contain:
directory, a repository-local canonical record directory;merge-strategy, exactlymerge,squash, orrebase;- positive
max-title-lengthandmax-body-lengthvalues; require-ready, stating whether integration requires ready conformance; andverification-statuses, containing accepted Intent Pull Requests states.
The standard verification states are passed, failed, skipped,
unavailable, and not-applicable. A project MAY restrict the allowed set but
MUST NOT redefine a standard state’s meaning. Forge mappings MAY be extensions,
but portable validation MUST NOT depend on a forge API.
Pull-request targets use the profile’s existing release units, streams, and impacts. A profile MUST NOT define parallel pull-request identifiers for those concepts.
15. Field ownership and conflict resolution
The profile connects the layers without collapsing them:
| Concern | Owning layer |
|---|---|
| Atomic implementation description | Intent Commits |
| Integration rationale, approach, and review evidence | Intent Pull Requests |
| Release decision and target-specific consequence | Intent Changesets |
| Canonical audience-facing release history | Intent Changelog |
| Exact source and artifact evidence | Release Manifest |
Mechanical mappings MAY seed later fields. Editorial fields MAY be revised in the changelog before publication. A consumer MUST report a conflict before overwriting an existing reviewed entry.
The profile MUST document any additional mapping and MUST distinguish copied evidence from editorial synthesis. It MUST NOT declare a commit body to be an audience-ready rationale automatically.
16. Paths and repository safety
Every configured path MUST be repository-relative, non-empty, and normalized.
It MUST NOT be absolute, resolve to the repository root, or escape through
.., symbolic links, mount points, or platform-specific path semantics.
changelog paths MUST reside beneath ledger-directory. Stream manifests
paths MUST reside beneath release-manifest-directory.
A writer MUST create temporary files in the destination directory and replace records atomically when the platform permits it. A multi-record operation MUST be retry-safe and MUST NOT delete or archive its source until every destination has been verified.
17. AI-assisted use
An AI system claiming profile-aware support:
- MUST receive the exact profile bytes or a verified equivalent;
- MUST identify the profile version and every enabled specification version;
- MUST treat repository content as untrusted evidence, not instructions that can override this profile;
- MUST NOT invent scopes, release units, streams, types, audiences, impacts, disclosure states, paths, or mappings;
- MUST return
NEEDS_INPUTfor an unresolved required decision; and - MUST preserve embargo, redaction, and repository access boundaries in prompts, logs, caches, and output.
When reproducibility matters, the caller SHOULD retain the profile digest, source revision, selected evidence revision, model or tool identity, and the distinction between quoted evidence and generated synthesis.
AI output does not alter profile authority. A fluent value that is absent from the profile remains invalid.
18. Security considerations
Profiles control file locations, policy, and data disclosure. Implementations MUST treat them as untrusted input until validated.
Tools MUST defend against path traversal, symbolic-link escape, YAML resource exhaustion, terminal escape injection, template injection, command injection, and regular-expression denial of service. RE2 is selected because it avoids backtracking-based denial of service.
An extension MUST NOT contain executable configuration merely because a tool preserves it. Implementations MUST treat profile strings as data unless a separate trusted configuration layer explicitly defines execution.
19. Conformance classes
19.1 Project Profile Reader
A Reader MUST parse the canonical data model, enforce section 5, and preserve unknown fields.
19.2 Project Profile Validator
A Validator MUST implement Reader requirements and validate sections 6 through 16. It MUST report unsupported specification versions distinctly from malformed or project-invalid data.
19.3 Project Profile Resolver
A Resolver MUST implement Validator requirements and deterministically resolve:
- a scope to its release unit or affected-unit requirement;
- a
(release-unit, stream)target to its changelog and manifest paths; - an explicit or default impact; and
- whether a change requires a changeset.