You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Three related bugs in the tachi threat-report generation pipeline:
1. Attack tree baseline handling lost Mermaid content on UNCHANGED findings.
Replaced the old "skip UNCHANGED" rule with a three-rule approach that
copies baseline Mermaid when nothing changed, regenerates all trees when
architecture shifted, and reconciles structurally-equivalent trees against
the baseline to avoid diff noise.
2. MAESTRO layer context was dropped from Section 3 narratives and the
threats.md Section 7 summary table despite the data being parsed into
findings. Promoted MAESTRO layer references to mandatory on first mention
of every finding and added a MAESTRO Layer column to the summary table.
3. Attack tree filename convention was stated once as a parenthetical and
not enforced, leading to files like AG-1-no-hitl-stdio.md that the spec
112 parser silently dropped. Added explicit convention block, dedicated
skill section, and a validation checklist item.
Schema plumbing: schemas/report.yaml bumps 1.0 -> 1.1 with baseline_source,
baseline_date, delta_counts frontmatter fields and a conditional Section 8
Delta Summary. schemas/output.yaml adds status and maestro_layer columns.
Closes#134
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
**Before writing any section**, generate the YAML frontmatter block at the top of the report. Read `../../../templates/tachi/output-schemas/threat-report.md` for the exact field structure. The frontmatter MUST be the first content after the H1 heading, enclosed in a fenced `yaml` code block between `---` delimiters. Populate all fields from `threats.md`: schema_version (`"1.1"`), date, source_file, finding_count, risk_distribution (Critical/High/Medium/Low counts), attack_tree_count, baseline_source, baseline_date, and delta_counts. When no baseline exists, set baseline_source, baseline_date, and all delta_counts fields to `null`.
169
+
165
170
### Section 1: Executive Summary
166
171
167
172
**MANDATORY**: Read `.claude/skills/tachi-threat-reporting/references/narrative-templates.md` for the 5 required elements, language rules, and remediation timeline tiers.
@@ -178,7 +183,9 @@ Generate the Architecture Overview deriving system context from `threats.md` Sec
178
183
179
184
**MANDATORY**: Read `.claude/skills/tachi-threat-reporting/references/narrative-templates.md` for per-category subsection headers, per-finding narrative pattern, progressive depth rules, and large threat model handling.
180
185
181
-
Generate the Threat Analysis with agent-by-agent narrative covering all 8 categories. When findings include a `maestro_layer` field, reference the architectural layer in finding narratives for additional context (e.g., "This threat targets the Agent Framework layer (L3)"). MAESTRO layer references are informational -- they do not change narrative structure, severity assessments, or attack tree construction.
186
+
Generate the Threat Analysis with agent-by-agent narrative covering all 8 categories.
187
+
188
+
**MAESTRO Layer References (MANDATORY when present)**: When findings include a `maestro_layer` field, you MUST reference the architectural layer in each finding's narrative. Include the layer designation on first mention of each finding — for example: "**S-1** targets the Agent Framework layer (L3), where..." or "Operating at the Data Operations layer (L2), **T-3** exploits...". Every finding narrative must include its MAESTRO layer context. These references are informational — they do not change narrative structure, severity assessments, or attack tree construction.
182
189
183
190
### Section 4: Cross-Cutting Themes
184
191
@@ -192,7 +199,20 @@ Scan all findings for emergent patterns across categories that reveal systemic i
192
199
193
200
**MANDATORY**: Read `.claude/skills/tachi-threat-reporting/references/attack-tree-examples.md` before generating the first tree -- load once as reference patterns.
194
201
195
-
Generate Mermaid attack trees for every Critical and High finding following Bruce Schneier's attack tree methodology. **Skip findings with delta_status RESOLVED** -- resolved threats are no longer active and must not receive attack trees. **ALWAYS generate fresh attack trees for UNCHANGED findings** -- do NOT produce placeholder text like "carried forward from baseline." An unchanged threat description does not mean the attack paths are static; adjacent components and techniques may have changed. Every active Critical/High finding gets a fully constructed Mermaid attack tree, regardless of delta_status.
202
+
Generate Mermaid attack trees for every Critical and High finding following Bruce Schneier's attack tree methodology.
203
+
204
+
**Attack tree delta handling (three rules):**
205
+
206
+
First, check `delta_counts` from the `threats.md` frontmatter to determine which rule applies:
207
+
208
+
**Rule 1 — All UNCHANGED (delta_counts: new=0, updated=0, resolved=0):** Architecture has not changed. For each UNCHANGED Critical/High finding, read and copy the full Mermaid content from the baseline at `{baseline_dir}/attack-trees/{finding-id}-attack-tree.md`. Derive `baseline_dir` from the `baseline.source` frontmatter path by dropping `threats.md`. Include the complete Mermaid code block in both inline (Section 5) and standalone file output. Do NOT output placeholder text without the diagram. If the baseline file is missing, generate fresh as fallback.
209
+
210
+
**Rule 2 — Any NEW/UPDATED/RESOLVED (any delta_counts > 0):** Architecture shifted -- attack paths to all threats may have changed. Generate fresh attack trees for ALL Critical/High findings, including UNCHANGED ones. For UPDATED findings, add a note: _"Context changed since baseline -- attack tree regenerated."_
211
+
212
+
**Rule 3 — Reconciliation (after Rule 2 only):** After generating all fresh trees, compare each UNCHANGED finding's fresh tree against its baseline version. If structurally similar (same nodes, same paths, minor wording only), use the baseline version for consistency. If materially different (new paths, removed nodes, structural changes), use the fresh version.
213
+
214
+
**RESOLVED**: Skip entirely -- no attack tree.
215
+
**No baseline**: Generate all trees fresh.
196
216
197
217
### Section 6: Remediation Roadmap
198
218
@@ -252,7 +272,14 @@ Embed each attack tree directly in the Attack Trees section using Mermaid code b
252
272
253
273
### Location 2: Standalone Files in attack-trees/
254
274
255
-
Save each attack tree as an independent Markdown file in the `attack-trees/` directory within the output directory. File naming: `{finding-id}-attack-tree.md`(lowercase, e.g., `ag-1-attack-tree.md`).
275
+
Save each attack tree as an independent Markdown file in the `attack-trees/` directory within the output directory.
276
+
277
+
**File naming convention** (MUST follow exactly):
278
+
- Pattern: `{finding-id}-attack-tree.md`
279
+
- Case: **always lowercase** — the finding ID is lowercased in the filename
280
+
- Suffix: **always `-attack-tree.md`** — never use a description slug
Each standalone file contains: H1 heading with finding ID and threat description, a metadata table (Finding ID, Component, Risk Level, Threat, Correlation), and the Mermaid code block **identical** to the inline version in `threat-report.md`.
To produce the filename: take the finding ID (e.g., `AG-1`), convert to lowercase (e.g., `ag-1`), append `-attack-tree.md`.
151
+
152
+
---
153
+
140
154
## Validation Checklist
141
155
142
156
Before including any Mermaid attack tree in the report or standalone file, run every check below. A tree that fails any check must be corrected before output.
@@ -178,6 +192,12 @@ Before including any Mermaid attack tree in the report or standalone file, run e
178
192
-[ ] Leaf nodes assigned `leaf` class
179
193
-[ ] Color values match the standard palette: goal=`#ff6b6b`, andGate=`#ffa500`, orGate=`#4ecdc4`, leaf=`#95e1d3`
180
194
195
+
### Standalone File Naming
196
+
197
+
-[ ] Filename is the finding ID lowercased plus `-attack-tree.md` (e.g., AG-1 → `ag-1-attack-tree.md`)
198
+
-[ ] No uppercase letters in filename
199
+
-[ ] No description slugs — suffix is always `-attack-tree.md`
Copy file name to clipboardExpand all lines: .claude/skills/tachi-threat-reporting/references/narrative-templates.md
+5-4Lines changed: 5 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -75,10 +75,11 @@ For each category, include all findings from the corresponding STRIDE or AI tabl
75
75
76
76
For each finding, provide:
77
77
1.**Finding reference**: State the finding ID (e.g., "**S-1**") as a bold reference
78
-
2.**Component annotation**: Name the affected component
79
-
3.**Threat description**: Explain the threat in context -- what could happen, how, and why it matters
80
-
4.**Risk context**: State the likelihood, impact, and computed risk level
81
-
5.**Mitigation summary**: Reference the recommended mitigation (the full mitigation text appears in the Remediation Roadmap)
78
+
2.**MAESTRO layer context**: On first mention of each finding, include its MAESTRO architectural layer from the `maestro_layer` field. Integrate naturally into the sentence — for example: "**S-1** targets the Agent Framework layer (L3), where..." or "Operating at the Data Operations layer (L2), **T-3** exploits...". Every finding MUST include its MAESTRO layer on first reference.
79
+
3.**Component annotation**: Name the affected component
80
+
4.**Threat description**: Explain the threat in context -- what could happen, how, and why it matters
81
+
5.**Risk context**: State the likelihood, impact, and computed risk level
82
+
6.**Mitigation summary**: Reference the recommended mitigation (the full mitigation text appears in the Remediation Roadmap)
Copy file name to clipboardExpand all lines: templates/tachi/output-schemas/threat-report.md
+11-6Lines changed: 11 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -196,12 +196,17 @@ flowchart TD
196
196
>
197
197
> **Correlated findings**: Each correlated finding receives its own individual tree with a cross-reference note to related finding IDs — not a single unified tree for the correlation group.
198
198
>
199
-
> **Baseline handling** (delta_status branching):
200
-
> -**NEW**: Generate a fresh attack tree following all standard conventions above.
201
-
> -**UPDATED**: Generate a fresh attack tree. Add a note below the tree: _"Context changed since baseline ({baseline_date}) — attack tree regenerated."_
202
-
> -**UNCHANGED**: Do NOT generate an attack tree. Instead, note: _"Attack tree carried forward from baseline ({baseline_date}) — finding unchanged since last assessment."_
203
-
> -**RESOLVED**: Not applicable — RESOLVED findings do not appear in Section 5. They appear only in Section 4b of the input threats.md.
204
-
> -**No baseline**: When `baseline_source` is null in the input frontmatter, generate all attack trees fresh with no delta annotations. This is standard first-run behavior.
199
+
> **Baseline handling** (three-rule approach):
200
+
>
201
+
> **Rule 1 — All UNCHANGED (no architecture change):** When `delta_counts` shows zero NEW, zero UPDATED, and zero RESOLVED findings, the architecture has not changed. For each UNCHANGED Critical/High finding, copy the full Mermaid attack tree content from the baseline's `attack-trees/{finding-id}-attack-tree.md` file. Derive the baseline directory from the `baseline.source` frontmatter field by dropping the `threats.md` filename. Include the complete Mermaid code block — do NOT output placeholder text without the actual diagram. If the baseline file is missing, generate a fresh tree as fallback.
202
+
>
203
+
> **Rule 2 — Any NEW/UPDATED/RESOLVED (architecture changed):** When `delta_counts` shows any non-zero value for `new`, `updated`, or `resolved`, the architecture has shifted and attack paths to all threats may have changed. Generate fresh attack trees for ALL Critical/High findings — including UNCHANGED ones — following all standard conventions above. For NEW findings, generate normally. For UPDATED findings, add a note below the tree: _"Context changed since baseline ({baseline_date}) — attack tree regenerated."_
204
+
>
205
+
> **Rule 3 — Post-generation reconciliation (applies only when Rule 2 fires):** After generating all fresh trees, compare each UNCHANGED finding's fresh tree against its baseline counterpart from `attack-trees/{finding-id}-attack-tree.md`. If they are structurally similar (same nodes, same paths, minor wording differences only), use the baseline version for consistency — this avoids noisy churn on trees that didn't actually change. If they are materially different (new attack paths, removed nodes, structural changes), use the fresh version. This ensures diffs between runs only show meaningful changes.
206
+
>
207
+
> **RESOLVED**: Not applicable — RESOLVED findings do not appear in Section 5. They appear only in Section 4b of the input threats.md.
208
+
>
209
+
> **No baseline**: When `baseline_source` is null in the input frontmatter, generate all attack trees fresh with no delta annotations. This is standard first-run behavior.
0 commit comments