diff --git a/Cargo.lock b/Cargo.lock index 1a97cfd1..1abcd37f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -299,6 +299,7 @@ version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7281235d6e96d3544ca18bba9049be92f4190f8d923e3caef1b5f66cfa752608" dependencies = [ + "camino", "cap-primitives 4.0.2", "io-extras 0.19.0", "io-lifetimes 3.0.1", @@ -1462,11 +1463,10 @@ dependencies = [ [[package]] name = "ortho_config" version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9314c7a4be184287f3f9a66fcbcec054ac215d4975152df86b7aadeae8d5e019" +source = "git+https://github.com/leynos/ortho-config.git?rev=4339a6f3c61dc4fed86493d99ffb05230bee2a1b#4339a6f3c61dc4fed86493d99ffb05230bee2a1b" dependencies = [ "camino", - "cap-std 3.4.5", + "cap-std 4.0.2", "clap", "clap-dispatch", "directories", @@ -1489,8 +1489,7 @@ dependencies = [ [[package]] name = "ortho_config_macros" version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3941ab7c592a0b93aadf12ce30e0ef3d01af87b46c8f363d8157dc33273ba83" +source = "git+https://github.com/leynos/ortho-config.git?rev=4339a6f3c61dc4fed86493d99ffb05230bee2a1b#4339a6f3c61dc4fed86493d99ffb05230bee2a1b" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -3253,6 +3252,17 @@ dependencies = [ "serde", ] +[[package]] +name = "weaver-docs-gate" +version = "0.1.0" +dependencies = [ + "camino", + "cap-std 4.0.2", + "serde", + "thiserror 2.0.18", + "toml 0.9.12+spec-1.1.0", +] + [[package]] name = "weaver-e2e" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 9966f22a..5e6794ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ members = [ "crates/sempai-yaml", "crates/sempai", "crates/weaver-cards", + "crates/weaver-docs-gate", ] resolver = "2" @@ -38,7 +39,7 @@ lru = "0.12" lsp-types = "0.97" mockall = "0.14.0" once_cell = "1.19" -ortho_config = "0.8.0" +ortho_config = { git = "https://github.com/leynos/ortho-config.git", rev = "4339a6f3c61dc4fed86493d99ffb05230bee2a1b" } predicates = "3.1" proptest = "1.5" rstest = "0.26.1" @@ -53,6 +54,7 @@ saphyr = "0.0.6" tempfile = "3.10" thiserror = "2.0" time = { version = "0.3", features = ["formatting"] } +toml = "0.9.12" tracing = "0.1" tree-sitter = "0.25.10" tree-sitter-python = "0.25.0" diff --git a/crates/weaver-docs-gate/Cargo.toml b/crates/weaver-docs-gate/Cargo.toml new file mode 100644 index 00000000..b83081cf --- /dev/null +++ b/crates/weaver-docs-gate/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "weaver-docs-gate" +edition.workspace = true +version.workspace = true +rust-version.workspace = true +publish = false + +[dependencies] +cap-std = { workspace = true } +camino = { workspace = true } +serde = { workspace = true } +thiserror = { workspace = true } +toml = { workspace = true } + +[lints] +workspace = true diff --git a/crates/weaver-docs-gate/examples/render_boundary_matrix.rs b/crates/weaver-docs-gate/examples/render_boundary_matrix.rs new file mode 100644 index 00000000..c439e729 --- /dev/null +++ b/crates/weaver-docs-gate/examples/render_boundary_matrix.rs @@ -0,0 +1,38 @@ +//! Regenerate the `OrthoConfig` consumer boundary matrix. + +use std::env; + +use camino::Utf8Path; +use cap_std::{ambient_authority, fs::Dir}; +use weaver_docs_gate::{load_manifest, render_matrix}; + +fn main() -> Result<(), String> { + let mut args = env::args().skip(1); + let manifest_path = args + .next() + .ok_or_else(|| "usage: render_boundary_matrix ".to_owned())?; + let output_path = args + .next() + .ok_or_else(|| "usage: render_boundary_matrix ".to_owned())?; + + if args.next().is_some() { + return Err("usage: render_boundary_matrix ".to_owned()); + } + + let manifest = + load_manifest(Utf8Path::new(&manifest_path)).map_err(|error| error.to_string())?; + write_output(Utf8Path::new(&output_path), render_matrix(&manifest)) +} + +fn write_output(path: &Utf8Path, content: String) -> Result<(), String> { + let parent = path + .parent() + .ok_or_else(|| format!("invalid output path: {path}"))?; + let file_name = path + .file_name() + .ok_or_else(|| format!("invalid output path: {path}"))?; + let dir = + Dir::open_ambient_dir(parent, ambient_authority()).map_err(|error| error.to_string())?; + dir.write(file_name, content) + .map_err(|error| error.to_string()) +} diff --git a/crates/weaver-docs-gate/src/lib.rs b/crates/weaver-docs-gate/src/lib.rs new file mode 100644 index 00000000..6575f5d8 --- /dev/null +++ b/crates/weaver-docs-gate/src/lib.rs @@ -0,0 +1,234 @@ +//! Tooling for the `OrthoConfig` consumer boundary matrix. + +use std::io::{self, ErrorKind}; + +use camino::{Utf8Path, Utf8PathBuf}; +use cap_std::{ambient_authority, fs::Dir}; +use serde::{Deserialize, Deserializer}; + +mod renderer; +pub use renderer::render_matrix; + +/// One boundary classification state for a Weaver roadmap task. +/// +/// # Examples +/// ``` +/// use weaver_docs_gate::BoundaryState; +/// +/// assert_eq!(BoundaryState::Wraps.as_str(), "wraps"); +/// ``` +#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum BoundaryState { + /// Weaver follows an `OrthoConfig` contract that has shipped. + Consumes, + /// Weaver uses a temporary local adapter with a removal gate. + Wraps, + /// Weaver waits for an upstream contract whose shape is undecided. + Pending, + /// Weaver deliberately keeps a different contract. + Divergent, +} + +impl BoundaryState { + /// Return the manifest spelling for the state. + /// + /// # Examples + /// ``` + /// use weaver_docs_gate::BoundaryState; + /// + /// assert_eq!(BoundaryState::Consumes.as_str(), "consumes"); + /// ``` + #[must_use] + pub const fn as_str(self) -> &'static str { + match self { + Self::Consumes => "consumes", + Self::Wraps => "wraps", + Self::Pending => "pending", + Self::Divergent => "divergent", + } + } +} + +/// The upstream `OrthoConfig` role that a Weaver task consumes or waits for. +/// +/// # Examples +/// ``` +/// use weaver_docs_gate::UpstreamRole; +/// +/// assert_eq!(UpstreamRole::Renderer.as_str(), "renderer"); +/// ``` +#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum UpstreamRole { + /// Consumer-boundary ownership and governance. + Boundary, + /// Recursive command metadata. + Metadata, + /// Capability and provider provenance metadata. + CapabilityProvenance, + /// Canonical command vocabulary. + Vocabulary, + /// Human and machine renderer contracts. + Renderer, + /// Profile parsing, precedence, and redaction. + Profile, + /// Delivery sink contracts. + Delivery, + /// Feedback command contracts. + Feedback, + /// Execution ledger contracts. + ExecutionLedger, +} + +impl UpstreamRole { + /// Return the manifest spelling for the role. + /// + /// # Examples + /// ``` + /// use weaver_docs_gate::UpstreamRole; + /// + /// assert_eq!(UpstreamRole::Boundary.as_str(), "boundary"); + /// ``` + #[must_use] + pub const fn as_str(self) -> &'static str { + match self { + Self::Boundary => "boundary", + Self::Metadata => "metadata", + Self::CapabilityProvenance => "capability_provenance", + Self::Vocabulary => "vocabulary", + Self::Renderer => "renderer", + Self::Profile => "profile", + Self::Delivery => "delivery", + Self::Feedback => "feedback", + Self::ExecutionLedger => "execution_ledger", + } + } +} + +/// A single upstream `OrthoConfig` task reference. +#[derive(Debug, Clone, PartialEq, Eq, Deserialize)] +pub struct UpstreamRef { + /// The upstream roadmap task or stable design section. + pub task: String, + /// The role that upstream reference plays for the Weaver task. + pub role: UpstreamRole, +} + +/// One classified Weaver roadmap task. +#[derive(Debug, Clone, PartialEq, Eq, Deserialize)] +pub struct BoundaryTask { + /// Weaver roadmap task ID, such as `13.1.2`. + pub id: String, + /// One-sentence task summary. + pub gist: String, + /// Boundary classification state. + pub state: BoundaryState, + /// Upstream `OrthoConfig` task references. + pub upstream: Vec, + /// `OrthoConfig` release tag or pinned SHA for shipped contracts. + #[serde(deserialize_with = "empty_string_as_none")] + pub shipped_in: Option, + /// Replacement condition for temporary wrappers. + #[serde(deserialize_with = "empty_string_as_none")] + pub removal_gate: Option, + /// ADR 007 heading slug for deliberate divergences. + #[serde(deserialize_with = "empty_string_as_none")] + pub adr_anchor: Option, + /// ISO-8601 review date for pending contracts. + #[serde(deserialize_with = "empty_string_as_none")] + pub next_review_by: Option, + /// ISO-8601 date when the row was last reviewed. + pub last_reviewed: String, +} + +/// The complete boundary manifest. +#[derive(Debug, Clone, PartialEq, Eq, Deserialize)] +pub struct BoundaryManifest { + /// Manifest schema version. + pub schema_version: u32, + /// Ordered registry of Weaver roadmap task IDs governed by the matrix. + pub managed_tasks: Vec, + /// Classified task rows. + #[serde(rename = "task")] + pub tasks: Vec, +} + +/// Errors returned while loading the boundary manifest. +#[derive(Debug, thiserror::Error)] +pub enum BoundaryError { + /// The manifest path does not exist. + #[error("manifest file not found: {0}")] + NotFound(Utf8PathBuf), + /// The manifest path cannot be opened through a parent directory handle. + #[error("invalid manifest path: {0}")] + InvalidPath(Utf8PathBuf), + /// The file could not be read. + #[error("manifest file could not be read: {path}: {source}")] + Read { + /// Manifest path. + path: Utf8PathBuf, + /// Underlying I/O error. + source: Box, + }, + /// The file is not valid TOML for the boundary schema. + #[error("invalid TOML in {path}: {source}")] + InvalidToml { + /// Manifest path. + path: Utf8PathBuf, + /// TOML parse error. + source: Box, + }, +} + +/// Load the boundary manifest from disk. +/// +/// # Errors +/// +/// Returns [`BoundaryError`] when the manifest is missing, unreadable, or not +/// valid TOML for the boundary schema. +/// +/// # Examples +/// ```no_run +/// use camino::Utf8Path; +/// use weaver_docs_gate::load_manifest; +/// +/// let manifest = load_manifest(Utf8Path::new("docs/orthoconfig-consumer-boundary.toml"))?; +/// assert_eq!(manifest.schema_version, 1); +/// # Ok::<(), weaver_docs_gate::BoundaryError>(()) +/// ``` +pub fn load_manifest(path: &Utf8Path) -> Result { + let parent = path.parent().unwrap_or_else(|| Utf8Path::new(".")); + let file_name = path + .file_name() + .ok_or_else(|| BoundaryError::InvalidPath(path.to_path_buf()))?; + let dir = Dir::open_ambient_dir(parent, ambient_authority()) + .map_err(|source| read_error(path, source))?; + + let contents = dir + .read_to_string(file_name) + .map_err(|source| read_error(path, source))?; + toml::from_str(&contents).map_err(|source| BoundaryError::InvalidToml { + path: path.to_path_buf(), + source: Box::new(source), + }) +} + +fn read_error(path: &Utf8Path, source: io::Error) -> BoundaryError { + if source.kind() == ErrorKind::NotFound { + BoundaryError::NotFound(path.to_path_buf()) + } else { + BoundaryError::Read { + path: path.to_path_buf(), + source: Box::new(source), + } + } +} + +fn empty_string_as_none<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let value = String::deserialize(deserializer)?; + Ok((!value.is_empty()).then_some(value)) +} diff --git a/crates/weaver-docs-gate/src/renderer.rs b/crates/weaver-docs-gate/src/renderer.rs new file mode 100644 index 00000000..6eab7f11 --- /dev/null +++ b/crates/weaver-docs-gate/src/renderer.rs @@ -0,0 +1,281 @@ +//! Markdown rendering for the `OrthoConfig` consumer boundary matrix. + +use crate::{BoundaryManifest, BoundaryState, BoundaryTask}; + +const NA: &str = "n/a"; + +struct MatrixRow { + roadmap_task: String, + gist: String, + state: String, + upstream: String, + shipped_in: String, + gate_or_divergence: String, + next_review_by: String, + last_reviewed: String, +} + +struct ColumnWidths { + roadmap_task: usize, + gist: usize, + state: usize, + upstream: usize, + shipped_in: usize, + gate_or_divergence: usize, + next_review_by: usize, + last_reviewed: usize, +} + +impl ColumnWidths { + fn for_rows(rows: &[MatrixRow]) -> Self { + let mut widths = Self::headers(); + for row in rows { + widths.include(row); + } + widths + } + + const fn headers() -> Self { + Self { + roadmap_task: 12, + gist: 4, + state: 5, + upstream: 25, + shipped_in: 10, + gate_or_divergence: 26, + next_review_by: 14, + last_reviewed: 13, + } + } + + fn include(&mut self, row: &MatrixRow) { + self.roadmap_task = self.roadmap_task.max(cell_width(&row.roadmap_task)); + self.gist = self.gist.max(cell_width(&row.gist)); + self.state = self.state.max(cell_width(&row.state)); + self.upstream = self.upstream.max(cell_width(&row.upstream)); + self.shipped_in = self.shipped_in.max(cell_width(&row.shipped_in)); + self.gate_or_divergence = self + .gate_or_divergence + .max(cell_width(&row.gate_or_divergence)); + self.next_review_by = self.next_review_by.max(cell_width(&row.next_review_by)); + self.last_reviewed = self.last_reviewed.max(cell_width(&row.last_reviewed)); + } +} + +/// Render the human-readable boundary matrix from the manifest. +/// +/// # Examples +/// ``` +/// use weaver_docs_gate::{BoundaryManifest, BoundaryState, BoundaryTask, render_matrix}; +/// +/// let manifest = BoundaryManifest { +/// schema_version: 1, +/// managed_tasks: vec!["12.1.1".into()], +/// tasks: vec![BoundaryTask { +/// id: "12.1.1".into(), +/// gist: "Track the downstream consumer boundary.".into(), +/// state: BoundaryState::Consumes, +/// upstream: Vec::new(), +/// shipped_in: Some("4339a6f3".into()), +/// removal_gate: None, +/// adr_anchor: None, +/// next_review_by: None, +/// last_reviewed: "2026-06-14".into(), +/// }], +/// }; +/// +/// assert!(render_matrix(&manifest).contains("12.1.1")); +/// ``` +#[must_use] +pub fn render_matrix(manifest: &BoundaryManifest) -> String { + let mut rendered = String::from(concat!( + "# OrthoConfig consumer boundary\n\n", + "\n\n", + "This matrix is generated from ", + "`docs/orthoconfig-consumer-boundary.toml`. Do not\n", + "edit the table by hand; update the manifest and regenerate it with\n", + "`cargo run -p weaver-docs-gate --example render_boundary_matrix -- ", + "docs/orthoconfig-consumer-boundary.toml ", + "docs/orthoconfig-consumer-boundary.md`.\n\n", + "The matrix tracks every live Weaver command-contract roadmap task ", + "that consumes\n", + "OrthoConfig, wraps it temporarily, waits on upstream shape, or ", + "deliberately\n", + "diverges under ADR 007.\n\n", + )); + + for phase in grouped_phases(manifest) { + push_phase(&mut rendered, phase, manifest); + } + + while rendered.ends_with("\n\n") { + rendered.pop(); + } + rendered.push_str("\n"); + + rendered +} + +fn grouped_phases(manifest: &BoundaryManifest) -> Vec<&str> { + let mut phases = Vec::new(); + for task in &manifest.tasks { + let phase = task.id.split('.').next().unwrap_or_default(); + if !phases.contains(&phase) { + phases.push(phase); + } + } + phases +} + +fn push_phase(rendered: &mut String, phase: &str, manifest: &BoundaryManifest) { + let rows = manifest + .tasks + .iter() + .filter(|task| task.id.starts_with(phase)) + .map(MatrixRow::from) + .collect::>(); + let widths = ColumnWidths::for_rows(&rows); + + rendered.push_str("## Phase "); + rendered.push_str(phase); + rendered.push_str("\n\n"); + push_header(rendered, &widths); + push_separator(rendered, &widths); + for row in &rows { + push_row(rendered, row, &widths); + } + rendered.push('\n'); +} + +fn push_header(rendered: &mut String, widths: &ColumnWidths) { + push_cells( + rendered, + widths, + &MatrixRow { + roadmap_task: "Roadmap task".into(), + gist: "Gist".into(), + state: "State".into(), + upstream: "Upstream OrthoConfig task".into(), + shipped_in: "Shipped in".into(), + gate_or_divergence: "Removal gate or divergence".into(), + next_review_by: "Next review by".into(), + last_reviewed: "Last reviewed".into(), + }, + ); +} + +fn push_separator(rendered: &mut String, widths: &ColumnWidths) { + push_cells( + rendered, + widths, + &MatrixRow { + roadmap_task: "-".repeat(widths.roadmap_task), + gist: "-".repeat(widths.gist), + state: "-".repeat(widths.state), + upstream: "-".repeat(widths.upstream), + shipped_in: "-".repeat(widths.shipped_in), + gate_or_divergence: "-".repeat(widths.gate_or_divergence), + next_review_by: "-".repeat(widths.next_review_by), + last_reviewed: "-".repeat(widths.last_reviewed), + }, + ); +} + +fn push_row(rendered: &mut String, row: &MatrixRow, widths: &ColumnWidths) { + push_cells(rendered, widths, row); +} + +fn push_cells(rendered: &mut String, widths: &ColumnWidths, row: &MatrixRow) { + rendered.push_str("| "); + rendered.push_str(&padded(&row.roadmap_task, widths.roadmap_task)); + rendered.push_str(" | "); + rendered.push_str(&padded(&row.gist, widths.gist)); + rendered.push_str(" | "); + rendered.push_str(&padded(&row.state, widths.state)); + rendered.push_str(" | "); + rendered.push_str(&padded(&row.upstream, widths.upstream)); + rendered.push_str(" | "); + rendered.push_str(&padded(&row.shipped_in, widths.shipped_in)); + rendered.push_str(" | "); + rendered.push_str(&padded(&row.gate_or_divergence, widths.gate_or_divergence)); + rendered.push_str(" | "); + rendered.push_str(&padded(&row.next_review_by, widths.next_review_by)); + rendered.push_str(" | "); + rendered.push_str(&padded(&row.last_reviewed, widths.last_reviewed)); + rendered.push_str(" |\n"); +} + +impl From<&BoundaryTask> for MatrixRow { + fn from(task: &BoundaryTask) -> Self { + Self { + roadmap_task: format!("[{}]({})", escape_cell(&task.id), roadmap_anchor(&task.id)), + gist: escape_cell(&task.gist), + state: state_label(task.state).into(), + upstream: upstream_tasks(task), + shipped_in: optional_cell(task.shipped_in.as_deref()), + gate_or_divergence: gate_or_divergence(task), + next_review_by: optional_cell(task.next_review_by.as_deref()), + last_reviewed: escape_cell(&task.last_reviewed), + } + } +} + +fn upstream_tasks(task: &BoundaryTask) -> String { + let upstream = task + .upstream + .iter() + .map(|reference| reference.task.as_str()) + .collect::>() + .join(", "); + optional_cell(Some(&upstream)) +} + +fn gate_or_divergence(task: &BoundaryTask) -> String { + if let Some(gate) = task.removal_gate.as_deref() { + return escape_cell(gate); + } + + task.adr_anchor.as_deref().map_or_else( + || NA.into(), + |anchor| format!("[ADR 007](adr-007-agent-native-command-surface.md#{anchor})"), + ) +} + +fn optional_cell(value: Option<&str>) -> String { + value + .filter(|inner| !inner.is_empty()) + .map_or_else(|| NA.into(), escape_cell) +} + +const fn state_label(state: BoundaryState) -> &'static str { + match state { + BoundaryState::Consumes => "✓ consumes", + BoundaryState::Wraps => "~ wraps", + BoundaryState::Pending => "? pending", + BoundaryState::Divergent => "× divergent", + } +} + +fn roadmap_anchor(task_id: &str) -> &'static str { + match task_id.split('.').next().unwrap_or_default() { + "12" => "roadmap.md#121-confirm-reusable-contracts-that-weaver-must-not-duplicate", + "13" => "roadmap.md#13-command-contract-proving-slice", + "14" => "roadmap.md#14-code-reading-loop-slice", + "15" => "roadmap.md#15-sempai-selector-to-context-slice", + "16" => "roadmap.md#16-safe-change-loop-slice", + "17" => "roadmap.md#17-impact-and-history-slice", + "18" => "roadmap.md#18-provider-ecosystem-slice", + "19" => "roadmap.md#19-agent-workflow-and-assurance-slice", + "20" => "roadmap.md#20-deferred-extensions-after-the-core-product-promise", + _ => "roadmap.md", + } +} + +fn escape_cell(value: &str) -> String { value.replace('|', "\\|").replace('\n', "
") } + +fn padded(value: &str, width: usize) -> String { + let padding = width.saturating_sub(cell_width(value)); + format!("{value}{}", " ".repeat(padding)) +} + +fn cell_width(value: &str) -> usize { value.chars().count() } diff --git a/crates/weaver-docs-gate/tests/boundary_manifest.rs b/crates/weaver-docs-gate/tests/boundary_manifest.rs new file mode 100644 index 00000000..271e727f --- /dev/null +++ b/crates/weaver-docs-gate/tests/boundary_manifest.rs @@ -0,0 +1,321 @@ +//! Integration tests for the `OrthoConfig` consumer boundary manifest. + +use std::collections::BTreeSet; + +use camino::{Utf8Path, Utf8PathBuf}; +use cap_std::{ambient_authority, fs::Dir}; +use weaver_docs_gate::{ + BoundaryManifest, + BoundaryState, + BoundaryTask, + load_manifest, + render_matrix, +}; + +const ADR_007: &str = "docs/adr-007-agent-native-command-surface.md"; +const MANIFEST: &str = "docs/orthoconfig-consumer-boundary.toml"; +const MATRIX: &str = "docs/orthoconfig-consumer-boundary.md"; +const ROADMAP: &str = "docs/roadmap.md"; + +type TestResult = Result; + +#[test] +fn manifest_registry_matches_rows_and_roadmap_tasks() -> TestResult { + let manifest = manifest().map_err(|error| format!("load boundary manifest: {error}"))?; + let row_ids = manifest + .tasks + .iter() + .map(|task| task.id.as_str()) + .collect::>(); + let managed_ids = manifest + .managed_tasks + .iter() + .map(String::as_str) + .collect::>(); + + ensure_equal(&managed_ids, &row_ids, "managed_tasks must match task rows")?; + if let Some(dup) = first_duplicate(&managed_ids) { + return Err(format!("managed_tasks contains duplicate value {dup}")); + } + + let roadmap = + read_doc(Utf8Path::new(ROADMAP)).map_err(|error| format!("read {ROADMAP}: {error}"))?; + let roadmap_ids = roadmap_task_ids(&roadmap); + for task_id in managed_ids { + ensure( + roadmap_ids.contains(task_id), + format!("manifest task {task_id} is missing from {ROADMAP}"), + )?; + } + + Ok(()) +} + +#[test] +fn boundary_state_rows_have_required_evidence() -> TestResult { + let manifest = manifest().map_err(|error| format!("load boundary manifest: {error}"))?; + + for task in &manifest.tasks { + validate_date(&task.last_reviewed, DateField::LastReviewed, task)?; + ensure( + !task.upstream.is_empty(), + format!("task {} must name at least one upstream reference", task.id), + )?; + + match task.state { + BoundaryState::Consumes => validate_consumes_evidence(task), + BoundaryState::Wraps => validate_wraps_evidence(task), + BoundaryState::Pending => validate_pending_evidence(task), + BoundaryState::Divergent => validate_divergence_evidence(task), + }?; + } + + Ok(()) +} + +#[test] +fn divergent_rows_reference_existing_adr_007_anchors() -> TestResult { + let manifest = manifest().map_err(|error| format!("load boundary manifest: {error}"))?; + let adr = + read_doc(Utf8Path::new(ADR_007)).map_err(|error| format!("read {ADR_007}: {error}"))?; + let anchors = heading_anchors(&adr); + + for task in manifest + .tasks + .iter() + .filter(|task| task.state == BoundaryState::Divergent) + { + let anchor = task + .adr_anchor + .as_deref() + .ok_or_else(|| format!("divergent task {} has no ADR anchor", task.id))?; + ensure( + anchors.contains(anchor), + format!( + "task {} references missing ADR 007 anchor {anchor}", + task.id + ), + )?; + } + + Ok(()) +} + +#[test] +fn committed_matrix_matches_manifest_rendering() -> TestResult { + let manifest = manifest().map_err(|error| format!("load boundary manifest: {error}"))?; + let expected = render_matrix(&manifest); + let actual = + read_doc(Utf8Path::new(MATRIX)).map_err(|error| format!("read {MATRIX}: {error}"))?; + + ensure_equal( + &expected, + &actual, + format!("{MATRIX} is not generated from {MANIFEST}"), + ) +} + +fn manifest() -> TestResult { + load_manifest(&repo_path(Utf8Path::new(MANIFEST))?).map_err(|error| error.to_string()) +} + +fn read_doc(doc_path: &Utf8Path) -> TestResult { + let resolved_path = repo_path(doc_path)?; + let parent = resolved_path.parent().unwrap_or_else(|| Utf8Path::new(".")); + let file_name = resolved_path + .file_name() + .ok_or_else(|| format!("invalid doc path: {resolved_path}"))?; + let dir = Dir::open_ambient_dir(parent, ambient_authority()) + .map_err(|error| format!("open {parent}: {error}"))?; + dir.read_to_string(file_name) + .map_err(|error| format!("read {resolved_path}: {error}")) +} + +fn repo_path(path: &Utf8Path) -> TestResult { + let crate_dir = Utf8Path::new(env!("CARGO_MANIFEST_DIR")); + let repo_root = crate_dir + .parent() + .and_then(Utf8Path::parent) + .ok_or_else(|| format!("cannot resolve repository root from {crate_dir}"))?; + Ok(repo_root.join(path)) +} + +fn roadmap_task_ids(roadmap: &str) -> BTreeSet<&str> { + roadmap + .lines() + .filter_map(|line| line.trim_start().split_once("] ").map(|(_, task)| task)) + .filter_map(|task| task.split_once(". ").map(|(task_id, _)| task_id)) + .filter(|task_id| { + task_id + .chars() + .all(|char| char.is_ascii_digit() || char == '.') + }) + .collect() +} + +fn heading_anchors(document: &str) -> BTreeSet { + document + .lines() + .filter_map(|line| line.trim_start().strip_prefix("## ")) + .map(markdown_anchor) + .collect() +} + +fn markdown_anchor(heading: &str) -> String { + let mut anchor = String::new(); + let mut previous_was_dash = false; + + for char in heading.chars().flat_map(char::to_lowercase) { + if char.is_ascii_alphanumeric() { + anchor.push(char); + previous_was_dash = false; + } else if char.is_whitespace() || char == '-' { + push_dash(&mut anchor, &mut previous_was_dash); + } + } + + anchor.trim_matches('-').to_owned() +} + +fn push_dash(anchor: &mut String, previous_was_dash: &mut bool) { + if !*previous_was_dash && !anchor.is_empty() { + anchor.push('-'); + *previous_was_dash = true; + } +} + +fn ensure(condition: bool, message: String) -> TestResult { + if condition { Ok(()) } else { Err(message) } +} + +fn ensure_equal(left: &T, right: &T, message: impl Into) -> TestResult +where + T: std::fmt::Debug + PartialEq, +{ + if left == right { + Ok(()) + } else { + Err(format!( + "{}\nleft: {left:?}\nright: {right:?}", + message.into() + )) + } +} + +fn first_duplicate<'a>(values: &[&'a str]) -> Option<&'a str> { + let mut seen = BTreeSet::new(); + values.iter().find(|&&v| !seen.insert(v)).copied() +} + +fn validate_consumes_evidence(task: &BoundaryTask) -> TestResult { + ensure( + task.shipped_in.is_some(), + format!("consumes task {} must name shipped_in", task.id), + )?; + ensure( + task.removal_gate.is_none(), + format!("consumes task {} must not carry removal_gate", task.id), + )?; + ensure( + task.adr_anchor.is_none(), + format!("consumes task {} must not carry adr_anchor", task.id), + )?; + ensure( + task.next_review_by.is_none(), + format!("consumes task {} must not carry next_review_by", task.id), + ) +} + +fn validate_wraps_evidence(task: &BoundaryTask) -> TestResult { + ensure( + task.removal_gate.is_some(), + format!("wraps task {} must name a removal gate", task.id), + )?; + ensure( + task.shipped_in.is_none(), + format!("wraps task {} must not carry shipped_in", task.id), + )?; + ensure( + task.adr_anchor.is_none(), + format!("wraps task {} must not carry adr_anchor", task.id), + )?; + ensure( + task.next_review_by.is_none(), + format!("wraps task {} must not carry next_review_by", task.id), + ) +} + +fn validate_pending_evidence(task: &BoundaryTask) -> TestResult { + let next_review_by = task + .next_review_by + .as_deref() + .ok_or_else(|| format!("pending task {} must provide next_review_by", task.id))?; + validate_date(next_review_by, DateField::NextReviewBy, task)?; + ensure( + task.shipped_in.is_none(), + format!("pending task {} must not carry shipped_in", task.id), + )?; + ensure( + task.removal_gate.is_none(), + format!("pending task {} must not carry removal_gate", task.id), + )?; + ensure( + task.adr_anchor.is_none(), + format!("pending task {} must not carry adr_anchor", task.id), + ) +} + +fn validate_divergence_evidence(task: &BoundaryTask) -> TestResult { + ensure( + task.adr_anchor.is_some(), + format!("divergent task {} must name an ADR 007 anchor", task.id), + )?; + ensure( + task.shipped_in.is_none(), + format!("divergent task {} must not carry shipped_in", task.id), + )?; + ensure( + task.removal_gate.is_none(), + format!("divergent task {} must not carry removal_gate", task.id), + )?; + ensure( + task.next_review_by.is_none(), + format!("divergent task {} must not carry next_review_by", task.id), + ) +} + +/// Date fields that carry an ISO-8601 date and are validated by [`validate_date`]. +#[derive(Clone, Copy)] +enum DateField { + LastReviewed, + NextReviewBy, +} + +impl DateField { + const fn as_str(self) -> &'static str { + match self { + Self::LastReviewed => "last_reviewed", + Self::NextReviewBy => "next_review_by", + } + } +} + +fn validate_date(value: &str, field: DateField, task: &BoundaryTask) -> TestResult { + let field = field.as_str(); + ensure( + is_iso_date(value), + format!("task {} has invalid {field} date {value:?}", task.id), + +} + +fn is_iso_date(value: &str) -> bool { + value.len() == 10 + && value + .chars() + .enumerate() + .all(|(index, char)| matches!(index, 4 | 7) == (char == '-')) + && value + .chars() + .filter(|char| *char != '-') + .all(|char| char.is_ascii_digit()) +} diff --git a/docs/adr-007-agent-native-command-surface.md b/docs/adr-007-agent-native-command-surface.md index 62f98838..732f56c2 100644 --- a/docs/adr-007-agent-native-command-surface.md +++ b/docs/adr-007-agent-native-command-surface.md @@ -146,6 +146,50 @@ Any local helper that survives after those OrthoConfig tasks are available must record a permanent divergence in this ADR before it can remain in the implementation. +## Boundary classification + +Every live roadmap task that touches the command contract must be classified in +the OrthoConfig consumer boundary matrix at +[`docs/orthoconfig-consumer-boundary.md`](orthoconfig-consumer-boundary.md). +The machine-readable source of truth is +[`docs/orthoconfig-consumer-boundary.toml`](orthoconfig-consumer-boundary.toml). +The matrix complements the dependency table and removal policy above; it does +not replace either one. + +The matrix uses these columns: + +- `Roadmap task` links to the Weaver roadmap task being classified. +- `Gist` summarizes the task in one reviewable sentence. +- `State` is one of `consumes`, `wraps`, `pending`, or `divergent`. +- `Upstream OrthoConfig task` names the upstream task IDs the Weaver task + depends on. +- `Shipped in` names the OrthoConfig release tag or pinned commit SHA that + landed the contract for `consumes` rows. +- `Removal gate or divergence` records either the replacement condition for a + temporary wrapper or the ADR 007 section that owns a deliberate divergence. +- `Next review by` records the next review date for unresolved upstream + contracts. +- `Last reviewed` records the last date the row was checked. + +The four boundary states have fixed evidence requirements: + +- `consumes` means Weaver follows an OrthoConfig contract that has already + shipped. The row must name the upstream task and the OrthoConfig release tag + or pinned commit SHA in `Shipped in`. +- `wraps` means Weaver keeps a narrow temporary adapter while waiting for an + upstream contract whose shape is already committed. The row must name the + upstream task and the removal gate. +- `pending` means Weaver depends on an upstream contract whose shape has not + yet been decided. The row must name the upstream task and a `Next review by` + date. This state exists so `wraps` remains reserved for contracts whose + upstream shape is already committed. +- `divergent` means Weaver deliberately keeps a different contract. The row + must point to the ADR 007 section that explains the divergence. + +The matrix may display the states with symbols for scanning, but the textual +state is the contract. Reviewers should treat the TOML row as the authority and +the Markdown matrix as generated documentation. + ## Human renderer contract The default renderer is for humans. It emits localized, readable output with diff --git a/docs/contents.md b/docs/contents.md index 80e04d1f..47009f69 100644 --- a/docs/contents.md +++ b/docs/contents.md @@ -32,6 +32,10 @@ readers can find the source of truth without scanning the whole tree. surface](adr-007-agent-native-command-surface.md) - Decision record for the human-friendly, agent-native 0.1.0 command contract and OrthoConfig dependency boundary. +- [OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md) + - Generated matrix classifying every command-contract roadmap task as an + OrthoConfig consumer, temporary wrapper, pending dependency, or deliberate + divergence. - [Archived prototype roadmap](archive/prototype-roadmap.md) - Historical completed and superseded roadmap tasks from the pre-ADR-007 command grammar, preserving task numbers `1` through `11`. diff --git a/docs/developers-guide.md b/docs/developers-guide.md index 08e9870d..cc05c015 100644 --- a/docs/developers-guide.md +++ b/docs/developers-guide.md @@ -16,6 +16,23 @@ from OrthoConfig-backed command metadata plus Weaver-owned semantic adapters. Do not add new public command grammar by hand in `clap`, daemon routing, manual pages, help text, and docs independently. +The [OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md) is +the source of truth for command-contract roadmap tasks. Before adding, +renaming, or reclassifying a public command task, update +`docs/orthoconfig-consumer-boundary.toml` and regenerate +`docs/orthoconfig-consumer-boundary.md` with: + +```sh +cargo run -p weaver-docs-gate --example render_boundary_matrix -- \ + docs/orthoconfig-consumer-boundary.toml docs/orthoconfig-consumer-boundary.md +``` + +Use `consumes` only when the upstream OrthoConfig contract has shipped and the +row can name the release or pinned SHA in `shipped_in`. Use `wraps` for a +temporary Weaver adapter with a concrete removal gate, `pending` for an +upstream contract that is not decided or shipped yet, and `divergent` only when +ADR 007 records the deliberate Weaver-owned divergence. + When adding or renaming a public command: 1. Update the OrthoConfig-backed command metadata or the Weaver semantic diff --git a/docs/execplans/12-1-1-track-downstream-consumer-boundary.md b/docs/execplans/12-1-1-track-downstream-consumer-boundary.md new file mode 100644 index 00000000..36609e74 --- /dev/null +++ b/docs/execplans/12-1-1-track-downstream-consumer-boundary.md @@ -0,0 +1,1108 @@ +# Track the downstream consumer boundary (roadmap 12.1.1) + +This ExecPlan (execution plan) is a living document. The sections +`Constraints`, `Tolerances`, `Risks`, `Progress`, `Surprises & Discoveries`, +`Decision Log`, and `Outcomes & Retrospective` must be kept up to date as work +proceeds. + +Status: IN PROGRESS + +This document must be maintained in accordance with `AGENTS.md` at the +repository root. + +## Purpose / big picture + +Weaver consumes generic command-contract machinery from OrthoConfig and owns +only Weaver-specific semantic code-edit metadata (capabilities, routing, +selectors, safety). Today that split is captured in two places: the OrthoConfig +dependency table and the temporary-adapter removal policy in +`docs/adr-007-agent-native-command-surface.md`. Neither place can answer the +question "for every command-contract task in the live Weaver roadmap, what is +its relationship to OrthoConfig?" — there is no single matrix, no machine +check, and no fixed vocabulary. + +Roadmap item 12.1.1 closes that gap. The success criterion in +`docs/roadmap.md` line 46 is: + +> Success: every command-contract task says whether it consumes OrthoConfig, +> wraps it temporarily, or records a deliberate divergence in ADR 007. + +After this change a contributor can open the roadmap, follow a back-link to a +single boundary matrix, and read for every command-contract task: the +classification state (`consumes`, `wraps`, or `divergent`), the upstream +OrthoConfig task it pairs with, and either the removal gate or the ADR 007 +divergence section that governs it. A test in the workspace fails when a new +command-contract task lands without a matrix entry, when a matrix entry +references a missing roadmap task, when a `wraps` entry has no removal gate, or +when a `divergent` entry has no ADR 007 anchor. + +Observable behaviour after this change: + +- `docs/orthoconfig-consumer-boundary.md` exists and lists every Weaver + command-contract task with its classification state and upstream pairing. +- `docs/adr-007-agent-native-command-surface.md` defines the three states in a + dedicated "Boundary classification" section and back-links to the matrix. +- `docs/roadmap.md` carries an inline back-link near each command-contract task + group to the matrix entry. +- `docs/developers-guide.md` documents the workflow for adding a new + command-contract task and updating the matrix. +- `docs/users-guide.md` notes the temporary divergences that users may see + while OrthoConfig contracts ship. +- `cargo test --workspace` exercises a new dedicated + `crates/weaver-docs-gate` integration test that parses the boundary + manifest (`docs/orthoconfig-consumer-boundary.toml`), the roadmap, and + the boundary matrix and asserts referential integrity. +- `make check-fmt && make lint && make test && make markdownlint && make nixie` + all pass. + +Downstream tasks 12.1.2 through 12.1.5 and every subsequent command-contract +task can record their boundary classification in one place instead of +reinventing the ADR cross-reference. + +## Why this matters now + +Phase 12 is the unavoidable foundation that prevents every later slice from +re-asking the same dependency question. Without a classification mechanism, +each command-contract task in phases 13 through 19 has to argue from first +principles whether the surface belongs upstream. With one, each task either +points at the matrix entry it inherits or proposes a single delta to it. + +The work is documentation-led, but the test gate is not optional. Without it +the matrix decays the moment a roadmap task is added or renamed and the +boundary becomes review-only again. + +## Constraints + +1. **OrthoConfig 5.2.3 may not have shipped.** The roadmap notes the + dependency, but 5.2.3 itself is documentation-only and can be tracked + independently. The matrix must rely on already-published OrthoConfig + decisions (the OrthoConfig `§2.1` consumer-boundary statement and + OrthoConfig ADR-003 schema ownership) rather than the unshipped bullets of + 5.2.3. The matrix is forward-compatible with 5.2.3 once it lands. +2. **No new runtime crate dependencies.** Documentation and tests use crates + already in the workspace (`camino`, `serde`, `toml`, `rstest`, + `pretty_assertions`, `googletest`). The test must compile under + `--workspace --all-targets --all-features`. No new workspace member adds + a runtime binary; `crates/weaver-docs-gate` exists only to host the + integration test and the small manifest parser it shares with itself. +3. **Do not duplicate the OrthoConfig roadmap.** Each matrix row references an + OrthoConfig task ID, not its content. If OrthoConfig renames a task, the + matrix needs a one-line update, not a re-derivation. +4. **No new commands, schemas, or runtime crates.** This task does not extend + `crates/weaver-cli/src/command_surface.rs` types nor introduce a new + adapter. Its job is to classify, not to refactor. +5. **No removal of ADR 007 content.** The existing OrthoConfig dependency + table and temporary-adapter removal policy stay where they are. The new + "Boundary classification" section sits alongside them and the matrix doc + references both. +6. **400-line file limit.** Every Rust source file added or modified must + stay below 400 lines. The matrix Markdown is exempt by repository policy + for prose, but the manifest TOML should remain well below that limit by + design. +7. **en-GB Oxford spelling.** All new prose follows `en-GB-oxendict` + conventions and `docs/documentation-style-guide.md`. +8. **No prototype command grammar reintroduction.** The matrix references + resource-first commands only. Prototype `observe`, `act`, `verify`, + provider-first commands, and root `--output` remain archive provenance. +9. **Stable task IDs.** The manifest keys roadmap task IDs as strings + (`"12.1.2"`). Roadmap renumbering is out of scope; ID stability is + asserted by the test gate. +10. **Strict Clippy.** New code must compile under + `cargo clippy --workspace --all-targets --all-features -- -D warnings`. + +## Tolerances (exception triggers) + +- **Scope.** If implementation modifies more than twelve documentation + files or six Rust source files (excluding the new + `crates/weaver-docs-gate` member's `Cargo.toml`, `src/lib.rs`, + `examples/render_boundary_matrix.rs`, and the test file), stop and + escalate. The new workspace member is expected; growth beyond it is + not. +- **Roadmap renames.** If classifying the existing tasks requires renumbering + a roadmap entry or moving a task between phases, stop and escalate. +- **ADR 007 rewrites.** If the boundary classification cannot fit alongside + the existing OrthoConfig dependency table and temporary-adapter removal + policy without rewriting either, stop and escalate. +- **Dependencies.** If the test gate requires a new external crate + dependency, stop and escalate. +- **Divergent classifications.** If two or more command-contract tasks must + be classified `divergent` without an existing ADR 007 anchor, stop and + open a follow-up ADR-007 amendment before continuing. +- **Iterations.** If the test gate fails after three attempts at adjustment, + stop and escalate. +- **Time.** If any single stage (A through E) takes more than four working + hours of focused effort, stop, record progress, and escalate. + +## Risks + +- Risk: OrthoConfig renumbers a roadmap task and the matrix points at a stale + ID. Severity: medium. Likelihood: medium. Mitigation: store the OrthoConfig + task ID plus a short stable phrase (for example, + `"5.2.3 — Record consumer dependency boundaries"`). The developers' guide + documents a quarterly cross-repo reconciliation step that compares the + manifest phrases against the OrthoConfig roadmap when that repository is + available locally. The CI gate intentionally does not check OrthoConfig + out; cross-repo drift is caught by the reconciliation rite, not by an + always-on probe. +- Risk: A command-contract task is missed during classification. Severity: + high. Likelihood: medium. Mitigation: the candidate set is an explicit + opt-in registry, not a topic-keyword heuristic. Every roadmap task ID + that should be classified appears in + `docs/orthoconfig-consumer-boundary.toml` under a top-level + `managed_tasks` array. The test gate fails when a roadmap task heading + matches an ID in `managed_tasks` but has no matching `[[task]]` row, and + also when a `[[task]]` row references an ID outside `managed_tasks`. + Adding a new command-contract task therefore requires editing the + registry first; default-fail prevents silent omission. +- Risk: Contributors classify a new task as `consumes` even though the + upstream OrthoConfig contract has not shipped yet. Severity: medium. + Likelihood: medium. Mitigation: the manifest's `consumes` state requires + a non-empty `shipped_in` field naming the upstream release (or commit + SHA) that landed the contract, plus the upstream task ID. The test gate + rejects `consumes` rows without `shipped_in`. +- Risk: A roadmap task depends on an OrthoConfig contract that is not yet + decided. Severity: high. Likelihood: high (phases 17–20 in particular). + Mitigation: a fourth state `pending` captures exactly this case. A + `pending` row carries the upstream task ID with `shipped_in = None` and + a non-empty `next_review_by` field (ISO-8601 date). The test gate fails + when a `pending` row's `next_review_by` is more than 270 days in the past + to prevent the matrix from decaying into a parking lot. +- Risk: The matrix doc and the manifest TOML drift. Severity: high. + Likelihood: medium. Mitigation: the matrix is generated from the manifest + by a Rust helper that the test calls; the test asserts byte-for-byte + equality with the committed matrix Markdown. There is no second snapshot + layer to maintain. +- Risk: Boundary classification is treated as a one-off audit rather than a + living contract. Severity: high. Likelihood: medium. Mitigation: + documentation in `docs/developers-guide.md` describes the workflow and + links to the matrix; the test gate runs on every CI build; every row + carries a `last_reviewed` ISO-8601 date and the gate warns (without + failing) when any row is more than 270 days stale, prompting a refresh. +- Risk: A `divergent` state is used as a parking lot for "we have not + decided". Severity: medium. Likelihood: low (now that `pending` exists). + Mitigation: every `divergent` row must carry an `adr_anchor` field + pointing to a specific section heading in + `docs/adr-007-agent-native-command-surface.md` and the test asserts the + anchor exists. Anchors may be shared by multiple rows (many-to-one), but + the anchor itself must be present. +- Risk: Wafflecat's lighter alternative (inline roadmap annotations with a + small lint, no separate manifest) would satisfy the same prose-level + success criterion at lower surface cost. Severity: low (this is a scope + trade-off, not a correctness risk). Likelihood: n/a. Mitigation: the + Decision Log captures the explicit choice to take the heavier matrix + approach for downstream queryability. If team capacity becomes the + binding constraint, the alternative remains available as a follow-up + redesign. + +## Progress + +Each item carries a UTC timestamp once it completes. The list reflects actual +state, not the intended sequence. + +- [ ] 2026-06-14T02:44:33Z: Execution approved by the user and started on + branch `12-1-1-track-downstream-consumer-boundary`. +- [x] 2026-06-14T02:44:33Z: Stage A ratified the boundary vocabulary and + matrix columns in ADR 007. Validation passed with + `make markdownlint` (`Summary: 0 error(s)`) and `make nixie` + (`All diagrams validated successfully!`). Logs: + `/tmp/markdownlint-weaver-12-1-1-track-downstream-consumer-boundary.out` + and `/tmp/nixie-weaver-12-1-1-track-downstream-consumer-boundary.out`. +- [x] 2026-06-14T03:28:00Z: Stage B produced + `docs/orthoconfig-consumer-boundary.toml`, generated + `docs/orthoconfig-consumer-boundary.md`, added + `crates/weaver-docs-gate`, and pinned `ortho_config` to + `4339a6f3c61dc4fed86493d99ffb05230bee2a1b`. Validation passed with + `cargo build --workspace`, `make fmt`, `make check-fmt`, `make lint`, + `make test`, `make markdownlint`, and `make nixie`. The first + CodeRabbit pass found one valid generic `OrthoConfig 9.2` reference + issue; after fixing the manifest to use `OrthoConfig 9.2.1` and + `OrthoConfig 9.2.2`, regenerating the matrix, and rerunning gates, the + repeat CodeRabbit review completed with `findings: 0`. +- [x] 2026-06-14T04:52:00Z: Stage C cross-linked the generated matrix from + `docs/contents.md`, `docs/developers-guide.md`, and every + manifest-managed roadmap task group. ADR 007 already linked both the + matrix and the TOML source of truth from Stage A. Validation passed with + `make fmt`, `make markdownlint`, `make nixie`, and CodeRabbit + `findings: 0`. +- [x] 2026-06-14T05:36:00Z: Stage D added + `crates/weaver-docs-gate/tests/boundary_manifest.rs`, covering + manifest registry order, roadmap task references, state-specific + evidence fields, ADR 007 divergence anchors, and byte-for-byte matrix + regeneration. Validation passed with `cargo test -p weaver-docs-gate`, + `make fmt`, `make check-fmt`, `make lint`, `make test`, + `make markdownlint`, and `make nixie`. The first CodeRabbit pass found + five valid test-diagnostic issues; after refactoring the tests to return + `Result<(), String>` with explicit validation errors, the repeat review + completed with `findings: 0`. +- [x] 2026-06-14T06:28:00Z: Stage E refreshed + `docs/users-guide.md` with the operator-facing boundary note for + temporary wrappers and pending OrthoConfig contracts. Validation passed + with `make fmt`, `make check-fmt`, `make lint`, `make test`, + `make markdownlint`, and `make nixie` before the final CodeRabbit + review. Final CodeRabbit completed with `findings: 0`. + +## Surprises & discoveries + +Recorded as they occur during implementation. Format: + +- Observation: … + Evidence: … + Impact: … +- Observation: `toml` was already present in `Cargo.lock` but was not a + workspace dependency. + Evidence: repository search showed transitive lockfile entries and no + workspace dependency entry before Stage B. + Impact: Stage B added `toml = "0.9.12"` to `[workspace.dependencies]` so + the private docs-gate crate can use the parser explicitly. +- Observation: `mdtablefix` rewrites generated Markdown tables and can break + rows that contain empty cells. + Evidence: the first `make fmt` attempt failed with `MD056` after wrapping + empty table cells in `docs/orthoconfig-consumer-boundary.md`. + Impact: the renderer now emits formatter-stable aligned tables and displays + absent values as `n/a`; the TOML manifest remains the evidence source for + genuinely empty fields. +- Observation: delivery and feedback OrthoConfig references need versioned + leaf task identifiers in shared upstream lists. + Evidence: `coderabbit review --agent` flagged the `12.1.5` manifest row + while later rows already used `OrthoConfig 9.2.1` and + `OrthoConfig 9.2.2`. + Impact: the manifest now uses the leaf task identifiers consistently before + generated matrix publication. +- Observation: the matrix drift test must compare against the Markdown shape + after repository formatting, not only the raw renderer's first draft. + Evidence: the first Stage D focused test run passed integrity checks but + failed `committed_matrix_matches_manifest_rendering` because the renderer + emitted pre-`mdtablefix` paragraph wrapping and a one-character wider final + table column. + Impact: the renderer now emits the formatter-stable matrix text that is + committed, making future manifest or renderer drift deterministic. + +## Decision log + +Recorded for any decision that future work must respect. + +- Decision: execute this plan despite the document's previous draft status. + Rationale: the user explicitly requested implementation of this plan on + 2026-06-14, satisfying the ExecPlan approval gate. Date/Author: + 2026-06-14, implementation. +- Decision: pin `ortho_config` to commit + `4339a6f3c61dc4fed86493d99ffb05230bee2a1b` until the project agrees an + OrthoConfig v0.9.0 release. + Rationale: the user requested a pinned SHA rather than a release version for + now; `git ls-remote https://github.com/leynos/ortho-config.git HEAD` + resolved that revision for the current upstream main branch. Date/Author: + 2026-06-14, implementation. +- Decision: classify boundary state with a closed four-value vocabulary + (`consumes`, `wraps`, `pending`, `divergent`) rather than free-form prose. + Rationale: the three-value vocabulary (consumes/wraps/divergent) borrowed + from OpenAPI Generator and IETF BCP 9 compliance reports does not + distinguish "upstream contract exists but unshipped" (`wraps`, with a + removal gate) from "upstream contract not yet decided" (`pending`, with + a `next_review_by` date). Without the fourth state the matrix would + pollute `wraps` and `divergent` with non-decisions, exactly the parking + lot the gate is meant to prevent. Date/Author: 2026-06-07, Logisphere + review by Telefono and Doggylump. +- Decision: hold the classification as a single TOML manifest at + `docs/orthoconfig-consumer-boundary.toml`, render the Markdown matrix from + it, and gate referential integrity from a Rust integration test. + Rationale: keeps the source of truth machine-readable, avoids + hand-maintained tables drifting, and follows the `xtask`-style drift gate + pattern (matklad/cargo-xtask, `trycmd`) used in the wider Rust ecosystem. + Date/Author: 2026-06-07, planning. +- Decision: host the test gate in a new tiny workspace member + `crates/weaver-docs-gate`, not in `crates/weaver-build-util`. + Rationale: `weaver-build-util` exists for build-script helpers (manual + page dates, capability-based `Dir` access). Adding documentation- + governance integration tests there mixes concerns and gives the + build-helper crate a misleading public surface. A dedicated workspace + member is honest about scope and keeps `weaver-build-util` boring. + Date/Author: 2026-06-07, Logisphere review by Pandalump. +- Decision: identify upstream contract availability with a + `shipped_in: Option` field (an OrthoConfig version tag such as + `"0.9.0"` or a fallback commit short SHA when no release exists yet), + not a Boolean `shipped` flag. Rationale: Boolean is too coarse for an + evolving dependency; a version string survives the `wraps → consumes` + transition audibly and lets the matrix encode minimum-known-good + versions. Date/Author: 2026-06-07, Logisphere review by Telefono. +- Decision: maintain the candidate set as an explicit `managed_tasks` + array in the manifest, not as a topic-keyword heuristic over the + roadmap prose. Rationale: heuristics produce silent false negatives + when a new task uses unfamiliar terminology; the explicit list defaults + to fail-closed and forces classification on every new command-contract + task. Date/Author: 2026-06-07, Logisphere review by Buzzy Bee. +- Decision: do not wire `rstest-bdd` scenarios for the matrix gate. + Rationale: the candidate behavioural scenarios are direct restatements + of the integration-test invariants. `rstest-bdd` would add ceremony + without adding behavioural coverage. The integration test stays as a + parameterized `rstest` suite. Date/Author: 2026-06-07, Logisphere + review by Dinolump. +- Decision: assert matrix freshness by byte-for-byte equality with the + committed Markdown file, not via an `insta` snapshot. Rationale: the + manifest is the source of truth and the renderer is deterministic; a + second snapshot review layer would duplicate the equality check + without adding signal. Date/Author: 2026-06-07, Logisphere review by + Dinolump. +- Decision: do not generate the OrthoConfig dependency table in ADR 007 + from the manifest. Rationale: ADR 007 is a stable, human-readable + architectural record. The manifest is the per-task index that points + back to the ADR; a cycle would couple them too tightly. Date/Author: + 2026-06-07, planning. +- Decision considered and deferred: switch entirely to inline roadmap + annotations (Wafflecat's lighter alternative) with no separate manifest + or matrix doc. Rationale for deferring: the heavier matrix approach + enables cross-phase queryability and a single discoverable artefact for + contributors and reviewers. If team capacity proves limiting, the + lighter alternative remains a viable follow-up. Date/Author: 2026-06-07, + Logisphere review by Wafflecat; deferred. + +## Outcomes & retrospective + +Recorded at completion. Includes whether the gate caught a regression in +practice, how often the manifest needed updates during subsequent tasks, and +any vocabulary or schema adjustments. + +## Context and orientation + +A novice opening this plan needs the following landmarks before reading the +"Plan of work" section. + +### Repository landmarks + +- `docs/roadmap.md` — the live forward roadmap. Tasks 12 through 20 belong to + the post-ADR-007 grammar. Task 12.1.1 lives at lines 38 to 47. +- `docs/adr-007-agent-native-command-surface.md` — the ADR that introduced + the agent-native command surface, the OrthoConfig dependency table (lines + 104 to 122), and the temporary-adapter removal policy (lines 129 to 147). +- `crates/weaver-cli/src/command_surface.rs` — the only current temporary + adapter, holding `CommandSurfaceRecord`, `READ_ONLY_COMMANDS`, and + `find_read_only_command` for the pilot `definitions get` and + `references list` family. Its module documentation already names the + OrthoConfig replacement tasks. This file is not modified by 12.1.1. +- `crates/weaver-build-util/src/lib.rs` — a shared build-time helper + crate (manual-page dates, capability-based `Dir` access). This plan + does *not* touch it; the boundary gate has nothing to do with build + scripts. +- `crates/weaver-docs-gate/` — new workspace member introduced by this + plan. It hosts the manifest parser (`load_manifest`), the matrix + renderer (`render_matrix`), the `cargo run --example` regenerator, + and the `boundary_gate` integration test. It has no runtime + consumers; its only role is to make documentation governance + testable. +- `docs/developers-guide.md` — the long-form contributor guide. A new + subsection ("Tracking the OrthoConfig consumer boundary") sits next to the + existing ADR guidance. +- `docs/users-guide.md` — the long-form user guide. A new short paragraph + records that some `--json` and human-renderer details may temporarily + diverge from upstream until OrthoConfig contracts ship. + +### Upstream landmarks (read once for context) + +- OrthoConfig roadmap, task 5.2.3: documentation-only commitment to record + consumer dependency boundaries for Weaver and Netsuke. The hard + dependencies are whole-CLI introspection, strict vocabulary policy, + agent-context IR, and localized help generation. The soft dependencies are + profiles, delivery, feedback, skill manifests, and execution ledgers. +- OrthoConfig `docs/agent-native-cli-design.md` §2.1: states that OrthoConfig + owns schemas, command metadata, vocabulary, renderer metadata, generated + help and man pages, policy linting, and optional primitives for profiles, + delivery, feedback, skill manifests, and execution ledgers. Weaver owns + semantic execution, capability routing, providers, sandboxing, Double-Lock + safety, edits, jobs, and provider-specific idempotency. +- OrthoConfig `docs/adr-003-define-schema-ownership-for-agent-native-contracts.md`: + defines the three contract crates and the schema-version constants + (`ORTHO_AGENT_CONTEXT_SCHEMA_VERSION`, + `ORTHO_POLICY_REPORT_SCHEMA_VERSION`). + +### Terms of art + +- **Command-contract task.** A roadmap task whose body or success criterion + touches at least one of: command surface metadata, public CLI grammar, + resource path or canonical verb, renderer contract (`--json`, human + renderer, `--plain`, `--color`, `--width`, paging), exit-code taxonomy, + bounded-list output, mutation policy (`--dry-run`, `--force`, + idempotency), structured error schemas, enumerating diagnostics, selector + forms (`--uri`, `--position`, `--query`, `--from-stdin`), capability + discoverability (`context --json`, `capabilities list`, `help`, manpages, + completions, skills), profiles, delivery, feedback, jobs, execution + ledger, or drift gates. The canonical candidate list is built into the + manifest. +- **Boundary state.** One of `consumes`, `wraps`, `pending`, or + `divergent`. + - `consumes` means the Weaver task imports or follows an OrthoConfig + contract that has already shipped. The manifest row carries the + upstream task ID *and* a non-empty `shipped_in` field naming the + OrthoConfig release tag (for example `"0.9.0"`) or a fallback short + commit SHA. The row carries no `removal_gate`. + - `wraps` means the Weaver task creates or reuses a temporary local + adapter while waiting for OrthoConfig to ship a contract whose shape + is committed upstream but whose implementation has not yet landed. + The manifest row carries the upstream task ID, an empty + `shipped_in`, and a non-empty `removal_gate`. + - `pending` means the Weaver task depends on an OrthoConfig contract + whose shape is not yet decided upstream. The row carries the upstream + task ID, an empty `shipped_in`, no `removal_gate`, and a non-empty + `next_review_by` ISO-8601 date naming when the row will be + re-evaluated. + - `divergent` means the Weaver task deliberately deviates from an + OrthoConfig contract. The row carries a non-empty `adr_anchor` + pointing to a heading slug in + `docs/adr-007-agent-native-command-surface.md`. +- **Removal gate.** The condition under which a `wraps` row must be + retired: usually "the upstream OrthoConfig task is implemented" or a + composite of several upstream tasks. The gate text matches the language + already used in the ADR 007 removal policy. +- **`managed_tasks` registry.** A top-level array in the manifest listing + every Weaver roadmap task ID whose body sits inside the boundary + surface. The registry is the candidate set; the gate fails when a + registry entry has no `[[task]]` row, when a `[[task]]` row references + an ID outside the registry, or when a candidate task heading appears + in the roadmap but is missing from both. + +### Hexagonal architecture relevance + +Boundary classification is a dependency-rule artefact, not a runtime port. +The matrix records, for each Weaver task, which side of the +domain-versus-adapter line its contract sits on. `consumes` means Weaver +imports a port owned by OrthoConfig; `wraps` means Weaver maintains a local +adapter that will be replaced by the upstream port; `divergent` means +Weaver's domain deliberately defines its own port because the upstream port +does not fit. Treat the matrix as a guard against accidentally inverting the +dependency rule when a new task lands. + +## Plan of work + +The work runs in five short stages. Each stage ends with a validation step +that must pass before the next stage starts. + +### Stage A: ratify the boundary vocabulary and matrix shape + +Stage A is documentation-led. No code lands. + +1. Open `docs/adr-007-agent-native-command-surface.md` and add a new section + titled "Boundary classification" before "Consequences". The section + defines the four states (`consumes`, `wraps`, `pending`, `divergent`), + the evidence each state requires, and the location of the matrix + (`docs/orthoconfig-consumer-boundary.md`). It does not duplicate the + existing "OrthoConfig dependencies" or "Temporary adapter removal + policy" sections; it points at them. It states explicitly that + `pending` exists to keep `wraps` honest about "shape committed + upstream" versus "shape not yet decided upstream". +2. Choose canonical column names for the matrix: `Roadmap task`, `Gist`, + `State`, `Upstream OrthoConfig task`, `Shipped in`, + `Removal gate or divergence`, `Next review by`, `Last reviewed`. + Document them in the new ADR section. +3. Open `docs/documentation-style-guide.md` only if a style entry is needed + for the badge or symbol convention used in the matrix (a leading + `✓`, `~`, or `×` character paired with the textual state name); if no + entry is needed, do not modify the style guide. + +Validation: `make markdownlint` passes, `make nixie` passes, and the new +section in ADR 007 reads as a self-contained explanation that a contributor +without prior context can use to classify a new task. + +### Stage B: produce the boundary manifest, generator, and matrix doc + +Stage B introduces a single source of truth and the renderer that derives +the human-readable matrix from it. + +1. Create `docs/orthoconfig-consumer-boundary.toml`. The file has a + top-level `managed_tasks` array listing every Weaver roadmap task ID + that falls inside the boundary surface, and one `[[task]]` row per + entry: + + ```toml + schema_version = 1 + + managed_tasks = [ + "12.1.1", "12.1.2", "12.1.3", "12.1.4", "12.1.5", + "13.1.1", "13.1.2", "13.1.3", + "13.2.1", "13.2.2", "13.2.3", + "13.3.1", "13.3.2", "13.3.3", "13.3.4", + # … through phases 14–20 (see Stage B step 2). + ] + + [[task]] + id = "13.1.2" + gist = "Implement the Weaver command-surface adapter for one read-only command family." + state = "wraps" + upstream = [ + { task = "OrthoConfig 5.2.3", role = "boundary" }, + { task = "OrthoConfig 6.1", role = "metadata" }, + { task = "OrthoConfig 7.2.7", role = "capability_provenance" }, + ] + shipped_in = "" + removal_gate = """ + Replace `CommandSurfaceRecord` once OrthoConfig 6.1 and 7.2.7 ship the \ + recursive command and capability/provenance metadata. + """ + adr_anchor = "" + next_review_by = "" + last_reviewed = "2026-06-07" + ``` + + The fields encode each state's evidence requirement: + + - `consumes` — `shipped_in` is non-empty and names an OrthoConfig + release tag or short commit SHA; `removal_gate`, `adr_anchor`, and + `next_review_by` are empty. + - `wraps` — `shipped_in` is empty; `removal_gate` is non-empty; + `adr_anchor` is empty; `next_review_by` may be empty. + - `pending` — `shipped_in` and `removal_gate` are empty; + `next_review_by` is non-empty (ISO-8601 date); `adr_anchor` may be + empty. + - `divergent` — `adr_anchor` is non-empty and names a stable heading + slug in `docs/adr-007-agent-native-command-surface.md` (anchors may + be shared by multiple rows); `shipped_in` and `removal_gate` are + empty. + + The `role` field on each upstream entry is a closed enum: + `boundary`, `metadata`, `capability_provenance`, `vocabulary`, + `renderer`, `profile`, `delivery`, `feedback`, `execution_ledger`. + The test gate rejects unknown roles. +2. Populate the manifest with the candidate set derived from + `docs/roadmap.md` and ADR 007. Use the topic-keyword scan described in + the Risks section. At minimum the seed set must include: + - 12.1.1 through 12.1.5; + - 13.1.1, 13.1.2, 13.1.3, 13.2.1, 13.2.2, 13.2.3, 13.3.1, 13.3.2, + 13.3.3, 13.3.4; + - 14.1.1 through 14.1.4, 14.2.1 through 14.2.3, 14.3.1, 14.3.2; + - 15.1.1, 15.1.2, 15.3.2, 15.3.3, 15.3.5, 15.3.6; + - 16.1.1, 16.1.2, 16.1.3, 16.2.1, 16.2.2, 16.2.3, 16.3.3, 16.3.5; + - 17.1.5, 17.2.2; + - 18.2.1; + - 19.1.1, 19.1.2, 19.1.3, 19.1.4, 19.2.2; + - 20.1.1, 20.1.2, 20.3.3. + + Each row carries its classification, upstream pairing, and (where + applicable) removal gate language derived from ADR 007's existing + table. Tasks classified `consumes` must reference an upstream that has + already shipped; tasks classified `wraps` must reference a removal + gate; tasks classified `divergent` must reference an ADR 007 anchor. +3. Create a new tiny workspace member at `crates/weaver-docs-gate` that + exposes the manifest parser and the matrix renderer to the test + harness: + + ```toml + # crates/weaver-docs-gate/Cargo.toml + [package] + name = "weaver-docs-gate" + version = "0.0.0" + publish = false + edition = "2024" + ``` + + The crate has no runtime dependencies it does not need: only + `serde`, `toml`, `camino`, and `thiserror` (all already in the + workspace). It is not a library that downstream code links; it is a + test fixture in crate form. The crate's `src/lib.rs` exposes: + + ```rust + pub fn load_manifest(path: &Utf8Path) -> Result; + pub fn render_matrix(manifest: &BoundaryManifest) -> String; + ``` + + `BoundaryManifest` holds the `schema_version`, the ordered + `managed_tasks` array, and a `Vec` keyed by task ID. + `BoundaryTask` holds `id`, `gist`, `state` (an enum with four + variants), `upstream` (a `Vec`), `shipped_in`, + `removal_gate`, `adr_anchor`, `next_review_by`, and `last_reviewed`. +4. Generate `docs/orthoconfig-consumer-boundary.md` from the manifest. The + matrix uses pipe-delimited Markdown tables grouped by roadmap phase + (12, 13, 14, 15, 16, 17, 18, 19, 20). Each table row links the task ID + back to its roadmap anchor, displays the state with a leading symbol + (`✓` for `consumes`, `~` for `wraps`, `?` for `pending`, `×` for + `divergent`), and lists the upstream task IDs joined by commas. The + `Shipped in` column carries the OrthoConfig version tag for + `consumes` rows and is empty otherwise. Long removal-gate text wraps + in the cell; the gate is the single source of truth and is not + abbreviated. + +Validation: `cargo build --workspace` succeeds (the new +`weaver-docs-gate` crate compiles). `make markdownlint` and `make nixie` +pass. The generated matrix matches the committed +`docs/orthoconfig-consumer-boundary.md` byte for byte. + +### Stage C: cross-link the matrix from ADR 007, the roadmap, and the developers' guide + +Stage C adds the back-links and a contributor workflow that prevents +silent drift. + +1. In `docs/adr-007-agent-native-command-surface.md`, finish the + "Boundary classification" section by linking to the matrix and the + manifest. The existing OrthoConfig dependency table stays as-is. +2. In `docs/roadmap.md`, immediately under the "12.1.1" item, add a single + sentence linking the matrix: "See the OrthoConfig consumer boundary + matrix for the per-task classification." Add the same link near the + headings of phases 13 through 20 so contributors editing a later phase + discover the matrix without scrolling. +3. In `docs/developers-guide.md`, add a subsection titled "Tracking the + OrthoConfig consumer boundary". It describes the workflow: + - When adding a roadmap task that touches a command-contract topic, + first add its ID to the `managed_tasks` array, then add a + `[[task]]` row in `docs/orthoconfig-consumer-boundary.toml`. + - Choose the matching classification state. If the upstream + OrthoConfig contract has not yet been decided, use `pending` and + set `next_review_by`. + - Run `cargo test -p weaver-docs-gate --test boundary_gate` to + regenerate `docs/orthoconfig-consumer-boundary.md` and assert + referential integrity. + - When OrthoConfig ships an upstream contract, flip the manifest + row from `wraps` or `pending` to `consumes`, set `shipped_in` to + the OrthoConfig release tag (or short commit SHA), and drop the + removal gate or review date. + - For a `divergent` row, capture the rationale in a named ADR 007 + section anchor and reference it in the manifest. Anchors may be + shared by multiple rows. + - Run the quarterly cross-repo reconciliation step (a short + ritual): when an OrthoConfig checkout is locally available, scan + the manifest's upstream phrases against the OrthoConfig roadmap + and fix any drifted IDs by hand. This ritual lives in the + developers' guide because the CI gate intentionally does not + check OrthoConfig out. +4. In `docs/contents.md`, add a new entry for + `docs/orthoconfig-consumer-boundary.md` so the new doc is discoverable + from the index. + +Validation: `make markdownlint` passes; the cross-links resolve when the +repository is browsed locally; the developers' guide entry is reachable +from `docs/contents.md`. + +### Stage D: add the referential-integrity test gate and snapshot + +Stage D enforces the matrix at CI time. + +1. In `crates/weaver-docs-gate/Cargo.toml`, add `rstest`, + `pretty_assertions`, and `googletest` to `[dev-dependencies]` (each + already lives in the workspace). The crate does not gain new runtime + dependencies and does not depend on `insta` or `rstest-bdd`. +2. Add `crates/weaver-docs-gate/tests/boundary_gate.rs`. It loads the + manifest, generates the matrix Markdown, and asserts the following + invariants. Each invariant is parameterized with `rstest` so the test + reports the specific row or task ID at fault. + + The invariants are: + + - **Required fields.** Every `[[task]]` row has a non-empty `id`, + `gist`, `state`, and `last_reviewed` field, and `state` is one of + `consumes`, `wraps`, `pending`, `divergent`. + - **`consumes` evidence.** Rows with `state = "consumes"` carry a + non-empty `shipped_in`, at least one upstream entry, an empty + `removal_gate`, an empty `adr_anchor`, and an empty + `next_review_by`. + - **`wraps` evidence.** Rows with `state = "wraps"` carry at least + one upstream entry, an empty `shipped_in`, a non-empty + `removal_gate`, and an empty `adr_anchor`. + - **`pending` evidence.** Rows with `state = "pending"` carry at + least one upstream entry, an empty `shipped_in`, an empty + `removal_gate`, and a non-empty `next_review_by` ISO-8601 date. + - **`divergent` evidence.** Rows with `state = "divergent"` carry a + non-empty `adr_anchor`, an empty `shipped_in`, and an empty + `removal_gate`; the anchor occurs as a heading slug in + `docs/adr-007-agent-native-command-surface.md`. + - **Registry symmetry.** Every ID in `managed_tasks` has a matching + `[[task]]` row; every `[[task]]` row's `id` appears in + `managed_tasks`; every `managed_tasks` ID appears as a task + heading in `docs/roadmap.md`. + - **`role` enum.** Each upstream entry's `role` is one of + `boundary`, `metadata`, `capability_provenance`, `vocabulary`, + `renderer`, `profile`, `delivery`, `feedback`, `execution_ledger`. + - **Date formats.** `last_reviewed` and `next_review_by` parse as + ISO-8601 dates (`YYYY-MM-DD`). + - **Staleness budget (warn).** When any row's `last_reviewed` is + more than 270 days behind the build's `SOURCE_DATE_EPOCH` (or wall + clock if the variable is unset), the test prints a warning naming + the row but does not fail. + - **`pending` decay budget (fail).** When a `pending` row's + `next_review_by` is more than 270 days *behind* the same + reference date, the test fails. This stops `pending` rows from + becoming a parking lot. + - **Matrix freshness.** The Markdown produced by `render_matrix` + equals the committed `docs/orthoconfig-consumer-boundary.md` + byte for byte. + +3. **Failure-message format.** Each invariant emits a diagnostic in a + fixed shape so contributors can resolve it without reading the test + source. The shape is: + + ```plaintext + boundary-gate: + roadmap_task: + manifest_path: docs/orthoconfig-consumer-boundary.toml + details: + remediation: + see: docs/developers-guide.md#tracking-the-orthoconfig-consumer-boundary + ``` + + Concrete examples that the test must produce verbatim: + + ```plaintext + boundary-gate: registry-symmetry + roadmap_task: 13.2.4 + manifest_path: docs/orthoconfig-consumer-boundary.toml + details: managed_tasks lists "13.2.4" but no [[task]] row matches. + remediation: add a [[task]] row for "13.2.4" with the matching state. + see: docs/developers-guide.md#tracking-the-orthoconfig-consumer-boundary + ``` + + ```plaintext + boundary-gate: consumes-evidence + roadmap_task: 14.1.1 + manifest_path: docs/orthoconfig-consumer-boundary.toml + details: state = "consumes" but shipped_in is empty. + remediation: set shipped_in to the OrthoConfig release tag, or change state to "wraps" or "pending". + see: docs/developers-guide.md#tracking-the-orthoconfig-consumer-boundary + ``` + + The integration test produces these strings through a small + helper. `pretty_assertions::assert_eq!` reports the message verbatim + on failure. + +Validation: the new test fails before the manifest exists (Red), passes +once Stage B is in place (Green), and remains green after Stage E. + +### Stage E: refresh the users' guide, run the full quality gates, and run CodeRabbit + +1. In `docs/users-guide.md`, add a short paragraph in the appropriate + chapter (the user-facing JSON or output-mode discussion) noting that + some `--json` fields, exit classes, and error codes may be provisional + until the OrthoConfig contracts ship. The paragraph links to the + matrix and notes that field names and exit classes remain stable + inside a Weaver minor release. +2. Run `make check-fmt` and capture the output under + `/tmp/check-fmt-weaver-12-1-1-track-downstream-consumer-boundary.out`. +3. Run `make lint`, `make test`, `make markdownlint`, and `make nixie`, + each capturing to a log file with the same naming convention. Verify + each completes successfully. +4. Run `coderabbit review --agent` and resolve every comment before the + plan is marked COMPLETE. + +Validation: every command completes successfully and `coderabbit review +--agent` raises no outstanding concerns. The roadmap entry for 12.1.1 is +ticked off. + +## Concrete steps + +The following sequence assumes a clean working tree on branch +`12-1-1-track-downstream-consumer-boundary`. All commands run from the +repository root. + +### Stage A commands + +```sh +${EDITOR:-vi} docs/adr-007-agent-native-command-surface.md +make markdownlint 2>&1 | tee /tmp/markdownlint-weaver-12-1-1-track-downstream-consumer-boundary.out +make nixie 2>&1 | tee /tmp/nixie-weaver-12-1-1-track-downstream-consumer-boundary.out +git add docs/adr-007-agent-native-command-surface.md +git commit -m "Add OrthoConfig boundary classification section to ADR 007" +``` + +### Stage B commands + +```sh +${EDITOR:-vi} docs/orthoconfig-consumer-boundary.toml +${EDITOR:-vi} crates/weaver-docs-gate/Cargo.toml +${EDITOR:-vi} crates/weaver-docs-gate/src/lib.rs +${EDITOR:-vi} Cargo.toml # add the new workspace member +cargo build --workspace 2>&1 | tee /tmp/build-weaver-12-1-1-track-downstream-consumer-boundary.out +# Regenerate the matrix using the renderer exposed through cargo run --example. +cargo run -p weaver-docs-gate --example render_boundary_matrix \ + -- docs/orthoconfig-consumer-boundary.toml \ + docs/orthoconfig-consumer-boundary.md +make markdownlint 2>&1 | tee /tmp/markdownlint-weaver-12-1-1-track-downstream-consumer-boundary.out +git add crates/weaver-docs-gate docs/orthoconfig-consumer-boundary.toml \ + docs/orthoconfig-consumer-boundary.md Cargo.toml +git commit -m "Add OrthoConfig consumer boundary manifest, crate, and matrix" +``` + +The renderer is exposed through `cargo run --example` rather than a +`[[bin]]` entry; the example shares the same parser the test calls so +the test cannot rot behind the generator. + +### Stage C commands + +```sh +${EDITOR:-vi} docs/roadmap.md +${EDITOR:-vi} docs/developers-guide.md +${EDITOR:-vi} docs/contents.md +make markdownlint 2>&1 | tee /tmp/markdownlint-weaver-12-1-1-track-downstream-consumer-boundary.out +git add docs/roadmap.md docs/developers-guide.md docs/contents.md +git commit -m "Cross-link the OrthoConfig consumer boundary matrix" +``` + +### Stage D commands + +```sh +${EDITOR:-vi} crates/weaver-docs-gate/Cargo.toml +${EDITOR:-vi} crates/weaver-docs-gate/tests/boundary_gate.rs +make check-fmt 2>&1 | tee /tmp/check-fmt-weaver-12-1-1-track-downstream-consumer-boundary.out +make lint 2>&1 | tee /tmp/lint-weaver-12-1-1-track-downstream-consumer-boundary.out +make test 2>&1 | tee /tmp/test-weaver-12-1-1-track-downstream-consumer-boundary.out +git add crates/weaver-docs-gate +git commit -m "Gate the OrthoConfig boundary matrix with a referential-integrity test" +``` + +### Stage E commands + +```sh +${EDITOR:-vi} docs/users-guide.md +make check-fmt 2>&1 | tee /tmp/check-fmt-weaver-12-1-1-track-downstream-consumer-boundary.out +make lint 2>&1 | tee /tmp/lint-weaver-12-1-1-track-downstream-consumer-boundary.out +make test 2>&1 | tee /tmp/test-weaver-12-1-1-track-downstream-consumer-boundary.out +make markdownlint 2>&1 | tee /tmp/markdownlint-weaver-12-1-1-track-downstream-consumer-boundary.out +make nixie 2>&1 | tee /tmp/nixie-weaver-12-1-1-track-downstream-consumer-boundary.out +coderabbit review --agent +git add docs/users-guide.md +git commit -m "Note OrthoConfig boundary in the user's guide" +``` + +After Stage E, mark `12.1.1` complete in `docs/roadmap.md` in a final +commit. + +## Validation and acceptance + +Quality criteria define what "done" means. + +- **Behaviour.** A contributor adding a new command-contract roadmap task + without a manifest row sees `cargo test --workspace` fail with a + `boundary-gate: registry-symmetry` diagnostic naming the missing task. + A `wraps` row without a removal gate, a `consumes` row without + `shipped_in`, a `pending` row whose `next_review_by` is more than 270 + days in the past, or a `divergent` row without an ADR 007 anchor each + fail the same test with the matching diagnostic shape from Stage D. + The generated matrix Markdown matches the committed copy. +- **Tests.** `cargo test --workspace` passes including the new + `boundary_gate` integration test in `crates/weaver-docs-gate`. The + test fails for the expected reason before Stage B is in place (Red), + passes after Stage B and Stage D land (Green), and the matrix + regeneration is idempotent (Refactor). +- **Lint and typecheck.** `make check-fmt`, `make lint`, `make markdownlint`, + and `make nixie` succeed. New code adds no `#[allow]` or `#[expect]` + attributes beyond what existing files use. +- **Documentation.** `docs/contents.md` lists the new boundary matrix; + `docs/users-guide.md` mentions provisional contracts where users may + notice them; `docs/developers-guide.md` carries the contributor + workflow; ADR 007 carries the boundary classification section. +- **CodeRabbit.** `coderabbit review --agent` raises no outstanding + concerns at completion. + +### Red-Green-Refactor evidence + +- **Red.** Before Stage B and Stage D land, + `cargo test -p weaver-docs-gate --test boundary_gate` fails with the + exact `boundary-gate: registry-symmetry` diagnostic shape shown in + Stage D. Capture the failing transcript in `Progress` under Stage D. +- **Green.** After Stage B (manifest, generator) and Stage D (test gate) + land, the same command passes. Capture the passing transcript. +- **Refactor.** Re-render the matrix with the `cargo run --example` + invocation in Stage B and rerun the test; both remain green. Capture + the output. + +## Interfaces and dependencies + +The Rust helper carries a deliberately small public surface. + +```rust +//! Tooling for the OrthoConfig consumer boundary matrix. + +use camino::Utf8Path; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum BoundaryState { + Consumes, + Wraps, + Pending, + Divergent, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum UpstreamRole { + Boundary, + Metadata, + CapabilityProvenance, + Vocabulary, + Renderer, + Profile, + Delivery, + Feedback, + ExecutionLedger, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct UpstreamRef { + pub task: String, + pub role: UpstreamRole, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct BoundaryTask { + pub id: String, + pub gist: String, + pub state: BoundaryState, + pub upstream: Vec, + pub shipped_in: Option, + pub removal_gate: Option, + pub adr_anchor: Option, + pub next_review_by: Option, + pub last_reviewed: String, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct BoundaryManifest { + pub schema_version: u32, + pub managed_tasks: Vec, + pub tasks: Vec, +} + +#[derive(Debug, thiserror::Error)] +pub enum BoundaryError { + #[error("manifest file not found: {0}")] + NotFound(camino::Utf8PathBuf), + #[error("invalid TOML: {0}")] + InvalidToml(String), + #[error("invalid manifest row: {0}")] + InvalidRow(String), + #[error("unknown upstream role: {0}")] + UnknownRole(String), +} + +pub fn load_manifest(path: &Utf8Path) -> Result; +pub fn render_matrix(manifest: &BoundaryManifest) -> String; +``` + +The renderer takes no global state, accepts a parsed manifest, and +returns a `String`. The test gate calls `load_manifest` and +`render_matrix` and compares the rendered output against the committed +matrix Markdown byte for byte. + +The integration test depends only on existing workspace dependencies +(`rstest`, `pretty_assertions`, `googletest`, `toml`, `camino`, +`thiserror`). It does not use `insta` or `rstest-bdd`. + +## Boundary classification diagram + +A high-level view of the boundary states and their evidence: + +```mermaid +flowchart TD + Task[Command-contract roadmap task] + Task --> Classify{Boundary state} + Classify -- consumes --> Shipped[shipped_in: OrthoConfig release] + Classify -- wraps --> Gate[removal_gate text] + Classify -- pending --> Review[next_review_by date] + Classify -- divergent --> Anchor[ADR 007 anchor] + Shipped --> Matrix[docs/orthoconfig-consumer-boundary.md] + Gate --> Matrix + Review --> Matrix + Anchor --> Matrix + Matrix --> Test[weaver-docs-gate boundary_gate] + Test --> CI[make test] +``` + +The diagram captures the steady state once the matrix is in place. Each +new command-contract roadmap task adds a row to the manifest; the test +gate stops a commit that omits the row or carries the wrong evidence. + +## Idempotence and recovery + +- Re-running the matrix generator must produce byte-identical output. The + generator does not depend on wall-clock time. The `last_reviewed` field + is set explicitly per row by the contributor when they touch the row. +- Re-running the test gate is safe: the test reads the manifest, the + roadmap, the ADR, and the matrix, and asserts equality. No filesystem + mutation occurs. +- If the manifest and matrix drift, the test fails and the contributor + regenerates the matrix from the manifest. The manifest stays + authoritative. +- A partially completed plan stays in `Progress` so the next contributor + resumes from the last completed stage. Each stage's commit is reversible + by `git revert`. + +## Artefacts and notes + +The plan's working artefacts live under `/tmp` per `AGENTS.md`. They are +captured during execution and referenced from `Progress` once each stage +completes. Examples (filled in as work proceeds): + +```plaintext +/tmp/check-fmt-weaver-12-1-1-track-downstream-consumer-boundary.out +/tmp/lint-weaver-12-1-1-track-downstream-consumer-boundary.out +/tmp/test-weaver-12-1-1-track-downstream-consumer-boundary.out +/tmp/markdownlint-weaver-12-1-1-track-downstream-consumer-boundary.out +/tmp/nixie-weaver-12-1-1-track-downstream-consumer-boundary.out +``` + +## Revision note + +2026-06-07. Revised after a Logisphere pre-implementation design review. +Changes applied: (1) host crate moved from `weaver-build-util` to a new +`weaver-docs-gate` workspace member; (2) classification vocabulary +expanded to four states (`consumes`, `wraps`, `pending`, `divergent`) +to absorb "upstream contract not yet decided" cleanly; (3) the +`shipped: bool` flag replaced with a `shipped_in: Option` field +carrying the OrthoConfig release tag; (4) the topic-keyword candidate +heuristic replaced with an explicit `managed_tasks` registry that fails +closed when a new ID is missing; (5) the test stack pruned (dropped the +`rstest-bdd` feature file and the `insta` snapshot in favour of one +byte-for-byte equality check); (6) the test gate's failure-message +shape pinned with concrete examples; (7) staleness rules added +(`last_reviewed` warn-at-270-days, `pending.next_review_by` +fail-at-270-days); (8) the `role` field tightened into a closed enum; +(9) the developers' guide adds a quarterly cross-repo reconciliation +ritual. The remaining unresolved alternative (inline roadmap +annotations) is recorded in the Decision Log as deferred. + +## Relevant skills and documentation + +The contributor implementing this plan should load the following skills +and consult the following documents. + +Skills: + +- `execplans` — to keep this plan a living document. +- `hexagonal-architecture` — to interpret the boundary as a dependency-rule + artefact, not a runtime port. +- `arch-decision-records` — to amend ADR 007 cleanly when a `divergent` + row needs an anchor. +- `rust-unit-testing` — for the `rstest` parameterization and the + `pretty_assertions`/`googletest` shape of the gate. The plan + intentionally does *not* use `rstest-bdd` or `insta` because their + scenarios and snapshots would duplicate the integration test's + invariants. +- `arch-crate-design` — to keep `crates/weaver-docs-gate` minimal and + honest about its single test-fixture purpose. +- `commit-message` and `pr-creation` — for the final commits and the draft + pull request. +- `en-gb-oxendict` — for the prose updates. + +Documents: + +- `docs/roadmap.md` +- `docs/adr-007-agent-native-command-surface.md` +- `docs/documentation-style-guide.md` +- `docs/developers-guide.md` +- `docs/users-guide.md` +- `docs/rust-testing-with-rstest-fixtures.md` +- `docs/rust-doctest-dry-guide.md` +- `docs/reliable-testing-in-rust-via-dependency-injection.md` +- `docs/complexity-antipatterns-and-refactoring-strategies.md` +- `docs/ortho-config-users-guide.md` +- `docs/rstest-bdd-users-guide.md` + +Upstream references (read-only context): + +- OrthoConfig roadmap, task 5.2.3 (in the OrthoConfig repository). +- OrthoConfig `docs/agent-native-cli-design.md` §2.1. +- OrthoConfig `docs/adr-003-define-schema-ownership-for-agent-native-contracts.md`. + +Prior art consulted for the gate design: + +- The `cargo-vet` audit-criteria pattern: a per-row state with a + configurable vocabulary, gated at CI time. +- The OpenAPI Generator per-generator support matrix: a three-state + classification rendered into a single discoverable table. +- The `clap_mangen` + `clap_complete` + `trycmd` drift pattern: a + CI-enforced gate that asserts each generated artefact matches the + manifest. +- The Strangler-Fig retirement pattern (Martin Fowler): an ADR + superseded-by link is the right home for a `divergent` row that + later becomes `consumes`. diff --git a/docs/orthoconfig-consumer-boundary.md b/docs/orthoconfig-consumer-boundary.md new file mode 100644 index 00000000..5c9ac46c --- /dev/null +++ b/docs/orthoconfig-consumer-boundary.md @@ -0,0 +1,106 @@ +# OrthoConfig consumer boundary + + + +This matrix is generated from `docs/orthoconfig-consumer-boundary.toml`. Do not +edit the table by hand; update the manifest and regenerate it with +`cargo run -p weaver-docs-gate --example render_boundary_matrix -- docs/orthoconfig-consumer-boundary.toml docs/orthoconfig-consumer-boundary.md`. + +The matrix tracks every live Weaver command-contract roadmap task that consumes +OrthoConfig, wraps it temporarily, waits on upstream shape, or deliberately +diverges under ADR 007. + +## Phase 12 + +| Roadmap task | Gist | State | Upstream OrthoConfig task | Shipped in | Removal gate or divergence | Next review by | Last reviewed | +| ---------------------------------------------------------------------------------- | ------------------------------------------------------ | ---------- | ---------------------------------------------------------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------- | ------------- | +| [12.1.1](roadmap.md#121-confirm-reusable-contracts-that-weaver-must-not-duplicate) | Track the downstream consumer boundary. | ✓ consumes | OrthoConfig 5.2.3 / design §2.1 | 4339a6f3c61dc4fed86493d99ffb05230bee2a1b | n/a | n/a | 2026-06-14 | +| [12.1.2](roadmap.md#121-confirm-reusable-contracts-that-weaver-must-not-duplicate) | Consume recursive command metadata. | ~ wraps | OrthoConfig 6.1 | n/a | Replace local recursive command metadata once OrthoConfig 6.1 ships command and subcommand records that can drive help, manpages, completions, and context output. | n/a | 2026-06-14 | +| [12.1.3](roadmap.md#121-confirm-reusable-contracts-that-weaver-must-not-duplicate) | Consume compact context and skill metadata. | ~ wraps | OrthoConfig 6.2, OrthoConfig 6.3 | n/a | Replace Weaver-local context and skill metadata once OrthoConfig 6.2 and 6.3 ship reusable context and skill shapes that Weaver can extend. | n/a | 2026-06-14 | +| [12.1.4](roadmap.md#121-confirm-reusable-contracts-that-weaver-must-not-duplicate) | Consume canonical vocabulary and behavioural metadata. | ~ wraps | OrthoConfig 7.1, OrthoConfig 7.2, OrthoConfig 8.1 | n/a | Replace Weaver-local vocabulary, renderer, JSON, exit-code, bounded-list, mutation, and provenance checks once OrthoConfig 7.1, 7.2, and 8.1 ship those contracts. | n/a | 2026-06-14 | +| [12.1.5](roadmap.md#121-confirm-reusable-contracts-that-weaver-must-not-duplicate) | Consume compounding primitive contracts. | ? pending | OrthoConfig 9.1, OrthoConfig 9.2.1, OrthoConfig 9.2.2, OrthoConfig 9.3 | n/a | n/a | 2026-12-31 | 2026-06-14 | + +## Phase 13 + +| Roadmap task | Gist | State | Upstream OrthoConfig task | Shipped in | Removal gate or divergence | Next review by | Last reviewed | +| ------------------------------------------------------ | ------------------------------------------------------------------------------ | ----------- | ------------------------------------------------------------------------ | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | -------------- | ------------- | +| [13.1.1](roadmap.md#13-command-contract-proving-slice) | Record the agent-native command-surface reset as ADR 007. | × divergent | OrthoConfig 5.2.3 | n/a | [ADR 007](adr-007-agent-native-command-surface.md#decision-outcome) | n/a | 2026-06-14 | +| [13.1.2](roadmap.md#13-command-contract-proving-slice) | Implement the Weaver command-surface adapter for one read-only command family. | ~ wraps | OrthoConfig 5.2.3, OrthoConfig 6.1, OrthoConfig 7.2.7 | n/a | Replace CommandSurfaceRecord once OrthoConfig 6.1 and 7.2.7 ship recursive command and capability/provenance metadata for Weaver resource paths. | n/a | 2026-06-14 | +| [13.1.3](roadmap.md#13-command-contract-proving-slice) | Define the temporary-adapter removal policy. | ~ wraps | OrthoConfig 6.1, OrthoConfig 7.2.7 | n/a | Retire local generic helpers once their named OrthoConfig replacements are available, unless ADR 007 records a permanent divergence. | n/a | 2026-06-14 | +| [13.2.1](roadmap.md#13-command-contract-proving-slice) | Implement the localized human renderer for definitions get. | ~ wraps | OrthoConfig 7.2.2 | n/a | Replace Weaver-local human renderer metadata once OrthoConfig 7.2.2 ships reusable human-renderer controls and terminal behaviour metadata. | n/a | 2026-06-14 | +| [13.2.2](roadmap.md#13-command-contract-proving-slice) | Implement universal JSON and structured errors for definitions get. | ~ wraps | OrthoConfig 7.2.3, OrthoConfig 7.2.4, OrthoConfig 7.2.5, OrthoConfig 8.1 | n/a | Replace Weaver-local JSON, stderr error, and exit-class definitions once OrthoConfig 7.2.3 through 7.2.5 and 8.1 ship stable renderer contracts. | n/a | 2026-06-14 | +| [13.2.3](roadmap.md#13-command-contract-proving-slice) | Implement enumerating errors and bounded responses for the pilot. | ~ wraps | OrthoConfig 7.2.6 | n/a | Replace local bounded-list and enumerating-error metadata once OrthoConfig 7.2.6 ships the reusable contract. | n/a | 2026-06-14 | +| [13.3.1](roadmap.md#13-command-contract-proving-slice) | Implement weaver context JSON for the pilot command family. | ~ wraps | OrthoConfig 6.2 | n/a | Replace local context payload metadata once OrthoConfig 6.2 ships compact agent-context generation and schema stability. | n/a | 2026-06-14 | +| [13.3.2](roadmap.md#13-command-contract-proving-slice) | Implement capabilities list JSON from runtime provider state. | ~ wraps | OrthoConfig 7.2.7 | n/a | Replace local capability/provenance envelope metadata once OrthoConfig 7.2.7 ships the reusable capability contract. | n/a | 2026-06-14 | +| [13.3.3](roadmap.md#13-command-contract-proving-slice) | Generate help, manpage input, completions, and skill paths. | ~ wraps | OrthoConfig 6.3, OrthoConfig 8.1 | n/a | Replace local generated-reference metadata once OrthoConfig 6.3 and 8.1 ship skill and reference-CLI contracts. | n/a | 2026-06-14 | +| [13.3.4](roadmap.md#13-command-contract-proving-slice) | Add command-surface drift gates for the pilot. | ~ wraps | OrthoConfig 6.1, OrthoConfig 7.1, OrthoConfig 8.1 | n/a | Replace local drift checks for generic command metadata, vocabulary, and renderer surfaces once OrthoConfig ships reusable policy gates. | n/a | 2026-06-14 | + +## Phase 14 + +| Roadmap task | Gist | State | Upstream OrthoConfig task | Shipped in | Removal gate or divergence | Next review by | Last reviewed | +| ----------------------------------------------- | --------------------------------------------------------------------------- | --------- | ---------------------------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------- | -------------- | ------------- | +| [14.1.1](roadmap.md#14-code-reading-loop-slice) | Implement weaver definitions get. | ~ wraps | OrthoConfig 6.1, OrthoConfig 7.2 | n/a | Replace generic command and renderer metadata for definitions get once OrthoConfig 6.1 and 7.2 can express the resource command. | n/a | 2026-06-14 | +| [14.1.2](roadmap.md#14-code-reading-loop-slice) | Implement weaver references list. | ~ wraps | OrthoConfig 6.1, OrthoConfig 7.2.6 | n/a | Replace generic command and bounded-list metadata for references list once OrthoConfig 6.1 and 7.2.6 ship the reusable contracts. | n/a | 2026-06-14 | +| [14.1.3](roadmap.md#14-code-reading-loop-slice) | Implement weaver diagnostics list. | ~ wraps | OrthoConfig 6.1, OrthoConfig 7.2.5 | n/a | Replace generic command and structured-error metadata for diagnostics list once OrthoConfig ships the reusable contracts. | n/a | 2026-06-14 | +| [14.1.4](roadmap.md#14-code-reading-loop-slice) | Add combinatorial read-command end-to-end coverage. | ~ wraps | OrthoConfig 7.2, OrthoConfig 8.1 | n/a | Retire local generic renderer assertions once OrthoConfig reference-CLI and renderer conformance gates cover the shared contract. | n/a | 2026-06-14 | +| [14.2.1](roadmap.md#14-code-reading-loop-slice) | Implement weaver cards get for position references. | ~ wraps | OrthoConfig 6.1, OrthoConfig 7.2 | n/a | Replace generic command, JSON, and human-renderer metadata for cards get once OrthoConfig can express the resource command. | n/a | 2026-06-14 | +| [14.2.2](roadmap.md#14-code-reading-loop-slice) | Add qualified symbol selectors to cards get. | ~ wraps | OrthoConfig 7.2.6 | n/a | Replace generic enumerating-error metadata for ambiguous selectors once OrthoConfig 7.2.6 ships the reusable contract. | n/a | 2026-06-14 | +| [14.2.3](roadmap.md#14-code-reading-loop-slice) | Add one-hop relation summaries to cards. | ~ wraps | OrthoConfig 7.2.6 | n/a | Replace generic bounded-output metadata for relation summaries once OrthoConfig 7.2.6 ships the reusable contract. | n/a | 2026-06-14 | +| [14.3.1](roadmap.md#14-code-reading-loop-slice) | Prototype symbols list pattern search over weaver-syntax and optional srgn. | ? pending | OrthoConfig 6.1, OrthoConfig 7.1 | n/a | n/a | 2026-12-31 | 2026-06-14 | +| [14.3.2](roadmap.md#14-code-reading-loop-slice) | Decide whether the static-search pilot graduates. | ? pending | OrthoConfig 7.1 | n/a | n/a | 2026-12-31 | 2026-06-14 | + +## Phase 15 + +| Roadmap task | Gist | State | Upstream OrthoConfig task | Shipped in | Removal gate or divergence | Next review by | Last reviewed | +| -------------------------------------------------------- | -------------------------------------------------------------------------------- | ------- | ---------------------------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------- | -------------- | ------------- | +| [15.1.1](roadmap.md#15-sempai-selector-to-context-slice) | Implement one-liner tokenization and Pratt parsing for positive symbol patterns. | ~ wraps | OrthoConfig 7.2.5 | n/a | Replace generic diagnostic envelope and error-class metadata once OrthoConfig structured-error contracts are available. | n/a | 2026-06-14 | +| [15.1.2](roadmap.md#15-sempai-selector-to-context-slice) | Define selector record schemas for one-liner matches. | ~ wraps | OrthoConfig 7.2.7 | n/a | Replace generic selector provenance fields once OrthoConfig capability/provenance metadata can carry them. | n/a | 2026-06-14 | +| [15.3.2](roadmap.md#15-sempai-selector-to-context-slice) | Add weaver symbols list query inputs. | ~ wraps | OrthoConfig 6.1, OrthoConfig 7.2.5 | n/a | Replace generic command, input-combination, and error metadata once OrthoConfig can express the symbols list query contract. | n/a | 2026-06-14 | +| [15.3.3](roadmap.md#15-sempai-selector-to-context-slice) | Define stable JSONL request and response schemas for Sempai query operations. | ~ wraps | OrthoConfig 7.2.4 | n/a | Replace generic machine-renderer field and schema metadata once OrthoConfig 7.2.4 ships the reusable contract. | n/a | 2026-06-14 | +| [15.3.5](roadmap.md#15-sempai-selector-to-context-slice) | Implement actuation handoff contract using focus-first selection. | ~ wraps | OrthoConfig 7.2.7 | n/a | Replace generic selector handoff provenance once OrthoConfig capability/provenance metadata can carry downstream mutation inputs. | n/a | 2026-06-14 | +| [15.3.6](roadmap.md#15-sempai-selector-to-context-slice) | Add diagnostics conformance suites for Sempai error categories. | ~ wraps | OrthoConfig 7.2.5, OrthoConfig 8.1 | n/a | Replace generic structured-error conformance once OrthoConfig reference-CLI and renderer gates cover the shared error contract. | n/a | 2026-06-14 | + +## Phase 16 + +| Roadmap task | Gist | State | Upstream OrthoConfig task | Shipped in | Removal gate or divergence | Next review by | Last reviewed | +| ---------------------------------------------- | ------------------------------------------------------------------- | ------- | ---------------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------ | -------------- | ------------- | +| [16.1.1](roadmap.md#16-safe-change-loop-slice) | Implement weaver patches apply. | ~ wraps | OrthoConfig 6.1, OrthoConfig 7.2.1 | n/a | Replace generic mutation command and preview metadata once OrthoConfig 6.1 and 7.2.1 ship reusable mutation contracts. | n/a | 2026-06-14 | +| [16.1.2](roadmap.md#16-safe-change-loop-slice) | Add idempotency keys, transaction IDs, and retry matching. | ~ wraps | OrthoConfig 7.2.1 | n/a | Replace generic idempotency and retry metadata once OrthoConfig 7.2.1 ships mutation behavioural metadata. | n/a | 2026-06-14 | +| [16.1.3](roadmap.md#16-safe-change-loop-slice) | Standardize mutation dry-run, force, and safety metadata. | ~ wraps | OrthoConfig 7.2.1 | n/a | Replace local mutation flag and safety metadata once OrthoConfig 7.2.1 ships the reusable mutation policy contract. | n/a | 2026-06-14 | +| [16.2.1](roadmap.md#16-safe-change-loop-slice) | Implement weaver symbols rename for position references. | ~ wraps | OrthoConfig 6.1, OrthoConfig 7.2.7 | n/a | Replace generic command and capability/provenance metadata once OrthoConfig can express symbols rename. | n/a | 2026-06-14 | +| [16.2.2](roadmap.md#16-safe-change-loop-slice) | Add direct Sempai selector support to symbols rename. | ~ wraps | OrthoConfig 7.2.6 | n/a | Replace generic ambiguous-mutation and enumerating-error metadata once OrthoConfig 7.2.6 ships the reusable contract. | n/a | 2026-06-14 | +| [16.2.3](roadmap.md#16-safe-change-loop-slice) | Add from-stdin selector stream consumption to mutation commands. | ~ wraps | OrthoConfig 7.2.4 | n/a | Replace generic stream input and JSON renderer metadata once OrthoConfig 7.2.4 ships reusable machine contracts. | n/a | 2026-06-14 | +| [16.3.3](roadmap.md#16-safe-change-loop-slice) | Add symbols move command contract and discovery output. | ~ wraps | OrthoConfig 7.2.7 | n/a | Replace generic command discovery and capability/provenance metadata once OrthoConfig 7.2.7 can express symbols move and extricate-symbol. | n/a | 2026-06-14 | +| [16.3.5](roadmap.md#16-safe-change-loop-slice) | Extend refusal diagnostics and rollback guarantees for extrication. | ~ wraps | OrthoConfig 7.2.5 | n/a | Replace generic refusal diagnostic and error-code metadata once OrthoConfig structured-error contracts cover the shared surface. | n/a | 2026-06-14 | + +## Phase 17 + +| Roadmap task | Gist | State | Upstream OrthoConfig task | Shipped in | Removal gate or divergence | Next review by | Last reviewed | +| ------------------------------------------------ | --------------------------------------------------------------------- | ------- | ---------------------------------- | ---------- | --------------------------------------------------------------------------------------------------------------- | -------------- | ------------- | +| [17.1.5](roadmap.md#17-impact-and-history-slice) | Implement budgeted traversal and graph-slice command integration. | ~ wraps | OrthoConfig 6.1, OrthoConfig 7.2.6 | n/a | Replace generic command and bounded-output metadata once OrthoConfig can express graph-slices get. | n/a | 2026-06-14 | +| [17.2.2](roadmap.md#17-impact-and-history-slice) | Implement slice reconstruction per commit with data-quality metadata. | ~ wraps | OrthoConfig 7.2.4 | n/a | Replace generic machine-output field metadata once OrthoConfig renderer contracts cover history slice payloads. | n/a | 2026-06-14 | + +## Phase 18 + +| Roadmap task | Gist | State | Upstream OrthoConfig task | Shipped in | Removal gate or divergence | Next review by | Last reviewed | +| ------------------------------------------------ | ---------------------------------------------------------------- | ------- | ------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------------------- | -------------- | ------------- | +| [18.2.1](roadmap.md#18-provider-ecosystem-slice) | Wire provider summaries into capabilities list and context JSON. | ~ wraps | OrthoConfig 7.2.7 | n/a | Replace local provider summary envelope metadata once OrthoConfig 7.2.7 ships reusable capability/provenance metadata. | n/a | 2026-06-14 | + +## Phase 19 + +| Roadmap task | Gist | State | Upstream OrthoConfig task | Shipped in | Removal gate or divergence | Next review by | Last reviewed | +| ---------------------------------------------------------- | ----------------------------------------------------------------- | --------- | ---------------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------- | -------------- | ------------- | +| [19.1.1](roadmap.md#19-agent-workflow-and-assurance-slice) | Implement profile storage, redaction, and root profile selection. | ? pending | OrthoConfig 9.1 | n/a | n/a | 2026-12-31 | 2026-06-14 | +| [19.1.2](roadmap.md#19-agent-workflow-and-assurance-slice) | Implement durable job ledger support. | ? pending | OrthoConfig 9.3 | n/a | n/a | 2026-12-31 | 2026-06-14 | +| [19.1.3](roadmap.md#19-agent-workflow-and-assurance-slice) | Implement wait, jobs, and delivery sinks. | ? pending | OrthoConfig 9.2.1, OrthoConfig 9.3 | n/a | n/a | 2026-12-31 | 2026-06-14 | +| [19.1.4](roadmap.md#19-agent-workflow-and-assurance-slice) | Implement feedback create, list, and send. | ? pending | OrthoConfig 9.2.2 | n/a | n/a | 2026-12-31 | 2026-06-14 | +| [19.2.2](roadmap.md#19-agent-workflow-and-assurance-slice) | Implement explicit interactive review as an opt-in workflow. | ~ wraps | OrthoConfig 7.2.1 | n/a | Replace generic non-interactive and mutation-policy metadata once OrthoConfig 7.2.1 ships reusable interaction contracts. | n/a | 2026-06-14 | + +## Phase 20 + +| Roadmap task | Gist | State | Upstream OrthoConfig task | Shipped in | Removal gate or divergence | Next review by | Last reviewed | +| -------------------------------------------------------------------------- | ------------------------------------------------------------------------- | --------- | ------------------------- | ---------- | -------------------------- | -------------- | ------------- | +| [20.1.1](roadmap.md#20-deferred-extensions-after-the-core-product-promise) | Decide whether to generate MCP descriptions from context JSON. | ? pending | OrthoConfig 10.1.1 | n/a | n/a | 2026-12-31 | 2026-06-14 | +| [20.1.2](roadmap.md#20-deferred-extensions-after-the-core-product-promise) | Decide whether SDK or OpenAPI-shaped runtime explorers are in scope. | ? pending | OrthoConfig 10.1.2 | n/a | n/a | 2026-12-31 | 2026-06-14 | +| [20.3.3](roadmap.md#20-deferred-extensions-after-the-core-product-promise) | Decide whether weaver daemon status JSON belongs in the command contract. | ? pending | OrthoConfig 6.2.3 | n/a | n/a | 2026-12-31 | 2026-06-14 | + diff --git a/docs/orthoconfig-consumer-boundary.toml b/docs/orthoconfig-consumer-boundary.toml new file mode 100644 index 00000000..a253a816 --- /dev/null +++ b/docs/orthoconfig-consumer-boundary.toml @@ -0,0 +1,622 @@ +schema_version = 1 + +managed_tasks = [ + "12.1.1", "12.1.2", "12.1.3", "12.1.4", "12.1.5", + "13.1.1", "13.1.2", "13.1.3", "13.2.1", "13.2.2", "13.2.3", + "13.3.1", "13.3.2", "13.3.3", "13.3.4", + "14.1.1", "14.1.2", "14.1.3", "14.1.4", "14.2.1", "14.2.2", + "14.2.3", "14.3.1", "14.3.2", + "15.1.1", "15.1.2", "15.3.2", "15.3.3", "15.3.5", "15.3.6", + "16.1.1", "16.1.2", "16.1.3", "16.2.1", "16.2.2", "16.2.3", + "16.3.3", "16.3.5", + "17.1.5", "17.2.2", + "18.2.1", + "19.1.1", "19.1.2", "19.1.3", "19.1.4", "19.2.2", + "20.1.1", "20.1.2", "20.3.3", +] + +[[task]] +id = "12.1.1" +gist = "Track the downstream consumer boundary." +state = "consumes" +upstream = [{ task = "OrthoConfig 5.2.3 / design §2.1", role = "boundary" }] +shipped_in = "4339a6f3c61dc4fed86493d99ffb05230bee2a1b" +removal_gate = "" +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "12.1.2" +gist = "Consume recursive command metadata." +state = "wraps" +upstream = [{ task = "OrthoConfig 6.1", role = "metadata" }] +shipped_in = "" +removal_gate = "Replace local recursive command metadata once OrthoConfig 6.1 ships command and subcommand records that can drive help, manpages, completions, and context output." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "12.1.3" +gist = "Consume compact context and skill metadata." +state = "wraps" +upstream = [ + { task = "OrthoConfig 6.2", role = "metadata" }, + { task = "OrthoConfig 6.3", role = "metadata" }, +] +shipped_in = "" +removal_gate = "Replace Weaver-local context and skill metadata once OrthoConfig 6.2 and 6.3 ship reusable context and skill shapes that Weaver can extend." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "12.1.4" +gist = "Consume canonical vocabulary and behavioural metadata." +state = "wraps" +upstream = [ + { task = "OrthoConfig 7.1", role = "vocabulary" }, + { task = "OrthoConfig 7.2", role = "renderer" }, + { task = "OrthoConfig 8.1", role = "renderer" }, +] +shipped_in = "" +removal_gate = "Replace Weaver-local vocabulary, renderer, JSON, exit-code, bounded-list, mutation, and provenance checks once OrthoConfig 7.1, 7.2, and 8.1 ship those contracts." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "12.1.5" +gist = "Consume compounding primitive contracts." +state = "pending" +upstream = [ + { task = "OrthoConfig 9.1", role = "profile" }, + { task = "OrthoConfig 9.2.1", role = "delivery" }, + { task = "OrthoConfig 9.2.2", role = "feedback" }, + { task = "OrthoConfig 9.3", role = "execution_ledger" }, +] +shipped_in = "" +removal_gate = "" +adr_anchor = "" +next_review_by = "2026-12-31" +last_reviewed = "2026-06-14" + +[[task]] +id = "13.1.1" +gist = "Record the agent-native command-surface reset as ADR 007." +state = "divergent" +upstream = [{ task = "OrthoConfig 5.2.3", role = "boundary" }] +shipped_in = "" +removal_gate = "" +adr_anchor = "decision-outcome" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "13.1.2" +gist = "Implement the Weaver command-surface adapter for one read-only command family." +state = "wraps" +upstream = [ + { task = "OrthoConfig 5.2.3", role = "boundary" }, + { task = "OrthoConfig 6.1", role = "metadata" }, + { task = "OrthoConfig 7.2.7", role = "capability_provenance" }, +] +shipped_in = "" +removal_gate = "Replace CommandSurfaceRecord once OrthoConfig 6.1 and 7.2.7 ship recursive command and capability/provenance metadata for Weaver resource paths." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "13.1.3" +gist = "Define the temporary-adapter removal policy." +state = "wraps" +upstream = [ + { task = "OrthoConfig 6.1", role = "metadata" }, + { task = "OrthoConfig 7.2.7", role = "capability_provenance" }, +] +shipped_in = "" +removal_gate = "Retire local generic helpers once their named OrthoConfig replacements are available, unless ADR 007 records a permanent divergence." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "13.2.1" +gist = "Implement the localized human renderer for definitions get." +state = "wraps" +upstream = [{ task = "OrthoConfig 7.2.2", role = "renderer" }] +shipped_in = "" +removal_gate = "Replace Weaver-local human renderer metadata once OrthoConfig 7.2.2 ships reusable human-renderer controls and terminal behaviour metadata." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "13.2.2" +gist = "Implement universal JSON and structured errors for definitions get." +state = "wraps" +upstream = [ + { task = "OrthoConfig 7.2.3", role = "renderer" }, + { task = "OrthoConfig 7.2.4", role = "renderer" }, + { task = "OrthoConfig 7.2.5", role = "renderer" }, + { task = "OrthoConfig 8.1", role = "renderer" }, +] +shipped_in = "" +removal_gate = "Replace Weaver-local JSON, stderr error, and exit-class definitions once OrthoConfig 7.2.3 through 7.2.5 and 8.1 ship stable renderer contracts." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "13.2.3" +gist = "Implement enumerating errors and bounded responses for the pilot." +state = "wraps" +upstream = [{ task = "OrthoConfig 7.2.6", role = "renderer" }] +shipped_in = "" +removal_gate = "Replace local bounded-list and enumerating-error metadata once OrthoConfig 7.2.6 ships the reusable contract." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "13.3.1" +gist = "Implement weaver context JSON for the pilot command family." +state = "wraps" +upstream = [{ task = "OrthoConfig 6.2", role = "metadata" }] +shipped_in = "" +removal_gate = "Replace local context payload metadata once OrthoConfig 6.2 ships compact agent-context generation and schema stability." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "13.3.2" +gist = "Implement capabilities list JSON from runtime provider state." +state = "wraps" +upstream = [{ task = "OrthoConfig 7.2.7", role = "capability_provenance" }] +shipped_in = "" +removal_gate = "Replace local capability/provenance envelope metadata once OrthoConfig 7.2.7 ships the reusable capability contract." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "13.3.3" +gist = "Generate help, manpage input, completions, and skill paths." +state = "wraps" +upstream = [ + { task = "OrthoConfig 6.3", role = "metadata" }, + { task = "OrthoConfig 8.1", role = "renderer" }, +] +shipped_in = "" +removal_gate = "Replace local generated-reference metadata once OrthoConfig 6.3 and 8.1 ship skill and reference-CLI contracts." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "13.3.4" +gist = "Add command-surface drift gates for the pilot." +state = "wraps" +upstream = [ + { task = "OrthoConfig 6.1", role = "metadata" }, + { task = "OrthoConfig 7.1", role = "vocabulary" }, + { task = "OrthoConfig 8.1", role = "renderer" }, +] +shipped_in = "" +removal_gate = "Replace local drift checks for generic command metadata, vocabulary, and renderer surfaces once OrthoConfig ships reusable policy gates." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "14.1.1" +gist = "Implement weaver definitions get." +state = "wraps" +upstream = [ + { task = "OrthoConfig 6.1", role = "metadata" }, + { task = "OrthoConfig 7.2", role = "renderer" }, +] +shipped_in = "" +removal_gate = "Replace generic command and renderer metadata for definitions get once OrthoConfig 6.1 and 7.2 can express the resource command." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "14.1.2" +gist = "Implement weaver references list." +state = "wraps" +upstream = [ + { task = "OrthoConfig 6.1", role = "metadata" }, + { task = "OrthoConfig 7.2.6", role = "renderer" }, +] +shipped_in = "" +removal_gate = "Replace generic command and bounded-list metadata for references list once OrthoConfig 6.1 and 7.2.6 ship the reusable contracts." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "14.1.3" +gist = "Implement weaver diagnostics list." +state = "wraps" +upstream = [ + { task = "OrthoConfig 6.1", role = "metadata" }, + { task = "OrthoConfig 7.2.5", role = "renderer" }, +] +shipped_in = "" +removal_gate = "Replace generic command and structured-error metadata for diagnostics list once OrthoConfig ships the reusable contracts." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "14.1.4" +gist = "Add combinatorial read-command end-to-end coverage." +state = "wraps" +upstream = [ + { task = "OrthoConfig 7.2", role = "renderer" }, + { task = "OrthoConfig 8.1", role = "renderer" }, +] +shipped_in = "" +removal_gate = "Retire local generic renderer assertions once OrthoConfig reference-CLI and renderer conformance gates cover the shared contract." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "14.2.1" +gist = "Implement weaver cards get for position references." +state = "wraps" +upstream = [ + { task = "OrthoConfig 6.1", role = "metadata" }, + { task = "OrthoConfig 7.2", role = "renderer" }, +] +shipped_in = "" +removal_gate = "Replace generic command, JSON, and human-renderer metadata for cards get once OrthoConfig can express the resource command." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "14.2.2" +gist = "Add qualified symbol selectors to cards get." +state = "wraps" +upstream = [{ task = "OrthoConfig 7.2.6", role = "renderer" }] +shipped_in = "" +removal_gate = "Replace generic enumerating-error metadata for ambiguous selectors once OrthoConfig 7.2.6 ships the reusable contract." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "14.2.3" +gist = "Add one-hop relation summaries to cards." +state = "wraps" +upstream = [{ task = "OrthoConfig 7.2.6", role = "renderer" }] +shipped_in = "" +removal_gate = "Replace generic bounded-output metadata for relation summaries once OrthoConfig 7.2.6 ships the reusable contract." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "14.3.1" +gist = "Prototype symbols list pattern search over weaver-syntax and optional srgn." +state = "pending" +upstream = [ + { task = "OrthoConfig 6.1", role = "metadata" }, + { task = "OrthoConfig 7.1", role = "vocabulary" }, +] +shipped_in = "" +removal_gate = "" +adr_anchor = "" +next_review_by = "2026-12-31" +last_reviewed = "2026-06-14" + +[[task]] +id = "14.3.2" +gist = "Decide whether the static-search pilot graduates." +state = "pending" +upstream = [{ task = "OrthoConfig 7.1", role = "vocabulary" }] +shipped_in = "" +removal_gate = "" +adr_anchor = "" +next_review_by = "2026-12-31" +last_reviewed = "2026-06-14" + +[[task]] +id = "15.1.1" +gist = "Implement one-liner tokenization and Pratt parsing for positive symbol patterns." +state = "wraps" +upstream = [{ task = "OrthoConfig 7.2.5", role = "renderer" }] +shipped_in = "" +removal_gate = "Replace generic diagnostic envelope and error-class metadata once OrthoConfig structured-error contracts are available." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "15.1.2" +gist = "Define selector record schemas for one-liner matches." +state = "wraps" +upstream = [{ task = "OrthoConfig 7.2.7", role = "capability_provenance" }] +shipped_in = "" +removal_gate = "Replace generic selector provenance fields once OrthoConfig capability/provenance metadata can carry them." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "15.3.2" +gist = "Add weaver symbols list query inputs." +state = "wraps" +upstream = [ + { task = "OrthoConfig 6.1", role = "metadata" }, + { task = "OrthoConfig 7.2.5", role = "renderer" }, +] +shipped_in = "" +removal_gate = "Replace generic command, input-combination, and error metadata once OrthoConfig can express the symbols list query contract." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "15.3.3" +gist = "Define stable JSONL request and response schemas for Sempai query operations." +state = "wraps" +upstream = [{ task = "OrthoConfig 7.2.4", role = "renderer" }] +shipped_in = "" +removal_gate = "Replace generic machine-renderer field and schema metadata once OrthoConfig 7.2.4 ships the reusable contract." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "15.3.5" +gist = "Implement actuation handoff contract using focus-first selection." +state = "wraps" +upstream = [{ task = "OrthoConfig 7.2.7", role = "capability_provenance" }] +shipped_in = "" +removal_gate = "Replace generic selector handoff provenance once OrthoConfig capability/provenance metadata can carry downstream mutation inputs." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "15.3.6" +gist = "Add diagnostics conformance suites for Sempai error categories." +state = "wraps" +upstream = [ + { task = "OrthoConfig 7.2.5", role = "renderer" }, + { task = "OrthoConfig 8.1", role = "renderer" }, +] +shipped_in = "" +removal_gate = "Replace generic structured-error conformance once OrthoConfig reference-CLI and renderer gates cover the shared error contract." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "16.1.1" +gist = "Implement weaver patches apply." +state = "wraps" +upstream = [ + { task = "OrthoConfig 6.1", role = "metadata" }, + { task = "OrthoConfig 7.2.1", role = "renderer" }, +] +shipped_in = "" +removal_gate = "Replace generic mutation command and preview metadata once OrthoConfig 6.1 and 7.2.1 ship reusable mutation contracts." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "16.1.2" +gist = "Add idempotency keys, transaction IDs, and retry matching." +state = "wraps" +upstream = [{ task = "OrthoConfig 7.2.1", role = "renderer" }] +shipped_in = "" +removal_gate = "Replace generic idempotency and retry metadata once OrthoConfig 7.2.1 ships mutation behavioural metadata." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "16.1.3" +gist = "Standardize mutation dry-run, force, and safety metadata." +state = "wraps" +upstream = [{ task = "OrthoConfig 7.2.1", role = "renderer" }] +shipped_in = "" +removal_gate = "Replace local mutation flag and safety metadata once OrthoConfig 7.2.1 ships the reusable mutation policy contract." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "16.2.1" +gist = "Implement weaver symbols rename for position references." +state = "wraps" +upstream = [ + { task = "OrthoConfig 6.1", role = "metadata" }, + { task = "OrthoConfig 7.2.7", role = "capability_provenance" }, +] +shipped_in = "" +removal_gate = "Replace generic command and capability/provenance metadata once OrthoConfig can express symbols rename." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "16.2.2" +gist = "Add direct Sempai selector support to symbols rename." +state = "wraps" +upstream = [{ task = "OrthoConfig 7.2.6", role = "renderer" }] +shipped_in = "" +removal_gate = "Replace generic ambiguous-mutation and enumerating-error metadata once OrthoConfig 7.2.6 ships the reusable contract." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "16.2.3" +gist = "Add from-stdin selector stream consumption to mutation commands." +state = "wraps" +upstream = [{ task = "OrthoConfig 7.2.4", role = "renderer" }] +shipped_in = "" +removal_gate = "Replace generic stream input and JSON renderer metadata once OrthoConfig 7.2.4 ships reusable machine contracts." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "16.3.3" +gist = "Add symbols move command contract and discovery output." +state = "wraps" +upstream = [{ task = "OrthoConfig 7.2.7", role = "capability_provenance" }] +shipped_in = "" +removal_gate = "Replace generic command discovery and capability/provenance metadata once OrthoConfig 7.2.7 can express symbols move and extricate-symbol." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "16.3.5" +gist = "Extend refusal diagnostics and rollback guarantees for extrication." +state = "wraps" +upstream = [{ task = "OrthoConfig 7.2.5", role = "renderer" }] +shipped_in = "" +removal_gate = "Replace generic refusal diagnostic and error-code metadata once OrthoConfig structured-error contracts cover the shared surface." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "17.1.5" +gist = "Implement budgeted traversal and graph-slice command integration." +state = "wraps" +upstream = [ + { task = "OrthoConfig 6.1", role = "metadata" }, + { task = "OrthoConfig 7.2.6", role = "renderer" }, +] +shipped_in = "" +removal_gate = "Replace generic command and bounded-output metadata once OrthoConfig can express graph-slices get." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "17.2.2" +gist = "Implement slice reconstruction per commit with data-quality metadata." +state = "wraps" +upstream = [{ task = "OrthoConfig 7.2.4", role = "renderer" }] +shipped_in = "" +removal_gate = "Replace generic machine-output field metadata once OrthoConfig renderer contracts cover history slice payloads." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "18.2.1" +gist = "Wire provider summaries into capabilities list and context JSON." +state = "wraps" +upstream = [{ task = "OrthoConfig 7.2.7", role = "capability_provenance" }] +shipped_in = "" +removal_gate = "Replace local provider summary envelope metadata once OrthoConfig 7.2.7 ships reusable capability/provenance metadata." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "19.1.1" +gist = "Implement profile storage, redaction, and root profile selection." +state = "pending" +upstream = [{ task = "OrthoConfig 9.1", role = "profile" }] +shipped_in = "" +removal_gate = "" +adr_anchor = "" +next_review_by = "2026-12-31" +last_reviewed = "2026-06-14" + +[[task]] +id = "19.1.2" +gist = "Implement durable job ledger support." +state = "pending" +upstream = [{ task = "OrthoConfig 9.3", role = "execution_ledger" }] +shipped_in = "" +removal_gate = "" +adr_anchor = "" +next_review_by = "2026-12-31" +last_reviewed = "2026-06-14" + +[[task]] +id = "19.1.3" +gist = "Implement wait, jobs, and delivery sinks." +state = "pending" +upstream = [ + { task = "OrthoConfig 9.2.1", role = "delivery" }, + { task = "OrthoConfig 9.3", role = "execution_ledger" }, +] +shipped_in = "" +removal_gate = "" +adr_anchor = "" +next_review_by = "2026-12-31" +last_reviewed = "2026-06-14" + +[[task]] +id = "19.1.4" +gist = "Implement feedback create, list, and send." +state = "pending" +upstream = [{ task = "OrthoConfig 9.2.2", role = "feedback" }] +shipped_in = "" +removal_gate = "" +adr_anchor = "" +next_review_by = "2026-12-31" +last_reviewed = "2026-06-14" + +[[task]] +id = "19.2.2" +gist = "Implement explicit interactive review as an opt-in workflow." +state = "wraps" +upstream = [{ task = "OrthoConfig 7.2.1", role = "renderer" }] +shipped_in = "" +removal_gate = "Replace generic non-interactive and mutation-policy metadata once OrthoConfig 7.2.1 ships reusable interaction contracts." +adr_anchor = "" +next_review_by = "" +last_reviewed = "2026-06-14" + +[[task]] +id = "20.1.1" +gist = "Decide whether to generate MCP descriptions from context JSON." +state = "pending" +upstream = [{ task = "OrthoConfig 10.1.1", role = "metadata" }] +shipped_in = "" +removal_gate = "" +adr_anchor = "" +next_review_by = "2026-12-31" +last_reviewed = "2026-06-14" + +[[task]] +id = "20.1.2" +gist = "Decide whether SDK or OpenAPI-shaped runtime explorers are in scope." +state = "pending" +upstream = [{ task = "OrthoConfig 10.1.2", role = "metadata" }] +shipped_in = "" +removal_gate = "" +adr_anchor = "" +next_review_by = "2026-12-31" +last_reviewed = "2026-06-14" + +[[task]] +id = "20.3.3" +gist = "Decide whether weaver daemon status JSON belongs in the command contract." +state = "pending" +upstream = [{ task = "OrthoConfig 6.2.3", role = "metadata" }] +shipped_in = "" +removal_gate = "" +adr_anchor = "" +next_review_by = "2026-12-31" +last_reviewed = "2026-06-14" diff --git a/docs/roadmap.md b/docs/roadmap.md index 9b72cd5f..a75d3ecd 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -40,6 +40,8 @@ from rediscovering the same dependency and migration questions. This step answers which generic command-contract pieces come from OrthoConfig and which temporary Weaver adapters are allowed. Its outcome informs every command-surface and renderer task. See ADR 007 and the OrthoConfig roadmap. +Boundary classifications for this step are tracked in the +[OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md). - [ ] 12.1.1. Track the downstream consumer boundary. - Depends on OrthoConfig 5.2.3. @@ -106,7 +108,9 @@ introspection, and agent-grade CLI hardening into one acceptance surface. This step answers whether Weaver-specific semantic metadata can sit on top of OrthoConfig command contracts without duplicating them. See ADR 007 and -`docs/weaver-design.md` §§2.1.1-2.1.4. +`docs/weaver-design.md` §§2.1.1-2.1.4. Boundary classifications for these tasks +are tracked in the +[OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md). - [x] 13.1.1. Record the agent-native command-surface reset as ADR 007. - Records the forward OrthoConfig dependency boundary that 12.1 validates. @@ -131,7 +135,8 @@ OrthoConfig command contracts without duplicating them. See ADR 007 and This step answers whether the same command contract can serve humans and agents without forking command behaviour. It migrates prototype archive work 3.2.2 through 3.3.4 and 11.3.1 through 11.3.4. See `docs/weaver-design.md` §§2.1.3, -2.1.7, 2.1.10, and 2.1.11. +2.1.7, 2.1.10, and 2.1.11. Boundary classifications for these tasks are tracked +in the [OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md). - [ ] 13.2.1. Implement the localized human renderer for `definitions get`. - Requires 13.1.2 and depends on OrthoConfig 7.2.2. @@ -158,7 +163,9 @@ through 3.3.4 and 11.3.1 through 11.3.4. See `docs/weaver-design.md` §§2.1.3, This step answers whether humans and agents can discover the command contract from generated surfaces instead of hard-coded catalogues. It migrates prototype archive work 3.2.3 through 3.2.6, 5.7.1 through 5.7.5, and 11.3.2. See -`docs/weaver-design.md` §§2.1.4 and 6.1. +`docs/weaver-design.md` §§2.1.4 and 6.1. Boundary classifications for these +tasks are tracked in the +[OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md). - [ ] 13.3.1. Implement `weaver context --json` for the pilot command family. - Requires 13.2.3 and depends on OrthoConfig 6.2.1 through 6.2.3. @@ -242,6 +249,8 @@ cards-first context, same-file graph slices, and agent-grade compact output. This step answers whether existing semantic backends fit the resource-first surface without provider-specific commands. It migrates prototype archive work 10.1.1 through 10.3.2. See `docs/weaver-design.md` §§2.2, 3.1, and 6.1. +Boundary classifications for these tasks are tracked in the +[OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md). - [ ] 14.1.1. Implement `weaver definitions get`. - Requires phase 13. @@ -266,7 +275,9 @@ surface without provider-specific commands. It migrates prototype archive work This step answers whether compact symbol cards are enough to guide a user or agent to the next useful read. It migrates prototype archive work 7.1.1 through 7.1.4, 9.2.1 through 9.2.3, and 10.2.1 through 10.2.2. See -`docs/jacquard-card-first-symbol-graph-design.md` §§5-11. +`docs/jacquard-card-first-symbol-graph-design.md` §§5-11. Boundary +classifications for these tasks are tracked in the +[OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md). - [ ] 14.2.1. Implement `weaver cards get` for position references. - Requires 14.1.1 and reuses prototype archive work 7.1.1 through 7.1.4. @@ -286,6 +297,8 @@ agent to the next useful read. It migrates prototype archive work 7.1.1 through This step answers whether structural grep should graduate now or wait for the Sempai selector slice. It migrates the product intent of prototype archive work 10.4.1 through 10.4.2 and 5.5.1 without forcing provider-specific commands. +Boundary classifications for these tasks are tracked in the +[OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md). - [ ] 14.3.1. Prototype `weaver symbols list --pattern` over `weaver-syntax` and optional `srgn`. @@ -315,7 +328,9 @@ cards, and the Sempai-to-Jacquard vertical slice. This step answers whether the target one-liner grammar can select real symbols without overbuilding the full query engine. It migrates prototype archive work 4.1.6 through 4.1.7, 4.3.3, and 9.1.1. See -`docs/sempai-query-language-design.md` §§3-6. +`docs/sempai-query-language-design.md` §§3-6. Boundary classifications for +these tasks are tracked in the +[OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md). - [ ] 15.1.1. Implement one-liner tokenization and Pratt parsing for positive symbol patterns. @@ -407,7 +422,9 @@ This step answers whether the backend can be exposed through Weaver's resource-first command surface with stable schemas, cache behaviour, diagnostics, quality gates, and default-enablement rules. It preserves prototype archive work 4.3.1 through 4.3.9 under the new public command shape. -See `docs/weaver-design.md` §2.1.2. +See `docs/weaver-design.md` §2.1.2. Boundary classifications for these tasks +are tracked in the +[OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md). - [ ] 15.3.1. Add Sempai execution routing in `weaverd` for selector-backed `symbols list`. @@ -494,6 +511,8 @@ the symbol-relocation tasks below. This step answers whether the completed patch and Double-Lock foundations fit the resource-first grammar. It migrates prototype archive work 6.1.1 through 6.1.4 and 11.4.1 through 11.4.2. See `docs/weaver-design.md` §§4.2-4.3. +Boundary classifications for these tasks are tracked in the +[OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md). - [ ] 16.1.1. Implement `weaver patches apply`. - Requires phase 13 and reuses prototype archive work 6.1.1 through 6.1.4. @@ -516,6 +535,8 @@ the resource-first grammar. It migrates prototype archive work 6.1.1 through This step answers whether provider-hidden actuators can mutate safely from both direct references and Sempai streams. It migrates prototype archive work 5.2.1 through 5.2.6, 10.5.1 through 10.5.2, and 4.3.5. See ADR 001 and ADR 004. +Boundary classifications for these tasks are tracked in the +[OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md). - [ ] 16.2.1. Implement `weaver symbols rename` for position references. - Requires 16.1.3 and reuses prototype archive work 5.2.1 through 5.2.5. @@ -656,6 +677,8 @@ This step answers whether graph traversal gives enough extra value to justify its complexity. It preserves the completed prototype archive schema work 7.2.1 and migrates prototype archive work 7.2.2 through 7.2.5, 11.1.1, and 11.2.2. See `docs/jacquard-card-first-symbol-graph-design.md` §12.1 through §12.3. +Boundary classifications for these tasks are tracked in the +[OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md). - [ ] 17.1.1. Implement a two-pass Tree-sitter extraction pipeline for graph slices. @@ -694,7 +717,8 @@ and migrates prototype archive work 7.2.2 through 7.2.5, 11.1.1, and 11.2.2. See This step answers whether historical graph reconstruction is stable enough to support change-risk narratives. It migrates prototype archive work 7.3.1 through 7.3.5. See `docs/jacquard-card-first-symbol-graph-design.md` §13.1, -§13.2, and §22. +§13.2, and §22. Boundary classifications for these tasks are tracked in the +[OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md). - [ ] 17.2.1. Implement git-backed blob loading for historical revisions without checkout. @@ -852,7 +876,9 @@ prototype archive work 5.5.1, 5.6.1, and 5.8.1. See ADR 001, ADR 004, and ADR This step answers whether humans and agents can debug provider selection when needed without making provider names normal command syntax. It migrates prototype archive work 5.7.1 through 5.7.5 and 5.2.6. See -`docs/weaver-design.md` §6.1. +`docs/weaver-design.md` §6.1. Boundary classifications for these tasks are +tracked in the +[OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md). - [ ] 18.2.1. Wire provider summaries into `capabilities list` and `context --json`. @@ -886,7 +912,9 @@ formal verification, output delivery, feedback, profiles, and jobs. This step answers whether profiles, jobs, and delivery reduce repeated agent turns without making human usage worse. It migrates the product intent of ADR 007 compounding primitives and prototype archive work 6.2.1. See -`docs/weaver-design.md` §§2.1.5-2.1.6. +`docs/weaver-design.md` §§2.1.5-2.1.6. Boundary classifications for these tasks +are tracked in the +[OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md). - [ ] 19.1.1. Implement profile storage, redaction, and root `--profile`. - Requires 13.3.1 and depends on OrthoConfig 9.1. @@ -912,7 +940,9 @@ turns without making human usage worse. It migrates the product intent of ADR This step answers whether richer human workflows can exist without weakening the non-interactive agent contract. It migrates prototype archive work 6.2.1 -through 6.2.3. See `docs/weaver-design.md` §§5-6. +through 6.2.3. See `docs/weaver-design.md` §§5-6. Boundary classifications for +these tasks are tracked in the +[OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md). - [ ] 19.2.1. Recast project onboarding as a composition of resource-first commands. @@ -970,7 +1000,8 @@ the core Weaver promise. This step answers whether external integration surfaces are wrappers over the same command metadata or a distracting second product. See ADR 007 and -OrthoConfig 10.1. +OrthoConfig 10.1. Boundary classifications for these tasks are tracked in the +[OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md). - [ ] 20.1.1. Decide whether to generate MCP descriptions from `context --json`. @@ -1011,7 +1042,9 @@ This step answers whether optional observability surfaces have earned a new design after the local-first RFC 0001 contract exists. It keeps metrics, distributed tracing, retained diagnostics, and status expansion out of the core promise until their privacy, retention, endpoint, and command-latency costs are -explicit. See RFC 0001: +explicit. Boundary classifications for these tasks are tracked in the +[OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md). See +RFC 0001: - [Open questions](rfcs/0001-o11y.md#open-questions) - [Local request correlation](rfcs/0001-o11y.md#local-request-correlation) diff --git a/docs/users-guide.md b/docs/users-guide.md index 3f76612f..f73d7799 100644 --- a/docs/users-guide.md +++ b/docs/users-guide.md @@ -31,6 +31,14 @@ agent usage reliable: skill, and execution-ledger contracts depend on OrthoConfig where the OrthoConfig roadmap already owns the generic machinery. +The [OrthoConfig consumer boundary matrix](orthoconfig-consumer-boundary.md) +tracks which target command-contract tasks already consume OrthoConfig, which +ones use temporary Weaver wrappers, and which ones are pending upstream +OrthoConfig contracts. While those pending and wrapper rows remain open, users +may see Weaver-owned help, output, profile, delivery, feedback, or job-ledger +behaviour that is expected to converge on the named OrthoConfig contract before +the 0.1.0 compatibility promise is made. + Representative target commands look like this: ```sh