Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
1eb6fc4
chore: start @directededges/specs-schema v0.30.0 development
nathanacurtis Aug 7, 2026
64c3585
chore: start @directededges/specs-cli v0.27.0 development
nathanacurtis Aug 7, 2026
8392fe7
docs(adr): claim ADR 066 in INDEX
nathanacurtis Aug 10, 2026
501a58a
Point the engine link at its package inside the monorepo
nathanacurtis Aug 11, 2026
b119ea6
ADR-066: Lossless key formatting — safe key grammar and Figma name pr…
nathanacurtis Aug 11, 2026
a7083f6
docs(adr): drop the stale draft row for ADR-066
nathanacurtis Aug 11, 2026
6b43777
docs(adr): clear stale draft rows and stop the accept flow leaving them
nathanacurtis Aug 11, 2026
98f677f
docs(adr): reconcile ADR statuses with what the schema actually ships
nathanacurtis Aug 11, 2026
2ed89f5
feat(site): publish accepted ADRs as a generated docs section (#301)
nathanacurtis Aug 11, 2026
efb3804
docs(cli): fold the orphaned second Unreleased section into the first
nathanacurtis Aug 12, 2026
e8629e1
docs(adr): claim ADR number 069
nathanacurtis Aug 14, 2026
e139658
Rename clipContent to clipsContent (ADR-069) (#327)
nathanacurtis Aug 14, 2026
149f960
render: spec → Figma, plus the bridge and cache it needs (#329)
nathanacurtis Aug 16, 2026
4999398
docs(render): drop the source-file-caused differences section
nathanacurtis Aug 17, 2026
125fc1a
chore: restore local file: refs for development
nathanacurtis Aug 17, 2026
bcdf118
adr(index): claim 070 explicit-absolute-position
nathanacurtis Aug 17, 2026
9b2724d
fix(site): run generators in docs deploy via npm run build
nathanacurtis Aug 17, 2026
d49c286
release: @directededges/specs-schema v0.30.0
nathanacurtis Aug 17, 2026
6ffbedd
release: @directededges/specs-cli v0.27.0
nathanacurtis Aug 17, 2026
5bb8fde
merge: main into release/schema-0.30.0+cli-0.27.0
nathanacurtis Aug 17, 2026
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
56 changes: 42 additions & 14 deletions .github/agents/Specs.adr.accept.agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,42 +17,70 @@ You **MUST** consider the user input before proceeding (if not empty).
- Use `BRANCH` directly as `ADR_NAME` (e.g., `011-icon-glyph-as-content`).
- The branch name must match an ADR name pattern (starts with a number sequence followed by a hyphen, e.g., `011-`). If no ADR number is found, halt: "Branch does not appear to be an ADR branch."

2. **Load context**:
- **REQUIRED**: Read `$REPO_ROOT/adr/$ADR_NAME.md` — confirm Status is `DRAFT` (if already `ACCEPTED`, report and halt)
2. **Check for an existing PR — do this before any other work.** An ADR branch may already be in review from an earlier session; this command must never open a second PR for the same branch.

```bash
gh pr list --head "$BRANCH" --state all --json number,title,state,baseRefName,url
```

- **An OPEN PR exists** → set `EXISTING_PR` to its number and `$RELEASE_BRANCH` to its `baseRefName`. This run is an *update*, not a creation. Skip step 7 (release-branch determination) — the existing PR's base is authoritative. Report the PR number and base to the user before continuing.
- **A MERGED PR exists** → halt: "This ADR branch was already merged in PR #N. Accepting again would need a new branch."
- **A CLOSED (unmerged) PR exists** → do not reopen or replace it silently. Report it and ask the user whether to open a new PR or reopen that one.
- **No PR exists** → normal path; `EXISTING_PR` is unset.

3. **Load context**:
- **REQUIRED**: Read `$REPO_ROOT/adr/$ADR_NAME.md` — confirm Status is `DRAFT`.
- If already `ACCEPTED` **and** `EXISTING_PR` is set with no uncommitted changes, halt: "ADR is already accepted and PR #N is open — nothing to do."
- If already `ACCEPTED` and there *are* uncommitted changes, this is a follow-up edit: skip the status flip in step 5, and continue so the changes are validated, committed, and pushed to the existing PR.
- Confirm that `types/`, `schema/`, `package.json`, and `CHANGELOG.md` have been modified by the implement agent (check git status or file timestamps)
- If no changes are detected, halt: "Run the implement agent first."
- If no changes are detected **and** `EXISTING_PR` is unset, halt: "Run the implement agent first."

3. **Re-run validation gates**:
4. **Re-run validation gates**:
- Run: `tsc -p tsconfig.build.json --noEmit`
- If exit code ≠ 0: halt and display errors. Do not set ACCEPTED.
- Run: `scripts/validate-schema.sh`
- If any schema fails: halt and report. Do not set ACCEPTED.
- Run: `tsc --noEmit --strict tests/*.test-d.ts` (if `tests/*.test-d.ts` files exist)
- If exit code ≠ 0: halt and display errors. Do not set ACCEPTED.

4. **Mark ADR ACCEPTED**: In `$REPO_ROOT/adr/$ADR_NAME.md` header, change `Status: DRAFT` to `Status: ACCEPTED`.
5. **Mark ADR ACCEPTED**: In `$REPO_ROOT/adr/$ADR_NAME.md` header, change `Status: DRAFT` to `Status: ACCEPTED`. Skip if step 3 determined the ADR is already `ACCEPTED`.

6. **Update INDEX**: Read `adr/INDEX.md` and move this ADR's row from **Draft** to **Accepted**. Treat this as two discrete edits, not one "move" — every stale row in this file got there because the accepted row was added and the draft row was left behind.

1. **Delete** the ADR's row from the **Draft** table. Skip only if it genuinely has no draft row (older ADRs created before INDEX tracking).
2. **Insert** its row into the **Accepted** table, in descending number order, with:
- the **Title** matching the final ADR heading (it may have changed during implementation)
- a **Highlights** summary (max 144 characters) describing the key change as accepted
3. **Verify**: the ADR number must now appear exactly once in the file. Run
`grep -c "^| <NNN> |" adr/INDEX.md` and confirm it returns `1`. If it returns `2`, step 1 did not happen — delete the draft row before continuing.

A draft row left in place is not cosmetic: the draft table is how a reader finds unfinished work, and a stale row carries the pre-acceptance title, so the same ADR appears twice under two different names.

The file also has a **Superseded** table, for an ADR closed in favour of a later decision rather than accepted. Move the row there instead, and name what replaced it in the "Superseded by" column — an ADR abandoned without that pointer reads as merely unfinished.

5. **Update INDEX**: Read `adr/INDEX.md` and update the entry for this ADR:
- Move the row from the **Draft** table to the **Accepted** table (descending by number).
- Update the **Title** to match the final ADR heading (it may have changed during implementation).
- Add a **Highlights** summary (max 144 characters) describing the key change as accepted.
- If no entry exists in the Draft table (older ADR created before INDEX tracking), add the row directly to the Accepted table.
Re-check this after any merge or rebase. A draft row claimed on the release branch while the ADR branch was in flight will reappear when the branches reconcile, leaving a duplicate that neither side authored.

6. **Determine release branch**: Release branches follow the `release/<pkg>-<version>` convention and may jointly cover multiple published packages (e.g., `release/schema-0.21.0-cli-0.16.0`). Do **not** invent a bare version-number branch (e.g., `0.21.0`).
7. **Determine release branch** *(skip entirely if `EXISTING_PR` is set — use that PR's base)*: Release branches follow the `release/<pkg>-<version>` convention and may jointly cover multiple published packages (e.g., `release/schema-0.21.0-cli-0.16.0`). Do **not** invent a bare version-number branch (e.g., `0.21.0`).
1. Find active in-flight release branches with `git branch -r --list 'origin/release/*'`.
2. **Default: use the existing active release branch.** ADR branches are started from the current release branch, so the active branch is the correct target. Do not cross-reference the ADR's semver version against the branch name — the branch name reflects where the release *started*, not the final published version.
3. If exactly one release branch exists, use it as `$RELEASE_BRANCH` without asking.
4. If multiple release branches exist, pick the one the ADR branch was based on (`git merge-base --fork-point` or ask the user).
5. Only if **no** release branch exists at all, create one from `main` following the `release/<pkg>-<version>` convention, naming every package the release will publish.

7. **Create PR**: Commit any uncommitted changes (the status flip and INDEX update), push `$BRANCH`, and open a PR into the release branch using `gh pr create --base $RELEASE_BRANCH`.
8. **Push, and create the PR only if there isn't one**: Commit any uncommitted changes (the status flip and INDEX update) and push `$BRANCH`.
- **`EXISTING_PR` set** → the push updates that PR. Do **not** run `gh pr create`. Read the PR's current body (`gh pr view $EXISTING_PR --json body`) and, if it no longer describes what is on the branch, offer to update it with `gh pr edit $EXISTING_PR --body-file <path>` — ask first, since the user may have written it by hand.
- **`EXISTING_PR` unset** → open a PR into the release branch with `gh pr create --base $RELEASE_BRANCH`.
- Pass long PR bodies via `--body-file`, not an inline heredoc — bodies containing backticks and quotes break shell parsing.

8. **Report**: Confirm all gates passed, the ADR is ACCEPTED, and the PR has been created. List the next steps:
9. **Report**: Confirm all gates passed, the ADR is ACCEPTED, and state whether the PR was **created** or an **existing PR was updated** (with its number). List the next steps:
- Review and merge the PR into the release branch
- When all ADRs for the release are complete, merge `$RELEASE_BRANCH` into `main` and `npm publish`

## Key rules

- This command only flips the ADR status — it does not apply any code changes.
- Status MUST only move to `ACCEPTED` after all three validation gates pass in step 3.
- Status MUST only move to `ACCEPTED` after all three validation gates pass in step 4.
- **Never open a second PR for a branch that already has one.** Step 2 runs before everything else for this reason. This command is re-runnable: an ADR branch may already be in review from an earlier session, and re-running must update that PR, not duplicate it.
- Verify repo and PR state by querying it — never infer from the conversation or assume a branch is fresh.
- **An ADR appears in exactly one INDEX table.** Accepting means deleting the draft row as well as adding the accepted one; verify with the grep in step 6 rather than assuming the edit landed.
- Use absolute paths for all file operations.
27 changes: 19 additions & 8 deletions .github/agents/Specs.adr.implement.agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,30 +62,41 @@ You **MUST** consider the user input before proceeding (if not empty).
- Create or update `tests/[type-name].test-d.ts` for each changed type using `tsd`-style assertions or `@ts-expect-error` patterns
- Run: `tsc --noEmit --strict tests/*.test-d.ts` to confirm test files compile
- If tests fail: halt and report
- **All gates have now passed. Steps 10–12 are REQUIRED before reporting completion. Do not skip to step 13.**

10. **Update docs**:
- **All gates have now passed. Steps 10–13 are REQUIRED before reporting completion. Do not skip to step 14.**

10. **Write the ADR summary**: Add or update the `**Summary**:` line in the ADR's metadata block, directly beneath `**Status**`. Write it now rather than at draft time — it must describe what was actually implemented, which often differs from the original draft.
- **One sentence, present tense, roughly 15–18 words.** The new property, type, or config option is the grammatical subject.
- Anchor the addition to the neighbouring fields it joins, not to the gap it filled.
- Never open with "The schema", and never include a past-tense problem clause ("could not", "was dropped", "had nowhere to land").
- Keep identifiers in backticks.
- Examples of the target voice:
- A `strokeDashPattern` property adds dashes to strokes already supported with color, weight and alignment.
- A `glyph` element type, `IconProp` and `glyphNamePattern` emit icons as first-class by applying Figma conventions.
- Images are supported by `backgroundImage` style, `ImageProp` and binding in components and examples.
- **Gate**: read the ADR back and confirm the `**Summary**:` line is present and no longer a placeholder. The docs site publishes this line verbatim with no fallback — a missing summary leaves a blank row in the published index.

11. **Update docs**:
- Docs live in `site/src/content/docs/`. Schema type pages are under `site/src/content/docs/schema/` (e.g., `schema/styles.md` for `Styles`, `schema/config.md` for `Config`). Individual config option pages are under `site/src/content/docs/config/` (e.g., `config/tokens.md`, `config/keys.md`).
- For each property added, removed, or renamed in the ADR: update the relevant doc page's Properties table, Values table, and "Relating properties to values" section to reflect the new state.
- For new dedicated types (e.g., `LayoutMode`, `WrapAlignment`, `ItemSpacing`): add a row to the Values table describing the type and its valid values.
- For new config options: check if an individual config option page should be created under `config/` following the pattern of existing pages (e.g., `config/tokens.md`, `config/keys.md`).
- Do not create new doc pages for types that are only used as field values on an existing documented type — document them inline in the parent type's page.
- If no doc file exists for the changed type, skip this step.

11. **Update CHANGELOG.md**:
12. **Update CHANGELOG.md**:
- The release branch scaffolds an `## [X.Y.Z] - Unreleased` heading with empty sections. Add entries into the existing scaffold — do **not** replace `Unreleased` with a date (the date is set at release time). If no scaffold heading exists, prepend one using `Unreleased` as the date.
- **Format**: one top-level bullet per user-visible change; no sub-bullets; no bold; no code blocks; no wrapping prose paragraphs
- **Entry line**: `` `Parent.field` `` — one-phrase description; aim for ≤ 12 words; omit implementation detail (class names, file paths, method names)
- **Names**: `<Parent>.<field>` in backticks, em dash separator — e.g. `Styles.cornerSmoothing` — corner smoothing factor (0–1)
- **Consolidation**: When a new type exists only to serve a property, merge into one property-first bullet — e.g. `` `Styles.mainAxisAlignment` — typed as `MainAxisAlignment` (`'START' | 'END' | 'CENTER' | 'SPACE_BETWEEN'`) or `null`; description ``. Do not list the type as a separate bullet.
- **Sections**: use `### Added`, `### Changed`, `### Removed` as needed; add `### Migration` (MAJOR or rename only)
- **Migration line**: `` `Parent.old` → `Parent.new` ``: one sentence; imperative; describe what to read instead and how to handle the new type
- **Gate**: After writing, verify the new entry is present in the file. If CHANGELOG.md does not contain the new version heading, halt and report — do not proceed to step 12.
- **Gate**: After writing, verify the new entry is present in the file. If CHANGELOG.md does not contain the new version heading, halt and report — do not proceed to step 13.

12. **Bump version in `package.json`**: Apply the `NEW` version from the ADR's Semver Decision.
- **Gate**: After writing, read `package.json` back and confirm the `"version"` field matches the ADR's `NEW` version. If it does not match, halt and report — do not proceed to step 13.
13. **Bump version in `package.json`**: Apply the `NEW` version from the ADR's Semver Decision.
- **Gate**: After writing, read `package.json` back and confirm the `"version"` field matches the ADR's `NEW` version. If it does not match, halt and report — do not proceed to step 14.

13. **Report**: List every file modified (with one-line description each). The list **must** include `CHANGELOG.md` and `package.json` — if either is absent from the list, halt: steps 11–12 were not completed. State that the author should review the diff and accept the ADR once satisfied. Remind the author that this ADR branch (`$BRANCH`) targets the release branch (`$RELEASE_BRANCH`), not `main`.
14. **Report**: List every file modified (with one-line description each). The list **must** include the ADR file, `CHANGELOG.md`, and `package.json` — if any is absent from the list, halt: steps 10, 12, or 13 were not completed. State that the author should review the diff and accept the ADR once satisfied. Remind the author that this ADR branch (`$BRANCH`) targets the release branch (`$RELEASE_BRANCH`), not `main`.

## Key rules

Expand Down
5 changes: 1 addition & 4 deletions .github/workflows/deploy-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,9 @@ jobs:
- name: Install site dependencies
working-directory: site
run: npm ci
- name: Generate releases page
working-directory: site
run: node scripts/build-releases.mjs
- name: Build site
working-directory: site
run: npx astro build
run: npm run build
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v3
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ tests/tmp/

# Generated at build time from package CHANGELOGs
site/src/content/docs/overview/releases.mdx
site/src/content/docs/adr/
1 change: 1 addition & 0 deletions adr/001-metadata.license.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
**Branch**: `001-license-check`
**Created**: 2026-02-24
**Status**: ACCEPTED
**Summary**: A `license` field inside `metadata.generator` records the license state that produced a component's output.
**Deciders**: Nathan Curtis (author)
**Supersedes**: *(none)*

Expand Down
1 change: 1 addition & 0 deletions adr/002-effects-shadows-blurs.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
**Branch**: `v0.11.0`
**Created**: 2026-02-24
**Status**: ACCEPTED
**Summary**: An `effects` property with `Shadow`, `Blur` and `Effects` types replaces `effectStyleId` to describe shadows and blurs.
**Deciders**: Nathan Curtis (author)
**Supersedes**: *(none)*

Expand Down
1 change: 1 addition & 0 deletions adr/003-gradients.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
**Branch**: `003-gradients`
**Created**: 2026-02-25
**Status**: ACCEPTED
**Summary**: Gradient types and a `ColorStyle` alias let `backgroundColor`, `textColor` and `strokes` carry linear, radial and angular gradients.
**Deciders**: Nathan Curtis
**Supersedes**: *(none)*

Expand Down
1 change: 1 addition & 0 deletions adr/004-aspect-ratio.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
**Branch**: `004-aspect-ratio`
**Created**: 2026-02-25
**Status**: ACCEPTED
**Summary**: An `aspectRatio` property carries an `x`/`y` ratio object on styles alongside width and height.
**Deciders**: Nathan Curtis (author)
**Supersedes**: *(none)*

Expand Down
1 change: 1 addition & 0 deletions adr/005-typography-composite.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
**Branch**: `005-typography-composite`
**Created**: 2026-02-26
**Status**: ACCEPTED
**Summary**: A composite `typography` property replaces fourteen flat text keys including `fontSize`, `lineHeight`, `letterSpacing` and `textStyleId`.
**Deciders**: Nathan Curtis (author)
**Supersedes**: *(none)*

Expand Down
1 change: 1 addition & 0 deletions adr/006-token-references.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
**Branch**: `v0.11.0/006-token-references`
**Created**: 2026-02-28
**Status**: ACCEPTED
**Summary**: A single `TokenReference` type replaces `VariableStyle` and `FigmaStyle` for variables, named styles and composite references.
**Deciders**: Nathan Curtis (author)
**Supersedes**: *(none)*

Expand Down
1 change: 1 addition & 0 deletions adr/007-token-reference-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
**Branch**: `007-token-reference-config`
**Created**: 2026-03-01
**Status**: ACCEPTED
**Summary**: A `format.tokens` option replaces `variables`, `simplifyVariables` and `simplifyStyles` with one token output format.
**Deciders**: Nathan Curtis (author)
**Supersedes**: *(none — extends ADR 006: Unified Token Reference Type)*

Expand Down
1 change: 1 addition & 0 deletions adr/008-prop-bindings.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
**Branch**: `v0.11.0`
**Created**: 2026-03-02
**Status**: ACCEPTED
**Summary**: A `PropBinding` type keyed `$binding` replaces `ReferenceValue` unions wherever a value is bound to a prop.
**Deciders**: Nathan Curtis (author)
**Supersedes**: *(none)*

Expand Down
1 change: 1 addition & 0 deletions adr/009-color-values.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

**Created**: 2026-03-02
**Status**: ACCEPTED
**Summary**: A DTCG `ColorValue` object replaces the hex string in `ColorStyle`, aligning color values with token standards.
**Deciders**: Nathan Curtis (author)
**Supersedes**: *(none)*

Expand Down
1 change: 1 addition & 0 deletions adr/010-sides-and-corners.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
**Branch**: `010-sides-and-corners`
**Created**: 2026-03-05
**Status**: ACCEPTED
**Summary**: Composite `Sides` and `Corners` types replace flat padding, stroke weight and corner radius properties.
**Deciders**: Nathan Curtis (author)
**Supersedes**: *(none)*

Expand Down
1 change: 1 addition & 0 deletions adr/011-icon-glyph-as-content.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
**Branch**: `011-icon-glyph-as-content`
**Created**: 2026-03-05
**Status**: ACCEPTED
**Summary**: An `ElementType` union and `iconNamePattern` option constrain element types and detect icons by Figma naming.
**Deciders**: Nathan Curtis (author)
**Supersedes**: *(none)*

Expand Down
1 change: 1 addition & 0 deletions adr/012-element-type-references.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
**Branch**: `012-element-type-references`
**Created**: 2026-03-05
**Status**: ACCEPTED
**Summary**: An `ElementTypeRef` widens `AnatomyElement.type`, letting an element type point at a shared definition.
**Deciders**: Nathan Curtis (author)
**Supersedes**: *(none)*

Expand Down
1 change: 1 addition & 0 deletions adr/013-icon-fillColor.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
**Branch**: `013-icon-fillColor`
**Created**: 2026-03-09
**Status**: ACCEPTED
**Summary**: A `fillColor` property colors icon elements alongside `backgroundColor`, `textColor` and `strokes`.
**Deciders**: Nathan Curtis (author)
**Supersedes**: *(none)*

Expand Down
1 change: 1 addition & 0 deletions adr/014-prop-examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
**Branch**: `014-prop-examples`
**Created**: 2026-03-09
**Status**: ACCEPTED
**Summary**: An `examples` array on `TextProp` and `IconProp` carries sample values, and `default` becomes optional.
**Deciders**: Nathan Curtis (author)
**Supersedes**: *(none)*

Expand Down
1 change: 1 addition & 0 deletions adr/015-anyprop-oneOf-discrimination.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
**Branch**: `015-anyprop-oneOf-discrimination`
**Created**: 2026-03-09
**Status**: ACCEPTED
**Summary**: A single `StringProp` merges `TextProp` and `IconProp`, restoring valid `oneOf` discrimination in `AnyProp`.
**Deciders**: Nathan Curtis (author), *(collaborators TBD)*
**Supersedes**: ADR 017 (`017-icon-or-glyph-element-name`) — prop rename portion only. ADR 017 renamed `IconProp` → `GlyphProp`; this ADR merges both `TextProp` and `IconProp` into `StringProp`, making the intermediate `GlyphProp` rename moot. The element type rename (`icon` → `glyph`) and other non-prop changes from ADR 017 remain in effect.

Expand Down
Loading