From 409cd77cbcbb2c12bfbd8420bea3b7a624f0230c Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 26 Mar 2026 17:00:06 -0500 Subject: [PATCH] feat(01-01): add taskMetadata to ClassificationResult and export extractTaskMetadata - Add taskMetadata?: TaskMetadata to ClassificationResult in complexity-classifier.ts - Add taskMetadata?: TaskMetadata to ClassificationResult in types.ts (duplicate interface) - Export extractTaskMetadata() so it can be imported by model-router.ts - Refactor classifyUnitComplexity() to extract metadata once for execute-task (eliminates double-extraction at adaptive learning step) - Populate taskMetadata field on ClassificationResult for execute-task units - Set taskMetadata: undefined explicitly on hook unit fast-path --- .../extensions/gsd/complexity-classifier.ts | 13 +++++++++---- src/resources/extensions/gsd/types.ts | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/resources/extensions/gsd/complexity-classifier.ts b/src/resources/extensions/gsd/complexity-classifier.ts index 114178810..82027227f 100644 --- a/src/resources/extensions/gsd/complexity-classifier.ts +++ b/src/resources/extensions/gsd/complexity-classifier.ts @@ -16,6 +16,7 @@ export interface ClassificationResult { tier: ComplexityTier; reason: string; downgraded: boolean; // true if budget pressure lowered the tier + taskMetadata?: TaskMetadata; } export interface TaskMetadata { @@ -71,17 +72,20 @@ export function classifyUnitComplexity( ): ClassificationResult { // Hook units default to light if (unitType.startsWith("hook/")) { - const result: ClassificationResult = { tier: "light", reason: "hook unit", downgraded: false }; + const result: ClassificationResult = { tier: "light", reason: "hook unit", downgraded: false, taskMetadata: undefined }; return applyBudgetPressure(result, budgetPct); } // Start with the default tier for this unit type let tier = UNIT_TYPE_TIERS[unitType] ?? "standard"; let reason = `unit type: ${unitType}`; + let taskMeta: TaskMetadata | undefined; // For execute-task, analyze task metadata for complexity signals if (unitType === "execute-task") { - const taskAnalysis = analyzeTaskComplexity(unitId, basePath, metadata); + // Extract metadata once and reuse throughout to avoid double-extraction + taskMeta = metadata ?? extractTaskMetadata(unitId, basePath); + const taskAnalysis = analyzeTaskComplexity(unitId, basePath, taskMeta); tier = taskAnalysis.tier; reason = taskAnalysis.reason; } @@ -96,14 +100,15 @@ export function classifyUnitComplexity( } // Adaptive learning: check if history suggests bumping the tier - const tags = metadata?.tags ?? extractTaskMetadata(unitId, basePath).tags; + // Use already-extracted taskMeta.tags if available to avoid double-extraction + const tags = taskMeta?.tags ?? metadata?.tags; const adaptiveAdjustment = getAdaptiveTierAdjustment(unitType, tier, tags); if (adaptiveAdjustment && tierOrdinal(adaptiveAdjustment) > tierOrdinal(tier)) { reason = `${reason} (adaptive: high failure rate at ${tier})`; tier = adaptiveAdjustment; } - const result: ClassificationResult = { tier, reason, downgraded: false }; + const result: ClassificationResult = { tier, reason, downgraded: false, taskMetadata: taskMeta }; return applyBudgetPressure(result, budgetPct); } diff --git a/src/resources/extensions/gsd/types.ts b/src/resources/extensions/gsd/types.ts index 25bee6774..c06891e07 100644 --- a/src/resources/extensions/gsd/types.ts +++ b/src/resources/extensions/gsd/types.ts @@ -316,6 +316,7 @@ export interface ClassificationResult { tier: ComplexityTier; reason: string; downgraded: boolean; + taskMetadata?: TaskMetadata; } export interface TaskMetadata {