Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ jobs:
node-version: 22
- name: Validate the pattern registry
run: node library/scripts/build-registry.ts --check
- name: Validate MAP schemas and fixtures
run: node library/scripts/validate-schemas.ts

sdk:
runs-on: ubuntu-latest
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/release-patterns.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@ jobs:
node-version: 22
- name: Build registry artifact
if: steps.check.outputs.exists == 'false'
run: node library/scripts/build-registry.ts --out library/dist/registry.json
run: |
node library/scripts/validate-schemas.ts
node library/scripts/build-registry.ts --out library/dist/registry.json
- name: Create release
if: steps.check.outputs.exists == 'false'
env:
GH_TOKEN: ${{ github.token }}
run: |
TAG="v${{ steps.version.outputs.version }}"
gh release create "$TAG" --target "$GITHUB_SHA" --title "$TAG" --generate-notes library/dist/registry.json
gh release create "$TAG" --target "$GITHUB_SHA" --title "$TAG" --generate-notes \
library/dist/registry.json library/schemas/*.schema.json
1 change: 1 addition & 0 deletions .map/map.config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"version": 3,
"specVersion": "0.1",
"project": {
"name": "map",
"createdAt": "2026-09-10T17:17:53.644Z",
Expand Down
2 changes: 2 additions & 0 deletions library/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ An open, framework-agnostic knowledge base of AI Engineering patterns.

[Philosophy](docs/philosophy.md) ·
[Patterns](patterns/) ·
[Schemas](docs/schemas/) ·
[Roadmap](ROADMAP.md) ·
[Contributing](CONTRIBUTING.md) ·
[Pattern Template](patterns/_template/PATTERN_TEMPLATE.md)
Expand Down Expand Up @@ -106,6 +107,7 @@ map/
reference/ Layer 3, Reference: small implementations (python, typescript)
examples/ Layer 3: end-to-end examples that combine several patterns
rfcs/ Design documents for changes that shape the MAP standard
schemas/ JSON Schema contracts, examples, and invalid fixtures
templates/ Generic prompt.md / acceptance.md skeletons patterns start from
scripts/ Registry builder: compiles the catalog into registry.json
.github/ Contributor experience: templates, labels, discussions, CI
Expand Down
1 change: 1 addition & 0 deletions library/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Specifications (the contracts tools build on — see the
- **[Pattern Lifecycle](specs/pattern-lifecycle.md)** — claiming, maturity, deprecation, and renames. *(draft)*
- **[Decision Guides](specs/decision-guides.md)** — cross-category "X or Y?" guides and their contract. *(draft)*
- **[Website](specs/website.md)** — the ultra-simple registry-fed site. *(draft)*
- **[MAP Schemas](schemas/README.md)** — machine contracts paired with human guides and fixtures.

For the patterns themselves, see [`../patterns/`](../patterns/). To contribute, see
[`../CONTRIBUTING.md`](../CONTRIBUTING.md). The `map` CLI lives in
Expand Down
13 changes: 13 additions & 0 deletions library/docs/schemas/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# MAP schemas

MAP schemas are contracts, not a replacement for documentation. Each schema is
published with a guide, examples, invalid fixtures, and an offline CI check.

| Contract | Machine-readable | Human-readable |
|---|---|---|
| Typed `.map/` document frontmatter | [`document.schema.json`](../../schemas/document.schema.json) | [Document envelope](document.md) |
| `.map/map.config.json` | [`project.schema.json`](../../schemas/project.schema.json) | [Project manifest](project.md) |

Schemas use JSON Schema draft 2020-12. Stable fields are strict; experiments use an
`x-` prefix. A schema change that alters accepted meaning requires compatibility and
migration notes.
58 changes: 58 additions & 0 deletions library/docs/schemas/document.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# MAP document envelope

The document envelope is the YAML frontmatter shared by typed Markdown files in
`.map/`. Frontmatter lets software select and validate a document; the Markdown body
explains the contract to people and agents.

Machine contract: [`document.schema.json`](../../schemas/document.schema.json).

## Fields

| Field | Required | Meaning |
|---|---:|---|
| `kind` | yes | Document type, such as `decision`, `agent`, `prompt`, or a namespaced extension. |
| `id` | yes | Stable identifier unique within `kind`; do not reuse it for different meaning. |
| `title` | yes | Short human name shown by tools. |
| `date` | no | ISO calendar date associated with the document or decision. |
| `status` | yes | Lifecycle state: `proposed`, `draft`, `active`, `accepted`, `rejected`, `superseded`, `deprecated`, or `archived`. |
| `scope` | no | One path glob or a unique list of globs where the contract applies. |
| `priority` | no | Compiler order: `high`, `normal` (default), or `low`. It is not permission or severity. |
| `targets` | no | Target adapters that receive the document. Omission means every configured target. |
| `x-*` | no | Namespaced experimental metadata preserved without becoming part of the stable contract. |

The namespace is the pair `kind` + `id`; an ID does not need to repeat its kind.
Lowercase kebab-case keeps references and Git diffs stable.

## Complete example

```markdown
---
kind: decision
id: adr-0001-human-and-ai-readable-contracts
title: Human- and AI-readable project contracts
date: 2026-09-13
status: accepted
scope: [".map/**", "library/schemas/**"]
priority: high
targets: [agents, claude, cursor]
x-owner: architecture
---

# ADR-0001: Human- and AI-readable project contracts

## Context

People need reasoning and tools need stable fields.

## Decision

Keep typed YAML frontmatter and explanatory Markdown in one canonical file.
```

## Validation and migration

Validation errors identify the file, JSON-style field path, reason, and expected
shape. Existing Markdown without frontmatter remains valid as legacy context and uses
compiler defaults. To make it a typed contract, add all four required fields in one
change; no body rewrite is required. Once published, change meaning through a new
document and lifecycle link rather than reusing an ID.
65 changes: 65 additions & 0 deletions library/docs/schemas/project.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# MAP project manifest

`.map/map.config.json` identifies a MAP project and configures analysis, registry,
context compilation, packs, and project tools. It is read by `map init`, `map doctor`,
editors, CI, and agents.

Machine contract: [`project.schema.json`](../../schemas/project.schema.json).

## Version fields

- `version` is the on-disk configuration revision understood and migrated by the CLI.
The current revision is `3`; revision `2` stays valid.
- `specVersion` identifies the MAP Standard contract. It is optional for existing v2
and v3 workspaces. New workspaces write `"0.1"` while the standard is pre-1.0.

Changing `version` can require `map init --yes` migration. A compatible addition to
the standard changes `specVersion` without silently rewriting user configuration.

## Top-level fields

| Field | Required | Meaning |
|---|---:|---|
| `version` | yes | CLI configuration revision. |
| `specVersion` | no | MAP Standard version; generated for new workspaces. |
| `project` | yes | Name, creation time, and detected languages. |
| `analysis` | yes | Analyzer IDs plus project-relative include/exclude globs. |
| `registry` | yes | `default`, a URL, or a local registry source. |
| `packs` | no | Unique namespaced pack requirements and optional version ranges. |
| `tools` | no | Project tool settings, currently the token optimizer. |
| `sources` | no | Markdown globs loaded from `.map/`; defaults to `**/*.md`. |
| `targets` | no | Adapter/output mapping for generated agent context. |
| `x-*` | no | Experimental project metadata. |

Paths and globs are project-relative. Absolute paths and `..` traversal are rejected.
Unknown stable fields fail validation; prefix experiments with `x-`.

## Minimal example

```json
{
"version": 3,
"specVersion": "0.1",
"project": {
"name": "example",
"createdAt": "2026-09-13T08:00:00.000Z",
"languages": []
},
"analysis": { "analyzers": [], "include": [], "exclude": [] },
"registry": { "source": "default" }
}
```

## Full example

See [`fixtures/project/valid/full.json`](../../schemas/fixtures/project/valid/full.json).
It shows scoped analysis, a pack requirement, token budgeting, source selection, and
multiple generated targets.

## Compatibility and rollback

The schema accepts existing v2/v3 manifests without `specVersion`, `packs`, `sources`,
or `targets`. New fields are additive. Older CLI releases ignore `specVersion` and
`packs`; pack resolution is intentionally a later capability. To roll back, remove
those optional fields. The CLI never rewrites an existing manifest without the
explicit `--force` path already used by `map init`.
63 changes: 63 additions & 0 deletions library/schemas/document.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://raw.githubusercontent.com/rajanbor/map/main/library/schemas/document.schema.json",
"title": "MAP document frontmatter",
"description": "Shared machine-readable envelope for typed Markdown documents in .map/.",
"type": "object",
"required": ["kind", "id", "title", "status"],
"properties": {
"kind": {
"type": "string",
"pattern": "^[a-z][a-z0-9]*(?:[/-][a-z0-9][a-z0-9-]*)*$"
},
"id": {
"type": "string",
"pattern": "^[a-z][a-z0-9]*(?:[/-][a-z0-9][a-z0-9-]*)*$"
},
"title": { "type": "string", "minLength": 1 },
"date": {
"type": "string",
"pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
},
"status": {
"enum": [
"proposed",
"draft",
"active",
"accepted",
"rejected",
"superseded",
"deprecated",
"archived"
]
},
"scope": {
"oneOf": [
{ "type": "string", "minLength": 1 },
{
"type": "array",
"items": { "type": "string", "minLength": 1 },
"minItems": 1,
"uniqueItems": true
}
]
},
"priority": {
"enum": ["high", "normal", "low"],
"default": "normal"
},
"targets": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-z][a-z0-9-]*$"
},
"minItems": 1,
"uniqueItems": true
}
},
"patternProperties": {
"^x-[a-z0-9][a-z0-9-]*$": true
},
"additionalProperties": false
}
6 changes: 6 additions & 0 deletions library/schemas/fixtures/document/invalid/bad-id.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"kind": "decision",
"id": "ADR 1",
"title": "An identifier with spaces",
"status": "proposed"
}
5 changes: 5 additions & 0 deletions library/schemas/fixtures/document/invalid/missing-id.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"kind": "decision",
"title": "A decision without stable identity",
"status": "proposed"
}
7 changes: 7 additions & 0 deletions library/schemas/fixtures/document/invalid/unknown-field.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"kind": "agent",
"id": "reviewer",
"title": "Reviewer",
"status": "active",
"vendorMagic": true
}
11 changes: 11 additions & 0 deletions library/schemas/fixtures/document/valid/decision.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"kind": "decision",
"id": "adr-0001-human-and-ai-readable-contracts",
"title": "Human- and AI-readable project contracts",
"date": "2026-09-13",
"status": "accepted",
"scope": [".map/**", "library/schemas/**"],
"priority": "high",
"targets": ["agents", "claude", "cursor"],
"x-owner": "architecture"
}
11 changes: 11 additions & 0 deletions library/schemas/fixtures/project/invalid/empty-targets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"version": 3,
"project": {
"name": "example",
"createdAt": "2026-09-13T08:00:00.000Z",
"languages": []
},
"analysis": { "analyzers": [], "include": [], "exclude": [] },
"registry": { "source": "default" },
"targets": {}
}
5 changes: 5 additions & 0 deletions library/schemas/fixtures/project/invalid/missing-project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"version": 3,
"analysis": { "analyzers": [], "include": [], "exclude": [] },
"registry": { "source": "default" }
}
10 changes: 10 additions & 0 deletions library/schemas/fixtures/project/invalid/path-traversal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"version": 3,
"project": {
"name": "example",
"createdAt": "2026-09-13T08:00:00.000Z",
"languages": []
},
"analysis": { "analyzers": [], "include": ["../secret/**"], "exclude": [] },
"registry": { "source": "default" }
}
11 changes: 11 additions & 0 deletions library/schemas/fixtures/project/invalid/unknown-field.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"version": 3,
"project": {
"name": "example",
"createdAt": "2026-09-13T08:00:00.000Z",
"languages": []
},
"analysis": { "analyzers": [], "include": [], "exclude": [] },
"registry": { "source": "default" },
"magic": true
}
31 changes: 31 additions & 0 deletions library/schemas/fixtures/project/valid/full.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"version": 3,
"specVersion": "0.1",
"project": {
"name": "support-agent",
"createdAt": "2026-09-13T08:00:00.000Z",
"languages": ["typescript", "python"]
},
"analysis": {
"analyzers": ["typescript", "python"],
"include": ["src/**", "services/**"],
"exclude": ["**/node_modules/**", "**/dist/**"]
},
"registry": { "source": "default" },
"packs": [
{ "name": "@map/reviewer", "version": "^1.0.0" }
],
"tools": {
"tokenOptimizer": {
"budget": 12000,
"include": ["**/*.md"],
"exclude": ["reports/**", "cache/**"]
}
},
"sources": ["**/*.md"],
"targets": {
"agents": { "output": "AGENTS.md" },
"cursor": { "output": ".cursor/rules/map.mdc", "adapter": "cursor" }
},
"x-team": "platform"
}
15 changes: 15 additions & 0 deletions library/schemas/fixtures/project/valid/minimal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"version": 3,
"specVersion": "0.1",
"project": {
"name": "example",
"createdAt": "2026-09-13T08:00:00.000Z",
"languages": []
},
"analysis": {
"analyzers": [],
"include": [],
"exclude": []
},
"registry": { "source": "default" }
}
Loading
Loading