- train_specialist_pt.py: pure PyTorch trainer replacing Fabricate binary. No SQLite/WAL — saves checkpoint.pt + history.json only. Fabricate was causing D-state IO blocking on the HDD due to continuous WAL writes. - eval_specialist_pt.py: PyTorch eval with confusion matrix, threshold analysis, guardrail assessment, and deployment verdict. - capacity_sweep.py: updated to call PyTorch scripts; TIERS now include heads field (4/6/8) since PyTorch supports multi-head unlike Fabricate. - prereq_op_binary_split.py: evaluate_combined rewritten in PyTorch. - Performance fix in train_specialist_pt.py: load training data onto GPU once and sample via torch.randint instead of DataLoader (eliminates Python/CPU overhead on tiny datasets). Fix applied, not yet timed. Next session: time the fix, then run sweep_all_gates.sh --pilot-only. See HANDOFF-2026-03-31.md for full context. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
17 KiB
Whetstone Specialist Fleet — Roadmap
Read README.md first. This document assumes you understand the core premise.
Guiding principle: "LLM required" is not a permanent category. Every decision is either deterministic, statistical, or not yet decomposed. This roadmap is the plan for collapsing the "not yet decomposed" pile, one specialist at a time.
Architectural correction (important): Whetstone is NOT a C++ code generator.
C++, Python, Rust, and all other output languages are projections of an
AST-as-source-of-truth. The AST uses language-neutral conceptType names
(Function, ClassDeclaration, IfStatement, etc.) that map uniformly across
19+ target languages. Specialists operate at the AST level — one specialist per
decision type covers all projection languages. Do not train per-language variants
of decisions that live in the AST layer.
The AST Is Already Rich
Whetstone's AST is not a minimal syntax tree. It carries annotation metadata that most derived ASTs never have. Key files:
editor/src/ast/ASTNode.h— base node withconceptType,semanticHash, role-based childreneditor/src/ast/Annotation.h— 60+ annotation types (see Subject breakdown below)editor/src/SemanticCoreIR.h— cross-language IR withintentTagseditor/src/SemanticTags.h— 10-tag vocabulary (@serialize,@crypto,@io, etc.)editor/src/ContextAPI.h—CallHierarchyInfowithcallerIds/calleeIdseditor/src/graduation/BlastRadiusAnalyzer.h— impact scoringeditor/src/DependencyGraph.h— dependency edges and critical path
The metadata that matters for specialists
Downstream impact — already computed, available as input features:
RiskAnnotation.dependentCount int how many callers/consumers
CallHierarchyInfo.callerIds list which functions call this one
BlastRadiusReport.riskLevel enum none/low/medium/high
BlastRadiusEntry.impactScore int numerical impact
FailureTriageScore.blastRadius int propagation count
Intent and complexity — already stored on nodes:
IntentAnnotation.category enum validation/transformation/io/
coordination/computation/initialization
IntentAnnotation.summary text 1-sentence description
ComplexityAnnotation.timeComplexity O(1)/O(n)/O(n^2)/...
ComplexityAnnotation.cognitiveComplexity 1-10 scale
SemanticTagAnnotation.tags list @serialize/@crypto/@io/@math/etc.
The Tacit Codex annotation — already in the schema:
AutomatabilityAnnotation.strategy enum deterministic | template | slm | llm | human
AutomatabilityAnnotation.confidence float 0.0–1.0
This annotation encodes the entire Tacit Codex hierarchy on individual AST nodes.
A specialist that predicts automatability.strategy for a given node is the
entropy classifier the Tacit Codex is building toward — it just needs to be trained.
Phase 0 — Foundation (COMPLETE)
Done:
verification_typespecialist: 5-way, 83.7% accuracy- Input: sprint step description text
- Output: unit / integration / schema / smoke / docs
- Checkpoint:
/mnt/storage/fabricate_runs/whetstone_verification_type/
confidence_tierspecialist: 3-way, 100% accuracy- Input:
"conflicts=N ambiguity=M deps=D prereqs=P queueready=yes/no" - Output: high / medium / low
- Checkpoint:
/mnt/storage/fabricate_runs/whetstone_confidence_tier/
- Input:
- Inference wrapper:
scripts/infer.py
Key finding from Phase 0: Sprint plan step descriptions are the right training data source for text-based specialists. The 18,519 JSONL pipeline run records are too homogeneous (2 task patterns repeated). Do not use JSONL as the text source.
Phase 1 — Pipeline Specialists (NEXT)
Goal: Cover the remaining bounded decisions in generate_taskitems
and validate_taskitem. These are at the taskitem planning layer, above the AST.
1.1 — prereq_op_selector (4-way)
Input: task step description text Output:
0: standard → [validate-intake, resolve-dependencies]
1: needs_review → [validate-intake, architect-review]
2: needs_approval → [validate-intake, manual-approval]
3: full_gates → [validate-intake, architect-review, manual-approval]
Training data: synthetic — generate task descriptions that signal each gate type.
Script to write: scripts/gen_prereq_op_data.py
1.2 — worker_type (4-way)
Input: task step description text
Output: implementer / reviewer / architect / qa
Training data: sprint plan files (same heuristic approach as verification_type).
Script to write: scripts/gen_worker_type_data.py
1.3 — gap_class (5-way)
Input: taskitem issue description text
Output: under_constrained / environment_gap / planning_gap / cross_project_gap / generator_capability_gap
Training data: synthetic — generate issue descriptions encoding each gap type.
Script to write: scripts/gen_gap_class_data.py
1.4 — escalation_predictor (binary)
Input: "confidence=N ambiguity=M" structural encoding
Output: escalate / proceed
Training data: synthetic from formula (escalate = confidence < 60 OR ambiguity > 0).
Expected accuracy: 100% (deterministic formula, same as confidence_tier).
Script to write: scripts/gen_escalation_data.py
Phase 2 — AST Annotation Specialists
Goal: Train specialists that predict annotation fields on AST nodes. These operate one level deeper than the taskitem pipeline — they answer questions about individual AST nodes, not about sprint planning.
The annotation system already defines the output schema. Specialists populate annotation fields that are currently filled by the LLM or left empty.
2.1 — automatability_strategy specialist (THE KEY ONE) — (6-way)
This is the Tacit Codex entropy classifier applied to AST nodes.
IMPORTANT — update editor/src/ast/Annotation.h first. The current enum
(deterministic|template|slm|llm|human) is missing the specialist tier.
The correct 6-tier hierarchy is:
deterministic same input → same output always. Formula. Zero parameters.
template deterministic composition of known structural patterns. No ambiguity.
specialist bounded output vocabulary (fixed N classes). Fuzzy/probabilistic.
~800KB model, microseconds — THIS PROJECT's outputs.
slm open vocabulary, arbitrary token generation. ~1-7GB.
llm full generative, cross-context, novel reasoning. ~14B+.
human not yet formalizable.
Boundary between specialist and slm: can the output be a fixed enum?
Yes → specialist. Requires generating novel tokens → slm or llm.
Boundary between template and specialist: deterministic? Yes → template.
Probabilistic with a confidence score → specialist.
Add "specialist" to the strategy field in Annotation.h before training.
Input features (all from existing AST/annotation metadata):
conceptType (Function/Class/Variable/EnumDeclaration/...)
intentCategory (validation/transformation/io/coordination/computation/init)
dependentCount (0-100+ from RiskAnnotation)
semanticTags (space-separated: @io @serialize @math...)
cognitiveComplexity (1-10 from ComplexityAnnotation)
hasBody (yes/no — skeleton vs implemented)
Encoded as: "type=Function intent=validation deps=12 tags=@io @serialize complexity=4 body=yes"
Output: deterministic / template / specialist / slm / llm / human
Why this is the most important specialist: Once trained, every node in the AST can be tagged with its automatability tier. The pipeline routes each node's decisions to the appropriate handler:
deterministic→ formula/rule, no inference at alltemplate→ template instantiation, near-zero costspecialist→ specialist fleet dispatch (~0.5ms)slm→ small model call (~500ms)llm→ full LLM call (~2-5s)human→ escalate via ReviewAnnotation
This replaces the current situation where every decision defaults to "llm" regardless.
Training data: The 93 existing editor/src/*.h headers are labeled examples.
Each header class can be manually categorized. Starting corpus: ~93 examples
(thin but the patterns are strong — expect grokking with heavy oversampling).
Future: every new header added to the codebase extends the training set.
Script to write: scripts/gen_automatability_data.py
2.2 — intent_category specialist (6-way)
Input: node name + semantic tags + parent conceptType (all language-neutral) Output: validation / transformation / io / coordination / computation / initialization
Training data: mine existing headers. The class name + role suffix strongly predicts the category:
*Validator,*Scorer,*Auditor→ validation*Generator,*Builder,*Composer→ transformation*Loader,*Writer,*Exporter→ io*Dispatcher,*Router,*Registry→ coordination*Calculator,*Analyzer,*Solver→ computation*Initializer,*Factory,*Bootstrap→ initialization
This is trainable from class name patterns alone. 93 headers = 93 examples to start.
Script to write: scripts/gen_intent_category_data.py
2.3 — change_risk_tier specialist (4-way)
Input: "deps=N callers=M impactScore=K blastRadius=R" (all from existing metadata)
Output: low / medium / high / critical
This specialist uses the blast radius and downstream dependency counts as its
primary input signal. A function with deps=47 and blastRadius=12 is high risk.
A function with deps=0 and callers=1 is low risk.
Training data: synthetic from rules:
- critical: deps > 20 OR callerIds.count > 15
- high: deps 10-20 OR callers 8-15
- medium: deps 3-10 OR callers 2-8
- low: deps 0-3, callers 0-2
Script to write: scripts/gen_change_risk_data.py
Expected accuracy: ~100% (formula-based, same as confidence_tier).
2.4 — semantic_tag specialist (multi-label → primary tag, 10-way)
Input: node name text (language-neutral conceptual name) Output: primary semantic tag from vocabulary: @serialize / @crypto / @io / @network / @math / @collection / @concurrency / @test / @ui / @parse
The SemanticTags.h file already has auto-tagging rules based on library names
and identifier keywords. This specialist learns the same rules from examples.
Training data: mine existing headers using the auto-tagger rules as labels.
Script to write: scripts/gen_semantic_tag_data.py
2.5 — component_suffix specialist (12-way)
Input: 1-sentence description of what a component does Output: naming suffix that fits the role: Validator / Scorer / Auditor / Generator / Processor / Selector / Advisor / Binder / Extractor / Composer / Builder / Registry
Training data: 93 existing editor/src/*.h headers as labeled examples.
Each filename encodes the ground-truth suffix. Thin data but strong patterns.
Script to write: scripts/gen_component_suffix_data.py
Phase 3 — Data Collection (Running in Background)
Goal: Make every LLM tool call a training data generator.
3.1 — Instrument bounded sub-decisions
Add post-processing to tools/mcp/export_taskitem_run_for_lora.sh to extract
per-decision labels from each pipeline run. When generate_taskitems emits a task
with verificationType: "integration", append (step_description, "integration")
to training_data/specialists/verification_type_examples.jsonl.
3.2 — Annotation capture hook
When the LLM fills an AutomatabilityAnnotation or IntentAnnotation on any
AST node, capture (input_features, annotation_value) as a training example.
These accumulate automatically with normal usage.
3.3 — Blast radius instrumentation
When BlastRadiusAnalyzer runs, emit (dependentCount, blastRadius, callerCount) → riskLevel
as a labeled example. This grows the change_risk_tier training set with every
real analysis run.
Phase 4 — Integration
Goal: Wire specialists into the MCP tool layer.
4.1 — Dispatch server
scripts/dispatch.py — loads all trained specialists at startup, accepts JSON,
returns predictions. All specialists run in a single batched forward pass.
4.2 — Pre-annotation pass
New MCP tool: whetstone_annotate_nodes — given a list of AST node descriptors,
runs the specialist fleet and returns predicted annotation values before the LLM
is called. The LLM then only handles open-text fields and human-tier decisions.
4.3 — Automatability routing
Once automatability_strategy specialist is trained and validated:
deterministicnodes: handled by formula/rule engine, no inferencetemplatenodes: handled by template instantiationslmnodes: handled by specialist dispatchllmnodes: LLM call with pre-filled context from specialistshumannodes: escalated viaReviewAnnotation.required = true
Phase 5 — Code Generation Specialists
Goal: Decompose "generative" decisions into bounded sub-decisions.
Once Phase 2 establishes the full annotation vocabulary, code generation becomes:
Node with annotations
→ automatability_strategy = "template" ← specialist decides
→ intent_category = "transformation" ← specialist decides
→ structural_pattern = "pipeline" ← specialist decides (new)
→ control_flow_pattern = "early-return" ← specialist decides (new)
→ error_handling_style = "Result<T,E>" ← specialist decides (new)
→ projection language = "cpp" ← human or router decides
↓
Deterministic template instantiation
↓
Code skeleton
↓
LLM fills only: identifier names, literal values, comments ← narrow residual
Specialists for this phase:
structural_pattern(factory/visitor/strategy/builder/observer/pipeline/scorer/registry...)control_flow_pattern(linear/if-else-chain/early-return/loop/recursive/dispatch-table...)error_handling_style(exception/Result/optional/expected/assert/error-code...)data_structure_choice(vector/map/deque/set/flat-array/ring-buffer...)
Each of these is a bounded classification over the AST node's role and annotation
context. Each can be trained from the existing editor/src/ headers as examples.
Tracking Progress
| Specialist | Phase | Status | Accuracy | Checkpoint |
|---|---|---|---|---|
verification_type |
0 | ✅ DONE | 83.7% | /mnt/storage/fabricate_runs/whetstone_verification_type/ |
confidence_tier |
0 | ✅ DONE | 100% | /mnt/storage/fabricate_runs/whetstone_confidence_tier/ |
prereq_op_selector |
1.1 | ⬜ planned | — | — |
worker_type |
1.2 | ⬜ planned | — | — |
gap_class |
1.3 | ⬜ planned | — | — |
escalation_predictor |
1.4 | ⬜ planned | — | — |
automatability_strategy |
2.1 | ⬜ planned (6-way, needs Annotation.h update first) | — | — |
intent_category |
2.2 | ⬜ planned | — | — |
change_risk_tier |
2.3 | ⬜ planned | — | — |
semantic_tag |
2.4 | ⬜ planned | — | — |
component_suffix |
2.5 | ⬜ planned | — | — |
structural_pattern |
5 | ⬜ planned | — | — |
control_flow_pattern |
5 | ⬜ planned | — | — |
error_handling_style |
5 | ⬜ planned | — | — |
What the Next Agent Should Do First
- Read
README.mdand this file completely - Verify Phase 0 specialists by running
infer.py --eval-tsvon both held-out sets - Start Phase 2.1 (
automatability_strategy) — it is the most architecturally significant specialist and training data already exists ineditor/src/*.h - Then Phase 1.1 (
prereq_op_selector) to complete the pipeline layer - Do not train per-language specialist variants — the AST is language-neutral; projection is handled downstream by deterministic grammar rules
Connection to Other Projects
WhetstoneAI_Fabricate (/home/bill/Documents/WhetstoneAI_Fabricate/):
Training infrastructure. Binary, harness, eval tools. The RSA experiments
(see HANDOFF-2026-03-28-RSA.md) validated the specialist architecture at scale.
The label convention fix (swap_label_rows.py) is documented there — read it
before resuming any checkpoint with a changed --labels order.
Tacit Codex (tacit_codex/):
AutomatabilityAnnotation.strategy in editor/src/ast/Annotation.h is the
Tacit Codex entropy classification built into the AST schema. Training the
automatability_strategy specialist is the concrete implementation of the
Tacit Codex collapse-to-formal-structure program applied to individual AST nodes.
The entropy ledger in HiveMind tracks the same quantity at the job-scheduling layer.
HiveMind (/home/bill/Documents/hivemind/):
Future state: a generate_taskitems job becomes a fan-out of N specialist jobs
- 1 LLM job (only for
llm-tier nodes), merged by coordinator. The automatability tier determines which job type each node gets dispatched to.