Progressive Disclosure Trees¶
Source: hooks/ways/meta/knowledge/authoring/trees/trees.md
Frontmatter
| Field | Value |
|---|---|
description |
decomposing a large way into a progressive disclosure tree of parent and child ways — when to split, the parent boost, sibling vocabulary isolation, token budgets, and anti-rationalization tables in leaf ways |
vocabulary |
tree child parent split decompose subway sub-way nest leaf sibling jaccard isolation boost cascade budget worst-case rationalization counter |
refire |
0.15 |
scope |
agent, subagent |
When a way covers multiple distinct concerns (>80 lines, >2 sub-topics, language/tool-specific variants), decompose into a tree. The supply chain tree (softwaredev/code/supplychain/) is the reference implementation. A way whose delivered body is over the 10,000-character hook context cap must be split: ways author lint reports it as an error.
How disclosure works now (ADR-125): ways are nodes in a DAG. When a parent fires, a session marker is set. Whenever any ancestor has a marker, an in-domain child's semantic bar is lowered from τ_s to (τ_s × config.parent_threshold_multiplier).max(config.parent_boost_floor) — by default max(0.5 × 0.8, 0.30) = 0.40 — so children fire on weaker signal once their domain is active. The multiplier (0.8) is the boost; the floor (0.30) stops cascading boosts from reaching the noise band; both operate in probability space (ADR-156). This is the mechanism behind "progressive disclosure": children are always candidates, but the boost makes in-domain children easier to fire. Full model in hooks-and-ways/matching.md.
Cross-firing between a child and its root — thresholds are global (τ_s / τ_k), not per-way, so there is no threshold to raise on the child. When a child cross-fires with the root (or a sibling), sharpen the child's own signal instead: add discriminating vocabulary, tighten the pattern:, then verify with tools/scripts/probe-measure.py. The remedy loop is always measure → edit vocabulary/pattern → re-measure — never move a threshold (there is none to move).
Vocabulary isolation — sibling ways MUST NOT share vocabulary:
- Target Jaccard similarity < 0.15 between siblings
- Each child owns its own keyword space
- Use ways author tree <path> --jaccard to verify; use ways author siblings <way-id> for embedding similarity, and ways tune locale --way <path> to surface cross-way confusers in multilingual space
Token awareness — aim for:
- Realistic path (root→leaf): ~1200 tokens
- Worst case (all fire): ~4000 tokens
- Use /ways-tests budget <tree> to measure
When NOT to tree: Leave flat if <80 lines, single cohesive concern, or all content is needed together.
Tree Validation¶
ways author tree <path>— structural analysis: depth, vocabulary size, and tokens per way/ways-tests tree <path>— structural analysis (depth, breadth, disclosure boost)/ways-tests budget <path>— token cost per way, per path, worst-case/ways-tests crowding "prompt"— vocabulary overlap detection/ways-tests metrics— session disclosure tracking (after live use)
Anti-Rationalization Patterns¶
For high-stakes ways where the agent is tempted to skip steps (testing, security, supply chain), add a "Common Rationalizations" table:
## Common Rationalizations
| Rationalization | Counter |
|---|---|
| "This is simple, tests aren't needed" | If it's simple, the test is trivial. Write it. |
| "I'll add tests later" | Later never comes. Tests verify understanding NOW. |
Placement: In the specific leaf/mid-tier node, not the root. The table should only appear when the agent is actively doing the thing it might skip.
Tone: Direct, not preachy. State the fact. 5-7 rows max.
See Also¶
- knowledge/authoring(meta) — parent: way format and matching
- knowledge/optimization(meta) — vocabulary tuning, sparsity, discrimination