Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Generated package input for the openprose-lint crate. Keep hidden by default
# in GitHub diffs; review the source docs and sync script instead.
crates/openprose-lint/spec-snapshot/** linguist-generated
67 changes: 67 additions & 0 deletions .github/workflows/openprose-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: OpenProse Lint

on:
pull_request:
push:
branches: [main]
workflow_dispatch:

concurrency:
group: openprose-lint-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

permissions:
contents: read

env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: "1"
REACTOR_OFFLINE: "1"

jobs:
lint:
name: OpenProse Lint
runs-on: ubuntu-latest
timeout-minutes: 35

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup pnpm
uses: pnpm/action-setup@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
cache-dependency-path: pnpm-lock.yaml

- name: Setup Rust
run: |
set -euo pipefail
rustup toolchain install 1.96.0 --profile minimal --component rustfmt --component clippy
rustup default 1.96.0
rustc --version
cargo --version

- name: Cache Cargo
uses: Swatinem/rust-cache@v2
with:
workspaces: . -> target

- name: Install system tools
run: |
set -euo pipefail
sudo apt-get update
sudo apt-get install -y jq

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Run deterministic linter gate
run: pnpm lint:prose

- name: Verify crate package dry-run
run: pnpm lint:prose:package
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ node_modules/
**/.turbo/
*.tsbuildinfo

# Rust build output
target/

# Optional true-up generated cache
.true-up/

# Current OpenProse generated state
.agents/prose/.env
.agents/prose/deps/
Expand Down
177 changes: 177 additions & 0 deletions .true-up.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
{
"_comment": "Optional true-up config for advisory drift checks. Commit this config; do not commit the generated .true-up/ cache.",
"facts": {
"crates/openprose-lint/specs/conformance/manifest.json": [
[
"cases",
"id"
]
]
},
"strictSpans": true,
"zones": [
{
"path": "AGENTS.md",
"visibility": "public",
"audience": "maintainer-agents",
"intent": "repo-agent-instructions",
"rules": [
"no-machine-local-paths"
]
},
{
"path": "CONTRIBUTING.md",
"visibility": "public",
"audience": "contributors",
"intent": "contributor-guide",
"rules": [
"no-machine-local-paths"
]
},
{
"path": "CHANGELOG.md",
"visibility": "public",
"audience": "users",
"intent": "release-history",
"rules": [
"no-machine-local-paths"
]
},
{
"path": "RELEASE.md",
"visibility": "public",
"audience": "maintainers",
"intent": "release-process",
"rules": [
"no-machine-local-paths"
]
},
{
"path": "README.md",
"visibility": "public",
"audience": "users",
"intent": "user-overview",
"rules": [
"no-machine-local-paths"
]
},
{
"path": "skills/",
"visibility": "public",
"audience": "agents-and-users",
"intent": "language-and-skill-source",
"rules": [
"no-machine-local-paths"
]
},
{
"path": "crates/openprose-lint/",
"visibility": "public",
"audience": "maintainers-and-integrators",
"intent": "deterministic-linter-crate",
"rules": [
"no-machine-local-paths"
]
},
{
"path": "**/AGENTS.md",
"visibility": "public",
"audience": "maintainer-agents",
"intent": "agent-instructions",
"rules": [
"no-machine-local-paths"
]
},
{
"path": "",
"visibility": "public",
"audience": "world",
"intent": "public-default",
"rules": [
"no-public->private-deps"
]
}
],
"seed": [
{
"from": "CHANGELOG.md",
"to": "Cargo.toml",
"kind": "derives-facts-from"
},
{
"from": "CHANGELOG.md",
"to": ".version-bump.json",
"kind": "derives-facts-from"
},
{
"from": "CHANGELOG.md",
"to": "scripts/lint-prose.sh",
"kind": "derives-facts-from"
},
{
"from": "CONTRIBUTING.md",
"to": "scripts/lint-prose.sh",
"kind": "derives-facts-from"
},
{
"from": "RELEASE.md",
"to": ".version-bump.json",
"kind": "derives-facts-from"
},
{
"from": "RELEASE.md",
"to": "crates/openprose-lint/Cargo.toml",
"kind": "derives-facts-from"
},
{
"from": "crates/openprose-lint/README.md",
"to": "crates/openprose-lint/Cargo.toml",
"kind": "derives-facts-from"
},
{
"from": "crates/openprose-lint/README.md",
"to": "crates/openprose-lint/src/cli.rs#command-surface",
"kind": "derives-facts-from"
},
{
"from": "crates/openprose-lint/README.md",
"to": "crates/openprose-lint/specs/openprose.json",
"kind": "derives-facts-from"
},
{
"from": "crates/openprose-lint/CONTRIBUTING.md",
"to": "scripts/lint-prose.sh",
"kind": "derives-facts-from"
},
{
"from": "crates/openprose-lint/CONTRIBUTING.md",
"to": "crates/openprose-lint/scripts/sync-spec-snapshot.sh",
"kind": "derives-facts-from"
},
{
"from": "crates/openprose-lint/docs/spec-integration.md",
"to": "crates/openprose-lint/specs/openprose.json",
"kind": "derives-facts-from"
},
{
"from": "crates/openprose-lint/docs/spec-integration.md",
"to": "crates/openprose-lint/src/spec_source.rs",
"kind": "derives-facts-from"
},
{
"from": "crates/openprose-lint/docs/spec-integration.md",
"to": "crates/openprose-lint/src/spec_identity.rs",
"kind": "derives-facts-from"
},
{
"from": "crates/openprose-lint/CHANGELOG.md",
"to": "crates/openprose-lint/Cargo.toml",
"kind": "derives-facts-from"
},
{
"from": "package.json",
"to": "scripts/lint-prose.sh",
"kind": "derives-facts-from"
}
]
}
6 changes: 6 additions & 0 deletions .version-bump.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
{ "path": ".codex-plugin/plugin.json", "kind": "json", "field": "version" },
{ "path": "skills/open-prose/SKILL.md", "kind": "yaml", "field": "version" }
]
},
"openprose-lint": {
"description": "The Rust crate that provides deterministic OpenProse linting, conformance fixtures, source identity checks, and LSP diagnostics. This track versions the crate independently from the SKILL/plugin and reactor package trains.",
"files": [
{ "path": "crates/openprose-lint/Cargo.toml", "kind": "toml", "field": "package.version" }
]
}
}
}
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- **`openprose-lint` Rust crate colocated under `crates/openprose-lint/`.**
The repo now has a Cargo workspace, a script-owned deterministic lint gate
(`scripts/lint-prose.sh`), a curated package-local OpenProse spec bundle for
future crates.io distribution, and an independent `openprose-lint` version
track.
- **Optional true-up advisory config.** `.true-up.json` records maintainer drift
relationships for the linter integration while `.true-up/` remains ignored;
`scripts/lint-prose.sh advisory` uses true-up only when it is explicitly
installed or supplied through `TRUE_UP_BIN`.
- **`prose react "<use case>"`** — A command for taking an English standing goal
to a running, inspectable Reactor on the `@openprose/reactor-cli` (`reactor`)
binary. The open-prose skill gains a `reactor.md` operator guide (install, the
Expand Down
27 changes: 27 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Use these when deciding whether a change belongs:
| Company-operation starter contracts | `packages/co/` | Opinionated company-as-prose building blocks |
| Agent-facing routing and activation guidance | `skills/open-prose/SKILL.md`, `AGENTS.md` | Keep globally loaded guidance concise |
| Reactor harness: SDK, `reactor` CLI, replay devtools | `packages/reactor*/` | The deterministic harness that compiles and runs Responsibilities; it does not replace the VM |
| Deterministic linting, LSP diagnostics, source identity, and linter conformance fixtures | `crates/openprose-lint/` | Language changes and lint support should land together; keep policy in repo scripts, not workflow YAML |
| Examples that teach a complete pattern | `skills/open-prose/examples/` | Include enough context for an agent to run or adapt them |
| Public contribution/process guidance | `CONTRIBUTING.md` | Keep it public, practical, and aligned with the repo |

Expand Down Expand Up @@ -117,13 +118,39 @@ again in the future when the behavior regresses.
| Reactor SDK or harness behavior | `pnpm --filter @openprose/reactor test` (offline: `REACTOR_OFFLINE=1`), or the narrow affected Vitest file |
| Skill or doc behavior | `pnpm test:skill` |
| Skill/spec docs | Link/structure checks plus a small scenario showing how an agent should route the command or file |
| Linter behavior or language-surface support | `bash scripts/lint-prose.sh`, or the narrow affected `cargo test -p openprose-lint <test-name>` during iteration |
| `*.prose.md` std/co contracts | Structural check for frontmatter and required sections; add or update a `kind: test` when behavior is executable |
| Examples | Run or dry-run the example in a Prose Complete host when practical; otherwise document the missing host capability |
| Docs-only copy | `git diff --check`, link existence checks, and examples reviewed for current command names |

If no deterministic test exists yet, say that plainly in the PR and either add
the smallest useful test or explain why a future eval is the right follow-up.

The root `pnpm lint` command is the whole-repo gate: it runs Reactor package
linting and the Rust-backed OpenProse linter, so it requires the Node/pnpm and
Rust/Cargo toolchains. For a Reactor-only edit, use `pnpm lint:reactor` during
iteration and state that narrower scope in the PR.

### Optional maintainer drift checks

`bash scripts/lint-prose.sh advisory` runs non-blocking linter discovery output.
If `true-up` is available on `PATH`, or if `TRUE_UP_BIN` points to a true-up
binary, the advisory profile also reports the committed `.true-up.json` drift
policy. This is intentionally optional maintainer tooling, not required
contributor setup.

The `OpenProse Lint` GitHub Actions workflow runs the same repository scripts on
pull requests and `main` pushes. Keep linter policy in `scripts/lint-prose.sh`;
the workflow should stay a thin runner that installs toolchains and invokes the
shared gate.

`bash scripts/lint-prose.sh package` is the crate packaging gate for
`openprose-lint`: it lists the Cargo package contents, runs `cargo publish
--dry-run --allow-dirty`, and verifies `specs verify --spec openprose` from the
packaged source tree. Release commits should additionally pass
`bash scripts/lint-prose.sh release-package`, which requires a clean worktree and
omits `--allow-dirty`.

## PR Description Shape

Use progressive disclosure. Maintainers and agents should understand the change
Expand Down
Loading
Loading