agentic scripts / humans
how compaction-driven orchestration works
the problem
Without a map, an AI agent typically needs 10-20+ tool calls to understand a codebase — globbing for files, reading each one in full, grepping for relationships. Each call is an LLM round-trip that costs tokens and time.
the solution: compaction
Compaction is a pre-processing step that strips source files down to their structural skeleton: function signatures, imports, exports, component props, and type definitions. No implementation details. The agent greps this single file instead of reading source files one by one.
| vanilla agent | with compaction | |
|---|---|---|
| tool calls to understand codebase | 10-20+ | 2-4 |
| tokens on source code | high (full files) | low (signatures only) |
| LLM round-trips | many | few |
| risk of wrong path | high | low |
The tradeoff is a one-time compaction cost (~5-10s to run the script). It pays for itself on the first task and is skipped entirely on subsequent ones.
why this works: out-of-context processing
JS scripts run outside the LLM context window. When an agent reads a 500-line file to find three function signatures, all 500 lines count as input tokens. These tools do the filtering in Node.js (zero tokens) and hand the agent only the structural output.
A typical 200-file project might be ~50k tokens of raw source. After compaction, the same project is ~3-5k tokens of signatures. This means fewer tool calls, less context pollution, and faster convergence on the right file to edit.
tools
Walks your project tree and strips every JS/TS/Python file down to its skeleton: imports,
exports, function signatures, component props, hook usage, class declarations, and type
definitions. Outputs a single compacted_*.md file. Supports React-specific
patterns (memo, forwardRef, useState, useEffect with dependency arrays, custom hooks).
Builds a full dependency graph from import/require statements. For each file it records
what it imports (forward edges), what imports it (reverse edges / imported-by),
and which external packages it uses. Runs cycle detection via DFS. Agents grep
imported-by to check blast radius before modifying a file.
Extracts every top-level symbol (components, functions, hooks, classes, types, constants) with its file path, line number, and export type (default, named, or internal). Lets agents answer "where is X defined?" with a single grep instead of globbing the entire codebase.
All three scripts are zero-dependency (Node.js built-ins only), run in ~5-10 seconds, and produce markdown files that persist across agent sessions.
claude code hooks
Claude Code supports hooks — shell scripts that run automatically at specific points in the agent lifecycle. This project uses four hooks to make orchestration fully automatic, with no manual prompting required.
Fires on every prompt. Reads the user's message, matches signal words against a classification
table (feature, bugfix, refactor, etc.), and injects the full orchestration protocol plus the
matched workflow into the agent's context. Also auto-detects the project's technology
(React, .NET, or general) for correct workflow routing. Extracts
prompt keywords — content words from the user's message with
stop words and classification signal words stripped — and writes them to
.prompt_keywords for use by the grep quality gate. If the project has no
.orchestration/ directory, it silently does nothing.
Runs once when a session starts. Compares the local orchestration.md against the CDN
version and updates if stale. Fetches the tool script manifest and re-downloads any scripts whose
sha256 hash has changed. Cleans up old compaction/dep-graph/symbol artifacts and removes any whose
embedded git-sha no longer matches HEAD.
Enforces the compaction-first gate with grep quality validation.
Blocks the agent from reading source files, globbing src/, or spawning Explore
agents until it has grepped the compacted output with meaningful search terms. Rejects trivial
patterns (single characters, .*, empty strings) and tracks every grep pattern in
.grep_patterns. Source access unlocks only when the agent has used
2+ distinct non-trivial patterns, or
1 pattern that matches a prompt keyword extracted by
classify.sh. When blocked, the deny message shows which patterns have been tried
and what's still needed.
Re-injects the orchestration protocol after context compaction (when the LLM's context window is
compressed). Not registered as a hook event (Claude Code doesn't have a PostCompact
event), but kept as a utility script that can be called manually or by future hook events.
grep quality gate
The guard doesn't just check whether the agent grepped compaction — it checks what it searched for. Without this, an agent could grep for a nonsense string, get zero results, and proceed to read every source file directly, defeating the purpose of compaction.
When the agent greps compaction, the guard records the pattern and checks two unlock criteria:
| criterion | what it means |
|---|---|
| 2+ distinct patterns | agent is genuinely exploring the compacted output |
| 1 pattern matches a prompt keyword | agent is searching for something task-relevant |
Prompt keywords are extracted by classify.sh on every
prompt: the user's message is lowercased, stop words (the, a, for, etc.) and classification signal
words (fix, add, build, etc.) are stripped, and the remaining 3+ character words are saved. For
example, "fix the login bug in TokenRefreshInterceptor" produces keywords login and
tokenrefreshinterceptor. If the agent greps compaction for "login", the gate unlocks
immediately because it matches a prompt keyword. All markers are cleared on each new prompt, so
the gate resets per-task.
the hook installer
The hook installer is a self-executing prompt — you pipe it into Claude Code and it installs everything automatically:
It writes all four hook scripts to ~/.claude/hooks/, registers them in
~/.claude/settings.json with the correct absolute paths, matchers, and timeouts,
then verifies each hook exits cleanly and the settings file is valid JSON. The hooks are installed
globally, so they activate for every project. Projects without an
.orchestration/ directory are silently skipped.