initial commit: codex draft

This commit is contained in:
2026-02-04 21:29:17 -05:00
commit 68bfab9c17
19 changed files with 1838 additions and 0 deletions

281
AGENTS.md Normal file
View File

@@ -0,0 +1,281 @@
# 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.