@scrymore/scry-deployer 0.12.0-next.20261006094957 → 0.12.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/package.json
CHANGED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# AT-16: install skills/scry-native-capture-setup from this checkout with `npx skills add` into a
|
|
3
|
+
# throwaway HOME and project, then check the skill landed and its SKILL.md frontmatter parses.
|
|
4
|
+
# Usage: bash scripts/check-skill-install.sh [skill-name] (default: scry-native-capture-setup)
|
|
5
|
+
# Also fails if the skill names the old epinnock/scry-node repo. Needs network for `npx skills` (npm registry) the first time. Never touches the real HOME or repo.
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
SKILL="${1:-scry-native-capture-setup}"
|
|
8
|
+
REPO="$(cd "$(dirname "$0")/.." && pwd)"
|
|
9
|
+
TMP="$(mktemp -d)"
|
|
10
|
+
trap 'rm -rf "$TMP"' EXIT
|
|
11
|
+
mkdir -p "$TMP/home" "$TMP/project"
|
|
12
|
+
git -C "$TMP/project" init -q .
|
|
13
|
+
|
|
14
|
+
# F14: the skill must name the canonical repo, never the old epinnock/ name.
|
|
15
|
+
if grep -rn "epinnock/scry-node" "$REPO/skills/$SKILL" >/dev/null 2>&1; then
|
|
16
|
+
echo "FAIL: skills/$SKILL still mentions epinnock/scry-node (use scryorg/scry-node)" >&2; exit 1
|
|
17
|
+
fi
|
|
18
|
+
grep -q "npx skills add scryorg/scry-node --skill $SKILL" "$REPO/skills/$SKILL/SKILL.md" \
|
|
19
|
+
|| { echo "FAIL: SKILL.md does not show 'npx skills add scryorg/scry-node --skill $SKILL'" >&2; exit 1; }
|
|
20
|
+
echo "canonical install command: npx skills add scryorg/scry-node --skill $SKILL (this script installs from the local checkout)"
|
|
21
|
+
|
|
22
|
+
echo "install: npx skills add $REPO --skill $SKILL (HOME=$TMP/home)"
|
|
23
|
+
(cd "$TMP/project" && HOME="$TMP/home" npx --yes skills add "$REPO" --skill "$SKILL" -y >"$TMP/install.log" 2>&1) \
|
|
24
|
+
|| { tail -20 "$TMP/install.log" >&2; echo "FAIL: skills add exited non-zero" >&2; exit 1; }
|
|
25
|
+
|
|
26
|
+
# The installer writes the canonical copy to .agents/skills/<name> and links Claude Code to it
|
|
27
|
+
# (other agents such as Amp get a rewritten copy under agent/skills; not checked here).
|
|
28
|
+
FOUND="$TMP/project/.agents/skills/$SKILL/SKILL.md"
|
|
29
|
+
[ -f "$FOUND" ] || { tail -20 "$TMP/install.log" >&2; echo "FAIL: .agents/skills/$SKILL/SKILL.md not found after install" >&2; exit 1; }
|
|
30
|
+
echo "landed: ${FOUND#"$TMP"/}"
|
|
31
|
+
[ -f "$TMP/project/.claude/skills/$SKILL/SKILL.md" ] || { echo "FAIL: Claude Code link .claude/skills/$SKILL missing" >&2; exit 1; }
|
|
32
|
+
echo "landed: project/.claude/skills/$SKILL/SKILL.md (Claude Code)"
|
|
33
|
+
|
|
34
|
+
# Only the requested skill may have been installed (no scry-setup riding along).
|
|
35
|
+
OTHERS="$(find "$TMP/project/.agents/skills" -mindepth 2 -maxdepth 2 -name SKILL.md ! -path "*/$SKILL/*" 2>/dev/null || true)"
|
|
36
|
+
[ -z "$OTHERS" ] || { echo "FAIL: unexpected extra skills installed: $OTHERS" >&2; exit 1; }
|
|
37
|
+
|
|
38
|
+
SKILL_MD="$FOUND" SKILL_NAME="$SKILL" node -e '
|
|
39
|
+
const fs = require("fs"), path = require("path");
|
|
40
|
+
const file = process.env.SKILL_MD, name = process.env.SKILL_NAME;
|
|
41
|
+
const text = fs.readFileSync(file, "utf8");
|
|
42
|
+
const m = /^---\r?\n([\s\S]*?)\r?\n---\r?\n/.exec(text);
|
|
43
|
+
if (!m) { console.error("FAIL: no YAML frontmatter"); process.exit(1); }
|
|
44
|
+
const fm = {};
|
|
45
|
+
for (const line of m[1].split(/\r?\n/)) { const k = /^([A-Za-z_-]+):\s*(.*)$/.exec(line); if (k) fm[k[1]] = k[2].trim(); }
|
|
46
|
+
if (fm.name !== name) { console.error(`FAIL: frontmatter name "${fm.name}" != "${name}"`); process.exit(1); }
|
|
47
|
+
if (!fm.description || fm.description.length < 40 || fm.description.length > 1024) { console.error("FAIL: description missing or outside 40..1024 chars"); process.exit(1); }
|
|
48
|
+
// every relative link in SKILL.md must resolve inside the installed skill
|
|
49
|
+
const dir = path.dirname(file), bad = [];
|
|
50
|
+
for (const l of text.matchAll(/\]\((?!https?:|#)([^)\s]+)\)/g)) if (!fs.existsSync(path.join(dir, l[1]))) bad.push(l[1]);
|
|
51
|
+
if (bad.length) { console.error("FAIL: broken relative links: " + bad.join(", ")); process.exit(1); }
|
|
52
|
+
const files = fs.readdirSync(dir, { recursive: true }).filter((f) => fs.statSync(path.join(dir, f)).isFile());
|
|
53
|
+
console.log(`frontmatter ok: name=${fm.name}, description ${fm.description.length} chars, ${files.length} files installed`);
|
|
54
|
+
'
|
|
55
|
+
|
|
56
|
+
# scry-native-capture-setup covers Flutter (feature flutter-capture): the Flutter files must have landed, the
|
|
57
|
+
# skill must not still refuse Flutter, and UIKit-only must still be refused with the pointer to bundle.md.
|
|
58
|
+
if [ "$SKILL" = scry-native-capture-setup ]; then
|
|
59
|
+
D="$TMP/project/.agents/skills/$SKILL"
|
|
60
|
+
for f in references/flutter.md references/bundle.md assets/make-scf.mjs assets/flutter/capture.sh assets/flutter/screens.dart \
|
|
61
|
+
assets/flutter/screens.json assets/flutter/scry_capture_test.dart assets/flutter/headless_scry_capture_test.dart \
|
|
62
|
+
assets/flutter/test_driver_integration_test.dart assets/flutter/scry_fonts.dart assets/flutter/scry_registry_test.dart; do
|
|
63
|
+
[ -f "$D/$f" ] || { echo "FAIL: $f missing from the installed skill" >&2; exit 1; }
|
|
64
|
+
done
|
|
65
|
+
if grep -Eqi 'not for[^.]*flutter|UIKit-only, Flutter' "$D/SKILL.md"; then
|
|
66
|
+
echo "FAIL: SKILL.md still refuses Flutter" >&2; exit 1
|
|
67
|
+
fi
|
|
68
|
+
grep -qi 'UIKit-only' "$D/SKILL.md" && grep -q 'references/bundle.md' "$D/SKILL.md" \
|
|
69
|
+
|| { echo "FAIL: SKILL.md no longer refuses UIKit-only with the pointer to references/bundle.md" >&2; exit 1; }
|
|
70
|
+
grep -q 'references/flutter.md' "$D/SKILL.md" || { echo "FAIL: SKILL.md does not link references/flutter.md" >&2; exit 1; }
|
|
71
|
+
echo "flutter: reference and assets installed, Flutter no longer refused, UIKit-only still refused"
|
|
72
|
+
fi
|
|
73
|
+
echo "PASS: $SKILL installs and parses"
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Drift check: the skill's assets/ are copies of the Kettle sample apps (the sample apps are canonical).
|
|
3
|
+
# Usage: bash scripts/check-skill-sync.sh <scry-sample-ios dir> <scry-sample-android dir> <scry-sample-flutter dir>
|
|
4
|
+
# Exit 0 = every copy matches its sample and the CI templates keep the G5 guards; 1 = drift (diff shown).
|
|
5
|
+
# The Flutter sample is the third argument; for the Flutter copies of make-scf.mjs (the sample's, iOS's and
|
|
6
|
+
# Android's) the rule is byte-identical to the skill asset (feature flutter-capture, guarantee 6); see the end.
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
[ $# -eq 3 ] || { echo "usage: $0 <ios-sample-dir> <android-sample-dir> <flutter-sample-dir>" >&2; exit 2; }
|
|
9
|
+
IOS="$1"; AND="$2"; FLU="$3"
|
|
10
|
+
ASSETS="$(cd "$(dirname "$0")/../skills/scry-native-capture-setup/assets" && pwd)"
|
|
11
|
+
AK="$AND/app/src"; fail=0
|
|
12
|
+
|
|
13
|
+
check() { # <asset> <sample file>
|
|
14
|
+
if [ ! -f "$2" ]; then echo "MISSING sample file: $2"; fail=1
|
|
15
|
+
elif diff -u "$2" "$ASSETS/$1" >"${TMPDIR:-/tmp}/skill-sync.diff"; then echo "ok $1 == $2"
|
|
16
|
+
else echo "DRIFT $1 differs from $2"; cat "${TMPDIR:-/tmp}/skill-sync.diff"; fail=1; fi
|
|
17
|
+
}
|
|
18
|
+
check ScryLaunch.swift "$IOS/Kettle/ScryLaunch.swift"
|
|
19
|
+
check ScryScreens.swift "$IOS/Kettle/ScryScreens.swift"
|
|
20
|
+
check capture-ios.sh "$IOS/scripts/capture.sh"
|
|
21
|
+
check make-scf.mjs "$IOS/scripts/make-scf.mjs"
|
|
22
|
+
check scry-capture-ios.yml "$IOS/.github/workflows/scry-capture.yml"
|
|
23
|
+
check ScryLaunch.kt "$(ls "$AK"/debug/java/*/*/*/ScryLaunch.kt 2>/dev/null | head -1)"
|
|
24
|
+
check ScryScreens.kt "$(ls "$AK"/debug/java/*/*/*/ScryScreens.kt 2>/dev/null | head -1)"
|
|
25
|
+
check ScryLaunch-release.kt "$(ls "$AK"/release/java/*/*/*/ScryLaunch.kt 2>/dev/null | head -1)"
|
|
26
|
+
check capture-android.sh "$AND/scripts/capture.sh"
|
|
27
|
+
check scry-capture-android.yml "$AND/.github/workflows/scry-capture.yml"
|
|
28
|
+
|
|
29
|
+
# Flutter (the sample is canonical for logic; screens.dart and screens.json are templates the user fills in, so
|
|
30
|
+
# they only have to exist in both places).
|
|
31
|
+
F="$ASSETS/flutter"
|
|
32
|
+
check flutter/scry_capture_test.dart "$FLU/integration_test/scry_capture_test.dart"
|
|
33
|
+
check flutter/test_driver_integration_test.dart "$FLU/test_driver/integration_test.dart"
|
|
34
|
+
check flutter/headless_scry_capture_test.dart "$FLU/test/scry_capture_test.dart"
|
|
35
|
+
check flutter/capture.sh "$FLU/scripts/capture.sh"
|
|
36
|
+
check flutter/scry_fonts.dart "$FLU/test/scry_fonts.dart"
|
|
37
|
+
check flutter/scry_registry_test.dart "$FLU/test/scry_registry_test.dart"
|
|
38
|
+
for t in screens.dart screens.json; do [ -f "$F/$t" ] && echo "ok flutter/$t template present" || { echo "MISSING flutter/$t template"; fail=1; }; done
|
|
39
|
+
[ -f "$FLU/integration_test/scry/screens.dart" ] && [ -f "$FLU/scripts/screens.json" ] \
|
|
40
|
+
&& echo "ok Flutter sample has its registry and screens.json" || { echo "MISSING Flutter sample registry or screens.json"; fail=1; }
|
|
41
|
+
check make-scf.mjs "$FLU/scripts/make-scf.mjs"
|
|
42
|
+
# make-scf.mjs is shared and must be byte-identical in the skill and all three samples (the iOS copy is checked above).
|
|
43
|
+
check make-scf.mjs "$AND/scripts/make-scf.mjs"
|
|
44
|
+
|
|
45
|
+
# G5 on the CI templates: default branch only, no pull_request(_target), no self-hosted, key only on upload.
|
|
46
|
+
for y in scry-capture-ios.yml scry-capture-android.yml; do
|
|
47
|
+
f="$ASSETS/$y"
|
|
48
|
+
grep -Eq '^\s*(pull_request|pull_request_target)\s*:' "$f" && { echo "G5 FAIL $y: pull_request trigger"; fail=1; }
|
|
49
|
+
grep -qi 'self-hosted' "$f" && { echo "G5 FAIL $y: self-hosted"; fail=1; }
|
|
50
|
+
grep -q 'branches: \[main\]' "$f" || { echo "G5 FAIL $y: not limited to a branch"; fail=1; }
|
|
51
|
+
n="$(grep -c 'secrets\.' "$f")"; [ "$n" -eq 1 ] || { echo "G5 FAIL $y: secrets referenced $n times (want 1, the upload step)"; fail=1; }
|
|
52
|
+
done
|
|
53
|
+
[ "$fail" -eq 0 ] && echo "PASS: skill assets match the samples, CI guards intact" || { echo "FAIL: drift found" >&2; exit 1; }
|