@rfxlamia/skillkit 1.0.0 ā 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/agents/creative-copywriter.md +212 -0
- package/agents/agents/dario-amodei.md +135 -0
- package/agents/agents/doc-simplifier.md +63 -0
- package/agents/agents/kotlin-pro.md +433 -0
- package/agents/agents/red-team.md +136 -0
- package/agents/agents/sam-altman.md +121 -0
- package/agents/agents/seo-manager.md +184 -0
- package/package.json +7 -2
- package/skills/quick-spec/tests/__pycache__/test_skill.cpython-314-pytest-9.0.2.pyc +0 -0
- package/skills/skillkit/.claude/settings.local.json +7 -0
- package/skills/skillkit/scripts/__pycache__/decision_helper.cpython-314.pyc +0 -0
- package/skills/skillkit/scripts/__pycache__/quick_validate.cpython-312.pyc +0 -0
- package/skills/skillkit/scripts/__pycache__/quick_validate.cpython-314.pyc +0 -0
- package/skills/skillkit/scripts/__pycache__/test_generator.cpython-314-pytest-9.0.2.pyc +0 -0
- package/skills/skillkit/scripts/utils/__pycache__/__init__.cpython-312.pyc +0 -0
- package/skills/skillkit/scripts/utils/__pycache__/__init__.cpython-314.pyc +0 -0
- package/skills/skillkit/scripts/utils/__pycache__/budget_tracker.cpython-312.pyc +0 -0
- package/skills/skillkit/scripts/utils/__pycache__/budget_tracker.cpython-314.pyc +0 -0
- package/skills/skillkit/scripts/utils/__pycache__/output_formatter.cpython-312.pyc +0 -0
- package/skills/skillkit/scripts/utils/__pycache__/output_formatter.cpython-314.pyc +0 -0
- package/skills/skillkit/scripts/utils/__pycache__/reference_validator.cpython-312.pyc +0 -0
- package/skills/skillkit/scripts/utils/__pycache__/reference_validator.cpython-314.pyc +0 -0
- package/skills/skillkit-help/SKILL.md +81 -0
- package/skills/skillkit-help/knowledge/application/09-case-studies.md +257 -0
- package/skills/skillkit-help/knowledge/application/12-testing-and-validation.md +276 -0
- package/skills/skillkit-help/knowledge/foundation/01-why-skills-exist.md +246 -0
- package/skills/skillkit-help/knowledge/foundation/02-skills-vs-subagents-comparison.md +312 -0
- package/skills/skillkit-help/knowledge/foundation/03-skills-vs-subagents-decision-tree.md +346 -0
- package/skills/skillkit-help/knowledge/foundation/06-platform-constraints.md +237 -0
- package/skills/skillkit-help/knowledge/foundation/08-when-not-to-use-skills.md +270 -0
- package/skills/skillkit-help/template/SKILL.md +52 -0
- package/skills/skills/adversarial-review/SKILL.md +219 -0
- package/skills/skills/baby-education/SKILL.md +260 -0
- package/skills/skills/baby-education/references/advanced-techniques.md +323 -0
- package/skills/skills/baby-education/references/transformations.md +345 -0
- package/skills/skills/been-there-done-that/SKILL.md +455 -0
- package/skills/skills/been-there-done-that/references/analysis-patterns.md +162 -0
- package/skills/skills/been-there-done-that/references/git-commands.md +132 -0
- package/skills/skills/been-there-done-that/references/tree-insertion-logic.md +145 -0
- package/skills/skills/coolhunter/SKILL.md +270 -0
- package/skills/skills/coolhunter/assets/elicitation-methods.csv +51 -0
- package/skills/skills/coolhunter/knowledge/elicitation-methods.md +312 -0
- package/skills/skills/coolhunter/references/workflow-execution.md +238 -0
- package/skills/skills/coolhunter/workflow-plan-coolhunter.md +232 -0
- package/skills/skills/creative-copywriting/SKILL.md +324 -0
- package/skills/skills/creative-copywriting/databases/README.md +60 -0
- package/skills/skills/creative-copywriting/databases/carousel-structures.csv +16 -0
- package/skills/skills/creative-copywriting/databases/emotional-arcs.csv +11 -0
- package/skills/skills/creative-copywriting/databases/hook-formulas.csv +51 -0
- package/skills/skills/creative-copywriting/databases/power-words.csv +201 -0
- package/skills/skills/creative-copywriting/databases/psychological-triggers.csv +21 -0
- package/skills/skills/creative-copywriting/databases/read-more-patterns.csv +26 -0
- package/skills/skills/creative-copywriting/databases/swipe-triggers.csv +31 -0
- package/skills/skills/creative-copywriting/references/carousel-psychology.md +223 -0
- package/skills/skills/creative-copywriting/references/hook-anatomy.md +169 -0
- package/skills/skills/creative-copywriting/references/power-word-science.md +134 -0
- package/skills/skills/creative-copywriting/references/storytelling-frameworks.md +157 -0
- package/skills/skills/diverse-content-gen/SKILL.md +201 -0
- package/skills/skills/diverse-content-gen/references/advanced-techniques.md +320 -0
- package/skills/skills/diverse-content-gen/references/research-findings.md +379 -0
- package/skills/skills/diverse-content-gen/references/task-workflows.md +241 -0
- package/skills/skills/diverse-content-gen/references/tool-integration.md +419 -0
- package/skills/skills/diverse-content-gen/references/troubleshooting.md +426 -0
- package/skills/skills/diverse-content-gen/references/vs-core-technique.md +240 -0
- package/skills/skills/framework-critical-thinking/SKILL.md +220 -0
- package/skills/skills/framework-critical-thinking/references/bias_detector.md +375 -0
- package/skills/skills/framework-critical-thinking/references/fallback_handler.md +239 -0
- package/skills/skills/framework-critical-thinking/references/memory_curator.md +161 -0
- package/skills/skills/framework-critical-thinking/references/metacognitive_monitor.md +297 -0
- package/skills/skills/framework-critical-thinking/references/producer_critic_orchestrator.md +333 -0
- package/skills/skills/framework-critical-thinking/references/reasoning_router.md +235 -0
- package/skills/skills/framework-critical-thinking/references/reasoning_validator.md +97 -0
- package/skills/skills/framework-critical-thinking/references/reflection_trigger.md +78 -0
- package/skills/skills/framework-critical-thinking/references/self_verification.md +388 -0
- package/skills/skills/framework-critical-thinking/references/uncertainty_quantifier.md +207 -0
- package/skills/skills/framework-initiative/SKILL.md +231 -0
- package/skills/skills/framework-initiative/references/examples.md +150 -0
- package/skills/skills/framework-initiative/references/impact-analysis.md +157 -0
- package/skills/skills/framework-initiative/references/intent-patterns.md +145 -0
- package/skills/skills/framework-initiative/references/star-framework.md +165 -0
- package/skills/skills/humanize-docs/SKILL.md +203 -0
- package/skills/skills/humanize-docs/references/advanced-techniques.md +13 -0
- package/skills/skills/humanize-docs/references/core-transformations.md +368 -0
- package/skills/skills/humanize-docs/references/detection-patterns.md +400 -0
- package/skills/skills/humanize-docs/references/examples-gallery.md +374 -0
- package/skills/skills/imagine/SKILL.md +190 -0
- package/skills/skills/imagine/references/artstyle-corporate-memphis.md +625 -0
- package/skills/skills/imagine/references/artstyle-crewdson-hyperrealism.md +295 -0
- package/skills/skills/imagine/references/artstyle-iphone-social-media.md +426 -0
- package/skills/skills/imagine/references/artstyle-sciencesaru.md +276 -0
- package/skills/skills/pre-deploy-checklist/README.md +26 -0
- package/skills/skills/pre-deploy-checklist/SKILL.md +153 -0
- package/skills/skills/pre-deploy-checklist/references/checklist-categories.md +174 -0
- package/skills/skills/pre-deploy-checklist/references/domain-prompts.md +216 -0
- package/skills/skills/prompt-engineering/SKILL.md +209 -0
- package/skills/skills/prompt-engineering/references/advanced-combinations.md +444 -0
- package/skills/skills/prompt-engineering/references/chain-of-thought.md +140 -0
- package/skills/skills/prompt-engineering/references/decision_matrix.md +220 -0
- package/skills/skills/prompt-engineering/references/few-shot.md +346 -0
- package/skills/skills/prompt-engineering/references/json-format.md +270 -0
- package/skills/skills/prompt-engineering/references/natural-language.md +420 -0
- package/skills/skills/prompt-engineering/references/pitfalls.md +365 -0
- package/skills/skills/prompt-engineering/references/prompt-chaining.md +498 -0
- package/skills/skills/prompt-engineering/references/react.md +108 -0
- package/skills/skills/prompt-engineering/references/self-consistency.md +322 -0
- package/skills/skills/prompt-engineering/references/tree-of-thoughts.md +386 -0
- package/skills/skills/prompt-engineering/references/xml-format.md +220 -0
- package/skills/skills/prompt-engineering/references/yaml-format.md +488 -0
- package/skills/skills/prompt-engineering/references/zero-shot.md +74 -0
- package/skills/skills/quick-spec/SKILL.md +280 -0
- package/skills/skills/quick-spec/assets/tech-spec-template.md +74 -0
- package/skills/skills/quick-spec/references/step-01-understand.md +189 -0
- package/skills/skills/quick-spec/references/step-02-investigate.md +144 -0
- package/skills/skills/quick-spec/references/step-03-generate.md +128 -0
- package/skills/skills/quick-spec/references/step-04-review.md +173 -0
- package/skills/skills/quick-spec/tests/__pycache__/test_skill.cpython-314-pytest-9.0.2.pyc +0 -0
- package/skills/skills/quick-spec/tests/test_scenarios.md +83 -0
- package/skills/skills/quick-spec/tests/test_skill.py +136 -0
- package/skills/skills/readme-expert/SKILL.md +538 -0
- package/skills/skills/readme-expert/knowledge/INDEX.md +192 -0
- package/skills/skills/readme-expert/knowledge/application/quality-standards.md +470 -0
- package/skills/skills/readme-expert/knowledge/application/script-executor.md +604 -0
- package/skills/skills/readme-expert/knowledge/application/template-library.md +822 -0
- package/skills/skills/readme-expert/knowledge/foundation/codebase-scanner.md +361 -0
- package/skills/skills/readme-expert/knowledge/foundation/validation-checklist.md +481 -0
- package/skills/skills/red-teaming/SKILL.md +321 -0
- package/skills/skills/red-teaming/references/ai-llm-redteam.md +517 -0
- package/skills/skills/red-teaming/references/attack-techniques.md +410 -0
- package/skills/skills/red-teaming/references/cybersecurity-redteam.md +383 -0
- package/skills/skills/red-teaming/references/tools-frameworks.md +446 -0
- package/skills/skills/releasing/.skillkit-mode +1 -0
- package/skills/skills/releasing/SKILL.md +225 -0
- package/skills/skills/releasing/references/version-detection.md +108 -0
- package/skills/skills/screenwriter/SKILL.md +273 -0
- package/skills/skills/screenwriter/references/advanced-techniques.md +216 -0
- package/skills/skills/screenwriter/references/pipeline-integration.md +266 -0
- package/skills/skills/skillkit/.claude/settings.local.json +7 -0
- package/skills/skills/skillkit/.claude-plugin/plugin.json +27 -0
- package/skills/skills/skillkit/CHANGELOG.md +484 -0
- package/skills/skills/skillkit/SKILL.md +511 -0
- package/skills/skills/skillkit/commands/skillkit.md +6 -0
- package/skills/skills/skillkit/commands/validate-plan.md +6 -0
- package/skills/skills/skillkit/commands/verify.md +6 -0
- package/skills/skills/skillkit/knowledge/INDEX.md +352 -0
- package/skills/skills/skillkit/knowledge/application/09-case-studies.md +257 -0
- package/skills/skills/skillkit/knowledge/application/10-technical-architecture.md +324 -0
- package/skills/skills/skillkit/knowledge/application/11-adoption-strategy.md +267 -0
- package/skills/skills/skillkit/knowledge/application/12-testing-and-validation.md +276 -0
- package/skills/skills/skillkit/knowledge/application/13-competitive-landscape.md +198 -0
- package/skills/skills/skillkit/knowledge/foundation/01-why-skills-exist.md +246 -0
- package/skills/skills/skillkit/knowledge/foundation/02-skills-vs-subagents-comparison.md +312 -0
- package/skills/skills/skillkit/knowledge/foundation/03-skills-vs-subagents-decision-tree.md +346 -0
- package/skills/skills/skillkit/knowledge/foundation/04-hybrid-patterns.md +308 -0
- package/skills/skills/skillkit/knowledge/foundation/05-token-economics.md +275 -0
- package/skills/skills/skillkit/knowledge/foundation/06-platform-constraints.md +237 -0
- package/skills/skills/skillkit/knowledge/foundation/07-security-concerns.md +322 -0
- package/skills/skills/skillkit/knowledge/foundation/08-when-not-to-use-skills.md +270 -0
- package/skills/skills/skillkit/knowledge/plugin-guide.md +614 -0
- package/skills/skills/skillkit/knowledge/tools/14-validation-tools-guide.md +150 -0
- package/skills/skills/skillkit/knowledge/tools/15-cost-tools-guide.md +157 -0
- package/skills/skills/skillkit/knowledge/tools/16-security-tools-guide.md +122 -0
- package/skills/skills/skillkit/knowledge/tools/17-pattern-tools-guide.md +161 -0
- package/skills/skills/skillkit/knowledge/tools/18-decision-helper-guide.md +243 -0
- package/skills/skills/skillkit/knowledge/tools/19-test-generator-guide.md +275 -0
- package/skills/skills/skillkit/knowledge/tools/20-split-skill-guide.md +149 -0
- package/skills/skills/skillkit/knowledge/tools/21-quality-scorer-guide.md +226 -0
- package/skills/skills/skillkit/knowledge/tools/22-migration-helper-guide.md +356 -0
- package/skills/skills/skillkit/knowledge/tools/23-subagent-creation-guide.md +448 -0
- package/skills/skills/skillkit/knowledge/tools/24-behavioral-testing-guide.md +122 -0
- package/skills/skills/skillkit/references/proposal-generation.md +982 -0
- package/skills/skills/skillkit/references/rationalization-catalog.md +75 -0
- package/skills/skills/skillkit/references/research-methodology.md +661 -0
- package/skills/skills/skillkit/references/section-2-full-creation-workflow.md +452 -0
- package/skills/skills/skillkit/references/section-3-validation-workflow-existing-skill.md +63 -0
- package/skills/skills/skillkit/references/section-4-decision-workflow-skills-vs-subagents.md +64 -0
- package/skills/skills/skillkit/references/section-5-migration-workflow-doc-to-skill.md +58 -0
- package/skills/skills/skillkit/references/section-6-subagent-creation-workflow.md +499 -0
- package/skills/skills/skillkit/references/section-7-knowledge-reference-map.md +72 -0
- package/skills/skills/skillkit/scripts/__pycache__/decision_helper.cpython-314.pyc +0 -0
- package/skills/skills/skillkit/scripts/__pycache__/quick_validate.cpython-312.pyc +0 -0
- package/skills/skills/skillkit/scripts/__pycache__/quick_validate.cpython-314.pyc +0 -0
- package/skills/skills/skillkit/scripts/__pycache__/test_generator.cpython-314-pytest-9.0.2.pyc +0 -0
- package/skills/skills/skillkit/scripts/decision_helper.py +799 -0
- package/skills/skills/skillkit/scripts/init_skill.py +400 -0
- package/skills/skills/skillkit/scripts/init_subagent.py +231 -0
- package/skills/skills/skillkit/scripts/migration_helper.py +669 -0
- package/skills/skills/skillkit/scripts/package_skill.py +211 -0
- package/skills/skills/skillkit/scripts/pattern_detector.py +381 -0
- package/skills/skills/skillkit/scripts/pattern_detector_new.py +382 -0
- package/skills/skills/skillkit/scripts/pressure_tester.py +157 -0
- package/skills/skills/skillkit/scripts/quality_scorer.py +999 -0
- package/skills/skills/skillkit/scripts/quick_validate.py +100 -0
- package/skills/skills/skillkit/scripts/security_scanner.py +474 -0
- package/skills/skills/skillkit/scripts/split_skill.py +540 -0
- package/skills/skills/skillkit/scripts/test_generator.py +695 -0
- package/skills/skills/skillkit/scripts/token_estimator.py +493 -0
- package/skills/skills/skillkit/scripts/utils/__init__.py +49 -0
- package/skills/skills/skillkit/scripts/utils/__pycache__/__init__.cpython-312.pyc +0 -0
- package/skills/skills/skillkit/scripts/utils/__pycache__/__init__.cpython-314.pyc +0 -0
- package/skills/skills/skillkit/scripts/utils/__pycache__/budget_tracker.cpython-312.pyc +0 -0
- package/skills/skills/skillkit/scripts/utils/__pycache__/budget_tracker.cpython-314.pyc +0 -0
- package/skills/skills/skillkit/scripts/utils/__pycache__/output_formatter.cpython-312.pyc +0 -0
- package/skills/skills/skillkit/scripts/utils/__pycache__/output_formatter.cpython-314.pyc +0 -0
- package/skills/skills/skillkit/scripts/utils/__pycache__/reference_validator.cpython-312.pyc +0 -0
- package/skills/skills/skillkit/scripts/utils/__pycache__/reference_validator.cpython-314.pyc +0 -0
- package/skills/skills/skillkit/scripts/utils/budget_tracker.py +388 -0
- package/skills/skills/skillkit/scripts/utils/output_formatter.py +263 -0
- package/skills/skills/skillkit/scripts/utils/reference_validator.py +401 -0
- package/skills/skills/skillkit/scripts/validate_skill.py +594 -0
- package/skills/skills/skillkit/tests/test_behavioral.py +39 -0
- package/skills/skills/skillkit/tests/test_scenarios.md +83 -0
- package/skills/skills/skillkit/tests/test_skill.py +136 -0
- package/skills/skills/skillkit-help/SKILL.md +81 -0
- package/skills/skills/skillkit-help/knowledge/application/09-case-studies.md +257 -0
- package/skills/skills/skillkit-help/knowledge/application/12-testing-and-validation.md +276 -0
- package/skills/skills/skillkit-help/knowledge/foundation/01-why-skills-exist.md +246 -0
- package/skills/skills/skillkit-help/knowledge/foundation/02-skills-vs-subagents-comparison.md +312 -0
- package/skills/skills/skillkit-help/knowledge/foundation/03-skills-vs-subagents-decision-tree.md +346 -0
- package/skills/skills/skillkit-help/knowledge/foundation/06-platform-constraints.md +237 -0
- package/skills/skills/skillkit-help/knowledge/foundation/08-when-not-to-use-skills.md +270 -0
- package/skills/skills/skillkit-help/template/SKILL.md +52 -0
- package/skills/skills/social-media-seo/SKILL.md +278 -0
- package/skills/skills/social-media-seo/databases/caption-styles.csv +31 -0
- package/skills/skills/social-media-seo/databases/engagement-tactics.csv +16 -0
- package/skills/skills/social-media-seo/databases/hashtag-strategies.csv +21 -0
- package/skills/skills/social-media-seo/databases/hook-formulas.csv +26 -0
- package/skills/skills/social-media-seo/databases/keyword-clusters.csv +11 -0
- package/skills/skills/social-media-seo/databases/thread-structures.csv +26 -0
- package/skills/skills/social-media-seo/databases/viral-patterns.csv +21 -0
- package/skills/skills/social-media-seo/references/analytics-guide.md +321 -0
- package/skills/skills/social-media-seo/references/instagram-seo.md +235 -0
- package/skills/skills/social-media-seo/references/threads-seo.md +305 -0
- package/skills/skills/social-media-seo/references/x-twitter-seo.md +337 -0
- package/skills/skills/social-media-seo/scripts/query_database.py +191 -0
- package/skills/skills/storyteller/SKILL.md +241 -0
- package/skills/skills/storyteller/references/transformation-methodology.md +293 -0
- package/skills/skills/storyteller/references/visual-vocabulary.md +177 -0
- package/skills/skills/thread-pro/SKILL.md +162 -0
- package/skills/skills/thread-pro/anti-ai-patterns.md +120 -0
- package/skills/skills/thread-pro/hook-formulas.md +138 -0
- package/skills/skills/thread-pro/references/anti-ai-patterns.md +120 -0
- package/skills/skills/thread-pro/references/hook-formulas.md +138 -0
- package/skills/skills/thread-pro/references/thread-structures.md +240 -0
- package/skills/skills/thread-pro/references/voice-injection.md +130 -0
- package/skills/skills/thread-pro/thread-structures.md +240 -0
- package/skills/skills/thread-pro/voice-injection.md +130 -0
- package/skills/skills/tinkering/SKILL.md +251 -0
- package/skills/skills/tinkering/references/graduation-checklist.md +100 -0
- package/skills/skills/validate-plan/.skillkit-mode +1 -0
- package/skills/skills/validate-plan/SKILL.md +406 -0
- package/skills/skills/validate-plan/references/dry-principles.md +251 -0
- package/skills/skills/validate-plan/references/gap-analysis-guide.md +320 -0
- package/skills/skills/validate-plan/references/tdd-patterns.md +413 -0
- package/skills/skills/validate-plan/references/yagni-checklist.md +330 -0
- package/skills/skills/verify-before-ship/.skillkit-mode +1 -0
- package/skills/skills/verify-before-ship/SKILL.md +116 -0
- package/skills/skills/verify-before-ship/references/anti-rationalization.md +212 -0
- package/skills/skills/verify-before-ship/references/verification-gates.md +305 -0
- package/skills-manifest.json +8 -2
- package/src/banner.js +1 -1
- package/src/cli.js +15 -4
- package/src/install.js +45 -29
- package/src/install.test.js +75 -7
- package/src/picker.js +15 -4
- package/src/picker.test.js +36 -1
- package/src/scope.js +8 -39
- package/src/scope.test.js +9 -13
- package/src/tools.js +76 -0
- package/src/tools.test.js +80 -0
|
@@ -0,0 +1,799 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Decision helper for Skills vs Subagents - AGENT-LAYER TOOL.
|
|
4
|
+
Called by Claude to provide instant recommendations based on use case analysis.
|
|
5
|
+
|
|
6
|
+
This script implements the 8-question decision tree from Files 02-03 and returns
|
|
7
|
+
structured JSON output for Claude to parse and explain to users.
|
|
8
|
+
|
|
9
|
+
Usage by Claude:
|
|
10
|
+
# Mode 1: Pre-answered questions (preferred)
|
|
11
|
+
python decision_helper.py --answers /tmp/answers.json [--format json]
|
|
12
|
+
|
|
13
|
+
# Mode 2: Keyword-based analysis (fallback)
|
|
14
|
+
python decision_helper.py --analyze "code review with validation" [--format json]
|
|
15
|
+
|
|
16
|
+
# Mode 3: Show decision criteria (reference)
|
|
17
|
+
python decision_helper.py --show-criteria [--format json]
|
|
18
|
+
|
|
19
|
+
References:
|
|
20
|
+
- File 02: Skills vs Subagents conceptual differences
|
|
21
|
+
- File 03: Decision tree logic and scoring
|
|
22
|
+
- File 05: Token economics analysis
|
|
23
|
+
|
|
24
|
+
Author: Claude Skills Research Project
|
|
25
|
+
Version: 1.1 (Agent-Layer with text mode support)
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
import json
|
|
29
|
+
import sys
|
|
30
|
+
import argparse
|
|
31
|
+
from typing import Dict, List, Optional
|
|
32
|
+
from pathlib import Path
|
|
33
|
+
import re
|
|
34
|
+
|
|
35
|
+
# Import shared utilities for standardized output
|
|
36
|
+
try:
|
|
37
|
+
from utils.output_formatter import add_format_argument
|
|
38
|
+
except ImportError:
|
|
39
|
+
# Fallback if utils not in path
|
|
40
|
+
sys.path.insert(0, str(Path(__file__).parent))
|
|
41
|
+
from utils.output_formatter import add_format_argument
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class DecisionHelper:
|
|
45
|
+
"""
|
|
46
|
+
Agent-layer decision helper for Skills vs Subagents.
|
|
47
|
+
|
|
48
|
+
Designed to be called by Claude via bash_tool, not by humans directly.
|
|
49
|
+
All input/output is JSON for programmatic parsing.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
# Configuration constants
|
|
53
|
+
MAX_UNCERTAIN_THRESHOLD = 4 # Max uncertain answers before returning "Need Explicit Answers"
|
|
54
|
+
CONFIDENCE_PENALTY_PER_UNCERTAIN = 0.15 # Penalty multiplier for each uncertain answer
|
|
55
|
+
MIN_CONFIDENCE_MULTIPLIER = 0.5 # Minimum confidence after penalties
|
|
56
|
+
|
|
57
|
+
# Token cost estimates (based on File 05 research)
|
|
58
|
+
TYPICAL_SKILL_TOKENS = 500 # Typical skill invocation cost
|
|
59
|
+
COMPLEX_SUBAGENT_TOKENS = 7500 # Complex subagent workflow cost
|
|
60
|
+
TOKEN_MULTIPLIER_SKILL_TO_SUBAGENT = 15 # Multiplier from Skill to Subagent
|
|
61
|
+
|
|
62
|
+
# Confidence calculation constants
|
|
63
|
+
CONFIDENCE_BASE_STRONG = 0.90 # Base confidence for strong recommendations (±6 to ±8)
|
|
64
|
+
CONFIDENCE_BASE_MODERATE = 0.75 # Base confidence for moderate recommendations (±3 to ±5)
|
|
65
|
+
CONFIDENCE_BASE_HYBRID = 0.60 # Base confidence for hybrid zone (-1 to +2)
|
|
66
|
+
CONFIDENCE_INCREMENT = 0.025 # Symmetric increment for all ranges
|
|
67
|
+
|
|
68
|
+
def __init__(self):
|
|
69
|
+
"""Initialize decision helper with question definitions."""
|
|
70
|
+
self.answers: Dict[str, bool] = {}
|
|
71
|
+
self.score: int = 0
|
|
72
|
+
self.reasoning: List[str] = []
|
|
73
|
+
self.questions = self._define_questions()
|
|
74
|
+
|
|
75
|
+
def _define_questions(self) -> Dict:
|
|
76
|
+
"""
|
|
77
|
+
Define 8 decision questions with keywords for inference.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Dict mapping question IDs to question data
|
|
81
|
+
|
|
82
|
+
References: File 03 (decision tree questions)
|
|
83
|
+
"""
|
|
84
|
+
return {
|
|
85
|
+
"utility_task": {
|
|
86
|
+
"question": "Is it a utility/conversion/template task?",
|
|
87
|
+
"examples": [
|
|
88
|
+
"Format conversion (JSON to CSV)",
|
|
89
|
+
"Data extraction from documents",
|
|
90
|
+
"Template application"
|
|
91
|
+
],
|
|
92
|
+
"skill_keywords": [
|
|
93
|
+
"convert", "transform", "template", "format",
|
|
94
|
+
"extract", "parse", "utility", "validation"
|
|
95
|
+
],
|
|
96
|
+
"score_if_yes": +1,
|
|
97
|
+
"score_if_no": -1
|
|
98
|
+
},
|
|
99
|
+
"multi_step": {
|
|
100
|
+
"question": "Does it need multiple steps of reasoning?",
|
|
101
|
+
"examples": [
|
|
102
|
+
"Code review with validation loops",
|
|
103
|
+
"Data analysis with hypothesis testing",
|
|
104
|
+
"Iterative refinement processes"
|
|
105
|
+
],
|
|
106
|
+
"subagent_keywords": [
|
|
107
|
+
"review", "analyze", "validate", "iterate",
|
|
108
|
+
"hypothesis", "decision", "multiple", "steps",
|
|
109
|
+
"refinement", "exploration"
|
|
110
|
+
],
|
|
111
|
+
"score_if_yes": -1,
|
|
112
|
+
"score_if_no": +1
|
|
113
|
+
},
|
|
114
|
+
"reusable": {
|
|
115
|
+
"question": "Will it be reused as building block?",
|
|
116
|
+
"examples": [
|
|
117
|
+
"Document converter used by multiple workflows",
|
|
118
|
+
"Data parser for common formats",
|
|
119
|
+
"Shared utility function"
|
|
120
|
+
],
|
|
121
|
+
"skill_keywords": [
|
|
122
|
+
"reusable", "utility", "helper", "common",
|
|
123
|
+
"shared", "library", "building block"
|
|
124
|
+
],
|
|
125
|
+
"score_if_yes": +1,
|
|
126
|
+
"score_if_no": -1
|
|
127
|
+
},
|
|
128
|
+
"specialized_personality": {
|
|
129
|
+
"question": "Does it need specialized personality?",
|
|
130
|
+
"examples": [
|
|
131
|
+
"Security auditor with paranoid perspective",
|
|
132
|
+
"Code reviewer with strict standards",
|
|
133
|
+
"Domain expert with specific tone"
|
|
134
|
+
],
|
|
135
|
+
"subagent_keywords": [
|
|
136
|
+
"personality", "persona", "role", "expert",
|
|
137
|
+
"specialized", "tone", "perspective", "auditor"
|
|
138
|
+
],
|
|
139
|
+
"score_if_yes": -1,
|
|
140
|
+
"score_if_no": +1
|
|
141
|
+
},
|
|
142
|
+
"missing_knowledge": {
|
|
143
|
+
"question": "Is it knowledge Claude doesn't have?",
|
|
144
|
+
"examples": [
|
|
145
|
+
"Company-specific procedures",
|
|
146
|
+
"Proprietary methodologies",
|
|
147
|
+
"Organizational standards"
|
|
148
|
+
],
|
|
149
|
+
"skill_keywords": [
|
|
150
|
+
"company", "proprietary", "organizational",
|
|
151
|
+
"internal", "procedure", "standard", "policy"
|
|
152
|
+
],
|
|
153
|
+
"score_if_yes": +1,
|
|
154
|
+
"score_if_no": 0 # Neutral if Claude knows it
|
|
155
|
+
},
|
|
156
|
+
"coordination": {
|
|
157
|
+
"question": "Does it coordinate operations with decision points?",
|
|
158
|
+
"examples": [
|
|
159
|
+
"Multi-stage validation with branching",
|
|
160
|
+
"Orchestration with conditional logic",
|
|
161
|
+
"Workflow coordination"
|
|
162
|
+
],
|
|
163
|
+
"subagent_keywords": [
|
|
164
|
+
"coordinate", "orchestrate", "workflow", "pipeline",
|
|
165
|
+
"branching", "conditional", "decision points"
|
|
166
|
+
],
|
|
167
|
+
"score_if_yes": -1,
|
|
168
|
+
"score_if_no": +1
|
|
169
|
+
},
|
|
170
|
+
"isolated_context": {
|
|
171
|
+
"question": "Does it need isolated context?",
|
|
172
|
+
"examples": [
|
|
173
|
+
"Long debugging session",
|
|
174
|
+
"Extensive exploration",
|
|
175
|
+
"Separate conversation thread"
|
|
176
|
+
],
|
|
177
|
+
"subagent_keywords": [
|
|
178
|
+
"isolated", "separate", "context", "independent",
|
|
179
|
+
"debugging", "exploration", "extensive"
|
|
180
|
+
],
|
|
181
|
+
"score_if_yes": -1,
|
|
182
|
+
"score_if_no": +1
|
|
183
|
+
},
|
|
184
|
+
"clutter_chat": {
|
|
185
|
+
"question": "Would it clutter main chat with intermediate steps?",
|
|
186
|
+
"examples": [
|
|
187
|
+
"Security scan with 50+ findings",
|
|
188
|
+
"Comprehensive code analysis",
|
|
189
|
+
"Verbose intermediate output"
|
|
190
|
+
],
|
|
191
|
+
"subagent_keywords": [
|
|
192
|
+
"verbose", "detailed", "comprehensive", "extensive",
|
|
193
|
+
"many", "multiple outputs", "clutter"
|
|
194
|
+
],
|
|
195
|
+
"score_if_yes": -1,
|
|
196
|
+
"score_if_no": +1
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
def analyze_from_answers(
|
|
201
|
+
self,
|
|
202
|
+
answers: Dict[str, bool],
|
|
203
|
+
skip_questions: List[str] = None,
|
|
204
|
+
mode: str = "fast",
|
|
205
|
+
) -> Dict:
|
|
206
|
+
"""
|
|
207
|
+
Analyze use case from pre-provided answers.
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
answers: Dict with Q1-Q8 answers as boolean values
|
|
211
|
+
skip_questions: List of question IDs to skip (for uncertain inferred answers)
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
Dict with status, recommendation, score, confidence, reasoning
|
|
215
|
+
|
|
216
|
+
This is the PRIMARY mode when Claude has extracted clear answers.
|
|
217
|
+
"""
|
|
218
|
+
if skip_questions is None:
|
|
219
|
+
skip_questions = []
|
|
220
|
+
|
|
221
|
+
# Validate input comprehensively
|
|
222
|
+
required_keys = set(self.questions.keys())
|
|
223
|
+
provided_keys = set(answers.keys())
|
|
224
|
+
|
|
225
|
+
# Check for missing keys
|
|
226
|
+
missing = required_keys - provided_keys
|
|
227
|
+
if missing:
|
|
228
|
+
return {
|
|
229
|
+
"status": "error",
|
|
230
|
+
"error_type": "InvalidInput",
|
|
231
|
+
"message": f"Missing required answers: {', '.join(sorted(missing))}",
|
|
232
|
+
"help": "Provide complete answers for all 8 questions",
|
|
233
|
+
"required_keys": sorted(list(required_keys))
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
# Check for extra/unexpected keys (typos detection)
|
|
237
|
+
extra = provided_keys - required_keys
|
|
238
|
+
if extra:
|
|
239
|
+
return {
|
|
240
|
+
"status": "error",
|
|
241
|
+
"error_type": "UnexpectedKeys",
|
|
242
|
+
"message": f"Unexpected question IDs (possible typos): {', '.join(sorted(extra))}",
|
|
243
|
+
"help": f"Valid question IDs are: {', '.join(sorted(list(required_keys)))}",
|
|
244
|
+
"expected_keys": sorted(list(required_keys)),
|
|
245
|
+
"received_keys": sorted(list(provided_keys))
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
# Validate types
|
|
249
|
+
invalid_types = []
|
|
250
|
+
for key, value in answers.items():
|
|
251
|
+
if not isinstance(value, bool):
|
|
252
|
+
invalid_types.append(f"{key}={type(value).__name__}")
|
|
253
|
+
|
|
254
|
+
if invalid_types:
|
|
255
|
+
return {
|
|
256
|
+
"status": "error",
|
|
257
|
+
"error_type": "InvalidType",
|
|
258
|
+
"message": f"All answers must be boolean: {', '.join(invalid_types)}",
|
|
259
|
+
"help": "Use true/false for all answer values"
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
# Store answers and calculate scores (passing skip_questions)
|
|
263
|
+
self.answers = answers
|
|
264
|
+
self._calculate_scores(skip_questions=skip_questions)
|
|
265
|
+
|
|
266
|
+
return self._build_recommendation(mode=mode)
|
|
267
|
+
|
|
268
|
+
def analyze_from_description(self, description: str, mode: str = "fast") -> Dict:
|
|
269
|
+
"""
|
|
270
|
+
Infer answers from natural language description.
|
|
271
|
+
|
|
272
|
+
Args:
|
|
273
|
+
description: User's use case description
|
|
274
|
+
|
|
275
|
+
Returns:
|
|
276
|
+
Dict with recommendation + inference metadata
|
|
277
|
+
|
|
278
|
+
FALLBACK mode when Claude doesn't have clear answers.
|
|
279
|
+
Lower confidence due to inference.
|
|
280
|
+
"""
|
|
281
|
+
if not description or len(description.strip()) < 3:
|
|
282
|
+
return {
|
|
283
|
+
"status": "error",
|
|
284
|
+
"error_type": "InvalidInput",
|
|
285
|
+
"message": "Description too short or empty",
|
|
286
|
+
"help": "Provide detailed use case description (at least 3 characters)"
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
# Infer answers from keywords
|
|
290
|
+
inference_result = self._infer_answers_from_keywords(description)
|
|
291
|
+
answers = inference_result['answers']
|
|
292
|
+
|
|
293
|
+
# Count inference quality
|
|
294
|
+
certain_count = sum(1 for v in answers.values() if v is not None)
|
|
295
|
+
uncertain_count = sum(1 for v in answers.values() if v is None)
|
|
296
|
+
|
|
297
|
+
# If too many uncertain answers, return warning
|
|
298
|
+
if uncertain_count >= self.MAX_UNCERTAIN_THRESHOLD:
|
|
299
|
+
mode_note = (
|
|
300
|
+
"Full mode includes pressure testing"
|
|
301
|
+
if mode == "full"
|
|
302
|
+
else "Use --mode full for TDD behavioral validation"
|
|
303
|
+
)
|
|
304
|
+
return {
|
|
305
|
+
"status": "success",
|
|
306
|
+
"recommendation": "Uncertain - Need Explicit Answers",
|
|
307
|
+
"score": None,
|
|
308
|
+
"confidence": 0.5,
|
|
309
|
+
"workflow_mode": mode,
|
|
310
|
+
"mode_note": mode_note,
|
|
311
|
+
"mode_reasoning": mode_note,
|
|
312
|
+
"reasoning": ["Too many questions could not be inferred from description"],
|
|
313
|
+
"inference_mode": True,
|
|
314
|
+
"inference_warning": f"Only {certain_count}/8 questions answered from keywords. {uncertain_count} questions uncertain.",
|
|
315
|
+
"detected_keywords": inference_result['detected'],
|
|
316
|
+
"inference_methods": inference_result.get('inference_methods', {}),
|
|
317
|
+
"suggestion": "Use --answers mode with explicit true/false for all 8 questions"
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
# Mark uncertain answers for special handling in scoring
|
|
321
|
+
# Store which answers are uncertain to skip them in score calculation
|
|
322
|
+
uncertain_questions = [q_id for q_id, val in answers.items() if val is None]
|
|
323
|
+
|
|
324
|
+
# Convert None to False only for validation purposes
|
|
325
|
+
# These will be skipped during actual scoring to maintain neutrality
|
|
326
|
+
for q_id in answers:
|
|
327
|
+
if answers[q_id] is None:
|
|
328
|
+
answers[q_id] = False # Placeholder only, won't affect score
|
|
329
|
+
|
|
330
|
+
# Analyze with inferred answers (passing uncertain_questions list)
|
|
331
|
+
result = self.analyze_from_answers(answers, skip_questions=uncertain_questions, mode=mode)
|
|
332
|
+
|
|
333
|
+
if result['status'] == 'success':
|
|
334
|
+
# Add inference metadata
|
|
335
|
+
result['inference_mode'] = True
|
|
336
|
+
result['certain_answers'] = certain_count
|
|
337
|
+
result['uncertain_answers'] = uncertain_count
|
|
338
|
+
result['detected_keywords'] = inference_result['detected']
|
|
339
|
+
result['inference_methods'] = inference_result.get('inference_methods', {})
|
|
340
|
+
|
|
341
|
+
# Dynamic confidence penalty based on uncertainty
|
|
342
|
+
# Each uncertain answer reduces confidence more
|
|
343
|
+
base_confidence = result['confidence']
|
|
344
|
+
penalty_per_uncertain = self.CONFIDENCE_PENALTY_PER_UNCERTAIN
|
|
345
|
+
confidence_multiplier = max(self.MIN_CONFIDENCE_MULTIPLIER, 1.0 - (uncertain_count * penalty_per_uncertain))
|
|
346
|
+
result['confidence'] = round(base_confidence * confidence_multiplier, 2)
|
|
347
|
+
|
|
348
|
+
if uncertain_count > 0:
|
|
349
|
+
result['inference_note'] = f"{certain_count}/8 answers certain, {uncertain_count}/8 inferred. Confidence adjusted."
|
|
350
|
+
else:
|
|
351
|
+
result['inference_note'] = "All answers inferred from keywords with strong signal."
|
|
352
|
+
|
|
353
|
+
return result
|
|
354
|
+
|
|
355
|
+
def show_criteria(self) -> Dict:
|
|
356
|
+
"""
|
|
357
|
+
Return decision criteria for Claude's reference.
|
|
358
|
+
|
|
359
|
+
Used when Claude needs to explain the decision framework to users.
|
|
360
|
+
|
|
361
|
+
Returns:
|
|
362
|
+
Dict with all questions and score interpretation table
|
|
363
|
+
"""
|
|
364
|
+
criteria = {}
|
|
365
|
+
for q_id, q_data in self.questions.items():
|
|
366
|
+
criteria[q_id] = {
|
|
367
|
+
"question": q_data["question"],
|
|
368
|
+
"examples": q_data["examples"],
|
|
369
|
+
"scoring": {
|
|
370
|
+
"yes": q_data["score_if_yes"],
|
|
371
|
+
"no": q_data["score_if_no"]
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return {
|
|
376
|
+
"status": "success",
|
|
377
|
+
"criteria": criteria,
|
|
378
|
+
"score_interpretation": {
|
|
379
|
+
"+6 to +8": {
|
|
380
|
+
"recommendation": "Strong Skill",
|
|
381
|
+
"confidence": "90-95%",
|
|
382
|
+
"characteristics": "Utility functions, procedures, templates",
|
|
383
|
+
"token_overhead": "30-50 tokens"
|
|
384
|
+
},
|
|
385
|
+
"+3 to +5": {
|
|
386
|
+
"recommendation": "Moderate Skill",
|
|
387
|
+
"confidence": "75-85%",
|
|
388
|
+
"characteristics": "Mostly procedural with some logic",
|
|
389
|
+
"token_overhead": "Low overhead"
|
|
390
|
+
},
|
|
391
|
+
"-1 to +2": {
|
|
392
|
+
"recommendation": "Hybrid Approach",
|
|
393
|
+
"confidence": "60-70%",
|
|
394
|
+
"characteristics": "Mix of utility and orchestration",
|
|
395
|
+
"token_overhead": "Optimized balance"
|
|
396
|
+
},
|
|
397
|
+
"-3 to -5": {
|
|
398
|
+
"recommendation": "Moderate Subagent",
|
|
399
|
+
"confidence": "75-85%",
|
|
400
|
+
"characteristics": "Multi-step workflows with some complexity",
|
|
401
|
+
"token_overhead": "15Ćā multiplier"
|
|
402
|
+
},
|
|
403
|
+
"-6 to -8": {
|
|
404
|
+
"recommendation": "Strong Subagent",
|
|
405
|
+
"confidence": "90-95%",
|
|
406
|
+
"characteristics": "Complex workflows, specialized expertise",
|
|
407
|
+
"token_overhead": "High (justified by complexity)"
|
|
408
|
+
}
|
|
409
|
+
},
|
|
410
|
+
"references": {
|
|
411
|
+
"conceptual": "File 02: Skills vs Subagents comparison",
|
|
412
|
+
"decision_tree": "File 03: Complete decision tree details",
|
|
413
|
+
"costs": "File 05: Token economics analysis"
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
def _calculate_scores(self, skip_questions: List[str] = None):
|
|
418
|
+
"""
|
|
419
|
+
Calculate score based on answers.
|
|
420
|
+
|
|
421
|
+
Score range: -8 (Strong Subagent) to +8 (Strong Skill)
|
|
422
|
+
Uses exact logic from File 03.
|
|
423
|
+
"""
|
|
424
|
+
if skip_questions is None:
|
|
425
|
+
skip_questions = []
|
|
426
|
+
|
|
427
|
+
self.score = 0
|
|
428
|
+
self.reasoning = []
|
|
429
|
+
|
|
430
|
+
for q_id, q_data in self.questions.items():
|
|
431
|
+
# Skip uncertain questions to maintain true neutrality
|
|
432
|
+
if q_id in skip_questions:
|
|
433
|
+
self.reasoning.append(
|
|
434
|
+
f"{q_data['question']} ā UNCERTAIN (skipped, 0 impact)"
|
|
435
|
+
)
|
|
436
|
+
continue
|
|
437
|
+
|
|
438
|
+
answer = self.answers[q_id]
|
|
439
|
+
|
|
440
|
+
if answer:
|
|
441
|
+
# YES answer
|
|
442
|
+
score_change = q_data["score_if_yes"]
|
|
443
|
+
direction = "favors Skill" if score_change > 0 else "favors Subagent"
|
|
444
|
+
self.reasoning.append(
|
|
445
|
+
f"{q_data['question']} Ć¢ā ā YES ({direction})"
|
|
446
|
+
)
|
|
447
|
+
else:
|
|
448
|
+
# NO answer
|
|
449
|
+
score_change = q_data["score_if_no"]
|
|
450
|
+
if score_change != 0:
|
|
451
|
+
direction = "favors Skill" if score_change > 0 else "favors Subagent"
|
|
452
|
+
self.reasoning.append(
|
|
453
|
+
f"{q_data['question']} Ć¢ā ā NO ({direction})"
|
|
454
|
+
)
|
|
455
|
+
else:
|
|
456
|
+
self.reasoning.append(
|
|
457
|
+
f"{q_data['question']} Ć¢ā ā NO (neutral)"
|
|
458
|
+
)
|
|
459
|
+
|
|
460
|
+
self.score += score_change
|
|
461
|
+
|
|
462
|
+
def _build_recommendation(self, mode: str = "fast") -> Dict:
|
|
463
|
+
"""
|
|
464
|
+
Generate final recommendation with confidence.
|
|
465
|
+
|
|
466
|
+
Returns:
|
|
467
|
+
Structured JSON for Claude to parse and explain
|
|
468
|
+
"""
|
|
469
|
+
# Interpret score (exact File 03 logic)
|
|
470
|
+
if self.score >= 6:
|
|
471
|
+
recommendation = "Strong Skill"
|
|
472
|
+
confidence = 0.90 + (self.score - 6) * 0.025 # 90-95%
|
|
473
|
+
elif self.score >= 3:
|
|
474
|
+
recommendation = "Moderate Skill"
|
|
475
|
+
confidence = 0.75 + (self.score - 3) * 0.025 # 75-85%
|
|
476
|
+
elif self.score >= -1:
|
|
477
|
+
recommendation = "Hybrid Approach"
|
|
478
|
+
confidence = 0.60 + (self.score + 1) * 0.025 # 60-70%
|
|
479
|
+
elif self.score >= -5:
|
|
480
|
+
recommendation = "Moderate Subagent"
|
|
481
|
+
confidence = 0.75 + (abs(self.score) - 3) * 0.025 # 75-85%
|
|
482
|
+
else:
|
|
483
|
+
recommendation = "Strong Subagent"
|
|
484
|
+
confidence = 0.90 + (abs(self.score) - 6) * 0.025 # 90-95%
|
|
485
|
+
|
|
486
|
+
mode_note = (
|
|
487
|
+
"Full mode includes pressure testing"
|
|
488
|
+
if mode == "full"
|
|
489
|
+
else "Use --mode full for TDD behavioral validation"
|
|
490
|
+
)
|
|
491
|
+
|
|
492
|
+
return {
|
|
493
|
+
"status": "success",
|
|
494
|
+
"recommendation": recommendation,
|
|
495
|
+
"score": self.score,
|
|
496
|
+
"confidence": round(confidence, 2),
|
|
497
|
+
"workflow_mode": mode,
|
|
498
|
+
"mode_note": mode_note,
|
|
499
|
+
"mode_reasoning": mode_note,
|
|
500
|
+
"reasoning": self.reasoning,
|
|
501
|
+
"token_analysis": self._calculate_token_impact(),
|
|
502
|
+
"pattern_suggestions": self._generate_pattern_suggestions(),
|
|
503
|
+
"references": {
|
|
504
|
+
"conceptual": "File 02: Skills vs Subagents comparison",
|
|
505
|
+
"decision_tree": "File 03: Complete decision tree",
|
|
506
|
+
"costs": "File 05: Token economics"
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
def _calculate_token_impact(self) -> Dict:
|
|
511
|
+
"""
|
|
512
|
+
Calculate estimated token costs for each approach.
|
|
513
|
+
|
|
514
|
+
Based on File 05 research findings:
|
|
515
|
+
- Skills: ~50 token overhead (progressive disclosure)
|
|
516
|
+
- Subagents: 15Ćā multiplier vs Skills
|
|
517
|
+
|
|
518
|
+
Returns:
|
|
519
|
+
Dict with token cost estimates and recommendations
|
|
520
|
+
"""
|
|
521
|
+
# Base estimates from File 05
|
|
522
|
+
if self.score >= 3:
|
|
523
|
+
# Skill-leaning recommendation
|
|
524
|
+
skill_cost = self.TYPICAL_SKILL_TOKENS
|
|
525
|
+
subagent_cost = skill_cost * self.TOKEN_MULTIPLIER_SKILL_TO_SUBAGENT
|
|
526
|
+
note = "Skill approach significantly more token-efficient"
|
|
527
|
+
elif self.score <= -3:
|
|
528
|
+
# Subagent-leaning recommendation
|
|
529
|
+
subagent_cost = self.COMPLEX_SUBAGENT_TOKENS
|
|
530
|
+
skill_cost = subagent_cost // self.TOKEN_MULTIPLIER_SKILL_TO_SUBAGENT
|
|
531
|
+
note = "High token cost justified for complex workflows"
|
|
532
|
+
else:
|
|
533
|
+
# Hybrid zone
|
|
534
|
+
skill_cost = self.TYPICAL_SKILL_TOKENS
|
|
535
|
+
subagent_cost = self.COMPLEX_SUBAGENT_TOKENS
|
|
536
|
+
note = "Consider hybrid: balance efficiency and capability"
|
|
537
|
+
|
|
538
|
+
return {
|
|
539
|
+
"skill_approach_tokens": skill_cost,
|
|
540
|
+
"subagent_approach_tokens": subagent_cost,
|
|
541
|
+
"cost_multiplier": round(subagent_cost / skill_cost, 1),
|
|
542
|
+
"recommendation_note": note
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
def _generate_pattern_suggestions(self) -> List[str]:
|
|
546
|
+
"""
|
|
547
|
+
Generate actionable pattern suggestions.
|
|
548
|
+
|
|
549
|
+
Based on File 04 (Hybrid Patterns) and score interpretation.
|
|
550
|
+
|
|
551
|
+
Returns:
|
|
552
|
+
List of actionable next-step suggestions
|
|
553
|
+
"""
|
|
554
|
+
suggestions = []
|
|
555
|
+
|
|
556
|
+
if self.score >= 6:
|
|
557
|
+
# Strong Skill
|
|
558
|
+
suggestions.append("Implement as pure Skill")
|
|
559
|
+
suggestions.append("Focus on clear YAML description for auto-discovery")
|
|
560
|
+
suggestions.append("Keep SKILL.md under 500 lines for efficiency")
|
|
561
|
+
|
|
562
|
+
elif self.score >= 3:
|
|
563
|
+
# Moderate Skill
|
|
564
|
+
suggestions.append("Implement as Skill")
|
|
565
|
+
suggestions.append("Consider extracting complex logic to scripts/")
|
|
566
|
+
suggestions.append("Use progressive disclosure for larger content")
|
|
567
|
+
|
|
568
|
+
elif -1 <= self.score <= 2:
|
|
569
|
+
# Hybrid Zone
|
|
570
|
+
suggestions.append("Consider Hybrid: Subagent orchestration + Skill utilities")
|
|
571
|
+
suggestions.append("Extract reusable parts to Skills")
|
|
572
|
+
suggestions.append("Use Subagent for main workflow coordination")
|
|
573
|
+
suggestions.append("See File 04 for hybrid pattern examples")
|
|
574
|
+
|
|
575
|
+
elif self.score >= -5:
|
|
576
|
+
# Moderate Subagent
|
|
577
|
+
suggestions.append("Implement as Subagent")
|
|
578
|
+
suggestions.append("Consider if any utilities can become Skills")
|
|
579
|
+
suggestions.append("Use isolated context for clean reasoning")
|
|
580
|
+
|
|
581
|
+
else:
|
|
582
|
+
# Strong Subagent
|
|
583
|
+
suggestions.append("Implement as Subagent")
|
|
584
|
+
suggestions.append("Full isolated context and specialized personality needed")
|
|
585
|
+
suggestions.append("High token cost justified by complexity and value")
|
|
586
|
+
|
|
587
|
+
return suggestions
|
|
588
|
+
|
|
589
|
+
def _infer_answers_from_keywords(self, text: str) -> Dict:
|
|
590
|
+
"""
|
|
591
|
+
Keyword-based answer inference from description.
|
|
592
|
+
|
|
593
|
+
Args:
|
|
594
|
+
text: Natural language use case description
|
|
595
|
+
|
|
596
|
+
Returns:
|
|
597
|
+
Dict with inferred answers and detected keywords
|
|
598
|
+
"""
|
|
599
|
+
text_lower = text.lower()
|
|
600
|
+
|
|
601
|
+
def match_keyword(keyword: str, text: str) -> bool:
|
|
602
|
+
"""Match keyword using word boundaries to avoid false positives."""
|
|
603
|
+
# Use word boundary regex: keyword
|
|
604
|
+
pattern = r'\b' + re.escape(keyword) + r'\b'
|
|
605
|
+
return bool(re.search(pattern, text, re.IGNORECASE))
|
|
606
|
+
detected = {}
|
|
607
|
+
inferred_answers = {}
|
|
608
|
+
inference_methods = {}
|
|
609
|
+
|
|
610
|
+
for q_id, q_data in self.questions.items():
|
|
611
|
+
# Check for skill-favoring keywords
|
|
612
|
+
skill_keywords = q_data.get("skill_keywords", [])
|
|
613
|
+
skill_matches = [k for k in skill_keywords if match_keyword(k, text_lower)]
|
|
614
|
+
|
|
615
|
+
# Check for subagent-favoring keywords
|
|
616
|
+
subagent_keywords = q_data.get("subagent_keywords", [])
|
|
617
|
+
subagent_matches = [k for k in subagent_keywords if match_keyword(k, text_lower)]
|
|
618
|
+
|
|
619
|
+
detected[q_id] = {
|
|
620
|
+
"skill_keywords": skill_matches,
|
|
621
|
+
"subagent_keywords": subagent_matches
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
# Infer answer based on keyword presence
|
|
625
|
+
if skill_matches and not subagent_matches:
|
|
626
|
+
inferred_answers[q_id] = True
|
|
627
|
+
inference_methods[q_id] = "skill_keywords"
|
|
628
|
+
elif subagent_matches and not skill_matches:
|
|
629
|
+
inferred_answers[q_id] = False
|
|
630
|
+
inference_methods[q_id] = "subagent_keywords"
|
|
631
|
+
elif len(skill_matches) > len(subagent_matches):
|
|
632
|
+
inferred_answers[q_id] = True
|
|
633
|
+
inference_methods[q_id] = "skill_keywords_majority"
|
|
634
|
+
elif len(subagent_matches) > len(skill_matches):
|
|
635
|
+
inferred_answers[q_id] = False
|
|
636
|
+
inference_methods[q_id] = "subagent_keywords_majority"
|
|
637
|
+
else:
|
|
638
|
+
# No clear signal - mark as uncertain (require explicit)
|
|
639
|
+
inferred_answers[q_id] = None
|
|
640
|
+
inference_methods[q_id] = "uncertain"
|
|
641
|
+
|
|
642
|
+
return {
|
|
643
|
+
"answers": inferred_answers,
|
|
644
|
+
"detected": detected,
|
|
645
|
+
"inference_methods": inference_methods
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
def main():
|
|
650
|
+
"""CLI entry point for agent-layer usage."""
|
|
651
|
+
parser = argparse.ArgumentParser(
|
|
652
|
+
description="Decision helper for Skills vs Subagents (Agent-Layer Tool)",
|
|
653
|
+
epilog="References: Files 02 (comparison), 03 (decision tree), 05 (token economics)",
|
|
654
|
+
formatter_class=argparse.RawDescriptionHelpFormatter
|
|
655
|
+
)
|
|
656
|
+
|
|
657
|
+
# Mutually exclusive modes
|
|
658
|
+
mode_group = parser.add_mutually_exclusive_group(required=True)
|
|
659
|
+
|
|
660
|
+
mode_group.add_argument(
|
|
661
|
+
'--answers',
|
|
662
|
+
type=str,
|
|
663
|
+
metavar='FILE',
|
|
664
|
+
help='JSON file with pre-answered questions (Mode 1 - Preferred)'
|
|
665
|
+
)
|
|
666
|
+
|
|
667
|
+
mode_group.add_argument(
|
|
668
|
+
'--analyze',
|
|
669
|
+
type=str,
|
|
670
|
+
metavar='DESCRIPTION',
|
|
671
|
+
help='Analyze use case from description (Mode 2 - Fallback)'
|
|
672
|
+
)
|
|
673
|
+
|
|
674
|
+
mode_group.add_argument(
|
|
675
|
+
'--show-criteria',
|
|
676
|
+
action='store_true',
|
|
677
|
+
help='Show decision criteria (Mode 3 - Reference)'
|
|
678
|
+
)
|
|
679
|
+
parser.add_argument(
|
|
680
|
+
'--mode',
|
|
681
|
+
choices=['fast', 'full'],
|
|
682
|
+
default='fast',
|
|
683
|
+
help='Workflow mode: fast (structural only) or full (structural + behavioral)'
|
|
684
|
+
)
|
|
685
|
+
|
|
686
|
+
# Add --format argument (JSON is default for agent-layer tool)
|
|
687
|
+
add_format_argument(parser, default='json')
|
|
688
|
+
|
|
689
|
+
args = parser.parse_args()
|
|
690
|
+
|
|
691
|
+
helper = DecisionHelper()
|
|
692
|
+
result = None
|
|
693
|
+
|
|
694
|
+
try:
|
|
695
|
+
if args.answers:
|
|
696
|
+
# Mode 1: Pre-answered questions
|
|
697
|
+
answers_path = Path(args.answers)
|
|
698
|
+
|
|
699
|
+
if not answers_path.exists():
|
|
700
|
+
result = {
|
|
701
|
+
"status": "error",
|
|
702
|
+
"error_type": "FileNotFound",
|
|
703
|
+
"message": f"Answers file not found: {args.answers}",
|
|
704
|
+
"help": "Check file path or use --analyze mode"
|
|
705
|
+
}
|
|
706
|
+
else:
|
|
707
|
+
with open(answers_path, 'r') as f:
|
|
708
|
+
answers = json.load(f)
|
|
709
|
+
result = helper.analyze_from_answers(answers, mode=args.mode)
|
|
710
|
+
|
|
711
|
+
elif args.analyze:
|
|
712
|
+
# Mode 2: Keyword-based inference
|
|
713
|
+
result = helper.analyze_from_description(args.analyze, mode=args.mode)
|
|
714
|
+
|
|
715
|
+
elif args.show_criteria:
|
|
716
|
+
# Mode 3: Show criteria
|
|
717
|
+
result = helper.show_criteria()
|
|
718
|
+
result["workflow_mode"] = args.mode
|
|
719
|
+
result["mode_note"] = (
|
|
720
|
+
"Full mode includes pressure testing"
|
|
721
|
+
if args.mode == "full"
|
|
722
|
+
else "Use --mode full for TDD behavioral validation"
|
|
723
|
+
)
|
|
724
|
+
result["mode_reasoning"] = result["mode_note"]
|
|
725
|
+
|
|
726
|
+
except json.JSONDecodeError as e:
|
|
727
|
+
result = {
|
|
728
|
+
"status": "error",
|
|
729
|
+
"error_type": "InvalidJSON",
|
|
730
|
+
"message": f"Invalid JSON in answers file: {str(e)}",
|
|
731
|
+
"help": "Ensure answers.json contains valid JSON"
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
except Exception as e:
|
|
735
|
+
result = {
|
|
736
|
+
"status": "error",
|
|
737
|
+
"error_type": "UnexpectedError",
|
|
738
|
+
"message": str(e),
|
|
739
|
+
"help": "Contact support if this persists"
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
# Output based on format
|
|
743
|
+
if args.format == 'json':
|
|
744
|
+
# JSON output (default for agent-layer)
|
|
745
|
+
print(json.dumps(result, indent=2))
|
|
746
|
+
else:
|
|
747
|
+
# Text output (for debugging/human reading)
|
|
748
|
+
print_text_format(result)
|
|
749
|
+
|
|
750
|
+
# Exit code based on status
|
|
751
|
+
return 0 if result and result.get('status') == 'success' else 1
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
def print_text_format(result: Dict):
|
|
755
|
+
"""Format result as human-readable text."""
|
|
756
|
+
if result.get('status') == 'error':
|
|
757
|
+
print(f"\nā Error: {result.get('error_type')}")
|
|
758
|
+
print(f" {result.get('message')}")
|
|
759
|
+
if result.get('help'):
|
|
760
|
+
print(f"\nš” Help: {result.get('help')}")
|
|
761
|
+
return
|
|
762
|
+
|
|
763
|
+
# Success - show recommendation
|
|
764
|
+
print(f"\n{'='*70}")
|
|
765
|
+
print(f"Decision: {result.get('recommendation')}")
|
|
766
|
+
print(f"{'='*70}\n")
|
|
767
|
+
|
|
768
|
+
print(f"Score: {result.get('score')} (Range: -8 to +8)")
|
|
769
|
+
print(f"Confidence: {result.get('confidence', 0)*100:.0f}%\n")
|
|
770
|
+
|
|
771
|
+
if result.get('reasoning'):
|
|
772
|
+
print("Reasoning:")
|
|
773
|
+
for i, reason in enumerate(result.get('reasoning', []), 1):
|
|
774
|
+
print(f" {i}. {reason}")
|
|
775
|
+
print()
|
|
776
|
+
|
|
777
|
+
if result.get('token_analysis'):
|
|
778
|
+
ta = result['token_analysis']
|
|
779
|
+
print("Token Impact:")
|
|
780
|
+
print(f" Skill approach: ~{ta.get('skill_approach_tokens')} tokens")
|
|
781
|
+
print(f" Subagent approach: ~{ta.get('subagent_approach_tokens')} tokens")
|
|
782
|
+
print(f" Cost multiplier: {ta.get('cost_multiplier')}x")
|
|
783
|
+
print(f" Note: {ta.get('recommendation_note')}\n")
|
|
784
|
+
|
|
785
|
+
if result.get('pattern_suggestions'):
|
|
786
|
+
print("Next Steps:")
|
|
787
|
+
for i, suggestion in enumerate(result.get('pattern_suggestions', []), 1):
|
|
788
|
+
print(f" {i}. {suggestion}")
|
|
789
|
+
print()
|
|
790
|
+
|
|
791
|
+
if result.get('references'):
|
|
792
|
+
print("References:")
|
|
793
|
+
for key, val in result.get('references', {}).items():
|
|
794
|
+
print(f" - {val}")
|
|
795
|
+
print()
|
|
796
|
+
|
|
797
|
+
|
|
798
|
+
if __name__ == "__main__":
|
|
799
|
+
sys.exit(main())
|