diff --git a/AGENTS.md b/AGENTS.md index d884cf6c..eae0b400 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # OpenProse for Codex -If you're running in Codex and see a `prose` command, a `*.prose.md` contract (`kind: service`, `kind: system`, `kind: test`, or `kind: pattern`), or a mention of OpenProse, ProseScript, Forme, or Contract Markdown, OpenProse is the language you're being asked to run. +If you're running in Codex and see a `prose` command, a `*.prose.md` contract (`kind: responsibility`, `kind: function`, `kind: gateway`, `kind: test`, or `kind: pattern`), or a mention of OpenProse, ProseScript, Forme, or Contract Markdown, OpenProse is the language you're being asked to run. Treat `prose run ...` as an instruction inside the current agent session. Do not call out to a shell command named `prose` unless the host explicitly provides one; instead, embody the OpenProse VM and execute the contract with the primitives available in this session. @@ -8,6 +8,9 @@ Use `prose upgrade --dry-run` to preview legacy migrations and `prose upgrade` t Open `skills/open-prose/SKILL.md` and treat it as the authoritative router. Every command, every file routing decision, and every capability assumption lives there or behind a pointer inside it. Do not search the workspace for alternate copies of the OpenProse documentation — the canonical files are the ones bundled under `skills/open-prose/`. +Use `prose init` and `prose compose` for progressive program architecture; use +`prose write` for focused authoring when one Contract is already understood. + If your run exposes a concrete improvement to OpenProse itself, consider `prose run std/evals/prose-contributor -- subjects: `. It turns run evidence into one focused draft PR. It still needs explicit user approval before diff --git a/CHANGELOG.md b/CHANGELOG.md index eb34761c..0790c6cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- **`prose init` and `prose compose` now provide guided, progressive program + architecture.** The obligation-centered `std/ops/compose` directory package + keeps the architect focused on a bounded conceptual frontier, materializes + settled decisions into one canonical Contract package, derives a disposable + visual view, and creates semantic tests outside-in from the package promise + through Contract boundaries, failure behavior, harness portability, and + performance. Framework pressure discovered during composition is routed to + deduplicated public issues rather than implemented in the target program. + ## [0.16.0] - 2026-08-24 — open-prose skill & plugin Skill/plugin-track release. This repository is now OpenProse only — the diff --git a/README.md b/README.md index 30ca032d..40a2af64 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,11 @@ npx skills add openprose/prose That installs OpenProse into any Prose-Complete coding agent (Claude Code, Codex CLI, OpenCode, and friends). From there, point your agent at a contract and say `prose run `: the session itself embodies the VM; there is no separate binary. The [`examples/`](skills/open-prose/examples/) directory is the tour; start small and read the contract before you run it. +For a new program, say `prose init`, then use `prose compose` to shape its +purpose, topology, Contract boundaries, and outside-in semantic tests. Compose +progressively materializes one directory package; use `prose write` when a +single Contract is already understood and needs focused authoring. + Your first contract is a Markdown file away: `kind: responsibility` frontmatter, a `### Goal` that states what should stay true, and the sections below. The skill teaches your agent the rest. ## The language: Responsibilities diff --git a/packages/std/README.md b/packages/std/README.md index 51e54b6f..cc045696 100644 --- a/packages/std/README.md +++ b/packages/std/README.md @@ -7,6 +7,7 @@ Reusable OpenProse functions, responsibilities, patterns, roles, delivery adapte ```prose use "std/evals/inspector" use "std/evals/prose-contributor" +use "std/ops/compose" use "std/ops/prose-author" use "std/patterns/worker-critic" use "std/patterns/pipeline" @@ -47,6 +48,7 @@ Operational contracts for profiling, debugging, validation, and wiring. | Contract | Purpose | |---------|---------| +| `compose` | Progressively design, test, visualize, and materialize one canonical OpenProse directory package | | `lint` | Validate structure, schema, shapes, and contract consistency for a contract and its sub-unit tree | | `preflight` | Check that all runtime dependencies are satisfied before executing a contract | | `status` | Summarize recent runs from `/runs/` | diff --git a/packages/std/ops/README.md b/packages/std/ops/README.md index 181adc07..42a19768 100644 --- a/packages/std/ops/README.md +++ b/packages/std/ops/README.md @@ -11,10 +11,18 @@ shape/root questions before authoring. The shell CLI wrapper passes request text up front and marks the run non-interactive, so missing blocking decisions come back as `unresolved-intent` instead of terminal prompts. +The `compose/` directory package powers `prose compose` and the architectural portion of +`prose init`. It maintains a small human-facing architectural frontier, +triangulates it with orthogonal constraints, and progressively materializes the +resolved design into one canonical Contract package plus an outside-in test +ladder. It routes OpenProse framework pressure to deduplicated public issues +rather than changing the framework during composition. + ## Systems | System | CLI Command | Description | |---------|-------------|-------------| +| `compose/` | `prose init` / `prose compose [request...]` | Guided Contract composition with progressive source, semantic tests, visual projection, and issue-routed OpenProse feedback | | `lint.prose.md` | `prose lint ` | Validate structure, schema, shapes, and contract matching | | `preflight.prose.md` | `prose preflight ` | Check that dependencies are installed and environment variables are set | | `wire.prose.md` | `prose run std/ops/wire` | Run Forme wiring to produce an execution manifest | diff --git a/packages/std/ops/compose/architecture.prose.md b/packages/std/ops/compose/architecture.prose.md new file mode 100644 index 00000000..23b15dbf --- /dev/null +++ b/packages/std/ops/compose/architecture.prose.md @@ -0,0 +1,378 @@ +--- +name: architecture-designer +kind: function +version: 0.16.0 +--- + +# Architecture Designer + +Update the program architecture from the known intent and elicited decisions. + +### Parameters + +- `current`: prior architecture +- `request`: current request +- `elicitation`: new answers and decisions +- `exploration`: orthogonal constraint analysis +- `topology`: selected whole-system and regional topology profiles, including + their lowering into existing OpenProse mechanisms +- `test_intent`: public promise, prohibited outcomes, and representative + scenarios that the architecture must make testable +- `mental_model_sync`: shared working model used for the decision +- `landscape`: source and runtime facts + +### Returns + +- `candidate`: proposed architecture, change set, Contract proposals, source + mismatches, scenarios, and next actions + +### Strategies + +- Give each Contract a one-line promise before detailing procedure. +- Use package-level test intent to challenge decomposition. Every important + observable must have an owner and every prohibited outcome an enforceable + boundary. +- Choose Contract boundaries in light of the selected topology; do not choose a + topology merely to rationalize boundaries already invented. +- Allow different named regions to use different profiles. Treat a hybrid as a + composition of explicit regional profiles, not as an uninformative catch-all. +- Record call edges separately from data, state, and capability edges. +- Name each data edge as `Return.field -> Parameter.field` when known. +- Preserve distinctions between current source, proposed architecture, and + discovered candidate procedure. +- Use the source projector for progressive whole-program source; recommend + `prose write` when one Contract needs focused authoring outside this cycle. +- Recommend `prose compile` only after blocking architectural gaps are closed. + +--- + +## architecture-landscape-scanner + +Read the local OpenProse landscape without changing it. + +### Parameters + +- `request`: current user request +- `subjects`: optional run or source references + +### Returns + +- `landscape`: OpenProse root, architecture files, source files, compiled + manifests, recent relevant runs, installed standard-library index, harness + configuration, and facts relevant to the current request + +### Invariants + +- Read-only. +- Prefer focused files and indexes over loading the entire repository. +- Do not treat generated manifests or runtime traces as authored intent. + +--- + +## architecture-loader + +Reconstruct the working architecture from the existing program package and its +supporting decision history, or establish an empty bootstrap model. + +### Parameters + +- `landscape`: scanner output +- `mode`: requested Architect mode + +### Returns + +- `current`: normalized projection of package source, decisions, assumptions, open + questions, prior feedback candidates, frozen source facts, and discovered + procedure candidates + +### Strategies + +- Treat the target directory package's `index.prose.md` and nearby Contract + files as the canonical current architecture. +- Use `/architecture/decisions.md` for durable decisions and + rejected alternatives. +- Use `/architecture/openprose-feedback.md` for candidate + framework feedback. +- Treat decision and feedback records as provenance, never as overrides for + Contract source. +- If the target package does not exist in `bootstrap` mode, return an empty + model so the source projector can establish its `index.prose.md`; do not + invent its contents here. + +--- + +## architecture-gap-modeler + +Find the highest-value unknowns in the current architecture. + +### Parameters + +- `request`: current design request +- `current`: loaded architecture +- `landscape`: local facts +- `framework_maturity`: current OpenProse maturity + +### Returns + +- `gaps`: ranked unknowns across desired render, inputs, Contract promises, + interfaces, context exclusions, state ownership, capabilities, composition, + failure behavior, evidence, and harness requirements + +### Strategies + +- Rank gaps by how many downstream decisions they affect. +- A missing desired render outranks naming and file-layout questions. +- A disputed Contract boundary outranks procedure details inside either side. +- Record possible framework pressure, but do not classify it here. + +--- + +## architectural-frontier-selector + +Limit the human-facing design surface without limiting internal exploration. + +### Parameters + +- `gaps`: ranked architecture gaps +- `current`: current architecture and constraint lattice +- `request`: current user direction + +### Returns + +- `active_frontier`: one to three concepts containing: + - concept and current architectural level + - why it is active now + - settled constraints that bound it + - orthogonal axes still needed to triangulate it + - decision that would close or materially narrow it +- `deferred_frontier`: important concepts intentionally kept outside the + current human working set, each with the decision or event that should bring + it back + +### Invariants + +- Never expose more than three active concepts. +- Prefer one concept when it dominates downstream architecture. +- Deferring a concept preserves it; it does not silently resolve or discard it. +- Before opening a new concept, resurface any deferred commitment whose return + condition has been met. +- A settled decision with an unperformed materialization step outranks a new + design question. Perform or explicitly block the step first. + +--- + +## orthogonal-constraint-explorer + +Explore each active concept from independent axes so one decomposition does not +run away with the design. + +### Parameters + +- `frontier`: active architectural concepts +- `current`: current architecture and constraints +- `landscape`: local source, standard-library, harness, and evidence facts + +### Returns + +- `exploration`: for each active concept: + - independent conceptual fan-outs + - agreements and contradictions among them + - orthogonal constraint seeds such as desired render, information boundary, + state ownership, authority, failure behavior, cost, portability, and UX + - option set that efficiently partitions the remaining concept space + - recommendation with uncertainty, never a hidden decision + +### Strategies + +- Many agents may investigate one conceptual task; do not confuse agent count + with conceptual breadth. +- Use no more than three conceptual fan-outs at once. +- Give parallel investigators distinct axes rather than near-duplicate briefs. +- Fan in before opening another conceptual task. + +--- + +## topology-profile-selector + +Select an architectural shape only after the purpose, desired render, and +load-bearing constraints are understood, and before Contract decomposition is +allowed to harden. + +### Parameters + +- `current`: current architecture and any prior topology selections +- `request`: current design request +- `elicitation`: newly resolved context and constraints +- `exploration`: orthogonal options and tradeoffs +- `landscape`: installed standard-library patterns, topology guidance, and + canonical examples + +### Returns + +- `topology`: one or more named regions containing: + - selected topology profile and status: `proposed` or `settled` + - context signals and counter-signals supporting the selection + - compact ASCII shorthand using the profile's standard notation + - likely Contract boundaries and state ownership + - lowering plan using only existing mechanisms: ProseScript `call`, a + `pattern:` instance, or `Requires` ↔ `Maintains` subscriptions + - compatible nested profiles and relevant standard-library patterns + - canonical examples and unresolved topology questions + +### Strategies + +- Load topology profiles through progressive disclosure: show a one-line name, + thumbnail, and fit statement first; load full guidance only for plausible + candidates. +- Distinguish architectural levels instead of placing every shape in one flat + list. A pipeline is usually intra-render coordination; a reactive renderer is + a lifecycle and state model; a bus is an integration shape; fan-out/fan-in is + a coordination shape. +- Prefer small labeled diagrams over symbolic shorthand. The diagram should say + what moves, why a branch exists, and where results meet. For example: + + Pipeline + [Research] -> [Draft] -> [Review] + + Fan out, then combine + +-> [Security review] -+ + [Change request] -+-> [API review] ------+-> [Combined findings] + +-> [UX review] -------+ + + Maintain a projection when its inputs change + [New event or changed input] -> [Render Contract] -> [Updated projection] + ^ | + +-- future change ---+ + + Publish once, deliver to interested Contracts + +-> [Billing Contract] + [Incoming event] -> [Topic] -> [Analytics Contract] + +-> [Notification Contract] +- Names such as `A`, `B`, and `topic` are acceptable only after the architect + already knows what they denote. The first disclosed view uses domain labels, + not notation that requires a legend. +- Prefer ordinary relationship words such as `calls`, `publishes`, `updates`, + and `combines` when arrows alone leave the semantics ambiguous. +- Treat the ASCII view as a mental-model thumbnail, not source or executable + syntax. It must expand into named Contracts and typed relationships before + source projection. +- Store reusable architecture profiles separately from executable coordination + patterns. Profiles may recommend and link to patterns; they do not execute. +- Do not introduce runtime semantics for a profile annotation. Record language + pressure only if repeated programs cannot lower the profile faithfully into + calls, patterns, and subscriptions. + +--- + +## architecture-critic + +Stress-test the proposed program without broadening it. + +### Parameters + +- `candidate`: proposed architecture +- `test_suite`: ordered package and Contract tests +- `landscape`: local facts +- `subjects`: optional run evidence + +### Returns + +- `program_diagnostics`: ranked findings with affected Contract or edge, + evidence, consequence, and smallest corrective decision + +### Strategies + +- Check that every Contract boundary earns its cost. +- Check that the package-level tests observe public behavior rather than + implementation trivia, and that Contract tests align with their declared + promises. +- Check that every required Return has a consumer or top-level purpose. +- Check for ambient context, authority widening, shared mutable scratch, + coordinator collapse, implicit joins, ambiguous state ownership, and missing + failure paths. +- Distinguish static architecture findings from observed runtime failures. +- Do not turn style preferences into blocking diagnostics. + +--- + +## architecture-renderer + +Render one coherent architecture update and its derived visual map. + +### Parameters + +- `candidate`: proposed architecture +- `critique`: program diagnostics +- `feedback`: classified OpenProse feedback +- `test_suite`: ordered tests and current readiness gates + +### Returns + +- `architecture`: complete human-readable architecture +- `constraint_lattice`: settled, provisional, disputed, and superseded + constraints with their relationships and evidence +- `architecture_changes`: focused change list +- `contract_proposals`: source-level changes, with materialization status +- `visual_map`: Mermaid Contract graph derived from the architecture +- `next_actions`: no more than three ordered actions + +### Strategies + +- Keep the default Contract map readable; split call/data, state, capability, + and runtime views when one graph would become ambiguous. +- Mark proposed Contracts and edges differently from frozen source. +- Include unresolved questions near the affected Contract or relationship. +- Do not include raw transcript or scratch in the architecture. + +--- + +## architecture-persister + +Persist only Compose-owned architecture and source projections. + +### Parameters + +- `rendered`: rendered architecture and feedback +- `source_projection`: progressive Contract source +- `visual_artifact`: derived HTML architecture view +- `persistence`: `persist` or `preview` +- `landscape`: root and existing architecture files + +### Returns + +- `final_status_summary`: status, mode, persistence result, architecture files + updated, Contracts proposed, unresolved decisions, feedback candidates, and + next action + +### Errors + +- `persistence-failed`: an owned file could not be written + +### Strategies + +- In `preview`, return the complete proposed contents and write nothing. +- In `persist`, update the canonical target directory package first: + - `/index.prose.md` + - `/*.prose.md` for Compose-managed child Contracts +- Then update supporting, non-authoritative records: + - `/architecture/decisions.md` + - `/architecture/openprose-feedback.md` + - `/architecture/view.html` +- Persist resolved and explicitly provisional Compose-managed source in the + target package. Ask before changing a human-frozen region or public promise. +- Keep system-level intent, desired renders, topology, and composition in the + root Contract without duplicating child Contract promises. Keep unresolved + decisions as explicit provisional markers beside the source they affect. +- Mark every Contract and relationship as `proposed`, `frozen-source`, or + `observed-runtime` so design intent and evidence cannot blur together. +- Keep each decision in `decisions.md` under a stable `ARCH-*` identifier with + status, decision, rationale, alternatives, evidence, and affected Contracts. +- Keep each framework feedback record in `openprose-feedback.md` under a stable + `OPF-*` identifier using the complete top-level feedback schema. +- Treat `view.html` as generated and replaceable; never recover canonical + architecture from it. +- Preserve user-authored notes and prior decisions; append or revise by stable + heading rather than replacing the files wholesale. +- Deduplicate feedback records by observation, layer, and affected construct. +- Report every source file and region changed, including its provenance and + whether it remains provisional. diff --git a/packages/std/ops/compose/compose.test.prose.md b/packages/std/ops/compose/compose.test.prose.md new file mode 100644 index 00000000..743f9eab --- /dev/null +++ b/packages/std/ops/compose/compose.test.prose.md @@ -0,0 +1,41 @@ +--- +name: test-compose-maintains-architectural-thread +kind: test +version: 0.16.0 +subject: compose +--- + +# Compose Maintains The Architectural Thread + +### Fixtures + +- `mode`: compose +- `interactive`: true +- `persistence`: preview +- `authority_scope`: openprose-maintainer +- `framework_maturity`: experimental +- `request`: | + The architect previously selected an obligation-centered directory package, + then explored topology guidance and supplied framework feedback. Continue + from the settled package decision without losing the topology findings. + +### Expects + +- `mental_model_sync`: identifies the obligation-centered package as settled +- `active_frontier`: resurfaces its pending materialization before opening a new + conceptual frontier +- `source_projection`: contains `index.prose.md` plus obligation-owned sibling + Contracts +- `test_strategy`: begins with the package promise and orders later testing + through Contract boundaries, interaction topology, failure behavior, harness + portability, and only then performance +- `openprose_feedback`: preserves topology and package-visibility framework + pressure separately from program architecture + +### Expects Not + +- `next_actions`: asks the architect to reconfirm the settled package decision +- `source_projection`: modifies topology profiles, language documentation, + compiler, adapter, or harness implementation as part of composition +- `test_strategy`: begins with internal helper implementation or performance + optimization before the public promise diff --git a/packages/std/ops/compose/dialogue.prose.md b/packages/std/ops/compose/dialogue.prose.md new file mode 100644 index 00000000..ff0d5b98 --- /dev/null +++ b/packages/std/ops/compose/dialogue.prose.md @@ -0,0 +1,73 @@ +--- +name: architecture-elicitor +kind: function +version: 0.16.0 +--- + +# Architecture Elicitor + +Ask only the questions needed to make meaningful architectural progress. + +### Parameters + +- `frontier`: at most three active architectural concepts +- `exploration`: orthogonal options and tradeoffs +- `mental_model_sync`: compact shared model and selective recall prompts +- `current`: current architecture +- `landscape`: local facts +- `interactive`: whether questions are available + +### Returns + +- `elicitation`: accepted answers, decisions resolved, new constraints, + remaining open questions, blocking missing decisions, and retry hint + +### Strategies + +- Begin a new architecture with: “What should be true after this program runs + that was not true before?” +- Ask the highest-leverage question first. +- Do not ask for confirmation of a settled decision. Materialize its next + reversible consequence and then surface the next genuinely unresolved + decision. +- Every question must identify what downstream architecture its answer unlocks. + If no meaningful branch closes or action becomes possible, do not ask it. +- Prefer mutually exclusive options that divide the remaining design space, + with the recommended option first and a short consequence for each. +- Allow the architect to reject the partition and restate the concept. +- Use recall prompts only when the present decision depends on them. +- Ask follow-ups about boundaries, not implementation trivia. +- If interaction is unavailable, preserve the ranked gaps and return a useful + retry hint rather than guessing. +- The user may say “provisional”; record the answer as an assumption rather + than a decision. + +--- + +## mental-model-synchronizer + +Restore a compact shared model before asking the architect to decide. + +### Parameters + +- `current`: current architecture and constraint lattice +- `frontier`: active and deferred concepts +- `exploration`: orthogonal exploration results + +### Returns + +- `mental_model_sync`: concise statement of: + - current system purpose and desired render + - current zoom level and path + - load-bearing settled constraints relevant now + - what the exploration clarified or challenged + - active options and their real tradeoff + - deferred concepts that remain untouched +- `recall_prompts`: earlier constraints worth resurfacing now because they are + load-bearing, contradicted, or at risk of mental-model drift + +### Invariants + +- Sync is short enough to hold in working memory. +- Do not repeat the whole architecture. +- Spaced repetition is selective recall, not ritual repetition. diff --git a/packages/std/ops/compose/feedback.prose.md b/packages/std/ops/compose/feedback.prose.md new file mode 100644 index 00000000..b3766dd3 --- /dev/null +++ b/packages/std/ops/compose/feedback.prose.md @@ -0,0 +1,83 @@ +--- +name: openprose-feedback-classifier +kind: function +version: 0.16.0 +--- + +# Openprose Feedback Classifier + +Separate project-local design issues from candidate improvements to OpenProse. + +### Parameters + +- `candidate`: proposed architecture +- `current`: prior architecture +- `request`: current user direction +- `landscape`: local facts +- `subjects`: optional evidence +- `authority_scope`: caller authority +- `framework_maturity`: current framework maturity + +### Returns + +- `openprose_feedback`: candidate records matching the top-level schema + +### Strategies + +- First ask whether a clearer Contract or different standard-library + composition solves the pressure without a framework change. +- Attribute each remaining pressure to exactly one primary layer. Record other + layers only as alternatives or follow-ups. +- A single project example is `possibly-general`, not `repeated`. +- Explicit direction from `openprose-maintainer` may be + `maintainer-direction`, even before run evidence exists. +- Broad semantic changes are acceptable candidates in `experimental` mode; + name the experiment that could validate or falsify them. +- Never create a patch, branch, issue, or PR from this classification stage. + Issue publication is a separate, auditable operation after classification. + +--- + +## openprose-feedback-publisher + +Move classified framework pressure across the project boundary without changing +the installed OpenProse package. + +### Parameters + +- `feedback`: classified OpenProse feedback candidates +- `authority_scope`: caller authority +- `landscape`: canonical public repository, existing local feedback records, + and available issue-publishing capability + +### Returns + +- `openprose_feedback`: candidates annotated with publication status and issue + URL when available +- `feedback_publication`: issues found, issues filed, issue drafts, failures, + and deduplication rationale + +### Invariants + +- Never implement framework feedback during Compose. +- Never edit the installed language, standard library, interpreter guidance, + compiler, adapter, or harness in response to feedback from the current design + session. +- Search open and closed public issues before filing. Prefer adding evidence to + an existing issue over creating a duplicate. +- Each issue separates observation and evidence from the candidate solution; + Compose discoveries are requests for later work, not foregone conclusions. +- Issue publication is the only permitted outward framework mutation. Never + create a patch, branch, commit, or pull request. + +### Strategies + +- With `openprose-maintainer` authority and issue capability available, file or + deduplicate the issue after classification. +- Without maintainer authority or issue capability, return a complete issue + draft and preserve it in `architecture/openprose-feedback.md`. +- Use a concise problem-oriented title. Include affected layer, evidence, + smallest plausible change, alternatives, compatibility pressure, and links + to any originating architecture decision that is safe to publish. +- Do not publish project secrets, private paths, raw transcripts, or proprietary + program details. Reduce evidence to the smallest public reproduction. diff --git a/packages/std/ops/compose/index.prose.md b/packages/std/ops/compose/index.prose.md new file mode 100644 index 00000000..376fb20e --- /dev/null +++ b/packages/std/ops/compose/index.prose.md @@ -0,0 +1,368 @@ +--- +name: compose +kind: function +version: 0.16.0 +--- + +# Compose + +Progressively design and materialize an OpenProse program while keeping the +human architect's mental model coherent. Compose may explore broadly behind the +scenes, but exposes only a small architectural frontier at a time. + +This function powers `prose compose`. `prose init` invokes it in `bootstrap` +mode after establishing the OpenProse root and harness selection. + +Compose maintains two deliberately separate feedback loops: + +1. **Program architecture** — what this program promises, which Contracts it + needs, how values and authority cross boundaries, and what it renders. +2. **OpenProse feedback** — where designing the program reveals pressure on the + language, standard library, interpreter guidance, compiler, adapter ABI, or + authoring experience. + +Program decisions progressively update one coherent OpenProse directory +package. Its root `index.prose.md` expresses system-level intent and +composition; nearby Contract files own their local promises. The architecture +model is reconstructed from that package plus its decision history—it is not a +parallel source of truth. OpenProse feedback is recorded only as candidate +feedback. It never changes the language, standard library, skill, or harness +implementation during `prose compose`. +After classification and deduplication, maintainer-authorized feedback is filed +as an issue on the public OpenProse repository for separate implementation. + +### Parameters + +- `mode`: one of `bootstrap`, `compose`, `review`, or `reflect`; default + `compose` +- `request`: the user's current design goal, question, correction, rough + workflow, or feedback +- `interactive`: whether the host may ask targeted questions; default `true` +- `persistence`: `persist` or `preview`; default `persist` +- `authority_scope`: `project-author` or `openprose-maintainer`; default + `project-author` +- `framework_maturity`: `experimental`, `stabilizing`, or `stable`; default + `experimental` until project configuration says otherwise +- `subjects`: optional completed run IDs, inspection reports, or source paths + to consider in `review` or `reflect` mode + +### Returns + +- `architecture`: a working projection of the current program package containing: + - intent and desired renders + - topology profiles selected for the whole system or named regions, with + compact ASCII shorthand and the evidence for each selection + - Contract inventory and one-line promises + - parameters, Returns, maintained projections, capabilities, and important + exclusions at each boundary + - call, data, state, and authority relationships + - relevant standard-library composition candidates + - harness capability requirements + - scenarios, failure behavior, decisions, assumptions, and open questions +- `architecture_changes`: changes made or proposed during this invocation, + with rationale +- `contract_proposals`: Contracts to add, split, merge, remove, or revise, + including which resolved changes were materialized into source +- `test_strategy`: ordered tests that progressively constrain the program from + its public promise down to Contract boundaries, failure behavior, portability, + and performance +- `visual_map`: a derived Mermaid Contract map plus a compact ASCII topology + shorthand and concise legends for call, data, maintained-state, and + capability relationships +- `program_diagnostics`: findings about this program, ordered by architectural + impact +- `openprose_feedback`: zero or more candidate feedback records, each with: + - observation: what the design session exposed + - pressure: why the current OpenProse surface made the work harder, less + clear, less portable, or less expressive + - layer: `language`, `standard-library`, `interpreter`, `compiler`, + `adapter`, `authoring`, `visualization`, or `documentation` + - scope: `project-specific`, `possibly-general`, `repeated`, or + `maintainer-direction` + - evidence: answers, architecture decisions, source locations, runs, or + scenarios supporting the record + - candidate_change: the smallest currently plausible change + - alternatives: viable ways to address the pressure without changing that + layer + - maturity_effect: how the proposal should be treated at the current + framework maturity + - status: `candidate`, `already-filed`, or `filed` + - issue_url: public issue when one already exists or was filed +- `feedback_publication`: issues found, filed, or prepared as drafts, including + why any candidate was not published +- `constraint_lattice`: established, provisional, disputed, and superseded + constraints, including the orthogonal constraints that triangulate each + important architectural concept +- `active_frontier`: at most three architectural concepts currently exposed + for human attention, with why each is active and what decision would close it +- `mental_model_sync`: concise restatement of the current system, what changed, + which earlier constraints remain load-bearing, and where uncertainty remains +- `source_projection`: complete Contract source for resolved regions plus + clearly marked placeholders for unresolved regions; never disguise a + placeholder as settled source +- `visual_artifact`: a generated, self-contained HTML view derived from the + architecture and constraint lattice +- `next_actions`: small ordered set such as another composition question, + `prose write`, `prose compile`, or an evidence-gathering run +- `final_status_summary`: concise status, files updated, Contracts proposed, + unresolved decisions, feedback candidates, and next action + +### Errors + +- `architecture-unresolved`: a missing decision prevents a coherent Contract + boundary or desired render; include the exact decision without inventing it +- `architecture-conflict`: current source, architecture, and the user's new + direction make incompatible claims; preserve both claims and ask which wins +- `persistence-failed`: the program package or supporting records could not be updated; + return the proposed update without claiming it was written +- `insufficient-evidence`: `reflect` was requested but the subjects do not + support the proposed program or OpenProse conclusion + +### Invariants + +- Begin from the desired render: what should be true after the program runs + that was not true before. Do not begin by asking how many agents the user + wants. +- Turn the desired render into a package-level `kind: test` before internal + decomposition hardens. Tests constrain architecture; they are not merely a + validation batch written after implementation. +- A proposed Contract boundary must earn its existence through an independent + promise, useful isolation, distinct authority, reusable composition, + independently useful output, separate state ownership, parallelism, or + different runtime needs. +- Do not manufacture orchestration when one competent Contract is sufficient. +- Expose no more than three active architectural concepts to the user at once. + Internal agent fan-out may be wider; the human-facing frontier may not. +- Triangulate important concepts with orthogonal constraints. Do not let one + decomposition axis define the architecture by itself. +- Before asking for another decision, provide a compact mental-model sync: + current scope, relevant settled constraints, new pressure, and the decision + now being divided. +- Prefer multiple-choice questions whose options partition the remaining + concept space. Always permit correction or an option the model missed. +- Use spaced repetition for load-bearing constraints: resurface an earlier + decision when new work depends on it, appears to contradict it, or enough + architectural distance has accumulated that drift is plausible. +- Support zooming without losing position. A zoomed-in Contract view retains + its path to the desired render; a zoomed-out system view preserves unresolved + details instead of flattening them away. +- Keep program diagnostics and OpenProse feedback separate. A defect in one + program is not automatically a language defect. +- Materialize Contract source continuously as architecture resolves. Mark + provisional and unresolved regions explicitly; never present them as frozen. +- Compose may update source files it created or regions explicitly marked as + Compose-managed. It must ask before replacing human-frozen procedure or + changing a public Contract promise. +- Never modify OpenProse framework, standard-library, skill, compiler, adapter, + or documentation source during composition. +- `authority_scope: openprose-maintainer` permits explicit + `maintainer-direction` feedback; it does not bypass the separation or apply + changes automatically. +- In `experimental` maturity, foundational changes are legitimate candidates + and may be based on explicit maintainer direction. Mark uncertainty and + compatibility consequences rather than suppressing the proposal. +- In `stabilizing` maturity, prefer repeated evidence, executable examples, + and migration plans for semantic changes. +- In `stable` maturity, require compatibility analysis and strong evidence for + semantic changes; prefer library or guidance changes when they solve the + pressure without changing the language. +- The OpenProse directory package is the canonical authored truth. Its + `index.prose.md` owns system-level intent and composition; each child Contract + owns its promise and interface. Supporting architecture records explain or + visualize the package but never override it. +- Compose owns only source it created or regions explicitly marked + Compose-managed. Generated `dist/`, run evidence, human-frozen source, and + upstream OpenProse files remain outside its unilateral write boundary. +- The visual map is derived from the program package and decision records. It + is never a second, independently edited source of truth. +- Generated HTML is disposable and derived. It must identify the source + package revision and may never carry architectural facts absent from the + package or its explicitly provisional source markers. +- Static architecture describes what may happen. Runtime traces describe what + did happen. Never present one as the other. +- Ask one highest-leverage question at a time when practical, or at most three + tightly related questions in one interaction. Accept narrative answers that + resolve several gaps at once. +- Do not ask questions whose answers are already available in nearby source, + architecture, configuration, or run evidence. +- Preserve unresolved decisions explicitly. Do not create false architectural + certainty to make the diagram look complete. +- Keep discovered candidate procedure separate from frozen, source-controlled + procedure. +- Contract source crystallizes incrementally. Resolved regions may become full + source while unresolved regions remain explicit proposals or placeholders. +- Do not ask for secrets or include raw environment values in architecture or + feedback artifacts. + +### Tools + +- `ask_user`: targeted architecture questions when the host supports them +- filesystem read/list/search: read-only landscape and evidence inspection +- filesystem write: limited to `/architecture/` and explicitly + Compose-managed source regions when `persistence` is `persist` +- public issue search/create: optional; limited to the canonical OpenProse + repository and only for classified OpenProse feedback + +### Strategies + +- Work backward from desired renders, observable Returns, and maintained + projections before naming Contracts. +- Prefer questions that change a boundary, interface, state owner, authority + boundary, failure policy, or harness requirement. +- Name Contract promises before discussing their procedures. +- For each proposed call, make the downward arguments and upward Returns + explicit; record learnings separately from Returns. +- Identify what each frame must not see as well as what it receives. +- Distinguish semantic work from mechanics that should be deterministic code. +- Reuse standard-library Contracts when their promises and invariants fit; + never select a pattern by name alone. +- Challenge coordination Contracts that also perform their children's work. +- Use scenario walkthroughs to expose hidden coupling: ordinary success, one + child failure, incomplete settlement, partial fan-out, budget exhaustion, + state conflict, prohibited context leakage, and resume/re-entry. +- When a difficulty may be either a weak program design or a framework gap, + state both hypotheses and propose the cheapest discriminating example or run. +- Treat explicit maintainer corrections as important design evidence, while + still recording affected layer, alternatives, and compatibility pressure. +- Keep `next_actions` short. Prefer the one action that resolves the most + architectural uncertainty. + +### Execution + +```prose +let landscape = call architecture-landscape-scanner + request: request + subjects: subjects + +let current = call architecture-loader + landscape: landscape + mode: mode + +let gaps = call architecture-gap-modeler + request: request + current: current + landscape: landscape + framework_maturity: framework_maturity + +let frontier = call architectural-frontier-selector + gaps: gaps + current: current + request: request + +let exploration = call orthogonal-constraint-explorer + frontier: frontier + current: current + landscape: landscape + +let sync = call mental-model-synchronizer + current: current + frontier: frontier + exploration: exploration + +let elicitation = call architecture-elicitor + frontier: frontier + exploration: exploration + mental_model_sync: sync + current: current + landscape: landscape + interactive: interactive + +if elicitation has blocking missing decisions: + throw { + error: "architecture-unresolved", + missing_decisions: elicitation.blocking_missing_decisions, + known_architecture: current.summary, + retry_request_hint: elicitation.retry_request_hint + } + +let topology = call topology-profile-selector + current: current + request: request + elicitation: elicitation + exploration: exploration + landscape: landscape + +let test_intent = call test-intent-designer + current: current + request: request + elicitation: elicitation + topology: topology + landscape: landscape + +let candidate = call architecture-designer + current: current + request: request + elicitation: elicitation + exploration: exploration + topology: topology + test_intent: test_intent + mental_model_sync: sync + landscape: landscape + +let test_suite = call test-suite-projector + candidate: candidate + test_intent: test_intent + current: current + landscape: landscape + +parallel: + let critique = call architecture-critic + candidate: candidate + test_suite: test_suite + landscape: landscape + subjects: subjects + + let feedback = call openprose-feedback-classifier + candidate: candidate + current: current + request: request + landscape: landscape + subjects: subjects + authority_scope: authority_scope + framework_maturity: framework_maturity + +let feedback_publication = call openprose-feedback-publisher + feedback: feedback + authority_scope: authority_scope + landscape: landscape + +let rendered = call architecture-renderer + candidate: candidate + critique: critique + feedback: feedback_publication + test_suite: test_suite + +let source_projection = call contract-source-projector + rendered: rendered + current: current + test_suite: test_suite + +let visual_artifact = call architecture-view-renderer + rendered: rendered + source_projection: source_projection + +let persisted = call architecture-persister + rendered: rendered + source_projection: source_projection + visual_artifact: visual_artifact + persistence: persistence + landscape: landscape + +return { + architecture: rendered.architecture, + architecture_changes: rendered.architecture_changes, + contract_proposals: rendered.contract_proposals, + test_strategy: test_suite.test_strategy, + visual_map: rendered.visual_map, + program_diagnostics: critique.program_diagnostics, + openprose_feedback: feedback_publication.openprose_feedback, + feedback_publication: feedback_publication.feedback_publication, + constraint_lattice: rendered.constraint_lattice, + active_frontier: frontier.active_frontier, + mental_model_sync: sync.mental_model_sync, + source_projection: source_projection.source_projection, + visual_artifact: visual_artifact.visual_artifact, + next_actions: rendered.next_actions, + final_status_summary: persisted.final_status_summary +} +``` diff --git a/packages/std/ops/compose/source.prose.md b/packages/std/ops/compose/source.prose.md new file mode 100644 index 00000000..6cd199bc --- /dev/null +++ b/packages/std/ops/compose/source.prose.md @@ -0,0 +1,56 @@ +--- +name: contract-source-projector +kind: function +version: 0.16.0 +--- + +# Contract Source Projector + +Continuously materialize settled design into one readable OpenProse directory +package. + +### Parameters + +- `rendered`: updated architecture, constraints, proposals, and diagnostics +- `current`: current package source, supporting decisions, and frozen-source facts +- `test_suite`: ordered test sources and readiness gates + +### Returns + +- `source_projection`: complete source tree containing: + - full Contract source for resolved regions + - explicit architect markers for provisional or unresolved regions + - provenance per changed region: `compose-managed`, `human-frozen`, or + `discovered-candidate` + - source changes proposed for this cycle + - package-level and Contract-level `kind: test` source for resolved behavior + - compile readiness and remaining blockers + +### Invariants + +- The directory package is the canonical persisted program. The working + architecture proposes changes to it; it does not remain a parallel truth + after persistence. +- The root `index.prose.md` owns system-level intent and composition. Child + Contracts own local promises and interfaces. +- Materialization is progressive, not a final batch generated after all + questions are answered. +- Never fill an unresolved semantic boundary with plausible prose merely to + make a file look complete. +- Never overwrite `human-frozen` procedure without an explicit decision. +- Every public promise change is visible in the mental-model sync before it is + persisted. +- Keep tests beside the package they constrain. A public promise is not resolved + until its package-level test expresses the observable outcome and important + exclusions. +- Resolved source uses current Contract Markdown and remains suitable for + focused refinement through `prose write`. + +### Strategies + +- Prefer stable filenames and Contract identities as specificity increases. +- Use concise HTML comments for unresolved architect decisions so ordinary + Markdown remains readable. +- Remove a marker when its underlying constraint is resolved; do not retain a + shadow checklist elsewhere. +- Report `compile-ready` only when no blocking markers remain. diff --git a/packages/std/ops/compose/tests.prose.md b/packages/std/ops/compose/tests.prose.md new file mode 100644 index 00000000..e83aa3a5 --- /dev/null +++ b/packages/std/ops/compose/tests.prose.md @@ -0,0 +1,112 @@ +--- +name: test-intent-designer +kind: function +version: 0.16.0 +--- + +# Test Intent Designer + +Turn the desired render into an outside-in testing intent before internal +decomposition hardens. The first test constrains the package promise, not its +implementation. + +### Parameters + +- `current`: current program package and prior test evidence +- `request`: current design request +- `elicitation`: resolved purpose, requirements, exclusions, and assumptions +- `topology`: proposed system and regional topology profiles +- `landscape`: existing test source, `kind: test` guidance, harnesses, and run + evidence + +### Returns + +- `test_intent`: containing: + - public subject: the package-root Contract from `index.prose.md` + - representative fixtures derived from real intended use + - observable desired outcomes + - important prohibited outcomes + - unresolved assertions that still require architect judgment + - topology and harness behaviors that must become observable later + +### Invariants + +- Start with the package promise: given representative inputs, what observable + result or maintained truth proves that the program did its job? +- Assert semantics, not exact wording or a preferred internal decomposition. +- Include `Expects Not` for the most important forms of plausible but wrong + behavior. +- Do not invent fixtures that hide an unresolved product decision. +- Do not require every internal Contract to exist before the public test can be + drafted. + +### Strategies + +- Derive the first fixture from the ordinary success scenario, then add the + smallest fixture that distinguishes a dangerous near-miss. +- Keep architectural quality claims observable: isolation becomes prohibited + leakage; bounded work becomes a termination or budget assertion; durable + state becomes an assertion over the maintained projection. +- Mark the test provisional when its public promise is still provisional. A + provisional test guides composition but does not falsely certify readiness. + +--- + +## test-suite-projector + +Refine package test intent into an ordered suite that guides implementation and +iteration without freezing internal details too early. + +### Parameters + +- `candidate`: proposed program architecture and Contract inventory +- `test_intent`: outside-in public test intent +- `current`: existing package tests and prior run evidence +- `landscape`: current `kind: test` semantics and available harnesses + +### Returns + +- `test_strategy`: an ordered ladder containing: + 1. **Package promise** — root `index.prose.md` behavior under ordinary and + distinguishing fixtures + 2. **Contract boundaries** — each stable child promise, inputs, Returns or + maintained truth, invariants, and prohibited context or authority + 3. **Interaction topology** — fan-out/fan-in, ordering, subscription, + settlement, and state-ownership behavior visible through the root + 4. **Failure and recovery** — child failure, partial results, timeout, + retries, budget exhaustion, resume, and side-effect safety where relevant + 5. **Harness portability** — the same semantic test corpus under each + supported harness adapter, without provider-specific assertions + 6. **Performance and cost** — tracked only after semantic behavior has a + stable baseline +- `test_sources`: complete or provisional `kind: test` files using `subject`, + `### Fixtures`, `### Expects`, and `### Expects Not` +- `readiness`: first failing or missing rung, evidence, and the smallest next + change that can advance it + +### Invariants + +- Iterate in ladder order. A later performance improvement never outranks a + failing public promise or unsafe failure path. +- Package tests target the root Contract. Contract tests target a child only + after its boundary is stable enough to be meaningful. +- Prefer the smallest test that rules out the largest incorrect region of the + design space. +- A test failure is evidence about the program first. Classify framework + pressure separately and publish it through the feedback obligation. +- Do not encode topology as an implementation snapshot when the same promise + can be tested through observable behavior. +- Do not claim cross-harness portability until the same test sources have run + through each selected adapter. + +### Strategies + +- Preserve useful failing tests. They are unresolved constraints, not clutter. +- After each material architecture change, run the earliest affected rung + before widening the test scope. +- When a test is flaky, separate ambiguity in the assertion from model + variability and harness nondeterminism before weakening it. +- Use semantic assertions for agent outputs and deterministic checks for file + shape, schemas, bounds, receipts, and side-effect limits. +- Track performance and cost over comparable passing runs; never trade away a + semantic assertion merely to improve the metric. diff --git a/packages/std/ops/compose/view.prose.md b/packages/std/ops/compose/view.prose.md new file mode 100644 index 00000000..7c842910 --- /dev/null +++ b/packages/std/ops/compose/view.prose.md @@ -0,0 +1,49 @@ +--- +name: architecture-view-renderer +kind: function +version: 0.16.0 +--- + +# Architecture View Renderer + +Render a disposable visual interface over the canonical program package. + +### Parameters + +- `rendered`: program-package projection and constraint lattice +- `source_projection`: current Contract source projection + +### Returns + +- `visual_artifact`: self-contained HTML containing: + - zoomable Contract map + - topology profile cards with the standard ASCII thumbnail, fit statement, + selected regions, and links to the full profile and canonical examples + - active-frontier emphasis and deferred-concept dimming + - call, data, state, context, and capability overlays + - settled, provisional, disputed, and unresolved constraint states + - source completeness and compile-readiness indicators + - architecture version and generation timestamp + +### Invariants + +- HTML is downstream, disposable, and never authoritative. +- Every displayed fact traces to Contract source, an explicit provisional + marker, or a supporting decision record. +- The view must distinguish proposed architecture from observed runtime traces. + +### Strategies + +- Generate one self-contained file with no service dependency. +- Default to the current zoom level and active frontier rather than displaying + the entire graph at full detail. +- Prefer semantic zoom: system purpose → Contract promises → interfaces → + procedure and evidence. +- Keep the selected topology thumbnail visible as an orientation landmark while + zooming. Highlight the current region instead of redrawing the whole system. +- Keep meaningful layout hints beside the system-level composition in + `index.prose.md`; keep incidental coordinates in the generated artifact. + +This renderer remains an internal function initially. Promote it to a separate +downstream Contract only when another program needs the view independently or +when its interface stabilizes enough to reuse. diff --git a/skills/open-prose/SKILL.md b/skills/open-prose/SKILL.md index 6da56abf..6f6bfd64 100644 --- a/skills/open-prose/SKILL.md +++ b/skills/open-prose/SKILL.md @@ -36,6 +36,7 @@ After activation, choose the narrowest path that matches the user's intent: | User Intent | Load First | Then Load If Needed | |-------------|------------|---------------------| | Explain OpenProse or answer "how do I..." | `help.md` | `examples/README.md`, then one focused example | +| Initialize or compose an OpenProse program | `guidance/tenets.md` | `guidance/authoring.md`, then run `std/ops/compose` | | Run a `.prose.md` responsibility or function | `contract-markdown.md` | `state/README.md` and the selected backend (`state/filesystem.md` by default); `forme.md` if responsibilities must be wired (`### Requires` → `### Maintains`); `prose.md` to execute | | Inspect or upgrade source layout | `changelog.md` | `contract-markdown.md`, `prosescript.md` if migration details require them | | Write a new `.prose.md` responsibility or function | `contract-markdown.md` | `guidance/tenets.md`, `guidance/authoring.md` | @@ -60,9 +61,11 @@ All OpenProse paths are relative to ``. | Attached repository | `repo/.agents/prose` | | User-global | `~/.agents/prose` | -The root contains `src/` for authored intent, `dist/` for compiled intent, -`runs/` for activation receipts, `state/` for durable cross-run state, `deps/` -for installed dependencies, plus `prose.lock` and `.env`. +The root contains `src/` for the canonical authored program packages, +`architecture/` for supporting decisions, visual projections, and issue +records, `dist/` for compiled intent, `runs/` for activation receipts, `state/` +for durable cross-run state, `deps/` for installed dependencies, plus +`prose.lock` and `.env`. ## Proposing This Skill On Your Own Judgment @@ -123,6 +126,9 @@ executing the contract. The shell executable is the agent runner, e.g. | Command | Action | |---------|--------| +| `prose init [request...]` | Establish the minimal OpenProse root and harness selection, then run `std/ops/compose` in `bootstrap` mode. Begin from the desired render and progressively establish a directory package whose `index.prose.md` is the public root | +| `prose compose [request...]` | Load `guidance/tenets.md`, `guidance/authoring.md`, the target Contract package, supporting decisions, and relevant run evidence; run `std/ops/compose` in `compose` mode. Maintain no more than three active conceptual fronts, materialize settled design into source, build tests from package promise through performance, generate a derived HTML view, and route framework pressure to deduplicated public issues when authorized | +| `prose compose --review` / `--reflect ` | Run `std/ops/compose` in `review` mode to challenge static design and test coverage, or `reflect` mode to compare it with completed run evidence. Keep program diagnostics distinct from OpenProse issue feedback | | `prose compile [path] [--out ]` | Load `responsibility-runtime.md`, then `compiler/index.prose.md`; run the pinned ProseScript compiler and emit the compile-phase IR — the topology world-model (nodes, edges, entry points), per-node canonicalizers and postcondition validators, frozen contract fingerprints, and diagnostics — into `/dist/manifest.next.json` by default | | `prose compile ` | Load `visual-source.md`. The image is a **typed image** (a visual brief, one rung above markdown). Run the *resolve* render: read the pixels against `visual-source.md`'s requirement tiers, emit `.prose.md` contract(s) into `/src/` for ratification (the `prose write` discipline — interrupt, do not guess, on safety-bearing blanks), then run the ordinary compile. Compiling **is** the typecheck (acyclic + round-trip-stable) | | `prose serve` | Load and validate `/dist/manifest.active.json`, which is promoted from `manifest.next.json` with `cp dist/manifest.next.json dist/manifest.active.json`; register local cron and HTTP trigger adapters; launch ordinary bounded activations | @@ -283,6 +289,7 @@ another repository uses `repo/.agents/prose`. User-global work uses | Path | Purpose | |------|---------| +| `/architecture/` | Supporting decisions, generated visual map, and OpenProse issue links or drafts; never a second source of truth | | `/src/` | Default source root for project, directory, or repository scoped OpenProse | | `/src/**/index.prose.md` | Conventional multi-file DAG root for a set of wired responsibilities | | `/dist/` | Compiled intent and served manifests | diff --git a/skills/open-prose/changelog.md b/skills/open-prose/changelog.md index 3e1f7e3d..c8161bb0 100644 --- a/skills/open-prose/changelog.md +++ b/skills/open-prose/changelog.md @@ -26,16 +26,28 @@ plan. - Native repositories use the repository root as the OpenProse root. - Attached repositories use `repo/.agents/prose`. - User-global OpenProse uses `~/.agents/prose`. -- The root contains `src/`, `dist/`, `runs/`, `state/`, `deps/`, - `prose.lock`, and `.env`. +- The root contains `src/`, `architecture/`, `dist/`, `runs/`, `state/`, + `deps/`, `prose.lock`, and `.env`. Canonical authored truth remains in + `src/`; `architecture/` contains supporting Compose decisions and projections. - Durable cross-run agents live in `state/agents/`. - Each responsibility's persisted world-model and its signed, append-only receipt ledger are the durable cross-run truth; there is no separate status or pressure store (the judge loop is retired). - Multi-file systems conventionally use `index.prose.md`. +- `prose init` and `prose compose` run the `std/ops/compose` directory package. + Compose progressively materializes a canonical directory package, develops + semantic tests outside-in, and routes framework feedback to public issues + rather than implementing it during composition. - Generated run internals include the compiled activation manifest, `root.prose.md`, and `vm.log.md`. +## Unreleased + +- Introduces `prose init` / `prose compose` and the obligation-centered + `std/ops/compose` directory package, including bounded architectural fronts, + progressive Contract source, derived visual views, outside-in semantic test + ordering, and issue-routed OpenProse feedback. + ## History - `v0.4.x`: early skill discovery, `prose help`, filesystem state, examples in diff --git a/skills/open-prose/help.md b/skills/open-prose/help.md index 8f50f5d6..25b322eb 100644 --- a/skills/open-prose/help.md +++ b/skills/open-prose/help.md @@ -33,7 +33,7 @@ Options: **After the user responds:** - **Run a contract**: Ask for the file path, then load `prose.md` and execute -- **Build something new**: Ask them to describe their task, then help write a contract (load `guidance/authoring.md`) +- **Build something new**: Start with `prose init` / `prose compose` when the Contract system is not yet clear; use `prose write` when one Contract is already understood - **Keep a goal true**: Help author a `kind: responsibility`, then explain `prose compile`, `prose serve`, and `prose status` - **Learn the syntax**: Show examples from `examples/`, explain the VM model - **Improve OpenProse**: Run `std/evals/prose-contributor` on relevant run IDs; require explicit user approval before pushing or opening a PR @@ -45,6 +45,8 @@ Options: | Command | What it does | |---------|--------------| +| `prose init [request...]` | Initialize an OpenProse workspace and begin its architecture | +| `prose compose [request...]` | Design and evolve the program's Contracts, relationships, and architecture | | `prose compile [path] [--out ]` | Compile source into `/dist/manifest.next.json` | | `prose serve` | Serve the active IR as local cron and HTTP trigger adapters | | `prose run ` | Run a responsibility or function contract | @@ -75,11 +77,20 @@ prose serve **Create your first contract:** ``` -prose help --> Select "Build something new" --> Describe what you want to automate +prose init +prose compose +prose write ``` +`prose compose` progressively turns the project architecture into full Contract +source while keeping unresolved regions explicit. It creates semantic tests in +order from the package promise through Contract boundaries, failure behavior, +portability, and performance. It never edits the OpenProse framework during +composition; framework feedback is deduplicated and filed as a public issue +when authorized, or preserved as an issue draft. +Use `prose compose --review` to challenge the current design and +`prose compose --reflect ` to compare it with execution evidence. + Default project source lives under `/src/`. Multi-file systems conventionally start at `/src/{system}/index.prose.md`; runs are written to `/runs/`. diff --git a/skills/open-prose/prose.md b/skills/open-prose/prose.md index c5e1c7ed..445855ae 100644 --- a/skills/open-prose/prose.md +++ b/skills/open-prose/prose.md @@ -37,6 +37,8 @@ codex exec "prose run research.prose.md" | Command | Action | | --------------------------- | --------------------------------------------------------------- | +| `prose init [request...]` | Initialize an OpenProse root and invoke the `std/ops/compose` package in bootstrap mode | +| `prose compose [request...]` | Progressively design, test, visualize, and materialize one canonical Contract package | | `prose compile [path]` | Compile Responsibility Runtime source into validated repository IR | | `prose serve` | Serve active repository IR as local cron and HTTP trigger adapters | | `prose run ` | Execute a local responsibility or function | diff --git a/tests/open-prose/compose/compose.test.ts b/tests/open-prose/compose/compose.test.ts new file mode 100644 index 00000000..b968924b --- /dev/null +++ b/tests/open-prose/compose/compose.test.ts @@ -0,0 +1,133 @@ +import { readFileSync } from "node:fs"; +import { join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { describe, expect, it } from "vitest"; + +const repoRoot = fileURLToPath(new URL("../../../", import.meta.url)); + +function read(path: string): string { + return readFileSync(join(repoRoot, path), "utf8"); +} + +describe("prose compose", () => { + const composePackage = [ + "index.prose.md", + "compose.test.prose.md", + "architecture.prose.md", + "dialogue.prose.md", + "source.prose.md", + "tests.prose.md", + "view.prose.md", + "feedback.prose.md", + ]; + const compose = composePackage + .map((path) => read(`packages/std/ops/compose/${path}`)) + .join("\n"); + + it("is a bounded standard-library function behind init and compose", () => { + expect(compose).toMatch(/name: compose/); + expect(compose).toMatch(/kind: function/); + expect(compose).toMatch(/powers `prose compose`/); + expect(compose).toMatch(/`prose init` invokes it in `bootstrap`/); + }); + + it("is an obligation-centered directory package", () => { + expect(composePackage).toEqual([ + "index.prose.md", + "compose.test.prose.md", + "architecture.prose.md", + "dialogue.prose.md", + "source.prose.md", + "tests.prose.md", + "view.prose.md", + "feedback.prose.md", + ]); + }); + + it("resolves every root call within the directory package", () => { + const defined = new Set(); + for (const path of composePackage) { + const source = read(`packages/std/ops/compose/${path}`); + for (const match of source.matchAll(/^name:\s+([a-z][a-z0-9-]*)$/gm)) { + defined.add(match[1]); + } + for (const match of source.matchAll(/^##\s+([a-z][a-z0-9-]*)$/gm)) { + defined.add(match[1]); + } + } + + const root = read("packages/std/ops/compose/index.prose.md"); + const calls = [...root.matchAll(/\bcall\s+([a-z][a-z0-9-]*)/g)].map( + (match) => match[1], + ); + expect(calls.length).toBeGreaterThan(0); + expect(calls.filter((name) => !defined.has(name))).toEqual([]); + }); + + it("orders program tests from public promise toward optimization", () => { + expect(compose).toMatch(/name: test-intent-designer/); + expect(compose).toMatch(/package promise/); + expect(compose).toMatch(/Contract boundaries/); + expect(compose).toMatch(/failure and recovery/i); + expect(compose).toMatch(/harness portability/i); + expect(compose).toMatch(/performance and cost/i); + }); + + it("keeps program design and framework feedback separate", () => { + expect(compose).toMatch(/Program architecture/); + expect(compose).toMatch(/OpenProse feedback/); + expect(compose).toMatch(/openprose-feedback-publisher/); + expect(compose).toMatch(/filed\s+as an issue on the public OpenProse repository/); + expect(compose).toMatch(/Never implement framework feedback during Compose/); + expect(compose).toMatch(/Never modify OpenProse framework/); + }); + + it("allows deep early feedback without silently promoting it", () => { + expect(compose).toMatch(/`experimental`, `stabilizing`, or `stable`/); + expect(compose).toMatch(/foundational changes are legitimate candidates/); + expect(compose).toMatch(/maintainer-direction/); + }); + + it("starts architecture from the render rather than an agent org chart", () => { + expect(compose).toMatch(/Begin from the desired render/); + expect(compose).toMatch(/What should be true after this program runs/); + expect(compose).toMatch(/must earn its existence/); + }); + + it("bounds the human frontier and triangulates with orthogonal constraints", () => { + expect(compose).toMatch(/no more than three active architectural concepts/i); + expect(compose).toMatch(/orthogonal constraints/i); + expect(compose).toMatch(/mental-model sync/i); + expect(compose).toMatch(/spaced repetition/i); + expect(compose).toMatch(/resurface any deferred commitment/i); + expect(compose).toMatch(/Do not ask for confirmation of a settled decision/); + }); + + it("progressively materializes source while preserving human-frozen regions", () => { + expect(compose).toContain("/index.prose.md"); + expect(compose).toContain("/architecture/decisions.md"); + expect(compose).toContain("/architecture/openprose-feedback.md"); + expect(compose).toMatch(/directory package is the canonical authored truth/); + expect(compose).toMatch(/Materialize Contract source continuously/); + expect(compose).toMatch(/human-frozen/); + }); + + it("keeps the HTML view downstream and disposable", () => { + expect(compose).toMatch(/architecture-view-renderer/); + expect(compose).toContain("/architecture/view.html"); + expect(compose).toMatch(/HTML is downstream, disposable, and never authoritative/); + }); + + it("is routed consistently across the interpreter docs", () => { + for (const path of [ + "skills/open-prose/SKILL.md", + "skills/open-prose/help.md", + "skills/open-prose/prose.md", + "packages/std/ops/README.md", + ]) { + const source = read(path); + expect(source, path).toMatch(/prose init/); + expect(source, path).toMatch(/prose compose/); + } + }); +});