-
Notifications
You must be signed in to change notification settings - Fork 1
Document Holmes weslaw assurance PRDs #535
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
500f89a
docs(holmes): plan weslaw assurance prd slices
flyingrobots 2152a6e
docs(holmes): define law assurance evidence intake prds
flyingrobots 90a7a78
docs(holmes): expand law assurance prd coverage
flyingrobots 527f46a
docs(holmes): resolve assurance planning review issues
flyingrobots 0670b80
docs(holmes): finish law assurance qa and migration prds
flyingrobots 180da82
docs(holmes): close law assurance planning campaign
flyingrobots 06e50e7
docs(bearing): add Holmes implementation slice ledger
flyingrobots dcfa5cf
feat(holmes): add Rust assurance foundation
flyingrobots 1b33fa3
fix(holmes): close assurance review gaps
flyingrobots File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| [package] | ||
| name = "wesley-holmes" | ||
| version = "0.0.5" | ||
| edition = "2021" | ||
| description = "Rust Holmes law assurance foundation for Wesley semantic evidence" | ||
| license = "MIT" | ||
| repository = "https://github.com/flyingrobots/wesley" | ||
| homepage = "https://github.com/flyingrobots/wesley" | ||
| readme = "README.md" | ||
| publish = false | ||
|
|
||
| [dependencies] | ||
| serde = { version = "1.0", features = ["derive"] } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # wesley-holmes | ||
|
|
||
| `wesley-holmes` is the Rust foundation for Holmes law assurance work inside | ||
| Wesley. It consumes Wesley-published law evidence, policy, witness, MCP, and | ||
| GitHub payload artifacts; validates their envelope shape and version posture; | ||
| and prepares deterministic diagnostics and reporting surfaces for later CLI, | ||
| API, and MCP interfaces. | ||
|
|
||
| This crate is intentionally not published yet. It is a workspace implementation | ||
| crate for the Holmes redesign described in the Wesley design packet: | ||
|
|
||
| - [Holmes `weslaw` Assurance PRD/Test Plan](https://github.com/flyingrobots/wesley/blob/main/docs/design/0020-holmes-weslaw-assurance-prd-test-plan/holmes-weslaw-assurance-prd-test-plan.md) | ||
| - [Holmes Assurance Hexagon](https://github.com/flyingrobots/wesley/blob/main/docs/design/0018-holmes-assurance-hexagon/holmes-assurance-hexagon.md) | ||
|
|
||
| ## Boundary | ||
|
|
||
| The crate follows the planned hexagonal boundary: | ||
|
|
||
| - `domain`: pure law-assurance data, diagnostics, evidence models, and version | ||
| rules. Domain code must not import filesystem, network, process, GitHub, MCP, | ||
| or wall-clock dependencies. | ||
| - `application`: deterministic orchestration utilities that bind domain facts | ||
| to ports without owning external side effects. | ||
| - `ports`: abstract clock, artifact, policy, reporting, GitHub, MCP, and command | ||
| I/O traits plus deterministic fakes for tests. | ||
| - `adapters`: future concrete integrations for filesystem, GitHub, MCP, and CLI | ||
| surfaces. | ||
| - `reporting`: future renderer-facing DTOs and report assembly helpers. | ||
|
|
||
| The current slice establishes the foundation only. No public Holmes CLI command | ||
| is exposed from Wesley yet. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| //! Concrete adapter boundary for future filesystem, GitHub, MCP, and CLI integrations. | ||
| //! | ||
| //! The first Holmes implementation slice deliberately leaves this namespace | ||
| //! empty. Concrete adapters will land only after the domain and port contracts | ||
| //! have proven stable. |
108 changes: 108 additions & 0 deletions
108
crates/wesley-holmes/src/application/artifact_locator.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| //! Workspace-relative artifact path resolution. | ||
|
|
||
| use std::path::{Component, Path}; | ||
|
|
||
| use crate::domain::{HolmesDiagnostic, HolmesDiagnosticCode, HolmesResult, HolmesSeverity}; | ||
|
|
||
| /// A normalized artifact path that stays inside the configured workspace root. | ||
| #[derive(Debug, Clone, PartialEq, Eq)] | ||
| pub struct ResolvedArtifactPath { | ||
| /// Workspace-relative path using `/` separators. | ||
| pub workspace_relative: String, | ||
| } | ||
|
|
||
| /// Resolves `weslaw` artifact references without touching the filesystem. | ||
| #[derive(Debug, Clone, PartialEq, Eq)] | ||
| pub struct WeslawArtifactLocator { | ||
| workspace_root: String, | ||
| } | ||
|
|
||
| impl WeslawArtifactLocator { | ||
| /// Create a locator for a workspace root label. | ||
| pub fn new(workspace_root: impl Into<String>) -> Self { | ||
| Self { | ||
| workspace_root: workspace_root.into(), | ||
| } | ||
| } | ||
|
|
||
| /// Return the configured workspace root label. | ||
| pub fn workspace_root(&self) -> &str { | ||
| &self.workspace_root | ||
| } | ||
|
|
||
| /// Normalize a user-authored artifact path relative to the workspace. | ||
| /// | ||
| /// The resolver is lexical by design. It rejects absolute paths, Windows | ||
| /// prefixes, empty paths, and `..` components that would escape the | ||
| /// workspace root. It does not perform symlink or filesystem | ||
| /// canonicalization. | ||
| pub fn resolve(&self, path: &str) -> HolmesResult<ResolvedArtifactPath> { | ||
| if path.trim().is_empty() { | ||
| return Err(invalid_path("artifact path must not be empty")); | ||
| } | ||
|
|
||
| if path.contains('\\') { | ||
| return Err(path_escape("artifact path must use `/` separators")); | ||
| } | ||
|
|
||
| if looks_like_windows_drive_path(path) { | ||
| return Err(path_escape("artifact path must be workspace-relative")); | ||
| } | ||
|
|
||
| let path = Path::new(path); | ||
| if path.is_absolute() { | ||
| return Err(path_escape("artifact path must be workspace-relative")); | ||
| } | ||
|
|
||
| let mut normalized = Vec::new(); | ||
| for component in path.components() { | ||
| match component { | ||
| Component::CurDir => {} | ||
| Component::Normal(segment) => { | ||
| normalized.push(segment.to_string_lossy().into_owned()) | ||
| } | ||
| Component::ParentDir => { | ||
| if normalized.pop().is_none() { | ||
| return Err(path_escape( | ||
| "artifact path must not escape the workspace root", | ||
| )); | ||
| } | ||
| } | ||
| Component::Prefix(_) | Component::RootDir => { | ||
| return Err(path_escape("artifact path must be workspace-relative")); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if normalized.is_empty() { | ||
| return Err(invalid_path("artifact path must reference a file")); | ||
| } | ||
|
|
||
| Ok(ResolvedArtifactPath { | ||
| workspace_relative: normalized.join("/"), | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| fn invalid_path(message: impl Into<String>) -> HolmesDiagnostic { | ||
| HolmesDiagnostic::new( | ||
| HolmesDiagnosticCode::HlawArtifactPathInvalid, | ||
| HolmesSeverity::Error, | ||
| message, | ||
| ) | ||
| .at_field("path") | ||
| } | ||
|
|
||
| fn path_escape(message: impl Into<String>) -> HolmesDiagnostic { | ||
| HolmesDiagnostic::new( | ||
| HolmesDiagnosticCode::HlawArtifactPathEscape, | ||
| HolmesSeverity::Error, | ||
| message, | ||
| ) | ||
| .at_field("path") | ||
| } | ||
|
|
||
| fn looks_like_windows_drive_path(path: &str) -> bool { | ||
| let bytes = path.as_bytes(); | ||
| bytes.len() >= 2 && bytes[0].is_ascii_alphabetic() && bytes[1] == b':' | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| //! Application services for deterministic Holmes law-assurance orchestration. | ||
|
|
||
| mod artifact_locator; | ||
|
|
||
| pub use artifact_locator::{ResolvedArtifactPath, WeslawArtifactLocator}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| //! Deterministic diagnostic envelopes for Holmes law assurance. | ||
|
|
||
| use std::error::Error; | ||
| use std::fmt; | ||
|
|
||
| use serde::{Deserialize, Serialize}; | ||
|
|
||
| /// Stable diagnostic code emitted by Holmes validation and ingest paths. | ||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] | ||
| #[serde(rename_all = "SCREAMING_SNAKE_CASE")] | ||
| pub enum HolmesDiagnosticCode { | ||
| /// A required `schemaVersion` field was absent or blank. | ||
| HlawSchemaVersionMissing, | ||
| /// A `schemaVersion` field was not valid semantic version syntax. | ||
| HlawSchemaVersionMalformed, | ||
| /// A `schemaVersion` major version is not supported by this Holmes build. | ||
| HlawSchemaVersionUnsupportedMajor, | ||
| /// A `schemaVersion` minor version is newer than this Holmes build accepts. | ||
| HlawSchemaVersionUnsupportedMinor, | ||
| /// No local version requirement was configured for an artifact family. | ||
| HlawSchemaVersionRequirementMissing, | ||
| /// An artifact path attempted to escape the workspace root. | ||
| HlawArtifactPathEscape, | ||
| /// An artifact path was malformed before resolution. | ||
| HlawArtifactPathInvalid, | ||
| /// A law evidence bundle was missing a required artifact reference. | ||
| HlawEvidenceBundleInvalid, | ||
| /// A requested artifact was unavailable through its port. | ||
| HlawArtifactUnavailable, | ||
| } | ||
|
|
||
| /// Severity attached to a Holmes diagnostic. | ||
| #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] | ||
| #[serde(rename_all = "SCREAMING_SNAKE_CASE")] | ||
| pub enum HolmesSeverity { | ||
| /// A hard failure that prevents safe continuation. | ||
| Error, | ||
| /// A non-blocking issue that should be visible in reports. | ||
| Warning, | ||
| /// Informational context attached to a report. | ||
| Info, | ||
| } | ||
|
|
||
| /// Structured diagnostic envelope shared by validation and ingest flows. | ||
| #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] | ||
| #[serde(rename_all = "camelCase")] | ||
| pub struct HolmesDiagnostic { | ||
| /// Stable diagnostic code. | ||
| pub code: HolmesDiagnosticCode, | ||
| /// Diagnostic severity. | ||
| pub severity: HolmesSeverity, | ||
| /// Human-readable explanation. | ||
| pub message: String, | ||
| /// Optional artifact family associated with this diagnostic. | ||
| #[serde(skip_serializing_if = "Option::is_none")] | ||
| pub artifact_family: Option<String>, | ||
| /// Optional field path associated with this diagnostic. | ||
| #[serde(skip_serializing_if = "Option::is_none")] | ||
| pub field_path: Option<String>, | ||
| } | ||
|
|
||
| impl HolmesDiagnostic { | ||
| /// Create a new diagnostic envelope. | ||
| pub fn new( | ||
| code: HolmesDiagnosticCode, | ||
| severity: HolmesSeverity, | ||
| message: impl Into<String>, | ||
| ) -> Self { | ||
| Self { | ||
| code, | ||
| severity, | ||
| message: message.into(), | ||
| artifact_family: None, | ||
| field_path: None, | ||
| } | ||
| } | ||
|
|
||
| /// Attach an artifact-family label. | ||
| pub fn for_family(mut self, family: impl Into<String>) -> Self { | ||
| self.artifact_family = Some(family.into()); | ||
| self | ||
| } | ||
|
|
||
| /// Attach a field path. | ||
| pub fn at_field(mut self, field_path: impl Into<String>) -> Self { | ||
| self.field_path = Some(field_path.into()); | ||
| self | ||
| } | ||
| } | ||
|
|
||
| impl fmt::Display for HolmesDiagnostic { | ||
| fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| write!(formatter, "{:?}: {}", self.code, self.message) | ||
| } | ||
| } | ||
|
|
||
| impl Error for HolmesDiagnostic {} | ||
|
|
||
| /// Result alias for Holmes domain and port operations. | ||
| pub type HolmesResult<T> = Result<T, HolmesDiagnostic>; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.