@aicf/agent-skills 1.0.0-rc.4
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/.codex-plugin/plugin.json +40 -0
- package/CHANGELOG.md +28 -0
- package/LICENSE +21 -0
- package/README.md +114 -0
- package/assets/aicf-agent-skills-icon.svg +7 -0
- package/assets/aicf-agent-skills-logo.svg +9 -0
- package/docs/codex-plugin-distribution.md +50 -0
- package/docs/installation.md +96 -0
- package/docs/public-release-checklist.md +57 -0
- package/docs/skill-authoring-standard.md +55 -0
- package/docs/skill-index.md +157 -0
- package/docs/validation.md +50 -0
- package/package.json +61 -0
- package/scripts/README.md +6 -0
- package/scripts/aicf-skills.mjs +51 -0
- package/scripts/check-release-readiness.mjs +197 -0
- package/scripts/check-skills-public.mjs +12 -0
- package/scripts/check-trigger-coverage.mjs +20 -0
- package/scripts/generate-skill-index.mjs +30 -0
- package/scripts/install-skills.mjs +31 -0
- package/scripts/lib/skill-common.mjs +511 -0
- package/scripts/validate-skills.mjs +13 -0
- package/skills/README.md +12 -0
- package/skills/aicf-action-lifecycle/SKILL.md +87 -0
- package/skills/aicf-action-lifecycle/assets/action-handler.template.ts +24 -0
- package/skills/aicf-action-lifecycle/assets/approval-record.json +9 -0
- package/skills/aicf-action-lifecycle/assets/prepared-action-record.json +11 -0
- package/skills/aicf-action-lifecycle/references/action-state-machine.md +17 -0
- package/skills/aicf-action-lifecycle/references/approval-patterns.md +9 -0
- package/skills/aicf-action-lifecycle/references/idempotency-and-audit.md +8 -0
- package/skills/aicf-action-lifecycle/references/verification-patterns.md +7 -0
- package/skills/aicf-capability-authoring/SKILL.md +100 -0
- package/skills/aicf-capability-authoring/assets/capability.manifest.yaml +31 -0
- package/skills/aicf-capability-authoring/assets/entity.manifest.yaml +12 -0
- package/skills/aicf-capability-authoring/assets/eval-case.yaml +12 -0
- package/skills/aicf-capability-authoring/references/checklist.md +13 -0
- package/skills/aicf-capability-authoring/references/examples.md +12 -0
- package/skills/aicf-capability-authoring/references/field-guide.md +13 -0
- package/skills/aicf-capability-authoring/references/manifest-decision-tree.md +10 -0
- package/skills/aicf-control-plane-ui/SKILL.md +90 -0
- package/skills/aicf-control-plane-ui/assets/control-plane-wireframe.md +29 -0
- package/skills/aicf-control-plane-ui/assets/ui-acceptance-checklist.md +11 -0
- package/skills/aicf-control-plane-ui/references/api-contracts.md +14 -0
- package/skills/aicf-control-plane-ui/references/approval-console.md +12 -0
- package/skills/aicf-control-plane-ui/references/control-plane-screens.md +14 -0
- package/skills/aicf-control-plane-ui/references/operational-ux.md +7 -0
- package/skills/aicf-controls-and-budgets/SKILL.md +88 -0
- package/skills/aicf-controls-and-budgets/assets/budget-fixture.json +15 -0
- package/skills/aicf-controls-and-budgets/assets/controls-policy.yaml +14 -0
- package/skills/aicf-controls-and-budgets/references/budget-policy.md +12 -0
- package/skills/aicf-controls-and-budgets/references/circuit-breakers.md +13 -0
- package/skills/aicf-controls-and-budgets/references/control-types.md +10 -0
- package/skills/aicf-docs-and-examples/SKILL.md +87 -0
- package/skills/aicf-docs-and-examples/assets/example-readme-template.md +21 -0
- package/skills/aicf-docs-and-examples/assets/provider-guide-template.md +17 -0
- package/skills/aicf-docs-and-examples/references/docs-style-guide.md +9 -0
- package/skills/aicf-docs-and-examples/references/example-app-checklist.md +9 -0
- package/skills/aicf-docs-and-examples/references/public-api-docs.md +11 -0
- package/skills/aicf-docs-and-examples/references/quickstart-template.md +17 -0
- package/skills/aicf-eval-authoring/SKILL.md +86 -0
- package/skills/aicf-eval-authoring/assets/eval-case.yaml +17 -0
- package/skills/aicf-eval-authoring/assets/eval-result.json +15 -0
- package/skills/aicf-eval-authoring/assets/promptfoo.config.yaml +12 -0
- package/skills/aicf-eval-authoring/references/deterministic-scorers.md +13 -0
- package/skills/aicf-eval-authoring/references/eval-rubric.md +10 -0
- package/skills/aicf-eval-authoring/references/golden-test-patterns.md +8 -0
- package/skills/aicf-eval-authoring/references/real-provider-evals.md +8 -0
- package/skills/aicf-governance-lifecycle/SKILL.md +91 -0
- package/skills/aicf-governance-lifecycle/assets/lifecycle-change-request.md +21 -0
- package/skills/aicf-governance-lifecycle/assets/riskwaiver.md +17 -0
- package/skills/aicf-governance-lifecycle/references/compatibility-checks.md +21 -0
- package/skills/aicf-governance-lifecycle/references/impact-analysis.md +13 -0
- package/skills/aicf-governance-lifecycle/references/lifecycle-state-machine.md +15 -0
- package/skills/aicf-governance-lifecycle/references/riskcompiler-rules.md +13 -0
- package/skills/aicf-migration/SKILL.md +87 -0
- package/skills/aicf-migration/assets/legacy-tool-inventory.csv +3 -0
- package/skills/aicf-migration/assets/migration-plan.md +19 -0
- package/skills/aicf-migration/references/conversion-playbook.md +9 -0
- package/skills/aicf-migration/references/legacy-tool-riskmap.md +14 -0
- package/skills/aicf-migration/references/migration-inventory.md +12 -0
- package/skills/aicf-migration/references/rollout-plan.md +12 -0
- package/skills/aicf-observability-replay/SKILL.md +88 -0
- package/skills/aicf-observability-replay/assets/replay-fixture.json +23 -0
- package/skills/aicf-observability-replay/assets/trace-to-golden-template.yaml +14 -0
- package/skills/aicf-observability-replay/references/redacted-telemetry.md +7 -0
- package/skills/aicf-observability-replay/references/replay-simulation.md +10 -0
- package/skills/aicf-observability-replay/references/trace-span-map.md +17 -0
- package/skills/aicf-observability-replay/references/trace-to-golden.md +12 -0
- package/skills/aicf-policy-and-risk/SKILL.md +88 -0
- package/skills/aicf-policy-and-risk/assets/policy-broker.template.ts +29 -0
- package/skills/aicf-policy-and-risk/assets/policy-decision-fixture.json +15 -0
- package/skills/aicf-policy-and-risk/references/deny-approval-allow-matrix.md +12 -0
- package/skills/aicf-policy-and-risk/references/policy-broker-contract.md +13 -0
- package/skills/aicf-policy-and-risk/references/risktier-rules.md +10 -0
- package/skills/aicf-policy-and-risk/references/semantic-invariants.md +9 -0
- package/skills/aicf-provider-conformance/SKILL.md +88 -0
- package/skills/aicf-provider-conformance/assets/provider-conformance-case.yaml +18 -0
- package/skills/aicf-provider-conformance/assets/provider-matrix.json +19 -0
- package/skills/aicf-provider-conformance/references/provider-normalization-matrix.md +14 -0
- package/skills/aicf-provider-conformance/references/provider-runtime-boundaries.md +10 -0
- package/skills/aicf-provider-conformance/references/schema-compatibility.md +8 -0
- package/skills/aicf-provider-conformance/references/tool-call-mapping.md +8 -0
- package/skills/aicf-release-hygiene/SKILL.md +85 -0
- package/skills/aicf-release-hygiene/assets/release-report-template.md +19 -0
- package/skills/aicf-release-hygiene/references/forbidden-artifacts.md +12 -0
- package/skills/aicf-release-hygiene/references/package-smoke-test.md +10 -0
- package/skills/aicf-release-hygiene/references/release-checklist.md +10 -0
- package/skills/aicf-release-hygiene/references/source-archive-rules.md +8 -0
- package/skills/aicf-runtime-integration/SKILL.md +87 -0
- package/skills/aicf-runtime-integration/assets/context-builder.template.ts +22 -0
- package/skills/aicf-runtime-integration/assets/handler-registry.template.ts +20 -0
- package/skills/aicf-runtime-integration/assets/runtime-integration-plan.md +23 -0
- package/skills/aicf-runtime-integration/references/capability-router-patterns.md +8 -0
- package/skills/aicf-runtime-integration/references/context-builder-patterns.md +8 -0
- package/skills/aicf-runtime-integration/references/handler-registry-patterns.md +8 -0
- package/skills/aicf-runtime-integration/references/policy-broker-adapter.md +8 -0
- package/skills/aicf-runtime-integration/references/runtime-integration-checklist.md +10 -0
- package/skills/aicf-security-redteam/SKILL.md +89 -0
- package/skills/aicf-security-redteam/assets/promptfoo-redteam.config.yaml +13 -0
- package/skills/aicf-security-redteam/assets/redteam-case.yaml +15 -0
- package/skills/aicf-security-redteam/references/prompt-injection-patterns.md +12 -0
- package/skills/aicf-security-redteam/references/redteam-acceptance.md +11 -0
- package/skills/aicf-security-redteam/references/security-test-pack-map.md +11 -0
- package/skills/aicf-security-redteam/references/tool-misuse-patterns.md +11 -0
- package/skills/aicf-skill-pack-maintenance/SKILL.md +88 -0
- package/skills/aicf-skill-pack-maintenance/assets/skill-template.md +52 -0
- package/skills/aicf-skill-pack-maintenance/references/overlap-prevention.md +9 -0
- package/skills/aicf-skill-pack-maintenance/references/plugin-packaging.md +8 -0
- package/skills/aicf-skill-pack-maintenance/references/skill-authoring-rules.md +10 -0
- package/skills/aicf-skill-pack-maintenance/references/trigger-evaluation.md +9 -0
- package/skills/aicf-storage-and-aws/SKILL.md +86 -0
- package/skills/aicf-storage-and-aws/assets/dynamodb-store.template.ts +21 -0
- package/skills/aicf-storage-and-aws/assets/postgres-store.template.ts +22 -0
- package/skills/aicf-storage-and-aws/assets/step-functions-approval.template.ts +15 -0
- package/skills/aicf-storage-and-aws/references/aws-adapter-boundaries.md +8 -0
- package/skills/aicf-storage-and-aws/references/least-privilege-iam.md +11 -0
- package/skills/aicf-storage-and-aws/references/step-functions-approval.md +10 -0
- package/skills/aicf-storage-and-aws/references/store-interface-map.md +10 -0
- package/skills/aicf-trust-redaction-retention/SKILL.md +88 -0
- package/skills/aicf-trust-redaction-retention/assets/redaction-policy.yaml +15 -0
- package/skills/aicf-trust-redaction-retention/assets/trust-labelled-context.json +18 -0
- package/skills/aicf-trust-redaction-retention/references/redaction-rules.md +8 -0
- package/skills/aicf-trust-redaction-retention/references/retention-rules.md +11 -0
- package/skills/aicf-trust-redaction-retention/references/taint-rules.md +9 -0
- package/skills/aicf-trust-redaction-retention/references/trust-labels.md +16 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Validation
|
|
2
|
+
|
|
3
|
+
Run validation from `agent-skills/`.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm run validate
|
|
7
|
+
npm run check:triggers
|
|
8
|
+
npm run index
|
|
9
|
+
npm run check:index
|
|
10
|
+
npm run test
|
|
11
|
+
npm run check:public
|
|
12
|
+
npm run check:release
|
|
13
|
+
npm run check
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Expected output from a healthy package includes:
|
|
17
|
+
|
|
18
|
+
- `Skill validation passed`
|
|
19
|
+
- `Trigger coverage passed`
|
|
20
|
+
- `Generated ... docs/skill-index.md`
|
|
21
|
+
- `Skill index is current`
|
|
22
|
+
- `Agent skills release readiness passed`
|
|
23
|
+
|
|
24
|
+
## What Each Check Covers
|
|
25
|
+
|
|
26
|
+
- `validate`: skill folder names, `SKILL.md` frontmatter, MIT license, AICF metadata,
|
|
27
|
+
required sections, one-level references/assets, parseable JSON/YAML, and public-safety
|
|
28
|
+
markers.
|
|
29
|
+
- `check:triggers`: every real skill has positive and negative trigger examples, and
|
|
30
|
+
fixture description terms match the skill descriptions.
|
|
31
|
+
- `index`: regenerates `docs/skill-index.md` from skill metadata and trigger fixtures.
|
|
32
|
+
- `check:index`: verifies `docs/skill-index.md` is current without writing files.
|
|
33
|
+
- `test`: runs deterministic Node tests for validation, trigger coverage, package
|
|
34
|
+
metadata, npm dry-run contents, and install behavior.
|
|
35
|
+
- `check:public`: scans npm dry-run contents for forbidden paths, archives, generated
|
|
36
|
+
output, dependency folders, and high-confidence credential markers.
|
|
37
|
+
- `check:release`: verifies the final 17-skill inventory, plugin metadata, docs, package
|
|
38
|
+
scripts, relative asset paths, trigger fixtures, npm dry-run contents, and public
|
|
39
|
+
package hygiene.
|
|
40
|
+
|
|
41
|
+
## Common Failures
|
|
42
|
+
|
|
43
|
+
- Stale index: run `npm run index`, then `npm run check:index`.
|
|
44
|
+
- Missing trigger coverage: update `tests/fixtures/trigger-prompts.json`.
|
|
45
|
+
- Broken reference link: link only to one-level `references/`, `assets/`, or `scripts/`
|
|
46
|
+
files inside the skill folder.
|
|
47
|
+
- Package public-safety failure: remove the unsafe text or move local/private material
|
|
48
|
+
to an ignored path outside the package.
|
|
49
|
+
- Pack content failure: update `package.json` `files`, package docs, or the
|
|
50
|
+
public-safety rules so dry-run contents match the release boundary.
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aicf/agent-skills",
|
|
3
|
+
"version": "1.0.0-rc.4",
|
|
4
|
+
"description": "Agent Skills for building, integrating, testing, auditing, and releasing AICF-based AI capability systems.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"private": false,
|
|
8
|
+
"homepage": "https://github.com/xennon101/ai-capability-framework/tree/main/agent-skills#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/xennon101/ai-capability-framework.git",
|
|
12
|
+
"directory": "agent-skills"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/xennon101/ai-capability-framework/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"aicf",
|
|
19
|
+
"agent-skills",
|
|
20
|
+
"codex",
|
|
21
|
+
"capabilities",
|
|
22
|
+
"evals",
|
|
23
|
+
"governance",
|
|
24
|
+
"runtime",
|
|
25
|
+
"tool-calling"
|
|
26
|
+
],
|
|
27
|
+
"files": [
|
|
28
|
+
".codex-plugin",
|
|
29
|
+
"skills",
|
|
30
|
+
"scripts",
|
|
31
|
+
"docs",
|
|
32
|
+
"assets",
|
|
33
|
+
"README.md",
|
|
34
|
+
"LICENSE",
|
|
35
|
+
"CHANGELOG.md"
|
|
36
|
+
],
|
|
37
|
+
"bin": {
|
|
38
|
+
"aicf-skills": "scripts/aicf-skills.mjs"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"validate": "node scripts/validate-skills.mjs ./skills",
|
|
42
|
+
"check:public": "node scripts/check-skills-public.mjs .",
|
|
43
|
+
"check:triggers": "node scripts/check-trigger-coverage.mjs ./skills ./tests/fixtures/trigger-prompts.json",
|
|
44
|
+
"index": "node scripts/generate-skill-index.mjs ./skills ./docs/skill-index.md",
|
|
45
|
+
"check:index": "node scripts/generate-skill-index.mjs ./skills ./docs/skill-index.md --check",
|
|
46
|
+
"test": "node --test tests/*.test.mjs",
|
|
47
|
+
"check:release": "node scripts/check-release-readiness.mjs",
|
|
48
|
+
"check": "npm run validate && npm run check:triggers && npm run check:index && npm run test && npm run check:public && npm run check:release",
|
|
49
|
+
"pack:dry": "npm pack --dry-run"
|
|
50
|
+
},
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=20"
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"yaml": "^2.8.0"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {},
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"access": "public"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import {
|
|
4
|
+
packageRoot,
|
|
5
|
+
resolvePath,
|
|
6
|
+
skillSummaries
|
|
7
|
+
} from "./lib/skill-common.mjs";
|
|
8
|
+
|
|
9
|
+
const command = process.argv[2] ?? "help";
|
|
10
|
+
const root = packageRoot();
|
|
11
|
+
|
|
12
|
+
switch (command) {
|
|
13
|
+
case "validate":
|
|
14
|
+
run("validate-skills.mjs", ["./skills"]);
|
|
15
|
+
break;
|
|
16
|
+
case "check-public":
|
|
17
|
+
run("check-skills-public.mjs", ["."]);
|
|
18
|
+
break;
|
|
19
|
+
case "check-triggers":
|
|
20
|
+
run("check-trigger-coverage.mjs", ["./skills", "./tests/fixtures/trigger-prompts.json"]);
|
|
21
|
+
break;
|
|
22
|
+
case "index":
|
|
23
|
+
run("generate-skill-index.mjs", ["./skills", "./docs/skill-index.md"]);
|
|
24
|
+
break;
|
|
25
|
+
case "install":
|
|
26
|
+
run("install-skills.mjs", process.argv.slice(3));
|
|
27
|
+
break;
|
|
28
|
+
case "list":
|
|
29
|
+
list();
|
|
30
|
+
break;
|
|
31
|
+
default:
|
|
32
|
+
console.log("Usage: aicf-skills <validate|check-public|check-triggers|index|install|list>");
|
|
33
|
+
process.exitCode = command === "help" ? 0 : 1;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function run(script, args) {
|
|
37
|
+
const result = spawnSync(process.execPath, [resolvePath(root, `./scripts/${script}`), ...args], {
|
|
38
|
+
cwd: root,
|
|
39
|
+
stdio: "inherit"
|
|
40
|
+
});
|
|
41
|
+
process.exitCode = result.status ?? 1;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function list() {
|
|
45
|
+
const skills = skillSummaries(resolvePath(root, "./skills"));
|
|
46
|
+
if (skills.length === 0) {
|
|
47
|
+
console.log("No AICF Agent Skills are installed in this package yet.");
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
for (const skill of skills) console.log(`${skill.name}\t${skill.description}`);
|
|
51
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import {
|
|
5
|
+
expectedSkillNames,
|
|
6
|
+
forbiddenPathFailures,
|
|
7
|
+
listSkillDirs,
|
|
8
|
+
loadTriggerFixture,
|
|
9
|
+
normalizePath,
|
|
10
|
+
npmPackFiles,
|
|
11
|
+
packageRoot,
|
|
12
|
+
parseSkillFile,
|
|
13
|
+
publicPackageFailures,
|
|
14
|
+
readJson,
|
|
15
|
+
readText,
|
|
16
|
+
validateSkills
|
|
17
|
+
} from "./lib/skill-common.mjs";
|
|
18
|
+
|
|
19
|
+
const root = packageRoot();
|
|
20
|
+
const failures = [];
|
|
21
|
+
|
|
22
|
+
checkPackageMetadata();
|
|
23
|
+
checkPluginMetadata();
|
|
24
|
+
checkSkills();
|
|
25
|
+
checkTriggerFixtures();
|
|
26
|
+
checkDocs();
|
|
27
|
+
checkPackContents();
|
|
28
|
+
checkPublicScan();
|
|
29
|
+
|
|
30
|
+
if (failures.length > 0) {
|
|
31
|
+
console.error(failures.join("\n"));
|
|
32
|
+
process.exitCode = 1;
|
|
33
|
+
} else {
|
|
34
|
+
console.log("Agent skills release readiness passed.");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function checkPackageMetadata() {
|
|
38
|
+
const pkg = readJson(path.join(root, "package.json"));
|
|
39
|
+
expect(pkg.name === "@aicf/agent-skills", "package.json: name must be @aicf/agent-skills.");
|
|
40
|
+
expect(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(pkg.version), "package.json: version must be semver-like.");
|
|
41
|
+
expect(pkg.private === false, "package.json: private must be false.");
|
|
42
|
+
expect(pkg.license === "MIT", "package.json: license must be MIT.");
|
|
43
|
+
expect(pkg.publishConfig?.access === "public", "package.json: publishConfig.access must be public.");
|
|
44
|
+
expect(pkg.type === "module", "package.json: type must be module.");
|
|
45
|
+
expect(pkg.bin?.["aicf-skills"] === "scripts/aicf-skills.mjs", "package.json: bin.aicf-skills must point to scripts/aicf-skills.mjs.");
|
|
46
|
+
|
|
47
|
+
for (const rel of [
|
|
48
|
+
"scripts/validate-skills.mjs",
|
|
49
|
+
"scripts/check-skills-public.mjs",
|
|
50
|
+
"scripts/check-trigger-coverage.mjs",
|
|
51
|
+
"scripts/generate-skill-index.mjs",
|
|
52
|
+
"scripts/install-skills.mjs",
|
|
53
|
+
"scripts/aicf-skills.mjs",
|
|
54
|
+
"scripts/check-release-readiness.mjs"
|
|
55
|
+
]) {
|
|
56
|
+
requireFile(rel);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const requiredScripts = {
|
|
60
|
+
validate: "node scripts/validate-skills.mjs ./skills",
|
|
61
|
+
"check:public": "node scripts/check-skills-public.mjs .",
|
|
62
|
+
"check:triggers": "node scripts/check-trigger-coverage.mjs ./skills ./tests/fixtures/trigger-prompts.json",
|
|
63
|
+
index: "node scripts/generate-skill-index.mjs ./skills ./docs/skill-index.md",
|
|
64
|
+
"check:index": "node scripts/generate-skill-index.mjs ./skills ./docs/skill-index.md --check",
|
|
65
|
+
test: "node --test tests/*.test.mjs",
|
|
66
|
+
"check:release": "node scripts/check-release-readiness.mjs",
|
|
67
|
+
"pack:dry": "npm pack --dry-run"
|
|
68
|
+
};
|
|
69
|
+
for (const [scriptName, expected] of Object.entries(requiredScripts)) {
|
|
70
|
+
expect(pkg.scripts?.[scriptName] === expected, `package.json: script ${scriptName} must be "${expected}".`);
|
|
71
|
+
}
|
|
72
|
+
expect(String(pkg.scripts?.check ?? "").includes("npm run check:index"), "package.json: check must include check:index.");
|
|
73
|
+
expect(String(pkg.scripts?.check ?? "").includes("npm run check:release"), "package.json: check must include check:release.");
|
|
74
|
+
|
|
75
|
+
for (const requiredFileEntry of [".codex-plugin", "skills", "scripts", "docs", "assets", "README.md", "LICENSE", "CHANGELOG.md"]) {
|
|
76
|
+
expect(pkg.files?.includes(requiredFileEntry), `package.json: files must include ${requiredFileEntry}.`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function checkPluginMetadata() {
|
|
81
|
+
const pkg = readJson(path.join(root, "package.json"));
|
|
82
|
+
const plugin = readJson(path.join(root, ".codex-plugin", "plugin.json"));
|
|
83
|
+
expect(plugin.name === "aicf-agent-skills", ".codex-plugin/plugin.json: name must be aicf-agent-skills.");
|
|
84
|
+
expect(plugin.version === pkg.version, ".codex-plugin/plugin.json: version must match package.json.");
|
|
85
|
+
expect(plugin.license === "MIT", ".codex-plugin/plugin.json: license must be MIT.");
|
|
86
|
+
expect(plugin.skills === "./skills/", ".codex-plugin/plugin.json: skills must be ./skills/.");
|
|
87
|
+
checkRelativeExistingPath(plugin.interface?.composerIcon, "composerIcon");
|
|
88
|
+
checkRelativeExistingPath(plugin.interface?.logo, "logo");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function checkSkills() {
|
|
92
|
+
const skillsRoot = path.join(root, "skills");
|
|
93
|
+
const actualNames = listSkillDirs(skillsRoot).map((skillDir) => path.basename(skillDir)).sort();
|
|
94
|
+
const expectedNames = [...expectedSkillNames].sort();
|
|
95
|
+
expect(JSON.stringify(actualNames) === JSON.stringify(expectedNames), `skills/: expected exactly ${expectedNames.length} skills.`);
|
|
96
|
+
|
|
97
|
+
for (const failure of validateSkills(skillsRoot, { root })) failures.push(failure);
|
|
98
|
+
|
|
99
|
+
const pkg = readJson(path.join(root, "package.json"));
|
|
100
|
+
for (const skillName of expectedNames) {
|
|
101
|
+
const parsed = parseSkillFile(path.join(skillsRoot, skillName, "SKILL.md"));
|
|
102
|
+
expect(parsed.frontmatter.license === "MIT", `${skillName}: license must be MIT.`);
|
|
103
|
+
expect(parsed.frontmatter.metadata?.["aicf.skill.package"] === pkg.name, `${skillName}: metadata package must match package.json.`);
|
|
104
|
+
expect(parsed.frontmatter.metadata?.["aicf.skill.version"] === pkg.version, `${skillName}: metadata version must match package.json.`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function checkTriggerFixtures() {
|
|
109
|
+
const fixture = loadTriggerFixture(path.join(root, "tests", "fixtures", "trigger-prompts.json"));
|
|
110
|
+
const byName = new Map(fixture.skills.map((entry) => [entry.name, entry]));
|
|
111
|
+
for (const skillName of expectedSkillNames) {
|
|
112
|
+
const entry = byName.get(skillName);
|
|
113
|
+
expect(Boolean(entry), `${skillName}: trigger fixture is required.`);
|
|
114
|
+
expect(Array.isArray(entry?.positive) && entry.positive.length > 0, `${skillName}: positive trigger fixtures are required.`);
|
|
115
|
+
expect(Array.isArray(entry?.negative) && entry.negative.length > 0, `${skillName}: negative trigger fixtures are required.`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function checkDocs() {
|
|
120
|
+
const requiredDocs = {
|
|
121
|
+
"README.md": ["builder skills", "not AICF runtime capabilities", "npm run check", "https://developers.openai.com/codex/skills"],
|
|
122
|
+
"docs/installation.md": ["../.agents/skills", "$HOME/.agents/skills", "codex plugin marketplace add", "npm package"],
|
|
123
|
+
"docs/skill-authoring-standard.md": ["frontmatter", "required sections", "one-level", "public-safe"],
|
|
124
|
+
"docs/validation.md": ["npm run check:index", "npm run check:release", "common failures", "expected output"],
|
|
125
|
+
"docs/public-release-checklist.md": ["npm run check", "npm run pack:dry", "plugin manifest", "version consistency"],
|
|
126
|
+
"docs/codex-plugin-distribution.md": [".codex-plugin/plugin.json", "./skills/", "relative asset paths", "Codex plugin"],
|
|
127
|
+
"docs/skill-index.md": expectedSkillNames,
|
|
128
|
+
"skills/README.md": ["17", "source of truth", "install script"]
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
for (const [rel, terms] of Object.entries(requiredDocs)) {
|
|
132
|
+
requireFile(rel);
|
|
133
|
+
const content = readText(path.join(root, rel));
|
|
134
|
+
const lowerContent = content.toLowerCase();
|
|
135
|
+
for (const term of terms) {
|
|
136
|
+
expect(lowerContent.includes(String(term).toLowerCase()), `${rel}: must mention ${term}.`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function checkPackContents() {
|
|
142
|
+
const files = npmPackFiles(root);
|
|
143
|
+
const fileSet = new Set(files);
|
|
144
|
+
const requiredFiles = [
|
|
145
|
+
"README.md",
|
|
146
|
+
"LICENSE",
|
|
147
|
+
"CHANGELOG.md",
|
|
148
|
+
"package.json",
|
|
149
|
+
".codex-plugin/plugin.json",
|
|
150
|
+
"docs/installation.md",
|
|
151
|
+
"docs/validation.md",
|
|
152
|
+
"docs/public-release-checklist.md",
|
|
153
|
+
"docs/codex-plugin-distribution.md",
|
|
154
|
+
"docs/skill-authoring-standard.md",
|
|
155
|
+
"docs/skill-index.md",
|
|
156
|
+
"assets/aicf-agent-skills-icon.svg",
|
|
157
|
+
"assets/aicf-agent-skills-logo.svg",
|
|
158
|
+
"scripts/aicf-skills.mjs",
|
|
159
|
+
"scripts/check-release-readiness.mjs"
|
|
160
|
+
];
|
|
161
|
+
|
|
162
|
+
for (const skillName of expectedSkillNames) {
|
|
163
|
+
requiredFiles.push(`skills/${skillName}/SKILL.md`);
|
|
164
|
+
}
|
|
165
|
+
for (const rel of requiredFiles) {
|
|
166
|
+
expect(fileSet.has(rel), `npm dry-run package must include ${rel}.`);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
for (const file of files) {
|
|
170
|
+
for (const failure of forbiddenPathFailures(file, "npm package")) failures.push(failure);
|
|
171
|
+
expect(!file.startsWith("tests/"), `npm dry-run package must not include tests: ${file}.`);
|
|
172
|
+
expect(!file.startsWith(".agents/"), `npm dry-run package must not include a local skill mirror: ${file}.`);
|
|
173
|
+
expect(!file.includes("node_modules/"), `npm dry-run package must not include dependencies: ${file}.`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function checkPublicScan() {
|
|
178
|
+
for (const failure of publicPackageFailures(root)) failures.push(failure);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function checkRelativeExistingPath(value, label) {
|
|
182
|
+
expect(typeof value === "string" && value.length > 0, `.codex-plugin/plugin.json: ${label} is required.`);
|
|
183
|
+
if (typeof value !== "string") return;
|
|
184
|
+
expect(!path.isAbsolute(value), `.codex-plugin/plugin.json: ${label} must be relative.`);
|
|
185
|
+
expect(!/^[a-z]+:/i.test(value), `.codex-plugin/plugin.json: ${label} must not be a URL.`);
|
|
186
|
+
const normalized = normalizePath(value);
|
|
187
|
+
expect(!normalized.startsWith("../"), `.codex-plugin/plugin.json: ${label} must stay inside the package.`);
|
|
188
|
+
requireFile(normalized);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function requireFile(rel) {
|
|
192
|
+
expect(existsSync(path.join(root, rel)), `${rel}: required file is missing.`);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function expect(condition, message) {
|
|
196
|
+
if (!condition) failures.push(message);
|
|
197
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { packageRoot, publicPackageFailures, resolvePath } from "./lib/skill-common.mjs";
|
|
3
|
+
|
|
4
|
+
const root = resolvePath(packageRoot(), process.argv[2] ?? ".");
|
|
5
|
+
const failures = publicPackageFailures(root);
|
|
6
|
+
|
|
7
|
+
if (failures.length > 0) {
|
|
8
|
+
console.error(failures.join("\n"));
|
|
9
|
+
process.exitCode = 1;
|
|
10
|
+
} else {
|
|
11
|
+
console.log(`Skills package public hygiene passed for ${root}.`);
|
|
12
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { checkTriggerCoverage, packageRoot, resolvePath } from "./lib/skill-common.mjs";
|
|
3
|
+
|
|
4
|
+
const root = packageRoot();
|
|
5
|
+
const skillsRoot = resolvePath(root, process.argv[2] ?? "./skills");
|
|
6
|
+
const fixturePath = resolvePath(root, process.argv[3] ?? "./tests/fixtures/trigger-prompts.json");
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
const { failures, warnings } = checkTriggerCoverage(skillsRoot, fixturePath);
|
|
10
|
+
for (const warning of warnings) console.warn(`warning: ${warning}`);
|
|
11
|
+
if (failures.length > 0) {
|
|
12
|
+
console.error(failures.join("\n"));
|
|
13
|
+
process.exitCode = 1;
|
|
14
|
+
} else {
|
|
15
|
+
console.log("Trigger coverage check passed.");
|
|
16
|
+
}
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.error(error.message);
|
|
19
|
+
process.exitCode = 1;
|
|
20
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
generateSkillIndex,
|
|
4
|
+
packageRoot,
|
|
5
|
+
readText,
|
|
6
|
+
resolvePath,
|
|
7
|
+
writeText
|
|
8
|
+
} from "./lib/skill-common.mjs";
|
|
9
|
+
|
|
10
|
+
const root = packageRoot();
|
|
11
|
+
const args = process.argv.slice(2);
|
|
12
|
+
const checkOnly = args.includes("--check");
|
|
13
|
+
const positional = args.filter((arg) => arg !== "--check");
|
|
14
|
+
const skillsRoot = resolvePath(root, positional[0] ?? "./skills");
|
|
15
|
+
const outputPath = resolvePath(root, positional[1] ?? "./docs/skill-index.md");
|
|
16
|
+
const fixturePath = resolvePath(root, "./tests/fixtures/trigger-prompts.json");
|
|
17
|
+
const expected = generateSkillIndex(skillsRoot, fixturePath);
|
|
18
|
+
|
|
19
|
+
if (checkOnly) {
|
|
20
|
+
const actual = readText(outputPath);
|
|
21
|
+
if (actual !== expected) {
|
|
22
|
+
console.error(`${outputPath} is stale. Run npm run index.`);
|
|
23
|
+
process.exitCode = 1;
|
|
24
|
+
} else {
|
|
25
|
+
console.log(`Skill index is current: ${outputPath}.`);
|
|
26
|
+
}
|
|
27
|
+
} else {
|
|
28
|
+
writeText(outputPath, expected);
|
|
29
|
+
console.log(`Generated ${outputPath}.`);
|
|
30
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { installSkills, packageRoot, resolvePath } from "./lib/skill-common.mjs";
|
|
3
|
+
|
|
4
|
+
const args = process.argv.slice(2);
|
|
5
|
+
const target = valueAfter(args, "--target");
|
|
6
|
+
const force = args.includes("--force");
|
|
7
|
+
const allowOutside = args.includes("--allow-outside");
|
|
8
|
+
const root = packageRoot();
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
const result = installSkills({
|
|
12
|
+
skillsRoot: resolvePath(root, "./skills"),
|
|
13
|
+
target,
|
|
14
|
+
force,
|
|
15
|
+
allowOutside,
|
|
16
|
+
root
|
|
17
|
+
});
|
|
18
|
+
if (result.installed.length === 0) {
|
|
19
|
+
console.log(`No skills to install into ${result.target}.`);
|
|
20
|
+
} else {
|
|
21
|
+
console.log(`Installed ${result.installed.length} skill(s) into ${result.target}: ${result.installed.join(", ")}`);
|
|
22
|
+
}
|
|
23
|
+
} catch (error) {
|
|
24
|
+
console.error(error.message);
|
|
25
|
+
process.exitCode = 1;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function valueAfter(args, flag) {
|
|
29
|
+
const index = args.indexOf(flag);
|
|
30
|
+
return index >= 0 ? args[index + 1] : undefined;
|
|
31
|
+
}
|