@pipemd-core/pipemd 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.
Files changed (96) hide show
  1. package/AI_SETUP_PIPEMD.md +184 -0
  2. package/CHANGELOG.md +47 -0
  3. package/LICENSE +15 -0
  4. package/README.md +535 -0
  5. package/dist/index.js +6647 -0
  6. package/dist/plugins/opencode-server.js +235 -0
  7. package/dist/plugins/opencode-tui.js +914 -0
  8. package/dist/templates/agent-decision-tree.md +113 -0
  9. package/dist/templates/static-rules.md +7 -0
  10. package/package.json +68 -0
  11. package/scripts/C-CPP/architecture/arch.sh +229 -0
  12. package/scripts/C-CPP/lib/limit.sh +146 -0
  13. package/scripts/C-CPP/project/class-diagram.sh +96 -0
  14. package/scripts/C-CPP/project/cmake-targets.sh +68 -0
  15. package/scripts/C-CPP/project/deps.sh +44 -0
  16. package/scripts/C-CPP/project/find-todos.sh +6 -0
  17. package/scripts/C-CPP/project/include-graph.sh +110 -0
  18. package/scripts/C-CPP/project/interfaces.sh +108 -0
  19. package/scripts/C-CPP/project/tree.sh +5 -0
  20. package/scripts/C-CPP/quality/lint.sh +14 -0
  21. package/scripts/C-CPP/quality/test-summary.sh +22 -0
  22. package/scripts/C-CPP/quality/type-check.sh +26 -0
  23. package/scripts/DevOps/architecture/arch.sh +186 -0
  24. package/scripts/DevOps/devops/aws-context.sh +34 -0
  25. package/scripts/DevOps/devops/docker-stats.sh +42 -0
  26. package/scripts/DevOps/devops/k8s-unhealthy.sh +41 -0
  27. package/scripts/DevOps/devops/tf-state.sh +65 -0
  28. package/scripts/DevOps/lib/limit.sh +143 -0
  29. package/scripts/Generic/architecture/arch.sh +570 -0
  30. package/scripts/Generic/lib/limit.sh +140 -0
  31. package/scripts/Go/architecture/arch.sh +79 -0
  32. package/scripts/Go/lib/limit.sh +142 -0
  33. package/scripts/Go/project/deps.sh +35 -0
  34. package/scripts/Go/project/find-todos.sh +6 -0
  35. package/scripts/Go/project/go-interfaces.sh +18 -0
  36. package/scripts/Go/project/go-packages.sh +28 -0
  37. package/scripts/Go/project/tree.sh +5 -0
  38. package/scripts/Go/quality/lint.sh +16 -0
  39. package/scripts/Go/quality/test-summary.sh +16 -0
  40. package/scripts/Go/quality/type-check.sh +16 -0
  41. package/scripts/Node-TypeScript/api/express-routes.sh +14 -0
  42. package/scripts/Node-TypeScript/api/nest-controllers.sh +18 -0
  43. package/scripts/Node-TypeScript/architecture/arch.sh +174 -0
  44. package/scripts/Node-TypeScript/frontend/angular-routes.sh +15 -0
  45. package/scripts/Node-TypeScript/frontend/nextjs-app-router.sh +13 -0
  46. package/scripts/Node-TypeScript/frontend/react-components.sh +20 -0
  47. package/scripts/Node-TypeScript/lib/limit.sh +146 -0
  48. package/scripts/Node-TypeScript/project/deps.sh +15 -0
  49. package/scripts/Node-TypeScript/project/find-todos.sh +6 -0
  50. package/scripts/Node-TypeScript/quality/lint.sh +10 -0
  51. package/scripts/Node-TypeScript/quality/test-summary.sh +39 -0
  52. package/scripts/Node-TypeScript/quality/type-check.sh +10 -0
  53. package/scripts/Python/api/fastapi-routes.sh +12 -0
  54. package/scripts/Python/architecture/arch.sh +220 -0
  55. package/scripts/Python/db/django-models.sh +12 -0
  56. package/scripts/Python/db/sqlalchemy.sh +17 -0
  57. package/scripts/Python/lib/limit.sh +144 -0
  58. package/scripts/Python/project/deps.sh +28 -0
  59. package/scripts/Python/project/find-todos.sh +6 -0
  60. package/scripts/Python/quality/lint.sh +13 -0
  61. package/scripts/Python/quality/test-summary.sh +11 -0
  62. package/scripts/Python/quality/type-check.sh +10 -0
  63. package/scripts/Rust/architecture/arch.sh +176 -0
  64. package/scripts/Rust/lib/limit.sh +142 -0
  65. package/scripts/Rust/project/cargo-deps.sh +42 -0
  66. package/scripts/Rust/project/cargo-features.sh +26 -0
  67. package/scripts/Rust/project/find-todos.sh +6 -0
  68. package/scripts/Rust/project/tree.sh +5 -0
  69. package/scripts/Rust/quality/lint.sh +16 -0
  70. package/scripts/Rust/quality/test-summary.sh +16 -0
  71. package/scripts/Rust/quality/type-check.sh +16 -0
  72. package/scripts/Shared/api/express-routes.sh +11 -0
  73. package/scripts/Shared/api/fastapi-routes.sh +10 -0
  74. package/scripts/Shared/api/nest-controllers.sh +22 -0
  75. package/scripts/Shared/architecture/normalize.sh +178 -0
  76. package/scripts/Shared/crew/crew.sh +15 -0
  77. package/scripts/Shared/db/django-models.sh +11 -0
  78. package/scripts/Shared/db/prisma.sh +33 -0
  79. package/scripts/Shared/db/sqlalchemy.sh +12 -0
  80. package/scripts/Shared/frontend/angular-routes.sh +11 -0
  81. package/scripts/Shared/frontend/nextjs-app-router.sh +13 -0
  82. package/scripts/Shared/frontend/react-components.sh +11 -0
  83. package/scripts/Shared/git/diff-stat.sh +6 -0
  84. package/scripts/Shared/git/git-branch.sh +16 -0
  85. package/scripts/Shared/git/git-log.sh +6 -0
  86. package/scripts/Shared/git/git-status.sh +6 -0
  87. package/scripts/Shared/lib/limit.sh +144 -0
  88. package/scripts/Shared/project/compose-md.sh +182 -0
  89. package/scripts/Shared/project/deps.sh +69 -0
  90. package/scripts/Shared/project/find-todos.sh +6 -0
  91. package/scripts/Shared/project/tree.sh +5 -0
  92. package/scripts/Shared/quality/lint.sh +81 -0
  93. package/scripts/Shared/quality/test-summary.sh +103 -0
  94. package/scripts/Shared/quality/type-check.sh +114 -0
  95. package/scripts/copy-plugins.mjs +4 -0
  96. package/scripts/copy-templates.mjs +5 -0
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env bash
2
+ set -uo pipefail
3
+ # CMake target metadata — executables, libraries, and link dependencies
4
+ source "$(dirname "$0")/../lib/limit.sh"
5
+
6
+ if ! command -v python3 &>/dev/null; then
7
+ echo "python3 is required for CMake parsing"
8
+ exit 0
9
+ fi
10
+
11
+ out=""
12
+ tmpfile=$(mktemp)
13
+
14
+ find . -name "CMakeLists.txt" \
15
+ -not -path "*/build/*" -not -path "*/.git/*" \
16
+ -not -path "*/cmake-build-*/*" -not -path "*/_deps/*" \
17
+ 2>/dev/null | head -20 | while IFS= read -r cmake_file; do
18
+ rel="${cmake_file#./}"
19
+ dir="$(dirname "$rel")"
20
+ [ "$dir" = "." ] && dir="(root)"
21
+
22
+ PMDFILE="$cmake_file" PMDDIR="$dir" python3 -c '
23
+ import sys, re, os
24
+
25
+ cmake_file = os.environ.get("PMDFILE", "")
26
+ dir_label = os.environ.get("PMDDIR", "")
27
+
28
+ try:
29
+ with open(cmake_file, "r", errors="replace") as f:
30
+ content = f.read()
31
+ except Exception:
32
+ sys.exit(0)
33
+
34
+ content = re.sub(r"#.*", "", content)
35
+ content = content.replace("\\\n", " ")
36
+ content = re.sub(r"\s+", " ", content)
37
+
38
+ targets = []
39
+ links = []
40
+
41
+ for m in re.finditer(r"add_executable\s*\(\s*([A-Za-z_]\w*)", content):
42
+ targets.append(f"exe:{m.group(1)}")
43
+
44
+ for m in re.finditer(r"add_library\s*\(\s*([A-Za-z_]\w*)\s+(STATIC|SHARED|MODULE|OBJECT|INTERFACE)", content):
45
+ targets.append(f"lib:{m.group(1)}({m.group(2)})")
46
+
47
+ for m in re.finditer(r"target_link_libraries\s*\(\s*([A-Za-z_]\w*)\s+(PUBLIC|PRIVATE|INTERFACE)\s+(.*?)\)", content):
48
+ links.append(f"{m.group(1)} <- {m.group(2)}: {m.group(3).strip()}")
49
+
50
+ if not targets and not links:
51
+ sys.exit(0)
52
+
53
+ print(f"[dir] {dir_label}")
54
+ for t in targets:
55
+ print(f" + {t}")
56
+ for l in links:
57
+ print(f" - {l}")
58
+ ' >> "$tmpfile" 2>/dev/null
59
+ done
60
+
61
+ out=$(cat "$tmpfile")
62
+ rm -f "$tmpfile"
63
+
64
+ if [ -z "$out" ]; then
65
+ echo "No CMake targets found"
66
+ exit 0
67
+ fi
68
+ limit_output "$out" "$MAX_CMAKE" "$(echo "$out" | head -10 && echo "... and more CMake targets")"
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env bash
2
+ set -uo pipefail
3
+ # C/C++ dependency detection — Makefile, CMake, Conan, vcpkg
4
+ source "$(dirname "$0")/../lib/limit.sh"
5
+
6
+ if [ -f CMakeLists.txt ]; then
7
+ out=$(grep -E '^\s*find_package|^\s*FetchContent_Declare|^\s*target_link_libraries' CMakeLists.txt 2>/dev/null | head -"$MAX_DEPS")
8
+ if [ -n "$out" ]; then
9
+ echo "CMake dependencies:"
10
+ echo "$out"
11
+ exit 0
12
+ fi
13
+ fi
14
+
15
+ if [ -f Makefile ] || [ -f makefile ]; then
16
+ makefile="${makefile:-Makefile}"
17
+ [ -f makefile ] && makefile="makefile"
18
+ out=$(grep -E '^\s*(include|require|load|use)' "$makefile" 2>/dev/null | head -"$MAX_DEPS")
19
+ if [ -n "$out" ]; then
20
+ echo "Makefile dependencies:"
21
+ echo "$out"
22
+ exit 0
23
+ fi
24
+ fi
25
+
26
+ if [ -f conanfile.txt ]; then
27
+ out=$(grep -E '^\s*[a-zA-Z]' conanfile.txt 2>/dev/null | head -"$MAX_DEPS")
28
+ if [ -n "$out" ]; then
29
+ echo "Conan dependencies:"
30
+ echo "$out"
31
+ exit 0
32
+ fi
33
+ fi
34
+
35
+ if [ -f vcpkg.json ]; then
36
+ out=$(node -e "try{const p=require('./vcpkg.json');console.log((p.dependencies||[]).join('\n'))}catch{}" 2>/dev/null)
37
+ if [ -n "$out" ]; then
38
+ echo "vcpkg dependencies:"
39
+ echo "$out"
40
+ exit 0
41
+ fi
42
+ fi
43
+
44
+ echo "No recognized C/C++ dependency file found"
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ set -uo pipefail
3
+ # Find TODO, FIXME, HACK in C/C++ source files
4
+ source "$(dirname "$0")/../lib/limit.sh"
5
+ out=$(grep -rn --include="*.c" --include="*.cpp" --include="*.cc" --include="*.cxx" --include="*.h" --include="*.hpp" --include="*.hxx" 'TODO\|FIXME\|HACK' . 2>/dev/null | grep -v '/.git/' | grep -v '/.pipemd/' | grep -v '/build/' | grep -v '/cmake-build-' | grep -v '/_deps/')
6
+ limit_output "$out" "$MAX_TODOS" "$(echo "$out" | head -3 && echo "... and $(($(echo "$out" | wc -l) - 3)) more items")"
@@ -0,0 +1,110 @@
1
+ #!/usr/bin/env bash
2
+ set -uo pipefail
3
+ # Include graph — external and standard library header dependencies
4
+ source "$(dirname "$0")/../lib/limit.sh"
5
+
6
+ if ! command -v python3 &>/dev/null; then
7
+ echo "python3 is required for C++ include graph extraction"
8
+ exit 0
9
+ fi
10
+
11
+ SOURCES=$(find . -type f \( -name "*.cpp" -o -name "*.cc" -o -name "*.cxx" -o -name "*.h" -o -name "*.hpp" -o -name "*.hxx" \) \
12
+ -not -path "*/build/*" -not -path "*/.git/*" -not -path "*/cmake-build-*/*" \
13
+ -not -path "*/_deps/*" -not -path "*/third_party/*" -not -path "*/external/*" \
14
+ 2>/dev/null | head -50)
15
+
16
+ if [ -z "$SOURCES" ]; then
17
+ echo "No C/C++ source files found"
18
+ exit 0
19
+ fi
20
+
21
+ echo "$SOURCES" | PMDMAX="${MAX_INCLUDE:-20}" python3 -c "
22
+ import sys, os, re
23
+ from collections import defaultdict
24
+
25
+ MAX = int(os.environ.get('PMDMAX', '20'))
26
+
27
+ STANDARD_HEADERS = {
28
+ 'algorithm', 'array', 'atomic', 'bitset', 'cassert', 'ccomplex',
29
+ 'cctype', 'cerrno', 'cfenv', 'cfloat', 'chrono', 'cinttypes',
30
+ 'ciso646', 'climits', 'clocale', 'cmath', 'codecvt', 'compare',
31
+ 'complex', 'concepts', 'condition_variable', 'coroutine', 'csetjmp',
32
+ 'csignal', 'cstdalign', 'cstdarg', 'cstdbool', 'cstddef', 'cstdint',
33
+ 'cstdio', 'cstdlib', 'cstring', 'ctgmath', 'ctime', 'cuchar',
34
+ 'cwchar', 'cwctype', 'deque', 'exception', 'execution', 'filesystem',
35
+ 'format', 'forward_list', 'fstream', 'functional', 'future',
36
+ 'initializer_list', 'iomanip', 'ios', 'iosfwd', 'iostream',
37
+ 'istream', 'iterator', 'limits', 'list', 'locale', 'map', 'memory',
38
+ 'memory_resource', 'mutex', 'new', 'numbers', 'numeric', 'optional',
39
+ 'ostream', 'queue', 'random', 'ranges', 'ratio', 'regex', 'scoped_allocator',
40
+ 'set', 'shared_mutex', 'span', 'sstream', 'stack', 'stdexcept',
41
+ 'streambuf', 'string', 'string_view', 'syncstream', 'system_error',
42
+ 'thread', 'tuple', 'type_traits', 'typeindex', 'typeinfo', 'unordered_map',
43
+ 'unordered_set', 'utility', 'valarray', 'variant', 'vector', 'version',
44
+ }
45
+
46
+ KNOWN_LIBS = {'boost', 'gtest', 'gmock', 'fmt', 'spdlog', 'nlohmann', 'openssl', 'curl', 'zlib', 'pthread', 'dlfcn'}
47
+
48
+ ext_re = re.compile(r'^\s*#\s*include\s*<([^>]+)>', re.MULTILINE)
49
+ local_re = re.compile(r'^\s*#\s*include\s*\x22([^\x22]+)\x22', re.MULTILINE)
50
+
51
+ ext_count = defaultdict(int)
52
+ ext_includes = defaultdict(set)
53
+ std_count = defaultdict(int)
54
+ local_includes = defaultdict(set)
55
+
56
+ for line in sys.stdin:
57
+ hdr = line.strip()
58
+ if not hdr or not os.path.isfile(hdr):
59
+ continue
60
+ try:
61
+ with open(hdr, 'r', errors='replace') as f:
62
+ content = f.read()
63
+ except Exception:
64
+ continue
65
+
66
+ basename = os.path.basename(hdr)
67
+
68
+ for m in ext_re.finditer(content):
69
+ header = m.group(1)
70
+ first_part = header.split('/')[0] if '/' in header else header
71
+ if header in STANDARD_HEADERS:
72
+ std_count[header] += 1
73
+ elif first_part in KNOWN_LIBS:
74
+ ext_count[first_part] += 1
75
+ ext_includes[first_part].add(header)
76
+ else:
77
+ ext_count[header] += 1
78
+ ext_includes[header].add(header)
79
+
80
+ for m in local_re.finditer(content):
81
+ inc = m.group(1)
82
+ local_includes[basename].add(inc)
83
+
84
+ lines = []
85
+ if std_count:
86
+ lines.append('Standard Library:')
87
+ for h in sorted(std_count, key=lambda x: -std_count[x])[:MAX]:
88
+ lines.append(f' <{h}> ({std_count[h]} files)')
89
+
90
+ if ext_count:
91
+ lines.append('')
92
+ lines.append('External Dependencies:')
93
+ for h in sorted(ext_count, key=lambda x: -ext_count[x])[:MAX]:
94
+ headers = ', '.join(sorted(ext_includes[h])[:3])
95
+ if len(ext_includes[h]) > 3:
96
+ headers += f' (+{len(ext_includes[h])-3} more)'
97
+ lines.append(f' {h} ({ext_count[h]} refs): {headers}')
98
+
99
+ if local_includes:
100
+ lines.append('')
101
+ lines.append('Internal Includes:')
102
+ sorted_local = sorted(local_includes.items(), key=lambda x: -len(x[1]))[:MAX]
103
+ for f, incs in sorted_local:
104
+ lines.append(f' {f} -> {len(incs)} headers')
105
+
106
+ if not std_count and not ext_count and not local_includes:
107
+ print('No includes found')
108
+ else:
109
+ print('\n'.join(lines))
110
+ "
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env bash
2
+ set -uo pipefail
3
+ # C++ interface extraction — pure virtual function signatures
4
+ source "$(dirname "$0")/../lib/limit.sh"
5
+
6
+ if ! command -v python3 &>/dev/null; then
7
+ echo "python3 is required for C++ interface extraction"
8
+ exit 0
9
+ fi
10
+
11
+ HEADERS=$(find . -type f \( -name "*.h" -o -name "*.hpp" -o -name "*.hxx" \) \
12
+ -not -path "*/build/*" -not -path "*/.git/*" -not -path "*/cmake-build-*/*" \
13
+ -not -path "*/_deps/*" -not -path "*/third_party/*" -not -path "*/external/*" \
14
+ 2>/dev/null | head -30)
15
+
16
+ if [ -z "$HEADERS" ]; then
17
+ echo "No C++ headers found"
18
+ exit 0
19
+ fi
20
+
21
+ echo "$HEADERS" | PMDMAX="${MAX_INTERFACE:-15}" python3 -c "
22
+ import sys, os, re
23
+
24
+ MAX = int(os.environ.get('PMDMAX', '15'))
25
+
26
+ headers = []
27
+ for line in sys.stdin:
28
+ line = line.strip()
29
+ if line and os.path.isfile(line):
30
+ headers.append(line)
31
+
32
+ if not headers:
33
+ print('No C++ headers found')
34
+ sys.exit(0)
35
+
36
+ iface_blocks = []
37
+ class_re = re.compile(r'^\s*(?:class|struct)\s+([A-Za-z_]\w*)\s*(?::\s*(?:public|protected|private)\s+([A-Za-z_]\w*))?\s*\{', re.MULTILINE)
38
+ virt_re = re.compile(r'virtual\s+([\w:]+(?:\s*<[^>]+>)?(?:\s*[*&])?)\s+(\w+)\s*\(([^)]*)\)\s*(const)?\s*=\s*0\s*;')
39
+
40
+ for hdr in headers:
41
+ try:
42
+ with open(hdr, 'r', errors='replace') as f:
43
+ content = f.read()
44
+ except Exception:
45
+ continue
46
+
47
+ content = re.sub(r'//.*', '', content)
48
+ content = re.sub(r'/\*.*?\*/', '', content, flags=re.DOTALL)
49
+
50
+ pos = 0
51
+ while pos < len(content):
52
+ m = class_re.search(content, pos)
53
+ if not m:
54
+ break
55
+ cls_name = m.group(1)
56
+ start = m.end()
57
+ depth = 1
58
+ end = start
59
+ while end < len(content) and depth > 0:
60
+ if content[end] == '{':
61
+ depth += 1
62
+ elif content[end] == '}':
63
+ depth -= 1
64
+ end += 1
65
+
66
+ body = content[start:end]
67
+ found_methods = []
68
+ for vm in virt_re.finditer(body):
69
+ ret_type = vm.group(1).strip()
70
+ method_name = vm.group(2).strip()
71
+ params = vm.group(3).strip()
72
+ is_const = vm.group(4) is not None
73
+ if params:
74
+ params = re.sub(r'\s+', ' ', params)
75
+ param_types = []
76
+ for p in params.split(','):
77
+ p = p.strip()
78
+ if p:
79
+ parts = p.rsplit(None, 1)
80
+ if len(parts) == 2:
81
+ param_types.append(parts[0])
82
+ else:
83
+ param_types.append(p)
84
+ param_str = ', '.join(param_types)
85
+ suffix = ' const' if is_const else ''
86
+ sig = f'{method_name}({param_str}){suffix} -> {ret_type}'
87
+ else:
88
+ suffix = ' const' if is_const else ''
89
+ sig = f'{method_name}(){suffix} -> {ret_type}'
90
+ found_methods.append(sig)
91
+
92
+ if found_methods:
93
+ iface_blocks.append((os.path.basename(hdr), cls_name, found_methods))
94
+ pos = end
95
+
96
+ if not iface_blocks:
97
+ print('No pure virtual interfaces found')
98
+ sys.exit(0)
99
+
100
+ count = 0
101
+ for hdr, cls, methods in iface_blocks:
102
+ if count >= MAX:
103
+ break
104
+ print(f'[iface] {cls} ({hdr})')
105
+ for m in methods:
106
+ print(f' {m}')
107
+ count += 1
108
+ "
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bash
2
+ set -uo pipefail
3
+ # C/C++ project tree — progressive depth fallback with build exclusions
4
+ source "$(dirname "$0")/../lib/limit.sh"
5
+ limit_tree "$MAX_TREE"
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env bash
2
+ set -uo pipefail
3
+ # C/C++ lint — clang-tidy or cppcheck
4
+ source "$(dirname "$0")/../lib/limit.sh"
5
+
6
+ if command -v clang-tidy &>/dev/null; then
7
+ out=$(clang-tidy --checks='-*,bugprone-*,modernize-*,readability-*' -p build . 2>&1 | head -50)
8
+ limit_output "$out" "$MAX_LINT" "$(echo "$out" | head -3 && echo '... more clang-tidy warnings')"
9
+ elif command -v cppcheck &>/dev/null; then
10
+ out=$(cppcheck --enable=all --suppress=missingInclude . 2>&1 | head -50)
11
+ limit_output "$out" "$MAX_LINT" "$(echo "$out" | head -3 && echo '... more cppcheck warnings')"
12
+ else
13
+ echo "No C/C++ linter found (install clang-tidy or cppcheck)"
14
+ fi
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bash
2
+ set -uo pipefail
3
+ # C/C++ test summary — ctest or make test
4
+ source "$(dirname "$0")/../lib/limit.sh"
5
+
6
+ if [ -f CMakeLists.txt ] && [ -d build ]; then
7
+ out=$(ctest --test-dir build --output-on-failure 2>&1 | tail -10)
8
+ if [ -n "$out" ]; then
9
+ limit_output "$out" "$MAX_TEST" "$(echo "$out" | head -3 && echo '... more test results')"
10
+ exit 0
11
+ fi
12
+ fi
13
+
14
+ if [ -f Makefile ] || [ -f makefile ]; then
15
+ out=$(make test 2>&1 | tail -10)
16
+ if [ -n "$out" ]; then
17
+ limit_output "$out" "$MAX_TEST" "$(echo "$out" | head -3 && echo '... more test results')"
18
+ exit 0
19
+ fi
20
+ fi
21
+
22
+ echo "No C/C++ test runner configured"
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env bash
2
+ set -uo pipefail
3
+ # C/C++ type check — compiler warnings
4
+ source "$(dirname "$0")/../lib/limit.sh"
5
+
6
+ if [ -f CMakeLists.txt ] && [ -d build ]; then
7
+ out=$(cmake --build build 2>&1 | grep -E 'warning:|error:' | head -30)
8
+ if [ -z "$out" ]; then
9
+ echo "No compiler warnings"
10
+ exit 0
11
+ fi
12
+ limit_output "$out" "$MAX_TYPECHECK" "$(echo "$out" | head -3 && echo '... more compiler warnings')"
13
+ exit 0
14
+ fi
15
+
16
+ if [ -f Makefile ] || [ -f makefile ]; then
17
+ out=$(make 2>&1 | grep -E 'warning:|error:' | head -30)
18
+ if [ -z "$out" ]; then
19
+ echo "No compiler warnings"
20
+ exit 0
21
+ fi
22
+ limit_output "$out" "$MAX_TYPECHECK" "$(echo "$out" | head -3 && echo '... more compiler warnings')"
23
+ exit 0
24
+ fi
25
+
26
+ echo "No C/C++ type checker configured (build the project first)"
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env bash
2
+ set -uo pipefail
3
+ # Architecture map — DevOps service dependencies (Docker Compose, Dockerfiles, Terraform)
4
+ source "$(dirname "$0")/../lib/limit.sh"
5
+
6
+ : "${MAX_ARCH:=100}"
7
+
8
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
9
+ NORMALIZE="$SCRIPT_DIR/normalize.sh"
10
+ [ -f "$NORMALIZE" ] || NORMALIZE="$SCRIPT_DIR/../../Shared/architecture/normalize.sh"
11
+
12
+ (
13
+ if [ -f docker-compose.yml ] || [ -f docker-compose.yaml ]; then
14
+ COMPOSE_FILE="docker-compose.yml"
15
+ [ -f docker-compose.yaml ] && COMPOSE_FILE="docker-compose.yaml"
16
+
17
+ if command -v python3 &>/dev/null && python3 -c "import yaml" 2>/dev/null; then
18
+ python3 -c "
19
+ import sys, yaml, os
20
+
21
+ compose_file = os.environ.get('COMPOSE_FILE', 'docker-compose.yml')
22
+ try:
23
+ with open(compose_file, 'r') as f:
24
+ data = yaml.safe_load(f) or {}
25
+ except Exception:
26
+ sys.exit(0)
27
+
28
+ services = data.get('services', {})
29
+ if not services:
30
+ sys.exit(0)
31
+
32
+ for svc, cfg in services.items():
33
+ if not isinstance(cfg, dict):
34
+ continue
35
+ image = cfg.get('image', '')
36
+ if image:
37
+ img_name = image.split(':')[0].split('/')[-1]
38
+ print(f'{svc}\text:{img_name}')
39
+ depends = cfg.get('depends_on', [])
40
+ if isinstance(depends, list):
41
+ for dep in depends:
42
+ print(f'{svc}\t{dep}')
43
+ elif isinstance(depends, dict):
44
+ for dep in depends:
45
+ print(f'{svc}\t{dep}')
46
+ links = cfg.get('links', [])
47
+ for link in links:
48
+ dep = link.split(':')[0] if ':' in link else link
49
+ print(f'{svc}\t{dep}')
50
+ " COMPOSE_FILE="$COMPOSE_FILE" 2>/dev/null
51
+ else
52
+ awk '
53
+ /^[a-zA-Z0-9_-]+:/ && !/^[[:space:]]/ {
54
+ if (in_service && current_svc != "") {
55
+ services[current_svc] = 1
56
+ }
57
+ gsub(/:.*$/, "")
58
+ current_svc = $0
59
+ in_service = 1
60
+ next
61
+ }
62
+ in_service && /^[[:space:]]+depends_on:/ {
63
+ in_depends = 1
64
+ next
65
+ }
66
+ in_service && in_depends && /^[[:space:]]+-[[:space:]]*/ {
67
+ gsub(/^[[:space:]]+-[[:space:]]*/, "")
68
+ gsub(/:.*$/, "")
69
+ if (current_svc != "" && $0 != "") print current_svc "\t" $0
70
+ next
71
+ }
72
+ in_service && /^[[:space:]]+image:/ {
73
+ gsub(/^[[:space:]]+image:[[:space:]]*/, "")
74
+ gsub(/:.*$/, "")
75
+ img = $0
76
+ n = split(img, parts, "/")
77
+ short = parts[n]
78
+ if (current_svc != "" && short != "") print current_svc "\text:" short
79
+ next
80
+ }
81
+ /^[[:space:]]*$/ { in_depends = 0 }
82
+ /^[^[:space:]]/ && !/[a-zA-Z0-9_-]+:/ { in_service = 0 }
83
+ END { if (in_service && current_svc != "") services[current_svc] = 1 }
84
+ ' "$COMPOSE_FILE" 2>/dev/null
85
+ fi
86
+ fi
87
+
88
+ find . -name "Dockerfile" -not -path "*/.git/*" -not -path "*/.pipemd/*" 2>/dev/null | while IFS= read -r df; do
89
+ rel="${df#./}"
90
+ context_dir="$(dirname "$rel")"
91
+ [ "$context_dir" = "." ] && stage="main" || stage="$(basename "$context_dir")"
92
+
93
+ awk -v stage="$stage" '
94
+ /^FROM[[:space:]]/ {
95
+ img = $2
96
+ asname = ""
97
+ for (i = 3; i <= NF; i++) {
98
+ if ($i == "AS" || $i == "as" || $i == "As") {
99
+ asname = $(i+1)
100
+ break
101
+ }
102
+ }
103
+ gsub(/:.*$/, "", img)
104
+ base = img
105
+ n = split(base, parts, "/")
106
+ short = parts[n]
107
+ printf "%s\text:%s\n", stage, short
108
+ if (asname != "") printf "%s\t%s\n", stage, asname
109
+ }
110
+ /COPY[[:space:]]+--from=/ {
111
+ for (i = 1; i <= NF; i++) {
112
+ if ($i == "--from") {
113
+ src = $(i+1)
114
+ if (src !~ /^[0-9]+$/) {
115
+ printf "%s\t%s\n", stage, src
116
+ }
117
+ }
118
+ }
119
+ }
120
+ ' "$df" 2>/dev/null
121
+ done
122
+
123
+ find . -name "*.tf" -not -path "*/.git/*" -not -path "*/.pipemd/*" -not -path "*/.terraform/*" 2>/dev/null | head -30 | while IFS= read -r tf; do
124
+ rel="${tf#./}"
125
+ tf_dir="$(dirname "$rel")"
126
+ [ "$tf_dir" = "." ] && tf_ctx="main" || tf_ctx="$(basename "$tf_dir")"
127
+
128
+ awk -v ctx="$tf_ctx" '
129
+ /^module[[:space:]]+"?/ {
130
+ gsub(/^module[[:space:]]+"?/, "")
131
+ gsub(/".*/, "")
132
+ name = $0
133
+ gsub(/[[:space:]]+/, "", name)
134
+ if (name != "") print ctx "\ttf:" name
135
+ }
136
+ /^data[[:space:]]+"?[a-zA-Z]/ {
137
+ gsub(/^data[[:space:]]+"?/, "")
138
+ gsub(/".*/, "")
139
+ dtype = $1
140
+ gsub(/[[:space:]]+/, "", dtype)
141
+ if (dtype != "") print ctx "\ttf:data_" dtype
142
+ }
143
+ /^resource[[:space:]]+"?[a-zA-Z]/ {
144
+ gsub(/^resource[[:space:]]+"?/, "")
145
+ gsub(/".*/, "")
146
+ rtype = $1
147
+ gsub(/[[:space:]]+/, "", rtype)
148
+ if (rtype != "") print ctx "\ttf:" rtype
149
+ }
150
+ /^provider[[:space:]]+"?[a-zA-Z]/ {
151
+ gsub(/^provider[[:space:]]+"?/, "")
152
+ gsub(/".*/, "")
153
+ pname = $0
154
+ gsub(/[[:space:]]+/, "", pname)
155
+ if (pname != "") print ctx "\text:" pname
156
+ }
157
+ ' "$tf" 2>/dev/null
158
+ done
159
+
160
+ find . \( -name "*.yaml" -o -name "*.yml" \) -not -name "docker-compose.*" -not -path "*/.git/*" -not -path "*/.pipemd/*" 2>/dev/null | head -10 | while IFS= read -r kf; do
161
+ rel="${kf#./}"
162
+ kf_dir="$(dirname "$rel")"
163
+ [ "$kf_dir" = "." ] && kf_ctx="main" || kf_ctx="$(basename "$kf_dir")"
164
+ kf_base="$(basename "$rel" .yaml)"
165
+ [ "$kf_base" = "$(basename "$rel" .yml)" ] || kf_base="$(basename "$rel" .yml)"
166
+
167
+ if echo "$kf_base" | grep -qE '^(deploy|service|ingress|configmap|secret|daemonset|statefulset|deployment|cronjob|job|pod|hpa|pdb|namespace|pv|pvc)$'; then
168
+ awk -v ctx="$kf_ctx" '
169
+ /^[[:space:]]*name:/ {
170
+ gsub(/^[[:space:]]*name:[[:space:]]*/, "")
171
+ gsub(/"/, "")
172
+ gsub(/'"'"'/, "")
173
+ if ($0 != "") print ctx "\tk8s:" $0
174
+ }
175
+ /^[[:space:]]*image:/ {
176
+ gsub(/^[[:space:]]*image:[[:space:]]*/, "")
177
+ gsub(/:.*$/, "")
178
+ n = split($0, parts, "/")
179
+ short = parts[n]
180
+ if (short != "") print ctx "\text:" short
181
+ }
182
+ ' "$kf" 2>/dev/null
183
+ fi
184
+ done
185
+
186
+ ) | sort -u | MAX_ARCH="$MAX_ARCH" bash "$NORMALIZE"
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env bash
2
+ set -uo pipefail
3
+ # AWS caller identity — prevents account hallucination
4
+ source "$(dirname "$0")/../lib/limit.sh"
5
+
6
+ if ! command -v aws &>/dev/null; then
7
+ echo "> ℹ️ aws CLI is not installed or not in PATH"
8
+ exit 0
9
+ fi
10
+
11
+ identity=$(timeout 3s aws sts get-caller-identity --output json 2>/dev/null || true)
12
+
13
+ if [ -z "$identity" ]; then
14
+ echo "> ℹ️ Could not retrieve AWS caller identity (no credentials or timeout)"
15
+ exit 0
16
+ fi
17
+
18
+ echo "## AWS Caller Identity"
19
+ echo ""
20
+
21
+ account=$(echo "$identity" | timeout 2s python3 -c "
22
+ import sys, json
23
+ d = json.load(sys.stdin)
24
+ account = d.get('Account', 'unknown')
25
+ userid = d.get('UserId', 'unknown')
26
+ arn = d.get('Arn', 'unknown')
27
+ print('| Field | Value |')
28
+ print('|-------|-------|')
29
+ print('| Account | {} |'.format(account))
30
+ print('| UserID | {} |'.format(userid))
31
+ print('| ARN | {} |'.format(arn))
32
+ " 2>/dev/null || echo "> Could not parse STS response")
33
+
34
+ echo "$account"
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env bash
2
+ set -uo pipefail
3
+ # Docker container health summary
4
+ source "$(dirname "$0")/../lib/limit.sh"
5
+
6
+ if ! command -v docker &>/dev/null; then
7
+ echo "> ℹ️ docker is not installed or not in PATH"
8
+ exit 0
9
+ fi
10
+
11
+ if ! timeout 3s docker info &>/dev/null; then
12
+ echo "> ℹ️ Docker daemon is not running"
13
+ exit 0
14
+ fi
15
+
16
+ echo "## Docker Containers"
17
+ echo ""
18
+
19
+ containers=$(timeout 5s docker ps -a \
20
+ --filter "status=running" \
21
+ --filter "status=exited" \
22
+ --format "{{.Names}}|{{.Status}}|{{.Ports}}" 2>/dev/null)
23
+
24
+ if [ -z "$containers" ]; then
25
+ echo "> No running or recently exited containers found."
26
+ exit 0
27
+ fi
28
+
29
+ echo "| Name | Status | Ports |"
30
+ echo "|------|--------|-------|"
31
+
32
+ echo "$containers" | head -15 | while IFS='|' read -r name status ports; do
33
+ clean_ports="${ports//-/}"
34
+ if [ -z "$clean_ports" ]; then clean_ports="—"; fi
35
+ echo "| ${name} | ${status} | ${clean_ports} |"
36
+ done
37
+
38
+ total=$(echo "$containers" | wc -l)
39
+ if [ "$total" -gt 15 ]; then
40
+ echo ""
41
+ echo "> Showing 15 of ${total} containers (truncated for token budget)"
42
+ fi