@ivannikov-pro/ai-context-surgeon 1.0.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/LICENSE +22 -0
- package/README.md +372 -0
- package/bin/catalog.js +153 -0
- package/bin/cli.js +380 -0
- package/bin/installer.js +135 -0
- package/bin/prompts.js +371 -0
- package/checklists/phase-1-analysis.md +58 -0
- package/checklists/phase-2-planning.md +67 -0
- package/checklists/phase-3-restructuring.md +77 -0
- package/checklists/phase-4-documentation.md +111 -0
- package/checklists/phase-5-validation.md +91 -0
- package/examples/before-after/README.md +139 -0
- package/examples/ideal-monorepo/README.md +127 -0
- package/knowledge/agent-context-system/artifacts/guide.md +183 -0
- package/knowledge/agent-context-system/artifacts/knowledge.md +177 -0
- package/knowledge/agent-context-system/artifacts/skills.md +101 -0
- package/knowledge/agent-context-system/artifacts/workflows.md +143 -0
- package/knowledge/agent-context-system/metadata.json +26 -0
- package/knowledge/agent-context-system/timestamps.json +5 -0
- package/knowledge/agent-vulnerabilities/LICENSE +21 -0
- package/knowledge/agent-vulnerabilities/artifacts/stealth_injection.md +110 -0
- package/knowledge/agent-vulnerabilities/artifacts/vulnerabilities.md +232 -0
- package/knowledge/agent-vulnerabilities/metadata.json +14 -0
- package/knowledge/agent-vulnerabilities/timestamps.json +5 -0
- package/knowledge/power-words-dictionary/LICENSE +21 -0
- package/knowledge/power-words-dictionary/artifacts/dictionary.md +231 -0
- package/knowledge/power-words-dictionary/artifacts/prompt_amplifier.py +381 -0
- package/knowledge/power-words-dictionary/metadata.json +14 -0
- package/knowledge/power-words-dictionary/timestamps.json +5 -0
- package/package.json +77 -0
- package/roles/README.md +81 -0
- package/roles/architect.md +203 -0
- package/roles/inspector.md +232 -0
- package/roles/librarian.md +176 -0
- package/roles/scout.md +169 -0
- package/roles/surgeon.md +172 -0
- package/roles/tuner.md +204 -0
- package/skills/annotate-jsdoc/SKILL.md +262 -0
- package/skills/prompt-engineering/LICENSE +21 -0
- package/skills/prompt-engineering/SKILL.md +235 -0
- package/skills/prompt-engineering/scripts/extract_instructions.py +416 -0
- package/skills/prompt-engineering/scripts/prompt_amplifier.py +381 -0
- package/skills/prompt-engineering/scripts/prompt_diff_tracker.py +281 -0
- package/skills/prompt-engineering/scripts/prompt_dna_analyzer.py +692 -0
- package/skills/prompt-engineering/scripts/templates/code_review.md +47 -0
- package/skills/prompt-engineering/scripts/templates/dump_extraction.md +59 -0
- package/skills/prompt-engineering/scripts/templates/multi_agent_orchestration.md +100 -0
- package/skills/prompt-engineering/scripts/templates/prompt_audit.md +106 -0
- package/skills/prompt-engineering/scripts/templates/stealth_injection.md +110 -0
- package/skills/prompt-engineering/scripts/templates/task_automation.md +87 -0
- package/skills/prompt-engineering/workflows/amplify.md +36 -0
- package/skills/prompt-engineering/workflows/audit.md +55 -0
- package/skills/prompt-engineering/workflows/context-dump.md +90 -0
- package/skills/prompt-engineering/workflows/diff.md +44 -0
- package/strategy/bash-guide.md +134 -0
- package/strategy/context-exclusion.md +220 -0
- package/strategy/context-weight-theory.md +49 -0
- package/strategy/file-navigation-header.md +562 -0
- package/strategy/jsdoc-guide.md +596 -0
- package/strategy/monorepo_strategy.md +726 -0
- package/strategy/package-json-guide.md +541 -0
- package/templates/AGENTS.md.template +148 -0
- package/templates/antigravityignore.template +64 -0
- package/templates/cursorrules.template +7 -0
- package/templates/knowledge-item.template +44 -0
- package/templates/package-json-ideal.template +26 -0
- package/templates/package-readme.template +45 -0
- package/templates/publish-meta.template +34 -0
- package/templates/skill.template +50 -0
- package/templates/workflow.template +33 -0
- package/tools/analyze-package-json.sh +213 -0
- package/tools/analyze-structure.sh +101 -0
- package/tools/audit-jsdoc.sh +176 -0
- package/tools/check-fnh-freshness.sh +74 -0
- package/tools/detect-circular-deps.sh +147 -0
- package/tools/detect-god-files.sh +71 -0
- package/tools/enforce-god-files.sh +112 -0
- package/tools/enrich-package-json.js +311 -0
- package/tools/generate-jsdoc-headers.sh +109 -0
- package/tools/generate-source-map.sh +71 -0
- package/tools/lint-imports.sh +123 -0
- package/tools/measure-context-cost.sh +206 -0
- package/tools/scan-fnh.sh +174 -0
- package/tools/shared/config.sh +53 -0
- package/tools/validate-context-hygiene.sh +52 -0
- package/tools/validate-context-weight.sh +100 -0
- package/tools/validate-naming.sh +98 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Config: antigravityignore — files to exclude from AI agent context
|
|
2
|
+
# Syntax: same as .gitignore | Each level is self-contained
|
|
3
|
+
# THREE SYSTEMS: .gitignore (git), .antigravityignore (agent context), .npmignore (npm publish)
|
|
4
|
+
|
|
5
|
+
# ─ Lock files (massive, zero context value)
|
|
6
|
+
pnpm-lock.yaml
|
|
7
|
+
package-lock.json
|
|
8
|
+
yarn.lock
|
|
9
|
+
bun.lockb
|
|
10
|
+
|
|
11
|
+
# ─ Build artifacts
|
|
12
|
+
dist/
|
|
13
|
+
build/
|
|
14
|
+
.next/
|
|
15
|
+
.nuxt/
|
|
16
|
+
out/
|
|
17
|
+
|
|
18
|
+
# ─ Cache
|
|
19
|
+
.turbo/
|
|
20
|
+
.cache/
|
|
21
|
+
.parcel-cache/
|
|
22
|
+
*.tsbuildinfo
|
|
23
|
+
|
|
24
|
+
# ─ Coverage & reports
|
|
25
|
+
coverage/
|
|
26
|
+
.nyc_output/
|
|
27
|
+
|
|
28
|
+
# ─ Generated files
|
|
29
|
+
*.generated.ts
|
|
30
|
+
*.generated.js
|
|
31
|
+
*.d.ts.map
|
|
32
|
+
|
|
33
|
+
# ─ Minified files
|
|
34
|
+
*.min.js
|
|
35
|
+
*.min.css
|
|
36
|
+
|
|
37
|
+
# ─ Source maps
|
|
38
|
+
*.map
|
|
39
|
+
|
|
40
|
+
# ─ IDE / OS
|
|
41
|
+
.DS_Store
|
|
42
|
+
.idea/
|
|
43
|
+
.vscode/settings.json
|
|
44
|
+
|
|
45
|
+
# ─ Changelog (history, not context)
|
|
46
|
+
CHANGELOG.md
|
|
47
|
+
|
|
48
|
+
# ─ Web3 / Solidity Generated Files
|
|
49
|
+
artifacts/
|
|
50
|
+
cache/
|
|
51
|
+
cache_forge/
|
|
52
|
+
out/
|
|
53
|
+
out_forge/
|
|
54
|
+
typechain/
|
|
55
|
+
typechain-types/
|
|
56
|
+
broadcast/
|
|
57
|
+
broadcast_forge/
|
|
58
|
+
flatten/
|
|
59
|
+
flattened/
|
|
60
|
+
build/contracts/
|
|
61
|
+
# Common Foundry dependencies that kill context limits:
|
|
62
|
+
lib/forge-std/
|
|
63
|
+
lib/openzeppelin-contracts*/
|
|
64
|
+
lib/erc721a*/
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<!-- FNH: Template — Knowledge Item (metadata.json) | SECTIONS: Metadata, Artifacts | DEPS: none -->
|
|
2
|
+
<!-- Knowledge Item Template -->
|
|
3
|
+
<!-- Directory: .agents/knowledge/{{KI_NAME}}/ -->
|
|
4
|
+
|
|
5
|
+
<!-- FILE: metadata.json -->
|
|
6
|
+
{
|
|
7
|
+
"title": "{{KI_TITLE}}",
|
|
8
|
+
"summary": "{{KI_SUMMARY_1_2_SENTENCES}}",
|
|
9
|
+
"references": [
|
|
10
|
+
{
|
|
11
|
+
"type": "file",
|
|
12
|
+
"path": "artifacts/{{ARTIFACT_NAME}}.md"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
<!-- FILE: artifacts/{{ARTIFACT_NAME}}.md -->
|
|
18
|
+
|
|
19
|
+
# {{KI_TITLE}}
|
|
20
|
+
|
|
21
|
+
> {{KI_SUMMARY_1_2_SENTENCES}}
|
|
22
|
+
|
|
23
|
+
## {{SECTION_1}}
|
|
24
|
+
|
|
25
|
+
{{CONCRETE_SPECIFIC_INFORMATION}}
|
|
26
|
+
|
|
27
|
+
## {{SECTION_2}}
|
|
28
|
+
|
|
29
|
+
{{MORE_CONCRETE_INFORMATION}}
|
|
30
|
+
|
|
31
|
+
<!--
|
|
32
|
+
RULES FOR WRITING KNOWLEDGE ITEMS:
|
|
33
|
+
1. ATOMIC — One topic per KI. Not "everything about the project".
|
|
34
|
+
2. CONCRETE — Specific values, rules, patterns. Not "our API is modern".
|
|
35
|
+
3. ACTIONABLE — Agent should know WHAT TO DO after reading.
|
|
36
|
+
4. STRUCTURED — Headers, tables, code blocks. Easy to scan.
|
|
37
|
+
5. SMALL — Keep under 200 lines. Agent loads full KI into context.
|
|
38
|
+
|
|
39
|
+
GOOD EXAMPLE:
|
|
40
|
+
"API responses use: { data: T, error: null } | { data: null, error: { code, message } }"
|
|
41
|
+
|
|
42
|
+
BAD EXAMPLE:
|
|
43
|
+
"Our API supports many flexible response formats"
|
|
44
|
+
-->
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<!-- FNH: Template — ideal package.json | SECTIONS: Fields Tier, Sort Order | DEPS: strategy/package-json-guide.md -->
|
|
2
|
+
{
|
|
3
|
+
"name": "@{{SCOPE}}/{{PACKAGE_NAME}}",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "{{ONE_LINE_DESCRIPTION}}",
|
|
6
|
+
"private": true,
|
|
7
|
+
"type": "module",
|
|
8
|
+
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
|
|
12
|
+
"scripts": {
|
|
13
|
+
"dev": "{{DEV_COMMAND}}",
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"test": "vitest run",
|
|
16
|
+
"lint": "eslint src/"
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
"dependencies": {
|
|
20
|
+
{{RUNTIME_DEPENDENCIES}}
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
{{MINIMAL_DEV_DEPENDENCIES}}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<!-- FNH: Template — package README for new packages | EXPORTS: domain logic, API | DEPS: none -->
|
|
2
|
+
# packages/{{PACKAGE_NAME}}
|
|
3
|
+
|
|
4
|
+
> Package: {{PACKAGE_DESCRIPTION}} | SECTIONS: Source Structure, Scripts, Meta | DEPS: none
|
|
5
|
+
|
|
6
|
+
## Source Structure
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
src/
|
|
10
|
+
index.ts ← Public API exports
|
|
11
|
+
types.ts ← Type contracts (interfaces, DTOs)
|
|
12
|
+
{{FILE_TREE}}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Dependencies
|
|
16
|
+
|
|
17
|
+
| Package | Purpose |
|
|
18
|
+
|----|----|
|
|
19
|
+
| `@{{SCOPE}}/{{DEP_NAME}}` | {{DEP_PURPOSE}} |
|
|
20
|
+
|
|
21
|
+
## Public API
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
// Key exports from src/index.ts
|
|
25
|
+
export { {{EXPORTS}} } from './...';
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Environment Variables
|
|
29
|
+
|
|
30
|
+
| Variable | Required | Description |
|
|
31
|
+
|----|----|----|
|
|
32
|
+
| `{{ENV_VAR}}` | {{REQUIRED}} | {{ENV_DESC}} |
|
|
33
|
+
|
|
34
|
+
## Scripts
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Build
|
|
38
|
+
{{BUILD_CMD}}
|
|
39
|
+
|
|
40
|
+
# Test
|
|
41
|
+
{{TEST_CMD}}
|
|
42
|
+
|
|
43
|
+
# Lint
|
|
44
|
+
{{LINT_CMD}}
|
|
45
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<!-- FNH: Template — publish-meta.json for bulk metadata injection | SECTIONS: Shared Meta, Overrides | DEPS: tools/enrich-package-json.js -->
|
|
2
|
+
{
|
|
3
|
+
"_comment": "Publish metadata — injected into package.json before npm publish, stripped after",
|
|
4
|
+
|
|
5
|
+
"shared": {
|
|
6
|
+
"author": "{{AUTHOR_NAME}} <{{AUTHOR_EMAIL}}>",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"engines": {
|
|
9
|
+
"node": ">=18.0.0"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
"repositoryPattern": "git+https://github.com/{{ORG}}/{{REPO}}.git",
|
|
14
|
+
"homepagePattern": "https://github.com/{{ORG}}/{{REPO}}/tree/main/packages/{{package}}",
|
|
15
|
+
"bugsUrl": "https://github.com/{{ORG}}/{{REPO}}/issues",
|
|
16
|
+
|
|
17
|
+
"defaultFiles": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md",
|
|
20
|
+
"LICENSE"
|
|
21
|
+
],
|
|
22
|
+
|
|
23
|
+
"packages": {
|
|
24
|
+
"@{{SCOPE}}/core": {
|
|
25
|
+
"keywords": ["core", "domain", "entities"]
|
|
26
|
+
},
|
|
27
|
+
"@{{SCOPE}}/api": {
|
|
28
|
+
"keywords": ["api", "rest", "express"]
|
|
29
|
+
},
|
|
30
|
+
"@{{SCOPE}}/shared": {
|
|
31
|
+
"keywords": ["shared", "types", "utils"]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<!-- FNH: Template — skill definition (SKILL.md) | SECTIONS: Use, Prerequisites, Steps | DEPS: none -->
|
|
2
|
+
---
|
|
3
|
+
name: {{SKILL_NAME}}
|
|
4
|
+
description: >-
|
|
5
|
+
{{SKILL_DESCRIPTION_ONE_LINE}}
|
|
6
|
+
Use when {{TRIGGER_CONDITION}}.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# {{SKILL_TITLE}}
|
|
10
|
+
|
|
11
|
+
## When to Use
|
|
12
|
+
- {{TRIGGER_1}}
|
|
13
|
+
- {{TRIGGER_2}}
|
|
14
|
+
|
|
15
|
+
## When NOT to Use
|
|
16
|
+
- {{ANTI_TRIGGER_1}}
|
|
17
|
+
- {{ANTI_TRIGGER_2}}
|
|
18
|
+
|
|
19
|
+
## Prerequisites
|
|
20
|
+
- {{PREREQ_1}}
|
|
21
|
+
|
|
22
|
+
## Steps
|
|
23
|
+
|
|
24
|
+
1. {{STEP_1}}
|
|
25
|
+
2. {{STEP_2}}
|
|
26
|
+
3. {{STEP_3}}
|
|
27
|
+
4. Verify: `{{VERIFY_COMMAND}}`
|
|
28
|
+
|
|
29
|
+
## Template Code
|
|
30
|
+
|
|
31
|
+
### {{TEMPLATE_FILE_1}}
|
|
32
|
+
|
|
33
|
+
```{{LANGUAGE}}
|
|
34
|
+
{{TEMPLATE_CODE}}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Gotchas
|
|
38
|
+
|
|
39
|
+
- ⚠️ {{GOTCHA_1}}
|
|
40
|
+
- ⚠️ {{GOTCHA_2}}
|
|
41
|
+
|
|
42
|
+
<!--
|
|
43
|
+
RULES FOR WRITING SKILLS:
|
|
44
|
+
1. SELF-CONTAINED — Everything needed is in this file + assets/
|
|
45
|
+
2. SPECIFIC TRIGGERS — Clear "when to use" / "when NOT to use"
|
|
46
|
+
3. STEP-BY-STEP — Numbered steps, not prose
|
|
47
|
+
4. TEMPLATES — Copy-paste ready code
|
|
48
|
+
5. VERIFY — Always include a verification step
|
|
49
|
+
6. CONCISE — Agent context is limited. Don't waste it.
|
|
50
|
+
-->
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<!-- FNH: Template — executable workflow | SECTIONS: Steps, Annotations | DEPS: none -->
|
|
2
|
+
---
|
|
3
|
+
description: {{WORKFLOW_DESCRIPTION}}
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
{{TURBO_ANNOTATION}}
|
|
7
|
+
<!-- Use '// turbo-all' above to auto-approve ALL commands -->
|
|
8
|
+
<!-- Use '// turbo' above individual steps to auto-approve that step only -->
|
|
9
|
+
<!-- Omit both for manual approval of every command -->
|
|
10
|
+
|
|
11
|
+
1. {{STEP_1_DESCRIPTION}}
|
|
12
|
+
```bash
|
|
13
|
+
{{COMMAND_1}}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
2. {{STEP_2_DESCRIPTION}}
|
|
17
|
+
```bash
|
|
18
|
+
{{COMMAND_2}}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
3. Verify result:
|
|
22
|
+
```bash
|
|
23
|
+
{{VERIFY_COMMAND}}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
<!--
|
|
27
|
+
RULES FOR WRITING WORKFLOWS:
|
|
28
|
+
1. IDEMPOTENT — Running twice should not break anything
|
|
29
|
+
2. EXPLICIT — Every command fully specified (no "run the usual build")
|
|
30
|
+
3. VERIFIABLE — Last step always verifies success
|
|
31
|
+
4. SAFE — Use '// turbo' only for read-only/safe commands
|
|
32
|
+
5. PARAMETERIZED — Use {{PLACEHOLDERS}} for variable parts
|
|
33
|
+
-->
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tool: analyze-package-json — Analyze package.json files for AI-readiness | DEPS: none
|
|
3
|
+
# USAGE: bash tools/analyze-package-json.sh /path/to/monorepo
|
|
4
|
+
# OUTPUT: analysis report in scout-report.md
|
|
5
|
+
# MODE: read-only analysis
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
source "$(dirname "$0")/shared/config.sh"
|
|
10
|
+
|
|
11
|
+
TARGET="${1:-.}"
|
|
12
|
+
|
|
13
|
+
if [[ "$1" == "--help" || "$1" == "-h" ]]; then
|
|
14
|
+
echo "Usage: bash tools/analyze-package-json.sh /path/to/monorepo"
|
|
15
|
+
echo ""
|
|
16
|
+
echo "Analyzes all package.json files in a monorepo for AI-agent readiness."
|
|
17
|
+
echo "Checks for:"
|
|
18
|
+
echo " - Inline configs (jest, eslint, prettier, babel) — should be separate files"
|
|
19
|
+
echo " - Missing critical fields (name, description, scripts)"
|
|
20
|
+
echo " - Excessive dependencies"
|
|
21
|
+
echo " - Field ordering"
|
|
22
|
+
echo " - Token cost estimation"
|
|
23
|
+
exit 0
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
if [[ ! -d "$TARGET" ]]; then
|
|
27
|
+
echo "❌ Error: '$TARGET' is not a directory"
|
|
28
|
+
exit 1
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
echo "📦 Analyzing package.json files in: $TARGET"
|
|
32
|
+
echo "════════════════════════════════════════════════════════"
|
|
33
|
+
|
|
34
|
+
TOTAL_ISSUES=0
|
|
35
|
+
TOTAL_FILES=0
|
|
36
|
+
|
|
37
|
+
# Find all package.json files (excluding node_modules)
|
|
38
|
+
find "$TARGET" -name "package.json" \
|
|
39
|
+
-not -path "*/node_modules/*" -not -path "*/lib/forge-std/*" -not -path "*/lib/openzeppelin-contracts*" -not -path "*/lib/erc721a*" \
|
|
40
|
+
-not -path "*/dist/*" \
|
|
41
|
+
-not -path "*/.git/*" \
|
|
42
|
+
| sort \
|
|
43
|
+
| while read -r pkg_file; do
|
|
44
|
+
|
|
45
|
+
TOTAL_FILES=$((TOTAL_FILES + 1))
|
|
46
|
+
ISSUES=0
|
|
47
|
+
|
|
48
|
+
rel_path="${pkg_file#$TARGET/}"
|
|
49
|
+
line_count=$(wc -l < "$pkg_file" | tr -d ' ')
|
|
50
|
+
byte_count=$(wc -c < "$pkg_file" | tr -d ' ')
|
|
51
|
+
token_estimate=$((byte_count / 4))
|
|
52
|
+
|
|
53
|
+
echo ""
|
|
54
|
+
echo "────────────────────────────────────────"
|
|
55
|
+
echo "📄 $rel_path"
|
|
56
|
+
echo " Lines: $line_count | Tokens: ~$token_estimate"
|
|
57
|
+
echo ""
|
|
58
|
+
|
|
59
|
+
# ── Tier 1: Critical fields check ──
|
|
60
|
+
|
|
61
|
+
pkg_name=$(python3 -c "import json; d=json.load(open('$pkg_file')); print(d.get('name',''))" 2>/dev/null || echo "")
|
|
62
|
+
pkg_desc=$(python3 -c "import json; d=json.load(open('$pkg_file')); print(d.get('description',''))" 2>/dev/null || echo "")
|
|
63
|
+
has_scripts=$(python3 -c "import json; d=json.load(open('$pkg_file')); print('yes' if d.get('scripts') else 'no')" 2>/dev/null || echo "no")
|
|
64
|
+
has_main=$(python3 -c "import json; d=json.load(open('$pkg_file')); print('yes' if d.get('main') or d.get('exports') else 'no')" 2>/dev/null || echo "no")
|
|
65
|
+
has_type=$(python3 -c "import json; d=json.load(open('$pkg_file')); print('yes' if d.get('type') else 'no')" 2>/dev/null || echo "no")
|
|
66
|
+
|
|
67
|
+
if [[ -z "$pkg_name" ]]; then
|
|
68
|
+
echo " 🔴 MISSING: name"
|
|
69
|
+
ISSUES=$((ISSUES + 1))
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
if [[ -z "$pkg_desc" ]]; then
|
|
73
|
+
echo " 🟡 MISSING: description — agent won't understand purpose"
|
|
74
|
+
ISSUES=$((ISSUES + 1))
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
if [[ "$has_scripts" == "no" ]]; then
|
|
78
|
+
echo " 🟡 MISSING: scripts — agent won't know how to build/test"
|
|
79
|
+
ISSUES=$((ISSUES + 1))
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
if [[ "$has_main" == "no" ]]; then
|
|
83
|
+
echo " 🟢 MISSING: main/exports — no entry point defined"
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
if [[ "$has_type" == "no" ]]; then
|
|
87
|
+
echo " 🟢 MISSING: type — module system unclear (CJS assumed)"
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
# ── Tier 4: Inline configs check ──
|
|
91
|
+
|
|
92
|
+
python3 -c "
|
|
93
|
+
import json, sys
|
|
94
|
+
|
|
95
|
+
d = json.load(open('$pkg_file'))
|
|
96
|
+
issues = 0
|
|
97
|
+
|
|
98
|
+
# Inline config detection
|
|
99
|
+
inline_configs = {
|
|
100
|
+
'jest': 'jest.config.ts',
|
|
101
|
+
'eslintConfig': '.eslintrc.js or eslint.config.js',
|
|
102
|
+
'prettier': '.prettierrc',
|
|
103
|
+
'babel': 'babel.config.js',
|
|
104
|
+
'browserslist': '.browserslistrc',
|
|
105
|
+
'lint-staged': '.lintstagedrc',
|
|
106
|
+
'husky': '.husky/',
|
|
107
|
+
'commitlint': 'commitlint.config.js',
|
|
108
|
+
'stylelint': '.stylelintrc',
|
|
109
|
+
'postcss': 'postcss.config.js',
|
|
110
|
+
'ava': 'ava.config.js',
|
|
111
|
+
'mocha': '.mocharc.yml',
|
|
112
|
+
'nyc': '.nycrc',
|
|
113
|
+
'c8': 'c8 CLI flags',
|
|
114
|
+
'release-it': '.release-it.json',
|
|
115
|
+
'standard-version': '.versionrc',
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
for field, target in inline_configs.items():
|
|
119
|
+
if field in d:
|
|
120
|
+
val = d[field]
|
|
121
|
+
lines = len(json.dumps(val, indent=2).split('\n'))
|
|
122
|
+
tokens = len(json.dumps(val)) // 4
|
|
123
|
+
print(f' 🔴 INLINE CONFIG: \"{field}\" ({lines} lines, ~{tokens} tokens) → move to {target}')
|
|
124
|
+
issues += 1
|
|
125
|
+
|
|
126
|
+
# Dependency counts
|
|
127
|
+
deps = d.get('dependencies', {})
|
|
128
|
+
dev_deps = d.get('devDependencies', {})
|
|
129
|
+
peer_deps = d.get('peerDependencies', {})
|
|
130
|
+
|
|
131
|
+
dep_count = len(deps)
|
|
132
|
+
dev_dep_count = len(dev_deps)
|
|
133
|
+
|
|
134
|
+
if dep_count > 25:
|
|
135
|
+
print(f' 🟡 MANY dependencies: {dep_count} — consider splitting package')
|
|
136
|
+
issues += 1
|
|
137
|
+
elif dep_count > 50:
|
|
138
|
+
print(f' 🔴 TOO MANY dependencies: {dep_count} — package does too much')
|
|
139
|
+
issues += 1
|
|
140
|
+
|
|
141
|
+
if dev_dep_count > 20:
|
|
142
|
+
print(f' 🟡 MANY devDependencies: {dev_dep_count} — consider hoisting to root')
|
|
143
|
+
issues += 1
|
|
144
|
+
|
|
145
|
+
# Resolutions/overrides
|
|
146
|
+
if 'resolutions' in d:
|
|
147
|
+
res_count = len(d['resolutions'])
|
|
148
|
+
res_tokens = len(json.dumps(d['resolutions'])) // 4
|
|
149
|
+
if res_count > 5:
|
|
150
|
+
print(f' 🟡 resolutions: {res_count} entries (~{res_tokens} tokens) — keep only in root')
|
|
151
|
+
issues += 1
|
|
152
|
+
|
|
153
|
+
if 'overrides' in d:
|
|
154
|
+
ovr_count = len(d['overrides']) if isinstance(d['overrides'], dict) else 0
|
|
155
|
+
ovr_tokens = len(json.dumps(d['overrides'])) // 4
|
|
156
|
+
if ovr_count > 5:
|
|
157
|
+
print(f' 🟡 overrides: {ovr_count} entries (~{ovr_tokens} tokens) — keep only in root')
|
|
158
|
+
issues += 1
|
|
159
|
+
|
|
160
|
+
# Scripts count
|
|
161
|
+
scripts = d.get('scripts', {})
|
|
162
|
+
script_count = len(scripts)
|
|
163
|
+
if script_count > 12:
|
|
164
|
+
print(f' 🟡 TOO MANY scripts: {script_count} — simplify to 4-8 key scripts')
|
|
165
|
+
issues += 1
|
|
166
|
+
|
|
167
|
+
# Long script values
|
|
168
|
+
for name, cmd in scripts.items():
|
|
169
|
+
if len(cmd) > 150:
|
|
170
|
+
print(f' 🟡 LONG script \"{name}\": {len(cmd)} chars — move to scripts/*.sh')
|
|
171
|
+
issues += 1
|
|
172
|
+
|
|
173
|
+
# Size check
|
|
174
|
+
if lines_count := len(json.dumps(d, indent=2).split('\n')):
|
|
175
|
+
if lines_count > 60:
|
|
176
|
+
print(f' 🔴 FILE TOO LARGE: {lines_count} lines — target ≤30 lines')
|
|
177
|
+
issues += 1
|
|
178
|
+
elif lines_count > 30:
|
|
179
|
+
print(f' 🟡 FILE LARGE: {lines_count} lines — target ≤30 lines')
|
|
180
|
+
issues += 1
|
|
181
|
+
|
|
182
|
+
# Token budget assessment
|
|
183
|
+
total_tokens = len(json.dumps(d)) // 4
|
|
184
|
+
if total_tokens > 2000:
|
|
185
|
+
emoji = '🔴'
|
|
186
|
+
label = 'HARMFUL'
|
|
187
|
+
elif total_tokens > 800:
|
|
188
|
+
emoji = '🟡'
|
|
189
|
+
label = 'HIGH'
|
|
190
|
+
elif total_tokens > 300:
|
|
191
|
+
emoji = '🟢'
|
|
192
|
+
label = 'OK'
|
|
193
|
+
else:
|
|
194
|
+
emoji = '⭐'
|
|
195
|
+
label = 'EXCELLENT'
|
|
196
|
+
|
|
197
|
+
print(f'')
|
|
198
|
+
print(f' {emoji} Context cost: ~{total_tokens} tokens ({label})')
|
|
199
|
+
print(f' deps: {dep_count} | devDeps: {dev_dep_count} | scripts: {script_count}')
|
|
200
|
+
|
|
201
|
+
if issues == 0:
|
|
202
|
+
print(f' ✅ No issues found')
|
|
203
|
+
|
|
204
|
+
sys.exit(issues)
|
|
205
|
+
" 2>/dev/null || true
|
|
206
|
+
|
|
207
|
+
done
|
|
208
|
+
|
|
209
|
+
echo ""
|
|
210
|
+
echo "════════════════════════════════════════════════════════"
|
|
211
|
+
echo "✅ Analysis complete"
|
|
212
|
+
echo ""
|
|
213
|
+
echo "📖 See strategy/package-json-guide.md for full optimization guide"
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tool: analyze-structure — Analyze monorepo structure and generate metrics | DEPS: none
|
|
3
|
+
# USAGE: bash tools/analyze-structure.sh /path/to/monorepo
|
|
4
|
+
# OUTPUT: structural metrics and directory map
|
|
5
|
+
# MODE: read-only analysis
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
source "$(dirname "$0")/shared/config.sh"
|
|
10
|
+
|
|
11
|
+
TARGET="${1:-.}"
|
|
12
|
+
DIVIDER="────────────────────────────────────────"
|
|
13
|
+
|
|
14
|
+
if [[ "$1" == "--help" || "$1" == "-h" ]]; then
|
|
15
|
+
echo "Usage: bash tools/analyze-structure.sh /path/to/monorepo"
|
|
16
|
+
echo ""
|
|
17
|
+
echo "Analyzes monorepo structure and outputs key metrics:"
|
|
18
|
+
echo " - Total files and directories"
|
|
19
|
+
echo " - Files per directory (top 10 densest)"
|
|
20
|
+
echo " - Deepest nesting level"
|
|
21
|
+
echo " - Package inventory with README/index.ts/types.ts presence"
|
|
22
|
+
echo " - Overall health indicators"
|
|
23
|
+
exit 0
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
if [[ ! -d "$TARGET" ]]; then
|
|
27
|
+
echo "❌ Error: '$TARGET' is not a directory"
|
|
28
|
+
exit 1
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
echo "🔍 Analyzing: $TARGET"
|
|
32
|
+
echo "$DIVIDER"
|
|
33
|
+
|
|
34
|
+
# Exclude common non-source directories
|
|
35
|
+
EXCLUDE="-not -path '*/node_modules/*' -not -path '*/lib/forge-std/*' -not -path '*/lib/openzeppelin-contracts*' -not -path '*/lib/erc721a*' -not -path '*/.git/*' -not -path '*/dist/*' -not -path '*/build/*' -not -path '*/.next/*' -not -path '*/.turbo/*'"
|
|
36
|
+
|
|
37
|
+
# 1. Total file counts
|
|
38
|
+
echo ""
|
|
39
|
+
echo "📊 FILE METRICS"
|
|
40
|
+
echo "$DIVIDER"
|
|
41
|
+
|
|
42
|
+
TOTAL_FILES=$(eval "find '$TARGET' -type f $EXCLUDE" | wc -l | tr -d ' ')
|
|
43
|
+
TOTAL_DIRS=$(eval "find '$TARGET' -type d $EXCLUDE" | wc -l | tr -d ' ')
|
|
44
|
+
SRC_FILES=$(eval "find '$TARGET' -type f \( -name '*.ts' -o -name '*.tsx' -o -name '*.js' -o -name '*.jsx' -o -name '*.sol' \) $EXCLUDE" | wc -l | tr -d ' ')
|
|
45
|
+
|
|
46
|
+
echo "Total files: $TOTAL_FILES"
|
|
47
|
+
echo "Total directories: $TOTAL_DIRS"
|
|
48
|
+
echo "Source files: $SRC_FILES (ts/tsx/js/jsx)"
|
|
49
|
+
|
|
50
|
+
# 2. Deepest nesting
|
|
51
|
+
MAX_DEPTH=$(eval "find '$TARGET' -type f $EXCLUDE" | awk -F/ '{print NF}' | sort -n | tail -1)
|
|
52
|
+
echo "Max nesting depth: $MAX_DEPTH levels"
|
|
53
|
+
|
|
54
|
+
# 3. Densest directories (most files in one dir)
|
|
55
|
+
echo ""
|
|
56
|
+
echo "📁 DENSEST DIRECTORIES (top 10)"
|
|
57
|
+
echo "$DIVIDER"
|
|
58
|
+
|
|
59
|
+
eval "find '$TARGET' -type d $EXCLUDE" | while read -r dir; do
|
|
60
|
+
count=$(find "$dir" -maxdepth 1 -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
61
|
+
if [[ $count -gt 0 ]]; then
|
|
62
|
+
echo "$count $dir"
|
|
63
|
+
fi
|
|
64
|
+
done | sort -rn | head -10
|
|
65
|
+
|
|
66
|
+
# 4. Package inventory
|
|
67
|
+
echo ""
|
|
68
|
+
echo "📦 PACKAGE INVENTORY"
|
|
69
|
+
echo "$DIVIDER"
|
|
70
|
+
|
|
71
|
+
for pkg_dir in "$TARGET"/packages/* "$TARGET"/apps/*; do
|
|
72
|
+
if [[ -d "$pkg_dir" ]]; then
|
|
73
|
+
pkg_name=$(basename "$pkg_dir")
|
|
74
|
+
has_readme="❌"
|
|
75
|
+
has_index="❌"
|
|
76
|
+
has_types="❌"
|
|
77
|
+
has_tests="❌"
|
|
78
|
+
|
|
79
|
+
[[ -f "$pkg_dir/README.md" ]] && has_readme="✅"
|
|
80
|
+
[[ -f "$pkg_dir/src/index.ts" || -f "$pkg_dir/src/index.js" ]] && has_index="✅"
|
|
81
|
+
[[ -f "$pkg_dir/src/types.ts" || -d "$pkg_dir/src/types" ]] && has_types="✅"
|
|
82
|
+
[[ -d "$pkg_dir/tests" || -d "$pkg_dir/__tests__" || -d "$pkg_dir/test" ]] && has_tests="✅"
|
|
83
|
+
|
|
84
|
+
file_count=$(eval "find '$pkg_dir' -type f $EXCLUDE" | wc -l | tr -d ' ')
|
|
85
|
+
|
|
86
|
+
echo "$pkg_name: ${file_count} files | README:${has_readme} index:${has_index} types:${has_types} tests:${has_tests}"
|
|
87
|
+
fi
|
|
88
|
+
done
|
|
89
|
+
|
|
90
|
+
# 5. AGENTS.md check
|
|
91
|
+
echo ""
|
|
92
|
+
echo "🧠 AI-READINESS"
|
|
93
|
+
echo "$DIVIDER"
|
|
94
|
+
|
|
95
|
+
[[ -f "$TARGET/.agents/AGENTS.md" ]] && echo "AGENTS.md: ✅" || echo "AGENTS.md: ❌ MISSING"
|
|
96
|
+
[[ -d "$TARGET/.agents/knowledge" ]] && echo "Knowledge Items: ✅ ($(ls "$TARGET/.agents/knowledge" 2>/dev/null | wc -l | tr -d ' ') items)" || echo "Knowledge Items: ❌ MISSING"
|
|
97
|
+
[[ -d "$TARGET/.agents/skills" ]] && echo "Skills: ✅ ($(ls "$TARGET/.agents/skills" 2>/dev/null | wc -l | tr -d ' ') skills)" || echo "Skills: ❌ MISSING"
|
|
98
|
+
[[ -d "$TARGET/.agents/workflows" ]] && echo "Workflows: ✅ ($(ls "$TARGET/.agents/workflows" 2>/dev/null | wc -l | tr -d ' ') workflows)" || echo "Workflows: ❌ MISSING"
|
|
99
|
+
|
|
100
|
+
echo ""
|
|
101
|
+
echo "✅ Analysis complete"
|