quantum-reasoning-skill 1.0.0 → 1.1.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/index.js CHANGED
@@ -1 +1,207 @@
1
- module.exports = { name: 'quantum-reasoning-skill', version: '1.0.0', description: 'Quantum-inspired reasoning skill for exploring multiple solution paths', skill: require('./SKILL.md') };
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * quantum-reasoning-skill
6
+ *
7
+ * A real, executable entry point for the Node/MCP host ecosystem. It reads the
8
+ * skill contract that ships with this package and exposes it programmatically
9
+ * and from the command line.
10
+ *
11
+ * The previous implementation did `require('./SKILL.md')`, which made Node
12
+ * parse Markdown as JavaScript and throw a SyntaxError on every import.
13
+ * SKILL.md is now read as text via fs.readFileSync.
14
+ */
15
+
16
+ const fs = require('fs');
17
+ const path = require('path');
18
+
19
+ const REQUIRED_FIELDS = ['name', 'description'];
20
+
21
+ const SKILL_FILE = path.join(__dirname, 'SKILL.md');
22
+ const VERSION_FILE = path.join(__dirname, 'VERSION');
23
+
24
+ /**
25
+ * Parse leading `---` delimited front matter from the skill document.
26
+ * Deliberately dependency-free: the contract only uses `key: value` pairs.
27
+ *
28
+ * @param {string} text
29
+ * @returns {{fields: Record<string,string>, fenceEnd: number}}
30
+ */
31
+ function parseFrontMatter(text) {
32
+ const lines = text.split(/\r?\n/);
33
+ if (lines.length === 0 || lines[0].trim() !== '---') {
34
+ throw new Error('SKILL.md must start with a `---` front matter fence');
35
+ }
36
+ let fenceEnd = -1;
37
+ for (let i = 1; i < lines.length; i += 1) {
38
+ if (lines[i].trim() === '---') {
39
+ fenceEnd = i;
40
+ break;
41
+ }
42
+ }
43
+ if (fenceEnd === -1) {
44
+ throw new Error('SKILL.md front matter is not closed');
45
+ }
46
+ const fields = Object.create(null);
47
+ for (const line of lines.slice(1, fenceEnd)) {
48
+ const trimmed = line.trim();
49
+ if (trimmed === '' || trimmed.startsWith('#')) continue;
50
+ const idx = trimmed.indexOf(':');
51
+ if (idx === -1) continue;
52
+ const key = trimmed.slice(0, idx).trim();
53
+ let value = trimmed.slice(idx + 1).trim();
54
+ if (
55
+ (value.startsWith('"') && value.endsWith('"')) ||
56
+ (value.startsWith("'") && value.endsWith("'"))
57
+ ) {
58
+ value = value.slice(1, -1);
59
+ }
60
+ fields[key] = value;
61
+ }
62
+ return { fields, fenceEnd };
63
+ }
64
+
65
+ /**
66
+ * Read the packaged skill contract from disk.
67
+ *
68
+ * @returns {string}
69
+ */
70
+ function readSkillDocument() {
71
+ return fs.readFileSync(SKILL_FILE, 'utf8');
72
+ }
73
+
74
+ /**
75
+ * Read the packaged VERSION file.
76
+ *
77
+ * @returns {string}
78
+ */
79
+ function readVersion() {
80
+ const raw = fs.readFileSync(VERSION_FILE, 'utf8').trim();
81
+ return raw.startsWith('v') ? raw.slice(1) : raw;
82
+ }
83
+
84
+ /**
85
+ * Validate the skill contract.
86
+ *
87
+ * @param {string} text
88
+ * @returns {{name: string, description: string, descriptionLength: number,
89
+ * bodyLines: number, valid: boolean, problems: string[]}}
90
+ */
91
+ function validateSkill(text) {
92
+ const { fields, fenceEnd } = parseFrontMatter(text);
93
+ const problems = [];
94
+ for (const field of REQUIRED_FIELDS) {
95
+ if (!fields[field]) {
96
+ problems.push(`front matter must define a non-empty \`${field}\``);
97
+ }
98
+ }
99
+ if (fields.name && fields.name !== 'quantum-reasoning') {
100
+ problems.push('front matter `name` must be `quantum-reasoning`');
101
+ }
102
+ const bodyLines = text.split(/\r?\n/).slice(fenceEnd + 1).length;
103
+ if (bodyLines < 20) {
104
+ problems.push(`SKILL.md body is too short (${bodyLines} lines, expected >= 20)`);
105
+ }
106
+ return {
107
+ name: fields.name || '',
108
+ description: fields.description || '',
109
+ descriptionLength: (fields.description || '').length,
110
+ bodyLines,
111
+ valid: problems.length === 0,
112
+ problems,
113
+ };
114
+ }
115
+
116
+ /**
117
+ * Load and validate the packaged skill in one call.
118
+ *
119
+ * @returns {object} the parsed skill definition
120
+ */
121
+ function loadSkill() {
122
+ const document = readSkillDocument();
123
+ const { fields } = parseFrontMatter(document);
124
+ const report = validateSkill(document);
125
+ return {
126
+ name: report.name,
127
+ description: report.description,
128
+ version: readVersion(),
129
+ document,
130
+ valid: report.valid,
131
+ problems: report.problems,
132
+ metadata: fields,
133
+ };
134
+ }
135
+
136
+ const USAGE = `quantum-reasoning — inspect the packaged skill contract
137
+
138
+ Usage:
139
+ quantum-reasoning Print the skill summary
140
+ quantum-reasoning --json Print the full report as JSON
141
+ quantum-reasoning --validate Exit non-zero if the contract is invalid
142
+ quantum-reasoning --path Print the absolute SKILL.md path
143
+ quantum-reasoning --help Show this message
144
+
145
+ Exit codes:
146
+ 0 success
147
+ 1 invalid skill contract (--validate)
148
+ 2 SKILL.md could not be read
149
+ `;
150
+
151
+ function main(argv) {
152
+ const args = argv.slice(2);
153
+ const wantsJson = args.includes('--json');
154
+ const wantsValidate = args.includes('--validate');
155
+ const wantsPath = args.includes('--path');
156
+
157
+ if (args.includes('--help') || args.includes('-h')) {
158
+ process.stdout.write(USAGE);
159
+ return 0;
160
+ }
161
+
162
+ let report;
163
+ try {
164
+ report = validateSkill(readSkillDocument());
165
+ } catch (error) {
166
+ process.stderr.write(`error: ${error.message}\n`);
167
+ return 2;
168
+ }
169
+ report.version = readVersion();
170
+ report.path = SKILL_FILE;
171
+
172
+ if (wantsPath) {
173
+ process.stdout.write(`${SKILL_FILE}\n`);
174
+ return 0;
175
+ }
176
+ if (wantsJson) {
177
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
178
+ } else {
179
+ process.stdout.write(`skill: ${report.name || '<missing name>'}\n`);
180
+ process.stdout.write(`status: ${report.valid ? 'valid' : 'INVALID'}\n`);
181
+ process.stdout.write(`file: ${SKILL_FILE}\n`);
182
+ process.stdout.write(`version: ${report.version}\n`);
183
+ process.stdout.write(`body: ${report.bodyLines} lines\n`);
184
+ for (const problem of report.problems) {
185
+ process.stdout.write(` - ${problem}\n`);
186
+ }
187
+ }
188
+ if (wantsValidate && !report.valid) {
189
+ return 1;
190
+ }
191
+ return 0;
192
+ }
193
+
194
+ module.exports = {
195
+ name: 'quantum-reasoning-skill',
196
+ version: readVersion(),
197
+ skillFile: SKILL_FILE,
198
+ parseFrontMatter,
199
+ readSkillDocument,
200
+ readVersion,
201
+ validateSkill,
202
+ loadSkill,
203
+ };
204
+
205
+ if (require.main === module) {
206
+ process.exitCode = main(process.argv);
207
+ }
package/package.json CHANGED
@@ -1 +1,41 @@
1
- {"name":"quantum-reasoning-skill","version":"1.0.0","description":"Quantum-inspired reasoning skill for exploring multiple solution paths","main":"index.js","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"keywords":["ai-agents","reasoning","quantum-inspired","multi-branch"],"author":"Furox-Art","license":"MIT","repository":{"type":"git","url":"git+https://github.com/Furox-Art/quantum-reasoning-skill.git"},"bugs":{"url":"https://github.com/Furox-Art/quantum-reasoning-skill/issues"},"homepage":"https://github.com/Furox-Art/quantum-reasoning-skill#readme"}
1
+ {
2
+ "name": "quantum-reasoning-skill",
3
+ "version": "1.1.0",
4
+ "description": "Quantum-inspired reasoning skill for exploring multiple solution paths",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "quantum-reasoning": "index.js"
8
+ },
9
+ "files": [
10
+ "index.js",
11
+ "SKILL.md",
12
+ "VERSION",
13
+ "LICENSE",
14
+ "README.md"
15
+ ],
16
+ "scripts": {
17
+ "test": "node index.js --validate && node -e \"const s=require('./index.js'); if(!s.loadSkill().valid){console.error('skill contract invalid');process.exit(1)}\""
18
+ },
19
+ "engines": {
20
+ "node": ">=20"
21
+ },
22
+ "keywords": [
23
+ "ai-agents",
24
+ "reasoning",
25
+ "quantum-inspired",
26
+ "multi-branch",
27
+ "agent-skills",
28
+ "mcp",
29
+ "claude-skill"
30
+ ],
31
+ "author": "Furox-Art",
32
+ "license": "MIT",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/Furox-Art/quantum-reasoning-skill.git"
36
+ },
37
+ "bugs": {
38
+ "url": "https://github.com/Furox-Art/quantum-reasoning-skill/issues"
39
+ },
40
+ "homepage": "https://github.com/Furox-Art/quantum-reasoning-skill#readme"
41
+ }
@@ -1,81 +0,0 @@
1
- name: Benchmark result
2
- description: Submit an independently run baseline-vs-skill model evaluation
3
- title: "[Benchmark] "
4
- labels: []
5
- body:
6
- - type: markdown
7
- attributes:
8
- value: |
9
- Submit reproducible measurements only. Do not include private chain-of-thought. For PR submissions, validate the full bundle with `python benchmark/validate_submission.py --root benchmark/results/community`.
10
-
11
- - type: input
12
- id: provider
13
- attributes:
14
- label: Provider
15
- placeholder: Provider or local runtime
16
- validations:
17
- required: true
18
-
19
- - type: input
20
- id: model
21
- attributes:
22
- label: Exact model / version
23
- placeholder: Exact model identifier and version if available
24
- validations:
25
- required: true
26
-
27
- - type: input
28
- id: skill_version
29
- attributes:
30
- label: Skill version / commit
31
- placeholder: v0.3.1 or commit SHA
32
- validations:
33
- required: true
34
-
35
- - type: input
36
- id: run_date
37
- attributes:
38
- label: Run date
39
- placeholder: YYYY-MM-DD
40
- validations:
41
- required: true
42
-
43
- - type: textarea
44
- id: controls
45
- attributes:
46
- label: Experimental controls
47
- description: Describe sampling settings, context/output limits, tools, repetitions, seeds, prompt wrapper and hardware/runtime when relevant.
48
- validations:
49
- required: true
50
-
51
- - type: textarea
52
- id: artifacts
53
- attributes:
54
- label: Result artifacts
55
- description: Link or attach metadata.json, cases.jsonl, baseline.jsonl, skill.jsonl, comparison.json and README.md. State whether the bundle passed validate_submission.py.
56
- validations:
57
- required: true
58
-
59
- - type: textarea
60
- id: summary
61
- attributes:
62
- label: Result summary
63
- description: Report accuracy and compute/cost trade-offs. Include failures, refusals and timeouts.
64
- validations:
65
- required: true
66
-
67
- - type: checkboxes
68
- id: integrity
69
- attributes:
70
- label: Integrity checks
71
- options:
72
- - label: Baseline and skill used the same model/version, task set, tools, sampling settings and budget policy.
73
- required: true
74
- - label: I included the exact evaluated cases and did not remove failed runs, refusals or timeouts.
75
- required: true
76
- - label: comparison.json was generated from the submitted raw files and was not edited to improve the result.
77
- required: true
78
- - label: I did not include private chain-of-thought or fabricate unavailable telemetry.
79
- required: true
80
- - label: I disclosed modifications to SKILL.md, benchmark cases, wrappers or provider adapters.
81
- required: true
@@ -1,38 +0,0 @@
1
- name: Bug report
2
- description: Report a reproducible defect in the skill, reference controller, benchmark tooling, or CI.
3
- title: "[Bug]: "
4
- labels: ["bug"]
5
- body:
6
- - type: textarea
7
- id: summary
8
- attributes:
9
- label: What happened?
10
- description: Describe the observed behavior and what you expected instead.
11
- validations:
12
- required: true
13
- - type: textarea
14
- id: reproduce
15
- attributes:
16
- label: Minimal reproduction
17
- description: Include commands, inputs, or a small example that reproduces the problem.
18
- validations:
19
- required: true
20
- - type: input
21
- id: version
22
- attributes:
23
- label: Repository version or commit
24
- placeholder: v0.3.0 or commit SHA
25
- validations:
26
- required: true
27
- - type: textarea
28
- id: environment
29
- attributes:
30
- label: Environment
31
- description: Python version, host/agent integration, OS, and relevant tool versions.
32
- - type: checkboxes
33
- id: sensitive
34
- attributes:
35
- label: Safety check
36
- options:
37
- - label: I have not included secrets, credentials, private chain-of-thought, or sensitive benchmark data.
38
- required: true
@@ -1,31 +0,0 @@
1
- name: Feature request
2
- description: Propose a change to the reasoning protocol, tooling, benchmarks, or integration contract.
3
- title: "[Feature]: "
4
- labels: ["enhancement"]
5
- body:
6
- - type: textarea
7
- id: problem
8
- attributes:
9
- label: Problem or limitation
10
- description: What concrete limitation does this proposal address?
11
- validations:
12
- required: true
13
- - type: textarea
14
- id: proposal
15
- attributes:
16
- label: Proposed change
17
- description: Describe the behavior or interface you want to add or change.
18
- validations:
19
- required: true
20
- - type: textarea
21
- id: evidence
22
- attributes:
23
- label: Evidence or evaluation plan
24
- description: If this affects reasoning quality, explain how it could be tested without relying on anecdotal examples alone.
25
- - type: checkboxes
26
- id: scope
27
- attributes:
28
- label: Scope check
29
- options:
30
- - label: This proposal does not present unverified benchmark claims as established results.
31
- required: true
@@ -1,15 +0,0 @@
1
- ## Summary
2
-
3
- Describe the change and the behavior it affects.
4
-
5
- ## Validation
6
-
7
- - [ ] I ran `python -m unittest discover -s tests -v`.
8
- - [ ] I ran `python benchmark/evaluate.py --help`.
9
- - [ ] I added or updated tests when executable behavior changed.
10
- - [ ] I updated documentation when the public contract changed.
11
- - [ ] I did not include private chain-of-thought, secrets, credentials, or fabricated benchmark telemetry.
12
-
13
- ## Benchmark-impacting changes
14
-
15
- If this changes `SKILL.md`, scoring, collapse/revival behavior, benchmark schemas, or evaluation logic, explain how existing results should be interpreted and whether new community runs are needed.
@@ -1,32 +0,0 @@
1
- name: npm Publish
2
-
3
- on:
4
- workflow_dispatch:
5
- push:
6
- branches: [main]
7
- paths:
8
- - "package.json"
9
- - "index.js"
10
-
11
- concurrency:
12
- group: npm-publish
13
- cancel-in-progress: false
14
-
15
- permissions:
16
- contents: read
17
-
18
- jobs:
19
- publish:
20
- runs-on: ubuntu-latest
21
- steps:
22
- - uses: actions/checkout@v4
23
-
24
- - uses: actions/setup-node@v4
25
- with:
26
- node-version: "20"
27
- registry-url: "https://registry.npmjs.org"
28
-
29
- - name: Publish to npm
30
- run: npm publish --access public
31
- env:
32
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -1,79 +0,0 @@
1
- name: publish-release
2
-
3
- on:
4
- workflow_run:
5
- workflows: ["validate-skill"]
6
- types: [completed]
7
- branches: [main]
8
-
9
- permissions:
10
- contents: write
11
-
12
- concurrency:
13
- group: publish-release
14
- cancel-in-progress: false
15
-
16
- jobs:
17
- publish:
18
- if: ${{ github.event.workflow_run.conclusion == 'success' }}
19
- runs-on: ubuntu-latest
20
- steps:
21
- - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
22
- with:
23
- ref: ${{ github.event.workflow_run.head_sha }}
24
- fetch-depth: 0
25
-
26
- - name: Resolve and validate version
27
- id: version
28
- shell: bash
29
- run: |
30
- set -euo pipefail
31
- test -s VERSION
32
- version="$(tr -d '[:space:]' < VERSION)"
33
- version="${version#v}"
34
- if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?$ ]]; then
35
- echo "Invalid release version: $version" >&2
36
- exit 1
37
- fi
38
- echo "version=$version" >> "$GITHUB_OUTPUT"
39
- echo "tag=v${version}" >> "$GITHUB_OUTPUT"
40
-
41
- - name: Require matching changelog entry
42
- shell: bash
43
- env:
44
- VERSION: ${{ steps.version.outputs.version }}
45
- run: |
46
- set -euo pipefail
47
- grep -Fq "## [$VERSION]" CHANGELOG.md || {
48
- echo "CHANGELOG.md must contain a ## [$VERSION] section before release." >&2
49
- exit 1
50
- }
51
-
52
- - name: Check existing release
53
- id: existing
54
- shell: bash
55
- env:
56
- GH_TOKEN: ${{ github.token }}
57
- TAG: ${{ steps.version.outputs.tag }}
58
- run: |
59
- set -euo pipefail
60
- if gh release view "$TAG" >/dev/null 2>&1; then
61
- echo "exists=true" >> "$GITHUB_OUTPUT"
62
- echo "$TAG already exists; nothing to publish."
63
- else
64
- echo "exists=false" >> "$GITHUB_OUTPUT"
65
- fi
66
-
67
- - name: Create tag and GitHub Release
68
- if: steps.existing.outputs.exists != 'true'
69
- shell: bash
70
- env:
71
- GH_TOKEN: ${{ github.token }}
72
- TAG: ${{ steps.version.outputs.tag }}
73
- TARGET_SHA: ${{ github.event.workflow_run.head_sha }}
74
- run: |
75
- set -euo pipefail
76
- gh release create "$TAG" \
77
- --target "$TARGET_SHA" \
78
- --title "$TAG" \
79
- --generate-notes
@@ -1,154 +0,0 @@
1
- name: validate-skill
2
-
3
- on:
4
- push:
5
- pull_request:
6
-
7
- permissions:
8
- contents: read
9
-
10
- jobs:
11
- validate:
12
- runs-on: ubuntu-latest
13
- steps:
14
- - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
15
-
16
- - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
17
- with:
18
- python-version: "3.12"
19
-
20
- - name: Validate skill repository contract
21
- shell: bash
22
- run: |
23
- set -euo pipefail
24
- for required in \
25
- SKILL.md README.md LICENSE CHANGELOG.md VERSION CONTRIBUTING.md SECURITY.md CITATION.cff \
26
- examples/usage.md examples/host-integration.md \
27
- reference/branch_controller.py \
28
- docs/MEASUREMENT.md docs/COMPATIBILITY.md \
29
- benchmark/README.md benchmark/cases.jsonl benchmark/evaluate.py benchmark/validate_submission.py \
30
- benchmark/schemas/case.schema.json benchmark/schemas/result.schema.json \
31
- benchmark/schemas/metadata.schema.json benchmark/schemas/comparison.schema.json \
32
- tests/test_reference.py tests/test_benchmark.py tests/test_submission_validation.py \
33
- .github/ISSUE_TEMPLATE/benchmark-result.yml .github/ISSUE_TEMPLATE/bug-report.yml \
34
- .github/ISSUE_TEMPLATE/feature-request.yml .github/PULL_REQUEST_TEMPLATE.md; do
35
- test -s "$required"
36
- done
37
-
38
- python - <<'PY'
39
- from pathlib import Path
40
- import json
41
- import re
42
-
43
- root = Path.cwd().resolve()
44
- skill = (root / "SKILL.md").read_text(encoding="utf-8")
45
- lines = skill.splitlines()
46
- if not lines or lines[0].strip() != "---":
47
- raise SystemExit("SKILL.md must start with YAML front matter")
48
- try:
49
- end = next(i for i, line in enumerate(lines[1:], start=1) if line.strip() == "---")
50
- except StopIteration as exc:
51
- raise SystemExit("SKILL.md front matter is not closed") from exc
52
- fields = {}
53
- for line in lines[1:end]:
54
- if ":" in line:
55
- key, value = line.split(":", 1)
56
- fields[key.strip()] = value.strip()
57
- if fields.get("name") != "quantum-reasoning":
58
- raise SystemExit("SKILL.md front matter must declare name: quantum-reasoning")
59
- if not fields.get("description"):
60
- raise SystemExit("SKILL.md front matter must contain a non-empty description")
61
- if len(lines[end + 1:]) < 20:
62
- raise SystemExit("SKILL.md body is unexpectedly short")
63
-
64
- readme = (root / "README.md").read_text(encoding="utf-8")
65
- for required in (
66
- "SKILL.md", "examples/usage.md", "examples/host-integration.md",
67
- "reference/branch_controller.py", "docs/MEASUREMENT.md", "docs/COMPATIBILITY.md",
68
- "benchmark/README.md", "CONTRIBUTING.md", "SECURITY.md", "CITATION.cff",
69
- ):
70
- if required not in readme:
71
- raise SystemExit(f"README.md must reference {required}")
72
-
73
- markdown_files = [
74
- root / "README.md", root / "SKILL.md", root / "CONTRIBUTING.md", root / "SECURITY.md",
75
- root / "examples/usage.md", root / "examples/host-integration.md",
76
- root / "benchmark/README.md", root / "docs/MEASUREMENT.md", root / "docs/COMPATIBILITY.md",
77
- ]
78
- link_pattern = re.compile(r"\[[^\]]*\]\(([^)]+)\)")
79
- for document in markdown_files:
80
- text = document.read_text(encoding="utf-8")
81
- for raw_target in link_pattern.findall(text):
82
- target = raw_target.strip().split("#", 1)[0].split("?", 1)[0]
83
- if not target or "://" in target or target.startswith(("mailto:", "#")):
84
- continue
85
- resolved = (document.parent / target).resolve()
86
- try:
87
- resolved.relative_to(root)
88
- except ValueError as exc:
89
- raise SystemExit(f"{document.relative_to(root)} links outside repository: {raw_target}") from exc
90
- if not resolved.exists():
91
- raise SystemExit(f"Broken relative link in {document.relative_to(root)}: {raw_target}")
92
-
93
- case_path = root / "benchmark" / "cases.jsonl"
94
- seen_ids = set()
95
- for line_number, raw in enumerate(case_path.read_text(encoding="utf-8").splitlines(), start=1):
96
- if not raw.strip():
97
- continue
98
- try:
99
- case = json.loads(raw)
100
- except json.JSONDecodeError as exc:
101
- raise SystemExit(f"benchmark/cases.jsonl:{line_number}: invalid JSON: {exc}") from exc
102
- required = {"id", "domain", "prompt", "accepted_answers"}
103
- missing = required - set(case)
104
- if missing:
105
- raise SystemExit(f"benchmark/cases.jsonl:{line_number}: missing {sorted(missing)}")
106
- case_id = str(case["id"])
107
- if case_id in seen_ids:
108
- raise SystemExit(f"duplicate benchmark case id: {case_id}")
109
- seen_ids.add(case_id)
110
- if not isinstance(case["accepted_answers"], list) or not case["accepted_answers"]:
111
- raise SystemExit(f"benchmark/cases.jsonl:{line_number}: accepted_answers must be non-empty")
112
-
113
- schemas = sorted((root / "benchmark" / "schemas").glob("*.schema.json"))
114
- if len(schemas) < 4:
115
- raise SystemExit("expected case, result, metadata and comparison JSON Schemas")
116
- for schema_path in schemas:
117
- schema = json.loads(schema_path.read_text(encoding="utf-8"))
118
- if schema.get("$schema") != "https://json-schema.org/draft/2020-12/schema":
119
- raise SystemExit(f"{schema_path}: expected JSON Schema draft 2020-12")
120
- if schema.get("type") != "object" or not schema.get("required"):
121
- raise SystemExit(f"{schema_path}: must define an object with required fields")
122
-
123
- version = (root / "VERSION").read_text(encoding="utf-8").strip().lstrip("v")
124
- if not re.fullmatch(r"[0-9]+\.[0-9]+\.[0-9]+(?:[.-][0-9A-Za-z.-]+)?", version):
125
- raise SystemExit("VERSION is not a valid semantic version")
126
- cff = (root / "CITATION.cff").read_text(encoding="utf-8")
127
- for marker in ("cff-version: 1.2.0", "title:", "authors:", "repository-code:", "license: MIT"):
128
- if marker not in cff:
129
- raise SystemExit(f"CITATION.cff missing {marker!r}")
130
- if f"version: {version}" not in cff:
131
- raise SystemExit("CITATION.cff version must match VERSION")
132
-
133
- action_use = re.compile(r"uses:\s+(actions/[A-Za-z0-9_.-]+)@([^\s#]+)")
134
- for workflow in (root / ".github" / "workflows").glob("*.yml"):
135
- for action, ref in action_use.findall(workflow.read_text(encoding="utf-8")):
136
- if not re.fullmatch(r"[0-9a-f]{40}", ref):
137
- raise SystemExit(f"{workflow}: {action} must be pinned to an exact commit SHA")
138
-
139
- print("Skill repository contract validated successfully.")
140
- PY
141
-
142
- - name: Compile Python sources
143
- run: python -m compileall -q reference benchmark tests
144
-
145
- - name: Run behavioral tests
146
- run: python -m unittest discover -s tests -v
147
-
148
- - name: Validate community benchmark bundles
149
- run: python benchmark/validate_submission.py --root benchmark/results/community --allow-empty
150
-
151
- - name: Check benchmark CLIs
152
- run: |
153
- python benchmark/evaluate.py --help > /dev/null
154
- python benchmark/validate_submission.py --help > /dev/null