Skip to content

Proposal: add plan architecture system-of-record schema#23

Open
dbcall2 wants to merge 2 commits into
deftai:masterfrom
dbcall2:feat/system-of-record-architecture
Open

Proposal: add plan architecture system-of-record schema#23
dbcall2 wants to merge 2 commits into
deftai:masterfrom
dbcall2:feat/system-of-record-architecture

Conversation

@dbcall2

@dbcall2 dbcall2 commented Jun 4, 2026

Copy link
Copy Markdown

Proposal

This PR is a concrete proposal and candidate implementation for adding a system-of-record architecture block to vBRIEF. It is intentionally framed for schema-home review, not as an assumption that this field must immediately land in core.

Problem

Downstream Directive RFC work needs a canonical vBRIEF location for system-of-record design records before making its SOR preflight gate mandatory.

The interoperability question is broader than Directive:

  • Where should plan-level architecture decision records live?
  • Should system-of-record declarations be core vBRIEF, a profile/extension, or a consumer namespace?
  • If accepted, should the canonical shape be plan.architecture.systemOfRecord.stateSurfaces?

Related downstream context: deftai/directive#1492

Proposed Shape

This PR proposes:

{
  "plan": {
    "architecture": {
      "systemOfRecord": {
        "stateSurfaces": [
          {
            "name": "Workspace",
            "classification": "durable_product_state",
            "owner": "application database",
            "approvedStorage": "postgres"
          }
        ]
      }
    }
  }
}

The proposal keeps stateSurfaces inside systemOfRecord and places the architecture record under the plan it governs.

Open Maintainer Decision

I would like maintainer guidance on whether this should land as one of:

  1. Core plan.architecture.systemOfRecord
  2. A vBRIEF architecture/profile extension
  3. A consumer namespace such as x-directive/architecture
  4. A docs/proposal artifact first, with implementation deferred

If core is too early, I am happy to convert this into a proposal-only PR or follow with a narrower extension/profile PR.

Candidate Implementation Included

  • Adds optional plan.architecture.systemOfRecord to the vBRIEF core schemas.
  • Types stateSurfaces, classifications, storage declarations, and reference application comparison records.
  • Requires a declared systemOfRecord to contain at least one state surface.
  • Documents the system-of-record architecture block in the v0.5 and v0.6 specs.
  • Adds an example vBRIEF document.
  • Promotes plan.architecture to a known optional field in the Python and TypeScript models.
  • Exports TypeScript Zod schemas/types for SOR consumers.
  • Adds tests to prevent v0.5/v0.6 schema drift for the shared SOR definitions.

Validation

  • task python:test -> 136 passed
  • task ts:test -> 44 passed
  • task lint
  • task ts:lint
  • task ts:typecheck
  • uv run --extra dev python validation/vbrief_validator.py examples/system-of-record-plan.vbrief.json

Note: the direct example validation reports that jsonschema is not installed, so schema validation is skipped by that script; conformance validation passes.

@deft-slizard deft-slizard Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Superseded by a newer SLizard review
Machine-readable verdict
{
  "slizard_verdict": {
    "schema_version": 1,
    "decision": "comment",
    "severity": {
      "P0": 0,
      "P1": 0,
      "P2": 0,
      "P3": 0
    },
    "confidence": 0.5116,
    "decision_confidence": 0.5116,
    "finding_count": 0,
    "merge_impact": "non-blocking",
    "version": "slizard v0.3.1131",
    "head_sha": "b2a74f79d3e819e474efabd715b33ce8bba55257"
  }
}
**SLizard Review** — [low-signal review] 0 finding(s) across 0 file(s); 1 advisory note(s)

P2 · libvbrief-ts/src/index.ts:34 · confidence 0.75

Clean-review gap references ArchitectureSchema, schemas, SystemOfRecordSchema, StateSurfaceSchema, schema as unverified, but 5 of these symbols appear in the diff (first at libvbrief-ts/src/index.ts:34). The gap claimed: "Explicit unit tests for the newly defined ArchitectureSchema and its sub-schemas (e.g., SystemOfRecordSchema, StateSurfaceSchema) in libvbrief-ts are not visible in the diff. While the new exa…". Contradicted by diff content.

Blast radius graph (84 nodes)
%%{init: {'flowchart': {'rankSpacing': 30, 'nodeSpacing': 20}}}%%
graph TD
  libvbrief_models_py_PlanItem["🔴 PlanItem"]
  libvbrief_models_py__plan_item_completed["🔴 _plan_item_completed"]
  libvbrief_models_py_Plan["🔴 Plan"]
  libvbrief_models_py_VBriefDocument["🔴 VBriefDocument"]
  libvbrief_models_py__known_item_values["🔴 _known_item_values"]
  libvbrief_models_py__known_plan_values["🔴 _known_plan_values"]
  libvbrief_models_py__merge_values["🔴 _merge_values"]
  libvbrief_models_py__raise_if_invalid["🔴 _raise_if_invalid"]
  libvbrief_models_py__StatusFactory["🔴 _StatusFactory"]
  libvbrief_ts_src_models_ts_PlanItemInit["🔴 PlanItemInit"]
  libvbrief_ts_src_models_ts_PlanInit["🔴 PlanInit"]
  libvbrief_ts_src_models_ts_VBriefDocumentInit["🔴 VBriefDocumentInit"]
  libvbrief_ts_src_models_ts_DictOptions["🔴 DictOptions"]
  libvbrief_ts_src_models_ts_JsonOptions["🔴 JsonOptions"]
  libvbrief_ts_src_models_ts_ValidationOptions["🔴 ValidationOptions"]
  libvbrief_ts_src_models_ts_PlanItem["🔴 PlanItem"]
  libvbrief_ts_src_models_ts_Plan["🔴 Plan"]
  libvbrief_ts_src_models_ts_VBriefDocument["🔴 VBriefDocument"]
  libvbrief_ts_src_models_ts_knownItemValues["🔴 knownItemValues"]
  libvbrief_ts_src_models_ts_knownPlanValues["🔴 knownPlanValues"]
  libvbrief_ts_src_models_ts_raiseIfInvalid["🔴 raiseIfInvalid"]
  libvbrief_ts_src_schemas_ts_PlanEdgeData["🔴 PlanEdgeData"]
  libvbrief_ts_src_schemas_ts_PlanItemData["🔴 PlanItemData"]
  libvbrief_ts_src_schemas_ts_PlanData["🔴 PlanData"]
  libvbrief_ts_src_schemas_ts_VBriefDocumentData["🔴 VBriefDocumentData"]
  tests_test_models_api_py_test_model_from_dict_and_to_dict_preserves_unknown_fields["🔴 test_model_from_dict_and_to_dict_preserves_unknown_fields"]
  tests_test_models_api_py_test_model_validation_returns_report["🔴 test_model_validation_returns_report"]
  tests_test_models_api_py_test_model_preserve_order_uses_original_field_order["🔴 test_model_preserve_order_uses_original_field_order"]
  tests_test_models_api_py_test_model_vbrief_info_extras_round_trip["🔴 test_model_vbrief_info_extras_round_trip"]
  tests_test_models_api_py_test_model_from_dict_strict_raises_on_invalid["🔴 test_model_from_dict_strict_raises_on_invalid"]
  tests_test_models_api_py_test_model_from_json_round_trip["🔴 test_model_from_json_round_trip"]
  tests_test_models_api_py_test_model_from_file_and_to_file_round_trip["🔴 test_model_from_file_and_to_file_round_trip"]
  tests_test_models_api_py_test_plan_item_from_dict_with_sub_items["🔴 test_plan_item_from_dict_with_sub_items"]
  tests_test_models_api_py_test_plan_with_optional_fields_round_trips["🔴 test_plan_with_optional_fields_round_trips"]
  tests_test_models_api_py_test_merge_values_includes_fields_added_after_parse["🔴 test_merge_values_includes_fields_added_after_parse"]
  tests_test_models_api_py_test_plan_item_from_dict_non_mapping_returns_empty_item["🔴 test_plan_item_from_dict_non_mapping_returns_empty_item"]
  tests_test_models_api_py_test_plan_from_dict_non_mapping_returns_empty_plan["🔴 test_plan_from_dict_non_mapping_returns_empty_plan"]
  tests_test_models_api_py_test_vbrief_document_from_dict_non_mapping_returns_empty_doc["🔴 test_vbrief_document_from_dict_non_mapping_returns_empty_doc"]
  tests_test_models_api_py_test_vbrief_document_from_dict_non_dict_vbrief_info_becomes_empty["🔴 test_vbrief_document_from_dict_non_dict_vbrief_info_becomes_empty"]
  tests_test_models_api_py_test_merge_values_extras_added_after_parse_appear_in_preserve_order_output["🔴 test_merge_values_extras_added_after_parse_appear_in_preserve_order_output"]
  libvbrief_models_py_PlanItem --> libvbrief_models_py__known_item_values
  libvbrief_models_py_PlanItem --> libvbrief_models_py__merge_values
  libvbrief_models_py_Plan --> libvbrief_models_py__known_plan_values
  libvbrief_models_py_Plan --> libvbrief_models_py__merge_values
  libvbrief_models_py_VBriefDocument --> libvbrief_models_py__merge_values
  libvbrief_models_py_VBriefDocument --> libvbrief_models_py__raise_if_invalid
  libvbrief_ts_src_models_ts_PlanItem --> libvbrief_ts_src_models_ts_knownItemValues
  libvbrief_ts_src_models_ts_Plan --> libvbrief_ts_src_models_ts_knownPlanValues
  libvbrief_ts_src_models_ts_VBriefDocument --> libvbrief_ts_src_models_ts_Plan
  libvbrief_ts_src_models_ts_VBriefDocument --> libvbrief_ts_src_models_ts_raiseIfInvalid
  %% 44 additional affected node(s) omitted for diagram size
Loading

Review coverage

  • Reviewed files: docs/vbrief-spec-0.5.md, docs/vbrief-spec-0.6.md, examples/system-of-record-plan.vbrief.json, libvbrief-ts/src/compat.ts, libvbrief-ts/src/index.ts, libvbrief-ts/src/models.ts, libvbrief-ts/src/schemas.ts, libvbrief-ts/tests/models.test.ts, +4 more
  • Skipped files: none
  • Source: github @ b2a74f79d3e8

Context used

  • Static findings: 1
  • Static tools: unused-option
  • Graph/blast radius: 40 changed node(s), 44 affected node(s)
  • Vector context chunks: 41
  • Context availability: full
  • Review categories: default
  • Deterministic checks:
    365/370 passed, 5 failed: unused-option, graph-incompleteness, graph-callsite-not-updated, orphaned-module, graph-validation-gapvbrief-traceability=passed, markdown-fences=passed, unused-exports=passed, query-docstring=passed, xss-sprintf=passed, markdown-xref=passed, aria-target=passed, semantic-role=passed, aria-containment=passed, redundant-assertion=passed, tautological-assertion=passed, resource-lifecycle=passed, cross-diff-consistency=passed, redundant-css-block=passed, template-placeholder=passed, void-async-signal=passed, spread-override=passed, json-indent-consistency=passed, dep-swap=passed, powershell-scoping=passed, diff-truncation=passed, exception-type-contract=passed, dead-none-guard=passed, access-declaration=passed, unused-option=failed, css-property-interaction=passed, jsx-style-indent=passed, regex-breadth=passed, cartesian-fan-out=passed, exec-stdout-parse=passed, sentinel-error-wiring=passed, hardcoded-filemode=passed, api-response-shape=passed, python-cli-arg=passed, taskfile-namespace=passed, vbrief-schema=passed, go-shell-injection=passed, go-discarded-error=passed, go-json-field-exposure=passed, go-mutable-exported-slice=passed, go-silent-error-branch=passed, go-comment-log-contradiction=passed, go-unconditional-message=passed, inline-style-proliferation=passed, unnecessary-nonnull-assertion=passed, double-cast=passed, unguarded-await-cast=passed, ssrf-guard-completeness=passed, error-message-leak=passed, puppeteer-resource-cap=passed, trivial-argument=passed, unused-imports=passed, dead-store=passed, phantom-import=passed, fetch-timeout-guard=passed, log-level-expected-path=passed, unified-diff-construction=passed, sentinel-index-assertion=passed, unguarded-map-lookup=passed, unbounded-prompt-injection=passed, description-diff-consistency=passed, render-branch-symmetry=passed, go-gorm-unchained-error=passed, go-gorm-rowsaffected-noop=passed, error-handling-loop-break=passed, sync-state-batching=passed, sync-revoke-object-url=passed, go-like-wildcard-injection=passed, go-basename-dedup-gap=passed, go-missing-seed-in-migrate=passed, go-write-then-read-unfiltered=passed, go-direct-db-access=passed, async-handler-try-catch=passed, chat-sdk-history=passed, dead-code-ternary=passed, go-context-background=passed, go-git-arg-order=passed, go-n-plus-one=passed, go-nested-transaction=passed, go-ref-injection=passed, go-scanner-error=passed, go-toctou-db=passed, go-unused-validated-field=passed, hardcoded-literal=passed, hardcoded-undefined-field=passed, python-exception=passed, python-path-construction=passed, python-isdigit-int=passed, deprecated-python-utcnow=passed, python-variable-shadow=passed, frozen-dataclass-mutable-field=passed, sentinel-value=passed, sibling-constant=passed, url-interpolation=passed, jsx-guard-removal=passed, asymmetric-clamp=passed, optional-prop-guard=passed, server-lifecycle=passed, go-asymmetric-org-scope=passed, fetch-body-scope-omission=passed, regex-breadth-inconsistency=passed, typeof-object-array-guard=passed, test-production-divergence=passed, argument-axis-mismatch=passed, click-propagation-gap=passed, sanitization-gap=passed, response-shape-consistency=passed, keydown-target-guard=passed, changelog-test-count=passed, unbounded-metadata-assignment=passed, unchecked-json-response=passed, response-body-leak=passed, json-syntax=passed, requestid-route-param=passed, dict-key-as-value=passed, redundant-transitive-call=passed, incomplete-iteration=passed, call-site-parameter-consistency=passed, markdown-heading-level=passed, cross-section-order-contradiction=passed, dangling-reference=passed, useref-dead-store=passed, fetch-redirect-guard=passed, response-body-buffering=passed, svg-content-type=passed, conditional-mode-exclusion=passed, join-separator-inconsistency=passed, prompt-injection-guard=passed, asymmetric-guard=passed, unsafe-json-cast=passed, storage-unsafe-cast=passed, markdown-single-line-interpolation=passed, postmessage-origin-guard=passed, css-iframe-scope=passed, markdown-entry-completeness=passed, python-set-duplicate=passed, state-setter-symmetry=passed, changelog-sibling-truncation=passed, ternary-exhaustiveness=passed, exclusive-output-constraint=passed, nullish-fallback-regression=passed, shell-pipefail=passed, vbrief-acceptance-contradiction=passed, css-property-diff=passed, go-sync-call-labeled-background=passed, prompt-guardrail-conflict=passed, prompt-identity-duplication=passed, asymmetric-truncation=passed, claim-source-tracing=passed, go-duplicate-event-publish=passed, go-create-without-cleanup=passed, go-find-then-create-without-cleanup=passed, go-persist-without-validate=passed, ts-put-without-get=passed, go-fetch-id-without-liveness=passed, go-event-subscribe-without-publish=passed, go-log-aggregation-run-scoping=passed, falsy-string-fallback=passed, useeffect-unstable-prop-dep=passed, unused-state-read=passed, blob-mime-mismatch=passed, parseint-nan-guard=passed, shared-state-across-map=passed, context-menu-click-guard=passed, touch-action-ancestor=passed, usestate-innerwidth-matchmedia=passed, prefix-match-loop=passed, hardcoded-new-field=passed, enum-subset-completeness=passed, optional-guard-fallthrough=passed, html-template-token=passed, label-association=passed, empty-src-img=passed, jsx-prose-link-mismatch=passed, try-catch-scope=passed, viewport-meta-accessibility=passed, go-github-api-response-id=passed, go-github-api-pagination=passed, go-gorm-first-without-errrecordnotfound=passed, fetch-cache-consistency=passed, oauth-session-state-binding=passed, go-switch-exhaustiveness=passed, go-test-mutex-asymmetry=passed, nextjs-suspense-boundary=passed, nullable-nested-response=passed, nullish-coalesce-empty-url=passed, asymmetric-callback-state-reset=passed, go-docstring-contract-mismatch=passed, replace-dollar-pattern=passed, conditional-fallthrough-gap=passed, sanitization-completeness=passed, bare-selector-fallback=passed, sanitization-context-mismatch=passed, json-escape-completeness=passed, catch-block-guard-parity=passed, early-exit-guard-subset=passed, html-escape-context-collision=passed, cross-file-inline-duplication=passed, collection-gate-ordering=passed, regex-denylist-anchor-gap=passed, handler-validation-symmetry=passed, go-http-handler-body-persist-without-authz=passed, go-first-element-without-disambiguation=passed, ternary-wrapper-asymmetry=passed, promise-then-without-outer-catch=passed, effect-persist-hydration-race=passed, css-animation-ref=passed, idb-open-lifecycle=passed, interactive-role-mismatch=passed, array-duplicate-field=passed, mid-file-static-import=passed, changelog-section-deletion=passed, comment-anchored-regex=passed, go-sprintf-json-body=passed, observer-boundary-mismatch=passed, hook-return-shape-mismatch=passed, raw-vs-effective-state=passed, unstable-mapped-key=passed, parallel-state-init-divergence=passed, value-callback-prop-coherence=passed, cap-expansion-order=passed, cross-file-comment-claim=passed, useeffect-cleanup=passed, filter-ratio-threshold=passed, setter-argument-asymmetry=passed, panel-scoped-notification=passed, unawaited-async-dependency=passed, prompt-html-anti-pattern=passed, go-empty-collection-write-guard=passed, go-inconsistent-error-wrapping=passed, sentinel-substring-guard=passed, hardcoded-color-in-themed-context=passed, modal-escape-handler=passed, property-read-without-write-path=passed, iframe-nav-intercept-completeness=passed, tagname-case-sensitivity=passed, guard-clause-subsumption=passed, effect-cleanup-race=passed, style-template-injection=passed, textarea-min-height=passed, greedy-lookahead-futility=passed, window-open-null-guard=passed, orphaned-ambient-declaration=passed, char-ordinal-bounds=passed, stale-ref-callback-race=passed, missing-init-check=passed, stderr-redirect=passed, gitignore-tracked-file=passed, eager-defeats-lazy-import=passed, redundant-call-in-scope=passed, test-source-list-diff=passed, mixed-dict-access-pattern=passed, md-fragile-regex-lookahead=passed, misleading-none-branch=passed, discarded-validation-return=passed, loopback-range=passed, trust-proxy=passed, fly-toml-schema=passed, dockerfile-copy-shell-op=passed, dockerfile-build-secret=passed, string-dispatch=passed, python-toctou-file-lock=passed, python-non-reentrant-lock=passed, go-sibling-handler-guard=passed, stale-test-assertion=passed, go-batch-response-counter=passed, go-single-status-error-handler=passed, go-base64-body-size-mismatch=passed, dict-write-lookup-asymmetry=passed, identical-branch=passed, postmessage-targetorigin-regression=passed, react-namespace-import=passed, comment-payload-contradiction=passed, conditional-gating-dead-path=passed, go-mock-interface-completeness=passed, toggle-setter-mismatch=passed, localhost-in-allowlist=passed, unawaited-waitfor=passed, cli-example-validator=passed, python-tz-comparison-asymmetry=passed, missing-wildcard-guard=passed, react-ref-hydration-trigger=passed, react-unused-callback-dep=passed, scope-intent-mismatch=passed, supabase-join-path-mismatch=passed, incomplete-optional-property-guard=passed, retry-reenqueue-without-guard=passed, stale-self-call-in-callback=passed, empty-body-control-flow=passed, self-increment-comparison=passed, sequential-replace-dedup=passed, breaking-export-removal=passed, vacuous-test-assertion=passed, silent-fallible-coalesce=passed, dual-threshold-warning=passed, unresolved-relative-import=passed, coalescing-callback-dispatch=passed, removed-event-propagation-stopper=passed, jsx-inline-style-scope-leak=passed, hook-after-early-return=passed, fs-access-overwrite=passed, type-import-divergence=passed, conditional-state-no-clear=passed, gated-operation-silent-persist=passed, hardcoded-sentinel-dead-path=passed, swift-filepath-disclosure=passed, swift-lba-overflow=passed, swift-xpc-listener-validation=passed, python-weak-substring-match=passed, python-docstring-class-ref=passed, python-unused-subprocess-output=passed, python-narrow-exception-handler=passed, usememo-missing-dep=passed, localstorage-stale-cache=passed, localstorage-scope=passed, dead-action-variant=passed, switch-param-forwarding-gap=passed, changelog-entry-style=passed, vbrief-edge-completeness=passed, pr-body-vbrief-scope=passed, abort-signal-timeout-guard=passed, whitespace-control-char=passed, transient-error-permanent-state=passed, unused-variable=passed, postmessage-source-null-check=passed, atob-encoding-check=passed, phantom-identity-fallback-check=passed, workflow-comment-secret=passed, rls-circular-dep=passed, writable-stream-abort=passed, error-type-shadowing=passed, unguarded-iteration-component=passed, ci-checksum-provenance=passed, react-error-cache-nav-reset=passed, shell-injection-template=passed, flag-reset=passed, excess-property=passed, timestamp-sanitization-reuse=passed, boolean-null-guard=passed, catch-typeof-swallow=passed, optional-strict-compare=passed, leaked-debug-text=passed, inconsistent-component-import=passed, wrong-domain-copy=passed, unconditional-lfs-filter=passed, toml-config-injection=passed, dead-popen-timeout-except=passed, python-unused-local=passed, async-event-lock-no-recovery=passed, webkit-cancel-compat=passed, dom-cleanup-racing-interaction=passed, nonstandard-code-fence=passed, vba-value2-single-cell=passed, vba-doc-error-handler=passed, officejs-doc-sync-batching=passed, regex-word-boundary-method-name=passed, sliding-window-dedup=passed, double-localstorage-key-write=passed, new-class-missing-option=passed, branch-reset-asymmetry=passed, changelog-placeholder=passed, cockpit-state-before-try=passed, format-conversion-fallthrough=passed, normalize-to-empty=passed, sql-cursor-pagination-index=passed, graph-incompleteness=skipped, graph-callsite-not-updated=skipped, orphaned-module=skipped, graph-validation-gap=skipped, lockfile-version-suppression=passed
  • Embedding index:
    449/449 okattempted=449 succeeded=449 failed=0 pooled=0

Suggested verification

  • (agent) Independently inspect each SLizard finding against the referenced file, surrounding code, and linked context before accepting or dismissing it.
  • (static) Review 1 deterministic/static finding(s) included in the evidence set.

Agent verification brief

  • PR/CR: deftai/vBRIEF#23
  • Head SHA: b2a74f79d3e819e474efabd715b33ce8bba55257
  • Decision: comment
  • Highest-risk claims: P2 libvbrief-ts/src/index.ts:34 residual-gap-contradiction (0.75)
  • Reviewed files: docs/vbrief-spec-0.5.md, docs/vbrief-spec-0.6.md, examples/system-of-record-plan.vbrief.json, libvbrief-ts/src/compat.ts, libvbrief-ts/src/index.ts, libvbrief-ts/src/models.ts, libvbrief-ts/src/schemas.ts, libvbrief-ts/tests/models.test.ts, +4 more
  • Skipped files: none
  • Evidence sources: static analysis, call graph/blast radius, vector context, deterministic checks
  • Known blind spots: none recorded

Decision: comment
Merge impact: non-blocking
Review confidence: 0.51
Decision confidence: 0.51
Finding confidence: n/a
Reason: Findings are advisory under the current severity/confidence policy.
Severity counts: P0: 0, P1: 0, P2: 0, P3: 0
Important files: 12 changed file(s) reviewed; no finding hotspots identified.
Review scope: 12 files, 642 additions, 2 deletions

slizard v0.3.1131

@greptile-apps

greptile-apps Bot commented Jun 4, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds an optional plan.architecture.systemOfRecord block to the vBRIEF schema system, giving downstream Directive RFC work a canonical location for state surface design records before its SOR preflight gate becomes mandatory.

  • Schema/Zod additions: Both JSON schemas gain Architecture, SystemOfRecord, StateSurface, StateClassification, StorageDeclaration, and ReferenceApplication definitions; SystemOfRecord correctly enforces minItems: 1 on stateSurfaces in JSON schema and .min(1) in Zod. A new cross-schema consistency test (test_system_of_record_defs_stay_consistent_across_core_schemas) catches future divergence between the v0.5 and v0.6 schema files.
  • Model promotion: Both Python (libvbrief/models.py) and TypeScript (libvbrief-ts/src/models.ts) promote architecture from an unknown extra field to a first-class optional known field, preserving round-trip ordering. New typed Zod schemas and interfaces are exported from the TypeScript package for SOR consumers.
  • Docs and example: Both spec docs (vbrief-spec-0.5.md, vbrief-spec-0.6.md) receive identical §3.4 Architecture sections, and a representative example vBRIEF document is added.

Confidence Score: 5/5

Safe to merge — purely additive, all new fields are optional, and no existing behaviour is modified.

The change only adds optional fields to a passthrough-tolerant schema; existing documents remain valid without change. Both previously raised concerns (empty stateSurfaces and dual-schema drift) are now addressed: minItems:1 is enforced in both JSON schemas and Zod, and a dedicated consistency test will catch any future divergence between the v0.5 and v0.6 schema files.

No files require special attention.

Important Files Changed

Filename Overview
schemas/vbrief-core.schema.json Adds Architecture, SystemOfRecord (minItems:1), StateSurface, StateClassification, StorageDeclaration, and ReferenceApplication defs; correctly wires architecture into the Plan object via $ref.
schemas/vbrief-core-0.6.schema.json Identical SOR definitions added; the new cross-schema consistency test guards against future divergence from the v0.5 schema.
libvbrief-ts/src/schemas.ts Adds Zod schemas and TypeScript interfaces for all SOR types; SystemOfRecordSchema correctly enforces .min(1) on stateSurfaces matching the JSON schema constraint.
libvbrief-ts/src/models.ts Promotes architecture to a known optional field in PlanInit and Plan, correctly threaded through the constructor, fromMapping, and knownPlanValues serialization path.
libvbrief/models.py Python Plan dataclass promoted architecture to a first-class Any field; consistently added to field order list, from_dict, and _known_plan_values.
tests/test_schema_system_of_record.py New tests verify minItems:1 enforcement and structural equality of all six SOR definitions across both schema files.
tests/test_models_api.py New round-trip test confirms architecture lands as a known field (not in extras) and serializes back correctly.
libvbrief-ts/tests/models.test.ts Round-trip and Zod validation tests added; covers valid parse, empty stateSurfaces rejection, and invalid classification rejection.
examples/system-of-record-plan.vbrief.json Well-formed example demonstrating a full stateSurface with all optional fields and a referenceApplication entry.
docs/vbrief-spec-0.5.md §3.4 Architecture block added with all classification values, referenceApplications description, and a valid inline JSON example.
docs/vbrief-spec-0.6.md Identical §3.4 Architecture block added, consistent with the v0.5 spec.
libvbrief-ts/src/index.ts Exports all new SOR Zod schemas, STATE_CLASSIFICATIONS constant, and TypeScript types for external consumers.
libvbrief-ts/src/compat.ts Adds architecture to PLAN_FIELD_ORDER in the correct position (after metadata, before created), matching the Python and spec ordering.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[vBRIEF Document] --> B[plan]
    B --> C["architecture (optional)"]
    C --> D["systemOfRecord (optional)"]
    D --> E["stateSurfaces (required, minItems 1)"]
    D --> F["referenceApplications (optional)"]
    E --> G["StateSurface\nname + classification required"]
    G --> H["StateClassification enum\n11 values"]
    G --> I["StorageDeclaration\nstring or string array"]
    G --> J["optional fields\nowner, permissionBoundary, migrationRequired, ..."]
    F --> K["ReferenceApplication\nname required"]
    K --> L["evidence, mustPreserve,\nintentionallyNotCarriedForward (optional)"]
Loading

Reviews (2): Last reviewed commit: "fix: enforce non-empty system-of-record ..." | Re-trigger Greptile

Comment thread schemas/vbrief-core.schema.json
Comment thread schemas/vbrief-core.schema.json

@deft-slizard deft-slizard Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Machine-readable verdict
{
  "slizard_verdict": {
    "schema_version": 1,
    "decision": "approve",
    "severity": {
      "P0": 0,
      "P1": 0,
      "P2": 0,
      "P3": 0
    },
    "confidence": 0.576,
    "decision_confidence": 0.576,
    "finding_count": 0,
    "merge_impact": "non-blocking",
    "version": "slizard v0.3.1155",
    "analysis_outcome": "clean_with_rationale",
    "head_sha": "3aa1b2af60933d0215cf71330a48b2afc7116119"
  }
}
**SLizard Review** — 0 findings across 13 file(s)

⚠️ Low-confidence clean review — 0 findings at confidence 0.58 (below 0.60). The reviewer could not confirm whether zero findings reflects clean code or insufficient analytical depth.

Files reviewed:

  • docs/vbrief-spec-0.5.md
  • docs/vbrief-spec-0.6.md
  • examples/system-of-record-plan.vbrief.json
  • libvbrief-ts/src/compat.ts
  • libvbrief-ts/src/index.ts
  • libvbrief-ts/src/models.ts
  • libvbrief-ts/src/schemas.ts
  • libvbrief-ts/tests/models.test.ts
  • libvbrief/models.py
  • schemas/vbrief-core-0.6.schema.json
  • schemas/vbrief-core.schema.json
  • tests/test_models_api.py
  • tests/test_schema_system_of_record.py

Recommendation: A human reviewer should spot-check the files above, especially those with risk tags.

Clean-review rationale:

  • Changed invariant: None. The diff introduces a new optional field (architecture) to the VBRIEF plan schema, extending its capabilities without altering existing structural or data constraints of other fields.
  • Preserved behavior: PLAN_FIELD_ORDER (libvbrief-ts/src/compat.ts:78): The ordering of existing plan fields is preserved, with the new 'architecture' field added at a logical position, ensuring consistent serialization/deserialization.; VBriefDocumentSchema (libvbrief-ts/src/index.ts:33): The overall structure and validation rules for a VBriefDocument are preserved, as the 'architecture' field is an additive and optional property within the 'plan' object.; PlanSchema (libvbrief-ts/src/index.ts:35): The integrity of the PlanSchema is maintained; the new 'architecture' field is introduced as an optional property, not modifying the definition or behavior of existing plan fields.; Specification consistency (docs/vbrief-spec-0.5.md:148): The existing narrative and structural definitions in the specification documents remain unchanged, with the new 'Architecture' section being an additive extension.
  • Tests reviewed: examples/system-of-record-plan.vbrief.json: This new example serves as a functional test case for the 'architecture' field, demonstrating correct structure and data population according to the updated specification and schemas.
  • Residual advisory gaps: While an example is provided, dedicated unit tests for the new 'ArchitectureSchema' and its sub-schemas (e.g., 'SystemOfRecordSchema', 'StateSurfaceSchema') could cover various edge cases, such as invalid types, missing required properties (if any are implicitly required), or malformed data within the 'architecture' object.; The specification (docs/vbrief-spec-0.5.md, docs/vbrief-spec-0.6.md) introduces the 'architecture' field as 'OPTIONAL'. However, for sub-fields within 'architecture' (e.g., 'systemOfRecord', 'stateSurfaces'), the optionality or requirement of their properties (like 'name', 'classification', 'owner') is not explicitly stated. Clarifying these constraints in the documentation would enhance robustness and reduce ambiguity.; Consider adding validation logic that ensures consistency between 'approvedStorage' and 'forbiddenStorage' lists within 'StateSurfaceSchema' (e.g., no storage type should appear in both lists for the same state surface).

Deterministic checks: passed — No vBRIEF artifact domain detected.

Review coverage

  • Reviewed files: docs/vbrief-spec-0.5.md, docs/vbrief-spec-0.6.md, examples/system-of-record-plan.vbrief.json, libvbrief-ts/src/compat.ts, libvbrief-ts/src/index.ts, libvbrief-ts/src/models.ts, libvbrief-ts/src/schemas.ts, libvbrief-ts/tests/models.test.ts, +5 more
  • Skipped files: none
  • Source: github @ 3aa1b2af6093

Context used

  • Static findings: 1
  • Static tools: unused-option
  • Graph/blast radius: 40 changed node(s), 44 affected node(s)
  • Vector context chunks: 42
  • Context availability: full
  • Review categories: default
  • Deterministic checks:
    368/373 passed, 5 failed: unused-option, graph-incompleteness, graph-callsite-not-updated, orphaned-module, graph-validation-gapvbrief-traceability=passed, markdown-fences=passed, unused-exports=passed, query-docstring=passed, xss-sprintf=passed, markdown-xref=passed, aria-target=passed, semantic-role=passed, aria-containment=passed, redundant-assertion=passed, tautological-assertion=passed, resource-lifecycle=passed, cross-diff-consistency=passed, redundant-css-block=passed, template-placeholder=passed, void-async-signal=passed, spread-override=passed, json-indent-consistency=passed, dep-swap=passed, powershell-scoping=passed, diff-truncation=passed, exception-type-contract=passed, dead-none-guard=passed, access-declaration=passed, unused-option=failed, css-property-interaction=passed, jsx-style-indent=passed, regex-breadth=passed, cartesian-fan-out=passed, exec-stdout-parse=passed, sentinel-error-wiring=passed, hardcoded-filemode=passed, api-response-shape=passed, python-cli-arg=passed, taskfile-namespace=passed, vbrief-schema=passed, go-shell-injection=passed, go-discarded-error=passed, go-json-field-exposure=passed, go-mutable-exported-slice=passed, go-silent-error-branch=passed, go-comment-log-contradiction=passed, go-unconditional-message=passed, inline-style-proliferation=passed, unnecessary-nonnull-assertion=passed, double-cast=passed, unguarded-await-cast=passed, ssrf-guard-completeness=passed, error-message-leak=passed, puppeteer-resource-cap=passed, trivial-argument=passed, unused-imports=passed, dead-store=passed, phantom-import=passed, fetch-timeout-guard=passed, log-level-expected-path=passed, unified-diff-construction=passed, sentinel-index-assertion=passed, unguarded-map-lookup=passed, unbounded-prompt-injection=passed, description-diff-consistency=passed, render-branch-symmetry=passed, go-gorm-unchained-error=passed, go-gorm-rowsaffected-noop=passed, error-handling-loop-break=passed, sync-state-batching=passed, sync-revoke-object-url=passed, go-like-wildcard-injection=passed, go-basename-dedup-gap=passed, go-missing-seed-in-migrate=passed, go-write-then-read-unfiltered=passed, go-direct-db-access=passed, async-handler-try-catch=passed, chat-sdk-history=passed, dead-code-ternary=passed, go-context-background=passed, go-git-arg-order=passed, go-n-plus-one=passed, go-nested-transaction=passed, go-ref-injection=passed, go-scanner-error=passed, go-toctou-db=passed, go-unused-validated-field=passed, hardcoded-literal=passed, hardcoded-undefined-field=passed, python-exception=passed, python-path-construction=passed, python-isdigit-int=passed, deprecated-python-utcnow=passed, python-variable-shadow=passed, frozen-dataclass-mutable-field=passed, sentinel-value=passed, sibling-constant=passed, url-interpolation=passed, jsx-guard-removal=passed, asymmetric-clamp=passed, optional-prop-guard=passed, server-lifecycle=passed, go-asymmetric-org-scope=passed, fetch-body-scope-omission=passed, regex-breadth-inconsistency=passed, typeof-object-array-guard=passed, test-production-divergence=passed, argument-axis-mismatch=passed, click-propagation-gap=passed, sanitization-gap=passed, response-shape-consistency=passed, keydown-target-guard=passed, changelog-test-count=passed, unbounded-metadata-assignment=passed, unchecked-json-response=passed, response-body-leak=passed, json-syntax=passed, requestid-route-param=passed, dict-key-as-value=passed, redundant-transitive-call=passed, incomplete-iteration=passed, call-site-parameter-consistency=passed, markdown-heading-level=passed, cross-section-order-contradiction=passed, dangling-reference=passed, typescript-compilation=passed, useref-dead-store=passed, fetch-redirect-guard=passed, response-body-buffering=passed, svg-content-type=passed, conditional-mode-exclusion=passed, join-separator-inconsistency=passed, prompt-injection-guard=passed, asymmetric-guard=passed, unsafe-json-cast=passed, storage-unsafe-cast=passed, markdown-single-line-interpolation=passed, postmessage-origin-guard=passed, css-iframe-scope=passed, markdown-entry-completeness=passed, python-set-duplicate=passed, state-setter-symmetry=passed, changelog-sibling-truncation=passed, ternary-exhaustiveness=passed, exclusive-output-constraint=passed, nullish-fallback-regression=passed, shell-pipefail=passed, vbrief-acceptance-contradiction=passed, css-property-diff=passed, go-sync-call-labeled-background=passed, prompt-guardrail-conflict=passed, prompt-identity-duplication=passed, asymmetric-truncation=passed, claim-source-tracing=passed, go-duplicate-event-publish=passed, go-create-without-cleanup=passed, go-find-then-create-without-cleanup=passed, go-persist-without-validate=passed, ts-put-without-get=passed, go-fetch-id-without-liveness=passed, go-event-subscribe-without-publish=passed, go-log-aggregation-run-scoping=passed, falsy-string-fallback=passed, useeffect-unstable-prop-dep=passed, unused-state-read=passed, blob-mime-mismatch=passed, parseint-nan-guard=passed, shared-state-across-map=passed, context-menu-click-guard=passed, touch-action-ancestor=passed, usestate-innerwidth-matchmedia=passed, prefix-match-loop=passed, hardcoded-new-field=passed, enum-subset-completeness=passed, optional-guard-fallthrough=passed, html-template-token=passed, label-association=passed, empty-src-img=passed, jsx-prose-link-mismatch=passed, try-catch-scope=passed, viewport-meta-accessibility=passed, go-github-api-response-id=passed, go-github-api-pagination=passed, go-gorm-first-without-errrecordnotfound=passed, fetch-cache-consistency=passed, oauth-session-state-binding=passed, go-switch-exhaustiveness=passed, go-test-mutex-asymmetry=passed, nextjs-suspense-boundary=passed, nullable-nested-response=passed, nullish-coalesce-empty-url=passed, asymmetric-callback-state-reset=passed, go-docstring-contract-mismatch=passed, replace-dollar-pattern=passed, conditional-fallthrough-gap=passed, sanitization-completeness=passed, bare-selector-fallback=passed, sanitization-context-mismatch=passed, json-escape-completeness=passed, catch-block-guard-parity=passed, early-exit-guard-subset=passed, html-escape-context-collision=passed, cross-file-inline-duplication=passed, collection-gate-ordering=passed, regex-denylist-anchor-gap=passed, handler-validation-symmetry=passed, go-http-handler-body-persist-without-authz=passed, go-first-element-without-disambiguation=passed, ternary-wrapper-asymmetry=passed, promise-then-without-outer-catch=passed, effect-persist-hydration-race=passed, css-animation-ref=passed, idb-open-lifecycle=passed, interactive-role-mismatch=passed, array-duplicate-field=passed, mid-file-static-import=passed, changelog-section-deletion=passed, comment-anchored-regex=passed, go-sprintf-json-body=passed, observer-boundary-mismatch=passed, hook-return-shape-mismatch=passed, raw-vs-effective-state=passed, unstable-mapped-key=passed, parallel-state-init-divergence=passed, value-callback-prop-coherence=passed, cap-expansion-order=passed, cross-file-comment-claim=passed, useeffect-cleanup=passed, filter-ratio-threshold=passed, setter-argument-asymmetry=passed, panel-scoped-notification=passed, unawaited-async-dependency=passed, prompt-html-anti-pattern=passed, go-empty-collection-write-guard=passed, go-inconsistent-error-wrapping=passed, sentinel-substring-guard=passed, hardcoded-color-in-themed-context=passed, modal-escape-handler=passed, property-read-without-write-path=passed, iframe-nav-intercept-completeness=passed, tagname-case-sensitivity=passed, guard-clause-subsumption=passed, effect-cleanup-race=passed, style-template-injection=passed, textarea-min-height=passed, greedy-lookahead-futility=passed, window-open-null-guard=passed, orphaned-ambient-declaration=passed, char-ordinal-bounds=passed, stale-ref-callback-race=passed, missing-init-check=passed, stderr-redirect=passed, gitignore-tracked-file=passed, eager-defeats-lazy-import=passed, redundant-call-in-scope=passed, test-source-list-diff=passed, mixed-dict-access-pattern=passed, md-fragile-regex-lookahead=passed, misleading-none-branch=passed, discarded-validation-return=passed, loopback-range=passed, trust-proxy=passed, fly-toml-schema=passed, dockerfile-copy-shell-op=passed, dockerfile-build-secret=passed, string-dispatch=passed, python-toctou-file-lock=passed, python-non-reentrant-lock=passed, go-sibling-handler-guard=passed, stale-test-assertion=passed, go-batch-response-counter=passed, go-single-status-error-handler=passed, go-base64-body-size-mismatch=passed, dict-write-lookup-asymmetry=passed, identical-branch=passed, postmessage-targetorigin-regression=passed, react-namespace-import=passed, comment-payload-contradiction=passed, conditional-gating-dead-path=passed, go-mock-interface-completeness=passed, toggle-setter-mismatch=passed, localhost-in-allowlist=passed, unawaited-waitfor=passed, cli-example-validator=passed, python-tz-comparison-asymmetry=passed, missing-wildcard-guard=passed, react-ref-hydration-trigger=passed, react-unused-callback-dep=passed, scope-intent-mismatch=passed, supabase-join-path-mismatch=passed, incomplete-optional-property-guard=passed, retry-reenqueue-without-guard=passed, stale-self-call-in-callback=passed, empty-body-control-flow=passed, self-increment-comparison=passed, sequential-replace-dedup=passed, breaking-export-removal=passed, vacuous-test-assertion=passed, silent-fallible-coalesce=passed, dual-threshold-warning=passed, unresolved-relative-import=passed, coalescing-callback-dispatch=passed, removed-event-propagation-stopper=passed, jsx-inline-style-scope-leak=passed, hook-after-early-return=passed, fs-access-overwrite=passed, type-import-divergence=passed, conditional-state-no-clear=passed, gated-operation-silent-persist=passed, hardcoded-sentinel-dead-path=passed, swift-filepath-disclosure=passed, swift-lba-overflow=passed, swift-xpc-listener-validation=passed, python-weak-substring-match=passed, python-docstring-class-ref=passed, python-unused-subprocess-output=passed, python-narrow-exception-handler=passed, usememo-missing-dep=passed, localstorage-stale-cache=passed, localstorage-scope=passed, dead-action-variant=passed, switch-param-forwarding-gap=passed, changelog-entry-style=passed, vbrief-edge-completeness=passed, pr-body-vbrief-scope=passed, abort-signal-timeout-guard=passed, whitespace-control-char=passed, transient-error-permanent-state=passed, unused-variable=passed, postmessage-source-null-check=passed, atob-encoding-check=passed, phantom-identity-fallback-check=passed, workflow-comment-secret=passed, rls-circular-dep=passed, writable-stream-abort=passed, error-type-shadowing=passed, unguarded-iteration-component=passed, ci-checksum-provenance=passed, react-error-cache-nav-reset=passed, shell-injection-template=passed, flag-reset=passed, excess-property=passed, timestamp-sanitization-reuse=passed, boolean-null-guard=passed, catch-typeof-swallow=passed, optional-strict-compare=passed, leaked-debug-text=passed, inconsistent-component-import=passed, wrong-domain-copy=passed, unconditional-lfs-filter=passed, toml-config-injection=passed, dead-popen-timeout-except=passed, python-unused-local=passed, async-event-lock-no-recovery=passed, webkit-cancel-compat=passed, dom-cleanup-racing-interaction=passed, nonstandard-code-fence=passed, vba-value2-single-cell=passed, vba-doc-error-handler=passed, officejs-doc-sync-batching=passed, regex-word-boundary-method-name=passed, sliding-window-dedup=passed, double-localstorage-key-write=passed, new-class-missing-option=passed, branch-reset-asymmetry=passed, changelog-placeholder=passed, cockpit-state-before-try=passed, format-conversion-fallthrough=passed, normalize-to-empty=passed, sql-cursor-pagination-index=passed, temporary-debug-flag=passed, debug-console-log=passed, graph-incompleteness=skipped, graph-callsite-not-updated=skipped, orphaned-module=skipped, graph-validation-gap=skipped, lockfile-version-suppression=passed
  • Embedding index:
    48/48 okattempted=48 succeeded=48 failed=0 pooled=0

Suggested verification

  • (agent) Spot-check the highest-risk changed files and confirm the clean review did not skip relevant files or context.
  • (static) Review 1 deterministic/static finding(s) included in the evidence set.

Agent verification brief

  • PR/CR: deftai/vBRIEF#23
  • Head SHA: 3aa1b2af60933d0215cf71330a48b2afc7116119
  • Decision: approve
  • Highest-risk claims: none
  • Reviewed files: docs/vbrief-spec-0.5.md, docs/vbrief-spec-0.6.md, examples/system-of-record-plan.vbrief.json, libvbrief-ts/src/compat.ts, libvbrief-ts/src/index.ts, libvbrief-ts/src/models.ts, libvbrief-ts/src/schemas.ts, libvbrief-ts/tests/models.test.ts, +5 more
  • Skipped files: none
  • Evidence sources: static analysis, call graph/blast radius, vector context, deterministic checks
  • Known blind spots: none recorded

Decision: approve
Merge impact: non-blocking
Review confidence: 0.58
Decision confidence: 0.58
Finding confidence: n/a
Reason: No findings survived validation and all configured analysis completed.
Important files: 13 changed file(s) reviewed; no finding hotspots identified.
Review scope: 13 files, 727 additions, 2 deletions

slizard v0.3.1155

@dbcall2 dbcall2 changed the title Add plan architecture system-of-record schema Proposal: add plan architecture system-of-record schema Jun 4, 2026
@dbcall2

dbcall2 commented Jun 4, 2026

Copy link
Copy Markdown
Author

Reframed this PR as a concrete proposal/candidate implementation rather than an immediate merge request.

The main request now is maintainer guidance on schema home: core plan.architecture.systemOfRecord, a vBRIEF architecture/profile extension, or a consumer namespace such as x-directive/architecture.

The branch remains passing and mergeable if core is the right home. If core is too early, I can convert this into a proposal-only docs PR or follow up with a narrower extension/profile shape.

@dbcall2

dbcall2 commented Jun 9, 2026

Copy link
Copy Markdown
Author

@visionik This look okay?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant