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
4 changes: 4 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ A strong OpenProse PR should:
- Respect the language/framework/harness boundary. Put semantics in the skill
and interpreter docs, reusable contracts in `packages/std/`, and deterministic
harness behavior in `packages/reactor*/`.
- Preserve the data-flow boundary when changing language features. Runtime data
should flow through `### Requires`/`### Maintains`, gateway ingress, function
parameters, or returns; `### Context` is read-only grounding and should not be
used as a hidden payload or wake mechanism.
- Make the library more developer-friendly and agent-friendly at the same time:
clearer for humans to review, easier for agents to execute correctly.
- Add or identify a retestable mechanism. Use existing tests when they cover
Expand Down
2 changes: 2 additions & 0 deletions crates/openprose-lint/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ and this crate follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html

- `crates/openprose-lint/scripts/sync-spec-snapshot.sh` to refresh and check the
curated packaged OpenProse spec bundle.
- Current Contract Markdown support for `### Context`, including strict lint
recognition and `context-boundary` capability reporting.

## [0.2.0]

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
name: context-grounded-summary
kind: responsibility
version: 0.15.0
id: 067NC4KG01RG50R40M30E20918
---

### Context

- `style-guide`: `docs/style-guide.md` at the compiled source revision; read-only
guidance for tone and terminology.

### Maintains

- `summary`: concise current summary matching the declared style guidance.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@
"description": "Resume interrupted runs from artifacts and state.md",
"depends_on": ["file-io", "state-markers"]
},
"context-boundary": {
"layer": "protocol",
"description": "Preserve declared Context sections, avoid treating undeclared ambient context as input, and record bounded launch-context artifacts when child activations are used",
"depends_on": ["subagents", "state-markers"]
},
"secret-hygiene": {
"layer": "policy",
"description": "Verify environment presence without leaking raw secret values into artifacts or logs",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@
"mode": "incidental",
"verification": "unverified",
"notes": "Claude Code has session resume (--continue, --resume flags) which restores conversation context. However, OpenProse resume requires resuming from structured artifacts and state.md markers, which is a different protocol. The substrate supports continuation; the OpenProse-specific semantics are incidental."
},
"context-boundary": {
"mode": "incidental",
"verification": "unverified",
"notes": "Claude Code can use isolated subagents and write files, but raw CLI usage does not deterministically preserve declared OpenProse Context sections, exclude undeclared ambient context, or write bounded launch-context artifacts without an OpenProse adapter."
}
},
"profile_assessment": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@
"mode": "unsupported",
"verification": "self-declared",
"notes": "OpenProse resume from structured artifacts is not implemented in the current Codex host-mediated runner."
},
"context-boundary": {
"mode": "unsupported",
"verification": "self-declared",
"notes": "The current host-mediated runner does not preserve declared Context sections, exclude undeclared ambient context, or write bounded launch-context artifacts for child activations."
}
},
"profile_assessment": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@
"mode": "unsupported",
"verification": "self-declared",
"notes": "OpenProse resume from structured artifacts is not implemented in the current Hermes host-mediated runner."
},
"context-boundary": {
"mode": "unsupported",
"verification": "self-declared",
"notes": "The current host-mediated runner does not preserve declared Context sections, exclude undeclared ambient context, or write bounded launch-context artifacts for child activations."
}
},
"profile_assessment": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@
"resume": {
"mode": "unsupported",
"verification": "self-declared"
},
"context-boundary": {
"mode": "unsupported",
"verification": "self-declared",
"notes": "Bare pi has no OpenProse adapter that preserves declared Context sections or writes bounded launch-context artifacts."
}
},
"profile_assessment": {
Expand Down
40 changes: 40 additions & 0 deletions crates/openprose-lint/src/capabilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ pub struct CapabilityRequirements {
#[serde(rename = "test-evaluation")]
pub test_evaluation: bool,
pub resume: bool,
#[serde(rename = "context-boundary")]
pub context_boundary: bool,
#[serde(rename = "secret-hygiene")]
pub secret_hygiene: bool,
}
Expand Down Expand Up @@ -206,6 +208,11 @@ fn build_report(
let trimmed = line.trim_start().to_ascii_lowercase();
trimmed.starts_with("expects:") || trimmed.starts_with("expects-not:")
}));
let context_boundary = !sections.context.is_empty()
|| source.lines().any(|line| {
let trimmed = line.trim_start().to_ascii_lowercase();
trimmed.starts_with("context:")
});
let delegation = frontmatter.all_keys.contains_key("delegates")
|| source.contains("\nDelegate:")
|| source.starts_with("Delegate:")
Expand Down Expand Up @@ -238,6 +245,7 @@ fn build_report(
test_execution,
test_evaluation,
resume,
context_boundary,
secret_hygiene: environment.required,
};
let provenance = requirement_provenance(schema, &requires)?;
Expand Down Expand Up @@ -404,6 +412,7 @@ fn validate_schema_capabilities(schema: &CapabilitySchema) -> Result<()> {
"test-execution",
"test-evaluation",
"resume",
"context-boundary",
"secret-hygiene",
];

Expand Down Expand Up @@ -509,6 +518,9 @@ fn direct_required_capabilities(requires: &CapabilityRequirements) -> BTreeSet<S
if requires.resume {
caps.insert("resume".to_string());
}
if requires.context_boundary {
caps.insert("context-boundary".to_string());
}
if requires.secret_hygiene {
caps.insert("secret-hygiene".to_string());
}
Expand Down Expand Up @@ -724,6 +736,34 @@ subject: summarizer
assert_eq!(report.program, "test-summarizer");
assert!(report.requires.test_execution);
assert!(report.requires.test_evaluation);
assert!(!report.requires.context_boundary);
assert!(!report.requires.ask_user);
assert!(report.implied_substrate.subagents);
assert!(report.implied_substrate.file_io);
}

#[test]
fn infers_context_boundary_from_context_section() {
let source = r#"---
name: context-grounded-summary
kind: responsibility
version: 0.15.0
id: 067NC4KG01RG50R40M30E20918
---

### Context

- `style-guide`: `docs/style-guide.md` at the compiled source revision

### Maintains

- `summary`: concise current summary matching the style guide
"#;
let report =
capability_report_from_source(Path::new("context-grounded-summary.prose.md"), source)
.unwrap();

assert!(report.requires.context_boundary);
assert!(!report.requires.ask_user);
assert!(report.implied_substrate.subagents);
assert!(report.implied_substrate.file_io);
Expand Down
Loading
Loading