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.
Reactor now lives at github.com/openprose/reactor with its complete
history and a pinned copy of the Skill at skill-v0.15.0; its packages
(@openprose/reactor 0.3.3, reactor-cli 0.2.4, reactor-devtools 0.3.1)
publish from there and are labelled experimental (alpha).
This repository is OpenProse only again: the language spec, the Skill,
std/co, and the examples — installable and testable with no build step.
- Remove packages/reactor*, tools/eval-harness, the Reactor-driven
example suites and test kits, both Reactor workflows, and the vitest
aliases into packages/reactor/dist.
- Retire `prose react`, the reactor shell-out exception, and reactor.md
from the Skill; replace the README's Reactor section with a short
"Harnesses" pointer.
- Keep the four corpus-wide example guards as tests/open-prose/examples-corpus.
- Add ci-skill.yml: pnpm install --frozen-lockfile && pnpm test:skill —
the conformance suites now run in CI for the first time.
- Record the `prose react` and reactor-cli changelog entries under the
tags they actually shipped in.
The run-phase vocabulary (concepts/reactor.md, the spec titles) is
de-branded in a follow-up.
Cut the reactor train so the #136 canonicalizer fix (#153) reaches npm, along
with the reactor.yml provider/temperature fixes (#137, #138), the key-material
scrub, the MK-1 height-ordered drain, and the re-skinned replay viewer.
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Dependency installs and CI jobs both executed code this repo never
reviewed. This closes those paths without changing what anything
resolves to.
pnpm 9 ran every dependency's install lifecycle script and had no
allow-list model, so CI executed install hooks from the whole tree on
every PR. pnpm 10.34.5 blocks them by default and carries the fix for
the fail-open integrity check in CVE-2026-50021. minimumReleaseAge holds
freshly published versions out of resolution for 48 hours, the window in
which a registry compromise is typically caught and yanked.
The two `*` peer ranges in reactor-cli were the only place the workspace
opted out of range discipline: any future major satisfied them, including
a hijacked one. Both now carry carets on the versions already resolved,
and the README install lines are pinned to match, since a 0.x caret does
not cross the minor line.
Third-party actions take the commit SHA their movable tags resolved to,
with a monthly grouped Dependabot entry so those pins do not go stale.
GitHub-maintained actions stay on tags as a stated trust decision rather
than a claim that pinning them would buy nothing.
The benchmark jobs needed the most work, since they run an external
repository's code with five LLM provider keys in scope. Dispatch inputs
now travel through the step environment as quoted variables instead of
being interpolated into shell. The pi version is hardcoded rather than
dispatchable: npm accepts package sources after the `@` — an alias, a
repository, a tarball URL — so an input in that position chose a package
rather than a version. The remaining ref override is documented as an
operator escape hatch whose clone target is fixed.
The publish job holds a credential that can publish under our name and
installed npm at latest before using it. It now pins an exact version
above the floor OIDC trusted publishing requires, and fails at that step
if the pin does not take.
CI also fails on a tampered or unsigned tarball now, checked per
publishable package rather than once at the root where npm would only
see dev tooling. The advisory audit runs alongside it as a signal, not a
gate.
Nothing re-resolves: no version or integrity line in the lockfile moves.
The skill-meta suite was coupled to exact onboarding copy, so harmless
wording changes could fail CI even when the documented contract remained
correct.
Replace the slogan assertion with behavior-oriented checks for the
example's Requires and Maintains contracts, absence of execution
choreography, and retired kind: system. Scope Markdown extraction to the
intended sections and add negative regressions so misplaced fences or
near-match headings cannot satisfy the test.
Rendered artifacts can contain both an `@atomic.json` status file and a real
structured backing such as `sources.json`. The lexicographic fallback selected
the reserved status file first, reducing declared facets to `null` and
preventing downstream propagation.
Exclude `@`-prefixed JSON basenames from structured-backing candidates while
preserving the `state/` preference and deterministic fallback ordering. Add
regression coverage for root and nested reserved files, reserved-only
artifacts, and the existing `state/` behavior.
Fixes#136.
The smoke fixtures still exercised the retired pre-0.15 model: service
and system kinds, '### Ensures' contracts, and a harness that asked for
forme.manifest.json and checked every output under bindings/. The
execution docs now treat retired kinds as never-executable upgrade
input, which turned the kind-test case into a standing contradiction:
its subject resolved to a kind: service file the harness required to
execute. That contradiction fits kind-test's history as the suite's one
chronically flaky case.
Rewrite every fixture in current kinds while preserving what each case
smokes: functions for single render, caller input, execution block,
errors and strategies, and local pattern instantiation (standalone runs
publish '### Returns' under bindings/ via copy-on-return);
responsibility multi-node files for the wiring cases, with a deliberate
fan-in reconvergence replacing the retired '### Wiring' case; kind: test
now runs a function subject and asserts against its published bindings.
Align the harness with the current artifact layout: mounted runs
snapshot compiled-intent.json, publish node truth under world-model/,
and append receipts; a per-case outputRoot field selects world-model or
bindings for output checks. Give the test command a 40-turn budget,
since it reads the test file, resolves the subject, executes it, and
evaluates assertions in one session. Case ids and filenames are
unchanged, so required check names stay stable.
The skill's execution reference taught two models at once. Its head
sections describe the current runtime: responsibility and function
kinds, the deterministic reconciler, renders that self-police their
postconditions, world-model publishing with receipts. Its body still
taught the retired one: ### Ensures contracts, a post-render judgment
call on outputs, and the workspace-to-bindings copy as the publish
step.
Migrate the body to match the head and align the depicted run envelope
with the filesystem backend spec: compiled-intent.json, caller inputs
at world-model/caller/, a receipts/ ledger, rendered and skipped log
markers, and resumption from the receipt chain. ### Execution blocks
are intra-node choreography, the render body of the one node that
declares them. Copy-on-return survives only for standalone function
runs.
Retired kinds now refuse to execute: a file declaring kind: service or
kind: system halts and routes to prose upgrade instead of running under
either semantics. Compatibility is migration at the source, never
interpretation at runtime.
The backend spec gets the same pass so the pair reads as one wire
format: its marker tables, log example, header comments, and
write-trigger table move to node, render, and run vocabulary.
agent-onboarding.md is served verbatim as raw text (the prose.md
arrival narrative and the agents.openprose.ai text site), so its first
bytes are the product. An agent fetching it read 25 lines of HTML
comment about routing and editing before the first heading, and parts
of that comment had gone stale.
Drop the comment so the file starts at the title, align the host list
with SKILL.md (Claude Code, Codex CLI, OpenCode, Amp), say multi-node
contracts in the capability note to match the current contract
vocabulary, and tidy punctuation. The narrative itself is unchanged.
The CLI and devtools readmes pointed at notes that are not in the
repository. Drop the dangling pointers so every reference on the public
surface resolves.
The tenets still steered contributors toward retired constructs:
judges, kind service wiring, and an Ensures/Shape/Strategies section
list. Reword them around responsibilities, facets, and the
Requires-to-Maintains match Forme actually performs.
The front page of openprose/prose read mostly as a Reactor README: the
tagline, quickstart, SDK tour, and examples were all harness. Reorder it
so OpenProse the language leads, add the missing skill quickstart
(npx skills add openprose/prose), and consolidate everything Reactor
into one self-contained section with its own tagline. Also state the
failure semantics precisely (a failed render leaves prior truth
standing) and swap remaining em dashes for house punctuation.
A light refresh of the README header and the project tagline.
- New README banner image (`assets/readme-header.png`); trims the caption now that the banner carries it.
- Brings the tagline in line across the README, plugin manifests, spec, and onboarding: "Stop scripting agents. Declare them."
- Removes the unused legacy `readme-header.svg` (nothing references it).
- Small `assets/README.md` tidy.
No functional changes.
`reactor trigger` never threaded the configured provider into the render: it
called the run-project with no provider, model, or decoding settings, so a live
trigger always fell back to the SDK's default OpenRouter provider and model
regardless of reactor.yml. With only the configured provider's key present,
every trigger produced a bare, causeless `failed` receipt (model "none", zero
tokens). Separately, the reason a render failed was computed but never
persisted, so every surface could only say `failed` with no way to learn the
cause without editing the source.
This fixes both:
- `trigger` resolves the provider plan, fails fast with an actionable error
naming the exact env var when a custom provider's key is missing, and threads
render_model, temperature, and reasoning_effort plus the provider into the
render exactly like `run` and `serve`.
- A failed render now records its reason on the receipt, inside the
semantic_diff (no new receipt field and no schema change, so existing
.reactor/ ledgers keep verifying), and `run`, `trigger`, `logs`, `trace`, and
`inspect` all show it. Secret material in a reason is scrubbed before it is
stored or printed.
- `serve` reports per-gateway poll activity each cycle, so a poll that stages
nothing is no longer indistinguishable from a healthy one.
Behavior changes: `trigger` now exits non-zero on a failed render or a missing
provider key (it previously returned 0), and a project configured for a
non-default provider with only OPENROUTER_API_KEY present now errors asking for
the configured key instead of silently rendering through the wrong provider.
OpenAI reasoning models (gpt-5.5, the o-series) reject any explicit
temperature unless reasoning_effort is none, but the reactor always sent
one: the config hard-defaulted a missing temperature to 0, the render and
compile harnesses coerced unset to 0, and mergeModelSettings always
attached the key. Deleting the temperature line from reactor.yml changed
nothing, so no configuration made these models compile or render.
Separately, a configured temperature only ever reached compile sessions —
run and serve renders silently used the SDK default, so reactor.yml's
temperature was honored at compile but ignored at render.
Temperature is now optional end to end. An absent reactor.yml line (or an
unset SDK RenderOptions/CompileSessionConfig temperature) sends no
temperature and the provider's default applies; an explicit value,
including 0 for greedy decoding, is sent verbatim. run, serve, and the
multi-reactor host thread the configured temperature into renders exactly
like render_model, so one reactor.yml value governs both compile and
render.
A new optional reasoning_effort key (model.reasoning_effort in reactor.yml,
reasoningEffort in the SDK render/compile options) passes through verbatim
into modelSettings.reasoning.effort, so a reasoning model can keep a custom
temperature by pairing it with reasoning_effort: none. doctor --live no
longer pins temperature 0 in its probe (it 400ed against reasoning render
models), and a provider temperature-rejection 400 now maps to an actionable
hint naming the reactor.yml line to delete.
Behavior change: a project with no temperature line previously sent an
implicit 0; it now sends none and decoding follows the provider default.
Set temperature: 0 to keep greedy decoding — the reactor init scaffold
still writes it, so new projects are unaffected.
Adds focused unit coverage for a path that had none: temperature omitted
when unset and sent exactly when configured (render and compile request
capture), the config parse and run-path threading, and the scaffold pin.
Each runtime example shipped a committed replay/ state-dir that duplicated
fixtures @openprose/reactor-devtools already generates and publishes, and the
example generators forked the devtools generators. Now each recorded run and
its generator logic lives once.
- masked-relay, inbox-triage and research-tree import the canonical generators
from reactor-devtools and add only the example-library files (labels.json +
beats.json) on top, dropping the forked copies.
- Every example regenerates its replay/ into a tmpdir at test time and proves
determinism by two fresh generations agreeing; the committed bytes for the
six scenarios that mirror the devtools fixtures, plus tamper-forge, are
removed. The examples with no devtools counterpart keep their committed state.
- agent-observatory keeps its own generator on purpose: it teaches a different
story (four runtimes, a session-to-prose node, dual Markdown and HTML
artifacts) than the devtools corpus fixture, now noted in its header.
- Drop stale internal tracker references from the tamper-forge contract,
generator and tests.
Offline gate green: pnpm build && pnpm test:skill && pnpm test:examples.
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 height-ordered reconciler drain renders each recombinant (diamond) join
once, against fully-settled inputs, instead of the old arrival-order
double-render. The committed example replay/ trails and two assertions still
encoded the pre-drain receipt shape.
- Regenerate the committed replay/ for the six affected examples to the current
SDK output (masked-relay drops 77 -> 41 receipts; tamper-forge lenses the same
trail; agent-observatory, inbox-triage, basic-unit-suite, github-star-enricher
follow).
- github-star-enricher: a shared company diamond now coalesces into a single
render, so the second arm no longer mints a memo-skip receipt. Assert the reuse
via the single shared render (the stable signal) rather than a per-wake skip.
- tamper-forge: update the audited trail length (77 -> 41) in the test, the
generator beats, and the README/contract that cite it.
Offline gate green: build && test:skill && test:examples.
pnpm install --frozen-lockfile (used by CI, including the examples gate) fails
because the lockfile drifted from the workspace package.json files:
- reactor-cli pins @openprose/reactor as workspace:* in the lockfile but
workspace:^ in package.json.
- reactor-evals is a workspace package but was never recorded in the lockfile.
Regenerated with the pinned pnpm 9.15.0 via pnpm install --lockfile-only.
pnpm install --frozen-lockfile now passes.
Live render path validated end-to-end on OpenAI gpt-5.4-mini direct (real
metered receipt 36/4/40) after the OpenRouter key hit its limit. Per
decision, the shipped headline is the deterministic, price-independent
174.71x fresh-token fold; the full metered N=1 dollar bill is a bounded
follow-up, not fabricated. Updates live_n1, model_pin, and limitations note.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The U12 poison guard used text.includes('256:0'), which false-matched the
'sha256:0…' content-hash prefix saturating every receipt ledger — so the
gate exited 1 on the committed runs-sample. Match poison tokens only when
they stand alone, so a reused FIGURE is still caught but a hash digest is not.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The '2026 H2' target was an unratified placeholder. Replace with 'tracked
but not yet scheduled (C3)' at the three disclosure sites so no public
artifact commits to a quarter that isn't on the roadmap.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A live provider 403 ('Key limit exceeded') echoes the key's SHA-256 in an
openrouter.ai/.../keys/<hash> management URL — a key fingerprint that reached
test output / CI logs. Add redactSecrets/redactError (scrubs sk-* key
families, Bearer/Authorization headers, /keys/<hash>, and bare long-hex
fingerprints) and apply at the two render error chokepoints (render-backend
re-throw + smokeRun). 7 redaction unit tests with fully fabricated fixtures;
verified the real BYO live 403 now surfaces as .../keys/***REDACTED***.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New packages/reactor-evals/ — preregistered, equal-correctness-gated
offline benchmark minting the first measured 'cost scales with surprise'
result (~174x fewer fresh tokens than an equal-correctness cron at lambda=1%,
decaying to 1.36x at lambda=1.0). Deterministic ledger, 30/30 chain-verified
receipts, poison-grep + decidability guards. Authored against the public
SDK barrel; spec + reactor/src read-only. U10 live dollar-run is operator-
gated (follow-up).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace both arrival-order FIFO drains (drain/drainAsync) with a
compile-time height-ordered, dirty-input-count-gated drain so a staggered
unequal-path diamond renders its join once per settled wave (kills the
double-render glitch reproduced live in masked-relay). reconcile/
reconcileAsync + single-flight guard reused byte-for-byte; public API
unchanged; no spec edit. 11 new red-first regression tests (sync+async).
Closes#132.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mints the first preregistered, equal-correctness-gated measurement that Reactor's
fresh-token spend scales with surprise, not time. New packages/reactor-evals/
authored against the PUBLIC @openprose/reactor barrel (EVALS.md discipline);
spec/ and packages/reactor/src/** read-only.
Headline (deterministic offline ledger): at lambda=1%, Reactor spends ~174x fewer
fresh tokens than an equal-correctness cron; the fold DECAYS with the change-rate
(~1390x at lambda=0 -> 1.36x at lambda=1.0). Per-tick fresh regresses on the
PREREGISTERED material-change indicator (slope=30, intercept~0, permutation
p~1e-4); the null 'spend tracks wall-clock/event-count' is rejected for Reactor
and not for the cron. Every cost row gated to equal correctness vs the oracle.
Units: U1 deterministic-cost-v1 (preregistered surrogate); U2 lambda world-gen +
material projection + labels + oracle; U3 sweep (real reconciler, per-tick fresh
off the receipts); U4 six contestants (reactor/oracle-cron/content-cache/
no-memo/byte-diff/react-loop); U5 prereg hashed before any run; U6 scorers
(surprise-cost regression + permutation test, propagation #2, amortization #9,
gateCommit #6, per-node chain-verify); U7 equal-correctness gate + regime matrix;
U9 offline invariants #4/#5; U11 report + hero figure + suite CLI; U12 poison-grep
+ decidability guards. 30/30 cells chain-verified; 8/8 unit tests pass; prereg
hash + REPORT.md byte-stable across runs.
Deviations/blocked (honest): .cjs not .ts (toolchain availability; layout matches
the PLAN 1:1); U10 real N=1 LIVE run BLOCKED (no OPENROUTER_API_KEY) and never
fabricated; U8 long-horizon + U9 #8/#12 scaffolded; baseline coincidences flagged
in REPORT.md. Full runs/ (87M) gitignored (byte-deterministic, regenerable);
runs-sample/ commits the headline pair as a frozen chain-verifiable replay.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The arrival-order FIFO drains rendered a recombinant (diamond) join with
UNEQUAL path lengths TWICE: once prematurely against a half-propagated input
set (a glitch — the short edge moved, the long path still stale), then again
once the long path settled (a redundant render). "Cost scales with surprise"
(Invariant 5) visibly failed for that topology — reproducible live in the
shipped masked-relay demo.
Replace both `drain` and `drainAsync` with a compile-time height-ordered,
dirty-input-count-gated drain (Minsky / self-adjusting computation): a node
fires exactly once, in ascending height, only after every dirty producer has
SETTLED — so a join renders once, against fully-settled inputs.
- `computeHeights` + producer/subscriber adjacency, derived once per epoch from
the frozen topology edges ∪ entry_points (NOT topology.nodes, which is [] in
the IR). Cycle-guard throw kept; static-topology marker left for the fixpoint.
- One shared `startFrontier` core (PASS-1 dirty closure + dirty-count, the
height-ordered ready pick, settle-based decrement, move-aware prune) drives
both the sync and async loops; only the render call differs. `reconcile` /
`reconcileAsync` — including the per-node single-flight/coalesce guard — are
reused byte-for-byte. Async awaits each fire fully before advancing the
frontier (closes the await-frontier gap); stays serial (no Change-B parallelism).
- Settle-based (not move-based) decrement so a memo-skipping producer never
starves a join; move-aware prune so a no-change re-drain renders zero and
mints only the seed's skip; interior-seed gate so a directly-woken interior
node still waits on its dirty upstreams.
Public API unchanged; no caller edits (drain returns fire-order, not FIFO —
audited: no consumer asserts arrival order). No spec edit.
Tests (red-first; the primary demonstrably failed on the pre-fix FIFO drain,
E=2 with a glitch, proven in a scratch build): staggered unequal-path diamond
(sync + async) → join renders once against settled inputs; symmetric equal-path
control; no-change re-drain → zero renders / one seed skip; two-seeds-on-one-
chain interior-seed gate; 3-deep prune-no-deadlock; computeHeights height
assertions + forged-cyclic-topology throw. Full @openprose/reactor suite green.
Refs: planning/plans/2026-06-07-mk1-drain-fix/PLAN.md; backlog MK-1;
prototype planning/ideation/minsky-experiments/c2-topo-drain/.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Align the public artifacts with what npm and the code actually deliver — the
seams the 2026-06-06 investor-DD fanout independently verified as overstated.
Presentation/disclosure only; no runtime, invariant, or spec edit.
- IDD-vers: fix the two stale "live on npm" version callouts to reactor 0.3.1 /
CLI 0.2.2 (devtools 0.2.0 unchanged); reactor README "ideal surface" 0.3.0->0.3.1.
- IDD-reuse (+G27): devtools --describe COST ROLLUP now leads with the defensible
memo-skip count and demotes provider-prompt-cache `reuse=%` to a labeled
secondary line ("provider-reported; can be 0% on the default model"); test added.
- BR-F7 (+G10): dated cryptographic-signer roadmap line (targeted 2026 H2, tracked
as C3) at the three null-signer disclosure sites + the tamper-evident-not-proof
threat-model sentence. Also fixed the broken `@openprose/reactor/sdk` subpath
cites in the devtools README -> root `@openprose/reactor` (NOT `/internals` as
the plan said; these symbols are root exports), and the non-public
`new FileSystemReceiptLedger` -> the public `createFileSystemReceiptLedger`.
- IDD-footprint: rewrote the "Air-gapped?" note + added a quickstart footprint
line with the measured ~99 MB / ~100 packages (2026-06-06), preserving the
true SDK-core zero-dep claim.
- IDD-skew: ranged the devtools/CLI `@openprose/reactor` workspace ref
workspace:* -> workspace:^ (pnpm pack now emits ^0.3.1, verified) so npm
dedupes one SDK copy. (Republish of devtools 0.2.1 still required to land it on
npm — separate release action.)
Gate: pnpm --filter @openprose/reactor-devtools test green (96/96).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Completes the prose-CLI scrub the spec already documents as shipped: deletes tools/cli (the @openprose/prose-cli Oclif binary + eval harnesses), drops tools/cli from the workspace and lockfile, and removes the separately-authored `### Criteria` section from the reactor and reactor-cli contract loaders (postconditions live solely in `### Maintains`). Updates the accompanying skill tests, changelog, and release docs. Verified green: reactor SDK 458/0/10, reactor-cli 186/1 (pre-existing doctor test), devtools 96/0, skill 413/0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Repairs surfaced by an independent code-grounded verification pass. 00: cost is observed-not-budgeted (not 'resource budget the gates are constrained by'); Tenet 2's intelligence layer lists all three model-authored compile artifacts (Forme topology + canonicalizer + postcondition validators). 01: state the `### Invariants` actuation-boundary ideal in Part I (with a bridge note it is authored-only today); gateway compiles to a trigger the reactor serves (not `prose serve`); migration line corrected (`co` has no `kind: responsibility`; std has 3); note the language-root `receipts.jsonl` vs the harness `receipts.json`. 02: launch DoD no longer implies version-equality; new Part III §10 (declared-capability resolution + serve auth + async storage seam) so every Honest-Limit has a forward item. 03: signer rendered as shipped (`scheme: "none"`, no `kind:"null"|"signed"`); Part II honest that `### Tools`/`### Environment`/`### Skills` are name-only and not harness-consumed; `as_of` added to the gap-cluster-2 receipt set; gateway `### Schedule` forward item; no `reactor test` subcommand.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reconcile the OpenProse spec so Part I states the implementation-agnostic ideal, Part II matches shipped code, and Part III is a real actual->ideal path. Memo key stated as the 3-tuple (shipped 2-tuple as a bridge note); ideal receipt schema gains as_of + failure reason + author-addressing; precedence-stack scope and commit-gate pillar reconciled across 00/02/03; prose-CLI and `### Criteria` residue removed from the ideal; Part III re-baselined off shipped reality (the corpus migration retired as done) with the receipt-shape and actuation gap-cluster items added so every Part II limit has a forward item.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Capture the agent-observatory Reactor learnings as authoring doctrine,
scoped to multi-node Reactor pipelines so they are not over-applied.
guidance/authoring.md gains a `## Cost and Context Discipline` section
(tier with a cheap gatekeeper; bound each narrow render to its inline
input; validate the cost-shape; keep renders cheap-model-small) plus
four matching anti-patterns. SKILL.md's Authoring Guidance points to it
for continuous / fan-out / high-event-volume pipelines.
Opens with an explicit trigger and a Tenet-2 caveat: it applies to the
narrow-transform renders that dominate a pipeline's volume, not to
one-shot functions or single responsibilities, and a render whose job is
to explore should still explore. CLI/version gotchas are deliberately
left to reactor.md, not authoring doctrine.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
The "Inbound email as a trigger" group was authored before the README index was
restyled to use a colon (not an em-dash) between each example link and its
description. Align the three bullets (support-inbox-router, feedback-pulse,
press-desk) to that convention. Cosmetic only.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(examples): inbound primitive.dev email as a Reactor trigger (3 examples)
Wire a primitive.dev email inbox in as an external-driven gateway and keep a
downstream world-model current from what arrives. Three distinct reactor shapes,
each shipping the full validity contract (committed replay/ + deterministic
tier-2 offline test) plus a key-gated tier-3 LLM-as-judge live test.
- support-inbox-router (marquee): a cheap-model spam/content filter + a faceted
router whose facets are channels. A per-email triage drops spam (its `routed`
facet stays the fixed NULL token, so junk lights nothing) and tags ham to a
channel; the router catalogues one facet per channel (bug-reports,
feature-requests, docs-questions, billing) so a docs question wakes ONLY the
docs-gap tracker, never the bug board. `billing` has zero consumers on purpose
(a facet is a subscription symbol). The docs-gap tracker feeds the agent-native
docs / llms.txt surface.
- feedback-pulse: rollup aggregation + self-driven weekly `valid_until`
freshness; the brief refreshes on cadence even when the inbox is quiet, at zero
tokens on an unmoved rollup.
- press-desk: a deterministic human gate (gateCommit: needs_human,
auto_reply:false) + a privacy projection facet that keeps sender PII out of the
public view by construction.
Tier-2 offline: 45/45 new tests pass, byte-deterministic, chain-verifying; no
regression to the existing suite. Tier-3 live tests passing-skip offline and run
the render on a cheap model with a smart judge model when keyed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(examples): validate tier-3 LLM-judge live tests on direct OpenAI
OpenRouter is over its account spend cap, so point the three live tests at the
OpenAI Chat Completions surface directly with OPENAI_API_KEY: the render-under-
test runs on the cheap model (gpt-5.4-mini) and the rubric judge on a smarter one
(gpt-5.5), both via the same key. gating now resolves OPENAI_API_KEY (process.env
then the .env at REACTOR_ENV_PATH, honoring REACTOR_OFFLINE) and the body still
passing-skips offline. temperature pinned to 1 (the gpt-5.x models reject 0).
All three live tests pass live at reliability >= 0.8 across their labeled sets
(support-inbox-router spam/bug/feature/docs, feedback-pulse themes, press-desk
relevance/kind/no-PII-leak), grounding guard held. Offline gate unchanged: 45/45
tier-2 pass, live bodies passing-skip.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Frame OpenProse as a declarative language: you declare the ideal world
state, the Reactor keeps it true. Make that the spine across both layers
and present cost-scales-with-surprise as its consequence rather than the
headline. Sweep em dashes for a cleaner read.
The open-prose skill ships as a plain folder, so everything under
skills/open-prose/examples/ reaches every install. Each runtime example
shipped a committed replay/ state-dir (around 480 binary world-model files), a
generator, and a test suite wired to the workspace through a dist alias with no
local package.json. That machinery is internal validation, not the template a
user lifts: it cannot run from a copied folder, and it shipped generated
artifacts nobody should copy.
Keep the shipped examples to what a user actually adapts, and move the
validation into the repo's test tree:
- Move each example's tests, generator, and committed replay/ into
tests/open-prose/examples/<name>/. The shipped example is now its .prose
contracts under src/, a README, and a .gitignore.
- Re-point the vitest include and the test scripts; the byte-deterministic
offline coverage runs unchanged, just rooted under tests/.
- Rewrite the example READMEs to point at the reactor CLI for producing and
replaying a run, and drop the stale committed-fixture sections.
- Update the examples-gate workflow description to match the new layout.
No language, CLI, or runtime behavior changes, and the example contracts are
untouched. Verified with the offline gate (REACTOR_OFFLINE=1): the conformance
suite, the relocated example tests, and the eval harness all pass.
* fix(cli): typecheck repository-reactor-bridge test against branded Receipt fields
#106 hard-branded the reactor Receipt identity fields (node: NodeId,
contract_fingerprint / fingerprints: Fingerprint) and added this bridge test in
the same commit, constructing the Receipt fixture from raw strings — so the test
was born failing tsc. CLI Release Check only runs on tools/cli + release-script
paths and main has no required checks, so #106 merged with the typecheck red and
it stayed hidden (no cli-path change re-ran the check) until a release-infra PR
surfaced it.
Author the fixture with the same brand constructors the production bridge uses
(asNodeId / asFingerprint from @openprose/reactor/internals). The constructors are
identity-at-runtime brands, so behavior is unchanged: the affected test passes
10/10 and tsc is clean.
Note: this unmasks a SEPARATE pre-existing failure, also from #106 — the
repository-ir compiler fixtures were regenerated with kind
"openprose.compile-phase-ir" while validateRepositoryIr and its tests still expect
"openprose.repository-ir" (23 failing tests). That is a distinct IR-reconciliation
fix, tracked separately.
* fix(cli): restore repository-ir v0 validator tests with CLI-owned fixtures
#106 migrated the SKILL compiler's golden outputs (repo-root
tests/open-prose/compiler/) from repository-ir v0 to compile-phase-ir v2, but the
CLI's own compile path (compileRepositorySource -> validateRepositoryIr ->
repositoryIrToTopology) stayed v0. repository-ir.test.ts and
responsibility-status.test.ts borrowed those golden files across the package
boundary, so the v0 validator was being fed v2 inputs -> 21 failing tests.
Give the CLI's v0 validator tests their OWN v0 fixtures under
tools/cli/tests/prose/fixtures/repository-ir/ (recovered from f12dcda~1, the last
commit before the migration; the CLI compiler and validator are unchanged since,
so they still describe the current contract). The two compilers no longer share
fixtures: the SKILL compiler's compile-phase-ir fixtures are validated by
compiler-ir.test.ts; these repository-ir v0 fixtures are the CLI's. A README in the
fixtures dir documents the split and the migration path.
No validator or compiler change (not papering over) — the v0 validator is simply
fed correct v0 inputs. tools/cli suite: 573 -> 594 passing; the v0 validator suite
is 30/30. The 2 remaining failures (quickstart's dangling deleted-demo reference
and the agent-observatory example's missing id) are unrelated non-IR #106 fallout,
tracked separately.
* chore: deprecate prose-cli npm publish flow; park the eval suite
The `prose` CLI (@openprose/prose-cli) is deprecated in favor of the reactor
harness (@openprose/reactor + @openprose/reactor-cli) and the SKILL/plugin. This
removes its npm publish flow (it will be marked deprecated on npm manually) and
parks the eval harness out of the working tree.
Rip out the prose-cli publish flow:
- delete .github/workflows/{release,cli-release-check,cli-real-harness-smoke}.yml
and scripts/release-preflight.sh (the "OpenProse Release" publisher + its
preflight/checks).
- drop the `cli` track from .version-bump.json (only the skill/plugin track
releases here now) and the prose-cli sections from RELEASE.md.
- decouple the root build/test/lint scripts from @openprose/prose-cli.
Park the eval suite (it is rethought from scratch in the reactor backlog):
- remove the judge-era harness tools/cli/src/evals (45) + tools/cli/tests/evals
(18) and spec/04-Evals.md; they are copied verbatim into the planning
backlog-reactor for rehydration, and the methodology is synthesized there.
The harness was import-isolated (no code imported it); removal breaks nothing.
- fix the now-dangling spec/02 cross-reference to 04-Evals.md.
- remove the obsolete quickstart.test.ts (it read a #106-deleted demo test file).
The reactor packages, the new reactor-native tools/eval-harness, the skill
examples gate, and plugin-manifest are unaffected; prose-cli still typechecks.
Re-skin the keyless DevTools replay SPA onto the apps/run design system's
"Reactor monitor" machine surface (DESIGN.md §1/§4 name it as a sanctioned dark
machine surface): a flat charcoal ground, single-voice self-hosted JetBrains
Mono, gold as the one brand accent, 1px hairlines + small radii + one soft
shadow framing, three-dot window chrome, and always-labeled status.
- Machine palette (variable NAMES preserved so app.js + every selector keep
working; only values changed): --bg #1a1c22 flat (radial gradient removed,
per "no gradients"), machine-bar chrome bars, machine-fg/dim text, white-alpha
hairlines.
- Disposition + wake-cause hues mapped to the machine signal palette, kept
distinct AND labeled (never colour-only): render = machine-ok green,
active/lit path + per-facet edge-light + cost-fresh + external-wake =
machine-gold, memo-skip = machine-dim grey, fail = machine red (deepened for
AA on charcoal), self-tick = labeled violet.
- Self-host JetBrains Mono (400/500/700 woff2, latin subset, ~65KB) under
src/public/fonts so the machine surface is the real face, offline + keyless.
- Fix copy:public to recurse (fs.cpSync) so the new fonts/ subdir builds and
ships (the old non-recursive copy threw ENOTSUP on a subdir).
Scope: CSS + index.html + fonts only. No app.js logic changes; all class names
and animation hooks preserved, so replay/scrub/animation behaviour is identical.
Verified: pnpm build + typecheck pass and the built server serves /app.css and
/fonts/*.woff2 (200).
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Astro `reports` app (formerly apps/reports in openprose/platform,
publishing to reports.openprose.ai) is gone, leaving only this stale
`docs/reactor/v0.1/` content and a README describing a dead publishing
pipeline. The canonical documentation now lives at the Next.js/Fumadocs
site https://docs.openprose.ai (repo openprose/docs), which carries the
reactor technical report and architecture docs.
Removes `docs/` entirely and repoints the README's technical-report link
to the live docs site.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A Claude-Code session scanner piped into domain world-state. A cheap classifier
(session-signal) fans per-domain signals into four maintained truths
(decisions-log, eng-backlog, use-case-guide, attention-queue) and a coalesced
dashboard, so cost scales with surprise: a session moves only the domains it
touches; the rest memo-skip.
- 7 contracts + reactor.yml (OpenAI gpt-5.4-mini renders, gpt-5.4 compile),
inline-flow static fixtures, opt-in real scanner (connectors.cjs.example),
README + PIPELINE-DESIGN.md.
- Committed replay/ from a captured run (11 rendered, 2 skipped, 0 failed,
~38k fresh tokens) so the reactor eval-harness is reproducible.
- eval-harness: additive, env-gated Anthropic judge (JUDGE_PROVIDER=anthropic
+ JUDGE_MODEL, default claude-opus-4-8) via the CLI's native-Anthropic provider
builder. Default OpenRouter behavior unchanged; REACTOR_OFFLINE still forces
judges off. Eval result: 2/2 grade A (deterministic + opus judge).
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Closes the 3 critical Dependabot alerts (one advisory, GHSA-5xrq-8626-4rwp, CVSS 9.8). vitest is a devDependency; both configs run environment: node only. Offline gate verified green on the 3→4 bump. Resolved a pnpm-lock.yaml conflict with main by regenerating from main's base.