docassert 0.6.0__tar.gz → 0.7.1__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 (113) hide show
  1. {docassert-0.6.0/docassert.egg-info → docassert-0.7.1}/PKG-INFO +7 -2
  2. {docassert-0.6.0 → docassert-0.7.1}/README.md +6 -1
  3. {docassert-0.6.0 → docassert-0.7.1}/docassert/__init__.py +1 -1
  4. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/adr.criteria.yaml +6 -2
  5. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/benefits-realization.criteria.yaml +6 -2
  6. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/brd.criteria.yaml +5 -1
  7. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/business-case.criteria.yaml +5 -1
  8. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/charter.criteria.yaml +7 -3
  9. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/data-migration-plan.criteria.yaml +6 -2
  10. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/frnfr.criteria.yaml +5 -1
  11. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/hypercare-plan.criteria.yaml +6 -2
  12. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/post-implementation-review.criteria.yaml +5 -1
  13. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/prd.criteria.yaml +5 -1
  14. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/project.criteria.yaml +5 -1
  15. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/qa-test-plan.criteria.yaml +6 -2
  16. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/raci-stakeholder.criteria.yaml +6 -2
  17. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/release-cutover-plan.criteria.yaml +6 -2
  18. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/risk-register.criteria.yaml +6 -2
  19. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/rollback-plan.criteria.yaml +6 -2
  20. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/runbook.criteria.yaml +6 -2
  21. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/status-report.criteria.yaml +6 -2
  22. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/test-cases.criteria.yaml +5 -1
  23. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/criteria/user-story.criteria.yaml +6 -2
  24. {docassert-0.6.0 → docassert-0.7.1}/docassert/cli.py +7 -6
  25. {docassert-0.6.0 → docassert-0.7.1}/docassert/report.py +10 -5
  26. docassert-0.7.1/docassert/status/__init__.py +26 -0
  27. docassert-0.7.1/docassert/status/derive.py +231 -0
  28. docassert-0.6.0/docassert/status.py → docassert-0.7.1/docassert/status/render.py +10 -235
  29. {docassert-0.6.0 → docassert-0.7.1}/docassert/structural.py +51 -9
  30. {docassert-0.6.0 → docassert-0.7.1/docassert.egg-info}/PKG-INFO +7 -2
  31. {docassert-0.6.0 → docassert-0.7.1}/docassert.egg-info/SOURCES.txt +4 -1
  32. {docassert-0.6.0 → docassert-0.7.1}/pyproject.toml +2 -2
  33. docassert-0.7.1/tests/test_draft_relaxation.py +138 -0
  34. {docassert-0.6.0 → docassert-0.7.1}/LICENSE +0 -0
  35. {docassert-0.6.0 → docassert-0.7.1}/NOTICE +0 -0
  36. {docassert-0.6.0 → docassert-0.7.1}/docassert/__main__.py +0 -0
  37. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/consistency.yaml +0 -0
  38. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/profiles/agile-delivery.yaml +0 -0
  39. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/profiles/lean-startup.yaml +0 -0
  40. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/profiles/regulated-industry.yaml +0 -0
  41. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/adr.schema.json +0 -0
  42. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/benefits-realization.schema.json +0 -0
  43. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/brd.schema.json +0 -0
  44. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/business-case.schema.json +0 -0
  45. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/charter.schema.json +0 -0
  46. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/data-migration-plan.schema.json +0 -0
  47. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/frnfr.schema.json +0 -0
  48. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/hypercare-plan.schema.json +0 -0
  49. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/post-implementation-review.schema.json +0 -0
  50. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/prd.schema.json +0 -0
  51. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/project.schema.json +0 -0
  52. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/qa-test-plan.schema.json +0 -0
  53. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/raci-stakeholder.schema.json +0 -0
  54. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/release-cutover-plan.schema.json +0 -0
  55. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/risk-register.schema.json +0 -0
  56. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/rollback-plan.schema.json +0 -0
  57. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/runbook.schema.json +0 -0
  58. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/status-report.schema.json +0 -0
  59. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/test-cases.schema.json +0 -0
  60. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/schema/user-story.schema.json +0 -0
  61. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/skills/doc-to-pmo/SKILL.md +0 -0
  62. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/adr.template.md +0 -0
  63. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/benefits-realization.template.md +0 -0
  64. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/brd.template.md +0 -0
  65. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/business-case.template.md +0 -0
  66. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/charter.template.md +0 -0
  67. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/data-migration-plan.template.md +0 -0
  68. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/frnfr.template.md +0 -0
  69. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/hypercare-plan.template.md +0 -0
  70. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/post-implementation-review.template.md +0 -0
  71. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/prd.template.md +0 -0
  72. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/project.template.md +0 -0
  73. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/qa-test-plan.template.md +0 -0
  74. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/raci-stakeholder.template.md +0 -0
  75. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/release-cutover-plan.template.md +0 -0
  76. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/risk-register.template.md +0 -0
  77. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/rollback-plan.template.md +0 -0
  78. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/runbook.template.md +0 -0
  79. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/status-report.template.md +0 -0
  80. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/test-cases.template.md +0 -0
  81. {docassert-0.6.0 → docassert-0.7.1}/docassert/_data/templates/user-story.template.md +0 -0
  82. {docassert-0.6.0 → docassert-0.7.1}/docassert/config.py +0 -0
  83. {docassert-0.6.0 → docassert-0.7.1}/docassert/consistency.py +0 -0
  84. {docassert-0.6.0 → docassert-0.7.1}/docassert/extract.py +0 -0
  85. {docassert-0.6.0 → docassert-0.7.1}/docassert/graph.py +0 -0
  86. {docassert-0.6.0 → docassert-0.7.1}/docassert/loader.py +0 -0
  87. {docassert-0.6.0 → docassert-0.7.1}/docassert/models.py +0 -0
  88. {docassert-0.6.0 → docassert-0.7.1}/docassert/profiles.py +0 -0
  89. {docassert-0.6.0 → docassert-0.7.1}/docassert/projects.py +0 -0
  90. {docassert-0.6.0 → docassert-0.7.1}/docassert/rtm.py +0 -0
  91. {docassert-0.6.0 → docassert-0.7.1}/docassert/scaffold.py +0 -0
  92. {docassert-0.6.0 → docassert-0.7.1}/docassert/semantic.py +0 -0
  93. {docassert-0.6.0 → docassert-0.7.1}/docassert.egg-info/dependency_links.txt +0 -0
  94. {docassert-0.6.0 → docassert-0.7.1}/docassert.egg-info/entry_points.txt +0 -0
  95. {docassert-0.6.0 → docassert-0.7.1}/docassert.egg-info/requires.txt +0 -0
  96. {docassert-0.6.0 → docassert-0.7.1}/docassert.egg-info/top_level.txt +0 -0
  97. {docassert-0.6.0 → docassert-0.7.1}/setup.cfg +0 -0
  98. {docassert-0.6.0 → docassert-0.7.1}/tests/test_badge.py +0 -0
  99. {docassert-0.6.0 → docassert-0.7.1}/tests/test_config.py +0 -0
  100. {docassert-0.6.0 → docassert-0.7.1}/tests/test_consistency.py +0 -0
  101. {docassert-0.6.0 → docassert-0.7.1}/tests/test_defects.py +0 -0
  102. {docassert-0.6.0 → docassert-0.7.1}/tests/test_extract.py +0 -0
  103. {docassert-0.6.0 → docassert-0.7.1}/tests/test_graph.py +0 -0
  104. {docassert-0.6.0 → docassert-0.7.1}/tests/test_json_report.py +0 -0
  105. {docassert-0.6.0 → docassert-0.7.1}/tests/test_kinds_delivery.py +0 -0
  106. {docassert-0.6.0 → docassert-0.7.1}/tests/test_kinds_governance.py +0 -0
  107. {docassert-0.6.0 → docassert-0.7.1}/tests/test_kinds_operate.py +0 -0
  108. {docassert-0.6.0 → docassert-0.7.1}/tests/test_kinds_reporting.py +0 -0
  109. {docassert-0.6.0 → docassert-0.7.1}/tests/test_profiles.py +0 -0
  110. {docassert-0.6.0 → docassert-0.7.1}/tests/test_projects.py +0 -0
  111. {docassert-0.6.0 → docassert-0.7.1}/tests/test_scaffold.py +0 -0
  112. {docassert-0.6.0 → docassert-0.7.1}/tests/test_status.py +0 -0
  113. {docassert-0.6.0 → docassert-0.7.1}/tests/test_structural.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: docassert
3
- Version: 0.6.0
3
+ Version: 0.7.1
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
@@ -44,6 +44,8 @@ Dynamic: license-file
44
44
  [![Python](https://img.shields.io/pypi/pyversions/docassert)](https://pypi.org/project/docassert/)
45
45
  [![License](https://img.shields.io/badge/license-Apache--2.0-blue)](LICENSE)
46
46
 
47
+ ![docassert demo — a weak charter is blocked, fixed, and cleared](https://raw.githubusercontent.com/c4g-john/docassert/main/docs/demo.svg)
48
+
47
49
  **Unit testing for business documents.** Validate structured Markdown documents
48
50
  (charters, BRDs, PRDs, risk registers, …) against a configurable audit standard:
49
51
  deterministic structural checks that gate a merge, plus optional AI-graded
@@ -52,7 +54,7 @@ derived from the documents rather than self-reported.
52
54
 
53
55
  docassert is the reference implementation of **[PMO as Code](https://c4g-john.github.io/pmo-as-code/)** —
54
56
  a vendor-neutral standard for running a PMO from version-controlled, declarative
55
- files. It implements the [PMO as Code specification](https://github.com/c4g-john/pmo-as-code-spec) **v0.1**.
57
+ files. It implements the [PMO as Code specification](https://github.com/c4g-john/pmo-as-code-spec) **v0.2**.
56
58
 
57
59
  ## Install
58
60
 
@@ -117,6 +119,9 @@ kind is adding a trio — no code for the common cases.
117
119
  - **Structural — deterministic, blocking.** Required fields and sections,
118
120
  measurable success criteria, risks with owner + mitigation, resolving
119
121
  references, unique ids. Plain Python, reliable enough to gate a merge.
122
+ Within this tier, *integrity* checks (malformed items, bad types, duplicate
123
+ ids) block at any status, while *completeness* checks relax to advisory on
124
+ `status: draft` and gate once a document is proposed — WIP is never punished.
120
125
  - **Semantic — AI-graded, advisory.** Scored via the Anthropic API and posted to
121
126
  the PR — never blocking. Set `ANTHROPIC_API_KEY` to enable; skipped otherwise.
122
127
 
@@ -4,6 +4,8 @@
4
4
  [![Python](https://img.shields.io/pypi/pyversions/docassert)](https://pypi.org/project/docassert/)
5
5
  [![License](https://img.shields.io/badge/license-Apache--2.0-blue)](LICENSE)
6
6
 
7
+ ![docassert demo — a weak charter is blocked, fixed, and cleared](https://raw.githubusercontent.com/c4g-john/docassert/main/docs/demo.svg)
8
+
7
9
  **Unit testing for business documents.** Validate structured Markdown documents
8
10
  (charters, BRDs, PRDs, risk registers, …) against a configurable audit standard:
9
11
  deterministic structural checks that gate a merge, plus optional AI-graded
@@ -12,7 +14,7 @@ derived from the documents rather than self-reported.
12
14
 
13
15
  docassert is the reference implementation of **[PMO as Code](https://c4g-john.github.io/pmo-as-code/)** —
14
16
  a vendor-neutral standard for running a PMO from version-controlled, declarative
15
- files. It implements the [PMO as Code specification](https://github.com/c4g-john/pmo-as-code-spec) **v0.1**.
17
+ files. It implements the [PMO as Code specification](https://github.com/c4g-john/pmo-as-code-spec) **v0.2**.
16
18
 
17
19
  ## Install
18
20
 
@@ -77,6 +79,9 @@ kind is adding a trio — no code for the common cases.
77
79
  - **Structural — deterministic, blocking.** Required fields and sections,
78
80
  measurable success criteria, risks with owner + mitigation, resolving
79
81
  references, unique ids. Plain Python, reliable enough to gate a merge.
82
+ Within this tier, *integrity* checks (malformed items, bad types, duplicate
83
+ ids) block at any status, while *completeness* checks relax to advisory on
84
+ `status: draft` and gate once a document is proposed — WIP is never punished.
80
85
  - **Semantic — AI-graded, advisory.** Scored via the Anthropic API and posted to
81
86
  the PR — never blocking. Set `ANTHROPIC_API_KEY` to enable; skipped otherwise.
82
87
 
@@ -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.6.0"
8
+ __version__ = "0.7.1"
@@ -18,9 +18,13 @@ checks:
18
18
  type: structural
19
19
  blocking: true
20
20
  description: Frontmatter is valid against schema/adr.schema.json.
21
+ - id: frontmatter-complete
22
+ type: structural
23
+ blocking: once-proposed
24
+ description: Every schema-required frontmatter field is present (advisory while draft).
21
25
  - id: required-sections
22
26
  type: structural
23
- blocking: true
27
+ blocking: once-proposed
24
28
  description: Every required section is present and non-empty.
25
29
  - id: items-well-formed
26
30
  type: structural
@@ -28,7 +32,7 @@ checks:
28
32
  description: Every decision is a valid **ADR-###** item.
29
33
  - id: adr-items-have-status
30
34
  type: structural
31
- blocking: true
35
+ blocking: once-proposed
32
36
  description: Every decision declares a valid Status (proposed | accepted | superseded | deprecated | rejected).
33
37
  - id: unique-id
34
38
  type: structural
@@ -16,13 +16,17 @@ checks:
16
16
  type: structural
17
17
  blocking: true
18
18
  description: Frontmatter is valid against schema/benefits-realization.schema.json.
19
+ - id: frontmatter-complete
20
+ type: structural
21
+ blocking: once-proposed
22
+ description: Every schema-required frontmatter field is present (advisory while draft).
19
23
  - id: required-sections
20
24
  type: structural
21
- blocking: true
25
+ blocking: once-proposed
22
26
  description: Every required section is present and non-empty.
23
27
  - id: measurable-items
24
28
  type: structural
25
- blocking: true
29
+ blocking: once-proposed
26
30
  description: Every benefit states a measurable target.
27
31
  - id: unique-id
28
32
  type: structural
@@ -16,9 +16,13 @@ checks:
16
16
  type: structural
17
17
  blocking: true
18
18
  description: Frontmatter is valid against schema/brd.schema.json.
19
+ - id: frontmatter-complete
20
+ type: structural
21
+ blocking: once-proposed
22
+ description: Every schema-required frontmatter field is present (advisory while draft).
19
23
  - id: required-sections
20
24
  type: structural
21
- blocking: true
25
+ blocking: once-proposed
22
26
  description: Every required section is present and non-empty.
23
27
  - id: items-well-formed
24
28
  type: structural
@@ -13,9 +13,13 @@ checks:
13
13
  type: structural
14
14
  blocking: true
15
15
  description: Frontmatter is valid against schema/business-case.schema.json.
16
+ - id: frontmatter-complete
17
+ type: structural
18
+ blocking: once-proposed
19
+ description: Every schema-required frontmatter field is present (advisory while draft).
16
20
  - id: required-sections
17
21
  type: structural
18
- blocking: true
22
+ blocking: once-proposed
19
23
  description: Every required section is present and non-empty.
20
24
  - id: unique-id
21
25
  type: structural
@@ -26,19 +26,23 @@ checks:
26
26
  blocking: true
27
27
  description: Frontmatter is present and valid against schema/charter.schema.json.
28
28
 
29
+ - id: frontmatter-complete
30
+ type: structural
31
+ blocking: once-proposed
32
+ description: Every schema-required frontmatter field is present (advisory while draft).
29
33
  - id: required-sections
30
34
  type: structural
31
- blocking: true
35
+ blocking: once-proposed
32
36
  description: Every required section is present and non-empty.
33
37
 
34
38
  - id: measurable-success-criteria
35
39
  type: structural
36
- blocking: true
40
+ blocking: once-proposed
37
41
  description: Every Success Criteria bullet states a measurable threshold (number, %, currency, or date).
38
42
 
39
43
  - id: risks-have-owner-and-mitigation
40
44
  type: structural
41
- blocking: true
45
+ blocking: once-proposed
42
46
  description: Every Risks bullet names an Owner and a Mitigation.
43
47
 
44
48
  - id: dates-consistent
@@ -14,13 +14,17 @@ checks:
14
14
  type: structural
15
15
  blocking: true
16
16
  description: Frontmatter is valid against schema/data-migration-plan.schema.json.
17
+ - id: frontmatter-complete
18
+ type: structural
19
+ blocking: once-proposed
20
+ description: Every schema-required frontmatter field is present (advisory while draft).
17
21
  - id: required-sections
18
22
  type: structural
19
- blocking: true
23
+ blocking: once-proposed
20
24
  description: Every required section is present and non-empty.
21
25
  - id: mapping-table
22
26
  type: structural
23
- blocking: true
27
+ blocking: once-proposed
24
28
  description: The Field Mapping section contains a mapping table.
25
29
  - id: unique-id
26
30
  type: structural
@@ -17,9 +17,13 @@ checks:
17
17
  type: structural
18
18
  blocking: true
19
19
  description: Frontmatter is valid against schema/frnfr.schema.json.
20
+ - id: frontmatter-complete
21
+ type: structural
22
+ blocking: once-proposed
23
+ description: Every schema-required frontmatter field is present (advisory while draft).
20
24
  - id: required-sections
21
25
  type: structural
22
- blocking: true
26
+ blocking: once-proposed
23
27
  description: Every required section is present and non-empty.
24
28
  - id: items-well-formed
25
29
  type: structural
@@ -13,13 +13,17 @@ checks:
13
13
  type: structural
14
14
  blocking: true
15
15
  description: Frontmatter is valid against schema/hypercare-plan.schema.json.
16
+ - id: frontmatter-complete
17
+ type: structural
18
+ blocking: once-proposed
19
+ description: Every schema-required frontmatter field is present (advisory while draft).
16
20
  - id: required-sections
17
21
  type: structural
18
- blocking: true
22
+ blocking: once-proposed
19
23
  description: Every required section is present and non-empty.
20
24
  - id: measurable-exit-criteria
21
25
  type: structural
22
- blocking: true
26
+ blocking: once-proposed
23
27
  description: Every hypercare exit criterion states a measurable threshold.
24
28
  - id: unique-id
25
29
  type: structural
@@ -14,9 +14,13 @@ checks:
14
14
  type: structural
15
15
  blocking: true
16
16
  description: Frontmatter is valid against schema/post-implementation-review.schema.json.
17
+ - id: frontmatter-complete
18
+ type: structural
19
+ blocking: once-proposed
20
+ description: Every schema-required frontmatter field is present (advisory while draft).
17
21
  - id: required-sections
18
22
  type: structural
19
- blocking: true
23
+ blocking: once-proposed
20
24
  description: Every required section is present and non-empty.
21
25
  - id: unique-id
22
26
  type: structural
@@ -17,9 +17,13 @@ checks:
17
17
  type: structural
18
18
  blocking: true
19
19
  description: Frontmatter is valid against schema/prd.schema.json.
20
+ - id: frontmatter-complete
21
+ type: structural
22
+ blocking: once-proposed
23
+ description: Every schema-required frontmatter field is present (advisory while draft).
20
24
  - id: required-sections
21
25
  type: structural
22
- blocking: true
26
+ blocking: once-proposed
23
27
  description: Every required section is present and non-empty.
24
28
  - id: items-well-formed
25
29
  type: structural
@@ -16,6 +16,10 @@ checks:
16
16
  blocking: true
17
17
  description: Frontmatter is present and valid against schema/project.schema.json.
18
18
 
19
+ - id: frontmatter-complete
20
+ type: structural
21
+ blocking: once-proposed
22
+ description: Every schema-required frontmatter field is present (advisory while draft).
19
23
  - id: project-id-format
20
24
  type: structural
21
25
  blocking: true
@@ -23,7 +27,7 @@ checks:
23
27
 
24
28
  - id: required-sections
25
29
  type: structural
26
- blocking: true
30
+ blocking: once-proposed
27
31
  description: Every required section is present and non-empty.
28
32
 
29
33
  - id: unique-id
@@ -13,13 +13,17 @@ checks:
13
13
  type: structural
14
14
  blocking: true
15
15
  description: Frontmatter is valid against schema/qa-test-plan.schema.json.
16
+ - id: frontmatter-complete
17
+ type: structural
18
+ blocking: once-proposed
19
+ description: Every schema-required frontmatter field is present (advisory while draft).
16
20
  - id: required-sections
17
21
  type: structural
18
- blocking: true
22
+ blocking: once-proposed
19
23
  description: Every required section is present and non-empty.
20
24
  - id: measurable-exit-criteria
21
25
  type: structural
22
- blocking: true
26
+ blocking: once-proposed
23
27
  description: Every exit criterion states a measurable threshold.
24
28
  - id: unique-id
25
29
  type: structural
@@ -10,13 +10,17 @@ checks:
10
10
  type: structural
11
11
  blocking: true
12
12
  description: Frontmatter is valid against schema/raci-stakeholder.schema.json.
13
+ - id: frontmatter-complete
14
+ type: structural
15
+ blocking: once-proposed
16
+ description: Every schema-required frontmatter field is present (advisory while draft).
13
17
  - id: required-sections
14
18
  type: structural
15
- blocking: true
19
+ blocking: once-proposed
16
20
  description: Every required section is present and non-empty.
17
21
  - id: raci-one-accountable
18
22
  type: structural
19
- blocking: true
23
+ blocking: once-proposed
20
24
  description: Every activity in the RACI Matrix has exactly one Accountable (A) role.
21
25
  - id: unique-id
22
26
  type: structural
@@ -16,13 +16,17 @@ checks:
16
16
  type: structural
17
17
  blocking: true
18
18
  description: Frontmatter is valid against schema/release-cutover-plan.schema.json.
19
+ - id: frontmatter-complete
20
+ type: structural
21
+ blocking: once-proposed
22
+ description: Every schema-required frontmatter field is present (advisory while draft).
19
23
  - id: required-sections
20
24
  type: structural
21
- blocking: true
25
+ blocking: once-proposed
22
26
  description: Every required section is present and non-empty.
23
27
  - id: numbered-steps
24
28
  type: structural
25
- blocking: true
29
+ blocking: once-proposed
26
30
  description: Cutover Steps is an ordered list of at least two numbered steps.
27
31
  - id: unique-id
28
32
  type: structural
@@ -14,9 +14,13 @@ checks:
14
14
  type: structural
15
15
  blocking: true
16
16
  description: Frontmatter is valid against schema/risk-register.schema.json.
17
+ - id: frontmatter-complete
18
+ type: structural
19
+ blocking: once-proposed
20
+ description: Every schema-required frontmatter field is present (advisory while draft).
17
21
  - id: required-sections
18
22
  type: structural
19
- blocking: true
23
+ blocking: once-proposed
20
24
  description: Every required section is present and non-empty.
21
25
  - id: items-well-formed
22
26
  type: structural
@@ -24,7 +28,7 @@ checks:
24
28
  description: Every risk is a valid **RISK-###** item.
25
29
  - id: risk-items-complete
26
30
  type: structural
27
- blocking: true
31
+ blocking: once-proposed
28
32
  description: Every risk states a Probability, Impact, Owner, and Response.
29
33
  - id: unique-id
30
34
  type: structural
@@ -15,13 +15,17 @@ checks:
15
15
  type: structural
16
16
  blocking: true
17
17
  description: Frontmatter is valid against schema/rollback-plan.schema.json.
18
+ - id: frontmatter-complete
19
+ type: structural
20
+ blocking: once-proposed
21
+ description: Every schema-required frontmatter field is present (advisory while draft).
18
22
  - id: required-sections
19
23
  type: structural
20
- blocking: true
24
+ blocking: once-proposed
21
25
  description: Every required section is present and non-empty.
22
26
  - id: numbered-steps
23
27
  type: structural
24
- blocking: true
28
+ blocking: once-proposed
25
29
  description: Rollback Steps is an ordered list of at least two numbered steps.
26
30
  - id: unique-id
27
31
  type: structural
@@ -16,13 +16,17 @@ checks:
16
16
  type: structural
17
17
  blocking: true
18
18
  description: Frontmatter is valid against schema/runbook.schema.json.
19
+ - id: frontmatter-complete
20
+ type: structural
21
+ blocking: once-proposed
22
+ description: Every schema-required frontmatter field is present (advisory while draft).
19
23
  - id: required-sections
20
24
  type: structural
21
- blocking: true
25
+ blocking: once-proposed
22
26
  description: Every required section is present and non-empty.
23
27
  - id: numbered-steps
24
28
  type: structural
25
- blocking: true
29
+ blocking: once-proposed
26
30
  description: Procedures is an ordered list of at least two numbered steps.
27
31
  - id: unique-id
28
32
  type: structural
@@ -12,13 +12,17 @@ checks:
12
12
  type: structural
13
13
  blocking: true
14
14
  description: Frontmatter is valid (includes a period date and a green/amber/red rag).
15
+ - id: frontmatter-complete
16
+ type: structural
17
+ blocking: once-proposed
18
+ description: Every schema-required frontmatter field is present (advisory while draft).
15
19
  - id: required-sections
16
20
  type: structural
17
- blocking: true
21
+ blocking: once-proposed
18
22
  description: Every required section is present and non-empty.
19
23
  - id: references-risk
20
24
  type: structural
21
- blocking: true
25
+ blocking: once-proposed
22
26
  description: The Risks & Issues section cites at least one RISK-### from the register.
23
27
  - id: unique-id
24
28
  type: structural
@@ -14,9 +14,13 @@ checks:
14
14
  type: structural
15
15
  blocking: true
16
16
  description: Frontmatter is valid against schema/test-cases.schema.json.
17
+ - id: frontmatter-complete
18
+ type: structural
19
+ blocking: once-proposed
20
+ description: Every schema-required frontmatter field is present (advisory while draft).
17
21
  - id: required-sections
18
22
  type: structural
19
- blocking: true
23
+ blocking: once-proposed
20
24
  description: Every required section is present and non-empty.
21
25
  - id: items-well-formed
22
26
  type: structural
@@ -14,9 +14,13 @@ checks:
14
14
  type: structural
15
15
  blocking: true
16
16
  description: Frontmatter is valid against schema/user-story.schema.json.
17
+ - id: frontmatter-complete
18
+ type: structural
19
+ blocking: once-proposed
20
+ description: Every schema-required frontmatter field is present (advisory while draft).
17
21
  - id: required-sections
18
22
  type: structural
19
- blocking: true
23
+ blocking: once-proposed
20
24
  description: Every required section is present and non-empty.
21
25
  - id: items-well-formed
22
26
  type: structural
@@ -24,7 +28,7 @@ checks:
24
28
  description: Every story is a valid **US-###** item.
25
29
  - id: story-format
26
30
  type: structural
27
- blocking: true
31
+ blocking: once-proposed
28
32
  description: Every story follows "As a … I want … so that …".
29
33
  - id: unique-id
30
34
  type: structural
@@ -300,18 +300,19 @@ def main(argv: list[str] | None = None) -> int:
300
300
  sp.add_argument("--documents-dir", default=DEFAULT_DOCUMENTS_DIR,
301
301
  help=f"Documents tree to read (default: {DEFAULT_DOCUMENTS_DIR}/).")
302
302
 
303
+ def report_opts(sp: argparse.ArgumentParser) -> None:
304
+ sp.add_argument("--junit", help="Write a JUnit XML report to this path.")
305
+ sp.add_argument("--markdown", help="Write a PR-comment markdown report to this path.")
306
+ sp.add_argument("--json", help="Write a machine-readable JSON report to this path.")
307
+
303
308
  v = sub.add_parser("validate", help="Validate documents against their criteria.")
304
309
  v.add_argument("paths", nargs="+", help="Markdown files or globs.")
305
- v.add_argument("--junit", help="Write a JUnit XML report to this path.")
306
- v.add_argument("--markdown", help="Write a PR-comment markdown report to this path.")
307
- v.add_argument("--json", help="Write a machine-readable JSON report to this path.")
310
+ report_opts(v)
308
311
  docs_dir_opt(v)
309
312
  v.set_defaults(func=cmd_validate)
310
313
 
311
314
  c = sub.add_parser("consistency", help="Check cross-document traceability.")
312
- c.add_argument("--junit", help="Write a JUnit XML report to this path.")
313
- c.add_argument("--markdown", help="Write a PR-comment markdown report to this path.")
314
- c.add_argument("--json", help="Write a machine-readable JSON report to this path.")
315
+ report_opts(c)
315
316
  c.add_argument("--no-semantic", action="store_true",
316
317
  help="Skip AI alignment (structural consistency only).")
317
318
  docs_dir_opt(c)
@@ -12,6 +12,11 @@ _CROSS = "✗"
12
12
  _DASH = "—"
13
13
 
14
14
 
15
+ def _all(results_by_doc: dict[str, list[CheckResult]]) -> list[CheckResult]:
16
+ """Every result across every document, flattened."""
17
+ return [r for rs in results_by_doc.values() for r in rs]
18
+
19
+
15
20
  def _mark(r: CheckResult) -> str:
16
21
  if r.kind == "semantic" and r.score is None:
17
22
  return "○" # ○ skipped/unavailable
@@ -31,7 +36,7 @@ def console(results_by_doc: dict[str, list[CheckResult]]) -> str:
31
36
 
32
37
 
33
38
  def summary_line(results_by_doc: dict[str, list[CheckResult]]) -> str:
34
- blocking = sum(1 for rs in results_by_doc.values() for r in rs if r.is_blocking_failure)
39
+ blocking = sum(1 for r in _all(results_by_doc) if r.is_blocking_failure)
35
40
  docs = len(results_by_doc)
36
41
  if blocking:
37
42
  return f"{_CROSS} {blocking} blocking failure(s) across {docs} document(s) {_DASH} merge blocked."
@@ -51,7 +56,7 @@ def json_report(results_by_doc: dict[str, list[CheckResult]]) -> str:
51
56
  } for r in results]
52
57
  for path, results in results_by_doc.items()
53
58
  }
54
- all_results = [r for rs in results_by_doc.values() for r in rs]
59
+ all_results = _all(results_by_doc)
55
60
  summary = {
56
61
  "documents": len(results_by_doc),
57
62
  "checks": len(all_results),
@@ -89,9 +94,9 @@ def markdown(results_by_doc: dict[str, list[CheckResult]],
89
94
 
90
95
 
91
96
  def junit(results_by_doc: dict[str, list[CheckResult]]) -> str:
92
- total = sum(len(rs) for rs in results_by_doc.values())
93
- failures = sum(1 for rs in results_by_doc.values()
94
- for r in rs if r.is_blocking_failure)
97
+ all_results = _all(results_by_doc)
98
+ total = len(all_results)
99
+ failures = sum(1 for r in all_results if r.is_blocking_failure)
95
100
  suites = ET.Element("testsuites", tests=str(total), failures=str(failures))
96
101
  for path, results in results_by_doc.items():
97
102
  suite = ET.SubElement(suites, "testsuite", name=path,
@@ -0,0 +1,26 @@
1
+ """Status derivation and rendering, split into `derive` (model) and `render`
2
+ (views). This module re-exports the public API so existing imports are unchanged.
3
+ """
4
+ from .derive import (
5
+ APPROVED,
6
+ DOCUMENTS_DIR,
7
+ build_index,
8
+ build_status,
9
+ completeness_report,
10
+ derive_rag,
11
+ )
12
+ from .render import (
13
+ render_badge_json,
14
+ render_html,
15
+ render_index_html,
16
+ render_index_markdown,
17
+ render_json,
18
+ render_markdown,
19
+ )
20
+
21
+ __all__ = [
22
+ "DOCUMENTS_DIR", "APPROVED",
23
+ "build_status", "build_index", "completeness_report", "derive_rag",
24
+ "render_markdown", "render_json", "render_html",
25
+ "render_index_markdown", "render_index_html", "render_badge_json",
26
+ ]