Skip to content

Commit 5aeb10b

Browse files
fix(074): baseline auto-detection and downstream command context limits (#102)
Baseline auto-detection looked for threats.md in the output directory, but /threat-model creates a fresh timestamped subfolder per run so the directory is always empty. Auto-detection now scans the parent directory for the most recent sibling containing a threats.md. Also fixed /risk-score and /compensating-controls embedding full file contents in agent prompts, which exceeded subagent context limits on large threat models (61+ findings). Both commands now pass file paths and let agents read on-demand via their existing Read tool access. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 1bef130 commit 5aeb10b

File tree

5 files changed

+49
-40
lines changed

5 files changed

+49
-40
lines changed

.claude/agents/tachi/orchestrator.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ This optional phase detects whether a previous pipeline output exists and loads
117117
118118
### Baseline Detection
119119
120-
Locate a previous pipeline output using two methods in priority order: (1) **explicit flag** `--baseline <path>` pointing to a valid `threats.md`, (2) **auto-detection** of an existing `threats.md` in the output directory.
120+
Locate a previous pipeline output using two methods in priority order: (1) **explicit flag** `--baseline <path>` pointing to a valid `threats.md`, (2) **auto-detection** by scanning the output directory's **parent** for sibling directories containing a `threats.md`. Since each run creates a unique timestamped subfolder (e.g., `docs/security/2026-04-08T15-16-21/`), auto-detection lists all sibling directories in the parent (e.g., `docs/security/`), sorts them lexicographically descending (ISO timestamps sort naturally), skips the current run's directory, and uses the `threats.md` from the most recent previous directory.
121121

122122
**If neither method finds a baseline**: Set `baseline_present = false` and proceed to Phase 1 in stateless mode. **If a baseline file is found**: Validate it is parseable with YAML frontmatter. If corrupted, log a warning and proceed in stateless mode. The pipeline must never block on a bad baseline.
123123

.claude/commands/compensating-controls.md

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -88,40 +88,34 @@ Single-command entry point for tachi compensating controls analysis — the thir
8888
8989
## Step 2: Run Control Analysis
9090
91-
1. Read the risk score input file at `{input_file}`.
91+
**IMPORTANT**: Do NOT read or embed the input files in the agent prompt. The control-analyzer agent has Read tool access and will load files on-demand to manage its own context window. Pass file **paths**, not file **contents**.
9292
93-
2. If `architecture_path` is not null, read the architecture file.
94-
95-
3. Invoke the `tachi-control-analyzer` agent with the following prompt:
93+
1. Invoke the `tachi-control-analyzer` agent with the following prompt:
9694
9795
```
98-
Analyze the following scored threat findings against the target codebase to detect
99-
existing security controls, classify each threat, recommend remediation for gaps,
100-
and calculate residual risk. Execute your complete 6-phase analysis pipeline
101-
(internal to the control-analyzer agent, not the threat-model command pipeline):
96+
Analyze scored threat findings against the target codebase to detect existing
97+
security controls, classify each threat, recommend remediation for gaps, and
98+
calculate residual risk. Execute your complete 6-phase analysis pipeline:
10299
Phase 1 (Parse Input) → Phase 2 (Discover Codebase) → Phase 3 (Detect Controls) →
103100
Phase 4 (Map & Classify) → Phase 5 (Recommend & Calculate Residual Risk) →
104101
Phase 6 (Generate Output).
105102

106-
Write all output files to: {output_dir}
107-
- compensating-controls.md
108-
- compensating-controls.sarif
109-
103+
Input file: {absolute path to input_file}
110104
Input format: {input_format}
111-
Analysis date: {current date YYYY-MM-DD}
105+
Architecture file: {absolute path to architecture_path, or "none"}
112106
Target codebase: {target_path}
107+
Output directory: {output_dir}
108+
Analysis date: {current date YYYY-MM-DD}
113109

114-
<risk-score-input>
115-
{contents of input file}
116-
</risk-score-input>
110+
Read the input file yourself using the Read tool. For large inputs,
111+
read in sections to manage context.
117112

118-
{if architecture_path is not null:}
119-
<architecture-input>
120-
{contents of architecture file}
121-
</architecture-input>
113+
Write output files:
114+
- compensating-controls.md
115+
- compensating-controls.sarif
122116
```
123117
124-
4. Wait for the control-analyzer agent to complete all 6 pipeline phases.
118+
2. Wait for the control-analyzer agent to complete all 6 pipeline phases.
125119
126120
## Step 3: Report Results
127121

.claude/commands/risk-score.md

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -72,35 +72,31 @@ Single-command entry point for tachi quantitative risk scoring. Validates prereq
7272
7373
## Step 2: Run Risk Scoring
7474
75-
1. Read the input file at `{input_file}`.
75+
**IMPORTANT**: Do NOT read or embed the input files in the agent prompt. The risk-scorer agent has Read tool access and will load files on-demand to manage its own context window. Pass file **paths**, not file **contents**.
7676
77-
2. If `architecture_path` is not null, read the architecture file.
78-
79-
3. Invoke the `tachi-risk-scorer` agent with the following prompt:
77+
1. Invoke the `tachi-risk-scorer` agent with the following prompt:
8078
8179
```
82-
Score the following threat model output using your complete scoring pipeline
80+
Score the threat model output using your complete scoring pipeline
8381
(Threat Parsing → Trust Zone Extraction → Dimensional Scoring → Composite
8482
Calculation → Governance Fields → Output Generation).
8583

86-
Write all output files to: {output_dir}
87-
- risk-scores.md
88-
- risk-scores.sarif
89-
84+
Input file: {absolute path to input_file}
9085
Input format: {input_format}
86+
Architecture file: {absolute path to architecture_path, or "none"}
87+
Output directory: {output_dir}
9188
Scoring date: {current date YYYY-MM-DD}
9289

93-
<threat-model-input>
94-
{contents of input file}
95-
</threat-model-input>
90+
Read the input file yourself using the Read tool. For large threat models,
91+
read in sections: parse finding tables (Sections 3, 4, 4a) and trust zones
92+
(Section 2) first. You do not need to load the full file at once.
9693

97-
{if architecture_path is not null:}
98-
<architecture-input>
99-
{contents of architecture file}
100-
</architecture-input>
94+
Write output files:
95+
- risk-scores.md
96+
- risk-scores.sarif
10197
```
10298
103-
4. Wait for the risk-scorer agent to complete all 6 of its internal analysis phases.
99+
2. Wait for the risk-scorer agent to complete all 6 of its internal analysis phases.
104100
105101
## Step 3: Report Results
106102

.claude/commands/threat-model.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,23 @@ Consider user input before proceeding (if not empty).
2828

2929
7. Generate a unique run folder:
3030
- Compute timestamp: `YYYY-MM-DDTHH-MM-SS` (e.g., `2026-03-25T14-30-22`)
31+
- Set `parent_dir` to the current `output_dir` value (before appending timestamp)
3132
- Append to output_dir: `{output_dir}/{timestamp}/`
3233
- This ensures each run produces output in a unique subfolder
3334
- Example: `examples/agentic-app/test-output/2026-03-25T14-30-22/`
3435

36+
8. Auto-detect baseline from previous runs (unless `--baseline` was explicitly provided):
37+
- List all subdirectories in `parent_dir`
38+
- Exclude the current run's timestamp directory
39+
- Sort remaining directories lexicographically descending (ISO timestamps sort naturally)
40+
- Check each directory (most recent first) for a `threats.md` file
41+
- If found: set `baseline_path` to that file
42+
- If none found: `baseline_path = null` (first run — stateless mode)
43+
- Display when detected:
44+
```
45+
Baseline detected: {baseline_path}
46+
```
47+
3548
## Overview
3649
3750
Single-command entry point for tachi threat modeling. Validates prerequisites, invokes the tachi orchestrator agent against an architecture description, and writes the full output suite to the target directory.
@@ -92,6 +105,8 @@ Single-command entry point for tachi threat modeling. Validates prerequisites, i
92105
- threat-report.md
93106
- attack-trees/ (one file per Critical/High finding)
94107

108+
Baseline: {baseline_path or "none (first run — stateless mode)"}
109+
95110
Architecture input:
96111

97112
<architecture-input>
@@ -110,6 +125,7 @@ THREAT MODEL COMPLETE
110125
Architecture: {architecture_path}
111126
Output: {output_dir} ← includes timestamped subfolder
112127
Version: {version_tag or "unversioned"}
128+
Baseline: {baseline_path or "none (first run)"}
113129

114130
Files generated:
115131
threats.md — Primary threat model
@@ -120,6 +136,9 @@ Files generated:
120136
Risk Summary:
121137
Critical: {count} High: {count} Medium: {count} Low: {count}
122138

139+
Delta Summary (when baseline present):
140+
New: {count} Unchanged: {count} Updated: {count} Resolved: {count}
141+
123142
Next steps:
124143
1. Review Critical/High findings in {output_dir}/threats.md Section 7
125144
2. Run /risk-score to add quantitative risk scoring (CVSS, exploitability, scalability, reachability)

.claude/skills/tachi-orchestration/references/baseline-correlation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Reference material for baseline handling and carry-forward logic in the baseline
1313
### Priority Order
1414

1515
1. **Explicit `--baseline <path>`**: Use the specified file directly.
16-
2. **Auto-detection**: Check the output directory for an existing `threats.md`.
16+
2. **Auto-detection**: Scan the output directory's **parent** for the most recent sibling directory containing a `threats.md`. Since each run creates a timestamped subfolder (e.g., `docs/security/2026-04-08T15-16-21/`), list all sibling directories, sort lexicographically (ISO timestamps sort naturally), exclude the current run's directory, and use the `threats.md` from the most recent match.
1717
3. **No baseline found**: Operate in stateless mode (identical to pre-baseline behavior).
1818

1919
### Validation

0 commit comments

Comments
 (0)