mirror of
https://github.com/rmyndharis/antigravity-skills.git
synced 2026-09-19 02:19:16 +08:00
docs: private security channel, guarded --write-baseline, changelog
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project are documented here.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- `node:test` test suite covering the CLI, skill parsing, catalog generation, and the drift guard (`npm test`).
|
||||
- `lib/skill-schema.js` as the single source of frontmatter field rules.
|
||||
- `scripts/check-catalog-drift.js` (`npm run check:catalog`) — CI fails if committed catalog artifacts are stale.
|
||||
- `install --force` to overwrite already-installed skills.
|
||||
- `AG_SKILLS_DIR` environment variable to override the install destination (reported by `doctor`).
|
||||
- Validator now checks that backticked referenced files (`resources/`, `references/`, `assets/`, `scripts/`) exist.
|
||||
- `SECURITY.md` private vulnerability disclosure channel.
|
||||
|
||||
### Changed
|
||||
- `install` now skips already-installed skills by default (use `--force` to overwrite) and reports an honest installed/skipped/failed summary.
|
||||
- `install` exits non-zero when nothing could be installed; no longer prints "Installation complete!" on total failure.
|
||||
- `update` exits non-zero on real failures (no installation, invalid name, not installed).
|
||||
- Search scoring now also matches the catalog `triggers` field.
|
||||
- Corrupt `bundles.json`/`aliases.json` now produce an explicit warning instead of degrading silently.
|
||||
- `detectCategory` no longer treats generic "compliance" as `security`.
|
||||
- `--write-baseline` now requires `--yes` and prints what it would grandfather.
|
||||
|
||||
### Fixed
|
||||
- `listSkillIds`/`readSkill` no longer crash on a skill directory missing `SKILL.md`; `build-catalog` surfaces frontmatter parse warnings.
|
||||
- Removed 228 dangling helper-file references across 165 skills.
|
||||
- Removed dead code: `parseInlineList`/`stripQuotes` exports and the unreachable `name !== id` alias branch.
|
||||
+3
-1
@@ -12,4 +12,6 @@ This repository ships skills that may recommend terminal commands or infrastruct
|
||||
|
||||
## Reporting
|
||||
|
||||
If you discover a security issue in this repository, please open an issue with details and reproduction steps.
|
||||
For routine, non-sensitive issues, open a GitHub issue with details and reproduction steps.
|
||||
|
||||
For sensitive vulnerabilities (anything that could be exploited before a fix ships), report privately by email to **yudhi@rmyndharis.com** instead of opening a public issue. Include reproduction steps and impact. Please allow a reasonable window for a fix before any public disclosure.
|
||||
|
||||
@@ -20,6 +20,8 @@ const isStrict = process.argv.includes('--strict')
|
||||
const writeBaseline = process.argv.includes('--write-baseline')
|
||||
|| process.env.WRITE_BASELINE === '1'
|
||||
|| process.env.WRITE_BASELINE === 'true';
|
||||
const confirmWriteBaseline = process.argv.includes('--yes')
|
||||
|| process.env.WRITE_BASELINE_YES === '1';
|
||||
|
||||
function isPlainObject(value) {
|
||||
return value && typeof value === 'object' && !Array.isArray(value);
|
||||
@@ -250,15 +252,27 @@ addStrictSectionErrors('Instructions', missingInstructionsSection, baselineInstr
|
||||
addStrictSectionErrors(`SKILL.md line count <= ${LIMITS.skillLines}`, longFiles, baselineLongFile);
|
||||
|
||||
if (writeBaseline) {
|
||||
const baselineData = {
|
||||
generatedAt: new Date().toISOString(),
|
||||
const toGrandfather = {
|
||||
useSection: [...missingUseSection].sort(),
|
||||
doNotUseSection: [...missingDoNotUseSection].sort(),
|
||||
instructionsSection: [...missingInstructionsSection].sort(),
|
||||
longFile: [...longFiles].sort(),
|
||||
};
|
||||
fs.writeFileSync(BASELINE_PATH, JSON.stringify(baselineData, null, 2));
|
||||
console.log(`Baseline written to ${BASELINE_PATH}`);
|
||||
const totalGrandfathered = Object.values(toGrandfather).reduce((sum, arr) => sum + arr.length, 0);
|
||||
|
||||
console.warn('\n⚠ --write-baseline will grandfather the following soft violations,');
|
||||
console.warn(' silencing them in strict mode (CI). Review carefully:');
|
||||
for (const [key, arr] of Object.entries(toGrandfather)) {
|
||||
console.warn(` - ${key}: ${arr.length}`);
|
||||
}
|
||||
|
||||
if (!confirmWriteBaseline) {
|
||||
console.warn(`\nNot written. Re-run with --yes to grandfather ${totalGrandfathered} violation(s).`);
|
||||
} else {
|
||||
const baselineData = { generatedAt: new Date().toISOString(), ...toGrandfather };
|
||||
fs.writeFileSync(BASELINE_PATH, JSON.stringify(baselineData, null, 2));
|
||||
console.log(`Baseline written to ${BASELINE_PATH}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (warnings.length) {
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert');
|
||||
const { spawnSync } = require('node:child_process');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
const ROOT = path.resolve(__dirname, '..');
|
||||
const VALIDATOR = path.join(ROOT, 'scripts', 'validate-skills.js');
|
||||
const BASELINE = path.join(ROOT, 'validation-baseline.json');
|
||||
|
||||
function runValidator(args) {
|
||||
const result = spawnSync('node', [VALIDATOR, ...args], { encoding: 'utf8', cwd: ROOT });
|
||||
return { code: result.status || 0, out: (result.stdout || '') + (result.stderr || '') };
|
||||
}
|
||||
|
||||
test('--write-baseline without --yes does NOT write the baseline file', () => {
|
||||
const before = fs.readFileSync(BASELINE, 'utf8');
|
||||
const r = runValidator(['--write-baseline']);
|
||||
const after = fs.readFileSync(BASELINE, 'utf8');
|
||||
assert.strictEqual(after, before, 'baseline must be unchanged without --yes');
|
||||
assert.ok(/Not written/.test(r.out), 'should explain it was not written');
|
||||
assert.ok(/--yes/.test(r.out), 'should mention the --yes flag');
|
||||
});
|
||||
Reference in New Issue
Block a user