.agents/skills/technology-audit/SKILL.md
Audit the codebase and catalog for undocumented technologies, patterns, libraries, CLI tools, and components. Surfaces gaps where a tool/language/framework/library/pattern is in use but has no corresponding OpenSpec change, ADR, usage rule, or catalog entity.
npx skillsauth add em-jones/staccato-toolkit technology-auditInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Perform a comprehensive technology audit of the platform. The contract:
Don't use a tool, language, framework, library, or pattern without it existing as a change.
This skill surfaces every gap between what is actually in use in the codebase and what is formally documented via OpenSpec changes, usage rules, ADRs, and catalog entities. Each gap becomes either a new change (if the technology should be kept) or a refactoring recommendation (if a better alternative exists).
This skill is used together with the dev-portal-manager skill for catalog gap resolution.
/tech-audit custom command$SCOPE (optional): Narrow the audit to a specific layer — code, catalog, rules,
changes, or all (default: all)$PATH (optional): Subdirectory to scan (default: repo root)If neither is provided the audit runs in full-scope mode across the entire repository.
Run the session-start orientation:
td usage --new-session
Then announce the audit scope and begin. Do NOT wait for confirmation — proceed immediately.
## Technology Audit
Scope: <scope>
Path: <path>
Date: <today>
Scanning...
Gather raw evidence across five lenses. Run all collection steps before analysis.
# Detect languages by file extension and toolchain files
find . \
-not -path './.git/*' \
-not -path './node_modules/*' \
-not -path './.devbox/*' \
\( -name "go.mod" -o -name "package.json" -o -name "Cargo.toml" \
-o -name "pyproject.toml" -o -name "*.tf" -o -name "Makefile" \
-o -name "*.sh" -o -name "Dockerfile" -o -name "devbox.json" \) \
2>/dev/null
For each package.json found (excluding node_modules):
# Extract all dependencies (prod + dev)
jq -r '(.dependencies // {}) + (.devDependencies // {}) | keys[]' <path>/package.json
For each go.mod found:
# Extract DIRECT (non-indirect) module dependencies only
grep -E '^require' -A9999 <path>/go.mod | grep -v '^require' | grep -v '// indirect' | awk '{print $1}' | grep -v ')'
IMPORTANT: Filter out transitive/indirect dependencies. A transitive dependency is one that:
// indirect in go.modOnly report technologies that are direct platform choices (see Transitive Dependency Exclusion).
For devbox.json:
jq -r '.packages[]' devbox.json
# Commands invoked in shell scripts and Makefiles
grep -rh --include="*.sh" --include="Makefile" --include="*.mk" \
-oE '\b(kubectl|helm|kustomize|dagger|jq|yq|bun|node|go|docker|kind|skaffold|k9s|trivy|openspec|td)\b' \
. 2>/dev/null | sort -u
Also scan CI/CD pipeline definitions:
find . -name "*.yml" -o -name "*.yaml" | \
xargs grep -lh "uses:\|run:\|steps:" 2>/dev/null | \
grep -v node_modules
Look for direct framework usage in source code — exclude transitive dependencies pulled in by generated code:
# Go: HTTP routers, ORMs, test libraries (direct imports in .go files)
grep -rh --include="*.go" -oE '"(github\.com/[^"]+)"' . \
--exclude-dir=node_modules --exclude-dir=.devbox \
2>/dev/null | sort -u | head -60
# TypeScript/JS: framework imports (direct imports in .ts/.tsx/.js files)
grep -rh --include="*.ts" --include="*.tsx" --include="*.js" \
-oE "from '(@[a-z0-9-]+/[a-z0-9-]+|[a-z0-9-]+)'" \
--exclude-dir=node_modules \
. 2>/dev/null | sort -u | head -60
IMPORTANT: Filter out imports from:
dagger.gen.go, *.generated.ts)Only report libraries that appear as direct imports in the platform's own code.
# Helm charts in use
find . -name "Chart.yaml" 2>/dev/null
# Kubernetes API versions in use
grep -rh --include="*.yaml" --include="*.yml" "apiVersion:" . 2>/dev/null | \
sort -u | grep -v node_modules
# KubeVela OAM component types
grep -rh --include="*.yaml" --include="*.yml" "type:" . 2>/dev/null | \
grep -E "(webservice|worker|cron-task|k8s-objects)" | sort -u
# Dagger modules
find . -name "dagger.json" 2>/dev/null
Identify patterns by their structural signatures:
# Feature flags (env var gates, config toggles)
grep -rh --include="*.go" --include="*.ts" \
-E "(FeatureFlag|feature_flag|isEnabled|getFlag)" . 2>/dev/null | wc -l
# Structured logging
grep -rh --include="*.go" -E '(slog\.|log\.With|zap\.|logrus\.)' . 2>/dev/null | wc -l
# Observability (traces, metrics)
grep -rh --include="*.go" --include="*.ts" \
-E "(otel\.|opentelemetry|tracer\.|meter\.)" . 2>/dev/null | wc -l
openspec list --json 2>/dev/null
Also walk the changes directory for archived ones:
ls openspec/changes/ 2>/dev/null
ls openspec/archive/ 2>/dev/null
Read each design.md to extract the Technology Adoption & Usage Rules table:
grep -h "| " openspec/changes/*/design.md 2>/dev/null | \
grep -v "^| Technology\|^| ---" | head -80
find .opencode/rules/ -name "*.md" -not -name "README.md" -not -name "TEMPLATE.md" | sort
ls .entities/ 2>/dev/null
Read each entity's metadata.name and spec.type:
for f in .entities/*.yaml; do
yq -r '"\(.kind): \(.metadata.name) (\(.spec.type // "n/a"))"' "$f" 2>/dev/null
done
find docs/adrs/ -name "*.md" 2>/dev/null | sort
Compare the evidence sets. For each item discovered in Step 2, check:
| Check | Pass condition |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| Has a change? | An OpenSpec change (active or archived) names this technology or includes it in its Technology Adoption table |
| Has a usage rule? | A file exists at .opencode/rules/technologies/<domain>/<name>.md or .opencode/rules/patterns/<layer>/<domain>.md |
| Has a catalog entity? | A .entities/resource-<name>.yaml (or component/system) exists |
| Has an ADR? | A symlinked or native ADR in docs/adrs/ covers the adoption decision |
A technology "passes" if all four checks pass (or the check is explicitly N/A for its kind — e.g., a pattern doesn't need a catalog entity).
| Severity | Meaning | | --------------- | ------------------------------------------------------------------------------------------ | | 🔴 Critical | Technology is in active use with no change, no usage rule, AND no ADR | | 🟡 Warning | Technology has a change or ADR but is missing a usage rule or catalog entity | | 🟢 Info | Technology has a usage rule but the catalog entity is missing (mechanically derivable gap) |
Output a structured report:
## Technology Audit Report
Date: <YYYY-MM-DD>
Repo: <path>
### Summary
Total technologies detected: N
Fully documented: N ✓
Warning gaps: N 🟡
Critical gaps: N 🔴
### Critical Gaps 🔴
<For each critical gap:>
**<technology-name>** (`<category>`)
- Detected in: <file paths or locations>
- Missing: change, usage rule, ADR, catalog entity (list which)
- Recommended action: <see Step 6>
### Warning Gaps 🟡
<For each warning gap:>
**<technology-name>** (`<category>`)
- Detected in: <file paths>
- Missing: <which checks failed>
- Recommended action: <see Step 6>
### Info Gaps 🟢
<For each info gap:>
**<technology-name>**
- Missing: catalog entity only
- Recommended action: run derivation script or create entity manually
### Fully Documented ✓
<List technology names only — no details needed>
For each gap, determine the appropriate resolution:
When the technology is clearly the right choice and should be kept:
openspec new change "adopt-<technology-name>"
Then use /opsx-ff adopt-<technology-name> to author all artifacts, including:
When a change already exists but the usage rule is missing:
Load the create-usage-rules skill and create the rule:
skill: create-usage-rules
$TECHNICAL_DOMAIN: <domain>
$PACKAGE_NAME: <name>
$CHANGE_NAME: <nearest-related-change>
When the technology has a change and usage rule but no catalog entity:
For CLI tools/utilities from devbox.json:
.opencode/skills/dev-portal-manager/scripts/derive-from-devbox.sh
For npm packages:
.opencode/skills/dev-portal-manager/scripts/derive-from-package-json.sh
For manual entities, load dev-portal-manager skill and author the entity YAML.
When a better alternative already has formal documentation:
td issue: td create "Refactor: replace <old> with <new>" --type taskopenspec new change "replace-<old>-with-<new>"When a technology is intentionally not documented (e.g., a transitive dependency, a test-only tool with no usage decisions):
After producing the report, create td tasks for all non-trivial resolutions:
# Create an audit root issue to group resolution tasks
td create "Technology Audit: <date>" --type feature
# → <audit-root-id>
# For each critical gap
td create "Adopt: <technology-name> — create change + usage rule" \
--type task --parent <audit-root-id>
# For each warning gap
td create "Gap: <technology-name> — missing <what>" \
--type task --parent <audit-root-id>
# For each refactoring candidate
td create "Refactor: replace <old> with <new>" \
--type task --parent <audit-root-id>
Show the board:
td board create "tech-audit-<date>" --query "descendant_of(<audit-root-id>)"
td board show "tech-audit-<date>"
After creating the task board, automatically dispatch researcher subagents for warning gaps (missing usage rules where a change already exists). Do not wait for user input — this dispatch is automatic.
Collect all warning-gap tasks created in Step 7 that require Action B (create usage rule):
td ls --ancestor <audit-root-id> --status open --type task | grep "^Gap:"
For each warning-gap task that needs a usage rule, dispatch a researcher:
subagent_type: "researcher"description: "Create usage rules for <domain>" (5–10 words)prompt: the task id and domain, e.g.:Your assigned task ids: <gap-task-id>
Dispatch all researcher tasks in a single message (parallel). Announce:
Dispatching N researcher(s) for warning gaps...
Wait for all researchers to return, then mark their corresponding tasks done:
td handoff <task-id> --done "Usage rule created" --remaining "none"
td review <task-id>
After researchers complete (or if there were no warning gaps), offer:
"I can resolve remaining gaps immediately. Which would you like me to address now?"
all— resolve everything in severity order (critical → info)critical— critical gaps only<technology-name>— resolve a specific gapnone— just the report and tasks (default if no input provided)
If resolving immediately:
For each selected gap, execute the resolution action (A–D) from Step 6. For Action A (new change),
use the development-orchestrator skill to fast-forward through artifact authoring. Do NOT
implement code changes — this is a design + documentation activity.
After each resolution, mark the corresponding td task done:
td handoff <task-id> --done "<what was created>" --remaining "none"
td review <task-id>
Transitive dependencies are EXCLUDED from technology audit. A transitive dependency is a technology that is:
EXCLUDED (transitive):
gqlgen (pulled in by gqlgen-using dependencies)INCLUDED (direct):
chi router — explicitly imported and used in service codeopentelemetry SDK — directly called in instrumentation codedagger CLI — directly invoked in build scriptskubectl — directly run in deployment automationIn Go:
# Look for '// indirect' marker in go.mod
grep '// indirect' go.mod
In npm:
package-lock.json for nested structure (transitive packages appear deeper in the tree)npm ls --depth=0 to see only direct dependenciesIn code:
import, from, command-line invocationWhen reporting a detected technology:
To add a custom exclusion, document it here with a rationale.
After Step 6 resolutions, always check if new catalog entities are needed:
Load the dev-portal-manager skill
For any technology resolved via Action A or B, author the corresponding Resource entity
If a new component was introduced, author the Component entity
If a new system boundary was identified, author the System entity
Run both derivation scripts to catch mechanically-derivable gaps:
.opencode/skills/dev-portal-manager/scripts/derive-from-devbox.sh
.opencode/skills/dev-portal-manager/scripts/derive-from-package-json.sh
Verify all new entities reference existing spec.owner and spec.system entities
tools
<!--VITE PLUS START--> # Using Vite+, the Unified Toolchain for the Web This project is using Vite+, a unified toolchain built on top of Vite, Rolldown, Vitest, tsdown, Oxlint, Oxfmt, and Vite Task. Vite+ wraps runtime management, package management, and frontend tooling in a single global CLI called `vp`. Vite+ is distinct from Vite, but it invokes Vite through `vp dev` and `vp build`. ## Vite+ Workflow `vp` is a global binary that handles the full development lifecycle. Run `vp help` to pr
development
Guide for building performant data tables. Uses tanstack-table for table logic (sorting, filtering, pagination) and tanstack-virtual for rendering large datasets efficiently.
development
Expert guidance for building observable, expressive, and fault-tolerant TypeScript applications using the effect-ts/effect ecosystem. Covers Effect<A, E, R> type, error management, dependency injection via Layers, observability (logging, metrics, tracing), concurrency with Fibers, retry/scheduling, Schema validation, Streams, and Sinks.
tools
Complete E2E (end-to-end) and integration testing skill for TypeScript/NestJS projects using Jest, real infrastructure via Docker, and GWT pattern. ALWAYS use this skill when user needs to: **SETUP** - Initialize or configure E2E testing infrastructure: - Set up E2E testing for a new project - Configure docker-compose for testing (Kafka, PostgreSQL, MongoDB, Redis) - Create jest-e2e.config.ts or E2E Jest configuration - Set up test helpers for database, Kafka, or Redis - Configure .env.e2e environment variables - Create test/e2e directory structure **WRITE** - Create or add E2E/integration tests: - Write, create, add, or generate e2e tests or integration tests - Test API endpoints, workflows, or complete features end-to-end - Test with real databases, message brokers, or external services - Test Kafka consumers/producers, event-driven workflows - Working on any file ending in .e2e-spec.ts or in test/e2e/ directory - Use GWT (Given-When-Then) pattern for tests **REVIEW** - Audit or evaluate E2E tests: - Review existing E2E tests for quality - Check test isolation and cleanup patterns - Audit GWT pattern compliance - Evaluate assertion quality and specificity - Check for anti-patterns (multiple WHEN actions, conditional assertions) **RUN** - Execute or analyze E2E test results: - Run E2E tests - Start/stop Docker infrastructure for testing - Analyze E2E test results - Verify Docker services are healthy - Interpret test output and failures **DEBUG** - Fix failing or flaky E2E tests: - Fix failing E2E tests - Debug flaky tests or test isolation issues - Troubleshoot connection errors (database, Kafka, Redis) - Fix timeout issues or async operation failures - Diagnose race conditions or state leakage - Debug Kafka message consumption issues **OPTIMIZE** - Improve E2E test performance: - Speed up slow E2E tests - Optimize Docker infrastructure startup - Replace fixed waits with smart polling - Reduce beforeEach cleanup time - Improve test parallelization where safe Keywords: e2e, end-to-end, integration test, e2e-spec.ts, test/e2e, Jest, supertest, NestJS, Kafka, Redpanda, PostgreSQL, MongoDB, Redis, docker-compose, GWT pattern, Given-When-Then, real infrastructure, test isolation, flaky test, MSW, nock, waitForMessages, fix e2e, debug e2e, run e2e, review e2e, optimize e2e, setup e2e