guardian-framework 0.1.0

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 (216) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +463 -0
  3. package/dist/cli.js +12958 -0
  4. package/dist/exports.js +12765 -0
  5. package/package.json +61 -0
  6. package/templates/languages/go-patterns.md +411 -0
  7. package/templates/languages/java-patterns.md +545 -0
  8. package/templates/languages/python-patterns.md +312 -0
  9. package/templates/languages/rust-patterns.md +232 -0
  10. package/templates/languages/typescript-patterns.md +313 -0
  11. package/templates/pi/INDEX.md +437 -0
  12. package/templates/pi/agent/AGENTS.md +166 -0
  13. package/templates/pi/agents/architecture-coordinator.md +40 -0
  14. package/templates/pi/agents/architecture-validator.md +36 -0
  15. package/templates/pi/agents/bootstrap-implementer.md +37 -0
  16. package/templates/pi/agents/issue-factory.md +31 -0
  17. package/templates/pi/agents/operations-validator.md +32 -0
  18. package/templates/pi/agents/security-validator.md +33 -0
  19. package/templates/pi/architecture/CHANGELOG.md +78 -0
  20. package/templates/pi/architecture/decisions/ADR-template.md +76 -0
  21. package/templates/pi/architecture/diagrams/system-overview.md +159 -0
  22. package/templates/pi/architecture/modules/module-template.md +152 -0
  23. package/templates/pi/context/checklists.md +91 -0
  24. package/templates/pi/context/domain-workflow.md +180 -0
  25. package/templates/pi/context/output-formats.md +135 -0
  26. package/templates/pi/context/patterns-base.md +47 -0
  27. package/templates/pi/context/patterns.md +38 -0
  28. package/templates/pi/context/project.md +88 -0
  29. package/templates/pi/domain/exploration.md +93 -0
  30. package/templates/pi/domain/ubiquitous-language.md +24 -0
  31. package/templates/pi/extensions/architect-lib/generators.ts +528 -0
  32. package/templates/pi/extensions/architect-lib/helpers.ts +344 -0
  33. package/templates/pi/extensions/architect-lib/types.ts +117 -0
  34. package/templates/pi/extensions/architect.ts +1425 -0
  35. package/templates/pi/extensions/ask-user-question.ts +579 -0
  36. package/templates/pi/extensions/bash-guard.ts +556 -0
  37. package/templates/pi/extensions/config-reload.ts +115 -0
  38. package/templates/pi/extensions/coordinator.ts +304 -0
  39. package/templates/pi/extensions/curator.ts +543 -0
  40. package/templates/pi/extensions/domain-explorer.ts +990 -0
  41. package/templates/pi/extensions/filechanges.ts +656 -0
  42. package/templates/pi/extensions/goal-loop.ts +717 -0
  43. package/templates/pi/extensions/hooks.ts +452 -0
  44. package/templates/pi/extensions/kanban.ts +547 -0
  45. package/templates/pi/extensions/pipeline.ts +1246 -0
  46. package/templates/pi/extensions/plan-mode.ts +209 -0
  47. package/templates/pi/extensions/project-scaffolder.ts +284 -0
  48. package/templates/pi/extensions/read-only-mode.ts +192 -0
  49. package/templates/pi/extensions/redaction.ts +128 -0
  50. package/templates/pi/extensions/session-persistence.ts +174 -0
  51. package/templates/pi/extensions/slash-commands.ts +229 -0
  52. package/templates/pi/extensions/snippets.ts +201 -0
  53. package/templates/pi/extensions/validation-runner.ts +100 -0
  54. package/templates/pi/github/agents/architecture-coordinator.agent.md +27 -0
  55. package/templates/pi/github/agents/architecture-validator.agent.md +20 -0
  56. package/templates/pi/github/agents/bootstrap-implementer.agent.md +20 -0
  57. package/templates/pi/github/agents/epic-planner.agent.md +70 -0
  58. package/templates/pi/github/agents/issue-factory.agent.md +20 -0
  59. package/templates/pi/github/agents/operations-validator.agent.md +20 -0
  60. package/templates/pi/github/agents/security-validator.agent.md +20 -0
  61. package/templates/pi/github/copilot/settings.json +16 -0
  62. package/templates/pi/github/copilot-instructions.md +155 -0
  63. package/templates/pi/github/instructions/architecture.instructions.md +71 -0
  64. package/templates/pi/github/instructions/validation.instructions.md +69 -0
  65. package/templates/pi/github/workflows/01-planning-workflow.md +75 -0
  66. package/templates/pi/github/workflows/02-issue-generation-workflow.md +69 -0
  67. package/templates/pi/github/workflows/03-implementation-workflow.md +80 -0
  68. package/templates/pi/github/workflows/04-validation-workflow.md +68 -0
  69. package/templates/pi/preflight_report.json +99 -0
  70. package/templates/pi/prompts/blueprint-update.md +262 -0
  71. package/templates/pi/prompts/blueprint-validate.md +218 -0
  72. package/templates/pi/prompts/bug-fix.md +50 -0
  73. package/templates/pi/prompts/ci-blueprint.md +131 -0
  74. package/templates/pi/prompts/context-refresh.md +258 -0
  75. package/templates/pi/prompts/epic-plan.md +356 -0
  76. package/templates/pi/prompts/epic-template.md +186 -0
  77. package/templates/pi/prompts/feature-development.md +131 -0
  78. package/templates/pi/prompts/git-issues.md +243 -0
  79. package/templates/pi/prompts/hotfix.md +71 -0
  80. package/templates/pi/prompts/issue-closeout.md +342 -0
  81. package/templates/pi/prompts/issue-draft.md +218 -0
  82. package/templates/pi/prompts/issue-implementation-series.md +173 -0
  83. package/templates/pi/prompts/issue-merge.md +372 -0
  84. package/templates/pi/prompts/issue-template-set.md +392 -0
  85. package/templates/pi/prompts/issue-template.md +207 -0
  86. package/templates/pi/prompts/pattern-extract.md +269 -0
  87. package/templates/pi/prompts/plan-to-issues.md +430 -0
  88. package/templates/pi/prompts/refactoring.md +82 -0
  89. package/templates/pi/prompts/scope-analyzer.md +254 -0
  90. package/templates/pi/prompts/sync-check.md +230 -0
  91. package/templates/pi/scripts/categorize-issues.sh +171 -0
  92. package/templates/pi/scripts/ci/check_architecture_conformance.sh +748 -0
  93. package/templates/pi/scripts/ci/check_planning_packet.py +228 -0
  94. package/templates/pi/scripts/ci/run_hardening_stages.sh +264 -0
  95. package/templates/pi/scripts/ci/run_preflight.sh +649 -0
  96. package/templates/pi/scripts/ci/run_stage.sh +193 -0
  97. package/templates/pi/scripts/ci/stage_docs_policy.sh +82 -0
  98. package/templates/pi/scripts/ci/stage_integration.sh +3 -0
  99. package/templates/pi/scripts/ci/stage_lint.sh +130 -0
  100. package/templates/pi/scripts/ci/stage_migration_verify.sh +3 -0
  101. package/templates/pi/scripts/ci/stage_package_build.sh +3 -0
  102. package/templates/pi/scripts/ci/stage_release_readiness.sh +3 -0
  103. package/templates/pi/scripts/ci/stage_remaining.sh +242 -0
  104. package/templates/pi/scripts/ci/stage_security.sh +3 -0
  105. package/templates/pi/scripts/ci/stage_static_analysis.sh +114 -0
  106. package/templates/pi/scripts/ci/stage_unit.sh +119 -0
  107. package/templates/pi/scripts/ci/validate_agent_output.py +181 -0
  108. package/templates/pi/scripts/ci/validate_agent_output.sh +243 -0
  109. package/templates/pi/scripts/create-feature-branch.sh +136 -0
  110. package/templates/pi/scripts/create-mr.sh +117 -0
  111. package/templates/pi/scripts/fetch-issues.sh +131 -0
  112. package/templates/pi/scripts/generate-architecture.sh +161 -0
  113. package/templates/pi/scripts/git/close-epic.sh +69 -0
  114. package/templates/pi/scripts/git/close-issue.sh +35 -0
  115. package/templates/pi/scripts/git/create-tracking-issue.sh +174 -0
  116. package/templates/pi/scripts/git/link-issue-to-epic.sh +51 -0
  117. package/templates/pi/scripts/git/update-tracking-issue.sh +66 -0
  118. package/templates/pi/scripts/languages/go/validate-architecture.sh +139 -0
  119. package/templates/pi/scripts/languages/go/validate-canonical.sh +129 -0
  120. package/templates/pi/scripts/languages/go/validate-ci.sh +132 -0
  121. package/templates/pi/scripts/languages/go/validate-integration.sh +156 -0
  122. package/templates/pi/scripts/languages/go/validate-operations.sh +146 -0
  123. package/templates/pi/scripts/languages/go/validate-security.sh +135 -0
  124. package/templates/pi/scripts/languages/go/validate-tests.sh +125 -0
  125. package/templates/pi/scripts/languages/java/validate-annotations.sh +185 -0
  126. package/templates/pi/scripts/languages/java/validate-architecture.sh +159 -0
  127. package/templates/pi/scripts/languages/java/validate-canonical.sh +114 -0
  128. package/templates/pi/scripts/languages/java/validate-ci.sh +269 -0
  129. package/templates/pi/scripts/languages/java/validate-integration.sh +149 -0
  130. package/templates/pi/scripts/languages/java/validate-operations.sh +142 -0
  131. package/templates/pi/scripts/languages/java/validate-security.sh +174 -0
  132. package/templates/pi/scripts/languages/java/validate-spring-architecture.sh +227 -0
  133. package/templates/pi/scripts/languages/java/validate-tests.sh +159 -0
  134. package/templates/pi/scripts/languages/python/validate-architecture.sh +99 -0
  135. package/templates/pi/scripts/languages/python/validate-canonical.sh +124 -0
  136. package/templates/pi/scripts/languages/python/validate-ci.sh +130 -0
  137. package/templates/pi/scripts/languages/python/validate-integration.sh +119 -0
  138. package/templates/pi/scripts/languages/python/validate-operations.sh +107 -0
  139. package/templates/pi/scripts/languages/python/validate-security.sh +68 -0
  140. package/templates/pi/scripts/languages/python/validate-tests.sh +102 -0
  141. package/templates/pi/scripts/languages/rust/validate-architecture.sh +188 -0
  142. package/templates/pi/scripts/languages/rust/validate-canonical.sh +146 -0
  143. package/templates/pi/scripts/languages/rust/validate-ci.sh +147 -0
  144. package/templates/pi/scripts/languages/rust/validate-integration.sh +149 -0
  145. package/templates/pi/scripts/languages/rust/validate-operations.sh +154 -0
  146. package/templates/pi/scripts/languages/rust/validate-security.sh +153 -0
  147. package/templates/pi/scripts/languages/rust/validate-tests.sh +150 -0
  148. package/templates/pi/scripts/languages/typescript/validate-architecture.sh +157 -0
  149. package/templates/pi/scripts/languages/typescript/validate-canonical.sh +135 -0
  150. package/templates/pi/scripts/languages/typescript/validate-ci.sh +244 -0
  151. package/templates/pi/scripts/languages/typescript/validate-integration.sh +166 -0
  152. package/templates/pi/scripts/languages/typescript/validate-operations.sh +162 -0
  153. package/templates/pi/scripts/languages/typescript/validate-security.sh +169 -0
  154. package/templates/pi/scripts/languages/typescript/validate-tests.sh +158 -0
  155. package/templates/pi/scripts/merge-mr.sh +95 -0
  156. package/templates/pi/scripts/mr-validation.sh +228 -0
  157. package/templates/pi/scripts/validate-architecture-readiness.sh +153 -0
  158. package/templates/pi/scripts/validate-architecture.sh +22 -0
  159. package/templates/pi/scripts/validate-canonical.sh +22 -0
  160. package/templates/pi/scripts/validate-ci.sh +37 -0
  161. package/templates/pi/scripts/validate-integration.sh +22 -0
  162. package/templates/pi/scripts/validate-operations.sh +22 -0
  163. package/templates/pi/scripts/validate-security.sh +22 -0
  164. package/templates/pi/scripts/validate-tests.sh +22 -0
  165. package/templates/pi/scripts/validate-ubiquitous-language.sh +291 -0
  166. package/templates/pi/scripts/validation-cache.sh +139 -0
  167. package/templates/pi/skills/agents/architecture-coordinator.md +178 -0
  168. package/templates/pi/skills/agents/architecture-generator.md +79 -0
  169. package/templates/pi/skills/agents/architecture-validator.md +74 -0
  170. package/templates/pi/skills/agents/ci-mr-validator.md +46 -0
  171. package/templates/pi/skills/agents/code-developer.md +76 -0
  172. package/templates/pi/skills/agents/commit.md +46 -0
  173. package/templates/pi/skills/agents/curator.md +71 -0
  174. package/templates/pi/skills/agents/debug.md +59 -0
  175. package/templates/pi/skills/agents/documentation-maintainer.md +36 -0
  176. package/templates/pi/skills/agents/goal-loop.md +125 -0
  177. package/templates/pi/skills/agents/hooks.md +122 -0
  178. package/templates/pi/skills/agents/integration-validator.md +35 -0
  179. package/templates/pi/skills/agents/issue-creator.md +75 -0
  180. package/templates/pi/skills/agents/issue-factory.md +143 -0
  181. package/templates/pi/skills/agents/kanban.md +85 -0
  182. package/templates/pi/skills/agents/land.md +59 -0
  183. package/templates/pi/skills/agents/operations-validator.md +43 -0
  184. package/templates/pi/skills/agents/pipeline.md +113 -0
  185. package/templates/pi/skills/agents/plan-mode.md +77 -0
  186. package/templates/pi/skills/agents/pull.md +40 -0
  187. package/templates/pi/skills/agents/push.md +41 -0
  188. package/templates/pi/skills/agents/security-validator.md +85 -0
  189. package/templates/pi/skills/agents/session-persistence.md +119 -0
  190. package/templates/pi/skills/agents/slash-commands.md +117 -0
  191. package/templates/pi/skills/agents/snippets.md +99 -0
  192. package/templates/pi/skills/agents/subagent-registry.md +78 -0
  193. package/templates/pi/skills/agents/test-validator.md +42 -0
  194. package/templates/pi/skills/validators/architecture-validator.md +43 -0
  195. package/templates/pi/skills/validators/ci-validator.md +27 -0
  196. package/templates/pi/skills/validators/context-compaction.md +73 -0
  197. package/templates/pi/skills/validators/integration-validator.md +38 -0
  198. package/templates/pi/skills/validators/model-registry.md +96 -0
  199. package/templates/pi/skills/validators/operations-validator.md +34 -0
  200. package/templates/pi/skills/validators/security-guards.md +72 -0
  201. package/templates/pi/skills/validators/security-validator.md +41 -0
  202. package/templates/pi/skills/validators/system-prompt-tiers.md +69 -0
  203. package/templates/pi/skills/validators/test-validator.md +33 -0
  204. package/templates/pi/types.ts +62 -0
  205. package/templates/pi/validators/README.md +93 -0
  206. package/templates/pi/validators/default.toml +209 -0
  207. package/templates/pi/validators/spring.toml +142 -0
  208. package/templates/pi/workpad.md +53 -0
  209. package/templates/project/java/Dockerfile +14 -0
  210. package/templates/project/java/README.md +40 -0
  211. package/templates/project/java/pom.xml +132 -0
  212. package/templates/project/typescript/Dockerfile +15 -0
  213. package/templates/project/typescript/README.md +29 -0
  214. package/templates/project/typescript/package.json +23 -0
  215. package/templates/project/typescript/tsconfig.json +21 -0
  216. package/templates/workflow.md +123 -0
@@ -0,0 +1,228 @@
1
+ #!/usr/bin/env python3
2
+ """Validate planning packet structure and core gating rules.
3
+
4
+ Deterministic validator for epic planning packets produced by the
5
+ Architecture Coordinator. Checks required sections, valid values, and
6
+ structural consistency before the packet is handed off for issue generation.
7
+
8
+ Usage:
9
+ python scripts/ci/check_planning_packet.py --input=planning_packet.md
10
+ python scripts/ci/check_planning_packet.py --input=planning_packet.md --json
11
+
12
+ Exit codes:
13
+ 0 - Packet is valid
14
+ 1 - Validation errors found
15
+ 2 - Script error
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import argparse
21
+ import json
22
+ import re
23
+ import sys
24
+ from pathlib import Path
25
+
26
+
27
+ REQUIRED_SECTIONS = [
28
+ "## Stream classification",
29
+ "## Scope summary",
30
+ "## In scope",
31
+ "## Out of scope",
32
+ "## Impacted layers",
33
+ "## Risk classification",
34
+ "## Dependency graph",
35
+ "## Mandatory validators",
36
+ "## Mandatory CI gates",
37
+ "## Forbidden shortcuts",
38
+ "## First implementation issue recommendation",
39
+ "## Open questions / escalation items",
40
+ ]
41
+
42
+ ALLOWED_STREAMS = {"feature", "hardening", "migration", "control"}
43
+ ALLOWED_RISKS = {"low", "medium", "high"}
44
+ ALLOWED_CI_GATES = {
45
+ "docs_policy", "architecture_conformance", "lint", "static_analysis",
46
+ "unit", "integration", "security", "migration_verify", "release_readiness",
47
+ }
48
+ REQUIRED_VALIDATORS = {"architecture-validator"}
49
+
50
+
51
+ def extract_section(content: str, heading: str) -> str:
52
+ pattern = re.compile(rf"^{re.escape(heading)}\s*$", re.MULTILINE)
53
+ match = pattern.search(content)
54
+ if not match:
55
+ return ""
56
+ start = match.end()
57
+ next_heading = re.search(r"^##\s+", content[start:], re.MULTILINE)
58
+ end = start + next_heading.start() if next_heading else len(content)
59
+ return content[start:end].strip()
60
+
61
+
62
+ def contains_list_item(section: str) -> bool:
63
+ return bool(re.search(r"^[-*]\s+\S|^\d+\.\s+\S", section, re.MULTILINE))
64
+
65
+
66
+ def normalize_lower(section: str) -> str:
67
+ return re.sub(r"\s+", " ", section).strip().lower()
68
+
69
+
70
+ def parse_dash_items(section: str) -> list[str]:
71
+ items: list[str] = []
72
+ for line in section.splitlines():
73
+ stripped = line.strip()
74
+ if stripped.startswith("- "):
75
+ items.append(stripped[2:].strip())
76
+ return items
77
+
78
+
79
+ def main() -> int:
80
+ parser = argparse.ArgumentParser(description="Validate planning packet structure")
81
+ parser.add_argument("--input", required=True, help="Path to planning packet markdown")
82
+ parser.add_argument("--json", action="store_true", help="Emit JSON output")
83
+ args = parser.parse_args()
84
+
85
+ input_path = Path(args.input)
86
+ if not input_path.exists():
87
+ print(f"Error: Input file not found: {args.input}", file=sys.stderr)
88
+ return 2
89
+
90
+ content = input_path.read_text(encoding="utf-8")
91
+ checks: list[dict] = []
92
+ errors: list[str] = []
93
+
94
+ # 1. Required sections present
95
+ for section in REQUIRED_SECTIONS:
96
+ if section in content:
97
+ checks.append({"check": f"section:{section}", "status": "pass"})
98
+ else:
99
+ checks.append({"check": f"section:{section}", "status": "fail", "message": f"Missing required section"})
100
+ errors.append(f"Missing required section: {section}")
101
+
102
+ # 2. Stream classification is valid
103
+ stream_section = extract_section(content, "## Stream classification")
104
+ if stream_section:
105
+ stream_lower = normalize_lower(stream_section)
106
+ found_streams = [s for s in ALLOWED_STREAMS if s.lower() in stream_lower]
107
+ if found_streams:
108
+ checks.append({"check": "stream_classification", "status": "pass", "value": found_streams[0]})
109
+ else:
110
+ checks.append({"check": "stream_classification", "status": "fail", "message": f"Stream must be one of: {', '.join(sorted(ALLOWED_STREAMS))}"})
111
+ errors.append("Stream classification must be explicit and valid")
112
+
113
+ # 3. Risk classification is valid
114
+ risk_section = extract_section(content, "## Risk classification")
115
+ if risk_section:
116
+ risk_lower = normalize_lower(risk_section)
117
+ found_risks = [r for r in ALLOWED_RISKS if r in risk_lower]
118
+ if found_risks:
119
+ checks.append({"check": "risk_classification", "status": "pass", "value": found_risks[0]})
120
+ else:
121
+ checks.append({"check": "risk_classification", "status": "fail", "message": f"Risk must be one of: {', '.join(sorted(ALLOWED_RISKS))}"})
122
+ errors.append("Risk classification must be explicit and valid")
123
+
124
+ # 4. In scope has items
125
+ in_scope = extract_section(content, "## In scope")
126
+ if in_scope:
127
+ if contains_list_item(in_scope):
128
+ checks.append({"check": "in_scope_items", "status": "pass"})
129
+ else:
130
+ checks.append({"check": "in_scope_items", "status": "fail", "message": "In scope section must contain bullet items"})
131
+ errors.append("In scope section must have at least one bullet item")
132
+
133
+ # 5. Out of scope has items
134
+ out_scope = extract_section(content, "## Out of scope")
135
+ if out_scope:
136
+ if contains_list_item(out_scope):
137
+ checks.append({"check": "out_of_scope_items", "status": "pass"})
138
+ else:
139
+ checks.append({"check": "out_of_scope_items", "status": "fail", "message": "Out of scope section must contain bullet items"})
140
+ errors.append("Out of scope section must have at least one bullet item")
141
+
142
+ # 6. Impacted layers identified
143
+ layers_section = extract_section(content, "## Impacted layers")
144
+ if layers_section and contains_list_item(layers_section):
145
+ checks.append({"check": "impacted_layers", "status": "pass"})
146
+ else:
147
+ checks.append({"check": "impacted_layers", "status": "fail", "message": "Impacted layers section must contain bullet items"})
148
+ errors.append("Impacted layers must be listed")
149
+
150
+ # 7. Dependency graph has items
151
+ dep_section = extract_section(content, "## Dependency graph")
152
+ if dep_section and contains_list_item(dep_section):
153
+ checks.append({"check": "dependency_graph", "status": "pass"})
154
+ else:
155
+ checks.append({"check": "dependency_graph", "status": "fail", "message": "Dependency graph section must contain ordered items"})
156
+ errors.append("Dependency graph must be specified")
157
+
158
+ # 8. Mandatory validators include architecture-validator
159
+ validators_section = extract_section(content, "## Mandatory validators")
160
+ if validators_section:
161
+ items = parse_dash_items(validators_section)
162
+ items_lower = [i.lower() for i in items]
163
+ if any("architecture" in i for i in items_lower):
164
+ checks.append({"check": "mandatory_validators", "status": "pass"})
165
+ else:
166
+ checks.append({"check": "mandatory_validators", "status": "fail", "message": f"Architecture validator is mandatory"})
167
+ errors.append("Architecture Validator must be in mandatory validators")
168
+ else:
169
+ checks.append({"check": "mandatory_validators", "status": "fail", "message": "Section not found"})
170
+
171
+ # 9. CI gates are valid
172
+ ci_section = extract_section(content, "## Mandatory CI gates")
173
+ if ci_section:
174
+ items = parse_dash_items(ci_section)
175
+ invalid = [i for i in items if i not in ALLOWED_CI_GATES]
176
+ if invalid:
177
+ checks.append({"check": "ci_gates", "status": "fail", "message": f"Unknown CI gates: {', '.join(invalid)}"})
178
+ errors.append(f"Unknown CI gates: {', '.join(invalid)}")
179
+ elif items:
180
+ checks.append({"check": "ci_gates", "status": "pass", "value": items})
181
+ else:
182
+ checks.append({"check": "ci_gates", "status": "fail", "message": "No CI gates specified"})
183
+ errors.append("At least one CI gate must be specified")
184
+ else:
185
+ checks.append({"check": "ci_gates", "status": "fail", "message": "Section not found"})
186
+
187
+ # 10. First issue recommendation exists
188
+ first_issue = extract_section(content, "## First implementation issue recommendation")
189
+ if first_issue and len(first_issue) > 10:
190
+ checks.append({"check": "first_issue_recommendation", "status": "pass"})
191
+ else:
192
+ checks.append({"check": "first_issue_recommendation", "status": "fail", "message": "First implementation issue must be recommended"})
193
+ errors.append("First implementation issue must be recommended")
194
+
195
+ # Summary
196
+ passed = sum(1 for c in checks if c["status"] == "pass")
197
+ failed = sum(1 for c in checks if c["status"] == "fail")
198
+
199
+ if args.json:
200
+ output = {
201
+ "input": str(input_path),
202
+ "timestamp": __import__("datetime").datetime.utcnow().isoformat() + "Z",
203
+ "summary": {"total": len(checks), "passed": passed, "failed": failed},
204
+ "checks": checks,
205
+ "errors": errors,
206
+ "status": "pass" if failed == 0 else "fail",
207
+ }
208
+ print(json.dumps(output, indent=2))
209
+ else:
210
+ print(f"\nPlanning Packet Validation: {args.input}")
211
+ print(f"{'='*50}")
212
+ for check in checks:
213
+ icon = "PASS" if check["status"] == "pass" else "FAIL"
214
+ print(f" [{icon}] {check['check']}")
215
+ if check["status"] == "fail" and "message" in check:
216
+ print(f" {check['message']}")
217
+ print(f"\nSummary: {passed} passed, {failed} failed, {len(checks)} total")
218
+ if errors:
219
+ print(f"\nErrors ({len(errors)}):")
220
+ for e in errors:
221
+ print(f" - {e}")
222
+ print(f"\nResult: {'VALID' if failed == 0 else 'INVALID'}")
223
+
224
+ return 0 if failed == 0 else 1
225
+
226
+
227
+ if __name__ == "__main__":
228
+ sys.exit(main())
@@ -0,0 +1,264 @@
1
+ #!/usr/bin/env bash
2
+ # Hardening Stage Runner
3
+ #
4
+ # Runs all 10 hardening stages as defined in the architecture pipeline.
5
+ # Each stage runs its scripts and reports pass/fail.
6
+ # A stage failure prevents MR merge (allow_failure: No).
7
+ #
8
+ # Usage: bash .pi/scripts/ci/run_hardening_stages.sh [--stages <list>] [--verbose]
9
+ #
10
+ # Stages:
11
+ # 1. docs_policy — MR traceability, docs sync guard
12
+ # 2. architecture_conformance — 11+ architectural contract checks
13
+ # 3. lint — ruff/format/coverage
14
+ # 4. static_analysis — mypy/sonar/import-boundaries/sanity
15
+ # 5. unit — domain/app/contract/verification tests
16
+ # 6. integration — integration tests
17
+ # 7. security — SBOM/Trivy/secret scan/deps audit
18
+ # 8. migration_verify — Migration checks (conditional)
19
+ # 9. package_build — Docker build (conditional, main only)
20
+ # 10. release_readiness — Runbook/observability/policy checks
21
+
22
+ set -euo pipefail
23
+
24
+ PI_DIR=".pi"
25
+ SCRIPTS_DIR="${PI_DIR}/scripts/ci"
26
+ CI_DIR="${PI_DIR}/ci"
27
+
28
+ # Color output
29
+ RED='\033[0;31m'
30
+ GREEN='\033[0;32m'
31
+ YELLOW='\033[1;33m'
32
+ BLUE='\033[0;34m'
33
+ NC='\033[0m'
34
+
35
+ VERBOSE=false
36
+ ALL_STAGES=true
37
+ SELECTED_STAGES=()
38
+
39
+ # Parse arguments
40
+ while [[ $# -gt 0 ]]; do
41
+ case $1 in
42
+ --stages)
43
+ ALL_STAGES=false
44
+ IFS=',' read -ra SELECTED_STAGES <<< "$2"
45
+ shift 2
46
+ ;;
47
+ --verbose)
48
+ VERBOSE=true
49
+ shift
50
+ ;;
51
+ *)
52
+ shift
53
+ ;;
54
+ esac
55
+ done
56
+
57
+ should_run_stage() {
58
+ local stage="$1"
59
+ if [[ "$ALL_STAGES" == "true" ]]; then
60
+ return 0
61
+ fi
62
+ for s in "${SELECTED_STAGES[@]}"; do
63
+ if [[ "$s" == "$stage" ]]; then
64
+ return 0
65
+ fi
66
+ done
67
+ return 1
68
+ }
69
+
70
+ log_stage_start() {
71
+ echo ""
72
+ echo -e "${BLUE}═══ Stage $1: $2 ═══${NC}"
73
+ }
74
+
75
+ log_stage_pass() {
76
+ echo -e " ${GREEN}✓ Stage $1 PASSED${NC}"
77
+ }
78
+
79
+ log_stage_fail() {
80
+ echo -e " ${RED}✗ Stage $1 FAILED${NC}"
81
+ echo " $2"
82
+ }
83
+
84
+ log_stage_skip() {
85
+ echo -e " ${YELLOW}⊘ Stage $1 SKIPPED${NC} — $2"
86
+ }
87
+
88
+ TOTAL_STAGES=0
89
+ PASSED_STAGES=0
90
+ FAILED_STAGES=0
91
+ SKIPPED_STAGES=0
92
+
93
+ declare -a STAGE_RESULTS=()
94
+
95
+ run_stage() {
96
+ local stage_num="$1"
97
+ local stage_name="$2"
98
+ local stage_script="$3"
99
+ local conditional="$4" # "always", "main_only", "migration_only", "sonar_required"
100
+
101
+ if ! should_run_stage "$stage_name"; then
102
+ return 0
103
+ fi
104
+
105
+ ((TOTAL_STAGES++))
106
+
107
+ # Check conditional
108
+ case "$conditional" in
109
+ main_only)
110
+ if [[ "${CI_COMMIT_BRANCH:-}" != "main" && "${GITHUB_REF_NAME:-}" != "main" ]]; then
111
+ log_stage_skip "$stage_name" "Not on main branch"
112
+ ((SKIPPED_STAGES++))
113
+ return 0
114
+ fi
115
+ ;;
116
+ migration_only)
117
+ local has_migration=false
118
+ if command -v git &>/dev/null; then
119
+ if git diff --name-only HEAD~1 HEAD 2>/dev/null | grep -qE "(alembic|migrations?|database.*schema)"; then
120
+ has_migration=true
121
+ fi
122
+ fi
123
+ if [[ "$has_migration" == "false" ]]; then
124
+ log_stage_skip "$stage_name" "No migration changes detected"
125
+ ((SKIPPED_STAGES++))
126
+ return 0
127
+ fi
128
+ ;;
129
+ sonar_required)
130
+ if [[ -z "${SONAR_TOKEN:-}" || -z "${SONAR_HOST_URL:-}" ]]; then
131
+ log_stage_skip "$stage_name" "SONAR_TOKEN or SONAR_HOST_URL not set"
132
+ ((SKIPPED_STAGES++))
133
+ return 0
134
+ fi
135
+ ;;
136
+ esac
137
+
138
+ log_stage_start "$stage_num" "$stage_name"
139
+
140
+ if [[ ! -f "$stage_script" ]]; then
141
+ log_stage_skip "$stage_name" "Script not found: $stage_script"
142
+ ((SKIPPED_STAGES++))
143
+ return 0
144
+ fi
145
+
146
+ local output
147
+ if output=$(bash "$stage_script" 2>&1); then
148
+ log_stage_pass "$stage_name"
149
+ ((PASSED_STAGES++))
150
+ STAGE_RESULTS+=("PASS:$stage_name")
151
+ if [[ "$VERBOSE" == "true" ]]; then
152
+ echo "$output"
153
+ fi
154
+ else
155
+ log_stage_fail "$stage_name" "$output"
156
+ ((FAILED_STAGES++))
157
+ STAGE_RESULTS+=("FAIL:$stage_name:$(echo "$output" | head -5)")
158
+ fi
159
+ }
160
+
161
+ echo "╔══════════════════════════════════════════════════════╗"
162
+ echo "║ Guardian Hardening Stage Runner ║"
163
+ echo "╚══════════════════════════════════════════════════════╝"
164
+ echo ""
165
+ echo "Commit: ${CI_COMMIT_SHA:-${GITHUB_SHA:-unknown}}"
166
+ echo "Branch: ${CI_COMMIT_BRANCH:-${GITHUB_REF_NAME:-unknown}}"
167
+ echo "Pipeline: ${CI_PIPELINE_ID:-local}"
168
+ echo ""
169
+
170
+ # Stage 1: Docs Policy
171
+ run_stage "1" "docs_policy" \
172
+ "${SCRIPTS_DIR}/stage_docs_policy.sh" \
173
+ "always"
174
+
175
+ # Stage 2: Architecture Conformance
176
+ run_stage "2" "architecture_conformance" \
177
+ "${SCRIPTS_DIR}/check_architecture_conformance.sh" \
178
+ "always"
179
+
180
+ # Stage 3: Lint
181
+ run_stage "3" "lint" \
182
+ "${SCRIPTS_DIR}/stage_lint.sh" \
183
+ "always"
184
+
185
+ # Stage 4: Static Analysis
186
+ run_stage "4" "static_analysis" \
187
+ "${SCRIPTS_DIR}/stage_static_analysis.sh" \
188
+ "always"
189
+
190
+ # Stage 5: Unit Tests
191
+ run_stage "5" "unit" \
192
+ "${SCRIPTS_DIR}/stage_unit.sh" \
193
+ "always"
194
+
195
+ # Stage 6: Integration Tests
196
+ run_stage "6" "integration" \
197
+ "${SCRIPTS_DIR}/stage_integration.sh" \
198
+ "always"
199
+
200
+ # Stage 7: Security
201
+ run_stage "7" "security" \
202
+ "${SCRIPTS_DIR}/stage_security.sh" \
203
+ "always"
204
+
205
+ # Stage 8: Migration Verify (conditional)
206
+ run_stage "8" "migration_verify" \
207
+ "${SCRIPTS_DIR}/stage_migration_verify.sh" \
208
+ "migration_only"
209
+
210
+ # Stage 9: Package Build (conditional)
211
+ run_stage "9" "package_build" \
212
+ "${SCRIPTS_DIR}/stage_package_build.sh" \
213
+ "main_only"
214
+
215
+ # Stage 10: Release Readiness
216
+ run_stage "10" "release_readiness" \
217
+ "${SCRIPTS_DIR}/stage_release_readiness.sh" \
218
+ "always"
219
+
220
+ # ── Summary ──
221
+
222
+ echo ""
223
+ echo "╔══════════════════════════════════════════════════════╗"
224
+ echo "║ Hardening Stage Summary ║"
225
+ echo "╚══════════════════════════════════════════════════════╝"
226
+ echo ""
227
+
228
+ for result in "${STAGE_RESULTS[@]}"; do
229
+ IFS=':' read -ra parts <<< "$result"
230
+ status="${parts[0]}"
231
+ name="${parts[1]}"
232
+ detail="${parts[2]:-}"
233
+
234
+ case "$status" in
235
+ PASS)
236
+ echo -e " ${GREEN}✓${NC} ${name}"
237
+ ;;
238
+ FAIL)
239
+ echo -e " ${RED}✗${NC} ${name}"
240
+ if [[ -n "$detail" ]]; then
241
+ echo -e " ${RED}${detail}${NC}"
242
+ fi
243
+ ;;
244
+ SKIP)
245
+ echo -e " ${YELLOW}⊘${NC} ${name}"
246
+ ;;
247
+ esac
248
+ done
249
+
250
+ echo ""
251
+ echo -e " ${GREEN}Passed: ${PASSED_STAGES}${NC}"
252
+ echo -e " ${RED}Failed: ${FAILED_STAGES}${NC}"
253
+ echo -e " ${YELLOW}Skipped: ${SKIPPED_STAGES}${NC}"
254
+ echo " Total: ${TOTAL_STAGES}"
255
+ echo ""
256
+
257
+ if [[ ${FAILED_STAGES} -gt 0 ]]; then
258
+ echo -e "${RED}✗ Hardening FAILED. ${FAILED_STAGES} stage(s) did not pass.${NC}"
259
+ echo "MR cannot be merged until all mandatory stages pass."
260
+ exit 1
261
+ fi
262
+
263
+ echo -e "${GREEN}✓ All hardening stages passed. MR is ready for merge.${NC}"
264
+ exit 0