feat(arc-kit-au): retrofit SysmlBlock onto existing node types - #193
Merged
elasticdotventures merged 7 commits intoAug 23, 2026
Conversation
…ypes Applies the sysml-derive macro (feat/sysml-derive-spike, #183) to the 8 pre-existing arc-kit-au node structs that predate the systems-modeling epic: SourceDoc, ExtractedRow, Transaction, Classification, ModelProposal, OperatorApproval, ValidationIssue, WorkbookRow. This was the second of two explicitly-deferred follow-ons from task 3 (#184) — the first (HasVisualization/viz_manifest wiring for Requirement/Decision/Cost) landed as part of this same stack. The derive is purely syntactic (walks named fields via syn, stringifies each field's type via quote!) so it applies uniformly regardless of field type — no per-struct special-casing needed, confirmed by re-reading crates/sysml-derive/src/lib.rs before applying. Verified: cargo test -p sysml-derive (2 tests), cargo test -p arc-kit-au (46 tests, unchanged from pre-retrofit baseline), cargo check --workspace --all-features (clean, one pre-existing unrelated warning in ledgerr-mcp/src/fbar.rs), cargo clippy -p arc-kit-au --all-features (clean).
elasticdotventures
added a commit
that referenced
this pull request
Aug 22, 2026
Task 6 (ledgrrr#186's second commit) added import_requirement/ record_decision/record_cost to ledgerr_evidence's EVIDENCE_TOOL actions in contract.rs but never re-ran regen-docs, so the checked-in mcp-capability-contract.md drifted — caught by CI's check-drift step on downstream stacked PRs (#190, #193). Ran: cargo run -p ledgerr-mcp --bin regen-docs
…isualization' into feat/sysml-derive-retrofit-existing-nodes
elasticdotventures
added a commit
that referenced
this pull request
Aug 22, 2026
elasticdotventures
marked this pull request as ready for review
August 22, 2026 13:09
…isualization' into feat/sysml-derive-retrofit-existing-nodes
elasticdotventures
added a commit
that referenced
this pull request
Aug 22, 2026
…al SysML v2 grammar Same bug holon-viz's SysmlV2Emitter had (ledgrrr#197): SysML v1 called this construct Block/'block def'; SysML v2 renamed it to 'part def', and 'block' is not a SysML v2 keyword at all. Confirmed via the newly-wired ufo_types::sysml::validate_sysml_v2 (real sysml-v2-parser crate, not a hand-rolled heuristic) that the fixed output actually parses. Adds tests/real_grammar_validation.rs: runs the actual generated sysml_block_def() text for Transaction/Requirement/ExtractedRow/ ModelProposal/WorkbookRow (mirroring the real production structs from #184/#193) through the real parser. This replaces the 'no angle brackets' manual check used to validate the earlier DateTime/bool/usize scalar mapping fix with genuine grammar validation, closing out ledgrrr#195.
…isualization' into feat/sysml-derive-retrofit-existing-nodes
…isualization' into feat/sysml-derive-retrofit-existing-nodes
elasticdotventures
merged commit Aug 23, 2026
f464d5d
into
feat/requirement-decision-cost-visualization
13 checks passed
elasticdotventures
deleted the
feat/sysml-derive-retrofit-existing-nodes
branch
August 23, 2026 06:32
elasticdotventures
added a commit
that referenced
this pull request
Aug 23, 2026
…ision/Cost (#190) * feat(iso): HasVisualization + viz_manifest wiring for Requirement/Decision/Cost Adds dedicated SemanticType::{Requirement,Decision,Cost} variants (iso.rs) and HasVisualization impls for arc_kit_au::node::{Requirement, Decision,Cost} (iso_objects.rs, gated behind the arc-kit-au feature, matching ontology.rs's arc_kit_bridge precedent), all routed to ZLayer::SystemsModel (added in ledgrrr#185). Wires the 3 new types into xtask's export_viz_manifest (now 31 domain types, up from 28) and regenerates the checked-in viz-manifest.json. Updates pipeline_e2e.rs's EXPECTED_ENTRY_COUNT and representative-type assertions to match. Verified: cargo test -p ledger-core --lib (185 passed), cargo test -p ledgerr-mcp --test pipeline_e2e (manifest count test passes), cargo check --workspace --all-features clean. This closes out the one remaining gap from ledgrrr#185 (task 4 in docs/systems-modeling-registry-rescope.md's §6), left explicitly unfinished there pending this larger change. * feat(arc-kit-au): retrofit #[derive(SysmlBlock)] onto existing node types (#193) Applies the sysml-derive macro (feat/sysml-derive-spike, #183) to the 8 pre-existing arc-kit-au node structs that predate the systems-modeling epic: SourceDoc, ExtractedRow, Transaction, Classification, ModelProposal, OperatorApproval, ValidationIssue, WorkbookRow. This was the second of two explicitly-deferred follow-ons from task 3 (#184) — the first (HasVisualization/viz_manifest wiring for Requirement/Decision/Cost) landed as part of this same stack. The derive is purely syntactic (walks named fields via syn, stringifies each field's type via quote!) so it applies uniformly regardless of field type — no per-struct special-casing needed, confirmed by re-reading crates/sysml-derive/src/lib.rs before applying. Verified: cargo test -p sysml-derive (2 tests), cargo test -p arc-kit-au (46 tests, unchanged from pre-retrofit baseline), cargo check --workspace --all-features (clean, one pre-existing unrelated warning in ledgerr-mcp/src/fbar.rs), cargo clippy -p arc-kit-au --all-features (clean).
elasticdotventures
added a commit
that referenced
this pull request
Aug 23, 2026
* feat(reqif-mcp-spike): Rust MCP client for reqif-opa-mcp + Requirement converter
Spike per decision 6 (docs/systems-modeling-registry-rescope.md §5/§6
task 5): reqif-opa-mcp is wrapped over MCP, not ported to Rust;
arc-kit-au stays the canonical decision+cost ledger.
New crate reqif-mcp-spike:
- McpHttpClient: minimal blocking client for reqif-opa-mcp's Streamable-
HTTP MCP server (FastMCP 3.0.0b1, protocol 2024-11-05). Handles the
initialize handshake + mcp-session-id header, the mandatory
notifications/initialized follow-up, and tools/call, extracting the
JSON-RPC result out of the single-frame SSE response body.
- RequirementRecord: mirrors reqif-opa-mcp's requirement-record.schema.json
exactly (uid/key/subtypes/status/policy_baseline/rubrics/text/attrs).
- requirement_record_to_node(): converts a RequirementRecord into the
arc-kit-au Requirement struct from ledgrrr#184 (ArtifactKind::Requirement /
NodeType::Requirement). requirement_id<-uid, title<-key, rationale<-text,
source<-attrs.source_standard(+source_url) falling back to the policy
baseline id, status passed through, related_decisions always empty
(reqif-opa-mcp carries no decision links; those are created later in
arc-kit-au itself).
Verified live end-to-end against a real reqif-opa-mcp checkout
(uv sync --extra ingest-lite; uv run python -m reqif_mcp --http --port
8123) parsing both its own sample derived baselines,
samples/standards/derived/{nist_ssdf_dogfood,owasp_asvs_cwe}.reqif (4
and 7 requirements respectively), through reqif_parse -> reqif_query ->
requirement_record_to_node -> Requirement::node_id(), all producing
correct, deterministic req: NodeIds. That live run is captured as an
#[ignore]'d integration test (tests/live_server.rs) since it needs an
external repo checkout + Python/uv, not something CI or a fresh clone
has; re-run manually with REQIF_MCP_URL set to a running server.
cargo test -p reqif-mcp-spike: 5 unit tests pass, 1 ignored (live).
cargo check --workspace --all-features: clean. cargo clippy -p
reqif-mcp-spike --all-targets: clean.
* feat(ledgerr-mcp): wire Requirement/Decision/Cost into contract.rs (task 6)
- EvidenceArgs gains import_requirement/record_decision/record_cost
actions, each constructing the corresponding arc-kit-au node
(Requirement/Decision/Cost from ledgrrr#184) and inserting it into the
evidence graph via EvidenceGraph::add_node. DuplicateNode is treated as
idempotent success (content-hash dedup), matching the idempotent
semantics already established for EvidenceBuilder's ensure_* methods.
- parse_evidence_node_type gains requirement/req, decision/dec, cost
(plus previously-missing rnd_activity/tax_offset, same class of gap).
- Summary's node_counts and ListNodes' invalid-type error message
extended to include the 3 new types.
- EVIDENCE_TOOL's contract.rs action list and purpose string updated.
Verified: new tests/evidence_requirement_decision_cost.rs (3 tests,
covering import+list+detail+summary, record_decision+record_cost, and
idempotent re-import) all pass; cargo build -p ledgerr-mcp --features
legacy clean (1 pre-existing unrelated warning).
* docs: regenerate mcp-capability-contract.md (drift from task 6)
Task 6 (ledgrrr#186's second commit) added import_requirement/
record_decision/record_cost to ledgerr_evidence's EVIDENCE_TOOL actions
in contract.rs but never re-ran regen-docs, so the checked-in
mcp-capability-contract.md drifted — caught by CI's check-drift step
on downstream stacked PRs (#190, #193).
Ran: cargo run -p ledgerr-mcp --bin regen-docs
* docs: regenerate viz-manifest.json (stale version field, 1.9.0 -> 1.10.0)
Pre-existing drift, unrelated to Requirement/Decision/Cost content (28
objects, unchanged) -- the workspace version was bumped to 1.10.0 at
some point after this artifact was last regenerated. Only surfaced now
because check-drift's earlier mcp-capability-contract.md failure (fixed
in dd168f7) was masking this second, independent drift.
Ran: cargo run -p xtask-mcpb -- export-viz-manifest
* feat(iso): HasVisualization + viz_manifest wiring for Requirement/Decision/Cost (#190)
* feat(iso): HasVisualization + viz_manifest wiring for Requirement/Decision/Cost
Adds dedicated SemanticType::{Requirement,Decision,Cost} variants
(iso.rs) and HasVisualization impls for arc_kit_au::node::{Requirement,
Decision,Cost} (iso_objects.rs, gated behind the arc-kit-au feature,
matching ontology.rs's arc_kit_bridge precedent), all routed to
ZLayer::SystemsModel (added in ledgrrr#185).
Wires the 3 new types into xtask's export_viz_manifest (now 31 domain
types, up from 28) and regenerates the checked-in viz-manifest.json.
Updates pipeline_e2e.rs's EXPECTED_ENTRY_COUNT and representative-type
assertions to match.
Verified: cargo test -p ledger-core --lib (185 passed), cargo test -p
ledgerr-mcp --test pipeline_e2e (manifest count test passes), cargo
check --workspace --all-features clean.
This closes out the one remaining gap from ledgrrr#185 (task 4 in
docs/systems-modeling-registry-rescope.md's §6), left explicitly
unfinished there pending this larger change.
* feat(arc-kit-au): retrofit #[derive(SysmlBlock)] onto existing node types (#193)
Applies the sysml-derive macro (feat/sysml-derive-spike, #183) to the 8
pre-existing arc-kit-au node structs that predate the systems-modeling
epic: SourceDoc, ExtractedRow, Transaction, Classification,
ModelProposal, OperatorApproval, ValidationIssue, WorkbookRow.
This was the second of two explicitly-deferred follow-ons from task 3
(#184) — the first (HasVisualization/viz_manifest wiring for
Requirement/Decision/Cost) landed as part of this same stack. The
derive is purely syntactic (walks named fields via syn, stringifies
each field's type via quote!) so it applies uniformly regardless of
field type — no per-struct special-casing needed, confirmed by
re-reading crates/sysml-derive/src/lib.rs before applying.
Verified: cargo test -p sysml-derive (2 tests), cargo test -p
arc-kit-au (46 tests, unchanged from pre-retrofit baseline), cargo
check --workspace --all-features (clean, one pre-existing unrelated
warning in ledgerr-mcp/src/fbar.rs), cargo clippy -p arc-kit-au
--all-features (clean).
elasticdotventures
added a commit
that referenced
this pull request
Aug 23, 2026
* feat(iso): add dedicated ZLayer::SystemsModel variant Requirement/Decision/Cost content (ledgrrr#184) gets its own isometric layer rather than folding into the existing 6 or the still-unimplemented proposed Domain layer (docs/ontological-implementation-spec.md §6.1), per decision 2 in docs/systems-modeling-registry-rescope.md: independent toggle/color in the renderer over reusing an ontological-concepts layer. index=6, base_z=816.0 (continuing the existing 136.0 spacing), color #be185d (distinct from all 6 existing hexes). No HasVisualization impls wired yet for Requirement/Decision/Cost themselves — that requires also touching xtask's viz_manifest export + the checked-in viz-manifest.json per iso_objects.rs's own convention, tracked as a follow-on alongside task 6 (ledgerr-mcp/contract.rs wiring), not done here. * feat: spike reqif-opa-mcp over MCP + Requirement converter (#186) * feat(reqif-mcp-spike): Rust MCP client for reqif-opa-mcp + Requirement converter Spike per decision 6 (docs/systems-modeling-registry-rescope.md §5/§6 task 5): reqif-opa-mcp is wrapped over MCP, not ported to Rust; arc-kit-au stays the canonical decision+cost ledger. New crate reqif-mcp-spike: - McpHttpClient: minimal blocking client for reqif-opa-mcp's Streamable- HTTP MCP server (FastMCP 3.0.0b1, protocol 2024-11-05). Handles the initialize handshake + mcp-session-id header, the mandatory notifications/initialized follow-up, and tools/call, extracting the JSON-RPC result out of the single-frame SSE response body. - RequirementRecord: mirrors reqif-opa-mcp's requirement-record.schema.json exactly (uid/key/subtypes/status/policy_baseline/rubrics/text/attrs). - requirement_record_to_node(): converts a RequirementRecord into the arc-kit-au Requirement struct from ledgrrr#184 (ArtifactKind::Requirement / NodeType::Requirement). requirement_id<-uid, title<-key, rationale<-text, source<-attrs.source_standard(+source_url) falling back to the policy baseline id, status passed through, related_decisions always empty (reqif-opa-mcp carries no decision links; those are created later in arc-kit-au itself). Verified live end-to-end against a real reqif-opa-mcp checkout (uv sync --extra ingest-lite; uv run python -m reqif_mcp --http --port 8123) parsing both its own sample derived baselines, samples/standards/derived/{nist_ssdf_dogfood,owasp_asvs_cwe}.reqif (4 and 7 requirements respectively), through reqif_parse -> reqif_query -> requirement_record_to_node -> Requirement::node_id(), all producing correct, deterministic req: NodeIds. That live run is captured as an #[ignore]'d integration test (tests/live_server.rs) since it needs an external repo checkout + Python/uv, not something CI or a fresh clone has; re-run manually with REQIF_MCP_URL set to a running server. cargo test -p reqif-mcp-spike: 5 unit tests pass, 1 ignored (live). cargo check --workspace --all-features: clean. cargo clippy -p reqif-mcp-spike --all-targets: clean. * feat(ledgerr-mcp): wire Requirement/Decision/Cost into contract.rs (task 6) - EvidenceArgs gains import_requirement/record_decision/record_cost actions, each constructing the corresponding arc-kit-au node (Requirement/Decision/Cost from ledgrrr#184) and inserting it into the evidence graph via EvidenceGraph::add_node. DuplicateNode is treated as idempotent success (content-hash dedup), matching the idempotent semantics already established for EvidenceBuilder's ensure_* methods. - parse_evidence_node_type gains requirement/req, decision/dec, cost (plus previously-missing rnd_activity/tax_offset, same class of gap). - Summary's node_counts and ListNodes' invalid-type error message extended to include the 3 new types. - EVIDENCE_TOOL's contract.rs action list and purpose string updated. Verified: new tests/evidence_requirement_decision_cost.rs (3 tests, covering import+list+detail+summary, record_decision+record_cost, and idempotent re-import) all pass; cargo build -p ledgerr-mcp --features legacy clean (1 pre-existing unrelated warning). * docs: regenerate mcp-capability-contract.md (drift from task 6) Task 6 (ledgrrr#186's second commit) added import_requirement/ record_decision/record_cost to ledgerr_evidence's EVIDENCE_TOOL actions in contract.rs but never re-ran regen-docs, so the checked-in mcp-capability-contract.md drifted — caught by CI's check-drift step on downstream stacked PRs (#190, #193). Ran: cargo run -p ledgerr-mcp --bin regen-docs * docs: regenerate viz-manifest.json (stale version field, 1.9.0 -> 1.10.0) Pre-existing drift, unrelated to Requirement/Decision/Cost content (28 objects, unchanged) -- the workspace version was bumped to 1.10.0 at some point after this artifact was last regenerated. Only surfaced now because check-drift's earlier mcp-capability-contract.md failure (fixed in dd168f7) was masking this second, independent drift. Ran: cargo run -p xtask-mcpb -- export-viz-manifest * feat(iso): HasVisualization + viz_manifest wiring for Requirement/Decision/Cost (#190) * feat(iso): HasVisualization + viz_manifest wiring for Requirement/Decision/Cost Adds dedicated SemanticType::{Requirement,Decision,Cost} variants (iso.rs) and HasVisualization impls for arc_kit_au::node::{Requirement, Decision,Cost} (iso_objects.rs, gated behind the arc-kit-au feature, matching ontology.rs's arc_kit_bridge precedent), all routed to ZLayer::SystemsModel (added in ledgrrr#185). Wires the 3 new types into xtask's export_viz_manifest (now 31 domain types, up from 28) and regenerates the checked-in viz-manifest.json. Updates pipeline_e2e.rs's EXPECTED_ENTRY_COUNT and representative-type assertions to match. Verified: cargo test -p ledger-core --lib (185 passed), cargo test -p ledgerr-mcp --test pipeline_e2e (manifest count test passes), cargo check --workspace --all-features clean. This closes out the one remaining gap from ledgrrr#185 (task 4 in docs/systems-modeling-registry-rescope.md's §6), left explicitly unfinished there pending this larger change. * feat(arc-kit-au): retrofit #[derive(SysmlBlock)] onto existing node types (#193) Applies the sysml-derive macro (feat/sysml-derive-spike, #183) to the 8 pre-existing arc-kit-au node structs that predate the systems-modeling epic: SourceDoc, ExtractedRow, Transaction, Classification, ModelProposal, OperatorApproval, ValidationIssue, WorkbookRow. This was the second of two explicitly-deferred follow-ons from task 3 (#184) — the first (HasVisualization/viz_manifest wiring for Requirement/Decision/Cost) landed as part of this same stack. The derive is purely syntactic (walks named fields via syn, stringifies each field's type via quote!) so it applies uniformly regardless of field type — no per-struct special-casing needed, confirmed by re-reading crates/sysml-derive/src/lib.rs before applying. Verified: cargo test -p sysml-derive (2 tests), cargo test -p arc-kit-au (46 tests, unchanged from pre-retrofit baseline), cargo check --workspace --all-features (clean, one pre-existing unrelated warning in ledgerr-mcp/src/fbar.rs), cargo clippy -p arc-kit-au --all-features (clean).
elasticdotventures
added a commit
that referenced
this pull request
Aug 23, 2026
…sion/Cost (#184) * feat: widen ArtifactKind/NodeType/OperationKind with Requirement/Decision/Cost Task 3 from docs/systems-modeling-registry-rescope.md (epic part 2, ledgrrr#181), backed by sysml-derive (#183) per the resolved LinkML comparison (#3a). arc-kit-au: - NodeType gains Requirement/Decision/Cost variants (prefixes req/dec/cost) - New Requirement/Decision/Cost structs, following the existing Transaction/Classification pattern (content-hashed node_id()), each annotated with #[derive(SysmlBlock)] from sysml-derive - EvidenceNode gains matching variants; node_id()/node_type()/tx_id() updated (tx_id() -> None for all three, same as SourceDoc/ExtractedRow) - arc-kit-au now depends on sysml-derive ledger-core: - ArtifactKind gains matching variants + canonical_name() arms - arc_kit_bridge's From<ArtifactKind> for NodeType maps them explicitly (was previously falling through the _ => Unknown wildcard) - OperationKind gains RecordDecision/RecordCost/ImportRequirement, each with a corresponding LedgerOperation impl (content-hashed, idempotent, same shape as CheckTaxDeadlineOp) and wired into OperationDispatcher::from_scheduled_events ledgerr-mcp: - evidence_node_type_label() (behind the legacy feature) gets the 3 new NodeType arms it was missing Verified: cargo test -p arc-kit-au (46 tests), cargo test -p ledger-core --lib (184 tests), cargo build -p ledgerr-mcp --features legacy, and cargo check --workspace --all-features all pass. clippy clean on the touched files. Retrofitting existing variants (Transaction/TaxCategory/etc.) onto sysml-derive is a tracked follow-on, not done here, per the doc's own scoping. * fix(sysml-derive): map primitive scalars + DateTime to SysML ScalarValues DateTime<Utc> previously emitted the literal, invalid text `DateTime<Utc>` as a SysML v2 attribute type -- SysML v2's grammar has no angle-bracket generic-parameter syntax, so this would fail to parse under any conformant SysML v2 tool. bool/usize/etc. also passed through as bare Rust keywords with no corresponding SysML type. Map DateTime<_> -> ScalarValues::String, bool -> ScalarValues::Boolean, unsigned ints -> ScalarValues::Natural, signed ints -> ScalarValues::Integer, floats -> ScalarValues::Rational. Any other single-type-argument generic is now a compile error instead of a silent invalid-syntax emission. Opaque domain types (NodeId, Confidence, Decimal) still pass through as bare names -- documented as an intentional modeling assumption, not a bug. Adds regression tests for the field types introduced by #184/#193 (Decimal, Confidence, bool, usize, DateTime<Utc>) that basic.rs never exercised. Closes ledgrrr#195. * fix(holon-viz): emit valid SysML v2 (part def, not block def); wire real parser validation into ufo-types Ran SysmlV2Emitter's own output through the real sysml-v2-parser crate (docs/sysml-v2-parser-spike.md, an existing unmerged spike) and confirmed two bugs make it non-parseable: - The closing '}' was on the same line as a trailing '//' comment, so the comment swallowed it -- the block was never syntactically closed. - The emitter used SysML v1's 'block def' keyword. SysML v2 renamed this construct to 'part def'; 'block' is not a SysML v2 keyword at all. Fixed both. Added ufo_types::sysml -- a shared Constraint/Satisfies-based SysML v2 syntax validator wired to sysml-v2-parser (pinned to =0.54.0 per the spike's crate-health findings; not wasm32-compatible, so this must stay out of holon-viz's runtime dependency graph -- added to holon-viz only as a dev-dependency, used in a new round-trip test that feeds the emitter's own output through the real parser instead of just asserting on substrings. This is the concrete round-trip-closed signal the existing spike (PR #187) called out as the next step. * fix(sysml-derive): emit part def (not block def); validate against real SysML v2 grammar Same bug holon-viz's SysmlV2Emitter had (ledgrrr#197): SysML v1 called this construct Block/'block def'; SysML v2 renamed it to 'part def', and 'block' is not a SysML v2 keyword at all. Confirmed via the newly-wired ufo_types::sysml::validate_sysml_v2 (real sysml-v2-parser crate, not a hand-rolled heuristic) that the fixed output actually parses. Adds tests/real_grammar_validation.rs: runs the actual generated sysml_block_def() text for Transaction/Requirement/ExtractedRow/ ModelProposal/WorkbookRow (mirroring the real production structs from #184/#193) through the real parser. This replaces the 'no angle brackets' manual check used to validate the earlier DateTime/bool/usize scalar mapping fix with genuine grammar validation, closing out ledgrrr#195. * test(arc-kit-au): update block def -> part def assertion (sysml-derive fix) * chore: regenerate viz-manifest.json (version drift, ledgrrr#194) * feat(iso): dedicated ZLayer::SystemsModel variant (#185) * feat(iso): add dedicated ZLayer::SystemsModel variant Requirement/Decision/Cost content (ledgrrr#184) gets its own isometric layer rather than folding into the existing 6 or the still-unimplemented proposed Domain layer (docs/ontological-implementation-spec.md §6.1), per decision 2 in docs/systems-modeling-registry-rescope.md: independent toggle/color in the renderer over reusing an ontological-concepts layer. index=6, base_z=816.0 (continuing the existing 136.0 spacing), color #be185d (distinct from all 6 existing hexes). No HasVisualization impls wired yet for Requirement/Decision/Cost themselves — that requires also touching xtask's viz_manifest export + the checked-in viz-manifest.json per iso_objects.rs's own convention, tracked as a follow-on alongside task 6 (ledgerr-mcp/contract.rs wiring), not done here. * feat: spike reqif-opa-mcp over MCP + Requirement converter (#186) * feat(reqif-mcp-spike): Rust MCP client for reqif-opa-mcp + Requirement converter Spike per decision 6 (docs/systems-modeling-registry-rescope.md §5/§6 task 5): reqif-opa-mcp is wrapped over MCP, not ported to Rust; arc-kit-au stays the canonical decision+cost ledger. New crate reqif-mcp-spike: - McpHttpClient: minimal blocking client for reqif-opa-mcp's Streamable- HTTP MCP server (FastMCP 3.0.0b1, protocol 2024-11-05). Handles the initialize handshake + mcp-session-id header, the mandatory notifications/initialized follow-up, and tools/call, extracting the JSON-RPC result out of the single-frame SSE response body. - RequirementRecord: mirrors reqif-opa-mcp's requirement-record.schema.json exactly (uid/key/subtypes/status/policy_baseline/rubrics/text/attrs). - requirement_record_to_node(): converts a RequirementRecord into the arc-kit-au Requirement struct from ledgrrr#184 (ArtifactKind::Requirement / NodeType::Requirement). requirement_id<-uid, title<-key, rationale<-text, source<-attrs.source_standard(+source_url) falling back to the policy baseline id, status passed through, related_decisions always empty (reqif-opa-mcp carries no decision links; those are created later in arc-kit-au itself). Verified live end-to-end against a real reqif-opa-mcp checkout (uv sync --extra ingest-lite; uv run python -m reqif_mcp --http --port 8123) parsing both its own sample derived baselines, samples/standards/derived/{nist_ssdf_dogfood,owasp_asvs_cwe}.reqif (4 and 7 requirements respectively), through reqif_parse -> reqif_query -> requirement_record_to_node -> Requirement::node_id(), all producing correct, deterministic req: NodeIds. That live run is captured as an #[ignore]'d integration test (tests/live_server.rs) since it needs an external repo checkout + Python/uv, not something CI or a fresh clone has; re-run manually with REQIF_MCP_URL set to a running server. cargo test -p reqif-mcp-spike: 5 unit tests pass, 1 ignored (live). cargo check --workspace --all-features: clean. cargo clippy -p reqif-mcp-spike --all-targets: clean. * feat(ledgerr-mcp): wire Requirement/Decision/Cost into contract.rs (task 6) - EvidenceArgs gains import_requirement/record_decision/record_cost actions, each constructing the corresponding arc-kit-au node (Requirement/Decision/Cost from ledgrrr#184) and inserting it into the evidence graph via EvidenceGraph::add_node. DuplicateNode is treated as idempotent success (content-hash dedup), matching the idempotent semantics already established for EvidenceBuilder's ensure_* methods. - parse_evidence_node_type gains requirement/req, decision/dec, cost (plus previously-missing rnd_activity/tax_offset, same class of gap). - Summary's node_counts and ListNodes' invalid-type error message extended to include the 3 new types. - EVIDENCE_TOOL's contract.rs action list and purpose string updated. Verified: new tests/evidence_requirement_decision_cost.rs (3 tests, covering import+list+detail+summary, record_decision+record_cost, and idempotent re-import) all pass; cargo build -p ledgerr-mcp --features legacy clean (1 pre-existing unrelated warning). * docs: regenerate mcp-capability-contract.md (drift from task 6) Task 6 (ledgrrr#186's second commit) added import_requirement/ record_decision/record_cost to ledgerr_evidence's EVIDENCE_TOOL actions in contract.rs but never re-ran regen-docs, so the checked-in mcp-capability-contract.md drifted — caught by CI's check-drift step on downstream stacked PRs (#190, #193). Ran: cargo run -p ledgerr-mcp --bin regen-docs * docs: regenerate viz-manifest.json (stale version field, 1.9.0 -> 1.10.0) Pre-existing drift, unrelated to Requirement/Decision/Cost content (28 objects, unchanged) -- the workspace version was bumped to 1.10.0 at some point after this artifact was last regenerated. Only surfaced now because check-drift's earlier mcp-capability-contract.md failure (fixed in dd168f7) was masking this second, independent drift. Ran: cargo run -p xtask-mcpb -- export-viz-manifest * feat(iso): HasVisualization + viz_manifest wiring for Requirement/Decision/Cost (#190) * feat(iso): HasVisualization + viz_manifest wiring for Requirement/Decision/Cost Adds dedicated SemanticType::{Requirement,Decision,Cost} variants (iso.rs) and HasVisualization impls for arc_kit_au::node::{Requirement, Decision,Cost} (iso_objects.rs, gated behind the arc-kit-au feature, matching ontology.rs's arc_kit_bridge precedent), all routed to ZLayer::SystemsModel (added in ledgrrr#185). Wires the 3 new types into xtask's export_viz_manifest (now 31 domain types, up from 28) and regenerates the checked-in viz-manifest.json. Updates pipeline_e2e.rs's EXPECTED_ENTRY_COUNT and representative-type assertions to match. Verified: cargo test -p ledger-core --lib (185 passed), cargo test -p ledgerr-mcp --test pipeline_e2e (manifest count test passes), cargo check --workspace --all-features clean. This closes out the one remaining gap from ledgrrr#185 (task 4 in docs/systems-modeling-registry-rescope.md's §6), left explicitly unfinished there pending this larger change. * feat(arc-kit-au): retrofit #[derive(SysmlBlock)] onto existing node types (#193) Applies the sysml-derive macro (feat/sysml-derive-spike, #183) to the 8 pre-existing arc-kit-au node structs that predate the systems-modeling epic: SourceDoc, ExtractedRow, Transaction, Classification, ModelProposal, OperatorApproval, ValidationIssue, WorkbookRow. This was the second of two explicitly-deferred follow-ons from task 3 (#184) — the first (HasVisualization/viz_manifest wiring for Requirement/Decision/Cost) landed as part of this same stack. The derive is purely syntactic (walks named fields via syn, stringifies each field's type via quote!) so it applies uniformly regardless of field type — no per-struct special-casing needed, confirmed by re-reading crates/sysml-derive/src/lib.rs before applying. Verified: cargo test -p sysml-derive (2 tests), cargo test -p arc-kit-au (46 tests, unchanged from pre-retrofit baseline), cargo check --workspace --all-features (clean, one pre-existing unrelated warning in ledgerr-mcp/src/fbar.rs), cargo clippy -p arc-kit-au --all-features (clean).
elasticdotventures
added a commit
that referenced
this pull request
Aug 23, 2026
* feat(sysml-derive): spike a Rust-AST-to-SysML-v2 derive macro New crate: #[derive(SysmlBlock)] walks a struct's named fields via syn and generates a sysml_block_def() associated fn returning the equivalent SysML-v2 'block def' text at compile time (matching holon-viz's SysmlV2Emitter 'block def' terminology). Field-type mapping: Vec<T> -> T[*], Option<T> -> T[0..1], everything else -> plain T. Not yet checked against a real SysML-v2 grammar/parser (Part 1's Tier 0 candidates) -- this is the spike from docs/systems-modeling-registry-rescope.md #2a/#6 task 1, proving the AST-walk direction before comparing it against the LinkML spike (task 2) and wiring either into the real ArtifactKind/NodeType widening (task 3). Tests mirror arc-kit-au::Transaction's and ::Classification's field shapes (name+type only, no dependency on arc-kit-au itself -- wiring the derive onto the real production structs is task 3, not this spike) and assert on the emitted block def text for both the Vec and Option multiplicity branches. Same technique this codebase already approved for a different target: AGENTS.md (PM-3, 2026-05-13) sanctions #[derive(specta::Type)] for Rust-to-TypeScript; this is Rust-to-SysML-v2/KerML instead. * chore: regenerate viz-manifest.json (version drift 1.9.0 -> 1.10.0) * feat: widen ArtifactKind/NodeType/OperationKind with Requirement/Decision/Cost (#184) * feat: widen ArtifactKind/NodeType/OperationKind with Requirement/Decision/Cost Task 3 from docs/systems-modeling-registry-rescope.md (epic part 2, ledgrrr#181), backed by sysml-derive (#183) per the resolved LinkML comparison (#3a). arc-kit-au: - NodeType gains Requirement/Decision/Cost variants (prefixes req/dec/cost) - New Requirement/Decision/Cost structs, following the existing Transaction/Classification pattern (content-hashed node_id()), each annotated with #[derive(SysmlBlock)] from sysml-derive - EvidenceNode gains matching variants; node_id()/node_type()/tx_id() updated (tx_id() -> None for all three, same as SourceDoc/ExtractedRow) - arc-kit-au now depends on sysml-derive ledger-core: - ArtifactKind gains matching variants + canonical_name() arms - arc_kit_bridge's From<ArtifactKind> for NodeType maps them explicitly (was previously falling through the _ => Unknown wildcard) - OperationKind gains RecordDecision/RecordCost/ImportRequirement, each with a corresponding LedgerOperation impl (content-hashed, idempotent, same shape as CheckTaxDeadlineOp) and wired into OperationDispatcher::from_scheduled_events ledgerr-mcp: - evidence_node_type_label() (behind the legacy feature) gets the 3 new NodeType arms it was missing Verified: cargo test -p arc-kit-au (46 tests), cargo test -p ledger-core --lib (184 tests), cargo build -p ledgerr-mcp --features legacy, and cargo check --workspace --all-features all pass. clippy clean on the touched files. Retrofitting existing variants (Transaction/TaxCategory/etc.) onto sysml-derive is a tracked follow-on, not done here, per the doc's own scoping. * fix(sysml-derive): map primitive scalars + DateTime to SysML ScalarValues DateTime<Utc> previously emitted the literal, invalid text `DateTime<Utc>` as a SysML v2 attribute type -- SysML v2's grammar has no angle-bracket generic-parameter syntax, so this would fail to parse under any conformant SysML v2 tool. bool/usize/etc. also passed through as bare Rust keywords with no corresponding SysML type. Map DateTime<_> -> ScalarValues::String, bool -> ScalarValues::Boolean, unsigned ints -> ScalarValues::Natural, signed ints -> ScalarValues::Integer, floats -> ScalarValues::Rational. Any other single-type-argument generic is now a compile error instead of a silent invalid-syntax emission. Opaque domain types (NodeId, Confidence, Decimal) still pass through as bare names -- documented as an intentional modeling assumption, not a bug. Adds regression tests for the field types introduced by #184/#193 (Decimal, Confidence, bool, usize, DateTime<Utc>) that basic.rs never exercised. Closes ledgrrr#195. * fix(holon-viz): emit valid SysML v2 (part def, not block def); wire real parser validation into ufo-types Ran SysmlV2Emitter's own output through the real sysml-v2-parser crate (docs/sysml-v2-parser-spike.md, an existing unmerged spike) and confirmed two bugs make it non-parseable: - The closing '}' was on the same line as a trailing '//' comment, so the comment swallowed it -- the block was never syntactically closed. - The emitter used SysML v1's 'block def' keyword. SysML v2 renamed this construct to 'part def'; 'block' is not a SysML v2 keyword at all. Fixed both. Added ufo_types::sysml -- a shared Constraint/Satisfies-based SysML v2 syntax validator wired to sysml-v2-parser (pinned to =0.54.0 per the spike's crate-health findings; not wasm32-compatible, so this must stay out of holon-viz's runtime dependency graph -- added to holon-viz only as a dev-dependency, used in a new round-trip test that feeds the emitter's own output through the real parser instead of just asserting on substrings. This is the concrete round-trip-closed signal the existing spike (PR #187) called out as the next step. * fix(sysml-derive): emit part def (not block def); validate against real SysML v2 grammar Same bug holon-viz's SysmlV2Emitter had (ledgrrr#197): SysML v1 called this construct Block/'block def'; SysML v2 renamed it to 'part def', and 'block' is not a SysML v2 keyword at all. Confirmed via the newly-wired ufo_types::sysml::validate_sysml_v2 (real sysml-v2-parser crate, not a hand-rolled heuristic) that the fixed output actually parses. Adds tests/real_grammar_validation.rs: runs the actual generated sysml_block_def() text for Transaction/Requirement/ExtractedRow/ ModelProposal/WorkbookRow (mirroring the real production structs from #184/#193) through the real parser. This replaces the 'no angle brackets' manual check used to validate the earlier DateTime/bool/usize scalar mapping fix with genuine grammar validation, closing out ledgrrr#195. * test(arc-kit-au): update block def -> part def assertion (sysml-derive fix) * chore: regenerate viz-manifest.json (version drift, ledgrrr#194) * feat(iso): dedicated ZLayer::SystemsModel variant (#185) * feat(iso): add dedicated ZLayer::SystemsModel variant Requirement/Decision/Cost content (ledgrrr#184) gets its own isometric layer rather than folding into the existing 6 or the still-unimplemented proposed Domain layer (docs/ontological-implementation-spec.md §6.1), per decision 2 in docs/systems-modeling-registry-rescope.md: independent toggle/color in the renderer over reusing an ontological-concepts layer. index=6, base_z=816.0 (continuing the existing 136.0 spacing), color #be185d (distinct from all 6 existing hexes). No HasVisualization impls wired yet for Requirement/Decision/Cost themselves — that requires also touching xtask's viz_manifest export + the checked-in viz-manifest.json per iso_objects.rs's own convention, tracked as a follow-on alongside task 6 (ledgerr-mcp/contract.rs wiring), not done here. * feat: spike reqif-opa-mcp over MCP + Requirement converter (#186) * feat(reqif-mcp-spike): Rust MCP client for reqif-opa-mcp + Requirement converter Spike per decision 6 (docs/systems-modeling-registry-rescope.md §5/§6 task 5): reqif-opa-mcp is wrapped over MCP, not ported to Rust; arc-kit-au stays the canonical decision+cost ledger. New crate reqif-mcp-spike: - McpHttpClient: minimal blocking client for reqif-opa-mcp's Streamable- HTTP MCP server (FastMCP 3.0.0b1, protocol 2024-11-05). Handles the initialize handshake + mcp-session-id header, the mandatory notifications/initialized follow-up, and tools/call, extracting the JSON-RPC result out of the single-frame SSE response body. - RequirementRecord: mirrors reqif-opa-mcp's requirement-record.schema.json exactly (uid/key/subtypes/status/policy_baseline/rubrics/text/attrs). - requirement_record_to_node(): converts a RequirementRecord into the arc-kit-au Requirement struct from ledgrrr#184 (ArtifactKind::Requirement / NodeType::Requirement). requirement_id<-uid, title<-key, rationale<-text, source<-attrs.source_standard(+source_url) falling back to the policy baseline id, status passed through, related_decisions always empty (reqif-opa-mcp carries no decision links; those are created later in arc-kit-au itself). Verified live end-to-end against a real reqif-opa-mcp checkout (uv sync --extra ingest-lite; uv run python -m reqif_mcp --http --port 8123) parsing both its own sample derived baselines, samples/standards/derived/{nist_ssdf_dogfood,owasp_asvs_cwe}.reqif (4 and 7 requirements respectively), through reqif_parse -> reqif_query -> requirement_record_to_node -> Requirement::node_id(), all producing correct, deterministic req: NodeIds. That live run is captured as an #[ignore]'d integration test (tests/live_server.rs) since it needs an external repo checkout + Python/uv, not something CI or a fresh clone has; re-run manually with REQIF_MCP_URL set to a running server. cargo test -p reqif-mcp-spike: 5 unit tests pass, 1 ignored (live). cargo check --workspace --all-features: clean. cargo clippy -p reqif-mcp-spike --all-targets: clean. * feat(ledgerr-mcp): wire Requirement/Decision/Cost into contract.rs (task 6) - EvidenceArgs gains import_requirement/record_decision/record_cost actions, each constructing the corresponding arc-kit-au node (Requirement/Decision/Cost from ledgrrr#184) and inserting it into the evidence graph via EvidenceGraph::add_node. DuplicateNode is treated as idempotent success (content-hash dedup), matching the idempotent semantics already established for EvidenceBuilder's ensure_* methods. - parse_evidence_node_type gains requirement/req, decision/dec, cost (plus previously-missing rnd_activity/tax_offset, same class of gap). - Summary's node_counts and ListNodes' invalid-type error message extended to include the 3 new types. - EVIDENCE_TOOL's contract.rs action list and purpose string updated. Verified: new tests/evidence_requirement_decision_cost.rs (3 tests, covering import+list+detail+summary, record_decision+record_cost, and idempotent re-import) all pass; cargo build -p ledgerr-mcp --features legacy clean (1 pre-existing unrelated warning). * docs: regenerate mcp-capability-contract.md (drift from task 6) Task 6 (ledgrrr#186's second commit) added import_requirement/ record_decision/record_cost to ledgerr_evidence's EVIDENCE_TOOL actions in contract.rs but never re-ran regen-docs, so the checked-in mcp-capability-contract.md drifted — caught by CI's check-drift step on downstream stacked PRs (#190, #193). Ran: cargo run -p ledgerr-mcp --bin regen-docs * docs: regenerate viz-manifest.json (stale version field, 1.9.0 -> 1.10.0) Pre-existing drift, unrelated to Requirement/Decision/Cost content (28 objects, unchanged) -- the workspace version was bumped to 1.10.0 at some point after this artifact was last regenerated. Only surfaced now because check-drift's earlier mcp-capability-contract.md failure (fixed in dd168f7) was masking this second, independent drift. Ran: cargo run -p xtask-mcpb -- export-viz-manifest * feat(iso): HasVisualization + viz_manifest wiring for Requirement/Decision/Cost (#190) * feat(iso): HasVisualization + viz_manifest wiring for Requirement/Decision/Cost Adds dedicated SemanticType::{Requirement,Decision,Cost} variants (iso.rs) and HasVisualization impls for arc_kit_au::node::{Requirement, Decision,Cost} (iso_objects.rs, gated behind the arc-kit-au feature, matching ontology.rs's arc_kit_bridge precedent), all routed to ZLayer::SystemsModel (added in ledgrrr#185). Wires the 3 new types into xtask's export_viz_manifest (now 31 domain types, up from 28) and regenerates the checked-in viz-manifest.json. Updates pipeline_e2e.rs's EXPECTED_ENTRY_COUNT and representative-type assertions to match. Verified: cargo test -p ledger-core --lib (185 passed), cargo test -p ledgerr-mcp --test pipeline_e2e (manifest count test passes), cargo check --workspace --all-features clean. This closes out the one remaining gap from ledgrrr#185 (task 4 in docs/systems-modeling-registry-rescope.md's §6), left explicitly unfinished there pending this larger change. * feat(arc-kit-au): retrofit #[derive(SysmlBlock)] onto existing node types (#193) Applies the sysml-derive macro (feat/sysml-derive-spike, #183) to the 8 pre-existing arc-kit-au node structs that predate the systems-modeling epic: SourceDoc, ExtractedRow, Transaction, Classification, ModelProposal, OperatorApproval, ValidationIssue, WorkbookRow. This was the second of two explicitly-deferred follow-ons from task 3 (#184) — the first (HasVisualization/viz_manifest wiring for Requirement/Decision/Cost) landed as part of this same stack. The derive is purely syntactic (walks named fields via syn, stringifies each field's type via quote!) so it applies uniformly regardless of field type — no per-struct special-casing needed, confirmed by re-reading crates/sysml-derive/src/lib.rs before applying. Verified: cargo test -p sysml-derive (2 tests), cargo test -p arc-kit-au (46 tests, unchanged from pre-retrofit baseline), cargo check --workspace --all-features (clean, one pre-existing unrelated warning in ledgerr-mcp/src/fbar.rs), cargo clippy -p arc-kit-au --all-features (clean).
elasticdotventures
added a commit
that referenced
this pull request
Aug 23, 2026
* docs: systems modeling & action registry re-scope (epic part 2) Re-scopes ledgrrr from its README's tax-accounting framing to a general systems modeling process and action registry, with ReqIF (requirements), LinkML (schema), and a decision+cost ledger as new domain verticals on the existing substrate (arc-kit-au identity, ArtifactKind/NodeType ontology graph, ZLayer visualization, Rhai policy). All 6 open questions resolved: 1. Widen ArtifactKind/NodeType core enums (not custom kinds) 2. New dedicated ZLayer variant (not the existing proposed Domain layer) 3. reqif-opa-mcp (first-party) chosen over third-party ReqIF wraps 4. LinkML: spike before committing 5. sysgit.io: reference vibe only, not a feature-parity backlog 6. reqif-opa-mcp: wrap over MCP; arc-kit-au stays the canonical decision+cost ledger; OPA/Rego and Rhai coexist, one per domain Addendum folded in during review: existing ledger types (Transaction, TaxCategory) and new ones (Requirement/Decision/Cost) should be concrete specializations of generic SysML v2 types, generated via a Rust AST-walking derive macro (new sysml-derive crate) rather than hand-maintained per-type emitter logic -- same technique already approved here for specta's Rust-to-TypeScript codegen, aimed at SysML-v2/KerML instead. Task list reordered so this spike gates the ArtifactKind widening and runs alongside the LinkML spike as a direct comparison. * docs: mark sysml-derive spike (task 1) done, link ledgrrr#183 * docs: LinkML vs sysml-derive spike comparison, decision 4 resolved Ran the actual spike: installed linkml, confirmed gen-rust is real, authored the same 5-field Requirement schema sysml-derive's test suite mirrors, generated + built the Rust output, and consumed it from a throwaway crate. Findings: gen-rust works but produces 1219 lines for one class, pulls in pyo3/serde_yml scaffolding unconditionally, compiles with 7 warnings out of the box, and -- the deciding finding -- silently serializes a single-element Vec<String> as a bare JSON scalar instead of an array via its generated serialize_primitive_list_or_single_value helper. Same class of surprise already flagged for sysmlpy during the ReqIF survey, now found independently in LinkML's own generator. Decision: sysml-derive (Rust-native, macro-driven, ledgrrr#183) wins over LinkML for authoring Requirement/Decision/Cost's Rust shape -- Rust-first fit, no correctness surprise, no extra toolchain, matches the existing specta precedent. LinkML is not rejected for the whole epic, just this role. Task 3 (widen ArtifactKind/NodeType) is now unblocked. * docs: mark task 3 (ArtifactKind/NodeType/OperationKind widening) done, link ledgrrr#184 * docs: mark task 4 (ZLayer::SystemsModel variant) done, link ledgrrr#185 * docs: mark task 5 (reqif-opa-mcp MCP client spike) done, link ledgrrr#186 * docs: mark task 6 (contract.rs wiring) + README correction done, link ledgrrr#186/#188 All 6 tasks in epic part 2's §6 task list are now complete. * docs: mark HasVisualization wiring, retrofit, and DVC scoping done (#190/#193/#191) * chore: regenerate viz-manifest.json (version drift from v1.10.0 bump)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
#[derive(SysmlBlock)](fromsysml-derive, feat(sysml-derive): spike a Rust-AST-to-SysML-v2 derive macro #183) onto the 8pre-existing
arc-kit-aunode structs that predate the systems-modelingregistry epic:
SourceDoc,ExtractedRow,Transaction,Classification,ModelProposal,OperatorApproval,ValidationIssue,WorkbookRow.first (
HasVisualization/viz_manifestwiring forRequirement/Decision/Cost) already landed earlier in this stack.
adds a new
sysml_block_def()assoc. fn per struct; it does not touchSerialize/Deserialize/node_id()or any existing derive/impl.syn, stringifieseach field's type via
quote!), so it applies uniformly to all 8structs regardless of field type (
String,Decimal,Option<T>,Vec<NodeId>,DateTime<Utc>, etc.) — confirmed by re-readingcrates/sysml-derive/src/lib.rsbefore applying, not assumed.Stacked on
feat/requirement-decision-cost-visualizationper theestablished branch-stacking pattern for this epic (
main→feat/sysml-derive-spike(#183) →feat/requirement-decision-cost-kinds(#184) →
feat/zlayer-systems-model-variant(#185) →feat/reqif-opa-mcp-client-spike(#186) → this branch's base).Test plan
cargo test -p sysml-derive— 2 tests passcargo test -p arc-kit-au— 46 tests pass (unchanged count frompre-retrofit baseline)
cargo check --workspace --all-features— clean (one pre-existing,unrelated warning in
ledgerr-mcp/src/fbar.rs)cargo clippy -p arc-kit-au --all-features— clean