* fix: ContextScout falls back to global core/ when local core/ missing Users who install OAC globally have core standards at ~/.config/opencode/context/core/ but no local core/ directory. ContextScout now does a one-time check on startup: if local core/navigation.md doesn't exist, it checks the global path from paths.json. This resolves the ENOENT errors when agents try to read core/standards/ files that only exist globally. - paths.json: enabled global path (~/.config/opencode/context) - contextscout.md: added global_fallback rule with 2-glob cap - Fallback is ONLY for core/ files, never project-intelligence * docs: add context resolution explanation to README Explains how ContextScout resolves context files: local-first, global fallback only for core/ files, project-intelligence always local. Includes flow diagram, key rules, and common setup table. * fix: resolve installer failures and add comprehensive validation ## Summary Fixes critical installer failures where ContextScout and other components couldn't find their configuration files after installation. Adds comprehensive validation system to prevent future issues. ## Problems Fixed ### 1. Missing Critical Files (13 dead registry references) Files were referenced in registry but didn't exist on disk: - workflows-delegation (split into 3 files) - design-iteration (split into 8 files) - animation-patterns (split into 6 files) - adding-agent (split into 2 files) - adding-skill (split into 3 files) - navigation-design (split into 2 files) - external-libraries (split into 3 files) - claude-code-docs/* (directory removed) ### 2. Missing Infrastructure Files ContextScout failed after installation because 2 critical files weren't in registry: - paths.json - Context root configuration - navigation.md - Root navigation for discovery ### 3. Profile Inconsistencies Profiles referenced components that don't exist: - context:adding-skill → context:adding-skill-basics - context:animation-patterns → animation-basics/components/advanced - context:design-assets (removed - doesn't exist) - context:to-be-consumed/* (removed - directory doesn't exist) - skill:context-manager → subagent:context-manager ## Changes Made ### Registry (registry.json) - Removed 13 dead references - Added 27 new split-file entries - Added 2 critical infrastructure entries - Fixed all 5 profile configurations - Updated ContextScout dependencies - Updated agent-metadata.json dependencies ### New Validation Scripts - scripts/registry/check-dependencies.ts - Comprehensive dependency checker - scripts/tests/test-installer-files.sh - Installer simulation test - scripts/registry/fix-registry.py - Automated registry fixer - scripts/hooks/pre-commit - Git pre-commit hook ### Documentation - docs/maintenance/REGISTRY_FIXES_SUMMARY.md - docs/maintenance/CONTEXTSCOUT_FIX.md - docs/maintenance/REGISTRY_VALIDATION.md ## Validation Results Before: - 13 missing files in registry - 78 orphaned files on disk - 3 missing dependencies - Installer would fail After: - 244 total paths, 0 missing - 262 dependency checks, 0 failures - 0 orphaned dependencies - All profiles consistent - Installer works correctly ## Testing ```bash # Registry validation bun run scripts/registry/validate-registry.ts # ✓ All 244 paths valid # Dependency checking bun run scripts/registry/check-dependencies.ts # ✓ All 262 checks passed # Installer test ./scripts/tests/test-installer-files.sh --local --profile=essential # ✓ All files accessible ``` ## Usage ### Run validation before commits: ```bash bun run scripts/registry/check-dependencies.ts ``` ### Install pre-commit hook: ```bash cp scripts/hooks/pre-commit .git/hooks/pre-commit chmod +x .git/hooks/pre-commit ``` ### Test installer: ```bash ./scripts/tests/test-installer-files.sh --local --profile=essential ``` ## Impact This fix ensures: - ✓ Installer downloads all required files - ✓ ContextScout works immediately after install - ✓ No broken dependencies - ✓ No missing profile components - ✓ Future issues caught by validation ## Breaking Changes None - all changes are additive or fix broken references. ## Related - Fixes: ContextScout failing after installation - Prevents: Missing file errors during install - Adds: Comprehensive validation system * fix: resolve shellcheck warnings in test scripts - Remove unused REPO_URL variable from test-installer-files.sh - Add shellcheck disable comments for cleanup functions used via trap - Fixes CI failures in ShellCheck Analysis workflow * fix: resolve shellcheck errors across all scripts Fixed arithmetic expansion issues and code quality warnings: - Changed ((var++)) to POSIX-compliant 1 syntax - Fixed unquoted variables and grep pipe issues (SC2002, SC2143) - Added shellcheck disable comments for intentional patterns - Fixed variable initialization and return statement placement Scripts fixed: - scripts/tests/*.sh (5 files) - scripts/registry/*.sh (4 files) - scripts/validation/*.sh (2 files) - scripts/*.sh (2 files) - evals/framework/scripts/*.sh (2 files) All scripts now pass shellcheck --severity=warning * chore: trigger CI shellcheck validation
436 lines
17 KiB
Python
436 lines
17 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Registry Fix Script
|
|
Fixes dead references and adds orphaned files to registry.json
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
|
|
REPO_ROOT = Path(__file__).parent.parent.parent
|
|
REGISTRY_FILE = REPO_ROOT / "registry.json"
|
|
|
|
def load_registry():
|
|
with open(REGISTRY_FILE, 'r') as f:
|
|
return json.load(f)
|
|
|
|
def save_registry(registry):
|
|
with open(REGISTRY_FILE, 'w') as f:
|
|
json.dump(registry, f, indent=2)
|
|
print(f"✓ Registry saved to {REGISTRY_FILE}")
|
|
|
|
def remove_dead_references(registry):
|
|
"""Remove entries that point to non-existent files"""
|
|
dead_entries = [
|
|
"workflows-delegation", # Split into multiple files
|
|
"design-iteration", # Split into multiple files
|
|
"design-assets", # Doesn't exist
|
|
"animation-patterns", # Split into animation-*.md files
|
|
"adding-agent", # Split into adding-agent-*.md
|
|
"adding-skill", # Split into adding-skill-*.md
|
|
"navigation-design", # Split into navigation-design-*.md
|
|
"claude-agent-skills", # Directory doesn't exist
|
|
"claude-create-subagents", # Directory doesn't exist
|
|
"claude-hooks", # Directory doesn't exist
|
|
"claude-plugins", # Directory doesn't exist
|
|
"external-libraries", # Split into external-libraries-*.md
|
|
"navigation", # Duplicate/to-be-consumed doesn't exist
|
|
]
|
|
|
|
removed = []
|
|
for category in ['contexts']:
|
|
if category in registry['components']:
|
|
original_count = len(registry['components'][category])
|
|
registry['components'][category] = [
|
|
c for c in registry['components'][category]
|
|
if c['id'] not in dead_entries
|
|
]
|
|
removed_count = original_count - len(registry['components'][category])
|
|
if removed_count > 0:
|
|
removed.append(f"{category}: {removed_count} entries")
|
|
|
|
print(f"✓ Removed dead references: {', '.join(removed) if removed else 'None'}")
|
|
return registry
|
|
|
|
def add_split_file_entries(registry):
|
|
"""Add entries for split files that exist on disk"""
|
|
|
|
new_entries = [
|
|
# Task Delegation (split files)
|
|
{
|
|
"id": "task-delegation-basics",
|
|
"name": "Task Delegation Basics",
|
|
"type": "context",
|
|
"path": ".opencode/context/core/workflows/task-delegation-basics.md",
|
|
"description": "Task delegation fundamentals and basic usage patterns",
|
|
"tags": ["workflows", "delegation"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "task-delegation-specialists",
|
|
"name": "Task Delegation Specialists",
|
|
"type": "context",
|
|
"path": ".opencode/context/core/workflows/task-delegation-specialists.md",
|
|
"description": "Specialist subagents for task delegation workflows",
|
|
"tags": ["workflows", "delegation", "subagents"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "task-delegation-caching",
|
|
"name": "Task Delegation Caching",
|
|
"type": "context",
|
|
"path": ".opencode/context/core/workflows/task-delegation-caching.md",
|
|
"description": "Caching strategies for task delegation workflows",
|
|
"tags": ["workflows", "delegation", "caching"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
|
|
# Design Iteration (split files)
|
|
{
|
|
"id": "design-iteration-overview",
|
|
"name": "Design Iteration Overview",
|
|
"type": "context",
|
|
"path": ".opencode/context/core/workflows/design-iteration-overview.md",
|
|
"description": "Overview of the design iteration workflow process",
|
|
"tags": ["workflows", "design", "iteration"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "design-iteration-plan-file",
|
|
"name": "Design Iteration Plan File",
|
|
"type": "context",
|
|
"path": ".opencode/context/core/workflows/design-iteration-plan-file.md",
|
|
"description": "Structure and format for design iteration plan files",
|
|
"tags": ["workflows", "design", "planning"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "design-iteration-plan-iterations",
|
|
"name": "Design Iteration Plan Iterations",
|
|
"type": "context",
|
|
"path": ".opencode/context/core/workflows/design-iteration-plan-iterations.md",
|
|
"description": "Planning iterations in the design workflow",
|
|
"tags": ["workflows", "design", "planning"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "design-iteration-stage-layout",
|
|
"name": "Design Iteration Stage - Layout",
|
|
"type": "context",
|
|
"path": ".opencode/context/core/workflows/design-iteration-stage-layout.md",
|
|
"description": "Layout stage guidelines for design iteration",
|
|
"tags": ["workflows", "design", "layout"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "design-iteration-stage-theme",
|
|
"name": "Design Iteration Stage - Theme",
|
|
"type": "context",
|
|
"path": ".opencode/context/core/workflows/design-iteration-stage-theme.md",
|
|
"description": "Theme stage guidelines for design iteration",
|
|
"tags": ["workflows", "design", "theme"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "design-iteration-stage-implementation",
|
|
"name": "Design Iteration Stage - Implementation",
|
|
"type": "context",
|
|
"path": ".opencode/context/core/workflows/design-iteration-stage-implementation.md",
|
|
"description": "Implementation stage guidelines for design iteration",
|
|
"tags": ["workflows", "design", "implementation"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "design-iteration-stage-animation",
|
|
"name": "Design Iteration Stage - Animation",
|
|
"type": "context",
|
|
"path": ".opencode/context/core/workflows/design-iteration-stage-animation.md",
|
|
"description": "Animation stage guidelines for design iteration",
|
|
"tags": ["workflows", "design", "animation"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "design-iteration-visual-content",
|
|
"name": "Design Iteration Visual Content",
|
|
"type": "context",
|
|
"path": ".opencode/context/core/workflows/design-iteration-visual-content.md",
|
|
"description": "Visual content guidelines for design iteration",
|
|
"tags": ["workflows", "design", "visual"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "design-iteration-best-practices",
|
|
"name": "Design Iteration Best Practices",
|
|
"type": "context",
|
|
"path": ".opencode/context/core/workflows/design-iteration-best-practices.md",
|
|
"description": "Best practices for design iteration workflows",
|
|
"tags": ["workflows", "design", "best-practices"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
|
|
# External Libraries (split files)
|
|
{
|
|
"id": "external-libraries-workflow",
|
|
"name": "External Libraries Workflow",
|
|
"type": "context",
|
|
"path": ".opencode/context/core/workflows/external-libraries-workflow.md",
|
|
"description": "Workflow for managing external library dependencies",
|
|
"tags": ["workflows", "external", "libraries"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "external-libraries-scenarios",
|
|
"name": "External Libraries Scenarios",
|
|
"type": "context",
|
|
"path": ".opencode/context/core/workflows/external-libraries-scenarios.md",
|
|
"description": "Common scenarios for external library integration",
|
|
"tags": ["workflows", "external", "libraries", "scenarios"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "external-libraries-faq",
|
|
"name": "External Libraries FAQ",
|
|
"type": "context",
|
|
"path": ".opencode/context/core/workflows/external-libraries-faq.md",
|
|
"description": "Frequently asked questions about external libraries",
|
|
"tags": ["workflows", "external", "libraries", "faq"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
|
|
# Adding Agent (split files)
|
|
{
|
|
"id": "adding-agent-basics",
|
|
"name": "Adding Agent - Basics",
|
|
"type": "context",
|
|
"path": ".opencode/context/openagents-repo/guides/adding-agent-basics.md",
|
|
"description": "Basic guide for adding new agents",
|
|
"tags": ["guides", "agents", "basics"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "adding-agent-testing",
|
|
"name": "Adding Agent - Testing",
|
|
"type": "context",
|
|
"path": ".opencode/context/openagents-repo/guides/adding-agent-testing.md",
|
|
"description": "Testing guide for new agents",
|
|
"tags": ["guides", "agents", "testing"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
|
|
# Adding Skill (split files)
|
|
{
|
|
"id": "adding-skill-basics",
|
|
"name": "Adding Skill - Basics",
|
|
"type": "context",
|
|
"path": ".opencode/context/openagents-repo/guides/adding-skill-basics.md",
|
|
"description": "Basic guide for adding new skills",
|
|
"tags": ["guides", "skills", "basics"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "adding-skill-implementation",
|
|
"name": "Adding Skill - Implementation",
|
|
"type": "context",
|
|
"path": ".opencode/context/openagents-repo/guides/adding-skill-implementation.md",
|
|
"description": "Implementation guide for new skills",
|
|
"tags": ["guides", "skills", "implementation"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "adding-skill-example",
|
|
"name": "Adding Skill - Example",
|
|
"type": "context",
|
|
"path": ".opencode/context/openagents-repo/guides/adding-skill-example.md",
|
|
"description": "Example of adding a new skill",
|
|
"tags": ["guides", "skills", "examples"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
|
|
# Navigation Design (split files)
|
|
{
|
|
"id": "navigation-design-basics",
|
|
"name": "Navigation Design Basics",
|
|
"type": "context",
|
|
"path": ".opencode/context/core/context-system/guides/navigation-design-basics.md",
|
|
"description": "Basics of designing navigation files",
|
|
"tags": ["context-system", "navigation", "design"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "navigation-templates",
|
|
"name": "Navigation Templates",
|
|
"type": "context",
|
|
"path": ".opencode/context/core/context-system/guides/navigation-templates.md",
|
|
"description": "Templates for navigation files",
|
|
"tags": ["context-system", "navigation", "templates"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
|
|
# Animation Patterns (split files)
|
|
{
|
|
"id": "animation-basics",
|
|
"name": "Animation Basics",
|
|
"type": "context",
|
|
"path": ".opencode/context/ui/web/animation-basics.md",
|
|
"description": "Basic animation patterns and guidelines",
|
|
"tags": ["ui", "web", "animation"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "animation-advanced",
|
|
"name": "Animation Advanced",
|
|
"type": "context",
|
|
"path": ".opencode/context/ui/web/animation-advanced.md",
|
|
"description": "Advanced animation patterns and techniques",
|
|
"tags": ["ui", "web", "animation"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "animation-components",
|
|
"name": "Animation Components",
|
|
"type": "context",
|
|
"path": ".opencode/context/ui/web/animation-components.md",
|
|
"description": "Component-specific animation patterns",
|
|
"tags": ["ui", "web", "animation", "components"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "animation-forms",
|
|
"name": "Animation Forms",
|
|
"type": "context",
|
|
"path": ".opencode/context/ui/web/animation-forms.md",
|
|
"description": "Animation patterns for forms",
|
|
"tags": ["ui", "web", "animation", "forms"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "animation-chat",
|
|
"name": "Animation Chat",
|
|
"type": "context",
|
|
"path": ".opencode/context/ui/web/animation-chat.md",
|
|
"description": "Animation patterns for chat interfaces",
|
|
"tags": ["ui", "web", "animation", "chat"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
{
|
|
"id": "animation-loading",
|
|
"name": "Animation Loading",
|
|
"type": "context",
|
|
"path": ".opencode/context/ui/web/animation-loading.md",
|
|
"description": "Loading animation patterns",
|
|
"tags": ["ui", "web", "animation", "loading"],
|
|
"dependencies": [],
|
|
"category": "standard"
|
|
},
|
|
]
|
|
|
|
# Verify files exist before adding
|
|
verified_entries = []
|
|
for entry in new_entries:
|
|
file_path = REPO_ROOT / entry['path']
|
|
if file_path.exists():
|
|
verified_entries.append(entry)
|
|
else:
|
|
print(f"⚠ File doesn't exist: {entry['path']}")
|
|
|
|
# Add to registry
|
|
if 'contexts' not in registry['components']:
|
|
registry['components']['contexts'] = []
|
|
|
|
existing_ids = {c['id'] for c in registry['components']['contexts']}
|
|
added = 0
|
|
for entry in verified_entries:
|
|
if entry['id'] not in existing_ids:
|
|
registry['components']['contexts'].append(entry)
|
|
added += 1
|
|
|
|
print(f"✓ Added {added} new split-file entries")
|
|
return registry
|
|
|
|
def update_dependencies(registry):
|
|
"""Update dependencies that referenced old split files"""
|
|
# Update OpenCoder dependencies
|
|
for agent in registry['components'].get('agents', []):
|
|
if agent['id'] == 'opencoder':
|
|
# Replace workflows-delegation with task-delegation-basics
|
|
agent['dependencies'] = [
|
|
dep.replace('context:workflows-delegation', 'context:task-delegation-basics')
|
|
for dep in agent['dependencies']
|
|
]
|
|
print(f"✓ Updated dependencies for agent: {agent['id']}")
|
|
|
|
# Update context dependencies
|
|
for ctx in registry['components'].get('contexts', []):
|
|
if 'dependencies' in ctx:
|
|
# Replace external-libraries with external-libraries-workflow
|
|
ctx['dependencies'] = [
|
|
dep.replace('context:external-libraries', 'context:external-libraries-workflow')
|
|
for dep in ctx['dependencies']
|
|
]
|
|
# Replace adding-agent with adding-agent-basics
|
|
ctx['dependencies'] = [
|
|
dep.replace('context:adding-agent', 'context:adding-agent-basics')
|
|
for dep in ctx['dependencies']
|
|
]
|
|
# Replace adding-skill with adding-skill-basics
|
|
ctx['dependencies'] = [
|
|
dep.replace('context:adding-skill', 'context:adding-skill-basics')
|
|
for dep in ctx['dependencies']
|
|
]
|
|
|
|
print(f"✓ Updated dependencies referencing split files")
|
|
return registry
|
|
|
|
def main():
|
|
print("=" * 60)
|
|
print("Registry Fix Script")
|
|
print("=" * 60)
|
|
|
|
# Load registry
|
|
registry = load_registry()
|
|
print(f"✓ Loaded registry with {len(registry['components'].get('contexts', []))} contexts")
|
|
|
|
# Fix steps
|
|
registry = remove_dead_references(registry)
|
|
registry = add_split_file_entries(registry)
|
|
registry = update_dependencies(registry)
|
|
|
|
# Save registry
|
|
save_registry(registry)
|
|
|
|
# Validate
|
|
context_count = len(registry['components'].get('contexts', []))
|
|
print(f"\n✓ Registry now has {context_count} context entries")
|
|
print("\nNext: Run validation to check results")
|
|
print(" bun run scripts/registry/validate-registry.ts")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|