Files
wp-materialize/AGENTS.md

282 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# wp-materialize Agents Specification
## Purpose
`wp-materialize` is an **automation compiler** that materializes specified Markdown files in Git repositories (or local directories) into WordPress posts. Git / filesystem state is the **single source of truth**; WordPress is a **derived, materialized view**.
The system is **declarative, atomic, incremental, and fail-fast**. It never guesses intent, never partially updates WordPress, and never mutates state unless correctness is proven ahead of time.
This document is the **authoritative agent-facing spec** to be fed to Codex or other build agents.
---
## Core Principles (Non-Negotiable)
1. **Git / Filesystem as Source of Truth**
WordPress content must exactly reflect declared Markdown sources and manifests.
2. **Declarative Configuration Only**
No implicit discovery, no heuristics, no inference.
3. **Atomic Execution**
A full dry-run validation must succeed before *any* WordPress mutation occurs.
4. **Incremental Updates**
Only content whose source timestamp is newer than its cached materialization timestamp may be updated.
5. **Fail Fast, Fail Loud**
Any configuration, validation, or conversion error aborts the entire run.
---
## High-Level Architecture
The system operates in two strictly separated phases:
### Phase 1: Pure Evaluation (Dry Run)
* Read global config
* Discover and load repositories / directories
* Load and validate all `.wp-materialize.json` manifests
* Resolve inheritance (categories, tags, subdirectories)
* Convert Markdown → HTML (in-memory only)
* Resolve titles, timestamps, taxonomy
* Determine incremental update set
* Detect *all* errors
**If any error occurs, execution stops here.**
### Phase 2: Side-Effect Application
* Create missing WordPress categories
* Create or update WordPress posts
* Update cached timestamps *only for successfully applied posts*
---
## Global Configuration
Location:
```
.config/wp-materialize/config.json
```
Responsibilities:
* WordPress root directory (where `wp` CLI is executed)
* Repository storage directory
* List of Git repositories to clone / pull
* List of non-git directories to manage
### Runtime State (Separate from Config)
Mutable runtime state must be stored separately, e.g.:
```
.config/wp-materialize/state.json
```
State includes:
* Last successful materialization timestamp per post
* Cached per-post source timestamps
Config must remain declarative and diffable.
---
## Repository and Directory Rules
* Each managed directory **must** contain a `.wp-materialize.json` manifest.
* Any directory listed under `subdirectories` **must** contain its own manifest.
* Missing manifests are **hard errors**.
* No implicit recursion is allowed.
---
## Per-Directory Manifest: `.wp-materialize.json`
Each manifest defines a **scope boundary**.
### Top-Level Fields
#### `categories`
```json
{
"content": ["Systems", "Infrastructure"],
"inherit": true
}
```
* `content`: array of category paths
* `inherit: true` → append to parent effective categories
* `inherit: false` → override parent categories entirely
#### `tags`
```json
{
"content": ["automation", "wordpress"],
"inherit": true
}
```
Semantics identical to `categories`.
#### `subdirectories`
```json
{
"content": ["design", "notes"],
"inherit": true
}
```
* Controls traversal explicitly
* Included subdirectories **must** have their own manifest
* `inherit: false` cuts traversal
---
## File-Level Configuration
Each file listed under `files` represents a WordPress post.
```json
"files": {
"post.md": {
"title": "Explicit Title",
"categories": { "content": ["Overrides"], "inherit": false },
"tags": { "content": ["extra"], "inherit": true }
},
"essay.md": {
"use_heading_as_title": {
"level": 1,
"strict": true
}
}
}
```
### Title Rules
* If `use_heading_as_title` is specified:
* Extract the specified heading level
* Use it as the WordPress post title
* Remove that heading from the body
* Promote remaining headings by one level
* If `strict: true`, exactly one matching heading must exist
* Otherwise, `title` **must** be provided
---
## Markdown → HTML Conversion
* Conversion occurs **only during dry run**
* No HTML is written or sent to WordPress during evaluation
* Conversion errors are fatal
---
## Category Materialization
* Categories are treated as **hierarchical paths**
* If a declared category path does not exist in WordPress:
* It is **automatically created** during the apply phase
* Category creation:
* Must be planned during dry run
* Must occur before post updates
Tags are **not** auto-created.
---
## Timestamps and Incremental Updates
### Timestamp Sources
* Git repository:
* Use Git commit timestamps
* Non-git directory:
* Use filesystem timestamps
The source of timestamps must be **deterministic per repository**.
### Cached Metadata
* Each post stores a cached source timestamp representing the last **successful** materialization
* Failed runs **must not** update cached timestamps
### Incremental Rule
On each run:
* Compare current source timestamp vs cached timestamp
* Only posts where `source_timestamp > cached_timestamp` are eligible for update
* Unchanged posts are treated as no-ops
---
## Post Identity
Each WordPress post must store stable metadata:
```
_wp_materialize_source = <repo_name>:<relative_path>
```
This identity is used for:
* Idempotent updates
* Safe renames
* Incremental comparison
---
## Atomicity Guarantee
* If **any** dry-run validation fails:
* No WordPress calls are executed
* No categories are created
* No cached timestamps are updated
* Apply phase executes only after full validation succeeds
---
## Error Handling
All errors are fatal:
* Missing manifests
* Invalid inheritance
* Invalid Markdown
* Missing or ambiguous titles
* Invalid category/tag resolution
* Timestamp resolution failures
No warnings. No partial success.
---
## Implementation Notes
* Language: **Python**
* The implementation must prioritize:
* Determinism
* Readable error messages
* Testable pure functions for evaluation phase
This document is the **contract**. Implementation must not relax or reinterpret it.