* feat: make contract id: optional and hold every declared id to its format
The format doc required id: on every responsibility and the compiler CLI
preflighted for it, yet nothing downstream read the field: the IR keys
nodes by slug, the state backends key the world model by node, and the
fingerprint is over content. Sixty-seven of 86 example responsibilities
had no id and half of the ids that existed were hand-typed slugs, so 12
of 29 examples refused to compile for a rule with no consumer.
id: is now optional on responsibilities and gateways: the slug is the
identity by default, and a declared id is the source identity that
survives renames. The format doc, compiler instruction, CLI preflight,
changelog conventions, and language spec all say the same thing. The
eleven hand-typed slug ids in the corpus are dropped, since they named
nothing the slug does not, and the two over-long compiler fixture ids
are trimmed to the documented 26-character Crockford shape.
scripts/mint-contract-id.mjs mints ids for authors who want one and
repairs malformed ids in place. A new corpus suite walks every example
and holds each declared id to the format, checks uniqueness, and keeps
version: in semver form.
* fix: fold every example section into the canonical set
Twenty-two headings across 18 example contracts were near-misses of a
canonical section, so the VM lowered them to plain documentation instead
of the semantics their authors meant. Continuity headings that carried
the driven-ness in the title become a bare Continuity section with the
driven-ness as its first bullet. Postconditions bullets fold into
Maintains. Facets become named parts under Maintains, each with a
material boundary. Failure containment becomes Invariants, a Continuity
recheck becomes the self-driven bullet, and a gateway's watched globs
move into Receives.
A new corpus suite walks every example and holds each ### heading to
the canonical table in the format doc, cross-checking its own list
against the table so the two cannot drift apart. The three inbound-
email examples join the intelligent-react shape suite, and the four
implementation-pipeline contracts join the facet-named-parts suite, so
no example is invisible to CI.
* fix: every example Requires now names a producer in its own set
Three examples carried needs that Forme could never satisfy from their
own contracts. competitor-activity named three signal feeds that existed
only in parentheticals; research-inbox-triage named a question list and
an owner roster nothing produced; agent-observatory named four adapter
mount instances that lived only in its README.
The format doc gains a short rule for facet families and per-entity
mounts: a placeholder facet heading declares a family, a placeholder
need subscribes to one member, and the harness binds the member at
mount time while the compiler emits the family. Forme's matching step
says the same.
competitor-activity gains a signal-feeds gateway with one facet per
signal, so the monitor's three needs resolve facet by facet.
research-inbox-triage gains a research-registry gateway that brings the
human-maintained questions and roster into the graph. agent-observatory
rewrites its adapter needs in family form and stays at nine contracts.
Each example reaches Forme with zero unsatisfied needs and an acyclic
topology. The new contracts join the facet-named-parts suite, and
competitor-activity joins the intelligent-react shape suite.
* docs: attribute described example topologies to the reference harness
Eight example READMEs state node and edge counts that mounting src/
alone cannot produce; the numbers come from the reference harness's
per-entity expansion. Each README now says so in the sentence that
carries the count and points at the repository README's Harnesses
section, and no Conformance expectations section states a count that
src/ cannot mount. The corpus index says the same for the set.
A new corpus suite walks every example README, counts the contracts
src/ mounts, and requires any larger claim to share its sentence with
the attribution, so a future README cannot over-claim silently.
* docs: specify node identity, artifact locators, and the receipt cost shape
The IR doc keyed every worked example by slug without saying what the
node key is. It now states the two-identifier model: node is mount
identity, unique within a manifest and defaulting to the slug for a
single mount, while a declared frontmatter id: is the source identity
behind it and is not emitted in a version 2 manifest. The same doc says
what an artifact locator resolves against: the OpenProse root, for
canonicalizers and postconditions alike.
The reconciler concept doc gives the receipt cost field its sub-shape,
including the surprise_cause that must equal the wake source, which is
what makes cost-scales-with-surprise observable. Doc-conformance
assertions pin each addition in the suite that already owns the file.
No IR schema bump; the expected and invalid fixtures validate unchanged.
* docs: cite in-repo sections instead of private design documents
Thirty shipped files, from the format doc and the state backends to the
example contracts and the conformance tests, cited design documents by
section that live outside this repository. A public clone should never
point its readers at text they cannot open.
Every citation now names the in-repo section that owns the rule, such
as the named-parts rule in the format doc or the fingerprint rules in
the reconciler concept, or the sentence simply stands on its own where
it needed no support. Test titles that carried a citation are retitled.
No links were added; the replacements are prose a stranger can follow.
* docs: pin harness status facts and guard the spec against rot
The spec marked implementation-status facts with the word "today" and
no attribution, so they would rot silently now that the reference
harness versions on its own. Six claims about poll cadence, the unwired
commit gate, the thin v0 receipt, the flat serve loop, and the dropped
Schedule section now name the reference harness and the version they
describe, and point once per document at the repository README's
Harnesses section. The two spec documents agree on a harness-chosen
receipt ledger layout. Two ideation links and a stray phase marker are
gone, the README's Harnesses link targets the harness spec, and its
version sentence defers to SKILL.md as the version of record.
The version script writes each manifest field on its own line instead
of round-tripping the file through jq, so a bump no longer reflows the
codex manifest; that manifest's capabilities array is collapsed back to
one line. Three guards land in the suites that own the territory: no
shipped file may cite a private design document, every relative link
in spec/ and skills/ must resolve, and the README may not hardcode a
skill version.
* chore: release skill 0.18.0
The format doc gained documented surface this cycle: id: is optional
with the slug as default identity, version: is author-owned provenance,
and facet families and per-entity mounts have a notation. The example
corpus is compiler-clean under those rules and the keyless conformance
suite proves it. That is a minor bump on the skill track.
The changelog entry tells an author what changed in authored files and
that a missing id: is no longer a compile error. runtime_contract stays
at 2, so prose upgrade needs no source rewrite. The version script now
touches exactly one line per manifest, which this bump demonstrates.
With the Reactor harness in its own repository, the language describes
its run-phase model for what it is rather than after one implementation
of it.
- concepts/reactor.md → concepts/reconciler.md; spec/02 keeps only the
contract any conforming harness must satisfy (02-Harness.md) and
spec/03 becomes 03-AuthoringPattern.md. "Reactor" in the model sense
is now "the reconciler" across the Skill, std, and the examples.
- The example corpus is harness-neutral: authored intent plus the
observable behaviour a harness must preserve. Quick Start examples
carry the Skill's own flow (prose compile → promote → prose serve)
and say what serve waits for; expanded-topology examples state what
src/ ships and what a harness's expansion produces from it.
- The Skill's run-flow docs agree with each other and with the spec:
serve defines the manifest promotion step, compile names what
ir-v0.md emits, ir-v0.md is the authoritative IR contract, and the
spec lists compile/serve/status as in-session verbs that a conforming
harness may deliver durably outside the session.
- A harness-surface conformance test keeps product tokens out of the
Skill, spec, std/co, and root docs, outside the README's Harnesses
section and the Skill changelog.
Skill 0.16.0; runtime_contract stays 2. The Skill changelog records the
migration so prose upgrade can route workflows that used prose react.
prose.md is now the canonical product host; the apex/www openprose.ai and
docs.openprose.ai redirect to it. Update the self-referential links in agent
onboarding, the Codex plugin websiteURL, the asset docs, and the Reactor
technical report so they target prose.md / docs.prose.md directly instead of
bouncing through a redirect.
The SKILL, the plugin manifests, and the prose CLI were pinned to one shared
X.Y.Z by an earlier "unify release flow" change. Nothing couples them at runtime
— the skill carries its own runtime_contract compatibility signal — so the
shared version was process convention, not necessity, and a partial bump
(SKILL.md 0.15.0 vs everything-else 0.14.0) was stranding the Plugin Manifest
gate red on main.
Split .version-bump.json into two independent tracks:
- skill: both plugin manifests + SKILL.md, locked together (the plugin
marketplace dedupes by manifest version, so a skill change only reaches plugin
users when the manifest advances).
- cli: @openprose/prose-cli + install.sh.
bump-version.sh becomes track-aware (--track <name> <X.Y.Z>, per-track --check,
--list); release-preflight.sh validates only the cli track so a CLI release is
no longer blocked by the skill version. RELEASE.md documents both tracks and the
skill release flow; CHANGELOG gets a 0.15.0 skill entry.
Release the skill track at 0.15.0 (plugin manifests 0.14.0 -> 0.15.0; SKILL.md
already there): the Intelligent React overhaul, runtime_contract 1 -> 2. The CLI
stays 0.14.0. Clears the red Plugin Manifest check.
The `open-prose` plugin ships to two marketplaces (Claude Code and Codex) via three manifest surfaces with overlapping but drifted metadata. This change unifies copy across those surfaces behind a single declarative source, ships visual assets for the Codex `interface` block, gates drift in CI, and adds a maintainer-facing submission playbook to `RELEASE.md`.
## Changes
- **Copy sync** — `.plugin-meta.json` declares the canonical strings; `scripts/sync-copy.sh` writes them into every declared destination (mirrors `bump-version.sh`). `--check` mode asserts byte-equality and reports drift.
- **Unified manifests** — same descriptions across `.claude-plugin/`, `.codex-plugin/`, and `.agents/plugins/`. Registry name aligned to `openprose` (plugin name `open-prose` unchanged). Codex `skills` path normalized.
- **Visual assets** — `assets/plugin/logo.png` (512×512) and `assets/plugin/composer-icon.png` (64×64), wired into the Codex `interface` block with `brandColor` (`#8a6b2e`), `websiteURL`, and the icon slots.
- **CI gates** — four new steps in `.github/workflows/plugin-manifest.yml` covering copy sync, asset presence, Codex interface completeness, and unified registry names. Existing version-sync gate untouched.
- **Submission playbook** — new `## Marketplace submission` section in `RELEASE.md` covering Claude Code (live today) and the Codex Plugin Directory (curated; self-serve coming soon).
OpenProse already installed as a Claude Code plugin via
`npx skills add openprose/prose`, but the packaging surface was
uneven: missing manifest fields, no native Codex envelope, no
plugin-track release process, and a couple of doc/audience
inconsistencies. This commit closes those gaps without changing
skill behavior.
OpenProse now ships from the repo root as a dual-host plugin
envelope — `.claude-plugin/` for Claude Code, `.codex-plugin/`
plus `.agents/plugins/` for Codex — with `skills/open-prose/`
as the shared core and `prose ...` as the only user-facing
command surface.
Codex envelope:
- .codex-plugin/plugin.json with first-class catalog metadata
(displayName, developer, descriptions, category, capabilities,
defaultPrompt, privacy/terms URLs).
- .agents/plugins/marketplace.json local-source catalog, installable
by anyone who clones this repo.
Claude Code manifest hygiene:
- Added license, homepage, and skills: ./skills so the plugin is
self-describing.
- Added marketplace.json metadata.description, clearing the sole
`claude plugin validate` warning.
- Deleted the stale .claude-plugin/README.md.
Skill metadata:
- Added license: MIT to skills/open-prose/SKILL.md frontmatter
(no top-level version — Claude Code strips unrecognized top-level
frontmatter keys; see anthropics/claude-code#13005).
- Fixed an inconsistent parse-table cell pair in
skills/open-prose/deps.md.
Audience boundaries:
- AGENTS.md is now contributor-only per agents.md.
- Recommended consumer [agents] Codex config moved to README.md
alongside the Quickstart.
Release process:
- scripts/bump-version.sh + .version-bump.json bump both manifests
atomically, with a --check mode for CI. The Claude Code
marketplace deduplicates by version, so a forgotten bump silently
strands users on cached copies; this gate prevents that.
- scripts/extract-changelog.sh pulls a single `## [X.Y.Z]` block
out of CHANGELOG.md.
- RELEASE.md documents the manual flow.
- .github/workflows/release.yml verifies declared versions match
on `v*` tag push and publishes a GitHub Release.
CI:
- New plugin-manifest.yml: every-PR gate validating both plugin.json
files, asserting declared skills paths resolve, and running
bump-version.sh --check.
- cli-skills-smoke.yml: added `npx skills list openprose/prose`
discoverability check alongside the existing install smoke.
- openprose-smoke/run.ts: removed a dead commands/prose-*.md regex.