Commit 7f047b7
fix(154): PDF report — attack trees, MAESTRO headings, landscape whitespace (#155)
Three downstream rendering bugs surfaced in second-brain-mcp's generated
security-report.pdf. Two share a root cause; one is an independent template
bug.
Root cause A — scripts/ missing from INSTALL_MANIFEST.md
The install manifest never distributed scripts/extract-report-data.py,
scripts/extract-infographic-data.py, or scripts/tachi_parsers.py to target
projects. When /tachi.security-report ran in a downstream project, the
report-assembler agent's `python3 scripts/extract-report-data.py` invocation
failed silently and the agent fell through to a legacy LLM-based inline
extraction path, producing report-data.typ with has-image: false on every
attack-tree entry (skipping the Mermaid visuals) and empty layer-id /
layer-name on MAESTRO findings-by-layer groups (collapsing headings to bare
"—"). The PDF compiled cleanly, so failures were invisible to users.
Fixes for root cause A:
- INSTALL_MANIFEST.md: add scripts/extract-report-data.py,
scripts/extract-infographic-data.py, scripts/tachi_parsers.py to both the
human-readable Distributable Directories table and the machine-parseable
<!-- BEGIN MANIFEST --> section. Add a new "Script Files" section
documenting the distribution requirement and explicitly flagging the
silent-failure mode so it cannot recur.
- .claude/agents/tachi/report-assembler.md: add a mandatory Step 2b
preflight check (`test -f scripts/extract-report-data.py && test -f
scripts/tachi_parsers.py`) that hard-fails with an install.sh pointer
when the scripts are missing. Renumber subsequent steps (old 2b to 2c,
old 2c to 2d, old 2d to 2e). Add exit code 127 to the exit-code table.
Rewrite the legacy-reference paragraph as a "Deprecated inline extraction
path — DO NOT USE" warning that enumerates the observed failure modes
(missing has-image, empty MAESTRO fields).
- .claude/agents/tachi/threat-infographic.md: add a symmetric preflight
check for scripts/extract-infographic-data.py and scripts/tachi_parsers.py.
Root cause B — landscape infographic whitespace
Feature 128 introduced a fixed-height 7.5in block in full-bleed.typ's
infographic-page() to accommodate the portrait executive-architecture
infographic (912x1168). Landscape 1376x768 infographics (risk-funnel,
baseball-card, system-architecture, maestro-stack, maestro-heatmap) scale
to ~3.6in tall and were vertically centered inside the 7.5in block by
`fit: "contain"`, producing ~1.9in of wasted whitespace above and below the
image with the border stretched around the dead space.
Fix for root cause B:
- templates/tachi/security-report/full-bleed.typ: add is-portrait parameter
(default false). For landscape, use a block with width: 100% and no
height constraint so the block hugs the image's natural aspect height.
For portrait, keep the 7.5in height cap to prevent overflow and center
the block horizontally via align(). Both paths use inset: 0pt so the
border wraps tightly around the image.
- templates/tachi/security-report/main.typ: pass is-portrait: true only to
the executive-architecture infographic-page call; all other landscape
calls keep the default.
Verification:
- examples/agentic-app/sample-report/security-report.pdf regenerated
(SOURCE_DATE_EPOCH=1700000000) — executive-architecture portrait page
and five landscape infographic pages all render with tight borders and
no dead whitespace; MAESTRO Layer Analysis headings show full canonical
names (L1 Foundation Model, L5 Evaluation and Observability, etc.);
17/17 attack tree Mermaid PNGs rendered inline on their respective
Attack Path Analysis pages.
- All 47 tests in tests/scripts/ pass.
- All 5 backward-compat baselines remain byte-identical under the
preserved SOURCE_DATE_EPOCH=1700000000 contract (web-app, microservices,
ascii-web-api, mermaid-agentic-app, free-text-microservice): none of
these examples use infographic-page() so the template change has no
rendering side effect, and the unchanged main.typ call sites produce
identical compiled output.
Closes #154
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent 32e46a6 commit 7f047b7
File tree
6 files changed
+120
-18
lines changed- .claude/agents/tachi
- examples/agentic-app/sample-report
- templates/tachi/security-report
6 files changed
+120
-18
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
117 | 117 | | |
118 | 118 | | |
119 | 119 | | |
120 | | - | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
121 | 154 | | |
122 | 155 | | |
123 | 156 | | |
| |||
131 | 164 | | |
132 | 165 | | |
133 | 166 | | |
134 | | - | |
| 167 | + | |
135 | 168 | | |
136 | 169 | | |
137 | 170 | | |
138 | 171 | | |
139 | 172 | | |
140 | 173 | | |
| 174 | + | |
141 | 175 | | |
142 | | - | |
| 176 | + | |
143 | 177 | | |
144 | | - | |
| 178 | + | |
145 | 179 | | |
146 | 180 | | |
147 | 181 | | |
148 | 182 | | |
149 | 183 | | |
150 | | - | |
| 184 | + | |
151 | 185 | | |
152 | 186 | | |
153 | 187 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
138 | 138 | | |
139 | 139 | | |
140 | 140 | | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
141 | 163 | | |
142 | 164 | | |
143 | 165 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| 15 | + | |
15 | 16 | | |
16 | 17 | | |
17 | 18 | | |
| |||
53 | 54 | | |
54 | 55 | | |
55 | 56 | | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
56 | 73 | | |
57 | 74 | | |
58 | 75 | | |
| |||
80 | 97 | | |
81 | 98 | | |
82 | 99 | | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
83 | 103 | | |
84 | 104 | | |
85 | 105 | | |
| |||
95 | 115 | | |
96 | 116 | | |
97 | 117 | | |
| 118 | + | |
98 | 119 | | |
99 | 120 | | |
100 | 121 | | |
Binary file not shown.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
39 | 49 | | |
40 | 50 | | |
41 | 51 | | |
42 | 52 | | |
43 | 53 | | |
44 | 54 | | |
| 55 | + | |
45 | 56 | | |
46 | 57 | | |
47 | 58 | | |
| |||
62 | 73 | | |
63 | 74 | | |
64 | 75 | | |
65 | | - | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
70 | | - | |
71 | | - | |
72 | | - | |
73 | | - | |
74 | | - | |
75 | | - | |
76 | | - | |
77 | | - | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
78 | 102 | | |
79 | 103 | | |
80 | 104 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
204 | 204 | | |
205 | 205 | | |
206 | 206 | | |
| 207 | + | |
207 | 208 | | |
208 | 209 | | |
209 | 210 | | |
| |||
0 commit comments