Skip to content

feat(spec): upgrade vBRIEF to v0.7#20

Open
visionik wants to merge 1 commit into
masterfrom
feat/v0.7-spec-upgrade
Open

feat(spec): upgrade vBRIEF to v0.7#20
visionik wants to merge 1 commit into
masterfrom
feat/v0.7-spec-upgrade

Conversation

@visionik

@visionik visionik commented May 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

Upgrades the vBRIEF specification from v0.6 to v0.7, implementing issues #12#18 (excluding #19, which was closed as deferred).

Changes

Spec (docs/vbrief-spec-0.7.md)

Schema (schemas/vbrief-core-0.7.schema.json)

  • type enum, summary string, planRefs array on PlanItem
  • auto added to Status enum
  • patternProperties for extension namespace at all object levels
  • Source/Confidence in narrative properties
  • Updated VBriefReference descriptions with full registry

Python lib (libvbrief/)

  • models.pytype, summary, planRefs, items fields on PlanItem with round-trip support
  • compat/policy.pyfailed/auto in VALID_STATUSES; VALID_ITEM_TYPES, VALID_VERSIONS, EXTENSION_PROPERTY_PATTERN
  • validation.py — Accepts 0.5/0.6/0.7; validates type values and planRefs entries

Other

  • Examples updated to v0.7
  • README updated (version refs, repo URL fixed to deftai/vBRIEF)
  • 132 tests pass, zero regressions

Issues

Closes #13, closes #14, closes #15, closes #17, closes #18
Refs #12
#19 closed separately as deferred


Warp conversation

- Add PlanItem type field (task/group/milestone/epic) with auto status rollup (#13)
- Add PlanItem summary string field (#14)
- Add PlanItem planRefs array for container items (#15)
- Add extension properties namespace x-<consumer>/ with round-trip preservation (#12)
- Add Source and Confidence recommended narrative keys (#17)
- Add canonical x-vbrief/* reference type registry (#18)
- Add failed and auto to Status enum
- Update Python lib models, validation, and compat
- Update examples and README to v0.7
- Close #19 (delta/patch document type — deferred)

Closes #13, closes #14, closes #15, closes #17, closes #18
Refs #12
@greptile-apps

greptile-apps Bot commented May 4, 2026

Copy link
Copy Markdown

Greptile Summary

This PR upgrades the vBRIEF specification and Python library from v0.6 to v0.7, adding type/summary/planRefs fields on PlanItem, a formal extension property namespace (x-<consumer>/), provenance narrative keys, and a reference type registry. The spec, schema, and model changes are well-executed, but the validator has two defects that need fixing before merge:

  • _validate_items recurses only into subItems and never into the new preferred items field, so all PlanItems nested under items (the recommended v0.7 nesting path) bypass every validation check.
  • Adding \"auto\" to the shared VALID_STATUSES set allows plan.status = \"auto\" to pass plan-level validation, which is meaningless at the Plan level and violates the spec.

Confidence Score: 3/5

Not safe to merge — two P1 validator bugs mean invalid documents are silently accepted

Two P1 findings on a core path (validation) lower the score below the P1 ceiling of 4. The first bug (missing recursion into items) affects every v0.7 hierarchical plan; the second (auto at plan level) violates a normative spec constraint. Both are straightforward fixes but need to land before release.

libvbrief/validation.py (missing items recursion, missing auto-on-task guard) and libvbrief/compat/policy.py (VALID_STATUSES shared with plan-level check)

Important Files Changed

Filename Overview
libvbrief/validation.py Adds item type and planRefs validation; critical bug: _validate_items never recurses into the new preferred items field, leaving all nested PlanItems under items unvalidated
libvbrief/compat/policy.py Adds VALID_ITEM_TYPES, VALID_VERSIONS, EXTENSION_PROPERTY_PATTERN; adding "auto" to VALID_STATUSES inadvertently allows plan.status = "auto" to pass validation
libvbrief/models.py Adds type, summary, planRefs, and items fields to PlanItem with correct round-trip support; post-constructor assignment for items is functional but inconsistent with idiomatic dataclass usage
schemas/vbrief-core-0.7.schema.json New schema correctly adds type enum, summary, planRefs, auto status, patternProperties for extension namespace, and VBriefReference type registry
docs/vbrief-spec-0.7.md New v0.7 spec document; well-structured with clear normative language covering all new features (type/summary/planRefs/extensions/provenance/registry)
libvbrief/compat/init.py Exports new policy constants; clean addition with no issues
README.md Updates version references to 0.7 and corrects repo URL from visionik/vBRIEF to deftai/vBRIEF

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[validate_document] --> B[_validate_root]
    B --> C[_validate_plan]
    C --> D{plan.status in VALID_STATUSES?}
    D -- "auto now allowed ⚠️" --> E[No error raised]
    C --> F[_validate_items - plan.items]
    F --> G{For each item}
    G --> H[Validate title/status/id/type/planRef/planRefs]
    H --> I{item.get subItems?}
    I -- present --> J[_validate_items recurse - subItems ✅]
    I -- absent --> K[continue - skip item.get items ⚠️]
    G --> K
    J --> G
    H --> L{status: auto?}
    L -- "task type or childless" --> M[No error raised ⚠️]
Loading

Comments Outside Diff (2)

  1. libvbrief/validation.py, line 228-239 (link)

    P1 Nested items field not validated recursively

    _validate_items recurses only into subItems (line 239). The new v0.7 preferred field items on a PlanItem is fetched and parsed by the model (models.py line 184–186) but is never passed to a recursive _validate_items call. Any PlanItems nested under items escape all validation checks — missing required fields, invalid statuses, bad planRef URIs, duplicate IDs, etc.

    Since v0.7 explicitly recommends items over subItems and all new examples use it, this leaves the primary nesting path completely unvalidated.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: libvbrief/validation.py
    Line: 228-239
    
    Comment:
    **Nested `items` field not validated recursively**
    
    `_validate_items` recurses only into `subItems` (line 239). The new v0.7 preferred field `items` on a PlanItem is fetched and parsed by the model (`models.py` line 184–186) but is never passed to a recursive `_validate_items` call. Any PlanItems nested under `items` escape all validation checks — missing required fields, invalid statuses, bad `planRef` URIs, duplicate IDs, etc.
    
    Since v0.7 explicitly recommends `items` over `subItems` and all new examples use it, this leaves the primary nesting path completely unvalidated.
    
    How can I resolve this? If you propose a fix, please make it concise.
  2. libvbrief/validation.py, line 170-201 (link)

    P2 status: "auto" on task-type or childless items not rejected

    The spec says status: "auto" MUST NOT be used on items with type: "task" or items with no children, and that this constitutes a validation error. The added validation (lines 195–201) only checks that type is a valid string; there is no cross-field check that catches {"type": "task", "status": "auto"} or {"type": "group", "status": "auto", "items": []} as errors.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: libvbrief/validation.py
    Line: 170-201
    
    Comment:
    **`status: "auto"` on task-type or childless items not rejected**
    
    The spec says `status: "auto"` MUST NOT be used on items with `type: "task"` or items with no children, and that this constitutes a validation error. The added validation (lines 195–201) only checks that `type` is a valid string; there is no cross-field check that catches `{"type": "task", "status": "auto"}` or `{"type": "group", "status": "auto", "items": []}` as errors.
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
Fix the following 4 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 4
libvbrief/validation.py:228-239
**Nested `items` field not validated recursively**

`_validate_items` recurses only into `subItems` (line 239). The new v0.7 preferred field `items` on a PlanItem is fetched and parsed by the model (`models.py` line 184–186) but is never passed to a recursive `_validate_items` call. Any PlanItems nested under `items` escape all validation checks — missing required fields, invalid statuses, bad `planRef` URIs, duplicate IDs, etc.

Since v0.7 explicitly recommends `items` over `subItems` and all new examples use it, this leaves the primary nesting path completely unvalidated.

### Issue 2 of 4
libvbrief/compat/policy.py:13-22
**`"auto"` in `VALID_STATUSES` makes `plan.status = "auto"` pass validation**

`VALID_STATUSES` is shared between plan-level and item-level status checks. Adding `"auto"` here means `_validate_plan` (`validation.py` line 109) will accept `plan.status = "auto"`, which has no defined semantics at the Plan level and directly violates the spec's constraint that `"auto"` is valid **only on container PlanItems** (`group`, `milestone`, `epic`) with children.

Additionally, no validation enforces the per-item constraint (`MUST NOT` on `type: "task"` or childless items), but the plan-level bleed-through is the most concrete present defect since it produces no error on clearly invalid documents.

### Issue 3 of 4
libvbrief/validation.py:170-201
**`status: "auto"` on task-type or childless items not rejected**

The spec says `status: "auto"` MUST NOT be used on items with `type: "task"` or items with no children, and that this constitutes a validation error. The added validation (lines 195–201) only checks that `type` is a valid string; there is no cross-field check that catches `{"type": "task", "status": "auto"}` or `{"type": "group", "status": "auto", "items": []}` as errors.

### Issue 4 of 4
libvbrief/models.py:184-192
**`items` field omitted from `from_dict` constructor call, then reassigned**

`items` is handled by setting `item.items` after the constructor call (lines 184–186), bypassing the dataclass constructor. This means the `items` dataclass field's `default_factory` is invoked by `cls(...)` (creating an empty list), and then immediately overwritten. While functionally correct today, it departs from the idiomatic dataclass pattern. A comment explaining the deliberate split (matching the `subItems` pattern) would prevent confusion in future refactors.

Reviews (1): Last reviewed commit: "feat(spec): upgrade vBRIEF to v0.7" | Re-trigger Greptile

Comment on lines 13 to +22
"running",
"completed",
"blocked",
"failed",
"cancelled",
"auto",
}

VALID_ITEM_TYPES: Final[set[str]] = {
"task",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 "auto" in VALID_STATUSES makes plan.status = "auto" pass validation

VALID_STATUSES is shared between plan-level and item-level status checks. Adding "auto" here means _validate_plan (validation.py line 109) will accept plan.status = "auto", which has no defined semantics at the Plan level and directly violates the spec's constraint that "auto" is valid only on container PlanItems (group, milestone, epic) with children.

Additionally, no validation enforces the per-item constraint (MUST NOT on type: "task" or childless items), but the plan-level bleed-through is the most concrete present defect since it produces no error on clearly invalid documents.

Prompt To Fix With AI
This is a comment left during a code review.
Path: libvbrief/compat/policy.py
Line: 13-22

Comment:
**`"auto"` in `VALID_STATUSES` makes `plan.status = "auto"` pass validation**

`VALID_STATUSES` is shared between plan-level and item-level status checks. Adding `"auto"` here means `_validate_plan` (`validation.py` line 109) will accept `plan.status = "auto"`, which has no defined semantics at the Plan level and directly violates the spec's constraint that `"auto"` is valid **only on container PlanItems** (`group`, `milestone`, `epic`) with children.

Additionally, no validation enforces the per-item constraint (`MUST NOT` on `type: "task"` or childless items), but the plan-level bleed-through is the most concrete present defect since it produces no error on clearly invalid documents.

How can I resolve this? If you propose a fix, please make it concise.

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