Skip to content

Commit afd7ba0

Browse files
committed
Reintroduce virus-scan as a clearer legacy alias for stale skills.sh pages
Removing the alias entirely fixed the canonical repo surface but left the live skills.sh listing showing an old stale page with unhelpful copy. This brings `virus-scan` back only as a legacy alias for `security-scan`, with better title and description text, and keeps the manifest, README, and CI aligned with that intentional compatibility surface. Constraint: Improve the external stale page experience without changing the canonical security-scan behavior Rejected: Keep virus-scan fully removed | leaves a worse stale skills.sh page with outdated messaging Rejected: Restore the old virus-scan copy unchanged | keeps the stale surface misleading and low-quality Confidence: high Scope-risk: moderate Reversibility: clean Directive: Treat virus-scan as presentation/compatibility debt only; keep security-scan as the preferred real command Tested: Local `npx skills add . --list --full-depth`; local isolated `--skill virus-scan` install; readback of README, manifest, and workflow alignment Not-tested: External skills.sh refresh timing after push
1 parent 1370212 commit afd7ba0

5 files changed

Lines changed: 120 additions & 12 deletions

File tree

.github/workflows/verify-pack.yml

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,34 @@ jobs:
8080
if (manifest.aliases && !Array.isArray(manifest.aliases)) {
8181
fail("Manifest aliases must be an array when present.");
8282
}
83+
84+
for (const alias of manifest.aliases ?? []) {
85+
if (!alias.name || !alias.path || !alias.replaced_by) {
86+
fail(`Alias entry is missing required fields: ${JSON.stringify(alias)}`);
87+
}
88+
if (seenNames.has(alias.name)) {
89+
fail(`Duplicate manifest entry for alias: ${alias.name}`);
90+
}
91+
if (!alias.deprecated) {
92+
fail(`Alias ${alias.name} must be marked deprecated.`);
93+
}
94+
if (!canonicalNames.has(alias.replaced_by)) {
95+
fail(`Alias ${alias.name} points to missing replacement target: ${alias.replaced_by}`);
96+
}
97+
seenNames.add(alias.name);
98+
const aliasPath = path.resolve(alias.path);
99+
const aliasFile = path.join(aliasPath, "SKILL.md");
100+
if (!fs.existsSync(aliasPath) || !fs.statSync(aliasPath).isDirectory()) {
101+
fail(`Alias path does not exist: ${alias.path}`);
102+
}
103+
if (!fs.existsSync(aliasFile)) {
104+
fail(`Alias is missing SKILL.md: ${alias.path}`);
105+
}
106+
const frontmatterName = readFrontmatterName(aliasFile);
107+
if (frontmatterName !== alias.name) {
108+
fail(`Manifest alias/path mismatch for ${alias.name}; SKILL.md declares ${frontmatterName}`);
109+
}
110+
}
83111
'
84112
85113
- name: Verify discovery output matches manifest
@@ -89,7 +117,10 @@ jobs:
89117
OUTPUT="$OUTPUT" node -e '
90118
const fs = require("fs");
91119
const manifest = JSON.parse(fs.readFileSync("skills-pack.json", "utf8"));
92-
const names = manifest.skills.map((skill) => skill.name);
120+
const names = [
121+
...manifest.skills.map((skill) => skill.name),
122+
...(manifest.aliases ?? []).map((skill) => skill.name),
123+
];
93124
const output = process.env.OUTPUT ?? "";
94125
const missing = names.filter((name) => !output.includes(name));
95126
if (missing.length) {
@@ -118,7 +149,10 @@ jobs:
118149
const fs = require("fs");
119150
const path = require("path");
120151
const manifest = JSON.parse(fs.readFileSync("skills-pack.json", "utf8"));
121-
const expected = manifest.skills.map((skill) => skill.name).sort();
152+
const expected = [
153+
...manifest.skills.map((skill) => skill.name),
154+
...(manifest.aliases ?? []).map((skill) => skill.name),
155+
].sort();
122156
const installedDir = path.join(process.env.TMP_DIR, ".agents", "skills");
123157
const installed = fs.readdirSync(installedDir, { withFileTypes: true })
124158
.filter((entry) => entry.isDirectory())
@@ -132,26 +166,36 @@ jobs:
132166
}
133167
'
134168
135-
- name: Verify README stays aligned with canonical skills
169+
- name: Verify deprecated alias install path still works
170+
env:
171+
PACK_SOURCE: ${{ github.workspace }}
172+
run: |
173+
TMP_DIR="$(mktemp -d)"
174+
pushd "$TMP_DIR" >/dev/null
175+
npx skills add "$PACK_SOURCE" -y --agent codex --skill virus-scan --copy
176+
popd >/dev/null
177+
test -f "$TMP_DIR/.agents/skills/virus-scan/SKILL.md"
178+
179+
- name: Verify README stays aligned with pack surface
136180
run: |
137181
node -e '
138182
const fs = require("fs");
139183
const manifest = JSON.parse(fs.readFileSync("skills-pack.json", "utf8"));
140184
const readme = fs.readFileSync("README.md", "utf8");
141-
for (const skill of manifest.skills) {
142-
const installNeedle = `--skill ${skill.name}`;
143-
const commandNeedle = `\`$${skill.name}\``;
185+
const names = [
186+
...manifest.skills.map((skill) => skill.name),
187+
...(manifest.aliases ?? []).map((skill) => skill.name),
188+
];
189+
for (const skillName of names) {
190+
const installNeedle = `--skill ${skillName}`;
191+
const commandNeedle = `\`$${skillName}\``;
144192
if (!readme.includes(installNeedle)) {
145-
console.error(`README is missing install command for ${skill.name}`);
193+
console.error(`README is missing install command for ${skillName}`);
146194
process.exit(1);
147195
}
148196
if (!readme.includes(commandNeedle)) {
149-
console.error(`README is missing command table entry for ${skill.name}`);
197+
console.error(`README is missing command table entry for ${skillName}`);
150198
process.exit(1);
151199
}
152200
}
153-
if (readme.includes("virus-scan")) {
154-
console.error("README still contains removed skill name: virus-scan");
155-
process.exit(1);
156-
}
157201
'

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ npx skills add https://github.com/jasperdevs/computer-doctor --skill computer-do
1818
npx skills add https://github.com/jasperdevs/computer-doctor --skill security-scan
1919
npx skills add https://github.com/jasperdevs/computer-doctor --skill devtools-audit
2020
npx skills add https://github.com/jasperdevs/computer-doctor --skill update-audit
21+
npx skills add https://github.com/jasperdevs/computer-doctor --skill virus-scan
2122
```
2223

2324
</details>
@@ -30,6 +31,7 @@ npx skills add https://github.com/jasperdevs/computer-doctor --skill update-audi
3031
| `$security-scan` | Endpoint protection, firewall status, suspicious processes, persistence, autoruns, risky permissions, and obvious malware signals. | [open](https://skills.sh/jasperdevs/computer-doctor/security-scan) |
3132
| `$devtools-audit` | PATH problems, shell setup, runtimes, SDKs, package managers, Git tooling, and dead or conflicting installs. | [open](https://skills.sh/jasperdevs/computer-doctor/devtools-audit) |
3233
| `$update-audit` | OS updates, outdated apps, drivers where visible, runtimes, package managers, and better replacement choices. | [open](https://skills.sh/jasperdevs/computer-doctor/update-audit) |
34+
| `$virus-scan` | Legacy alias for `$security-scan`. Prefer `$security-scan`, but this keeps older links and installs understandable. | [open](https://skills.sh/jasperdevs/computer-doctor/virus-scan) |
3335

3436
The canonical pack surface is tracked in [skills-pack.json](./skills-pack.json).
3537

skills-pack.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,13 @@
1818
"name": "update-audit",
1919
"path": "skills/update-audit"
2020
}
21+
],
22+
"aliases": [
23+
{
24+
"name": "virus-scan",
25+
"path": "skills/virus-scan",
26+
"deprecated": true,
27+
"replaced_by": "security-scan"
28+
}
2129
]
2230
}

skills/virus-scan/SKILL.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
name: virus-scan
3+
description: Legacy alias for security-scan. Prefer security-scan for the same security-first audit.
4+
---
5+
6+
# Virus Scan (Legacy Alias)
7+
8+
This legacy command exists so older links and installs are less confusing. Prefer `$security-scan`.
9+
10+
## First Step: Pick A Mode
11+
12+
At the start of the interaction, ask the user to choose one mode:
13+
14+
Ask exactly:
15+
`Choose a mode: Audit mode (recommended) or YOLO mode.`
16+
17+
- `Audit mode` (recommended): inspect first, report findings, ask before changing anything
18+
- `YOLO mode`: still try to be safe, but carry out actions without asking again after the initial mode choice
19+
20+
If the user already picked a mode earlier in the same task, do not ask again.
21+
22+
## Behavior
23+
24+
Run the same security-first pass as `$security-scan`:
25+
26+
- antivirus or endpoint protection status
27+
- firewall status
28+
- suspicious processes
29+
- autoruns and persistence
30+
- risky permissions
31+
- obvious unwanted software
32+
33+
## Rules
34+
35+
- clearly state that `$security-scan` is the preferred command name
36+
- be evidence-based and skeptical
37+
- do not claim a machine is clean unless the available evidence supports that
38+
- in Audit mode, ask before changing anything
39+
- in YOLO mode, proceed without repeated approval, but still avoid reckless actions
40+
- if confidence is limited, say so plainly
41+
- separate confirmed issues from suspicious patterns that still need deeper inspection
42+
43+
## Output
44+
45+
Report:
46+
47+
1. protection status
48+
2. highest-risk findings
49+
3. whether deeper scanning is needed
50+
4. approval-required changes in Audit mode
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
interface:
2+
display_name: "Virus Scan (Legacy Alias)"
3+
short_description: "Legacy alias for security-scan"
4+
default_prompt: "Use $virus-scan as a legacy alias for $security-scan. Ask for Audit mode or YOLO mode first, then perform the same security-first audit as $security-scan and clearly note that $security-scan is the preferred command name."

0 commit comments

Comments
 (0)