@supportpages.io/wtfm 0.0.0-stage → 0.3.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 +201 -0
- package/NOTICE +23 -0
- package/README.md +392 -2
- package/dist/actions.d.ts +98 -0
- package/dist/actions.js +86 -0
- package/dist/actions.js.map +1 -0
- package/dist/agent-settings.d.ts +22 -0
- package/dist/agent-settings.js +35 -0
- package/dist/agent-settings.js.map +1 -0
- package/dist/api.d.ts +14 -0
- package/dist/api.js +159 -0
- package/dist/api.js.map +1 -0
- package/dist/article-link.d.ts +16 -0
- package/dist/article-link.js +25 -0
- package/dist/article-link.js.map +1 -0
- package/dist/artifacts.d.ts +45 -0
- package/dist/artifacts.js +144 -0
- package/dist/artifacts.js.map +1 -0
- package/dist/brand.d.ts +4 -0
- package/dist/brand.js +9 -0
- package/dist/brand.js.map +1 -0
- package/dist/bridge.d.ts +2964 -0
- package/dist/bridge.js +1036 -0
- package/dist/bridge.js.map +1 -0
- package/dist/capacity.d.ts +5 -0
- package/dist/capacity.js +11 -0
- package/dist/capacity.js.map +1 -0
- package/dist/credentials.d.ts +13 -0
- package/dist/credentials.js +88 -0
- package/dist/credentials.js.map +1 -0
- package/dist/development-tls.d.ts +8 -0
- package/dist/development-tls.js +38 -0
- package/dist/development-tls.js.map +1 -0
- package/dist/errors.d.ts +15 -0
- package/dist/errors.js +18 -0
- package/dist/errors.js.map +1 -0
- package/dist/export.d.ts +11 -0
- package/dist/export.js +91 -0
- package/dist/export.js.map +1 -0
- package/dist/hosted-operations.d.ts +108 -0
- package/dist/hosted-operations.js +120 -0
- package/dist/hosted-operations.js.map +1 -0
- package/dist/hosting-benefits.d.ts +66 -0
- package/dist/hosting-benefits.js +67 -0
- package/dist/hosting-benefits.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/local-inventory.d.ts +22 -0
- package/dist/local-inventory.js +59 -0
- package/dist/local-inventory.js.map +1 -0
- package/dist/local-setup.d.ts +208 -0
- package/dist/local-setup.js +140 -0
- package/dist/local-setup.js.map +1 -0
- package/dist/pairing.d.ts +71 -0
- package/dist/pairing.js +235 -0
- package/dist/pairing.js.map +1 -0
- package/dist/preferences.d.ts +18 -0
- package/dist/preferences.js +44 -0
- package/dist/preferences.js.map +1 -0
- package/dist/progress.d.ts +205 -0
- package/dist/progress.js +224 -0
- package/dist/progress.js.map +1 -0
- package/dist/reminders.d.ts +31 -0
- package/dist/reminders.js +73 -0
- package/dist/reminders.js.map +1 -0
- package/dist/replace-connection.d.ts +6 -0
- package/dist/replace-connection.js +77 -0
- package/dist/replace-connection.js.map +1 -0
- package/dist/repository-actions.d.ts +18 -0
- package/dist/repository-actions.js +9 -0
- package/dist/repository-actions.js.map +1 -0
- package/dist/repository-benefits.d.ts +96 -0
- package/dist/repository-benefits.js +64 -0
- package/dist/repository-benefits.js.map +1 -0
- package/dist/run-update.d.ts +17 -0
- package/dist/run-update.js +27 -0
- package/dist/run-update.js.map +1 -0
- package/dist/runs.d.ts +541 -0
- package/dist/runs.js +146 -0
- package/dist/runs.js.map +1 -0
- package/dist/runtime.d.ts +12 -0
- package/dist/runtime.js +58 -0
- package/dist/runtime.js.map +1 -0
- package/dist/schema.d.ts +277 -0
- package/dist/schema.js +66 -0
- package/dist/schema.js.map +1 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.js +298 -0
- package/dist/server.js.map +1 -0
- package/dist/session.d.ts +1714 -0
- package/dist/session.js +619 -0
- package/dist/session.js.map +1 -0
- package/dist/settings.d.ts +9 -0
- package/dist/settings.js +21 -0
- package/dist/settings.js.map +1 -0
- package/dist/sync.d.ts +495 -0
- package/dist/sync.js +191 -0
- package/dist/sync.js.map +1 -0
- package/dist/telemetry-scrub.d.ts +13 -0
- package/dist/telemetry-scrub.js +51 -0
- package/dist/telemetry-scrub.js.map +1 -0
- package/dist/telemetry.d.ts +73 -0
- package/dist/telemetry.js +173 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/walkthroughs.d.ts +224 -0
- package/dist/walkthroughs.js +109 -0
- package/dist/walkthroughs.js.map +1 -0
- package/dist/workspace.d.ts +14 -0
- package/dist/workspace.js +127 -0
- package/dist/workspace.js.map +1 -0
- package/dist/writer-agent.d.ts +21 -0
- package/dist/writer-agent.js +27 -0
- package/dist/writer-agent.js.map +1 -0
- package/dist/writer-entry.d.ts +171 -0
- package/dist/writer-entry.js +233 -0
- package/dist/writer-entry.js.map +1 -0
- package/dist/writing-style.d.ts +7 -0
- package/dist/writing-style.js +52 -0
- package/dist/writing-style.js.map +1 -0
- package/engine/SYNC.json +4 -0
- package/engine/VERSION +1 -0
- package/engine/detect-project/README.md +141 -0
- package/engine/detect-project/SKILL.md +1421 -0
- package/engine/detect-project/assets/desktop/desktop-frame.css +428 -0
- package/engine/detect-project/assets/game/game-frame.css +132 -0
- package/engine/detect-project/assets/macosui/LICENSE-puppertino.txt +21 -0
- package/engine/detect-project/assets/macosui/VERSIONS.txt +1 -0
- package/engine/detect-project/assets/macosui/fonts.css +15 -0
- package/engine/detect-project/assets/macosui/macos-frame.css +481 -0
- package/engine/detect-project/assets/macosui/puppertino.css +2153 -0
- package/engine/detect-project/assets/mobileui/LICENSE-fonts.txt +13 -0
- package/engine/detect-project/assets/mobileui/LICENSE-framework7.txt +52 -0
- package/engine/detect-project/assets/mobileui/VERSIONS.txt +6 -0
- package/engine/detect-project/assets/mobileui/device-frame.css +316 -0
- package/engine/detect-project/assets/mobileui/f7-color-theme.mjs +1345 -0
- package/engine/detect-project/assets/mobileui/f7-icons-names.json +1254 -0
- package/engine/detect-project/assets/mobileui/fonts.css +16 -0
- package/engine/detect-project/assets/mobileui/framework7-components.css +39 -0
- package/engine/detect-project/assets/mobileui/framework7-core.css +5245 -0
- package/engine/detect-project/assets/mobileui/icons.css +31 -0
- package/engine/detect-project/assets/mobileui/md3-defaults.css +89 -0
- package/engine/detect-project/assets/mobileui/platforms.json +46 -0
- package/engine/detect-project/assets/tailwind-fallback.css +1729 -0
- package/engine/detect-project/assets/webtui/LICENSE-webtui.txt +28 -0
- package/engine/detect-project/assets/webtui/VERSIONS.txt +7 -0
- package/engine/detect-project/assets/webtui/terminal-frame.css +195 -0
- package/engine/detect-project/assets/webtui/theme-catppuccin.css +1 -0
- package/engine/detect-project/assets/webtui/theme-everforest.css +1 -0
- package/engine/detect-project/assets/webtui/theme-gruvbox.css +1 -0
- package/engine/detect-project/assets/webtui/theme-nord.css +1 -0
- package/engine/detect-project/assets/webtui/theme-vitesse.css +1 -0
- package/engine/detect-project/assets/webtui/themes.json +37 -0
- package/engine/detect-project/assets/webtui/webtui-core.css +1 -0
- package/engine/detect-project/assets/win32ui/7css.css +2 -0
- package/engine/detect-project/assets/win32ui/LICENSE-7css.txt +21 -0
- package/engine/detect-project/assets/win32ui/VERSIONS.txt +1 -0
- package/engine/detect-project/assets/win32ui/win32-frame.css +278 -0
- package/engine/detect-project/package-lock.json +12 -0
- package/engine/detect-project/package.json +10 -0
- package/engine/detect-project/scripts/apply_runtime_profiles.js +313 -0
- package/engine/detect-project/scripts/check_css_health.js +412 -0
- package/engine/detect-project/scripts/check_project_map.js +150 -0
- package/engine/detect-project/scripts/check_runtime_coverage.js +311 -0
- package/engine/detect-project/scripts/check_runtime_recipe_quality.js +184 -0
- package/engine/detect-project/scripts/classify_app_type.sh +246 -0
- package/engine/detect-project/scripts/classify_surface.sh +95 -0
- package/engine/detect-project/scripts/classify_workspace.js +39 -0
- package/engine/detect-project/scripts/compile_css.sh +447 -0
- package/engine/detect-project/scripts/detect_static.js +645 -0
- package/engine/detect-project/scripts/detect_structure.js +187 -0
- package/engine/detect-project/scripts/include_census.js +451 -0
- package/engine/detect-project/scripts/json_get.js +142 -0
- package/engine/detect-project/scripts/merge_json.js +52 -0
- package/engine/detect-project/scripts/recommend_model_tier.js +252 -0
- package/engine/detect-project/scripts/resolve_route_chains.js +135 -0
- package/engine/detect-project/scripts/run_css_build.sh +40 -0
- package/engine/detect-project/scripts/sanitize_css.js +83 -0
- package/engine/detect-project/scripts/test_classify_surface.js +108 -0
- package/engine/detect-project/scripts/test_node_helpers.js +142 -0
- package/engine/detect-project/scripts/test_recommend_model_tier.js +119 -0
- package/engine/detect-project/scripts/test_resolve_route_chains.js +182 -0
- package/engine/detect-project/scripts/test_runtime_coverage.js +323 -0
- package/engine/detect-project/scripts/test_runtime_recipe_quality.js +187 -0
- package/engine/detect-project/scripts/theme_overrides.js +169 -0
- package/engine/detect-project/scripts/write_branding.js +129 -0
- package/engine/generate-illustrated-article/SKILL.md +461 -0
- package/engine/generate-illustrated-article/contracts/desktop.md +90 -0
- package/engine/generate-illustrated-article/contracts/game.md +38 -0
- package/engine/generate-illustrated-article/contracts/label-evidence.md +38 -0
- package/engine/generate-illustrated-article/contracts/macos.md +79 -0
- package/engine/generate-illustrated-article/contracts/mobile.md +40 -0
- package/engine/generate-illustrated-article/contracts/terminal.md +29 -0
- package/engine/generate-illustrated-article/contracts/win32.md +43 -0
- package/engine/generate-illustrated-article/package-lock.json +366 -0
- package/engine/generate-illustrated-article/package.json +15 -0
- package/engine/generate-illustrated-article/scripts/article_blocks.js +34 -0
- package/engine/generate-illustrated-article/scripts/check_article_json.js +105 -0
- package/engine/generate-illustrated-article/scripts/emit_walkthrough_signals.js +100 -0
- package/engine/generate-illustrated-article/scripts/extract_images.js +187 -0
- package/engine/generate-illustrated-article/scripts/generate_content_images.js +376 -0
- package/engine/generate-illustrated-article/scripts/include_census.js +451 -0
- package/engine/generate-illustrated-article/scripts/inject_assets.js +1691 -0
- package/engine/generate-illustrated-article/scripts/jit_mockup_css.js +191 -0
- package/engine/generate-illustrated-article/scripts/label_evidence.js +87 -0
- package/engine/generate-illustrated-article/scripts/lint_article_copy.js +252 -0
- package/engine/generate-illustrated-article/scripts/lint_mockup_fidelity.js +2403 -0
- package/engine/generate-illustrated-article/scripts/polish_tickets.js +1148 -0
- package/engine/generate-illustrated-article/scripts/related_repos.sh +52 -0
- package/engine/generate-illustrated-article/scripts/render_all.js +177 -0
- package/engine/generate-illustrated-article/scripts/render_mockup.js +665 -0
- package/engine/generate-illustrated-article/scripts/render_ready.js +164 -0
- package/engine/generate-illustrated-article/scripts/resolve_workspace.sh +86 -0
- package/engine/generate-illustrated-article/scripts/runtime_region_geometry.js +55 -0
- package/engine/generate-illustrated-article/scripts/source_paths.js +49 -0
- package/engine/generate-illustrated-article/scripts/test_control_visibility.js +30 -0
- package/engine/generate-illustrated-article/scripts/test_emit_walkthrough_signals.js +157 -0
- package/engine/generate-illustrated-article/scripts/test_generate_content_images.js +168 -0
- package/engine/generate-illustrated-article/scripts/test_include_census.js +126 -0
- package/engine/generate-illustrated-article/scripts/test_label_evidence.js +49 -0
- package/engine/generate-illustrated-article/scripts/test_lint_article_copy.js +138 -0
- package/engine/generate-illustrated-article/scripts/test_lint_mockup_fidelity.js +653 -0
- package/engine/generate-illustrated-article/scripts/test_node_ports.js +152 -0
- package/engine/generate-illustrated-article/scripts/test_polish_tickets.js +481 -0
- package/engine/generate-illustrated-article/scripts/test_related_repos.js +64 -0
- package/engine/generate-illustrated-article/scripts/test_render_ready.js +85 -0
- package/engine/generate-illustrated-article/scripts/test_source_paths.js +68 -0
- package/engine/generate-illustrated-article/scripts/trace_hook.js +79 -0
- package/engine/generate-illustrated-article/scripts/trace_hook.sh +4 -0
- package/engine/generate-illustrated-article/scripts/validate_html.js +114 -0
- package/engine/generate-illustrated-article/scripts/watermark.js +69 -0
- package/install.sh +14 -0
- package/package.json +57 -4
- package/scripts/auth.mjs +33 -0
- package/scripts/auto-update.mjs +7 -0
- package/scripts/build-plugin.mjs +58 -0
- package/scripts/build-release.mjs +94 -0
- package/scripts/check-release.mjs +40 -0
- package/scripts/check-runtime.mjs +10 -0
- package/scripts/cli.mjs +8 -0
- package/scripts/install.mjs +64 -0
- package/scripts/lib/agent-runner.mjs +181 -0
- package/scripts/lib/agent-settings.mjs +215 -0
- package/scripts/lib/article-skills.mjs +82 -0
- package/scripts/lib/auto-update.mjs +50 -0
- package/scripts/lib/brand.mjs +9 -0
- package/scripts/lib/browser.mjs +12 -0
- package/scripts/lib/claude-connection.mjs +33 -0
- package/scripts/lib/claude-permissions.mjs +47 -0
- package/scripts/lib/claude-plugin.mjs +15 -0
- package/scripts/lib/claude-writer.mjs +10 -0
- package/scripts/lib/cli-main.mjs +85 -0
- package/scripts/lib/cli.mjs +888 -0
- package/scripts/lib/codex-config.mjs +51 -0
- package/scripts/lib/codex-integration.mjs +61 -0
- package/scripts/lib/codex-skill.mjs +34 -0
- package/scripts/lib/harness-models.mjs +109 -0
- package/scripts/lib/install.mjs +269 -0
- package/scripts/lib/managed-writer.mjs +38 -0
- package/scripts/lib/planning.mjs +263 -0
- package/scripts/lib/prepare-update.mjs +85 -0
- package/scripts/lib/refresh-writers.mjs +12 -0
- package/scripts/lib/remove.mjs +167 -0
- package/scripts/lib/renderer.mjs +34 -0
- package/scripts/lib/terminal.mjs +252 -0
- package/scripts/lib/uninit.mjs +72 -0
- package/scripts/lib/update.mjs +55 -0
- package/scripts/lib/writer-recovery.mjs +35 -0
- package/scripts/lib/yolo.mjs +362 -0
- package/scripts/plugin-session.mjs +65 -0
- package/scripts/prepare-update.mjs +12 -0
- package/scripts/publish-release.mjs +92 -0
- package/scripts/skills/supportpages/SKILL.md +120 -0
- package/scripts/smoke-release.mjs +101 -0
- package/server.json +27 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# classify_app_type.sh — deterministic app-type classifier for /detect-project
|
|
3
|
+
# when the user gave no app_type hint. Root-level manifests only; conservative
|
|
4
|
+
# by design: it diverts from web only on unambiguous signals. Multi-surface
|
|
5
|
+
# repos (react-native + react-dom, CLI + web framework, monorepos with the app
|
|
6
|
+
# in a subdirectory) default to web and emit a note= line the caller surfaces.
|
|
7
|
+
#
|
|
8
|
+
# Usage: classify_app_type.sh <codebase_dir>
|
|
9
|
+
#
|
|
10
|
+
# Output (line-oriented):
|
|
11
|
+
# type=web|terminal|mobile|desktop|win32|macos|game
|
|
12
|
+
# source=auto|default auto = positive identification; default = nothing matched
|
|
13
|
+
# reason=<one line explaining the decision>
|
|
14
|
+
# note=<0+ lines — ambiguities worth surfacing to the user>
|
|
15
|
+
#
|
|
16
|
+
# Decision order: mobile → desktop (Electron/Tauri — must precede the web
|
|
17
|
+
# signals, since Electron renderers have react-dom) → web signals → game
|
|
18
|
+
# (web/canvas game engine + no web framework — before terminal, a game repo may
|
|
19
|
+
# also carry a CLI helper) → terminal (CLI framework + no web framework; Bevy
|
|
20
|
+
# vetoes the near-universal clap) → win32 (VS project + DIALOGEX .rc, no
|
|
21
|
+
# web/CLI signals) → macos (Xcode project + AppKit menu bar) → monorepo +
|
|
22
|
+
# native-game-engine + vanilla-canvas notes → web.
|
|
23
|
+
#
|
|
24
|
+
# Always exits 0. Bash 3.2 + BSD/GNU grep compatible (no \b, no flock, no jq).
|
|
25
|
+
|
|
26
|
+
CODEBASE="${1:-.}"
|
|
27
|
+
CODEBASE="${CODEBASE%/}"
|
|
28
|
+
NOTES=()
|
|
29
|
+
|
|
30
|
+
has() { [ -e "$CODEBASE/$1" ]; }
|
|
31
|
+
dep() { [ -f "$CODEBASE/$1" ] && grep -Eq "$2" "$CODEBASE/$1" 2>/dev/null; }
|
|
32
|
+
|
|
33
|
+
finish() { # finish <type> <source> <reason>
|
|
34
|
+
printf 'type=%s\nsource=%s\nreason=%s\n' "$1" "$2" "$3"
|
|
35
|
+
for n in ${NOTES[@]+"${NOTES[@]}"}; do printf 'note=%s\n' "$n"; done
|
|
36
|
+
exit 0
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
# ---------- mobile: unambiguous root-level signals ----------
|
|
40
|
+
if dep pubspec.yaml 'sdk:[[:space:]]*flutter'; then
|
|
41
|
+
# Flutter-DESKTOP refinement: desktop platform dirs with no mobile ones means
|
|
42
|
+
# the mobile branch would render this app in a phone frame — wrong, and the
|
|
43
|
+
# desktop branch supports Electron/Tauri only. Note it, stay web.
|
|
44
|
+
if { has macos || has windows || has linux; } && ! has android && ! has ios; then
|
|
45
|
+
NOTES+=("Flutter DESKTOP app (desktop platform dirs, no android/ or ios/) — not supported by the desktop branch (Electron/Tauri only). Defaulting to web; pass app_type=mobile to force phone-frame docs.")
|
|
46
|
+
else
|
|
47
|
+
finish mobile auto "pubspec.yaml declares an sdk: flutter dependency — Flutter app"
|
|
48
|
+
fi
|
|
49
|
+
fi
|
|
50
|
+
if dep package.json '"react-native"[[:space:]]*:'; then
|
|
51
|
+
if dep package.json '"react-dom"[[:space:]]*:'; then
|
|
52
|
+
NOTES+=("package.json has both react-native and react-dom — multi-surface repo (native app + web). Defaulting to web; pass app_type=mobile to document the native app instead.")
|
|
53
|
+
else
|
|
54
|
+
finish mobile auto "package.json depends on react-native with no react-dom — React Native app"
|
|
55
|
+
fi
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# ---------- desktop: Electron / Tauri ----------
|
|
59
|
+
# Checked BEFORE the web signals on purpose: an Electron renderer has react-dom
|
|
60
|
+
# (often next/vite too), so the web positive ID would otherwise always win.
|
|
61
|
+
if [ -f "$CODEBASE/src-tauri/tauri.conf.json" ] || [ -f "$CODEBASE/src-tauri/tauri.conf.json5" ] \
|
|
62
|
+
|| [ -f "$CODEBASE/src-tauri/Tauri.toml" ] || [ -f "$CODEBASE/tauri.conf.json" ]; then
|
|
63
|
+
finish desktop auto "Tauri configuration found — Tauri desktop app"
|
|
64
|
+
fi
|
|
65
|
+
if dep package.json '"electron"[[:space:]]*:'; then
|
|
66
|
+
# The dep alone is not unambiguous (a web workspace root can list electron for
|
|
67
|
+
# a wrapper subpackage) — require a main-process tell: the package.json "main"
|
|
68
|
+
# entry creating a BrowserWindow, or packaging config (electron-builder/forge/
|
|
69
|
+
# electron-vite).
|
|
70
|
+
ELECTRON_TELL=""
|
|
71
|
+
MAIN_REL=$(sed -n 's/.*"main"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$CODEBASE/package.json" 2>/dev/null | head -1)
|
|
72
|
+
if [ -n "$MAIN_REL" ] && [ -f "$CODEBASE/$MAIN_REL" ] && grep -Eq 'BrowserWindow|app\.whenReady' "$CODEBASE/$MAIN_REL" 2>/dev/null; then
|
|
73
|
+
ELECTRON_TELL="main entry $MAIN_REL creates a BrowserWindow"
|
|
74
|
+
elif [ -f "$CODEBASE/electron-builder.yml" ] || [ -f "$CODEBASE/electron-builder.yaml" ] || [ -f "$CODEBASE/electron-builder.json" ] \
|
|
75
|
+
|| [ -f "$CODEBASE/forge.config.js" ] || [ -f "$CODEBASE/forge.config.cjs" ] || [ -f "$CODEBASE/forge.config.ts" ] \
|
|
76
|
+
|| [ -f "$CODEBASE/electron.vite.config.js" ] || [ -f "$CODEBASE/electron.vite.config.mjs" ] || [ -f "$CODEBASE/electron.vite.config.ts" ] \
|
|
77
|
+
|| dep package.json '"forge"[[:space:]]*:'; then
|
|
78
|
+
ELECTRON_TELL="Electron packaging config present"
|
|
79
|
+
fi
|
|
80
|
+
if [ -n "$ELECTRON_TELL" ]; then
|
|
81
|
+
finish desktop auto "package.json depends on electron and $ELECTRON_TELL — Electron desktop app"
|
|
82
|
+
fi
|
|
83
|
+
NOTES+=("electron dependency found but no main-process tell (compiled entry, or a wrapper subpackage?). Defaulting to web; pass app_type=desktop if this repo is the Electron app.")
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
# ---------- web framework signals (positive web ID; also the terminal veto) ----------
|
|
87
|
+
WEB_REASON=""
|
|
88
|
+
if has config/routes.rb && has Gemfile; then WEB_REASON="Rails (Gemfile + config/routes.rb)"
|
|
89
|
+
elif dep mix.exs '\{:phoenix'; then WEB_REASON="Phoenix (mix.exs)"
|
|
90
|
+
elif has artisan; then WEB_REASON="Laravel (artisan)"
|
|
91
|
+
elif has manage.py; then WEB_REASON="Django (manage.py)"
|
|
92
|
+
elif has next.config.js || has next.config.mjs || has next.config.ts; then WEB_REASON="Next.js (next.config.*)"
|
|
93
|
+
elif dep package.json '"(react-dom|next|nuxt|vue|svelte|@angular/core|astro|@remix-run/react|express|fastify|koa|hono)"[[:space:]]*:'; then
|
|
94
|
+
WEB_REASON="web framework dependency in package.json"
|
|
95
|
+
elif dep Cargo.toml '^[[:space:]]*(actix-web|axum|rocket|warp|poem)[[:space:]]*='; then
|
|
96
|
+
WEB_REASON="Rust web framework in Cargo.toml"
|
|
97
|
+
elif dep go.mod '(gin-gonic/gin|labstack/echo|gofiber/fiber|go-chi/chi)'; then
|
|
98
|
+
WEB_REASON="Go web framework in go.mod"
|
|
99
|
+
elif dep pyproject.toml '(^(django|flask|fastapi|starlette)[[:space:]]*=|["'"'"'](django|flask|fastapi|starlette)[=>< ~!,"'"'"'])' \
|
|
100
|
+
|| dep requirements.txt '^(django|flask|fastapi|starlette)([=><~ !]|$)'; then
|
|
101
|
+
WEB_REASON="Python web framework dependency"
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
# ---------- game: web/canvas game engine (renders as web tech) ----------
|
|
105
|
+
# Positive only for engines that are games-only in practice. three.js / Babylon /
|
|
106
|
+
# playcanvas are deliberately NOT signals (huge non-game viz/3D usage — no note
|
|
107
|
+
# either). Native engines (Godot/Unity/Unreal/Bevy) are note-only further down:
|
|
108
|
+
# the game branch supports web-rendered games only.
|
|
109
|
+
GAME_REASON=""
|
|
110
|
+
if dep package.json '"(phaser|pixi\.js|@pixi/[a-z-]+|excalibur|kaboom|kaplay|melonjs)"[[:space:]]*:'; then
|
|
111
|
+
GAME_REASON="web game engine dependency in package.json"
|
|
112
|
+
fi
|
|
113
|
+
if [ -n "$GAME_REASON" ]; then
|
|
114
|
+
if [ -z "$WEB_REASON" ]; then
|
|
115
|
+
finish game auto "$GAME_REASON, and no web framework in the root manifests — web/canvas game"
|
|
116
|
+
fi
|
|
117
|
+
NOTES+=("Both a game engine ($GAME_REASON) and a web framework ($WEB_REASON) are present. Defaulting to web; pass app_type=game to document the game instead.")
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
# ---------- terminal: a CLI/TUI framework AND no web framework at all ----------
|
|
121
|
+
CLI_REASON=""
|
|
122
|
+
if dep Cargo.toml '^[[:space:]]*(clap|structopt)[[:space:]]*='; then
|
|
123
|
+
CLI_REASON="Rust CLI framework (clap/structopt) in Cargo.toml"
|
|
124
|
+
elif dep Cargo.toml '^[[:space:]]*(ratatui|crossterm|cursive|tui)[[:space:]]*='; then
|
|
125
|
+
CLI_REASON="Rust TUI framework in Cargo.toml"
|
|
126
|
+
elif dep go.mod '(spf13/cobra|urfave/cli|charmbracelet/bubbletea)'; then
|
|
127
|
+
CLI_REASON="Go CLI/TUI framework in go.mod"
|
|
128
|
+
elif dep pyproject.toml '^\[project\.scripts\]' || dep setup.cfg 'console_scripts' || dep setup.py 'console_scripts'; then
|
|
129
|
+
CLI_REASON="Python console-script entry points"
|
|
130
|
+
elif dep pyproject.toml '(^(click|typer|textual)[[:space:]]*=|["'"'"'](click|typer|textual)[=>< ~!,"'"'"'])' \
|
|
131
|
+
|| dep requirements.txt '^(click|typer|textual)([=><~ !]|$)'; then
|
|
132
|
+
CLI_REASON="Python CLI/TUI framework dependency"
|
|
133
|
+
elif dep package.json '"bin"[[:space:]]*:' && dep package.json '"(commander|yargs|oclif|@oclif/core|ink)"[[:space:]]*:'; then
|
|
134
|
+
CLI_REASON="package.json bin entry + Node CLI framework"
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
# Bevy veto: a Bevy game near-universally carries clap for launcher args, which
|
|
138
|
+
# would positively classify terminal. Bevy is a native-engine GAME — the mockup
|
|
139
|
+
# pipeline supports web-rendered games only, so veto the CLI signal and note it.
|
|
140
|
+
if dep Cargo.toml '^[[:space:]]*bevy[[:space:]]*='; then
|
|
141
|
+
CLI_REASON=""
|
|
142
|
+
NOTES+=("Cargo.toml carries the Bevy game engine — a native-engine game, not supported by the mockup pipeline (web-rendered games only). Defaulting to web.")
|
|
143
|
+
fi
|
|
144
|
+
|
|
145
|
+
if [ -n "$CLI_REASON" ]; then
|
|
146
|
+
if [ -z "$WEB_REASON" ]; then
|
|
147
|
+
finish terminal auto "$CLI_REASON, and no web framework in the root manifests — CLI/TUI app"
|
|
148
|
+
fi
|
|
149
|
+
NOTES+=("Both a CLI framework ($CLI_REASON) and a web framework ($WEB_REASON) are present. Defaulting to web; pass app_type=terminal to document the CLI instead.")
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
# ---------- win32: native Windows GUI (Visual Studio project + dialog resources) ----------
|
|
153
|
+
# Unambiguous only when nothing web/CLI matched: a .sln/.vcxproj plus an .rc
|
|
154
|
+
# resource that defines dialogs (DIALOGEX). Qt/.ui apps deliberately do NOT
|
|
155
|
+
# match (unsupported); a C++ CLI has no dialog resources.
|
|
156
|
+
if [ -z "$WEB_REASON" ] && [ -z "$CLI_REASON" ]; then
|
|
157
|
+
VS_PROJ=$(find "$CODEBASE" -maxdepth 3 \( -name '*.vcxproj' -o -name '*.sln' \) -not -path '*/.git/*' 2>/dev/null | head -1)
|
|
158
|
+
if [ -n "$VS_PROJ" ]; then
|
|
159
|
+
RC_DLG=""
|
|
160
|
+
while IFS= read -r rcf; do
|
|
161
|
+
if grep -q 'DIALOGEX' "$rcf" 2>/dev/null; then RC_DLG="$rcf"; break; fi
|
|
162
|
+
done < <(find "$CODEBASE" -maxdepth 4 -name '*.rc' -not -path '*/.git/*' 2>/dev/null | head -20)
|
|
163
|
+
if [ -n "$RC_DLG" ]; then
|
|
164
|
+
finish win32 auto "Visual Studio project + Win32 dialog resources (.rc with DIALOGEX) — native Windows GUI app"
|
|
165
|
+
fi
|
|
166
|
+
fi
|
|
167
|
+
fi
|
|
168
|
+
|
|
169
|
+
# ---------- macos: native AppKit (Xcode project + Interface Builder UI) ----------
|
|
170
|
+
# Checked after mobile/desktop on purpose: Flutter macOS runners and Electron
|
|
171
|
+
# apps also ship .xcodeproj files but are caught by the earlier signals. The
|
|
172
|
+
# gate is <menuItem — an AppKit menu bar is definitive (iOS storyboards have
|
|
173
|
+
# none). Pure-SwiftUI apps (no IB files) get a note, never auto-classified.
|
|
174
|
+
if [ -z "$WEB_REASON" ] && [ -z "$CLI_REASON" ]; then
|
|
175
|
+
XCPROJ=$(find "$CODEBASE" -maxdepth 2 -name '*.xcodeproj' -not -path '*/.git/*' 2>/dev/null | head -1)
|
|
176
|
+
if [ -n "$XCPROJ" ]; then
|
|
177
|
+
IB_FILE=""
|
|
178
|
+
while IFS= read -r xf; do
|
|
179
|
+
if grep -q '<menuItem ' "$xf" 2>/dev/null; then IB_FILE="$xf"; break; fi
|
|
180
|
+
done < <(find "$CODEBASE" -maxdepth 4 \( -name '*.xib' -o -name '*.storyboard' \) -not -path '*/.git/*' 2>/dev/null | head -20)
|
|
181
|
+
if [ -n "$IB_FILE" ]; then
|
|
182
|
+
for fe in qt gtk web android windows linux; do
|
|
183
|
+
if [ -d "$CODEBASE/$fe" ]; then
|
|
184
|
+
NOTES+=("Multi-frontend repo: $fe/ (and possibly others) exists alongside the macOS app. Classifying macos (root Xcode project is the primary-surface signal); pass app_type=web or another hint to document a different surface.")
|
|
185
|
+
break
|
|
186
|
+
fi
|
|
187
|
+
done
|
|
188
|
+
finish macos auto "Xcode project + Interface Builder UI (a .xib/.storyboard defines an AppKit menu bar) — native macOS app"
|
|
189
|
+
fi
|
|
190
|
+
NOTES+=("Xcode project found but no Interface Builder files with an AppKit menu bar (pure SwiftUI, or an iOS app?). Defaulting to web; pass app_type=macos if this is a native macOS app.")
|
|
191
|
+
fi
|
|
192
|
+
fi
|
|
193
|
+
|
|
194
|
+
# ---------- monorepo hints: notes only, never classification ----------
|
|
195
|
+
# An app living in a subdirectory can't be safely classified from the root, but
|
|
196
|
+
# it is worth telling the user where it is (Immich mobile/, LocalSend app/).
|
|
197
|
+
while IFS= read -r f; do
|
|
198
|
+
rel="${f#"$CODEBASE"/}"
|
|
199
|
+
if grep -Eq 'sdk:[[:space:]]*flutter' "$f" 2>/dev/null; then
|
|
200
|
+
NOTES+=("Flutter app found at $rel — to document it, re-run /detect-project with codebase_path=${rel%/pubspec.yaml} app_type=mobile.")
|
|
201
|
+
fi
|
|
202
|
+
done < <(find "$CODEBASE" -mindepth 2 -maxdepth 3 -name pubspec.yaml -not -path '*/node_modules/*' -not -path '*/.git/*' 2>/dev/null | head -3)
|
|
203
|
+
|
|
204
|
+
while IFS= read -r f; do
|
|
205
|
+
rel="${f#"$CODEBASE"/}"
|
|
206
|
+
if grep -Eq '"react-native"[[:space:]]*:' "$f" 2>/dev/null && ! grep -Eq '"react-dom"[[:space:]]*:' "$f" 2>/dev/null; then
|
|
207
|
+
NOTES+=("React Native app found at ${rel%/package.json} — to document it, re-run /detect-project with codebase_path=${rel%/package.json} app_type=mobile.")
|
|
208
|
+
elif grep -Eq '"electron"[[:space:]]*:' "$f" 2>/dev/null; then
|
|
209
|
+
NOTES+=("Electron app found at ${rel%/package.json} — to document it, re-run /detect-project with codebase_path=${rel%/package.json} app_type=desktop.")
|
|
210
|
+
fi
|
|
211
|
+
done < <(find "$CODEBASE" -mindepth 2 -maxdepth 3 -name package.json -not -path '*/node_modules/*' -not -path '*/.git/*' 2>/dev/null | head -20)
|
|
212
|
+
|
|
213
|
+
while IFS= read -r f; do
|
|
214
|
+
rel="${f#"$CODEBASE"/}"
|
|
215
|
+
if grep -Eq '^[[:space:]]*(clap|structopt|ratatui)[[:space:]]*=' "$f" 2>/dev/null; then
|
|
216
|
+
NOTES+=("CLI/TUI crate found at ${rel%/Cargo.toml} (workspace member) — if this repo is a CLI/TUI app, pass app_type=terminal.")
|
|
217
|
+
fi
|
|
218
|
+
done < <(find "$CODEBASE" -mindepth 2 -maxdepth 3 -name Cargo.toml -not -path '*/node_modules/*' -not -path '*/.git/*' -not -path '*/target/*' 2>/dev/null | head -5)
|
|
219
|
+
|
|
220
|
+
# ---------- native game engines: notes only, never classification ----------
|
|
221
|
+
# The game branch supports web-rendered games only; a native-engine project has
|
|
222
|
+
# no web CSS/DOM surface for the pipeline to work with.
|
|
223
|
+
if has project.godot; then
|
|
224
|
+
NOTES+=("project.godot found — a Godot game (native engine), not supported by the mockup pipeline (web-rendered games only).")
|
|
225
|
+
fi
|
|
226
|
+
if [ -f "$CODEBASE/ProjectSettings/ProjectVersion.txt" ]; then
|
|
227
|
+
NOTES+=("ProjectSettings/ProjectVersion.txt found — a Unity game (native engine), not supported by the mockup pipeline (web-rendered games only).")
|
|
228
|
+
fi
|
|
229
|
+
UPROJ=$(find "$CODEBASE" -maxdepth 2 -name '*.uproject' -not -path '*/.git/*' 2>/dev/null | head -1)
|
|
230
|
+
if [ -n "$UPROJ" ]; then
|
|
231
|
+
NOTES+=("${UPROJ#"$CODEBASE"/} found — an Unreal game (native engine), not supported by the mockup pipeline (web-rendered games only).")
|
|
232
|
+
fi
|
|
233
|
+
|
|
234
|
+
# ---------- vanilla-canvas game: note only, adjudicated in STEP 0 ----------
|
|
235
|
+
# A root index.html drawing to a <canvas> with no framework signal at all is
|
|
236
|
+
# often a hand-rolled canvas game — but canvas alone is weak evidence (charts,
|
|
237
|
+
# viz). The note triggers the STEP 0 surface adjudication, which diverts to
|
|
238
|
+
# game only when the repo evidence is one-sided.
|
|
239
|
+
if [ -z "$WEB_REASON" ] && [ -z "$CLI_REASON" ] && [ -z "$GAME_REASON" ] && dep index.html '<canvas'; then
|
|
240
|
+
NOTES+=("Root index.html draws to a <canvas> and no web framework is present — possibly a vanilla-canvas game. If it is, the right type is app_type=game (canvas-scene mockups); the surface adjudication should decide from the repo evidence.")
|
|
241
|
+
fi
|
|
242
|
+
|
|
243
|
+
if [ -n "$WEB_REASON" ]; then
|
|
244
|
+
finish web auto "$WEB_REASON"
|
|
245
|
+
fi
|
|
246
|
+
finish web default "no unambiguous app-type signals in the root manifests — taking the web path"
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# classify_surface.sh — does this checkout have a user-facing interface, and of
|
|
3
|
+
# which kind? Wraps classify_app_type.sh (which never says "no UI": an API-only
|
|
4
|
+
# Rails app or an Express JSON server is web to it) with a deterministic
|
|
5
|
+
# no-UI check, so a multi-repo product can tell its surfaces (web app, admin
|
|
6
|
+
# panel, CLI, mobile app) from its code-only repos (APIs, libraries).
|
|
7
|
+
#
|
|
8
|
+
# Usage: classify_surface.sh <codebase_dir>
|
|
9
|
+
#
|
|
10
|
+
# Output (line-oriented):
|
|
11
|
+
# surface=web|terminal|mobile|desktop|win32|macos|game|none
|
|
12
|
+
# source=auto|default auto = positive identification
|
|
13
|
+
# reason=<one line>
|
|
14
|
+
#
|
|
15
|
+
# Only a web verdict is refined: terminal/mobile/desktop/win32/macos/game are
|
|
16
|
+
# positive identifications of an interface. A web verdict becomes
|
|
17
|
+
# - none when Rails declares config.api_only = true;
|
|
18
|
+
# - web when package.json has a frontend framework dependency, or there are
|
|
19
|
+
# UI sources: 3+ template/markup/style/component files outside tests, docs,
|
|
20
|
+
# mailers and vendored/bundled code (engine/, third_party/, assets/vendor/…);
|
|
21
|
+
# - terminal when package.json declares a bin (a hand-rolled Node CLI that
|
|
22
|
+
# classify_app_type.sh's framework list misses);
|
|
23
|
+
# - none otherwise (a server/API or library).
|
|
24
|
+
#
|
|
25
|
+
# Always exits 0. Bash 3.2 + BSD/GNU grep compatible.
|
|
26
|
+
|
|
27
|
+
CODEBASE="${1:-.}"
|
|
28
|
+
CODEBASE="${CODEBASE%/}"
|
|
29
|
+
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
30
|
+
|
|
31
|
+
finish() { printf 'surface=%s\nsource=%s\nreason=%s\n' "$1" "$2" "$3"; exit 0; }
|
|
32
|
+
|
|
33
|
+
[ -d "$CODEBASE" ] || finish none default "codebase directory does not exist"
|
|
34
|
+
|
|
35
|
+
CLASSIFY=$(bash "$HERE/classify_app_type.sh" "$CODEBASE" 2>/dev/null)
|
|
36
|
+
TYPE=$(printf '%s\n' "$CLASSIFY" | sed -n 's/^type=//p' | head -1)
|
|
37
|
+
SOURCE=$(printf '%s\n' "$CLASSIFY" | sed -n 's/^source=//p' | head -1)
|
|
38
|
+
REASON=$(printf '%s\n' "$CLASSIFY" | sed -n 's/^reason=//p' | head -1)
|
|
39
|
+
TYPE="${TYPE:-web}"
|
|
40
|
+
SOURCE="${SOURCE:-default}"
|
|
41
|
+
|
|
42
|
+
if [ "$TYPE" != "web" ]; then
|
|
43
|
+
finish "$TYPE" "$SOURCE" "$REASON"
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# ---------- Rails API mode ----------
|
|
47
|
+
if [ -f "$CODEBASE/config/application.rb" ] &&
|
|
48
|
+
grep -Eq '^[[:space:]]*config\.api_only[[:space:]]*=[[:space:]]*true' "$CODEBASE/config/application.rb" 2>/dev/null; then
|
|
49
|
+
finish none auto "Rails app with config.api_only = true — an API, no user-facing interface"
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
# ---------- frontend framework dependency ----------
|
|
53
|
+
if [ -f "$CODEBASE/package.json" ] &&
|
|
54
|
+
grep -Eq '"(react-dom|vue|svelte|@sveltejs/kit|@angular/core|solid-js|preact|next|nuxt|@remix-run/react|astro|ember-source|lit|@builder.io/qwik|alpinejs|htmx.org|@hotwired/turbo|@hotwired/stimulus)"[[:space:]]*:' "$CODEBASE/package.json" 2>/dev/null; then
|
|
55
|
+
finish web "$SOURCE" "${REASON:-frontend framework dependency in package.json}"
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# ---------- UI sources ----------
|
|
59
|
+
# Templates, markup, styles and component files, excluding places that hold
|
|
60
|
+
# UI-shaped files without being an interface (tests, docs, mail, vendored code,
|
|
61
|
+
# and the skills' own .rtfm cache and ./output mockups).
|
|
62
|
+
UI_COUNT=$(find "$CODEBASE" \
|
|
63
|
+
\( -name .git -o -name node_modules -o -name vendor -o -name dist -o -name build \
|
|
64
|
+
-o -name coverage -o -name tmp -o -name test -o -name tests -o -name spec \
|
|
65
|
+
-o -name __tests__ -o -name fixtures -o -name docs -o -name doc -o -name examples \
|
|
66
|
+
-o -name '*mailer*' -o -name mail -o -name mails -o -name emails -o -name email \
|
|
67
|
+
-o -name .github -o -name target -o -name engine -o -name third_party -o -name third-party \
|
|
68
|
+
-o -name .rtfm -o -name '.rtfm-*' -o -name output \
|
|
69
|
+
-o -path '*/assets/vendor' -o -path '*/public/vendor' -o -path '*/static/vendor' \) -prune -o \
|
|
70
|
+
-type f \( -name '*.html' -o -name '*.htm' -o -name '*.erb' -o -name '*.haml' -o -name '*.slim' \
|
|
71
|
+
-o -name '*.heex' -o -name '*.leex' -o -name '*.eex' -o -name '*.vue' -o -name '*.svelte' \
|
|
72
|
+
-o -name '*.jsx' -o -name '*.tsx' -o -name '*.hbs' -o -name '*.handlebars' -o -name '*.ejs' \
|
|
73
|
+
-o -name '*.pug' -o -name '*.twig' -o -name '*.blade.php' -o -name '*.jinja' -o -name '*.jinja2' \
|
|
74
|
+
-o -name '*.j2' -o -name '*.cshtml' -o -name '*.razor' -o -name '*.liquid' -o -name '*.mustache' \
|
|
75
|
+
-o -name '*.css' -o -name '*.scss' -o -name '*.sass' -o -name '*.less' -o -name '*.templ' \) \
|
|
76
|
+
-print 2>/dev/null | head -50 | wc -l | tr -d ' ')
|
|
77
|
+
|
|
78
|
+
if [ "${UI_COUNT:-0}" -ge 3 ]; then
|
|
79
|
+
finish web "$SOURCE" "${REASON:-UI sources present} (${UI_COUNT}+ template/markup/style files)"
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
# ---------- Node CLI: a package.json bin with no frontend framework ----------
|
|
83
|
+
# classify_app_type.sh only recognises specific CLI frameworks (commander,
|
|
84
|
+
# yargs, oclif, ink); a hand-rolled Node CLI (process.argv, @clack/prompts, an
|
|
85
|
+
# MCP stdio server) has none of them. A declared executable with no frontend
|
|
86
|
+
# framework and no UI sources of its own (vendored engines/templates are
|
|
87
|
+
# pruned above) is a terminal tool.
|
|
88
|
+
if [ -f "$CODEBASE/package.json" ] && grep -Eq '"bin"[[:space:]]*:' "$CODEBASE/package.json" 2>/dev/null; then
|
|
89
|
+
finish terminal auto "package.json declares a bin (a command-line executable) with no frontend framework dependency"
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
if [ "$SOURCE" = "auto" ]; then
|
|
93
|
+
finish none auto "web framework but no templates, styles or frontend framework — a server/API with no user-facing interface ($REASON)"
|
|
94
|
+
fi
|
|
95
|
+
finish none default "no interface signals: no app-type manifest, templates, styles or frontend framework — a library or service"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* classify_workspace.js — run classify_surface.sh on every git checkout
|
|
4
|
+
* directly under a multi-repo workspace root and print JSON:
|
|
5
|
+
*
|
|
6
|
+
* [{ "directory": "acme-web", "surface": "web", "source": "auto", "reason": "…" }, …]
|
|
7
|
+
*
|
|
8
|
+
* Usage: node classify_workspace.js <repos_root>
|
|
9
|
+
* Sorted by directory; prints [] for a missing root. Always exits 0.
|
|
10
|
+
*/
|
|
11
|
+
'use strict';
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const { execFileSync } = require('child_process');
|
|
15
|
+
|
|
16
|
+
const SCRIPT = path.join(__dirname, 'classify_surface.sh');
|
|
17
|
+
|
|
18
|
+
function classifyWorkspace(root) {
|
|
19
|
+
if (!root || !fs.existsSync(root)) return [];
|
|
20
|
+
return fs.readdirSync(root, { withFileTypes: true })
|
|
21
|
+
.filter(entry => entry.isDirectory() && fs.existsSync(path.join(root, entry.name, '.git')))
|
|
22
|
+
.map(entry => entry.name)
|
|
23
|
+
.sort()
|
|
24
|
+
.map(directory => {
|
|
25
|
+
let out = '';
|
|
26
|
+
try { out = execFileSync('bash', [SCRIPT, path.join(root, directory)], { encoding: 'utf8' }); } catch { /* none below */ }
|
|
27
|
+
const fields = Object.fromEntries(out.trim().split('\n').filter(Boolean).map(line => {
|
|
28
|
+
const i = line.indexOf('=');
|
|
29
|
+
return [line.slice(0, i), line.slice(i + 1)];
|
|
30
|
+
}));
|
|
31
|
+
return { directory, surface: fields.surface || 'none', source: fields.source || 'default', reason: fields.reason || '' };
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (require.main === module) {
|
|
36
|
+
process.stdout.write(JSON.stringify(classifyWorkspace(process.argv[2]), null, 2) + '\n');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = { classifyWorkspace };
|