docassert 0.18.0__tar.gz → 0.19.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. {docassert-0.18.0/docassert.egg-info → docassert-0.19.0}/PKG-INFO +1 -1
  2. {docassert-0.18.0 → docassert-0.19.0}/docassert/__init__.py +1 -1
  3. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/consistency.yaml +6 -0
  4. {docassert-0.18.0 → docassert-0.19.0}/docassert/status/derive.py +25 -7
  5. {docassert-0.18.0 → docassert-0.19.0/docassert.egg-info}/PKG-INFO +1 -1
  6. {docassert-0.18.0 → docassert-0.19.0}/tests/test_status.py +29 -3
  7. {docassert-0.18.0 → docassert-0.19.0}/LICENSE +0 -0
  8. {docassert-0.18.0 → docassert-0.19.0}/NOTICE +0 -0
  9. {docassert-0.18.0 → docassert-0.19.0}/README.md +0 -0
  10. {docassert-0.18.0 → docassert-0.19.0}/docassert/__main__.py +0 -0
  11. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/adr.criteria.yaml +0 -0
  12. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/benefits-realization.criteria.yaml +0 -0
  13. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/brd.criteria.yaml +0 -0
  14. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/business-case.criteria.yaml +0 -0
  15. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/charter.criteria.yaml +0 -0
  16. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/data-migration-plan.criteria.yaml +0 -0
  17. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/frnfr.criteria.yaml +0 -0
  18. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/hypercare-plan.criteria.yaml +0 -0
  19. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/operations.criteria.yaml +0 -0
  20. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/post-implementation-review.criteria.yaml +0 -0
  21. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/prd.criteria.yaml +0 -0
  22. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/project.criteria.yaml +0 -0
  23. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/qa-test-plan.criteria.yaml +0 -0
  24. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/raci-stakeholder.criteria.yaml +0 -0
  25. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/release-cutover-plan.criteria.yaml +0 -0
  26. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/risk-register.criteria.yaml +0 -0
  27. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/rollback-plan.criteria.yaml +0 -0
  28. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/runbook.criteria.yaml +0 -0
  29. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/status-report.criteria.yaml +0 -0
  30. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/test-cases.criteria.yaml +0 -0
  31. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/criteria/user-story.criteria.yaml +0 -0
  32. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/profiles/agile-delivery.yaml +0 -0
  33. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/profiles/lean-startup.yaml +0 -0
  34. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/profiles/operations.yaml +0 -0
  35. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/profiles/regulated-industry.yaml +0 -0
  36. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/adr.schema.json +0 -0
  37. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/benefits-realization.schema.json +0 -0
  38. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/brd.schema.json +0 -0
  39. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/business-case.schema.json +0 -0
  40. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/charter.schema.json +0 -0
  41. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/data-migration-plan.schema.json +0 -0
  42. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/frnfr.schema.json +0 -0
  43. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/hypercare-plan.schema.json +0 -0
  44. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/operations.schema.json +0 -0
  45. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/post-implementation-review.schema.json +0 -0
  46. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/prd.schema.json +0 -0
  47. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/project.schema.json +0 -0
  48. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/qa-test-plan.schema.json +0 -0
  49. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/raci-stakeholder.schema.json +0 -0
  50. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/release-cutover-plan.schema.json +0 -0
  51. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/risk-register.schema.json +0 -0
  52. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/rollback-plan.schema.json +0 -0
  53. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/runbook.schema.json +0 -0
  54. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/status-report.schema.json +0 -0
  55. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/test-cases.schema.json +0 -0
  56. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/schema/user-story.schema.json +0 -0
  57. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/skills/doc-to-pmo/SKILL.md +0 -0
  58. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/adr.template.md +0 -0
  59. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/benefits-realization.template.md +0 -0
  60. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/brd.template.md +0 -0
  61. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/business-case.template.md +0 -0
  62. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/charter.template.md +0 -0
  63. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/data-migration-plan.template.md +0 -0
  64. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/frnfr.template.md +0 -0
  65. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/hypercare-plan.template.md +0 -0
  66. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/operations.template.md +0 -0
  67. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/post-implementation-review.template.md +0 -0
  68. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/prd.template.md +0 -0
  69. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/project.template.md +0 -0
  70. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/qa-test-plan.template.md +0 -0
  71. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/raci-stakeholder.template.md +0 -0
  72. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/release-cutover-plan.template.md +0 -0
  73. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/risk-register.template.md +0 -0
  74. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/rollback-plan.template.md +0 -0
  75. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/runbook.template.md +0 -0
  76. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/status-report.template.md +0 -0
  77. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/test-cases.template.md +0 -0
  78. {docassert-0.18.0 → docassert-0.19.0}/docassert/_data/templates/user-story.template.md +0 -0
  79. {docassert-0.18.0 → docassert-0.19.0}/docassert/bridge/__init__.py +0 -0
  80. {docassert-0.18.0 → docassert-0.19.0}/docassert/bridge/board.py +0 -0
  81. {docassert-0.18.0 → docassert-0.19.0}/docassert/bridge/gh.py +0 -0
  82. {docassert-0.18.0 → docassert-0.19.0}/docassert/bridge/ops.py +0 -0
  83. {docassert-0.18.0 → docassert-0.19.0}/docassert/bridge/plan.py +0 -0
  84. {docassert-0.18.0 → docassert-0.19.0}/docassert/cli.py +0 -0
  85. {docassert-0.18.0 → docassert-0.19.0}/docassert/config.py +0 -0
  86. {docassert-0.18.0 → docassert-0.19.0}/docassert/consistency.py +0 -0
  87. {docassert-0.18.0 → docassert-0.19.0}/docassert/extract.py +0 -0
  88. {docassert-0.18.0 → docassert-0.19.0}/docassert/graph.py +0 -0
  89. {docassert-0.18.0 → docassert-0.19.0}/docassert/loader.py +0 -0
  90. {docassert-0.18.0 → docassert-0.19.0}/docassert/models.py +0 -0
  91. {docassert-0.18.0 → docassert-0.19.0}/docassert/profiles.py +0 -0
  92. {docassert-0.18.0 → docassert-0.19.0}/docassert/projects.py +0 -0
  93. {docassert-0.18.0 → docassert-0.19.0}/docassert/report.py +0 -0
  94. {docassert-0.18.0 → docassert-0.19.0}/docassert/rtm.py +0 -0
  95. {docassert-0.18.0 → docassert-0.19.0}/docassert/scaffold.py +0 -0
  96. {docassert-0.18.0 → docassert-0.19.0}/docassert/semantic.py +0 -0
  97. {docassert-0.18.0 → docassert-0.19.0}/docassert/status/__init__.py +0 -0
  98. {docassert-0.18.0 → docassert-0.19.0}/docassert/status/render.py +0 -0
  99. {docassert-0.18.0 → docassert-0.19.0}/docassert/structural.py +0 -0
  100. {docassert-0.18.0 → docassert-0.19.0}/docassert.egg-info/SOURCES.txt +0 -0
  101. {docassert-0.18.0 → docassert-0.19.0}/docassert.egg-info/dependency_links.txt +0 -0
  102. {docassert-0.18.0 → docassert-0.19.0}/docassert.egg-info/entry_points.txt +0 -0
  103. {docassert-0.18.0 → docassert-0.19.0}/docassert.egg-info/requires.txt +0 -0
  104. {docassert-0.18.0 → docassert-0.19.0}/docassert.egg-info/top_level.txt +0 -0
  105. {docassert-0.18.0 → docassert-0.19.0}/pyproject.toml +0 -0
  106. {docassert-0.18.0 → docassert-0.19.0}/setup.cfg +0 -0
  107. {docassert-0.18.0 → docassert-0.19.0}/tests/test_badge.py +0 -0
  108. {docassert-0.18.0 → docassert-0.19.0}/tests/test_bridge.py +0 -0
  109. {docassert-0.18.0 → docassert-0.19.0}/tests/test_config.py +0 -0
  110. {docassert-0.18.0 → docassert-0.19.0}/tests/test_consistency.py +0 -0
  111. {docassert-0.18.0 → docassert-0.19.0}/tests/test_defects.py +0 -0
  112. {docassert-0.18.0 → docassert-0.19.0}/tests/test_draft_relaxation.py +0 -0
  113. {docassert-0.18.0 → docassert-0.19.0}/tests/test_extract.py +0 -0
  114. {docassert-0.18.0 → docassert-0.19.0}/tests/test_graph.py +0 -0
  115. {docassert-0.18.0 → docassert-0.19.0}/tests/test_json_report.py +0 -0
  116. {docassert-0.18.0 → docassert-0.19.0}/tests/test_kinds_delivery.py +0 -0
  117. {docassert-0.18.0 → docassert-0.19.0}/tests/test_kinds_governance.py +0 -0
  118. {docassert-0.18.0 → docassert-0.19.0}/tests/test_kinds_operate.py +0 -0
  119. {docassert-0.18.0 → docassert-0.19.0}/tests/test_kinds_reporting.py +0 -0
  120. {docassert-0.18.0 → docassert-0.19.0}/tests/test_profiles.py +0 -0
  121. {docassert-0.18.0 → docassert-0.19.0}/tests/test_projects.py +0 -0
  122. {docassert-0.18.0 → docassert-0.19.0}/tests/test_report_extract.py +0 -0
  123. {docassert-0.18.0 → docassert-0.19.0}/tests/test_scaffold.py +0 -0
  124. {docassert-0.18.0 → docassert-0.19.0}/tests/test_semantic.py +0 -0
  125. {docassert-0.18.0 → docassert-0.19.0}/tests/test_structural.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: docassert
3
- Version: 0.18.0
3
+ Version: 0.19.0
4
4
  Summary: Unit testing for business documents — validate structured Markdown docs against a configurable audit standard.
5
5
  Author: C4G Enterprises Inc.
6
6
  License: Apache-2.0
@@ -5,4 +5,4 @@ standard: deterministic structural checks that gate a merge, plus optional
5
5
  AI-graded semantic checks that advise.
6
6
  """
7
7
 
8
- __version__ = "0.18.0"
8
+ __version__ = "0.19.0"
@@ -39,6 +39,12 @@ coverage:
39
39
  # (0 = no cap).
40
40
  alignment_limit: 25
41
41
 
42
+ # Open risks move derived status to amber only at or above this
43
+ # probability x impact score (low=1 medium=2 high/critical=3). 0 = any open
44
+ # risk ambers (the strict pre-0.19 behavior). Exposure below the threshold
45
+ # stays fully reported; it just doesn't flatten the headline.
46
+ risk_amber_score: 6
47
+
42
48
  # Rules match in order; the first matching rule grades a link. Typed rules
43
49
  # (child_type/parent_type) come before the generic ones.
44
50
  alignment:
@@ -135,15 +135,29 @@ def _milestones(docs):
135
135
  due = datetime.date.fromisoformat(m.group("date"))
136
136
  except ValueError:
137
137
  continue
138
- delta = (due - today).days
139
- out.append({"label": m.group("label").strip(),
140
- "date": due.isoformat(),
141
- "days": delta,
142
- "when": ("today" if delta == 0 else
143
- "elapsed" if delta < 0 else "upcoming")})
138
+ out.append(_ms_entry(m.group("label").strip(), due, today))
139
+ for d in docs:
140
+ if d.kind != "charter":
141
+ continue
142
+ target = (d.frontmatter.get("dates") or {}).get("target")
143
+ if target:
144
+ try:
145
+ due = (target if isinstance(target, datetime.date)
146
+ else datetime.date.fromisoformat(str(target)))
147
+ if not any(x["date"] == due.isoformat() for x in out):
148
+ out.append(_ms_entry("Charter target", due, today))
149
+ except (TypeError, ValueError):
150
+ pass
144
151
  return sorted(out, key=lambda x: x["date"])
145
152
 
146
153
 
154
+ def _ms_entry(label, due, today):
155
+ delta = (due - today).days
156
+ return {"label": label, "date": due.isoformat(), "days": delta,
157
+ "when": ("today" if delta == 0 else
158
+ "elapsed" if delta < 0 else "upcoming")}
159
+
160
+
147
161
  def _operations(docs):
148
162
  """Operations documents with their review state."""
149
163
  import datetime
@@ -234,6 +248,7 @@ def build_status(documents_dir=DOCUMENTS_DIR, project: str | None = None) -> dic
234
248
  "broken_references": _broken_references(graph, code),
235
249
  "latest_report": _latest_report(docs),
236
250
  "completeness": completeness,
251
+ "risk_amber_score": int(cfg.get("risk_amber_score", 6) or 0),
237
252
  }
238
253
  model["rag"] = derive_rag(model)
239
254
  return model
@@ -313,7 +328,10 @@ def derive_rag(model) -> str:
313
328
  reported = (model["latest_report"] or {}).get("rag")
314
329
  completeness_gap = bool(comp and (comp["missing_required"] or comp["incomplete_required"]
315
330
  or comp["recommended_gaps"] or comp.get("unknown")))
316
- open_risks = [r for r in model["risks"] if r.get("disposition", "open") == "open"]
331
+ threshold = model.get("risk_amber_score", 6)
332
+ open_risks = [r for r in model["risks"]
333
+ if r.get("disposition", "open") == "open"
334
+ and (threshold == 0 or r.get("score", 0) >= threshold)]
317
335
  stale_ops = [o for o in model.get("operations", []) if not o["fresh"]]
318
336
  if (coverage_gap or open_risks or stale_ops
319
337
  or reported in {"amber", "red"} or completeness_gap):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: docassert
3
- Version: 0.18.0
3
+ Version: 0.19.0
4
4
  Summary: Unit testing for business documents — validate structured Markdown docs against a configurable audit standard.
5
5
  Author: C4G Enterprises Inc.
6
6
  License: Apache-2.0
@@ -53,7 +53,9 @@ def test_rag_red_on_failing_approved_doc():
53
53
 
54
54
 
55
55
  def test_rag_amber_on_open_risk():
56
- assert S.derive_rag(_model(risks=[{"id": "RISK-1", "score": 4}])) == "amber"
56
+ # at or above the appetite (default 6) ambers; below stays green
57
+ assert S.derive_rag(_model(risks=[{"id": "RISK-1", "score": 6}])) == "amber"
58
+ assert S.derive_rag(_model(risks=[{"id": "RISK-1", "score": 4}])) == "green"
57
59
 
58
60
 
59
61
  def test_rag_amber_on_coverage_gap():
@@ -189,8 +191,8 @@ def test_disposition_parsed_and_defaulted():
189
191
  def test_rag_green_when_all_risks_dispositioned():
190
192
  base = {"documents": [], "coverage": [], "broken_references": [],
191
193
  "latest_report": None, "completeness": None}
192
- open_r = dict(base, risks=[{"id": "R", "score": 2, "disposition": "open"}])
193
- done_r = dict(base, risks=[{"id": "R", "score": 2, "disposition": "accepted"}])
194
+ open_r = dict(base, risks=[{"id": "R", "score": 6, "disposition": "open"}])
195
+ done_r = dict(base, risks=[{"id": "R", "score": 6, "disposition": "accepted"}])
194
196
  assert S.derive_rag(open_r) == "amber"
195
197
  assert S.derive_rag(done_r) == "green"
196
198
 
@@ -275,3 +277,27 @@ def test_svc_and_freshness_checks(tmp_path):
275
277
  assert ok
276
278
  fresh_ok, detail = check_ops_review_fresh(doc, ctx)
277
279
  assert not fresh_ok and "overdue" in detail
280
+
281
+
282
+ # ── risk appetite (spec 0.7.0) ───────────────────────────────────────────────
283
+ def test_low_grade_open_risks_do_not_amber():
284
+ base = {"documents": [], "coverage": [], "broken_references": [],
285
+ "latest_report": None, "completeness": None, "operations": [],
286
+ "risk_amber_score": 6}
287
+ low = dict(base, risks=[{"id": "R", "score": 4, "disposition": "open"}])
288
+ hi = dict(base, risks=[{"id": "R", "score": 6, "disposition": "open"}])
289
+ strict = dict(low, risk_amber_score=0)
290
+ assert S.derive_rag(low) == "green"
291
+ assert S.derive_rag(hi) == "amber"
292
+ assert S.derive_rag(strict) == "amber"
293
+
294
+
295
+ def test_charter_target_becomes_implicit_milestone():
296
+ _cd_root()
297
+ m = S.build_status(ROOT / "documents", project="PRJ-002-ATL")
298
+ dates = [x["label"] for x in m["milestones"]]
299
+ assert any("Charter target" in lbl or lbl for lbl in dates) or m["milestones"] == []
300
+ # Aurora has explicit dated milestones AND a target; no duplicates by date
301
+ m2 = S.build_status(ROOT / "documents", project="PRJ-001-AUR")
302
+ seen = [x["date"] for x in m2["milestones"]]
303
+ assert len(seen) == len(set(seen))
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes