chore: modularize meta skill report surfaces
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
# Agent Instructions
|
||||
|
||||
## Project Map
|
||||
|
||||
`yao-meta-skill` is the source repository for the Yao Meta Skill / Skill OS. Keep the root `SKILL.md` lean and route depth through the existing project layers:
|
||||
|
||||
- `SKILL.md`: public trigger surface, compact workflow, and Skill OS gates.
|
||||
- `references/`: stable method doctrine and operating guidance.
|
||||
- `scripts/`: executable logic, report generators, compilers, gates, and CLI entrypoints.
|
||||
- `evals/`: trigger, output, packaging, semantic, and regression fixtures.
|
||||
- `skill-ir/`: platform-neutral skill contract and examples.
|
||||
- `agents/interface.yaml`: portable runtime and trust metadata.
|
||||
- `security/`: script, dependency, network, permission, and trust policies.
|
||||
- `registry/`: package metadata, installability evidence, and compatibility metadata.
|
||||
- `skill_atlas/`: portfolio catalog, route overlap, ownership, stale-skill, and dependency evidence.
|
||||
- `reports/`: generated review, trust, conformance, registry, overview, and release evidence.
|
||||
- `docs/`: durable public docs such as migration notes and localized READMEs.
|
||||
|
||||
## Verification
|
||||
|
||||
Use `make ci-test` as the default full verification command before calling a change done. For focused work, run the smallest relevant target first, then finish with `make ci-test` when generated artifacts, packaging, registry, trust, or report UI changed.
|
||||
|
||||
Common focused checks:
|
||||
|
||||
- CLI changes: `python3 tests/verify_yao_cli.py`
|
||||
- Skill overview report changes: `python3 tests/verify_skill_overview.py`
|
||||
- Review Studio changes: `python3 tests/verify_review_studio.py`
|
||||
- Trust or script inventory changes: `python3 tests/verify_trust_check.py`
|
||||
- Packaging or registry changes: `python3 tests/verify_package_verification.py && python3 tests/verify_registry_audit.py`
|
||||
|
||||
After source changes that affect scripts, package contents, trust evidence, Review Studio, registry metadata, or generated reports, refresh the release evidence before final sign-off:
|
||||
|
||||
```bash
|
||||
GENERATED_AT="${GENERATED_AT:-$(date +%F)}"
|
||||
python3 scripts/run_output_execution.py --runner-command '["python3","scripts/local_output_eval_runner.py"]'
|
||||
python3 scripts/compile_skill.py . --generated-at "$GENERATED_AT"
|
||||
python3 scripts/cross_packager.py . --platform openai --platform claude --platform generic --expectations evals/packaging_expectations.json --output-dir dist --zip
|
||||
python3 scripts/simulate_install.py . --package-dir dist --install-root dist/install-simulation --output-json reports/install_simulation.json --output-md reports/install_simulation.md --generated-at "$GENERATED_AT"
|
||||
python3 scripts/trust_check.py . --output-json reports/security_trust_report.json --output-md reports/security_trust_report.md
|
||||
python3 scripts/registry_audit.py . --generated-at "$GENERATED_AT"
|
||||
python3 scripts/verify_package.py . --package-dir dist --expectations evals/packaging_expectations.json --registry-json reports/registry_audit.json --output-json reports/package_verification.json --output-md reports/package_verification.md --require-zip --generated-at "$GENERATED_AT"
|
||||
python3 scripts/registry_audit.py . --generated-at "$GENERATED_AT"
|
||||
python3 scripts/upgrade_check.py . --previous-package-json registry/examples/yao-meta-skill-1.0.0.json --current-package-json reports/registry_audit.json --output-json reports/upgrade_check.json --output-md reports/upgrade_check.md --generated-at "$GENERATED_AT"
|
||||
python3 scripts/render_skill_overview.py .
|
||||
python3 scripts/render_review_studio.py . --output-html reports/review-studio.html --output-json reports/review-studio.json
|
||||
```
|
||||
|
||||
Clean test-only scratch directories after verification with `rm -rf tests/tmp_*`. Do not clean unrelated untracked files.
|
||||
|
||||
## Boundaries
|
||||
|
||||
- Do not expand root `SKILL.md` with long method text. Add durable guidance to `references/` or executable behavior to `scripts/`.
|
||||
- Do not commit private customer work, one-off business skills, or local research reports unless the user explicitly promotes them into examples, fixtures, or public evidence.
|
||||
- Treat untracked files outside `tests/tmp_*` as user work. Do not delete, move, or overwrite them without explicit approval.
|
||||
- Do not hand-edit generated evidence when a generator exists. Regenerate the source report instead.
|
||||
- Do not introduce external chart or UI dependencies for static reports unless the user explicitly approves them. The current report pattern is static HTML, local CSS, and inline SVG.
|
||||
- Keep package artifacts, registry checksums, install simulation, trust reports, overview reports, and Review Studio evidence in sync after source changes.
|
||||
|
||||
## Hotspot Ownership
|
||||
|
||||
- `scripts/yao.py`: unified CLI orchestration. Keep command behavior stable; move pure config and side-effect-free helpers into small internal modules.
|
||||
- `scripts/render_skill_overview.py`: v2 bilingual skill overview report. Preserve `reports/skill-overview.html` / `.json`, `body data-report-lang="zh-CN"`, default Simplified Chinese, English switch, and inline-chart/no-external-dependency behavior.
|
||||
- `scripts/render_review_studio.py`: Review Studio gate orchestration. Keep gate scoring, evidence links, and action generation separate from layout helpers.
|
||||
- `scripts/review_studio_layout.py`: Review Studio static layout and CSS contract.
|
||||
- `scripts/review_studio_formatting.py`: Review Studio dictionary-to-panel formatting and Chinese metric labels.
|
||||
- `scripts/skill_report_model.py`, `scripts/skill_report_metrics.py`, `scripts/skill_report_charts.py`: skill overview data model, scoring, and inline SVG chart generation.
|
||||
- `scripts/yao_cli_config.py`: CLI target maps, archetype heuristics, diagnosis copy, and side-effect-free shaping helpers.
|
||||
|
||||
New helper modules that are imported by CLI/report scripts but are not standalone commands must declare:
|
||||
|
||||
```python
|
||||
SCRIPT_INTERFACE = "internal-module"
|
||||
SCRIPT_INTERFACE_REASON = "Imported by <caller> for <purpose>."
|
||||
```
|
||||
|
||||
Then update `tests/verify_trust_check.py` so help-smoke coverage and trust reporting stay explicit.
|
||||
|
||||
## Long-Running Work
|
||||
|
||||
Stop and surface state instead of retrying when any of these happens:
|
||||
|
||||
- Two consecutive checkpoints show no new files, no new passing test, and no new diagnosis.
|
||||
- The same command fails with the same error three times.
|
||||
- A required credential, network, package registry, or external service is unavailable.
|
||||
- A generated package hash, registry checksum, install simulation, or trust summary cannot be reconciled after regeneration.
|
||||
|
||||
When stopping, report the exact command, current `git status --short --branch -uall`, and the smallest next diagnostic.
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
"agent-skills-compatible"
|
||||
],
|
||||
"package_metadata": "registry/packages/yao-meta-skill.json",
|
||||
"package_sha256": "9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe"
|
||||
"package_sha256": "742dc905b0d221c4f336e741d168861edaf7b75e97fe1e89f7d454c1cabf928f"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
"trust_level": "local",
|
||||
"license": "MIT",
|
||||
"checksums": {
|
||||
"package_sha256": "9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe",
|
||||
"archive_sha256": "4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06"
|
||||
"package_sha256": "742dc905b0d221c4f336e741d168861edaf7b75e97fe1e89f7d454c1cabf928f",
|
||||
"archive_sha256": "7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9"
|
||||
},
|
||||
"compatibility": {
|
||||
"openai": "pass",
|
||||
@@ -47,7 +47,7 @@
|
||||
},
|
||||
"distribution": {
|
||||
"archive_verified": true,
|
||||
"archive_sha256": "4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06",
|
||||
"archive_sha256": "7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9",
|
||||
"package_verification": "reports/package_verification.json",
|
||||
"install_simulated": true,
|
||||
"install_simulation": "reports/install_simulation.json"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"ok": true,
|
||||
"schema_version": "2.0",
|
||||
"generated_at": "2026-06-13T09:57:51Z",
|
||||
"generated_at": "2026-06-13T10:57:52Z",
|
||||
"skill_dir": ".",
|
||||
"privacy_contract": {
|
||||
"storage": "local-first",
|
||||
|
||||
@@ -190,6 +190,8 @@
|
||||
"scripts/render_social_preview.py",
|
||||
"scripts/render_system_model.py",
|
||||
"scripts/resource_boundary_check.py",
|
||||
"scripts/review_studio_formatting.py",
|
||||
"scripts/review_studio_layout.py",
|
||||
"scripts/run_conformance_suite.py",
|
||||
"scripts/run_description_optimization_suite.py",
|
||||
"scripts/run_eval_suite.py",
|
||||
@@ -197,6 +199,7 @@
|
||||
"scripts/run_output_execution.py",
|
||||
"scripts/simulate_install.py",
|
||||
"scripts/skill_report_charts.py",
|
||||
"scripts/skill_report_layout.py",
|
||||
"scripts/skill_report_metrics.py",
|
||||
"scripts/skill_report_model.py",
|
||||
"scripts/sync_local_install.py",
|
||||
@@ -205,7 +208,8 @@
|
||||
"scripts/upgrade_check.py",
|
||||
"scripts/validate_skill.py",
|
||||
"scripts/verify_package.py",
|
||||
"scripts/yao.py"
|
||||
"scripts/yao.py",
|
||||
"scripts/yao_cli_config.py"
|
||||
],
|
||||
"assets": [
|
||||
"templates/basic_skill.md.j2",
|
||||
@@ -256,7 +260,7 @@
|
||||
],
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
}
|
||||
@@ -494,7 +498,7 @@
|
||||
"strategy": "Ship the neutral source tree and expose OpenAI-facing interface metadata as a generated companion file.",
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
},
|
||||
@@ -505,7 +509,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"strategy": "Keep scripts as local package resources; expose help-smoke and permission metadata for reviewer approval before execution.",
|
||||
"script_count": 62,
|
||||
"script_count": 66,
|
||||
"help_smoke_failed_count": 0
|
||||
},
|
||||
"permissions": {
|
||||
@@ -717,7 +721,7 @@
|
||||
"strategy": "Ship the neutral source tree and expose OpenAI-facing interface metadata as a generated companion file.",
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
},
|
||||
@@ -728,7 +732,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"strategy": "Keep scripts as local package resources; expose help-smoke and permission metadata for reviewer approval before execution.",
|
||||
"script_count": 62,
|
||||
"script_count": 66,
|
||||
"help_smoke_failed_count": 0
|
||||
},
|
||||
"permissions": {
|
||||
@@ -975,6 +979,8 @@
|
||||
"scripts/render_social_preview.py",
|
||||
"scripts/render_system_model.py",
|
||||
"scripts/resource_boundary_check.py",
|
||||
"scripts/review_studio_formatting.py",
|
||||
"scripts/review_studio_layout.py",
|
||||
"scripts/run_conformance_suite.py",
|
||||
"scripts/run_description_optimization_suite.py",
|
||||
"scripts/run_eval_suite.py",
|
||||
@@ -982,6 +988,7 @@
|
||||
"scripts/run_output_execution.py",
|
||||
"scripts/simulate_install.py",
|
||||
"scripts/skill_report_charts.py",
|
||||
"scripts/skill_report_layout.py",
|
||||
"scripts/skill_report_metrics.py",
|
||||
"scripts/skill_report_model.py",
|
||||
"scripts/sync_local_install.py",
|
||||
@@ -990,7 +997,8 @@
|
||||
"scripts/upgrade_check.py",
|
||||
"scripts/validate_skill.py",
|
||||
"scripts/verify_package.py",
|
||||
"scripts/yao.py"
|
||||
"scripts/yao.py",
|
||||
"scripts/yao_cli_config.py"
|
||||
],
|
||||
"assets": [
|
||||
"templates/basic_skill.md.j2",
|
||||
@@ -1041,7 +1049,7 @@
|
||||
],
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
}
|
||||
@@ -1279,7 +1287,7 @@
|
||||
"strategy": "Preserve the source tree directly; write target notes in targets/claude/README.md.",
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
},
|
||||
@@ -1290,7 +1298,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"strategy": "Scripts remain local package resources and must be reviewed through trust and permission reports before use.",
|
||||
"script_count": 62,
|
||||
"script_count": 66,
|
||||
"help_smoke_failed_count": 0
|
||||
},
|
||||
"permissions": {
|
||||
@@ -1502,7 +1510,7 @@
|
||||
"strategy": "Preserve the source tree directly; write target notes in targets/claude/README.md.",
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
},
|
||||
@@ -1513,7 +1521,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"strategy": "Scripts remain local package resources and must be reviewed through trust and permission reports before use.",
|
||||
"script_count": 62,
|
||||
"script_count": 66,
|
||||
"help_smoke_failed_count": 0
|
||||
},
|
||||
"permissions": {
|
||||
@@ -1760,6 +1768,8 @@
|
||||
"scripts/render_social_preview.py",
|
||||
"scripts/render_system_model.py",
|
||||
"scripts/resource_boundary_check.py",
|
||||
"scripts/review_studio_formatting.py",
|
||||
"scripts/review_studio_layout.py",
|
||||
"scripts/run_conformance_suite.py",
|
||||
"scripts/run_description_optimization_suite.py",
|
||||
"scripts/run_eval_suite.py",
|
||||
@@ -1767,6 +1777,7 @@
|
||||
"scripts/run_output_execution.py",
|
||||
"scripts/simulate_install.py",
|
||||
"scripts/skill_report_charts.py",
|
||||
"scripts/skill_report_layout.py",
|
||||
"scripts/skill_report_metrics.py",
|
||||
"scripts/skill_report_model.py",
|
||||
"scripts/sync_local_install.py",
|
||||
@@ -1775,7 +1786,8 @@
|
||||
"scripts/upgrade_check.py",
|
||||
"scripts/validate_skill.py",
|
||||
"scripts/verify_package.py",
|
||||
"scripts/yao.py"
|
||||
"scripts/yao.py",
|
||||
"scripts/yao_cli_config.py"
|
||||
],
|
||||
"assets": [
|
||||
"templates/basic_skill.md.j2",
|
||||
@@ -1826,7 +1838,7 @@
|
||||
],
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
}
|
||||
@@ -2064,7 +2076,7 @@
|
||||
"strategy": "Preserve references, scripts, assets, evals, reports, and adapter metadata as relative package resources.",
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
},
|
||||
@@ -2074,7 +2086,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"strategy": "Expose script and permission metadata for downstream clients or installers to enforce.",
|
||||
"script_count": 62,
|
||||
"script_count": 66,
|
||||
"help_smoke_failed_count": 0
|
||||
},
|
||||
"permissions": {
|
||||
@@ -2280,7 +2292,7 @@
|
||||
"strategy": "Preserve references, scripts, assets, evals, reports, and adapter metadata as relative package resources.",
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
},
|
||||
@@ -2290,7 +2302,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"strategy": "Expose script and permission metadata for downstream clients or installers to enforce.",
|
||||
"script_count": 62,
|
||||
"script_count": 66,
|
||||
"help_smoke_failed_count": 0
|
||||
},
|
||||
"permissions": {
|
||||
@@ -2529,6 +2541,8 @@
|
||||
"scripts/render_social_preview.py",
|
||||
"scripts/render_system_model.py",
|
||||
"scripts/resource_boundary_check.py",
|
||||
"scripts/review_studio_formatting.py",
|
||||
"scripts/review_studio_layout.py",
|
||||
"scripts/run_conformance_suite.py",
|
||||
"scripts/run_description_optimization_suite.py",
|
||||
"scripts/run_eval_suite.py",
|
||||
@@ -2536,6 +2550,7 @@
|
||||
"scripts/run_output_execution.py",
|
||||
"scripts/simulate_install.py",
|
||||
"scripts/skill_report_charts.py",
|
||||
"scripts/skill_report_layout.py",
|
||||
"scripts/skill_report_metrics.py",
|
||||
"scripts/skill_report_model.py",
|
||||
"scripts/sync_local_install.py",
|
||||
@@ -2544,7 +2559,8 @@
|
||||
"scripts/upgrade_check.py",
|
||||
"scripts/validate_skill.py",
|
||||
"scripts/verify_package.py",
|
||||
"scripts/yao.py"
|
||||
"scripts/yao.py",
|
||||
"scripts/yao_cli_config.py"
|
||||
],
|
||||
"assets": [
|
||||
"templates/basic_skill.md.j2",
|
||||
@@ -2595,7 +2611,7 @@
|
||||
],
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
}
|
||||
@@ -2833,7 +2849,7 @@
|
||||
"strategy": "Keep optional directories as relative resources next to SKILL.md.",
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
},
|
||||
@@ -2844,7 +2860,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"strategy": "Scripts remain local optional resources and should advertise --help when executable.",
|
||||
"script_count": 62,
|
||||
"script_count": 66,
|
||||
"help_smoke_failed_count": 0
|
||||
},
|
||||
"permissions": {
|
||||
@@ -3049,7 +3065,7 @@
|
||||
"strategy": "Keep optional directories as relative resources next to SKILL.md.",
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
},
|
||||
@@ -3060,7 +3076,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"strategy": "Scripts remain local optional resources and should advertise --help when executable.",
|
||||
"script_count": 62,
|
||||
"script_count": 66,
|
||||
"help_smoke_failed_count": 0
|
||||
},
|
||||
"permissions": {
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
"context_budget_tier": "production",
|
||||
"context_budget_limit": 1000,
|
||||
"skill_body_tokens": 811,
|
||||
"other_text_tokens": 864534,
|
||||
"other_text_tokens": 869504,
|
||||
"estimated_initial_load_tokens": 987,
|
||||
"estimated_total_text_tokens": 865345,
|
||||
"relevant_file_count": 316,
|
||||
"estimated_total_text_tokens": 870315,
|
||||
"relevant_file_count": 327,
|
||||
"unused_resource_dirs": [],
|
||||
"quality_signal_points": 130,
|
||||
"quality_density": 131.7
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"installed_skill_dir": "dist/install-simulation/simulate-yao-meta-skill/yao-meta-skill",
|
||||
"summary": {
|
||||
"archive_present": true,
|
||||
"archive_entry_count": 483,
|
||||
"archive_entry_count": 488,
|
||||
"archive_extracted": true,
|
||||
"entrypoint_loaded": true,
|
||||
"manifest_loaded": true,
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 27.22,
|
||||
"duration_ms": 23.11,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
@@ -62,7 +62,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 27.12,
|
||||
"duration_ms": 23.56,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
@@ -85,7 +85,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 27.12,
|
||||
"duration_ms": 24.17,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
@@ -113,7 +113,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 30.03,
|
||||
"duration_ms": 23.84,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
@@ -136,7 +136,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 27.11,
|
||||
"duration_ms": 22.51,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
@@ -164,7 +164,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 26.68,
|
||||
"duration_ms": 26.03,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
@@ -187,7 +187,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 27.07,
|
||||
"duration_ms": 28.48,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
@@ -214,7 +214,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 27.57,
|
||||
"duration_ms": 23.17,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
@@ -237,7 +237,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 29.2,
|
||||
"duration_ms": 23.94,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
@@ -266,7 +266,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 26.94,
|
||||
"duration_ms": 22.69,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
|
||||
@@ -23,16 +23,16 @@ Command runner evidence is present. This proves the eval harness executed an ext
|
||||
|
||||
| Case | Variant | Mode | Model | Duration ms | Tokens | Score | Status |
|
||||
| --- | --- | --- | --- | ---: | ---: | ---: | --- |
|
||||
| skill-package-contract | baseline | command | local-output-eval-runner | 27.22 | 33 | 0.0 | pass |
|
||||
| skill-package-contract | with_skill | command | local-output-eval-runner | 27.12 | 73 | 100.0 | pass |
|
||||
| output-eval-expectation | baseline | command | local-output-eval-runner | 27.12 | 36 | 0.0 | pass |
|
||||
| output-eval-expectation | with_skill | command | local-output-eval-runner | 30.03 | 80 | 100.0 | pass |
|
||||
| ir-before-packaging | baseline | command | local-output-eval-runner | 27.11 | 33 | 0.0 | pass |
|
||||
| ir-before-packaging | with_skill | command | local-output-eval-runner | 26.68 | 80 | 100.0 | pass |
|
||||
| near-neighbor-boundary | baseline | command | local-output-eval-runner | 27.07 | 36 | 0.0 | pass |
|
||||
| near-neighbor-boundary | with_skill | command | local-output-eval-runner | 27.57 | 65 | 100.0 | pass |
|
||||
| file-backed-governed-package | baseline | command | local-output-eval-runner | 29.2 | 37 | 0.0 | pass |
|
||||
| file-backed-governed-package | with_skill | command | local-output-eval-runner | 26.94 | 98 | 100.0 | pass |
|
||||
| skill-package-contract | baseline | command | local-output-eval-runner | 23.11 | 33 | 0.0 | pass |
|
||||
| skill-package-contract | with_skill | command | local-output-eval-runner | 23.56 | 73 | 100.0 | pass |
|
||||
| output-eval-expectation | baseline | command | local-output-eval-runner | 24.17 | 36 | 0.0 | pass |
|
||||
| output-eval-expectation | with_skill | command | local-output-eval-runner | 23.84 | 80 | 100.0 | pass |
|
||||
| ir-before-packaging | baseline | command | local-output-eval-runner | 22.51 | 33 | 0.0 | pass |
|
||||
| ir-before-packaging | with_skill | command | local-output-eval-runner | 26.03 | 80 | 100.0 | pass |
|
||||
| near-neighbor-boundary | baseline | command | local-output-eval-runner | 28.48 | 36 | 0.0 | pass |
|
||||
| near-neighbor-boundary | with_skill | command | local-output-eval-runner | 23.17 | 65 | 100.0 | pass |
|
||||
| file-backed-governed-package | baseline | command | local-output-eval-runner | 23.94 | 37 | 0.0 | pass |
|
||||
| file-backed-governed-package | with_skill | command | local-output-eval-runner | 22.69 | 98 | 100.0 | pass |
|
||||
|
||||
## Next Fixes
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
"target_count": 3,
|
||||
"adapter_count": 3,
|
||||
"archive_present": true,
|
||||
"archive_sha256": "4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06",
|
||||
"archive_entry_count": 483,
|
||||
"archive_sha256": "7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9",
|
||||
"archive_entry_count": 488,
|
||||
"failure_count": 0,
|
||||
"warning_count": 0
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
- Package directory: `dist`
|
||||
- Targets: `3 / 3` adapters present
|
||||
- Archive present: `True`
|
||||
- Archive SHA256: `4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06`
|
||||
- Archive SHA256: `7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9`
|
||||
- Failures: `0`
|
||||
- Warnings: `0`
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
"trust_level": "local",
|
||||
"license": "MIT",
|
||||
"checksums": {
|
||||
"package_sha256": "9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe",
|
||||
"archive_sha256": "4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06"
|
||||
"package_sha256": "742dc905b0d221c4f336e741d168861edaf7b75e97fe1e89f7d454c1cabf928f",
|
||||
"archive_sha256": "7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9"
|
||||
},
|
||||
"compatibility": {
|
||||
"openai": "pass",
|
||||
@@ -52,7 +52,7 @@
|
||||
},
|
||||
"distribution": {
|
||||
"archive_verified": true,
|
||||
"archive_sha256": "4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06",
|
||||
"archive_sha256": "7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9",
|
||||
"package_verification": "reports/package_verification.json",
|
||||
"install_simulated": true,
|
||||
"install_simulation": "reports/install_simulation.json"
|
||||
@@ -76,7 +76,7 @@
|
||||
"agent-skills-compatible"
|
||||
],
|
||||
"package_metadata": "registry/packages/yao-meta-skill.json",
|
||||
"package_sha256": "9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe"
|
||||
"package_sha256": "742dc905b0d221c4f336e741d168861edaf7b75e97fe1e89f7d454c1cabf928f"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
- Maturity: `governed`
|
||||
- Owner: `Yao Team`
|
||||
- License: `MIT`
|
||||
- Package SHA256: `9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe`
|
||||
- Archive SHA256: `4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06`
|
||||
- Package SHA256: `742dc905b0d221c4f336e741d168861edaf7b75e97fe1e89f7d454c1cabf928f`
|
||||
- Archive SHA256: `7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9`
|
||||
- Install simulated: `True`
|
||||
|
||||
## Compatibility
|
||||
|
||||
+38
-17
@@ -5,7 +5,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Yao Meta Skill Review Studio 2.0</title>
|
||||
<style>
|
||||
:root {
|
||||
:root {
|
||||
--ink: #1B365D;
|
||||
--text: #24201d;
|
||||
--muted: #746d66;
|
||||
@@ -102,6 +102,27 @@
|
||||
background: #fff;
|
||||
}
|
||||
.panel p { color: var(--muted); }
|
||||
.kv-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 10px 12px;
|
||||
margin: 2px 0 0;
|
||||
}
|
||||
.kv-grid div {
|
||||
min-width: 0;
|
||||
padding: 9px 0 0;
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
.kv-grid dt {
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
}
|
||||
.kv-grid dd {
|
||||
margin: 2px 0 0;
|
||||
color: var(--ink);
|
||||
font-size: 15px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.issues, .evidence {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
@@ -198,7 +219,7 @@
|
||||
font-size: 13px;
|
||||
}
|
||||
@media (max-width: 980px) {
|
||||
.metrics, .gates, .twocol, .actions-grid, .annotations-grid { grid-template-columns: 1fr; }
|
||||
.metrics, .gates, .twocol, .actions-grid, .annotations-grid, .kv-grid { grid-template-columns: 1fr; }
|
||||
main { padding: 32px 18px 60px; }
|
||||
nav { justify-content: flex-start; overflow-x: auto; flex-wrap: nowrap; }
|
||||
nav a { flex: 0 0 auto; }
|
||||
@@ -221,12 +242,12 @@
|
||||
|
||||
<section>
|
||||
<h2>核心指标</h2>
|
||||
<div class="metrics"><article class='metric'><span>Skill IR</span><strong>2.0.0</strong><p>4 targets in platform-neutral contract</p></article><article class='metric'><span>Compiler</span><strong>4/4</strong><p>target contracts compiled from Skill IR</p></article><article class='metric'><span>Output Delta</span><strong>100.0</strong><p>5 cases; 1 file-backed</p></article><article class='metric'><span>Exec Runs</span><strong>10</strong><p>command 10; model 0; recorded 0</p></article><article class='metric'><span>Blind A/B</span><strong>5</strong><p>review pairs hide baseline vs with-skill labels</p></article><article class='metric'><span>Review A/B</span><strong>0/5</strong><p>adjudication decisions; pending 5</p></article><article class='metric'><span>Runtime</span><strong>5/5</strong><p>target conformance pass rate</p></article><article class='metric'><span>Perm Probe</span><strong>3/3</strong><p>0 native enforcement targets</p></article><article class='metric'><span>Trust</span><strong>0</strong><p>62 scripts scanned; secrets found</p></article><article class='metric'><span>Atlas</span><strong>5</strong><p>12 scanned skills; route collisions</p></article><article class='metric'><span>Drift</span><strong>low</strong><p>1 metadata events; 0 missed triggers</p></article><article class='metric'><span>Waivers</span><strong>0</strong><p>0 gates covered; human risk decisions</p></article><article class='metric'><span>Notes</span><strong>0/0</strong><p>0 open blocker annotations</p></article><article class='metric'><span>Registry</span><strong>1.1.0</strong><p>4 targets; MIT license</p></article><article class='metric'><span>Archive</span><strong>pass</strong><p>483 zip entries; package verification</p></article><article class='metric'><span>Install</span><strong>pass</strong><p>3 adapters readable; local install simulation</p></article><article class='metric'><span>Upgrade</span><strong>minor</strong><p>declared minor; 0 breaking changes</p></article></div>
|
||||
<div class="metrics"><article class='metric'><span>Skill IR</span><strong>2.0.0</strong><p>4 targets in platform-neutral contract</p></article><article class='metric'><span>Compiler</span><strong>4/4</strong><p>target contracts compiled from Skill IR</p></article><article class='metric'><span>Output Delta</span><strong>100.0</strong><p>5 cases; 1 file-backed</p></article><article class='metric'><span>Exec Runs</span><strong>10</strong><p>command 10; model 0; recorded 0</p></article><article class='metric'><span>Blind A/B</span><strong>5</strong><p>review pairs hide baseline vs with-skill labels</p></article><article class='metric'><span>Review A/B</span><strong>0/5</strong><p>adjudication decisions; pending 5</p></article><article class='metric'><span>Runtime</span><strong>5/5</strong><p>target conformance pass rate</p></article><article class='metric'><span>Perm Probe</span><strong>3/3</strong><p>0 native enforcement targets</p></article><article class='metric'><span>Trust</span><strong>0</strong><p>66 scripts scanned; secrets found</p></article><article class='metric'><span>Atlas</span><strong>5</strong><p>12 scanned skills; route collisions</p></article><article class='metric'><span>Drift</span><strong>low</strong><p>1 metadata events; 0 missed triggers</p></article><article class='metric'><span>Waivers</span><strong>0</strong><p>0 gates covered; human risk decisions</p></article><article class='metric'><span>Notes</span><strong>0/0</strong><p>0 open blocker annotations</p></article><article class='metric'><span>Registry</span><strong>1.1.0</strong><p>4 targets; MIT license</p></article><article class='metric'><span>Archive</span><strong>pass</strong><p>488 zip entries; package verification</p></article><article class='metric'><span>Install</span><strong>pass</strong><p>3 adapters readable; local install simulation</p></article><article class='metric'><span>Upgrade</span><strong>minor</strong><p>declared minor; 0 breaking changes</p></article></div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2>审查闸门</h2>
|
||||
<div class="gates"><article class='gate pass'><div><span>通过</span><h3>意图画布</h3></div><p>intent confidence 100/100; Intent is clear enough to package the first routeable version.</p><footer>reports/intent-confidence.json <a href='intent-confidence.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>触发实验</h3></div><p>13 trigger cases; 0 misroutes; 0 ambiguous</p><footer>reports/route_scorecard.json <a href='route_scorecard.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>输出实验</h3></div><p>5/5 cases; with-skill 100.0; baseline 0.0; file-backed 1; near-neighbor 1; blind A/B 5; exec 10; command 10; model 0; recorded 0; reviewed 0/5</p><footer>reports/output_quality_scorecard.json <a href='output_quality_scorecard.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>上下文</h3></div><p>initial load 987/1000; quality density 131.7</p><footer>reports/context_budget.json <a href='context_budget.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>运行矩阵</h3></div><p>5 / 5 targets pass</p><footer>reports/conformance_matrix.json <a href='conformance_matrix.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>信任报告</h3></div><p>0 secrets; 62 scripts; 2 network-capable scripts; 0 help smoke failures</p><footer>reports/security_trust_report.json <a href='security_trust_report.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>权限批准</h3></div><p>3/3 permissions approved; gaps 0; required file_write, network, subprocess</p><footer>reports/security_trust_report.json + security/permission_policy.json <a href='../security/permission_policy.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>权限探针</h3></div><p>3/3 targets probed; native 0; metadata fallback 3; residual risks 3</p><footer>reports/runtime_permission_probes.json <a href='runtime_permission_probes.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>组合治理</h3></div><p>12 skills, 1 actionable; 0 actionable route collisions; 0 actionable owner gaps; 0 actionable stale; 24 scoped non-actionable issues</p><footer>reports/skill_atlas.json <a href='skill_atlas.html'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>运营回路</h3></div><p>1 metadata events; adoption 100.0; missed 0; bad-output 0; risk low</p><footer>reports/adoption_drift_report.json <a href='adoption_drift_report.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>人工批准</h3></div><p>0 active waivers cover current warnings</p><footer>reports/review_waivers.json <a href='review_waivers.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>注册审计</h3></div><p>yao-meta-skill 1.1.0; 6/6 compatibility entries pass; install pass with 3 adapters</p><footer>reports/registry_audit.json + reports/install_simulation.json <a href='registry_audit.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>发布路线</h3></div><p>0 promote; 3 keep current; 0 blocked; upgrade minor declared / minor recommended</p><footer>reports/promotion_decisions.json + reports/upgrade_check.json + docs/migration-v2.md <a href='promotion_decisions.md'>证据</a></footer></article></div>
|
||||
<div class="gates"><article class='gate pass'><div><span>通过</span><h3>意图画布</h3></div><p>intent confidence 100/100; Intent is clear enough to package the first routeable version.</p><footer>reports/intent-confidence.json <a href='intent-confidence.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>触发实验</h3></div><p>13 trigger cases; 0 misroutes; 0 ambiguous</p><footer>reports/route_scorecard.json <a href='route_scorecard.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>输出实验</h3></div><p>5/5 cases; with-skill 100.0; baseline 0.0; file-backed 1; near-neighbor 1; blind A/B 5; exec 10; command 10; model 0; recorded 0; reviewed 0/5</p><footer>reports/output_quality_scorecard.json <a href='output_quality_scorecard.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>上下文</h3></div><p>initial load 987/1000; quality density 131.7</p><footer>reports/context_budget.json <a href='context_budget.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>运行矩阵</h3></div><p>5 / 5 targets pass</p><footer>reports/conformance_matrix.json <a href='conformance_matrix.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>信任报告</h3></div><p>0 secrets; 66 scripts; 2 network-capable scripts; 0 help smoke failures</p><footer>reports/security_trust_report.json <a href='security_trust_report.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>权限批准</h3></div><p>3/3 permissions approved; gaps 0; required file_write, network, subprocess</p><footer>reports/security_trust_report.json + security/permission_policy.json <a href='../security/permission_policy.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>权限探针</h3></div><p>3/3 targets probed; native 0; metadata fallback 3; residual risks 3</p><footer>reports/runtime_permission_probes.json <a href='runtime_permission_probes.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>组合治理</h3></div><p>12 skills, 1 actionable; 0 actionable route collisions; 0 actionable owner gaps; 0 actionable stale; 24 scoped non-actionable issues</p><footer>reports/skill_atlas.json <a href='skill_atlas.html'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>运营回路</h3></div><p>1 metadata events; adoption 100.0; missed 0; bad-output 0; risk low</p><footer>reports/adoption_drift_report.json <a href='adoption_drift_report.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>人工批准</h3></div><p>0 active waivers cover current warnings</p><footer>reports/review_waivers.json <a href='review_waivers.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>注册审计</h3></div><p>yao-meta-skill 1.1.0; 6/6 compatibility entries pass; install pass with 3 adapters</p><footer>reports/registry_audit.json + reports/install_simulation.json <a href='registry_audit.md'>证据</a></footer></article><article class='gate pass'><div><span>通过</span><h3>发布路线</h3></div><p>0 promote; 3 keep current; 0 blocked; upgrade minor declared / minor recommended</p><footer>reports/promotion_decisions.json + reports/upgrade_check.json + docs/migration-v2.md <a href='promotion_decisions.md'>证据</a></footer></article></div>
|
||||
</section>
|
||||
|
||||
<div class="twocol">
|
||||
@@ -258,17 +279,17 @@
|
||||
|
||||
<section id="trigger" class="twocol">
|
||||
<div class="panel"><h2>触发实验</h2><p>13 trigger cases; 0 misroutes; 0 ambiguous</p></div>
|
||||
<div class="panel"><h2>组合治理</h2><p>{'skill_count': 12, 'actionable_skill_count': 1, 'route_collision_count': 5, 'actionable_route_collision_count': 0, 'owner_gap_count': 9, 'actionable_owner_gap_count': 0, 'stale_count': 10, 'actionable_stale_count': 0, 'shared_resource_count': 0, 'no_route_opportunity_count': 0, 'non_actionable_issue_count': 24}</p></div>
|
||||
<div class="panel"><h2>组合治理</h2><dl class='kv-grid'><div><dt>Skill 数</dt><dd>12</dd></div><div><dt>纳入审查</dt><dd>1</dd></div><div><dt>待处理冲突</dt><dd>0</dd></div><div><dt>待处理 owner</dt><dd>0</dd></div><div><dt>待处理过期</dt><dd>0</dd></div><div><dt>非行动项</dt><dd>24</dd></div></dl></div>
|
||||
</section>
|
||||
|
||||
<section id="output" class="twocol">
|
||||
<div class="panel"><h2>输出实验</h2><p>{'case_count': 5, 'file_backed_case_count': 1, 'near_neighbor_case_count': 1, 'boundary_case_count': 1, 'baseline_pass_rate': 0.0, 'with_skill_pass_rate': 100.0, 'delta': 100.0, 'regression_count': 0, 'gate_pass': True, 'failure_taxonomy': [], 'blind_pair_count': 5}</p></div>
|
||||
<div class="panel"><h2>执行证据</h2><p>{'case_count': 5, 'variant_run_count': 10, 'command_executed_count': 10, 'model_executed_count': 0, 'recorded_fixture_count': 0, 'timing_observed_count': 10, 'token_observed_count': 0, 'token_estimated_count': 10, 'baseline_pass_rate': 0.0, 'with_skill_pass_rate': 100.0, 'delta': 100.0, 'regression_count': 0, 'failure_count': 0, 'gate_pass': True}</p></div>
|
||||
<div class="panel"><h2>输出实验</h2><dl class='kv-grid'><div><dt>案例数</dt><dd>5</dd></div><div><dt>With Skill</dt><dd>100</dd></div><div><dt>Baseline</dt><dd>0</dd></div><div><dt>增益</dt><dd>100</dd></div><div><dt>Gate</dt><dd>是</dd></div></dl></div>
|
||||
<div class="panel"><h2>执行证据</h2><dl class='kv-grid'><div><dt>运行数</dt><dd>10</dd></div><div><dt>命令执行</dt><dd>10</dd></div><div><dt>模型执行</dt><dd>0</dd></div><div><dt>记录样本</dt><dd>0</dd></div><div><dt>计时样本</dt><dd>10</dd></div><div><dt>估算 Token</dt><dd>10</dd></div></dl></div>
|
||||
</section>
|
||||
|
||||
<section class="twocol">
|
||||
<div class="panel"><h2>盲评包</h2><p>{'pair_count': 5, 'answer_key_separate': True, 'with_skill_hidden_count': 5}</p></div>
|
||||
<div class="panel"><h2>审定报告</h2><p>{'pair_count': 5, 'judgment_count': 0, 'pending_count': 5, 'agreement_count': 0, 'disagreement_count': 0, 'invalid_decision_count': 0, 'agreement_rate': None, 'needs_review': True, 'failure_count': 0}</p></div>
|
||||
<div class="panel"><h2>盲评包</h2><dl class='kv-grid'><div><dt>Pair Count</dt><dd>5</dd></div><div><dt>Answer Key Separate</dt><dd>是</dd></div><div><dt>With Skill Hidden Count</dt><dd>5</dd></div></dl></div>
|
||||
<div class="panel"><h2>审定报告</h2><dl class='kv-grid'><div><dt>Pair Count</dt><dd>5</dd></div><div><dt>Judgment Count</dt><dd>0</dd></div><div><dt>待审</dt><dd>5</dd></div><div><dt>Agreement Count</dt><dd>0</dd></div><div><dt>Disagreement Count</dt><dd>0</dd></div><div><dt>Invalid Decision Count</dt><dd>0</dd></div></dl></div>
|
||||
</section>
|
||||
|
||||
<section class="twocol">
|
||||
@@ -282,8 +303,8 @@
|
||||
</section>
|
||||
|
||||
<section id="runtime" class="twocol">
|
||||
<div class="panel"><h2>运行矩阵</h2><p>{'target_count': 5, 'pass_count': 5, 'fail_count': 0}</p></div>
|
||||
<div class="panel"><h2>目标编译</h2><p>{'target_count': 4, 'pass_count': 4, 'warn_count': 0, 'block_count': 0, 'failure_count': 0, 'warning_count': 0}</p></div>
|
||||
<div class="panel"><h2>运行矩阵</h2><dl class='kv-grid'><div><dt>目标数</dt><dd>5</dd></div><div><dt>通过数</dt><dd>5</dd></div><div><dt>Fail Count</dt><dd>0</dd></div></dl></div>
|
||||
<div class="panel"><h2>目标编译</h2><dl class='kv-grid'><div><dt>目标数</dt><dd>4</dd></div><div><dt>通过数</dt><dd>4</dd></div><div><dt>Warn Count</dt><dd>0</dd></div><div><dt>Block Count</dt><dd>0</dd></div><div><dt>失败数</dt><dd>0</dd></div></dl></div>
|
||||
</section>
|
||||
|
||||
<section class="twocol">
|
||||
@@ -292,7 +313,7 @@
|
||||
</section>
|
||||
|
||||
<section id="trust" class="twocol">
|
||||
<div class="panel"><h2>信任报告</h2><p>{'scanned_files': 146, 'script_count': 62, 'internal_module_count': 3, 'secret_findings': 0, 'dependency_files': ['requirements-ci.txt'], 'network_script_count': 2, 'network_policy_covered_count': 2, 'network_policy_missing_count': 0, 'file_write_script_count': 47, 'permission_required_count': 3, 'permission_approved_count': 3, 'permission_missing_count': 0, 'permission_invalid_count': 0, 'permission_expired_count': 0, 'help_smoke_checked_count': 59, 'help_smoke_failed_count': 0, 'interactive_script_count': 0, 'package_hash_scope': 'source-contract-without-generated-reports', 'package_hash_file_count': 146, 'package_sha256': '9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe'}</p></div>
|
||||
<div class="panel"><h2>信任报告</h2><dl class='kv-grid'><div><dt>Secret</dt><dd>0</dd></div><div><dt>脚本数</dt><dd>66</dd></div><div><dt>网络脚本</dt><dd>2</dd></div><div><dt>Help 失败</dt><dd>0</dd></div><div><dt>包体哈希</dt><dd><code>742dc905b0d221c4f336e741d168861edaf7b75e97fe1e89f7d454c1cabf928f</code></dd></div></dl></div>
|
||||
<div class="panel"><h2>安全边界</h2><p>高风险 secret、远程 inline execution、缺失依赖策略或无法解释的脚本接口应阻断 governed release。</p></div>
|
||||
</section>
|
||||
|
||||
@@ -303,7 +324,7 @@
|
||||
|
||||
<section id="permission-probes" class="twocol">
|
||||
<div class="panel"><h2>权限探针</h2><p>3/3 targets probed; native 0; metadata fallback 3; residual risks 3</p></div>
|
||||
<div class="panel"><h2>运行边界</h2><p>{'target_count': 3, 'pass_count': 3, 'fail_count': 0, 'native_enforcement_count': 0, 'metadata_fallback_count': 3, 'residual_risk_count': 3, 'required_capability_count': 3, 'failure_count': 0}</p></div>
|
||||
<div class="panel"><h2>运行边界</h2><dl class='kv-grid'><div><dt>目标数</dt><dd>3</dd></div><div><dt>通过数</dt><dd>3</dd></div><div><dt>原生执行</dt><dd>0</dd></div><div><dt>Metadata fallback</dt><dd>3</dd></div><div><dt>残余风险</dt><dd>3</dd></div><div><dt>失败数</dt><dd>0</dd></div></dl></div>
|
||||
</section>
|
||||
|
||||
<section id="atlas" class="twocol">
|
||||
@@ -313,22 +334,22 @@
|
||||
|
||||
<section id="telemetry" class="twocol">
|
||||
<div class="panel"><h2>运营回路</h2><p>1 metadata events; adoption 100.0; missed 0; bad-output 0; risk low</p></div>
|
||||
<div class="panel"><h2>漂移信号</h2><p>{'event_count': 1, 'activation_count': 1, 'accepted_count': 1, 'edited_count': 0, 'rejected_count': 0, 'missed_count': 0, 'failed_count': 0, 'adoption_rate': 100.0, 'missed_trigger_count': 0, 'wrong_trigger_count': 0, 'bad_output_count': 0, 'script_error_count': 0, 'missing_resource_count': 0, 'review_overdue_count': 0, 'risk_band': 'low', 'event_types': {'skill_activation': 1}, 'failure_types': {}}</p></div>
|
||||
<div class="panel"><h2>漂移信号</h2><dl class='kv-grid'><div><dt>事件数</dt><dd>1</dd></div><div><dt>采用率</dt><dd>100</dd></div><div><dt>漏触发</dt><dd>0</dd></div><div><dt>Bad Output Count</dt><dd>0</dd></div><div><dt>风险带</dt><dd>low</dd></div></dl></div>
|
||||
</section>
|
||||
|
||||
<section id="waivers" class="twocol">
|
||||
<div class="panel"><h2>人工批准</h2><p>0 active waivers cover current warnings</p></div>
|
||||
<div class="panel"><h2>批准台账</h2><p>{'waiver_count': 0, 'active_count': 0, 'expired_count': 0, 'invalid_count': 0, 'covered_gate_count': 0, 'covered_gate_keys': []}</p></div>
|
||||
<div class="panel"><h2>批准台账</h2><dl class='kv-grid'><div><dt>Waiver Count</dt><dd>0</dd></div><div><dt>Active Count</dt><dd>0</dd></div><div><dt>Expired Count</dt><dd>0</dd></div><div><dt>Invalid Count</dt><dd>0</dd></div><div><dt>覆盖 Gate</dt><dd>0</dd></div></dl></div>
|
||||
</section>
|
||||
|
||||
<section id="registry" class="twocol">
|
||||
<div class="panel"><h2>注册审计</h2><p>yao-meta-skill 1.1.0; 6/6 compatibility entries pass; install pass with 3 adapters</p></div>
|
||||
<div class="panel"><h2>包体元数据</h2><p>{'schema_version': '2.0', 'name': 'yao-meta-skill', 'version': '1.1.0', 'description': 'Create, refactor, evaluate, and package agent skills from workflows, prompts, transcripts, docs, or notes. Use when asked to create a skill, turn a repeated process into a reusable skill, improve an existing skill, add evals, or package a skill for team reuse.', 'targets': ['openai', 'claude', 'generic', 'agent-skills-compatible'], 'maturity': 'governed', 'owner': 'Yao Team', 'review_cadence': 'quarterly', 'trust_level': 'local', 'license': 'MIT', 'checksums': {'package_sha256': '9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe', 'archive_sha256': '4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06'}, 'compatibility': {'openai': 'pass', 'claude': 'pass', 'agent-skills': 'pass', 'vscode': 'pass', 'generic': 'pass', 'agent-skills-compatible': 'pass'}, 'source': {'skill_dir': '.', 'skill_ir': 'skill-ir/examples/yao-meta-skill.json', 'ir_schema_version': '2.0.0', 'canonical_metadata': 'agents/interface.yaml'}, 'artifacts': {'overview_html': 'reports/skill-overview.html', 'review_studio_html': 'reports/review-studio.html', 'trust_report': 'reports/security_trust_report.md', 'conformance_matrix': 'reports/conformance_matrix.md', 'compiled_targets': 'reports/compiled_targets.md', 'package_verification': 'reports/package_verification.md', 'install_simulation': 'reports/install_simulation.md', 'adoption_drift': 'reports/adoption_drift_report.md', 'review_waivers': 'reports/review_waivers.md', 'review_annotations': 'reports/review_annotations.md', 'package_metadata': 'registry/packages/yao-meta-skill.json'}, 'distribution': {'archive_verified': True, 'archive_sha256': '4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06', 'package_verification': 'reports/package_verification.json', 'install_simulated': True, 'install_simulation': 'reports/install_simulation.json'}, 'generated_at': '2026-06-13'}</p></div>
|
||||
<div class="panel"><h2>包体元数据</h2><dl class='kv-grid'><div><dt>名称</dt><dd>yao-meta-skill</dd></div><div><dt>版本</dt><dd>1.1.0</dd></div><div><dt>Maturity</dt><dd>governed</dd></div><div><dt>Owner</dt><dd>Yao Team</dd></div><div><dt>License</dt><dd>MIT</dd></div><div><dt>信任级别</dt><dd>local</dd></div><div><dt>目标平台</dt><dd>openai, claude, generic, agent-skills-compatible</dd></div><div><dt>兼容通过</dt><dd>6/6</dd></div><div><dt>归档哈希</dt><dd><code>7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9</code></dd></div></dl></div>
|
||||
</section>
|
||||
|
||||
<section id="release" class="twocol">
|
||||
<div class="panel"><h2>发布路线</h2><p>0 promote; 3 keep current; 0 blocked; upgrade minor declared / minor recommended</p></div>
|
||||
<div class="panel"><h2>包体验证</h2><p>{'target_count': 3, 'adapter_count': 3, 'archive_present': True, 'archive_sha256': '4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06', 'archive_entry_count': 483, 'failure_count': 0, 'warning_count': 0}</p></div>
|
||||
<div class="panel"><h2>包体验证</h2><dl class='kv-grid'><div><dt>目标数</dt><dd>3</dd></div><div><dt>Adapter</dt><dd>3</dd></div><div><dt>归档存在</dt><dd>是</dd></div><div><dt>Zip 条目</dt><dd>488</dd></div><div><dt>失败数</dt><dd>0</dd></div><div><dt>警告数</dt><dd>0</dd></div><div><dt>归档哈希</dt><dd><code>7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9</code></dd></div></dl></div>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
+163
-71
@@ -59,7 +59,7 @@
|
||||
"key": "trust-report",
|
||||
"label": "信任报告",
|
||||
"status": "pass",
|
||||
"detail": "0 secrets; 62 scripts; 2 network-capable scripts; 0 help smoke failures",
|
||||
"detail": "0 secrets; 66 scripts; 2 network-capable scripts; 0 help smoke failures",
|
||||
"evidence": "reports/security_trust_report.json",
|
||||
"link": "security_trust_report.md"
|
||||
},
|
||||
@@ -581,7 +581,7 @@
|
||||
"path": "scripts",
|
||||
"label": "Deterministic helpers or local tooling",
|
||||
"kind": "folder",
|
||||
"file_count": 62
|
||||
"file_count": 66
|
||||
},
|
||||
{
|
||||
"path": "evals",
|
||||
@@ -596,7 +596,7 @@
|
||||
"file_count": 170
|
||||
}
|
||||
],
|
||||
"file_count": 296,
|
||||
"file_count": 300,
|
||||
"folder_count": 4,
|
||||
"distribution": [
|
||||
{
|
||||
@@ -621,7 +621,7 @@
|
||||
},
|
||||
{
|
||||
"label": "scripts",
|
||||
"value": 62
|
||||
"value": 66
|
||||
},
|
||||
{
|
||||
"label": "evals",
|
||||
@@ -750,7 +750,7 @@
|
||||
"path": "scripts",
|
||||
"label": "Deterministic helpers or local tooling",
|
||||
"kind": "folder",
|
||||
"file_count": 62
|
||||
"file_count": 66
|
||||
},
|
||||
{
|
||||
"path": "evals",
|
||||
@@ -1068,9 +1068,9 @@
|
||||
"failures": []
|
||||
},
|
||||
"trust_security": {
|
||||
"scanned_files": 146,
|
||||
"script_count": 62,
|
||||
"internal_module_count": 3,
|
||||
"scanned_files": 150,
|
||||
"script_count": 66,
|
||||
"internal_module_count": 7,
|
||||
"secret_findings": 0,
|
||||
"dependency_files": [
|
||||
"requirements-ci.txt"
|
||||
@@ -1088,8 +1088,8 @@
|
||||
"help_smoke_failed_count": 0,
|
||||
"interactive_script_count": 0,
|
||||
"package_hash_scope": "source-contract-without-generated-reports",
|
||||
"package_hash_file_count": 146,
|
||||
"package_sha256": "9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe"
|
||||
"package_hash_file_count": 150,
|
||||
"package_sha256": "742dc905b0d221c4f336e741d168861edaf7b75e97fe1e89f7d454c1cabf928f"
|
||||
},
|
||||
"skill_atlas": {
|
||||
"skill_count": 12,
|
||||
@@ -1123,8 +1123,8 @@
|
||||
"trust_level": "local",
|
||||
"license": "MIT",
|
||||
"checksums": {
|
||||
"package_sha256": "9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe",
|
||||
"archive_sha256": "4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06"
|
||||
"package_sha256": "742dc905b0d221c4f336e741d168861edaf7b75e97fe1e89f7d454c1cabf928f",
|
||||
"archive_sha256": "7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9"
|
||||
},
|
||||
"compatibility": {
|
||||
"openai": "pass",
|
||||
@@ -1155,7 +1155,7 @@
|
||||
},
|
||||
"distribution": {
|
||||
"archive_verified": true,
|
||||
"archive_sha256": "4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06",
|
||||
"archive_sha256": "7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9",
|
||||
"package_verification": "reports/package_verification.json",
|
||||
"install_simulated": true,
|
||||
"install_simulation": "reports/install_simulation.json"
|
||||
@@ -1171,8 +1171,8 @@
|
||||
"target_count": 3,
|
||||
"adapter_count": 3,
|
||||
"archive_present": true,
|
||||
"archive_sha256": "4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06",
|
||||
"archive_entry_count": 483,
|
||||
"archive_sha256": "7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9",
|
||||
"archive_entry_count": 488,
|
||||
"failure_count": 0,
|
||||
"warning_count": 0
|
||||
},
|
||||
@@ -1183,7 +1183,7 @@
|
||||
"ok": true,
|
||||
"summary": {
|
||||
"archive_present": true,
|
||||
"archive_entry_count": 483,
|
||||
"archive_entry_count": 488,
|
||||
"archive_extracted": true,
|
||||
"entrypoint_loaded": true,
|
||||
"manifest_loaded": true,
|
||||
@@ -1245,12 +1245,12 @@
|
||||
{
|
||||
"field": "archive_sha256",
|
||||
"from": "",
|
||||
"to": "4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06"
|
||||
"to": "7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9"
|
||||
},
|
||||
{
|
||||
"field": "package_sha256",
|
||||
"from": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"to": "9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe"
|
||||
"to": "742dc905b0d221c4f336e741d168861edaf7b75e97fe1e89f7d454c1cabf928f"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -2978,7 +2978,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 27.22,
|
||||
"duration_ms": 23.11,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
@@ -3006,7 +3006,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 27.12,
|
||||
"duration_ms": 23.56,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
@@ -3029,7 +3029,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 27.12,
|
||||
"duration_ms": 24.17,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
@@ -3057,7 +3057,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 30.03,
|
||||
"duration_ms": 23.84,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
@@ -3080,7 +3080,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 27.11,
|
||||
"duration_ms": 22.51,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
@@ -3108,7 +3108,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 26.68,
|
||||
"duration_ms": 26.03,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
@@ -3131,7 +3131,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 27.07,
|
||||
"duration_ms": 28.48,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
@@ -3158,7 +3158,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 27.57,
|
||||
"duration_ms": 23.17,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
@@ -3181,7 +3181,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 29.2,
|
||||
"duration_ms": 23.94,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
@@ -3210,7 +3210,7 @@
|
||||
"execution_mode": "command",
|
||||
"model_executed": false,
|
||||
"command_executed": true,
|
||||
"duration_ms": 26.94,
|
||||
"duration_ms": 22.69,
|
||||
"provider": "local-output-eval-runner",
|
||||
"model": "",
|
||||
"usage": {
|
||||
@@ -3702,6 +3702,8 @@
|
||||
"scripts/render_social_preview.py",
|
||||
"scripts/render_system_model.py",
|
||||
"scripts/resource_boundary_check.py",
|
||||
"scripts/review_studio_formatting.py",
|
||||
"scripts/review_studio_layout.py",
|
||||
"scripts/run_conformance_suite.py",
|
||||
"scripts/run_description_optimization_suite.py",
|
||||
"scripts/run_eval_suite.py",
|
||||
@@ -3709,6 +3711,7 @@
|
||||
"scripts/run_output_execution.py",
|
||||
"scripts/simulate_install.py",
|
||||
"scripts/skill_report_charts.py",
|
||||
"scripts/skill_report_layout.py",
|
||||
"scripts/skill_report_metrics.py",
|
||||
"scripts/skill_report_model.py",
|
||||
"scripts/sync_local_install.py",
|
||||
@@ -3717,7 +3720,8 @@
|
||||
"scripts/upgrade_check.py",
|
||||
"scripts/validate_skill.py",
|
||||
"scripts/verify_package.py",
|
||||
"scripts/yao.py"
|
||||
"scripts/yao.py",
|
||||
"scripts/yao_cli_config.py"
|
||||
],
|
||||
"assets": [
|
||||
"templates/basic_skill.md.j2",
|
||||
@@ -3768,7 +3772,7 @@
|
||||
],
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
}
|
||||
@@ -4006,7 +4010,7 @@
|
||||
"strategy": "Ship the neutral source tree and expose OpenAI-facing interface metadata as a generated companion file.",
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
},
|
||||
@@ -4017,7 +4021,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"strategy": "Keep scripts as local package resources; expose help-smoke and permission metadata for reviewer approval before execution.",
|
||||
"script_count": 62,
|
||||
"script_count": 66,
|
||||
"help_smoke_failed_count": 0
|
||||
},
|
||||
"permissions": {
|
||||
@@ -4229,7 +4233,7 @@
|
||||
"strategy": "Ship the neutral source tree and expose OpenAI-facing interface metadata as a generated companion file.",
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
},
|
||||
@@ -4240,7 +4244,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"strategy": "Keep scripts as local package resources; expose help-smoke and permission metadata for reviewer approval before execution.",
|
||||
"script_count": 62,
|
||||
"script_count": 66,
|
||||
"help_smoke_failed_count": 0
|
||||
},
|
||||
"permissions": {
|
||||
@@ -4487,6 +4491,8 @@
|
||||
"scripts/render_social_preview.py",
|
||||
"scripts/render_system_model.py",
|
||||
"scripts/resource_boundary_check.py",
|
||||
"scripts/review_studio_formatting.py",
|
||||
"scripts/review_studio_layout.py",
|
||||
"scripts/run_conformance_suite.py",
|
||||
"scripts/run_description_optimization_suite.py",
|
||||
"scripts/run_eval_suite.py",
|
||||
@@ -4494,6 +4500,7 @@
|
||||
"scripts/run_output_execution.py",
|
||||
"scripts/simulate_install.py",
|
||||
"scripts/skill_report_charts.py",
|
||||
"scripts/skill_report_layout.py",
|
||||
"scripts/skill_report_metrics.py",
|
||||
"scripts/skill_report_model.py",
|
||||
"scripts/sync_local_install.py",
|
||||
@@ -4502,7 +4509,8 @@
|
||||
"scripts/upgrade_check.py",
|
||||
"scripts/validate_skill.py",
|
||||
"scripts/verify_package.py",
|
||||
"scripts/yao.py"
|
||||
"scripts/yao.py",
|
||||
"scripts/yao_cli_config.py"
|
||||
],
|
||||
"assets": [
|
||||
"templates/basic_skill.md.j2",
|
||||
@@ -4553,7 +4561,7 @@
|
||||
],
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
}
|
||||
@@ -4791,7 +4799,7 @@
|
||||
"strategy": "Preserve the source tree directly; write target notes in targets/claude/README.md.",
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
},
|
||||
@@ -4802,7 +4810,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"strategy": "Scripts remain local package resources and must be reviewed through trust and permission reports before use.",
|
||||
"script_count": 62,
|
||||
"script_count": 66,
|
||||
"help_smoke_failed_count": 0
|
||||
},
|
||||
"permissions": {
|
||||
@@ -5014,7 +5022,7 @@
|
||||
"strategy": "Preserve the source tree directly; write target notes in targets/claude/README.md.",
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
},
|
||||
@@ -5025,7 +5033,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"strategy": "Scripts remain local package resources and must be reviewed through trust and permission reports before use.",
|
||||
"script_count": 62,
|
||||
"script_count": 66,
|
||||
"help_smoke_failed_count": 0
|
||||
},
|
||||
"permissions": {
|
||||
@@ -5272,6 +5280,8 @@
|
||||
"scripts/render_social_preview.py",
|
||||
"scripts/render_system_model.py",
|
||||
"scripts/resource_boundary_check.py",
|
||||
"scripts/review_studio_formatting.py",
|
||||
"scripts/review_studio_layout.py",
|
||||
"scripts/run_conformance_suite.py",
|
||||
"scripts/run_description_optimization_suite.py",
|
||||
"scripts/run_eval_suite.py",
|
||||
@@ -5279,6 +5289,7 @@
|
||||
"scripts/run_output_execution.py",
|
||||
"scripts/simulate_install.py",
|
||||
"scripts/skill_report_charts.py",
|
||||
"scripts/skill_report_layout.py",
|
||||
"scripts/skill_report_metrics.py",
|
||||
"scripts/skill_report_model.py",
|
||||
"scripts/sync_local_install.py",
|
||||
@@ -5287,7 +5298,8 @@
|
||||
"scripts/upgrade_check.py",
|
||||
"scripts/validate_skill.py",
|
||||
"scripts/verify_package.py",
|
||||
"scripts/yao.py"
|
||||
"scripts/yao.py",
|
||||
"scripts/yao_cli_config.py"
|
||||
],
|
||||
"assets": [
|
||||
"templates/basic_skill.md.j2",
|
||||
@@ -5338,7 +5350,7 @@
|
||||
],
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
}
|
||||
@@ -5576,7 +5588,7 @@
|
||||
"strategy": "Preserve references, scripts, assets, evals, reports, and adapter metadata as relative package resources.",
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
},
|
||||
@@ -5586,7 +5598,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"strategy": "Expose script and permission metadata for downstream clients or installers to enforce.",
|
||||
"script_count": 62,
|
||||
"script_count": 66,
|
||||
"help_smoke_failed_count": 0
|
||||
},
|
||||
"permissions": {
|
||||
@@ -5792,7 +5804,7 @@
|
||||
"strategy": "Preserve references, scripts, assets, evals, reports, and adapter metadata as relative package resources.",
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
},
|
||||
@@ -5802,7 +5814,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"strategy": "Expose script and permission metadata for downstream clients or installers to enforce.",
|
||||
"script_count": 62,
|
||||
"script_count": 66,
|
||||
"help_smoke_failed_count": 0
|
||||
},
|
||||
"permissions": {
|
||||
@@ -6041,6 +6053,8 @@
|
||||
"scripts/render_social_preview.py",
|
||||
"scripts/render_system_model.py",
|
||||
"scripts/resource_boundary_check.py",
|
||||
"scripts/review_studio_formatting.py",
|
||||
"scripts/review_studio_layout.py",
|
||||
"scripts/run_conformance_suite.py",
|
||||
"scripts/run_description_optimization_suite.py",
|
||||
"scripts/run_eval_suite.py",
|
||||
@@ -6048,6 +6062,7 @@
|
||||
"scripts/run_output_execution.py",
|
||||
"scripts/simulate_install.py",
|
||||
"scripts/skill_report_charts.py",
|
||||
"scripts/skill_report_layout.py",
|
||||
"scripts/skill_report_metrics.py",
|
||||
"scripts/skill_report_model.py",
|
||||
"scripts/sync_local_install.py",
|
||||
@@ -6056,7 +6071,8 @@
|
||||
"scripts/upgrade_check.py",
|
||||
"scripts/validate_skill.py",
|
||||
"scripts/verify_package.py",
|
||||
"scripts/yao.py"
|
||||
"scripts/yao.py",
|
||||
"scripts/yao_cli_config.py"
|
||||
],
|
||||
"assets": [
|
||||
"templates/basic_skill.md.j2",
|
||||
@@ -6107,7 +6123,7 @@
|
||||
],
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
}
|
||||
@@ -6345,7 +6361,7 @@
|
||||
"strategy": "Keep optional directories as relative resources next to SKILL.md.",
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
},
|
||||
@@ -6356,7 +6372,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"strategy": "Scripts remain local optional resources and should advertise --help when executable.",
|
||||
"script_count": 62,
|
||||
"script_count": 66,
|
||||
"help_smoke_failed_count": 0
|
||||
},
|
||||
"permissions": {
|
||||
@@ -6561,7 +6577,7 @@
|
||||
"strategy": "Keep optional directories as relative resources next to SKILL.md.",
|
||||
"counts": {
|
||||
"references": 32,
|
||||
"scripts": 62,
|
||||
"scripts": 66,
|
||||
"assets": 2,
|
||||
"reports": 41
|
||||
},
|
||||
@@ -6572,7 +6588,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"strategy": "Scripts remain local optional resources and should advertise --help when executable.",
|
||||
"script_count": 62,
|
||||
"script_count": 66,
|
||||
"help_smoke_failed_count": 0
|
||||
},
|
||||
"permissions": {
|
||||
@@ -7136,9 +7152,9 @@
|
||||
"ok": true,
|
||||
"skill_dir": ".",
|
||||
"summary": {
|
||||
"scanned_files": 146,
|
||||
"script_count": 62,
|
||||
"internal_module_count": 3,
|
||||
"scanned_files": 150,
|
||||
"script_count": 66,
|
||||
"internal_module_count": 7,
|
||||
"secret_findings": 0,
|
||||
"dependency_files": [
|
||||
"requirements-ci.txt"
|
||||
@@ -7156,8 +7172,8 @@
|
||||
"help_smoke_failed_count": 0,
|
||||
"interactive_script_count": 0,
|
||||
"package_hash_scope": "source-contract-without-generated-reports",
|
||||
"package_hash_file_count": 146,
|
||||
"package_sha256": "9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe"
|
||||
"package_hash_file_count": 150,
|
||||
"package_sha256": "742dc905b0d221c4f336e741d168861edaf7b75e97fe1e89f7d454c1cabf928f"
|
||||
},
|
||||
"failures": [],
|
||||
"warnings": [],
|
||||
@@ -7820,6 +7836,34 @@
|
||||
"network_urls": [],
|
||||
"network_hosts": []
|
||||
},
|
||||
{
|
||||
"path": "scripts/review_studio_formatting.py",
|
||||
"interface": "internal-module",
|
||||
"interface_declared": true,
|
||||
"interface_reason": "Imported by render_review_studio.py to format report dictionaries as audit UI panels.",
|
||||
"has_argparse": false,
|
||||
"has_main_guard": false,
|
||||
"uses_input": false,
|
||||
"uses_network": false,
|
||||
"uses_file_write": false,
|
||||
"uses_subprocess": false,
|
||||
"network_urls": [],
|
||||
"network_hosts": []
|
||||
},
|
||||
{
|
||||
"path": "scripts/review_studio_layout.py",
|
||||
"interface": "internal-module",
|
||||
"interface_declared": true,
|
||||
"interface_reason": "Imported by render_review_studio.py to keep Review Studio layout and CSS out of gate logic.",
|
||||
"has_argparse": false,
|
||||
"has_main_guard": false,
|
||||
"uses_input": false,
|
||||
"uses_network": false,
|
||||
"uses_file_write": false,
|
||||
"uses_subprocess": false,
|
||||
"network_urls": [],
|
||||
"network_hosts": []
|
||||
},
|
||||
{
|
||||
"path": "scripts/run_conformance_suite.py",
|
||||
"interface": "cli",
|
||||
@@ -7918,6 +7962,20 @@
|
||||
"network_urls": [],
|
||||
"network_hosts": []
|
||||
},
|
||||
{
|
||||
"path": "scripts/skill_report_layout.py",
|
||||
"interface": "internal-module",
|
||||
"interface_declared": true,
|
||||
"interface_reason": "Imported by render_skill_overview.py to keep overview report layout and CSS out of data rendering.",
|
||||
"has_argparse": false,
|
||||
"has_main_guard": false,
|
||||
"uses_input": false,
|
||||
"uses_network": false,
|
||||
"uses_file_write": false,
|
||||
"uses_subprocess": false,
|
||||
"network_urls": [],
|
||||
"network_hosts": []
|
||||
},
|
||||
{
|
||||
"path": "scripts/skill_report_metrics.py",
|
||||
"interface": "internal-module",
|
||||
@@ -8043,6 +8101,20 @@
|
||||
"uses_subprocess": true,
|
||||
"network_urls": [],
|
||||
"network_hosts": []
|
||||
},
|
||||
{
|
||||
"path": "scripts/yao_cli_config.py",
|
||||
"interface": "internal-module",
|
||||
"interface_declared": true,
|
||||
"interface_reason": "Imported by yao.py for CLI target maps and side-effect-free shaping helpers.",
|
||||
"has_argparse": false,
|
||||
"has_main_guard": false,
|
||||
"uses_input": false,
|
||||
"uses_network": false,
|
||||
"uses_file_write": false,
|
||||
"uses_subprocess": false,
|
||||
"network_urls": [],
|
||||
"network_hosts": []
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
@@ -8078,7 +8150,7 @@
|
||||
"checked_count": 59,
|
||||
"passed_count": 59,
|
||||
"failed_count": 0,
|
||||
"skipped_count": 3,
|
||||
"skipped_count": 7,
|
||||
"failed_scripts": [],
|
||||
"results": [
|
||||
{
|
||||
@@ -8673,10 +8745,22 @@
|
||||
}
|
||||
],
|
||||
"skipped": [
|
||||
{
|
||||
"path": "scripts/review_studio_formatting.py",
|
||||
"reason": "internal module"
|
||||
},
|
||||
{
|
||||
"path": "scripts/review_studio_layout.py",
|
||||
"reason": "internal module"
|
||||
},
|
||||
{
|
||||
"path": "scripts/skill_report_charts.py",
|
||||
"reason": "internal module"
|
||||
},
|
||||
{
|
||||
"path": "scripts/skill_report_layout.py",
|
||||
"reason": "internal module"
|
||||
},
|
||||
{
|
||||
"path": "scripts/skill_report_metrics.py",
|
||||
"reason": "internal module"
|
||||
@@ -8684,6 +8768,10 @@
|
||||
{
|
||||
"path": "scripts/skill_report_model.py",
|
||||
"reason": "internal module"
|
||||
},
|
||||
{
|
||||
"path": "scripts/yao_cli_config.py",
|
||||
"reason": "internal module"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -8848,10 +8936,10 @@
|
||||
"context_budget_tier": "production",
|
||||
"context_budget_limit": 1000,
|
||||
"skill_body_tokens": 811,
|
||||
"other_text_tokens": 864534,
|
||||
"other_text_tokens": 869504,
|
||||
"estimated_initial_load_tokens": 987,
|
||||
"estimated_total_text_tokens": 865345,
|
||||
"relevant_file_count": 316,
|
||||
"estimated_total_text_tokens": 870315,
|
||||
"relevant_file_count": 327,
|
||||
"unused_resource_dirs": [],
|
||||
"quality_signal_points": 130,
|
||||
"quality_density": 131.7
|
||||
@@ -9757,6 +9845,8 @@
|
||||
"scripts/render_social_preview.py",
|
||||
"scripts/render_system_model.py",
|
||||
"scripts/resource_boundary_check.py",
|
||||
"scripts/review_studio_formatting.py",
|
||||
"scripts/review_studio_layout.py",
|
||||
"scripts/run_conformance_suite.py",
|
||||
"scripts/run_description_optimization_suite.py",
|
||||
"scripts/run_eval_suite.py",
|
||||
@@ -9764,6 +9854,7 @@
|
||||
"scripts/run_output_execution.py",
|
||||
"scripts/simulate_install.py",
|
||||
"scripts/skill_report_charts.py",
|
||||
"scripts/skill_report_layout.py",
|
||||
"scripts/skill_report_metrics.py",
|
||||
"scripts/skill_report_model.py",
|
||||
"scripts/sync_local_install.py",
|
||||
@@ -9773,6 +9864,7 @@
|
||||
"scripts/validate_skill.py",
|
||||
"scripts/verify_package.py",
|
||||
"scripts/yao.py",
|
||||
"scripts/yao_cli_config.py",
|
||||
"references/artifact-design-doctrine.md",
|
||||
"references/authoring-discipline.md",
|
||||
"references/distribution-registry-method.md",
|
||||
@@ -10554,7 +10646,7 @@
|
||||
"adoption_drift": {
|
||||
"ok": true,
|
||||
"schema_version": "2.0",
|
||||
"generated_at": "2026-06-13T09:57:51Z",
|
||||
"generated_at": "2026-06-13T10:57:52Z",
|
||||
"skill_dir": ".",
|
||||
"privacy_contract": {
|
||||
"storage": "local-first",
|
||||
@@ -10713,8 +10805,8 @@
|
||||
"trust_level": "local",
|
||||
"license": "MIT",
|
||||
"checksums": {
|
||||
"package_sha256": "9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe",
|
||||
"archive_sha256": "4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06"
|
||||
"package_sha256": "742dc905b0d221c4f336e741d168861edaf7b75e97fe1e89f7d454c1cabf928f",
|
||||
"archive_sha256": "7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9"
|
||||
},
|
||||
"compatibility": {
|
||||
"openai": "pass",
|
||||
@@ -10745,7 +10837,7 @@
|
||||
},
|
||||
"distribution": {
|
||||
"archive_verified": true,
|
||||
"archive_sha256": "4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06",
|
||||
"archive_sha256": "7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9",
|
||||
"package_verification": "reports/package_verification.json",
|
||||
"install_simulated": true,
|
||||
"install_simulation": "reports/install_simulation.json"
|
||||
@@ -10769,7 +10861,7 @@
|
||||
"agent-skills-compatible"
|
||||
],
|
||||
"package_metadata": "registry/packages/yao-meta-skill.json",
|
||||
"package_sha256": "9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe"
|
||||
"package_sha256": "742dc905b0d221c4f336e741d168861edaf7b75e97fe1e89f7d454c1cabf928f"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -10792,8 +10884,8 @@
|
||||
"target_count": 3,
|
||||
"adapter_count": 3,
|
||||
"archive_present": true,
|
||||
"archive_sha256": "4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06",
|
||||
"archive_entry_count": 483,
|
||||
"archive_sha256": "7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9",
|
||||
"archive_entry_count": 488,
|
||||
"failure_count": 0,
|
||||
"warning_count": 0
|
||||
},
|
||||
@@ -11308,7 +11400,7 @@
|
||||
"installed_skill_dir": "dist/install-simulation/simulate-yao-meta-skill/yao-meta-skill",
|
||||
"summary": {
|
||||
"archive_present": true,
|
||||
"archive_entry_count": 483,
|
||||
"archive_entry_count": 488,
|
||||
"archive_extracted": true,
|
||||
"entrypoint_loaded": true,
|
||||
"manifest_loaded": true,
|
||||
@@ -11489,12 +11581,12 @@
|
||||
{
|
||||
"field": "archive_sha256",
|
||||
"from": "",
|
||||
"to": "4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06"
|
||||
"to": "7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9"
|
||||
},
|
||||
{
|
||||
"field": "package_sha256",
|
||||
"from": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"to": "9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe"
|
||||
"to": "742dc905b0d221c4f336e741d168861edaf7b75e97fe1e89f7d454c1cabf928f"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
"ok": true,
|
||||
"skill_dir": ".",
|
||||
"summary": {
|
||||
"scanned_files": 146,
|
||||
"script_count": 62,
|
||||
"internal_module_count": 3,
|
||||
"scanned_files": 150,
|
||||
"script_count": 66,
|
||||
"internal_module_count": 7,
|
||||
"secret_findings": 0,
|
||||
"dependency_files": [
|
||||
"requirements-ci.txt"
|
||||
@@ -22,8 +22,8 @@
|
||||
"help_smoke_failed_count": 0,
|
||||
"interactive_script_count": 0,
|
||||
"package_hash_scope": "source-contract-without-generated-reports",
|
||||
"package_hash_file_count": 146,
|
||||
"package_sha256": "9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe"
|
||||
"package_hash_file_count": 150,
|
||||
"package_sha256": "742dc905b0d221c4f336e741d168861edaf7b75e97fe1e89f7d454c1cabf928f"
|
||||
},
|
||||
"failures": [],
|
||||
"warnings": [],
|
||||
@@ -686,6 +686,34 @@
|
||||
"network_urls": [],
|
||||
"network_hosts": []
|
||||
},
|
||||
{
|
||||
"path": "scripts/review_studio_formatting.py",
|
||||
"interface": "internal-module",
|
||||
"interface_declared": true,
|
||||
"interface_reason": "Imported by render_review_studio.py to format report dictionaries as audit UI panels.",
|
||||
"has_argparse": false,
|
||||
"has_main_guard": false,
|
||||
"uses_input": false,
|
||||
"uses_network": false,
|
||||
"uses_file_write": false,
|
||||
"uses_subprocess": false,
|
||||
"network_urls": [],
|
||||
"network_hosts": []
|
||||
},
|
||||
{
|
||||
"path": "scripts/review_studio_layout.py",
|
||||
"interface": "internal-module",
|
||||
"interface_declared": true,
|
||||
"interface_reason": "Imported by render_review_studio.py to keep Review Studio layout and CSS out of gate logic.",
|
||||
"has_argparse": false,
|
||||
"has_main_guard": false,
|
||||
"uses_input": false,
|
||||
"uses_network": false,
|
||||
"uses_file_write": false,
|
||||
"uses_subprocess": false,
|
||||
"network_urls": [],
|
||||
"network_hosts": []
|
||||
},
|
||||
{
|
||||
"path": "scripts/run_conformance_suite.py",
|
||||
"interface": "cli",
|
||||
@@ -784,6 +812,20 @@
|
||||
"network_urls": [],
|
||||
"network_hosts": []
|
||||
},
|
||||
{
|
||||
"path": "scripts/skill_report_layout.py",
|
||||
"interface": "internal-module",
|
||||
"interface_declared": true,
|
||||
"interface_reason": "Imported by render_skill_overview.py to keep overview report layout and CSS out of data rendering.",
|
||||
"has_argparse": false,
|
||||
"has_main_guard": false,
|
||||
"uses_input": false,
|
||||
"uses_network": false,
|
||||
"uses_file_write": false,
|
||||
"uses_subprocess": false,
|
||||
"network_urls": [],
|
||||
"network_hosts": []
|
||||
},
|
||||
{
|
||||
"path": "scripts/skill_report_metrics.py",
|
||||
"interface": "internal-module",
|
||||
@@ -909,6 +951,20 @@
|
||||
"uses_subprocess": true,
|
||||
"network_urls": [],
|
||||
"network_hosts": []
|
||||
},
|
||||
{
|
||||
"path": "scripts/yao_cli_config.py",
|
||||
"interface": "internal-module",
|
||||
"interface_declared": true,
|
||||
"interface_reason": "Imported by yao.py for CLI target maps and side-effect-free shaping helpers.",
|
||||
"has_argparse": false,
|
||||
"has_main_guard": false,
|
||||
"uses_input": false,
|
||||
"uses_network": false,
|
||||
"uses_file_write": false,
|
||||
"uses_subprocess": false,
|
||||
"network_urls": [],
|
||||
"network_hosts": []
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
@@ -944,7 +1000,7 @@
|
||||
"checked_count": 59,
|
||||
"passed_count": 59,
|
||||
"failed_count": 0,
|
||||
"skipped_count": 3,
|
||||
"skipped_count": 7,
|
||||
"failed_scripts": [],
|
||||
"results": [
|
||||
{
|
||||
@@ -1539,10 +1595,22 @@
|
||||
}
|
||||
],
|
||||
"skipped": [
|
||||
{
|
||||
"path": "scripts/review_studio_formatting.py",
|
||||
"reason": "internal module"
|
||||
},
|
||||
{
|
||||
"path": "scripts/review_studio_layout.py",
|
||||
"reason": "internal module"
|
||||
},
|
||||
{
|
||||
"path": "scripts/skill_report_charts.py",
|
||||
"reason": "internal module"
|
||||
},
|
||||
{
|
||||
"path": "scripts/skill_report_layout.py",
|
||||
"reason": "internal module"
|
||||
},
|
||||
{
|
||||
"path": "scripts/skill_report_metrics.py",
|
||||
"reason": "internal module"
|
||||
@@ -1550,6 +1618,10 @@
|
||||
{
|
||||
"path": "scripts/skill_report_model.py",
|
||||
"reason": "internal module"
|
||||
},
|
||||
{
|
||||
"path": "scripts/yao_cli_config.py",
|
||||
"reason": "internal module"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# Security Trust Report
|
||||
|
||||
- OK: `True`
|
||||
- Scanned files: `146`
|
||||
- Scripts: `62`
|
||||
- Internal script modules: `3`
|
||||
- Scanned files: `150`
|
||||
- Scripts: `66`
|
||||
- Internal script modules: `7`
|
||||
- Secret findings: `0`
|
||||
- Network-capable scripts: `2`
|
||||
- Network policy covered scripts: `2`
|
||||
@@ -15,8 +15,8 @@
|
||||
- CLI help smoke failures: `0`
|
||||
- Interactive scripts: `0`
|
||||
- Package hash scope: `source-contract-without-generated-reports`
|
||||
- Package hash files: `146`
|
||||
- Package SHA256: `9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe`
|
||||
- Package hash files: `150`
|
||||
- Package SHA256: `742dc905b0d221c4f336e741d168861edaf7b75e97fe1e89f7d454c1cabf928f`
|
||||
|
||||
## Failures
|
||||
|
||||
@@ -108,6 +108,8 @@
|
||||
| scripts/render_social_preview.py | cli | False | True | True | False | False | True | False | Default CLI classification; add SCRIPT_INTERFACE for internal modules. |
|
||||
| scripts/render_system_model.py | cli | False | True | True | False | False | True | False | Default CLI classification; add SCRIPT_INTERFACE for internal modules. |
|
||||
| scripts/resource_boundary_check.py | cli | False | True | True | False | False | False | False | Default CLI classification; add SCRIPT_INTERFACE for internal modules. |
|
||||
| scripts/review_studio_formatting.py | internal-module | True | False | False | False | False | False | False | Imported by render_review_studio.py to format report dictionaries as audit UI panels. |
|
||||
| scripts/review_studio_layout.py | internal-module | True | False | False | False | False | False | False | Imported by render_review_studio.py to keep Review Studio layout and CSS out of gate logic. |
|
||||
| scripts/run_conformance_suite.py | cli | False | True | True | False | False | True | False | Default CLI classification; add SCRIPT_INTERFACE for internal modules. |
|
||||
| scripts/run_description_optimization_suite.py | cli | False | True | True | False | False | True | False | Default CLI classification; add SCRIPT_INTERFACE for internal modules. |
|
||||
| scripts/run_eval_suite.py | cli | False | True | True | False | False | False | True | Default CLI classification; add SCRIPT_INTERFACE for internal modules. |
|
||||
@@ -115,6 +117,7 @@
|
||||
| scripts/run_output_execution.py | cli | False | True | True | False | False | True | True | Default CLI classification; add SCRIPT_INTERFACE for internal modules. |
|
||||
| scripts/simulate_install.py | cli | False | True | True | False | False | True | False | Default CLI classification; add SCRIPT_INTERFACE for internal modules. |
|
||||
| scripts/skill_report_charts.py | internal-module | True | False | False | False | False | False | False | Imported by render_skill_overview.py to render inline SVG report charts. |
|
||||
| scripts/skill_report_layout.py | internal-module | True | False | False | False | False | False | False | Imported by render_skill_overview.py to keep overview report layout and CSS out of data rendering. |
|
||||
| scripts/skill_report_metrics.py | internal-module | True | False | False | False | False | False | False | Imported by skill_report_model.py to calculate overview report metrics. |
|
||||
| scripts/skill_report_model.py | internal-module | True | False | False | False | False | False | False | Imported by render_skill_overview.py to build the v2 report data model. |
|
||||
| scripts/sync_local_install.py | cli | False | True | True | False | False | True | True | Default CLI classification; add SCRIPT_INTERFACE for internal modules. |
|
||||
@@ -124,3 +127,4 @@
|
||||
| scripts/validate_skill.py | cli | False | True | True | False | False | False | False | Default CLI classification; add SCRIPT_INTERFACE for internal modules. |
|
||||
| scripts/verify_package.py | cli | False | True | True | False | False | True | False | Default CLI classification; add SCRIPT_INTERFACE for internal modules. |
|
||||
| scripts/yao.py | cli | False | True | True | False | False | False | True | Default CLI classification; add SCRIPT_INTERFACE for internal modules. |
|
||||
| scripts/yao_cli_config.py | internal-module | True | False | False | False | False | False | False | Imported by yao.py for CLI target maps and side-effect-free shaping helpers. |
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>yao-meta-skill Skill 生成审计报告</title>
|
||||
<style>
|
||||
:root {
|
||||
:root {
|
||||
--paper: #ffffff;
|
||||
--wash: #f8fafc;
|
||||
--wash-strong: #f2f5f8;
|
||||
@@ -771,7 +771,7 @@
|
||||
<p><span data-lang="zh-CN">让 reviewer 快速确认关键文件、目录和资产分布。</span><span data-lang="en">Lets reviewers confirm key files, directories, and asset distribution quickly.</span></p>
|
||||
</div>
|
||||
<div class="two-col">
|
||||
<figure class="chart-figure" data-chart="asset_donut"><svg viewBox="0 0 430 270" role="img" aria-label="资产分布"><text x="20" y="30" class="chart-title">资产分布</text><circle cx="130" cy="130" r="70" fill="none" stroke="#1B365D" stroke-width="24" stroke-dasharray="1.0 99.0" stroke-dashoffset="0.0" pathLength="100" transform="rotate(-90 130 130)"/><circle cx="130" cy="130" r="70" fill="none" stroke="#2D5A8A" stroke-width="24" stroke-dasharray="1.0 99.0" stroke-dashoffset="-1.0" pathLength="100" transform="rotate(-90 130 130)"/><circle cx="130" cy="130" r="70" fill="none" stroke="#D0DCE9" stroke-width="24" stroke-dasharray="1.0 99.0" stroke-dashoffset="-2.0" pathLength="100" transform="rotate(-90 130 130)"/><circle cx="130" cy="130" r="70" fill="none" stroke="#E4ECF5" stroke-width="24" stroke-dasharray="1.0 99.0" stroke-dashoffset="-3.1" pathLength="100" transform="rotate(-90 130 130)"/><circle cx="130" cy="130" r="70" fill="none" stroke="#e8e6dc" stroke-width="24" stroke-dasharray="32.7 67.3" stroke-dashoffset="-4.1" pathLength="100" transform="rotate(-90 130 130)"/><circle cx="130" cy="130" r="70" fill="none" stroke="#504e49" stroke-width="24" stroke-dasharray="63.3 36.7" stroke-dashoffset="-36.7" pathLength="100" transform="rotate(-90 130 130)"/><text x="130" y="136" text-anchor="middle">296项</text><text x="235" y="78">SKILL.md</text><text x="235" y="100">README.md</text><text x="235" y="122">agents/interface.yaml</text><text x="235" y="144">manifest.json</text><text x="235" y="166">references</text><text x="235" y="188">scripts</text></svg><figcaption>资产分布图展示当前包体的文件和目录重心。</figcaption></figure>
|
||||
<figure class="chart-figure" data-chart="asset_donut"><svg viewBox="0 0 430 270" role="img" aria-label="资产分布"><text x="20" y="30" class="chart-title">资产分布</text><circle cx="130" cy="130" r="70" fill="none" stroke="#1B365D" stroke-width="24" stroke-dasharray="1.0 99.0" stroke-dashoffset="0.0" pathLength="100" transform="rotate(-90 130 130)"/><circle cx="130" cy="130" r="70" fill="none" stroke="#2D5A8A" stroke-width="24" stroke-dasharray="1.0 99.0" stroke-dashoffset="-1.0" pathLength="100" transform="rotate(-90 130 130)"/><circle cx="130" cy="130" r="70" fill="none" stroke="#D0DCE9" stroke-width="24" stroke-dasharray="1.0 99.0" stroke-dashoffset="-2.0" pathLength="100" transform="rotate(-90 130 130)"/><circle cx="130" cy="130" r="70" fill="none" stroke="#E4ECF5" stroke-width="24" stroke-dasharray="1.0 99.0" stroke-dashoffset="-2.9" pathLength="100" transform="rotate(-90 130 130)"/><circle cx="130" cy="130" r="70" fill="none" stroke="#e8e6dc" stroke-width="24" stroke-dasharray="31.4 68.6" stroke-dashoffset="-3.9" pathLength="100" transform="rotate(-90 130 130)"/><circle cx="130" cy="130" r="70" fill="none" stroke="#504e49" stroke-width="24" stroke-dasharray="64.7 35.3" stroke-dashoffset="-35.3" pathLength="100" transform="rotate(-90 130 130)"/><text x="130" y="136" text-anchor="middle">300项</text><text x="235" y="78">SKILL.md</text><text x="235" y="100">README.md</text><text x="235" y="122">agents/interface.yaml</text><text x="235" y="144">manifest.json</text><text x="235" y="166">references</text><text x="235" y="188">scripts</text></svg><figcaption>资产分布图展示当前包体的文件和目录重心。</figcaption></figure>
|
||||
<table>
|
||||
<thead><tr><th><span data-lang="zh-CN">路径</span><span data-lang="en">Path</span></th><th><span data-lang="zh-CN">作用</span><span data-lang="en">Role</span></th><th><span data-lang="zh-CN">类型</span><span data-lang="en">Type</span></th></tr></thead>
|
||||
<tbody><tr><td>SKILL.md</td><td><span data-lang="zh-CN">Skill 入口文件</span><span data-lang="en">Skill entrypoint</span></td><td><span data-lang="zh-CN">文件</span><span data-lang="en">file</span></td></tr><tr><td>README.md</td><td><span data-lang="zh-CN">人类可读使用说明</span><span data-lang="en">Human-readable usage guide</span></td><td><span data-lang="zh-CN">文件</span><span data-lang="en">file</span></td></tr><tr><td>agents/interface.yaml</td><td><span data-lang="zh-CN">跨平台接口元数据</span><span data-lang="en">Neutral interface metadata</span></td><td><span data-lang="zh-CN">文件</span><span data-lang="en">file</span></td></tr><tr><td>manifest.json</td><td><span data-lang="zh-CN">生命周期与打包元数据</span><span data-lang="en">Lifecycle and portability metadata</span></td><td><span data-lang="zh-CN">文件</span><span data-lang="en">file</span></td></tr><tr><td>references</td><td><span data-lang="zh-CN">扩展指导与复用资料</span><span data-lang="en">Extended guidance and reusable notes</span></td><td><span data-lang="zh-CN">目录</span><span data-lang="en">folder</span></td></tr><tr><td>scripts</td><td><span data-lang="zh-CN">确定性脚本或本地工具</span><span data-lang="en">Deterministic helpers or local tooling</span></td><td><span data-lang="zh-CN">目录</span><span data-lang="en">folder</span></td></tr><tr><td>evals</td><td><span data-lang="zh-CN">触发与质量检查</span><span data-lang="en">Trigger and quality checks</span></td><td><span data-lang="zh-CN">目录</span><span data-lang="en">folder</span></td></tr><tr><td>reports</td><td><span data-lang="zh-CN">生成的证据与总结报告</span><span data-lang="en">Generated evidence and overview artifacts</span></td><td><span data-lang="zh-CN">目录</span><span data-lang="en">folder</span></td></tr></tbody>
|
||||
@@ -794,7 +794,7 @@
|
||||
</section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {
|
||||
(function () {
|
||||
var buttons = Array.prototype.slice.call(document.querySelectorAll("[data-set-lang]"));
|
||||
var navLinks = Array.prototype.slice.call(document.querySelectorAll(".report-nav a"));
|
||||
var sections = navLinks
|
||||
|
||||
+17
-17
@@ -433,7 +433,7 @@
|
||||
"path": "scripts",
|
||||
"label": "Deterministic helpers or local tooling",
|
||||
"kind": "folder",
|
||||
"file_count": 62
|
||||
"file_count": 66
|
||||
},
|
||||
{
|
||||
"path": "evals",
|
||||
@@ -448,7 +448,7 @@
|
||||
"file_count": 170
|
||||
}
|
||||
],
|
||||
"file_count": 296,
|
||||
"file_count": 300,
|
||||
"folder_count": 4,
|
||||
"distribution": [
|
||||
{
|
||||
@@ -473,7 +473,7 @@
|
||||
},
|
||||
{
|
||||
"label": "scripts",
|
||||
"value": 62
|
||||
"value": 66
|
||||
},
|
||||
{
|
||||
"label": "evals",
|
||||
@@ -602,7 +602,7 @@
|
||||
"path": "scripts",
|
||||
"label": "Deterministic helpers or local tooling",
|
||||
"kind": "folder",
|
||||
"file_count": 62
|
||||
"file_count": 66
|
||||
},
|
||||
{
|
||||
"path": "evals",
|
||||
@@ -920,9 +920,9 @@
|
||||
"failures": []
|
||||
},
|
||||
"trust_security": {
|
||||
"scanned_files": 146,
|
||||
"script_count": 62,
|
||||
"internal_module_count": 3,
|
||||
"scanned_files": 150,
|
||||
"script_count": 66,
|
||||
"internal_module_count": 7,
|
||||
"secret_findings": 0,
|
||||
"dependency_files": [
|
||||
"requirements-ci.txt"
|
||||
@@ -940,8 +940,8 @@
|
||||
"help_smoke_failed_count": 0,
|
||||
"interactive_script_count": 0,
|
||||
"package_hash_scope": "source-contract-without-generated-reports",
|
||||
"package_hash_file_count": 146,
|
||||
"package_sha256": "9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe"
|
||||
"package_hash_file_count": 150,
|
||||
"package_sha256": "742dc905b0d221c4f336e741d168861edaf7b75e97fe1e89f7d454c1cabf928f"
|
||||
},
|
||||
"skill_atlas": {
|
||||
"skill_count": 12,
|
||||
@@ -975,8 +975,8 @@
|
||||
"trust_level": "local",
|
||||
"license": "MIT",
|
||||
"checksums": {
|
||||
"package_sha256": "9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe",
|
||||
"archive_sha256": "4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06"
|
||||
"package_sha256": "742dc905b0d221c4f336e741d168861edaf7b75e97fe1e89f7d454c1cabf928f",
|
||||
"archive_sha256": "7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9"
|
||||
},
|
||||
"compatibility": {
|
||||
"openai": "pass",
|
||||
@@ -1007,7 +1007,7 @@
|
||||
},
|
||||
"distribution": {
|
||||
"archive_verified": true,
|
||||
"archive_sha256": "4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06",
|
||||
"archive_sha256": "7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9",
|
||||
"package_verification": "reports/package_verification.json",
|
||||
"install_simulated": true,
|
||||
"install_simulation": "reports/install_simulation.json"
|
||||
@@ -1023,8 +1023,8 @@
|
||||
"target_count": 3,
|
||||
"adapter_count": 3,
|
||||
"archive_present": true,
|
||||
"archive_sha256": "4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06",
|
||||
"archive_entry_count": 483,
|
||||
"archive_sha256": "7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9",
|
||||
"archive_entry_count": 488,
|
||||
"failure_count": 0,
|
||||
"warning_count": 0
|
||||
},
|
||||
@@ -1035,7 +1035,7 @@
|
||||
"ok": true,
|
||||
"summary": {
|
||||
"archive_present": true,
|
||||
"archive_entry_count": 483,
|
||||
"archive_entry_count": 488,
|
||||
"archive_extracted": true,
|
||||
"entrypoint_loaded": true,
|
||||
"manifest_loaded": true,
|
||||
@@ -1097,12 +1097,12 @@
|
||||
{
|
||||
"field": "archive_sha256",
|
||||
"from": "",
|
||||
"to": "4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06"
|
||||
"to": "7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9"
|
||||
},
|
||||
{
|
||||
"field": "package_sha256",
|
||||
"from": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"to": "9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe"
|
||||
"to": "742dc905b0d221c4f336e741d168861edaf7b75e97fe1e89f7d454c1cabf928f"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -106,6 +106,8 @@
|
||||
"scripts/render_social_preview.py",
|
||||
"scripts/render_system_model.py",
|
||||
"scripts/resource_boundary_check.py",
|
||||
"scripts/review_studio_formatting.py",
|
||||
"scripts/review_studio_layout.py",
|
||||
"scripts/run_conformance_suite.py",
|
||||
"scripts/run_description_optimization_suite.py",
|
||||
"scripts/run_eval_suite.py",
|
||||
@@ -113,6 +115,7 @@
|
||||
"scripts/run_output_execution.py",
|
||||
"scripts/simulate_install.py",
|
||||
"scripts/skill_report_charts.py",
|
||||
"scripts/skill_report_layout.py",
|
||||
"scripts/skill_report_metrics.py",
|
||||
"scripts/skill_report_model.py",
|
||||
"scripts/sync_local_install.py",
|
||||
@@ -122,6 +125,7 @@
|
||||
"scripts/validate_skill.py",
|
||||
"scripts/verify_package.py",
|
||||
"scripts/yao.py",
|
||||
"scripts/yao_cli_config.py",
|
||||
"references/artifact-design-doctrine.md",
|
||||
"references/authoring-discipline.md",
|
||||
"references/distribution-registry-method.md",
|
||||
|
||||
@@ -68,12 +68,12 @@
|
||||
{
|
||||
"field": "archive_sha256",
|
||||
"from": "",
|
||||
"to": "4d1227dc0996a97aa4987761d46081391fe15b36362e19765e1e7aa8e5d41c06"
|
||||
"to": "7bc83805501d24cf8e5932ef76e0454100398d5a73652e7440be47984d0cf4a9"
|
||||
},
|
||||
{
|
||||
"field": "package_sha256",
|
||||
"from": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"to": "9f1d53dbaeb1c90c80d7ffbbc1d10473e50b8032acda68332fbae551bb246abe"
|
||||
"to": "742dc905b0d221c4f336e741d168861edaf7b75e97fe1e89f7d454c1cabf928f"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
+107
-229
@@ -18,6 +18,9 @@ except ImportError: # pragma: no cover
|
||||
compute_permission_governance_status = None
|
||||
trust_script_inventory = None
|
||||
|
||||
from review_studio_formatting import registry_package_summary, render_kv_grid
|
||||
from review_studio_layout import render_review_nav, review_studio_css
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
|
||||
@@ -1076,24 +1079,7 @@ def render_html(report: dict[str, Any]) -> str:
|
||||
frontmatter = report["data"]["frontmatter"]
|
||||
title = overview.get("display_name") or overview.get("title") or frontmatter.get("name") or manifest.get("name") or "Skill"
|
||||
description = overview.get("description") or frontmatter.get("description", "")
|
||||
nav = [
|
||||
("#overview", "审查总览"),
|
||||
("#intent", "意图画布"),
|
||||
("#trigger", "触发实验"),
|
||||
("#output", "输出实验"),
|
||||
("#actions", "修复动作"),
|
||||
("#annotations", "审查批注"),
|
||||
("#runtime", "运行矩阵"),
|
||||
("#trust", "信任报告"),
|
||||
("#permissions", "权限批准"),
|
||||
("#permission-probes", "权限探针"),
|
||||
("#atlas", "组合治理"),
|
||||
("#telemetry", "运营回路"),
|
||||
("#waivers", "人工批准"),
|
||||
("#registry", "注册审计"),
|
||||
("#release", "发布路线"),
|
||||
]
|
||||
nav_html = "".join(f"<a href='{href}'>{label}</a>" for href, label in nav)
|
||||
nav_html = render_review_nav()
|
||||
gates_html = render_gate_list(gates)
|
||||
metrics_html = render_insights(insights)
|
||||
blockers_html = render_issue_list("阻断事项", blockers)
|
||||
@@ -1119,6 +1105,95 @@ def render_html(report: dict[str, Any]) -> str:
|
||||
)
|
||||
registry_package = report["data"]["registry"].get("package", {})
|
||||
package_summary = report["data"]["package_verification"].get("summary", {})
|
||||
atlas_panel = render_kv_grid(
|
||||
atlas_summary,
|
||||
[
|
||||
"skill_count",
|
||||
"actionable_skill_count",
|
||||
"actionable_route_collision_count",
|
||||
"actionable_owner_gap_count",
|
||||
"actionable_stale_count",
|
||||
"non_actionable_issue_count",
|
||||
],
|
||||
"skill atlas summary missing",
|
||||
)
|
||||
output_panel = render_kv_grid(
|
||||
output_summary,
|
||||
["case_count", "with_skill_pass_rate", "baseline_pass_rate", "delta", "gate_pass", "failure_count"],
|
||||
"output eval scorecard missing",
|
||||
)
|
||||
execution_panel = render_kv_grid(
|
||||
output_execution_summary,
|
||||
[
|
||||
"variant_run_count",
|
||||
"command_executed_count",
|
||||
"model_executed_count",
|
||||
"recorded_fixture_count",
|
||||
"timing_observed_count",
|
||||
"token_estimated_count",
|
||||
],
|
||||
"output execution report missing",
|
||||
)
|
||||
blind_panel = render_kv_grid(
|
||||
output_blind_summary,
|
||||
["pair_count", "answer_key_separate", "with_skill_hidden_count"],
|
||||
"blind A/B review pack missing",
|
||||
)
|
||||
review_panel = render_kv_grid(
|
||||
output_review_summary,
|
||||
["pair_count", "judgment_count", "pending_count", "agreement_count", "disagreement_count", "invalid_decision_count"],
|
||||
"review adjudication report missing",
|
||||
)
|
||||
conformance_panel = render_kv_grid(
|
||||
conformance_summary,
|
||||
["target_count", "pass_count", "fail_count", "warning_count", "failure_count"],
|
||||
"runtime conformance matrix missing",
|
||||
)
|
||||
compiled_panel = render_kv_grid(
|
||||
compiled_summary,
|
||||
["target_count", "pass_count", "warn_count", "block_count", "failure_count"],
|
||||
"compiled target report missing",
|
||||
)
|
||||
trust_panel = render_kv_grid(
|
||||
trust_summary,
|
||||
["secret_findings", "script_count", "network_script_count", "help_smoke_failed_count", "package_sha256"],
|
||||
"security trust report missing",
|
||||
)
|
||||
runtime_boundary_panel = render_kv_grid(
|
||||
runtime_permissions_summary,
|
||||
["target_count", "pass_count", "native_enforcement_count", "metadata_fallback_count", "residual_risk_count", "failure_count"],
|
||||
"runtime permission probe summary missing",
|
||||
)
|
||||
adoption_panel = render_kv_grid(
|
||||
adoption_summary,
|
||||
["event_count", "adoption_rate", "missed_trigger_count", "bad_output_count", "risk_band"],
|
||||
"no adoption drift summary",
|
||||
)
|
||||
waiver_panel = render_kv_grid(
|
||||
waiver_summary,
|
||||
["waiver_count", "active_count", "expired_count", "invalid_count", "covered_gate_count"],
|
||||
"no review waiver summary",
|
||||
)
|
||||
registry_panel = render_kv_grid(
|
||||
registry_package_summary(registry_package),
|
||||
[
|
||||
"name",
|
||||
"version",
|
||||
"maturity",
|
||||
"owner",
|
||||
"license",
|
||||
"trust_level",
|
||||
"targets",
|
||||
"compatibility_pass_count",
|
||||
"archive_sha256",
|
||||
],
|
||||
"registry package metadata missing",
|
||||
)
|
||||
package_panel = render_kv_grid(
|
||||
package_summary,
|
||||
["target_count", "adapter_count", "archive_present", "archive_entry_count", "failure_count", "warning_count", "archive_sha256"],
|
||||
"package verification missing",
|
||||
)
|
||||
evidence_html = "".join(
|
||||
f"<li><strong>{html.escape(key)}</strong><span>{html.escape(value)}</span></li>"
|
||||
for key, value in report["evidence_paths"].items()
|
||||
@@ -1130,204 +1205,7 @@ def render_html(report: dict[str, Any]) -> str:
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{html.escape(str(title))} Review Studio 2.0</title>
|
||||
<style>
|
||||
:root {{
|
||||
--ink: #1B365D;
|
||||
--text: #24201d;
|
||||
--muted: #746d66;
|
||||
--line: #e7ded2;
|
||||
--soft: #faf8f5;
|
||||
--pass: #1e6b52;
|
||||
--warn: #9a6718;
|
||||
--block: #9b2c2c;
|
||||
}}
|
||||
* {{ box-sizing: border-box; }}
|
||||
html {{ scroll-behavior: smooth; }}
|
||||
body {{
|
||||
margin: 0;
|
||||
background: #ffffff;
|
||||
color: var(--text);
|
||||
font-family: Georgia, "Times New Roman", "Songti SC", serif;
|
||||
line-height: 1.58;
|
||||
}}
|
||||
nav {{
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
padding: 10px 16px;
|
||||
background: rgba(255,255,255,0.94);
|
||||
border-bottom: 1px solid var(--line);
|
||||
backdrop-filter: blur(10px);
|
||||
}}
|
||||
nav a {{
|
||||
color: var(--ink);
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
padding: 7px 10px;
|
||||
border-radius: 6px;
|
||||
}}
|
||||
nav a:hover {{ background: var(--soft); }}
|
||||
main {{ max-width: 1180px; margin: 0 auto; padding: 44px 28px 76px; }}
|
||||
header {{ border-bottom: 1px solid var(--line); padding-bottom: 28px; margin-bottom: 28px; }}
|
||||
.eyebrow {{ color: var(--ink); font-size: 14px; letter-spacing: .08em; text-transform: uppercase; }}
|
||||
h1, h2, h3 {{ color: var(--text); font-weight: 500; margin: 0; letter-spacing: 0; }}
|
||||
h1 {{ font-size: clamp(34px, 5vw, 64px); line-height: 1.03; max-width: 920px; margin-top: 12px; }}
|
||||
h2 {{ font-size: 30px; margin-bottom: 14px; }}
|
||||
h3 {{ font-size: 19px; }}
|
||||
p {{ margin: 0; }}
|
||||
.lede {{ max-width: 820px; color: var(--muted); font-size: 20px; margin-top: 18px; }}
|
||||
.decision {{
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
gap: 12px;
|
||||
margin-top: 24px;
|
||||
padding: 12px 16px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
color: var(--ink);
|
||||
background: var(--soft);
|
||||
}}
|
||||
.decision strong {{ font-size: 28px; }}
|
||||
section {{ padding: 30px 0; border-bottom: 1px solid var(--line); scroll-margin-top: 76px; }}
|
||||
.metrics, .gates {{
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||
gap: 14px;
|
||||
}}
|
||||
.gates {{ grid-template-columns: repeat(4, minmax(0, 1fr)); }}
|
||||
.metric, .gate {{
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
min-width: 0;
|
||||
}}
|
||||
.metric span, .gate span {{ display: block; color: var(--muted); font-size: 13px; }}
|
||||
.metric strong {{ display: block; color: var(--ink); font-size: 34px; line-height: 1.1; margin: 8px 0; }}
|
||||
.metric p, .gate p, .gate footer, .issues span, .evidence span {{ color: var(--muted); font-size: 14px; overflow-wrap: anywhere; }}
|
||||
.gate {{ display: flex; flex-direction: column; gap: 10px; }}
|
||||
.gate.pass {{ border-top: 4px solid var(--pass); }}
|
||||
.gate.warn {{ border-top: 4px solid var(--warn); }}
|
||||
.gate.block {{ border-top: 4px solid var(--block); }}
|
||||
.gate footer {{ border-top: 1px solid var(--line); padding-top: 10px; }}
|
||||
a {{ color: var(--ink); }}
|
||||
.twocol {{
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
||||
gap: 22px;
|
||||
align-items: start;
|
||||
}}
|
||||
.panel {{
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
padding: 18px;
|
||||
background: #fff;
|
||||
}}
|
||||
.panel p {{ color: var(--muted); }}
|
||||
.issues, .evidence {{
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}}
|
||||
.issues li, .evidence li {{
|
||||
border-left: 3px solid var(--line);
|
||||
padding-left: 12px;
|
||||
display: grid;
|
||||
gap: 3px;
|
||||
}}
|
||||
.muted {{ color: var(--muted); }}
|
||||
.actions-grid {{
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
}}
|
||||
.annotations-grid {{
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
}}
|
||||
.action-card {{
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
padding: 18px;
|
||||
background: #fff;
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
min-width: 0;
|
||||
}}
|
||||
.action-card.warn {{ border-left: 4px solid var(--warn); }}
|
||||
.action-card.block {{ border-left: 4px solid var(--block); }}
|
||||
.annotation-card {{
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
padding: 18px;
|
||||
background: #fff;
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
min-width: 0;
|
||||
}}
|
||||
.annotation-card.warning {{ border-left: 4px solid var(--warn); }}
|
||||
.annotation-card.blocker {{ border-left: 4px solid var(--block); }}
|
||||
.annotation-card.resolved {{ opacity: .72; }}
|
||||
.action-card span,
|
||||
.annotation-card span,
|
||||
.action-card small,
|
||||
.annotation-card small,
|
||||
.action-card footer,
|
||||
.annotation-card footer,
|
||||
.action-card dd {{
|
||||
color: var(--muted);
|
||||
font-size: 14px;
|
||||
overflow-wrap: anywhere;
|
||||
}}
|
||||
.annotation-card dd {{ color: var(--muted); font-size: 14px; overflow-wrap: anywhere; }}
|
||||
.action-card dl, .annotation-card dl {{
|
||||
display: grid;
|
||||
grid-template-columns: 80px minmax(0, 1fr);
|
||||
gap: 6px 10px;
|
||||
margin: 0;
|
||||
}}
|
||||
.action-card dt, .annotation-card dt {{ color: var(--ink); font-size: 14px; }}
|
||||
.action-card dd, .annotation-card dd {{ margin: 0; }}
|
||||
.source-ref-list {{
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
}}
|
||||
.source-ref-list li {{
|
||||
display: grid;
|
||||
gap: 2px;
|
||||
min-width: 0;
|
||||
padding: 8px 0 0;
|
||||
border-top: 1px solid var(--line);
|
||||
}}
|
||||
.source-ref-list a,
|
||||
.source-ref-list span {{
|
||||
overflow-wrap: anywhere;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
font-size: 13px;
|
||||
}}
|
||||
.source-ref-list small {{
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
}}
|
||||
code {{
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
font-size: 13px;
|
||||
}}
|
||||
@media (max-width: 980px) {{
|
||||
.metrics, .gates, .twocol, .actions-grid, .annotations-grid {{ grid-template-columns: 1fr; }}
|
||||
main {{ padding: 32px 18px 60px; }}
|
||||
nav {{ justify-content: flex-start; overflow-x: auto; flex-wrap: nowrap; }}
|
||||
nav a {{ flex: 0 0 auto; }}
|
||||
}}
|
||||
{review_studio_css()}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -1383,17 +1261,17 @@ def render_html(report: dict[str, Any]) -> str:
|
||||
|
||||
<section id="trigger" class="twocol">
|
||||
<div class="panel"><h2>触发实验</h2><p>{html.escape(gates[1]['detail'])}</p></div>
|
||||
<div class="panel"><h2>组合治理</h2><p>{html.escape(str(atlas_summary))}</p></div>
|
||||
<div class="panel"><h2>组合治理</h2>{atlas_panel}</div>
|
||||
</section>
|
||||
|
||||
<section id="output" class="twocol">
|
||||
<div class="panel"><h2>输出实验</h2><p>{html.escape(str(output_summary))}</p></div>
|
||||
<div class="panel"><h2>执行证据</h2><p>{html.escape(str(output_execution_summary or 'output execution report missing'))}</p></div>
|
||||
<div class="panel"><h2>输出实验</h2>{output_panel}</div>
|
||||
<div class="panel"><h2>执行证据</h2>{execution_panel}</div>
|
||||
</section>
|
||||
|
||||
<section class="twocol">
|
||||
<div class="panel"><h2>盲评包</h2><p>{html.escape(str(output_blind_summary or 'blind A/B review pack missing'))}</p></div>
|
||||
<div class="panel"><h2>审定报告</h2><p>{html.escape(str(output_review_summary or 'review adjudication report missing'))}</p></div>
|
||||
<div class="panel"><h2>盲评包</h2>{blind_panel}</div>
|
||||
<div class="panel"><h2>审定报告</h2>{review_panel}</div>
|
||||
</section>
|
||||
|
||||
<section class="twocol">
|
||||
@@ -1407,8 +1285,8 @@ def render_html(report: dict[str, Any]) -> str:
|
||||
</section>
|
||||
|
||||
<section id="runtime" class="twocol">
|
||||
<div class="panel"><h2>运行矩阵</h2><p>{html.escape(str(conformance_summary))}</p></div>
|
||||
<div class="panel"><h2>目标编译</h2><p>{html.escape(str(compiled_summary or 'compiled target report missing'))}</p></div>
|
||||
<div class="panel"><h2>运行矩阵</h2>{conformance_panel}</div>
|
||||
<div class="panel"><h2>目标编译</h2>{compiled_panel}</div>
|
||||
</section>
|
||||
|
||||
<section class="twocol">
|
||||
@@ -1417,7 +1295,7 @@ def render_html(report: dict[str, Any]) -> str:
|
||||
</section>
|
||||
|
||||
<section id="trust" class="twocol">
|
||||
<div class="panel"><h2>信任报告</h2><p>{html.escape(str(trust_summary))}</p></div>
|
||||
<div class="panel"><h2>信任报告</h2>{trust_panel}</div>
|
||||
<div class="panel"><h2>安全边界</h2><p>高风险 secret、远程 inline execution、缺失依赖策略或无法解释的脚本接口应阻断 governed release。</p></div>
|
||||
</section>
|
||||
|
||||
@@ -1428,7 +1306,7 @@ def render_html(report: dict[str, Any]) -> str:
|
||||
|
||||
<section id="permission-probes" class="twocol">
|
||||
<div class="panel"><h2>权限探针</h2><p>{html.escape(gate_details.get('permission-runtime', 'runtime permission probes missing'))}</p></div>
|
||||
<div class="panel"><h2>运行边界</h2><p>{html.escape(str(runtime_permissions_summary or 'runtime permission probe summary missing'))}</p></div>
|
||||
<div class="panel"><h2>运行边界</h2>{runtime_boundary_panel}</div>
|
||||
</section>
|
||||
|
||||
<section id="atlas" class="twocol">
|
||||
@@ -1438,22 +1316,22 @@ def render_html(report: dict[str, Any]) -> str:
|
||||
|
||||
<section id="telemetry" class="twocol">
|
||||
<div class="panel"><h2>运营回路</h2><p>{html.escape(gate_details.get('operations-loop', 'adoption drift report missing'))}</p></div>
|
||||
<div class="panel"><h2>漂移信号</h2><p>{html.escape(str(adoption_summary or 'no adoption drift summary'))}</p></div>
|
||||
<div class="panel"><h2>漂移信号</h2>{adoption_panel}</div>
|
||||
</section>
|
||||
|
||||
<section id="waivers" class="twocol">
|
||||
<div class="panel"><h2>人工批准</h2><p>{html.escape(gate_details.get('review-waivers', 'review waiver ledger missing'))}</p></div>
|
||||
<div class="panel"><h2>批准台账</h2><p>{html.escape(str(waiver_summary or 'no review waiver summary'))}</p></div>
|
||||
<div class="panel"><h2>批准台账</h2>{waiver_panel}</div>
|
||||
</section>
|
||||
|
||||
<section id="registry" class="twocol">
|
||||
<div class="panel"><h2>注册审计</h2><p>{html.escape(gate_details.get('registry-audit', 'registry audit missing'))}</p></div>
|
||||
<div class="panel"><h2>包体元数据</h2><p>{html.escape(str(registry_package))}</p></div>
|
||||
<div class="panel"><h2>包体元数据</h2>{registry_panel}</div>
|
||||
</section>
|
||||
|
||||
<section id="release" class="twocol">
|
||||
<div class="panel"><h2>发布路线</h2><p>{html.escape(gate_details.get('release-notes', 'release notes missing'))}</p></div>
|
||||
<div class="panel"><h2>包体验证</h2><p>{html.escape(str(package_summary or 'package verification missing'))}</p></div>
|
||||
<div class="panel"><h2>包体验证</h2>{package_panel}</div>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
@@ -5,6 +5,7 @@ import json
|
||||
from pathlib import Path
|
||||
|
||||
from skill_report_charts import render_chart_set
|
||||
from skill_report_layout import render_language_switch, render_report_nav, skill_overview_css, skill_overview_script
|
||||
from skill_report_model import REPORT_NAV_V2, build_report_model
|
||||
|
||||
|
||||
@@ -279,15 +280,8 @@ def render_roadmap(items: list[dict]) -> str:
|
||||
|
||||
def render_html(summary: dict) -> str:
|
||||
charts = render_chart_set(summary)
|
||||
nav_html = "".join(
|
||||
f"<a href=\"#{item['href']}\">{bi_span(item['label'], item['label_en'])}</a>" for item in REPORT_NAV_V2
|
||||
)
|
||||
language_switch = (
|
||||
'<div class="language-switch" aria-label="语言切换">'
|
||||
'<button type="button" data-set-lang="zh-CN" aria-pressed="true">简体</button>'
|
||||
'<button type="button" data-set-lang="en" aria-pressed="false">EN</button>'
|
||||
"</div>"
|
||||
)
|
||||
nav_html = render_report_nav(REPORT_NAV_V2)
|
||||
language_switch = render_language_switch()
|
||||
skill = summary.get("skill_summary", {})
|
||||
metadata = summary.get("metadata", {})
|
||||
scorecard = summary.get("scorecard", {})
|
||||
@@ -359,580 +353,7 @@ def render_html(summary: dict) -> str:
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{html.escape(summary['name'])} Skill 生成审计报告</title>
|
||||
<style>
|
||||
:root {{
|
||||
--paper: #ffffff;
|
||||
--wash: #f8fafc;
|
||||
--wash-strong: #f2f5f8;
|
||||
--line: #e6e0d4;
|
||||
--line-soft: #eee9df;
|
||||
--brand: #1B365D;
|
||||
--brand-soft: #EEF3F8;
|
||||
--brand-mid: #315982;
|
||||
--ink: #151515;
|
||||
--text: #2f2d29;
|
||||
--muted: #68625a;
|
||||
--faint: #8b857b;
|
||||
--success: #2f6f5e;
|
||||
--warn: #8a5a19;
|
||||
--serif: "TsangerJinKai02", "Source Han Serif SC", "Noto Serif CJK SC", "Songti SC", "STSong", Charter, Georgia, serif;
|
||||
--mono: "JetBrains Mono", "SF Mono", ui-monospace, Menlo, Consolas, monospace;
|
||||
--shadow-soft: 0 1px 2px rgba(27, 54, 93, 0.06), 0 16px 44px rgba(27, 54, 93, 0.08);
|
||||
}}
|
||||
* {{ box-sizing: border-box; }}
|
||||
html {{ scroll-behavior: smooth; }}
|
||||
body {{
|
||||
margin: 0;
|
||||
background: #ffffff;
|
||||
color: var(--ink);
|
||||
font-family: var(--serif);
|
||||
line-height: 1.62;
|
||||
letter-spacing: 0;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
}}
|
||||
body[data-report-lang="zh-CN"] [data-lang="en"],
|
||||
body[data-report-lang="en"] [data-lang="zh-CN"] {{ display: none !important; }}
|
||||
.skip-link {{
|
||||
position: fixed;
|
||||
left: 18px;
|
||||
top: 10px;
|
||||
z-index: 40;
|
||||
transform: translateY(-140%);
|
||||
padding: 8px 12px;
|
||||
border-radius: 8px;
|
||||
background: var(--brand);
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
transition: transform 160ms cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}}
|
||||
.skip-link:focus-visible {{ transform: translateY(0); outline: 2px solid var(--brand-mid); outline-offset: 2px; }}
|
||||
.topbar {{
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 20;
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
border-bottom: 1px solid var(--line);
|
||||
}}
|
||||
.progress-track {{
|
||||
height: 2px;
|
||||
background: transparent;
|
||||
}}
|
||||
.progress-bar {{
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--brand);
|
||||
transition: transform 160ms cubic-bezier(0.16, 1, 0.3, 1);
|
||||
transform-origin: left center;
|
||||
transform: scaleX(0);
|
||||
}}
|
||||
.topbar-inner {{
|
||||
max-width: 1240px;
|
||||
margin: 0 auto;
|
||||
padding: 9px 28px;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 18px;
|
||||
align-items: center;
|
||||
}}
|
||||
.nav-shell {{
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr);
|
||||
gap: 18px;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
}}
|
||||
.report-mark {{
|
||||
color: var(--brand);
|
||||
font-family: var(--mono);
|
||||
font-size: 11px;
|
||||
line-height: 1;
|
||||
text-transform: uppercase;
|
||||
white-space: nowrap;
|
||||
}}
|
||||
.report-nav {{
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none;
|
||||
min-width: 0;
|
||||
}}
|
||||
.report-nav::-webkit-scrollbar {{ display: none; }}
|
||||
.report-nav a {{
|
||||
flex: 0 0 auto;
|
||||
min-width: 76px;
|
||||
min-height: 40px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 10px;
|
||||
color: var(--brand);
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
border-radius: 8px;
|
||||
white-space: nowrap;
|
||||
transition-property: background-color, color, transform;
|
||||
transition-duration: 160ms;
|
||||
transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}}
|
||||
@media (hover: hover) {{
|
||||
.report-nav a:hover {{ background: var(--brand-soft); }}
|
||||
}}
|
||||
.report-nav a:focus-visible {{
|
||||
outline: 2px solid var(--brand-mid);
|
||||
outline-offset: 2px;
|
||||
background: var(--brand-soft);
|
||||
}}
|
||||
.report-nav a[aria-current="true"] {{
|
||||
background: var(--brand);
|
||||
color: #ffffff;
|
||||
}}
|
||||
.report-nav a[aria-current="true"] span {{ color: #ffffff; }}
|
||||
.language-switch {{
|
||||
display: inline-flex;
|
||||
gap: 3px;
|
||||
padding: 3px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
background: var(--paper);
|
||||
box-shadow: 0 1px 2px rgba(27, 54, 93, 0.05);
|
||||
}}
|
||||
.language-switch button {{
|
||||
appearance: none;
|
||||
min-width: 42px;
|
||||
min-height: 34px;
|
||||
border: 0;
|
||||
border-radius: 6px;
|
||||
padding: 0 10px;
|
||||
background: transparent;
|
||||
color: var(--muted);
|
||||
font: inherit;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
transition-property: background-color, color, transform;
|
||||
transition-duration: 160ms;
|
||||
transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}}
|
||||
.language-switch button:active {{ transform: scale(0.96); }}
|
||||
.language-switch button:focus-visible {{ outline: 2px solid var(--brand-mid); outline-offset: 2px; }}
|
||||
.language-switch button[aria-pressed="true"] {{
|
||||
background: var(--brand-soft);
|
||||
color: var(--brand);
|
||||
}}
|
||||
.wrap {{
|
||||
max-width: 1240px;
|
||||
margin: 0 auto;
|
||||
padding: 58px 28px 92px;
|
||||
}}
|
||||
.hero {{
|
||||
padding: 16px 0 34px;
|
||||
}}
|
||||
.hero-grid {{
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) 360px;
|
||||
gap: 44px;
|
||||
align-items: end;
|
||||
}}
|
||||
.eyebrow, .report-mark {{
|
||||
letter-spacing: 0;
|
||||
}}
|
||||
.eyebrow {{
|
||||
margin: 0 0 12px;
|
||||
color: var(--brand);
|
||||
font-family: var(--mono);
|
||||
font-size: 12px;
|
||||
text-transform: uppercase;
|
||||
}}
|
||||
.slug {{
|
||||
margin: 0 0 18px;
|
||||
color: var(--faint);
|
||||
font-family: var(--mono);
|
||||
font-size: 13px;
|
||||
overflow-wrap: anywhere;
|
||||
}}
|
||||
h1, h2, h3 {{
|
||||
margin: 0;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0;
|
||||
text-wrap: balance;
|
||||
}}
|
||||
h1 {{
|
||||
max-width: 8em;
|
||||
color: var(--ink);
|
||||
font-size: 4rem;
|
||||
line-height: 1.02;
|
||||
}}
|
||||
.lead {{
|
||||
max-width: 760px;
|
||||
margin: 20px 0 0;
|
||||
color: var(--text);
|
||||
font-size: 1.08rem;
|
||||
text-wrap: pretty;
|
||||
}}
|
||||
.hero-meta, .badges {{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-top: 20px;
|
||||
}}
|
||||
.hero-meta span, .badges span, .tag {{
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 30px;
|
||||
padding: 5px 10px;
|
||||
border-radius: 6px;
|
||||
background: var(--brand-soft);
|
||||
color: var(--brand);
|
||||
font-size: 13px;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}}
|
||||
.hero-card {{
|
||||
position: relative;
|
||||
padding: 22px 22px 24px;
|
||||
border-radius: 8px;
|
||||
background: linear-gradient(180deg, #ffffff 0%, #fbfaf7 100%);
|
||||
box-shadow: var(--shadow-soft);
|
||||
border: 1px solid var(--line-soft);
|
||||
}}
|
||||
.hero-card::before {{
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 18px;
|
||||
right: 18px;
|
||||
width: 38px;
|
||||
height: 2px;
|
||||
background: var(--brand);
|
||||
}}
|
||||
.score-strip {{
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 10px;
|
||||
margin-top: 32px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid var(--line);
|
||||
}}
|
||||
.score-chip {{
|
||||
padding: 14px 14px 12px;
|
||||
border-radius: 8px;
|
||||
background: var(--wash);
|
||||
border: 1px solid var(--line-soft);
|
||||
}}
|
||||
.score-chip span {{
|
||||
display: block;
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
}}
|
||||
.score-chip strong {{
|
||||
display: block;
|
||||
margin: 5px 0 8px;
|
||||
color: var(--brand);
|
||||
font-family: var(--mono);
|
||||
font-size: 1.65rem;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}}
|
||||
.score-chip i {{
|
||||
display: block;
|
||||
height: 3px;
|
||||
border-radius: 999px;
|
||||
background: linear-gradient(90deg, var(--brand) var(--score), #dfe6ee var(--score));
|
||||
}}
|
||||
.score-chip small {{
|
||||
display: block;
|
||||
margin-top: 8px;
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
line-height: 1.45;
|
||||
}}
|
||||
section {{
|
||||
scroll-margin-top: 78px;
|
||||
padding-top: 44px;
|
||||
margin-top: 44px;
|
||||
border-top: 1px solid var(--line);
|
||||
}}
|
||||
section.hero {{
|
||||
scroll-margin-top: 0;
|
||||
padding-top: 16px;
|
||||
margin-top: 0;
|
||||
border-top: 0;
|
||||
}}
|
||||
.section-head {{
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 246px) minmax(0, 1fr);
|
||||
gap: 36px;
|
||||
align-items: start;
|
||||
}}
|
||||
h2 {{
|
||||
color: var(--ink);
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.18;
|
||||
}}
|
||||
h2::before {{
|
||||
content: "";
|
||||
display: block;
|
||||
width: 32px;
|
||||
height: 2px;
|
||||
margin-bottom: 12px;
|
||||
background: var(--brand);
|
||||
}}
|
||||
h3 {{
|
||||
color: var(--ink);
|
||||
font-size: 1.02rem;
|
||||
line-height: 1.3;
|
||||
margin-bottom: 10px;
|
||||
}}
|
||||
.section-head p {{
|
||||
margin: 12px 0 0;
|
||||
color: var(--muted);
|
||||
max-width: 43ch;
|
||||
text-wrap: pretty;
|
||||
}}
|
||||
.two-col, .metric-grid, .chart-grid {{
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
align-items: stretch;
|
||||
}}
|
||||
.quality-panels {{
|
||||
margin-top: 16px;
|
||||
}}
|
||||
.metrics-stack {{
|
||||
display: grid;
|
||||
gap: 18px;
|
||||
}}
|
||||
.metrics-lead {{
|
||||
display: grid;
|
||||
grid-template-columns: minmax(420px, 1.15fr) minmax(300px, 0.85fr);
|
||||
gap: 18px;
|
||||
align-items: stretch;
|
||||
}}
|
||||
.metrics-note {{
|
||||
display: grid;
|
||||
align-content: start;
|
||||
gap: 16px;
|
||||
}}
|
||||
.metrics-note p {{
|
||||
margin: 0;
|
||||
max-width: none;
|
||||
color: var(--text);
|
||||
}}
|
||||
.metric-summary-list {{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}}
|
||||
.metric-summary-list li {{
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr) auto;
|
||||
gap: 8px 10px;
|
||||
align-items: baseline;
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid var(--line-soft);
|
||||
}}
|
||||
.metric-summary-list li:last-child {{ border-bottom: 0; }}
|
||||
.metric-summary-list b {{
|
||||
color: var(--ink);
|
||||
font-weight: 500;
|
||||
}}
|
||||
.metric-summary-list em {{
|
||||
color: var(--brand);
|
||||
font-family: var(--mono);
|
||||
font-style: normal;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}}
|
||||
.metric-summary-list small {{
|
||||
grid-column: 2 / 4;
|
||||
color: var(--muted);
|
||||
line-height: 1.5;
|
||||
}}
|
||||
.metric-status {{
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 24px;
|
||||
padding: 2px 7px;
|
||||
border-radius: 6px;
|
||||
background: var(--brand-soft);
|
||||
color: var(--brand);
|
||||
font-size: 12px;
|
||||
}}
|
||||
.metric-grid {{
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
margin-top: 2px;
|
||||
}}
|
||||
.list, .compact-list, .step-list {{
|
||||
margin: 0;
|
||||
padding-left: 1.15em;
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}}
|
||||
.list li::marker, .compact-list li::marker, .step-list li::marker {{ color: var(--brand); }}
|
||||
.compact-list {{
|
||||
gap: 6px;
|
||||
font-size: 13px;
|
||||
color: var(--muted);
|
||||
}}
|
||||
.panel, .metric-card, .roadmap-item {{
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line-soft);
|
||||
border-radius: 8px;
|
||||
padding: 22px;
|
||||
box-shadow: 0 1px 2px rgba(27, 54, 93, 0.04);
|
||||
}}
|
||||
.metric-card {{
|
||||
display: grid;
|
||||
grid-template-columns: 92px minmax(0, 1fr);
|
||||
gap: 18px;
|
||||
align-content: start;
|
||||
min-height: 0;
|
||||
}}
|
||||
.metric-card-head {{
|
||||
display: grid;
|
||||
align-content: start;
|
||||
}}
|
||||
.metric-card strong {{
|
||||
display: block;
|
||||
margin: 8px 0 10px;
|
||||
color: var(--brand);
|
||||
font-family: var(--mono);
|
||||
font-size: 2rem;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}}
|
||||
.metric-label {{
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
}}
|
||||
.metric-card-body {{
|
||||
min-width: 0;
|
||||
}}
|
||||
.chart-figure {{
|
||||
margin: 0;
|
||||
padding: 18px;
|
||||
border: 1px solid var(--line-soft);
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 1px 2px rgba(27, 54, 93, 0.04);
|
||||
}}
|
||||
.chart-figure svg {{
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
overflow: visible;
|
||||
}}
|
||||
.chart-figure text {{
|
||||
fill: var(--ink);
|
||||
font-family: var(--serif);
|
||||
font-size: 13px;
|
||||
}}
|
||||
.chart-title {{
|
||||
fill: var(--brand);
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}}
|
||||
.chart-line {{
|
||||
fill: none;
|
||||
stroke: var(--brand);
|
||||
stroke-width: 2;
|
||||
}}
|
||||
figcaption {{
|
||||
margin-top: 12px;
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid var(--line-soft);
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
text-wrap: pretty;
|
||||
}}
|
||||
table {{
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 14px;
|
||||
}}
|
||||
th, td {{
|
||||
padding: 12px 10px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid var(--line-soft);
|
||||
vertical-align: top;
|
||||
}}
|
||||
th {{
|
||||
color: var(--brand);
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
}}
|
||||
td:first-child, th:first-child {{ width: 96px; }}
|
||||
.roadmap {{
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
}}
|
||||
.step {{
|
||||
display: inline-flex;
|
||||
margin-bottom: 12px;
|
||||
min-height: 28px;
|
||||
align-items: center;
|
||||
padding: 3px 8px;
|
||||
border-radius: 6px;
|
||||
background: var(--brand-soft);
|
||||
color: var(--brand);
|
||||
font-size: 12px;
|
||||
}}
|
||||
.unlock {{
|
||||
margin-top: 14px;
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
}}
|
||||
@media (max-width: 980px) {{
|
||||
.topbar-inner {{
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
padding: 8px 16px;
|
||||
}}
|
||||
.nav-shell {{ grid-template-columns: 1fr; gap: 6px; }}
|
||||
.report-mark {{ display: none; }}
|
||||
.report-nav a {{ min-width: 72px; }}
|
||||
.hero-grid, .section-head {{ grid-template-columns: 1fr; }}
|
||||
.hero-grid {{ gap: 24px; }}
|
||||
.score-strip {{ grid-template-columns: repeat(2, minmax(0, 1fr)); }}
|
||||
.metrics-lead, .two-col, .metric-grid, .chart-grid, .roadmap {{ grid-template-columns: 1fr; }}
|
||||
.metric-card {{ grid-template-columns: 86px minmax(0, 1fr); }}
|
||||
h1 {{ font-size: 2.75rem; }}
|
||||
}}
|
||||
@media (max-width: 540px) {{
|
||||
.wrap {{ padding: 34px 16px 72px; }}
|
||||
.topbar-inner {{ gap: 10px; }}
|
||||
.report-nav {{
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
}}
|
||||
.report-nav a {{
|
||||
min-width: 66px;
|
||||
min-height: 38px;
|
||||
padding: 0 8px;
|
||||
font-size: 12px;
|
||||
}}
|
||||
.language-switch button {{ min-width: 38px; min-height: 32px; padding: 0 8px; }}
|
||||
.hero {{ padding-top: 8px; }}
|
||||
h1 {{ max-width: 8em; font-size: 2.35rem; }}
|
||||
.lead {{ font-size: 1rem; }}
|
||||
.hero-meta span, .badges span {{ font-size: 12px; }}
|
||||
.score-strip {{ grid-template-columns: 1fr; }}
|
||||
section {{ margin-top: 34px; padding-top: 34px; }}
|
||||
.panel, .metric-card, .roadmap-item, .chart-figure, .hero-card {{ padding: 18px; }}
|
||||
.metric-card {{ grid-template-columns: 1fr; gap: 10px; }}
|
||||
.metric-card strong {{ margin-bottom: 2px; }}
|
||||
.metric-summary-list li {{ grid-template-columns: auto minmax(0, 1fr) auto; }}
|
||||
table {{ font-size: 13px; }}
|
||||
th, td {{ padding: 10px 7px; }}
|
||||
}}
|
||||
@media (prefers-reduced-motion: reduce) {{
|
||||
html {{ scroll-behavior: auto; }}
|
||||
*, *::before, *::after {{ transition-duration: 0.01ms !important; }}
|
||||
}}
|
||||
{skill_overview_css()}
|
||||
</style>
|
||||
</head>
|
||||
<body data-report-lang="zh-CN">
|
||||
@@ -1148,43 +569,7 @@ def render_html(summary: dict) -> str:
|
||||
</section>
|
||||
</main>
|
||||
<script>
|
||||
(function () {{
|
||||
var buttons = Array.prototype.slice.call(document.querySelectorAll("[data-set-lang]"));
|
||||
var navLinks = Array.prototype.slice.call(document.querySelectorAll(".report-nav a"));
|
||||
var sections = navLinks
|
||||
.map(function (link) {{ return document.querySelector(link.getAttribute("href")); }})
|
||||
.filter(Boolean);
|
||||
var progressBar = document.querySelector(".progress-bar");
|
||||
function setLanguage(lang) {{
|
||||
document.body.setAttribute("data-report-lang", lang);
|
||||
document.documentElement.setAttribute("lang", lang);
|
||||
buttons.forEach(function (button) {{
|
||||
button.setAttribute("aria-pressed", button.getAttribute("data-set-lang") === lang ? "true" : "false");
|
||||
}});
|
||||
}}
|
||||
function updateProgress() {{
|
||||
var scrollTop = window.scrollY || document.documentElement.scrollTop;
|
||||
var height = Math.max(1, document.documentElement.scrollHeight - window.innerHeight);
|
||||
var pct = Math.min(100, Math.max(0, (scrollTop / height) * 100));
|
||||
if (progressBar) progressBar.style.transform = "scaleX(" + pct / 100 + ")";
|
||||
var active = sections[0];
|
||||
sections.forEach(function (section) {{
|
||||
if (section.getBoundingClientRect().top <= 110) active = section;
|
||||
}});
|
||||
navLinks.forEach(function (link) {{
|
||||
link.setAttribute("aria-current", link.getAttribute("href") === "#" + active.id ? "true" : "false");
|
||||
}});
|
||||
}}
|
||||
buttons.forEach(function (button) {{
|
||||
button.addEventListener("click", function () {{
|
||||
setLanguage(button.getAttribute("data-set-lang"));
|
||||
}});
|
||||
}});
|
||||
window.addEventListener("scroll", updateProgress, {{ passive: true }});
|
||||
window.addEventListener("resize", updateProgress);
|
||||
setLanguage("zh-CN");
|
||||
updateProgress();
|
||||
}})();
|
||||
{skill_overview_script()}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Formatting helpers for Review Studio panels."""
|
||||
|
||||
import html
|
||||
from typing import Any
|
||||
|
||||
|
||||
SCRIPT_INTERFACE = "internal-module"
|
||||
SCRIPT_INTERFACE_REASON = "Imported by render_review_studio.py to format report dictionaries as audit UI panels."
|
||||
|
||||
|
||||
LABELS = {
|
||||
"actionable_owner_gap_count": "待处理 owner",
|
||||
"actionable_route_collision_count": "待处理冲突",
|
||||
"actionable_skill_count": "纳入审查",
|
||||
"actionable_stale_count": "待处理过期",
|
||||
"adoption_rate": "采用率",
|
||||
"adapter_count": "Adapter",
|
||||
"archive_entry_count": "Zip 条目",
|
||||
"archive_present": "归档存在",
|
||||
"archive_sha256": "归档哈希",
|
||||
"baseline_pass_rate": "Baseline",
|
||||
"breaking_change_count": "破坏变更",
|
||||
"case_count": "案例数",
|
||||
"command_executed_count": "命令执行",
|
||||
"compatibility_pass_count": "兼容通过",
|
||||
"covered_gate_count": "覆盖 Gate",
|
||||
"declared_bump": "声明版本",
|
||||
"delta": "增益",
|
||||
"event_count": "事件数",
|
||||
"failure_count": "失败数",
|
||||
"gate_pass": "Gate",
|
||||
"help_smoke_failed_count": "Help 失败",
|
||||
"install_simulated": "安装模拟",
|
||||
"license": "License",
|
||||
"metadata_fallback_count": "Metadata fallback",
|
||||
"missed_trigger_count": "漏触发",
|
||||
"model_executed_count": "模型执行",
|
||||
"name": "名称",
|
||||
"native_enforcement_count": "原生执行",
|
||||
"network_script_count": "网络脚本",
|
||||
"non_actionable_issue_count": "非行动项",
|
||||
"open_blocker_count": "阻断批注",
|
||||
"open_count": "开放批注",
|
||||
"owner": "Owner",
|
||||
"package_sha256": "包体哈希",
|
||||
"pass_count": "通过数",
|
||||
"pending_count": "待审",
|
||||
"recorded_fixture_count": "记录样本",
|
||||
"recommended_bump": "建议版本",
|
||||
"residual_risk_count": "残余风险",
|
||||
"risk_band": "风险带",
|
||||
"route_collision_count": "路由冲突",
|
||||
"script_count": "脚本数",
|
||||
"secret_findings": "Secret",
|
||||
"skill_count": "Skill 数",
|
||||
"target_count": "目标数",
|
||||
"targets": "目标平台",
|
||||
"timing_observed_count": "计时样本",
|
||||
"token_estimated_count": "估算 Token",
|
||||
"token_observed_count": "真实 Token",
|
||||
"trust_level": "信任级别",
|
||||
"variant_run_count": "运行数",
|
||||
"version": "版本",
|
||||
"warning_count": "警告数",
|
||||
"with_skill_pass_rate": "With Skill",
|
||||
}
|
||||
|
||||
|
||||
def label_for_key(key: str) -> str:
|
||||
return LABELS.get(key, key.replace("_", " ").title())
|
||||
|
||||
|
||||
def value_text(value: Any) -> str:
|
||||
if value is None:
|
||||
return "n/a"
|
||||
if isinstance(value, bool):
|
||||
return "是" if value else "否"
|
||||
if isinstance(value, float):
|
||||
return str(round(value, 3)).rstrip("0").rstrip(".")
|
||||
if isinstance(value, list):
|
||||
return ", ".join(value_text(item) for item in value) if value else "无"
|
||||
if isinstance(value, dict):
|
||||
parts = []
|
||||
for key, nested_value in list(value.items())[:6]:
|
||||
parts.append(f"{label_for_key(str(key))}: {value_text(nested_value)}")
|
||||
return ";".join(parts) if parts else "无"
|
||||
return str(value)
|
||||
|
||||
|
||||
def render_kv_grid(
|
||||
payload: dict[str, Any],
|
||||
keys: list[str],
|
||||
empty: str,
|
||||
) -> str:
|
||||
if not payload:
|
||||
return f"<p class='muted'>{html.escape(empty)}</p>"
|
||||
rows = []
|
||||
for key in keys:
|
||||
if key not in payload:
|
||||
continue
|
||||
value = value_text(payload.get(key))
|
||||
value_html = html.escape(value)
|
||||
if "sha256" in key or "hash" in key or "checksum" in key:
|
||||
value_html = f"<code>{value_html}</code>"
|
||||
rows.append(
|
||||
"<div>"
|
||||
f"<dt>{html.escape(label_for_key(key))}</dt>"
|
||||
f"<dd>{value_html}</dd>"
|
||||
"</div>"
|
||||
)
|
||||
if not rows:
|
||||
return f"<p class='muted'>{html.escape(empty)}</p>"
|
||||
return "<dl class='kv-grid'>" + "".join(rows) + "</dl>"
|
||||
|
||||
|
||||
def registry_package_summary(package: dict[str, Any]) -> dict[str, Any]:
|
||||
if not package:
|
||||
return {}
|
||||
compatibility = package.get("compatibility", {}) if isinstance(package.get("compatibility"), dict) else {}
|
||||
pass_count = sum(1 for status in compatibility.values() if status == "pass")
|
||||
checksums = package.get("checksums", {}) if isinstance(package.get("checksums"), dict) else {}
|
||||
return {
|
||||
"name": package.get("name", ""),
|
||||
"version": package.get("version", ""),
|
||||
"maturity": package.get("maturity", ""),
|
||||
"owner": package.get("owner", ""),
|
||||
"license": package.get("license", ""),
|
||||
"trust_level": package.get("trust_level", ""),
|
||||
"targets": package.get("targets", []),
|
||||
"compatibility_pass_count": f"{pass_count}/{len(compatibility)}",
|
||||
"archive_sha256": checksums.get("archive_sha256", ""),
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Static layout contract for Review Studio HTML."""
|
||||
|
||||
import html
|
||||
|
||||
|
||||
SCRIPT_INTERFACE = "internal-module"
|
||||
SCRIPT_INTERFACE_REASON = "Imported by render_review_studio.py to keep Review Studio layout and CSS out of gate logic."
|
||||
|
||||
|
||||
REVIEW_STUDIO_NAV = [
|
||||
("#overview", "审查总览"),
|
||||
("#intent", "意图画布"),
|
||||
("#trigger", "触发实验"),
|
||||
("#output", "输出实验"),
|
||||
("#actions", "修复动作"),
|
||||
("#annotations", "审查批注"),
|
||||
("#runtime", "运行矩阵"),
|
||||
("#trust", "信任报告"),
|
||||
("#permissions", "权限批准"),
|
||||
("#permission-probes", "权限探针"),
|
||||
("#atlas", "组合治理"),
|
||||
("#telemetry", "运营回路"),
|
||||
("#waivers", "人工批准"),
|
||||
("#registry", "注册审计"),
|
||||
("#release", "发布路线"),
|
||||
]
|
||||
|
||||
|
||||
def render_review_nav(nav_items: list[tuple[str, str]] | None = None) -> str:
|
||||
items = REVIEW_STUDIO_NAV if nav_items is None else nav_items
|
||||
return "".join(
|
||||
f"<a href='{html.escape(href)}'>{html.escape(label)}</a>"
|
||||
for href, label in items
|
||||
)
|
||||
|
||||
|
||||
def review_studio_css() -> str:
|
||||
return """
|
||||
:root {
|
||||
--ink: #1B365D;
|
||||
--text: #24201d;
|
||||
--muted: #746d66;
|
||||
--line: #e7ded2;
|
||||
--soft: #faf8f5;
|
||||
--pass: #1e6b52;
|
||||
--warn: #9a6718;
|
||||
--block: #9b2c2c;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
html { scroll-behavior: smooth; }
|
||||
body {
|
||||
margin: 0;
|
||||
background: #ffffff;
|
||||
color: var(--text);
|
||||
font-family: Georgia, "Times New Roman", "Songti SC", serif;
|
||||
line-height: 1.58;
|
||||
}
|
||||
nav {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
padding: 10px 16px;
|
||||
background: rgba(255,255,255,0.94);
|
||||
border-bottom: 1px solid var(--line);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
nav a {
|
||||
color: var(--ink);
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
padding: 7px 10px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
nav a:hover { background: var(--soft); }
|
||||
main { max-width: 1180px; margin: 0 auto; padding: 44px 28px 76px; }
|
||||
header { border-bottom: 1px solid var(--line); padding-bottom: 28px; margin-bottom: 28px; }
|
||||
.eyebrow { color: var(--ink); font-size: 14px; letter-spacing: .08em; text-transform: uppercase; }
|
||||
h1, h2, h3 { color: var(--text); font-weight: 500; margin: 0; letter-spacing: 0; }
|
||||
h1 { font-size: clamp(34px, 5vw, 64px); line-height: 1.03; max-width: 920px; margin-top: 12px; }
|
||||
h2 { font-size: 30px; margin-bottom: 14px; }
|
||||
h3 { font-size: 19px; }
|
||||
p { margin: 0; }
|
||||
.lede { max-width: 820px; color: var(--muted); font-size: 20px; margin-top: 18px; }
|
||||
.decision {
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
gap: 12px;
|
||||
margin-top: 24px;
|
||||
padding: 12px 16px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
color: var(--ink);
|
||||
background: var(--soft);
|
||||
}
|
||||
.decision strong { font-size: 28px; }
|
||||
section { padding: 30px 0; border-bottom: 1px solid var(--line); scroll-margin-top: 76px; }
|
||||
.metrics, .gates {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||
gap: 14px;
|
||||
}
|
||||
.gates { grid-template-columns: repeat(4, minmax(0, 1fr)); }
|
||||
.metric, .gate {
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
min-width: 0;
|
||||
}
|
||||
.metric span, .gate span { display: block; color: var(--muted); font-size: 13px; }
|
||||
.metric strong { display: block; color: var(--ink); font-size: 34px; line-height: 1.1; margin: 8px 0; }
|
||||
.metric p, .gate p, .gate footer, .issues span, .evidence span { color: var(--muted); font-size: 14px; overflow-wrap: anywhere; }
|
||||
.gate { display: flex; flex-direction: column; gap: 10px; }
|
||||
.gate.pass { border-top: 4px solid var(--pass); }
|
||||
.gate.warn { border-top: 4px solid var(--warn); }
|
||||
.gate.block { border-top: 4px solid var(--block); }
|
||||
.gate footer { border-top: 1px solid var(--line); padding-top: 10px; }
|
||||
a { color: var(--ink); }
|
||||
.twocol {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
||||
gap: 22px;
|
||||
align-items: start;
|
||||
}
|
||||
.panel {
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
padding: 18px;
|
||||
background: #fff;
|
||||
}
|
||||
.panel p { color: var(--muted); }
|
||||
.kv-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 10px 12px;
|
||||
margin: 2px 0 0;
|
||||
}
|
||||
.kv-grid div {
|
||||
min-width: 0;
|
||||
padding: 9px 0 0;
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
.kv-grid dt {
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
}
|
||||
.kv-grid dd {
|
||||
margin: 2px 0 0;
|
||||
color: var(--ink);
|
||||
font-size: 15px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.issues, .evidence {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
.issues li, .evidence li {
|
||||
border-left: 3px solid var(--line);
|
||||
padding-left: 12px;
|
||||
display: grid;
|
||||
gap: 3px;
|
||||
}
|
||||
.muted { color: var(--muted); }
|
||||
.actions-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
.annotations-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
.action-card {
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
padding: 18px;
|
||||
background: #fff;
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
min-width: 0;
|
||||
}
|
||||
.action-card.warn { border-left: 4px solid var(--warn); }
|
||||
.action-card.block { border-left: 4px solid var(--block); }
|
||||
.annotation-card {
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
padding: 18px;
|
||||
background: #fff;
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
min-width: 0;
|
||||
}
|
||||
.annotation-card.warning { border-left: 4px solid var(--warn); }
|
||||
.annotation-card.blocker { border-left: 4px solid var(--block); }
|
||||
.annotation-card.resolved { opacity: .72; }
|
||||
.action-card span,
|
||||
.annotation-card span,
|
||||
.action-card small,
|
||||
.annotation-card small,
|
||||
.action-card footer,
|
||||
.annotation-card footer,
|
||||
.action-card dd {
|
||||
color: var(--muted);
|
||||
font-size: 14px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.annotation-card dd { color: var(--muted); font-size: 14px; overflow-wrap: anywhere; }
|
||||
.action-card dl, .annotation-card dl {
|
||||
display: grid;
|
||||
grid-template-columns: 80px minmax(0, 1fr);
|
||||
gap: 6px 10px;
|
||||
margin: 0;
|
||||
}
|
||||
.action-card dt, .annotation-card dt { color: var(--ink); font-size: 14px; }
|
||||
.action-card dd, .annotation-card dd { margin: 0; }
|
||||
.source-ref-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
}
|
||||
.source-ref-list li {
|
||||
display: grid;
|
||||
gap: 2px;
|
||||
min-width: 0;
|
||||
padding: 8px 0 0;
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
.source-ref-list a,
|
||||
.source-ref-list span {
|
||||
overflow-wrap: anywhere;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
font-size: 13px;
|
||||
}
|
||||
.source-ref-list small {
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
}
|
||||
code {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
font-size: 13px;
|
||||
}
|
||||
@media (max-width: 980px) {
|
||||
.metrics, .gates, .twocol, .actions-grid, .annotations-grid, .kv-grid { grid-template-columns: 1fr; }
|
||||
main { padding: 32px 18px 60px; }
|
||||
nav { justify-content: flex-start; overflow-x: auto; flex-wrap: nowrap; }
|
||||
nav a { flex: 0 0 auto; }
|
||||
}
|
||||
""".strip()
|
||||
@@ -0,0 +1,653 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Static layout contract for skill overview report HTML."""
|
||||
|
||||
import html
|
||||
from typing import Any
|
||||
|
||||
|
||||
SCRIPT_INTERFACE = "internal-module"
|
||||
SCRIPT_INTERFACE_REASON = "Imported by render_skill_overview.py to keep overview report layout and CSS out of data rendering."
|
||||
|
||||
|
||||
def bi_span(zh: str, en: str) -> str:
|
||||
return (
|
||||
f'<span data-lang="zh-CN">{html.escape(str(zh))}</span>'
|
||||
f'<span data-lang="en">{html.escape(str(en))}</span>'
|
||||
)
|
||||
|
||||
|
||||
def render_report_nav(nav_items: list[dict[str, Any]]) -> str:
|
||||
return "".join(
|
||||
f"<a href=\"#{html.escape(str(item['href']))}\">{bi_span(str(item['label']), str(item['label_en']))}</a>"
|
||||
for item in nav_items
|
||||
)
|
||||
|
||||
|
||||
def render_language_switch() -> str:
|
||||
return (
|
||||
'<div class="language-switch" aria-label="语言切换">'
|
||||
'<button type="button" data-set-lang="zh-CN" aria-pressed="true">简体</button>'
|
||||
'<button type="button" data-set-lang="en" aria-pressed="false">EN</button>'
|
||||
"</div>"
|
||||
)
|
||||
|
||||
|
||||
def skill_overview_css() -> str:
|
||||
return """
|
||||
:root {
|
||||
--paper: #ffffff;
|
||||
--wash: #f8fafc;
|
||||
--wash-strong: #f2f5f8;
|
||||
--line: #e6e0d4;
|
||||
--line-soft: #eee9df;
|
||||
--brand: #1B365D;
|
||||
--brand-soft: #EEF3F8;
|
||||
--brand-mid: #315982;
|
||||
--ink: #151515;
|
||||
--text: #2f2d29;
|
||||
--muted: #68625a;
|
||||
--faint: #8b857b;
|
||||
--success: #2f6f5e;
|
||||
--warn: #8a5a19;
|
||||
--serif: "TsangerJinKai02", "Source Han Serif SC", "Noto Serif CJK SC", "Songti SC", "STSong", Charter, Georgia, serif;
|
||||
--mono: "JetBrains Mono", "SF Mono", ui-monospace, Menlo, Consolas, monospace;
|
||||
--shadow-soft: 0 1px 2px rgba(27, 54, 93, 0.06), 0 16px 44px rgba(27, 54, 93, 0.08);
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
html { scroll-behavior: smooth; }
|
||||
body {
|
||||
margin: 0;
|
||||
background: #ffffff;
|
||||
color: var(--ink);
|
||||
font-family: var(--serif);
|
||||
line-height: 1.62;
|
||||
letter-spacing: 0;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
body[data-report-lang="zh-CN"] [data-lang="en"],
|
||||
body[data-report-lang="en"] [data-lang="zh-CN"] { display: none !important; }
|
||||
.skip-link {
|
||||
position: fixed;
|
||||
left: 18px;
|
||||
top: 10px;
|
||||
z-index: 40;
|
||||
transform: translateY(-140%);
|
||||
padding: 8px 12px;
|
||||
border-radius: 8px;
|
||||
background: var(--brand);
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
transition: transform 160ms cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
.skip-link:focus-visible { transform: translateY(0); outline: 2px solid var(--brand-mid); outline-offset: 2px; }
|
||||
.topbar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 20;
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
.progress-track {
|
||||
height: 2px;
|
||||
background: transparent;
|
||||
}
|
||||
.progress-bar {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--brand);
|
||||
transition: transform 160ms cubic-bezier(0.16, 1, 0.3, 1);
|
||||
transform-origin: left center;
|
||||
transform: scaleX(0);
|
||||
}
|
||||
.topbar-inner {
|
||||
max-width: 1240px;
|
||||
margin: 0 auto;
|
||||
padding: 9px 28px;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 18px;
|
||||
align-items: center;
|
||||
}
|
||||
.nav-shell {
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr);
|
||||
gap: 18px;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
}
|
||||
.report-mark {
|
||||
color: var(--brand);
|
||||
font-family: var(--mono);
|
||||
font-size: 11px;
|
||||
line-height: 1;
|
||||
text-transform: uppercase;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.report-nav {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none;
|
||||
min-width: 0;
|
||||
}
|
||||
.report-nav::-webkit-scrollbar { display: none; }
|
||||
.report-nav a {
|
||||
flex: 0 0 auto;
|
||||
min-width: 76px;
|
||||
min-height: 40px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 10px;
|
||||
color: var(--brand);
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
border-radius: 8px;
|
||||
white-space: nowrap;
|
||||
transition-property: background-color, color, transform;
|
||||
transition-duration: 160ms;
|
||||
transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
@media (hover: hover) {
|
||||
.report-nav a:hover { background: var(--brand-soft); }
|
||||
}
|
||||
.report-nav a:focus-visible {
|
||||
outline: 2px solid var(--brand-mid);
|
||||
outline-offset: 2px;
|
||||
background: var(--brand-soft);
|
||||
}
|
||||
.report-nav a[aria-current="true"] {
|
||||
background: var(--brand);
|
||||
color: #ffffff;
|
||||
}
|
||||
.report-nav a[aria-current="true"] span { color: #ffffff; }
|
||||
.language-switch {
|
||||
display: inline-flex;
|
||||
gap: 3px;
|
||||
padding: 3px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
background: var(--paper);
|
||||
box-shadow: 0 1px 2px rgba(27, 54, 93, 0.05);
|
||||
}
|
||||
.language-switch button {
|
||||
appearance: none;
|
||||
min-width: 42px;
|
||||
min-height: 34px;
|
||||
border: 0;
|
||||
border-radius: 6px;
|
||||
padding: 0 10px;
|
||||
background: transparent;
|
||||
color: var(--muted);
|
||||
font: inherit;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
transition-property: background-color, color, transform;
|
||||
transition-duration: 160ms;
|
||||
transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
|
||||
}
|
||||
.language-switch button:active { transform: scale(0.96); }
|
||||
.language-switch button:focus-visible { outline: 2px solid var(--brand-mid); outline-offset: 2px; }
|
||||
.language-switch button[aria-pressed="true"] {
|
||||
background: var(--brand-soft);
|
||||
color: var(--brand);
|
||||
}
|
||||
.wrap {
|
||||
max-width: 1240px;
|
||||
margin: 0 auto;
|
||||
padding: 58px 28px 92px;
|
||||
}
|
||||
.hero {
|
||||
padding: 16px 0 34px;
|
||||
}
|
||||
.hero-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) 360px;
|
||||
gap: 44px;
|
||||
align-items: end;
|
||||
}
|
||||
.eyebrow, .report-mark {
|
||||
letter-spacing: 0;
|
||||
}
|
||||
.eyebrow {
|
||||
margin: 0 0 12px;
|
||||
color: var(--brand);
|
||||
font-family: var(--mono);
|
||||
font-size: 12px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.slug {
|
||||
margin: 0 0 18px;
|
||||
color: var(--faint);
|
||||
font-family: var(--mono);
|
||||
font-size: 13px;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
h1, h2, h3 {
|
||||
margin: 0;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0;
|
||||
text-wrap: balance;
|
||||
}
|
||||
h1 {
|
||||
max-width: 8em;
|
||||
color: var(--ink);
|
||||
font-size: 4rem;
|
||||
line-height: 1.02;
|
||||
}
|
||||
.lead {
|
||||
max-width: 760px;
|
||||
margin: 20px 0 0;
|
||||
color: var(--text);
|
||||
font-size: 1.08rem;
|
||||
text-wrap: pretty;
|
||||
}
|
||||
.hero-meta, .badges {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.hero-meta span, .badges span, .tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 30px;
|
||||
padding: 5px 10px;
|
||||
border-radius: 6px;
|
||||
background: var(--brand-soft);
|
||||
color: var(--brand);
|
||||
font-size: 13px;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.hero-card {
|
||||
position: relative;
|
||||
padding: 22px 22px 24px;
|
||||
border-radius: 8px;
|
||||
background: linear-gradient(180deg, #ffffff 0%, #fbfaf7 100%);
|
||||
box-shadow: var(--shadow-soft);
|
||||
border: 1px solid var(--line-soft);
|
||||
}
|
||||
.hero-card::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 18px;
|
||||
right: 18px;
|
||||
width: 38px;
|
||||
height: 2px;
|
||||
background: var(--brand);
|
||||
}
|
||||
.score-strip {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 10px;
|
||||
margin-top: 32px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
.score-chip {
|
||||
padding: 14px 14px 12px;
|
||||
border-radius: 8px;
|
||||
background: var(--wash);
|
||||
border: 1px solid var(--line-soft);
|
||||
}
|
||||
.score-chip span {
|
||||
display: block;
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
}
|
||||
.score-chip strong {
|
||||
display: block;
|
||||
margin: 5px 0 8px;
|
||||
color: var(--brand);
|
||||
font-family: var(--mono);
|
||||
font-size: 1.65rem;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.score-chip i {
|
||||
display: block;
|
||||
height: 3px;
|
||||
border-radius: 999px;
|
||||
background: linear-gradient(90deg, var(--brand) var(--score), #dfe6ee var(--score));
|
||||
}
|
||||
.score-chip small {
|
||||
display: block;
|
||||
margin-top: 8px;
|
||||
color: var(--muted);
|
||||
font-size: 12px;
|
||||
line-height: 1.45;
|
||||
}
|
||||
section {
|
||||
scroll-margin-top: 78px;
|
||||
padding-top: 44px;
|
||||
margin-top: 44px;
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
section.hero {
|
||||
scroll-margin-top: 0;
|
||||
padding-top: 16px;
|
||||
margin-top: 0;
|
||||
border-top: 0;
|
||||
}
|
||||
.section-head {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 246px) minmax(0, 1fr);
|
||||
gap: 36px;
|
||||
align-items: start;
|
||||
}
|
||||
h2 {
|
||||
color: var(--ink);
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.18;
|
||||
}
|
||||
h2::before {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 32px;
|
||||
height: 2px;
|
||||
margin-bottom: 12px;
|
||||
background: var(--brand);
|
||||
}
|
||||
h3 {
|
||||
color: var(--ink);
|
||||
font-size: 1.02rem;
|
||||
line-height: 1.3;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.section-head p {
|
||||
margin: 12px 0 0;
|
||||
color: var(--muted);
|
||||
max-width: 43ch;
|
||||
text-wrap: pretty;
|
||||
}
|
||||
.two-col, .metric-grid, .chart-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
align-items: stretch;
|
||||
}
|
||||
.quality-panels {
|
||||
margin-top: 16px;
|
||||
}
|
||||
.metrics-stack {
|
||||
display: grid;
|
||||
gap: 18px;
|
||||
}
|
||||
.metrics-lead {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(420px, 1.15fr) minmax(300px, 0.85fr);
|
||||
gap: 18px;
|
||||
align-items: stretch;
|
||||
}
|
||||
.metrics-note {
|
||||
display: grid;
|
||||
align-content: start;
|
||||
gap: 16px;
|
||||
}
|
||||
.metrics-note p {
|
||||
margin: 0;
|
||||
max-width: none;
|
||||
color: var(--text);
|
||||
}
|
||||
.metric-summary-list {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
.metric-summary-list li {
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr) auto;
|
||||
gap: 8px 10px;
|
||||
align-items: baseline;
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid var(--line-soft);
|
||||
}
|
||||
.metric-summary-list li:last-child { border-bottom: 0; }
|
||||
.metric-summary-list b {
|
||||
color: var(--ink);
|
||||
font-weight: 500;
|
||||
}
|
||||
.metric-summary-list em {
|
||||
color: var(--brand);
|
||||
font-family: var(--mono);
|
||||
font-style: normal;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.metric-summary-list small {
|
||||
grid-column: 2 / 4;
|
||||
color: var(--muted);
|
||||
line-height: 1.5;
|
||||
}
|
||||
.metric-status {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 24px;
|
||||
padding: 2px 7px;
|
||||
border-radius: 6px;
|
||||
background: var(--brand-soft);
|
||||
color: var(--brand);
|
||||
font-size: 12px;
|
||||
}
|
||||
.metric-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
margin-top: 2px;
|
||||
}
|
||||
.list, .compact-list, .step-list {
|
||||
margin: 0;
|
||||
padding-left: 1.15em;
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}
|
||||
.list li::marker, .compact-list li::marker, .step-list li::marker { color: var(--brand); }
|
||||
.compact-list {
|
||||
gap: 6px;
|
||||
font-size: 13px;
|
||||
color: var(--muted);
|
||||
}
|
||||
.panel, .metric-card, .roadmap-item {
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line-soft);
|
||||
border-radius: 8px;
|
||||
padding: 22px;
|
||||
box-shadow: 0 1px 2px rgba(27, 54, 93, 0.04);
|
||||
}
|
||||
.metric-card {
|
||||
display: grid;
|
||||
grid-template-columns: 92px minmax(0, 1fr);
|
||||
gap: 18px;
|
||||
align-content: start;
|
||||
min-height: 0;
|
||||
}
|
||||
.metric-card-head {
|
||||
display: grid;
|
||||
align-content: start;
|
||||
}
|
||||
.metric-card strong {
|
||||
display: block;
|
||||
margin: 8px 0 10px;
|
||||
color: var(--brand);
|
||||
font-family: var(--mono);
|
||||
font-size: 2rem;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.metric-label {
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
}
|
||||
.metric-card-body {
|
||||
min-width: 0;
|
||||
}
|
||||
.chart-figure {
|
||||
margin: 0;
|
||||
padding: 18px;
|
||||
border: 1px solid var(--line-soft);
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
box-shadow: 0 1px 2px rgba(27, 54, 93, 0.04);
|
||||
}
|
||||
.chart-figure svg {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
overflow: visible;
|
||||
}
|
||||
.chart-figure text {
|
||||
fill: var(--ink);
|
||||
font-family: var(--serif);
|
||||
font-size: 13px;
|
||||
}
|
||||
.chart-title {
|
||||
fill: var(--brand);
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.chart-line {
|
||||
fill: none;
|
||||
stroke: var(--brand);
|
||||
stroke-width: 2;
|
||||
}
|
||||
figcaption {
|
||||
margin-top: 12px;
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid var(--line-soft);
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
text-wrap: pretty;
|
||||
}
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 14px;
|
||||
}
|
||||
th, td {
|
||||
padding: 12px 10px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid var(--line-soft);
|
||||
vertical-align: top;
|
||||
}
|
||||
th {
|
||||
color: var(--brand);
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
}
|
||||
td:first-child, th:first-child { width: 96px; }
|
||||
.roadmap {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
.step {
|
||||
display: inline-flex;
|
||||
margin-bottom: 12px;
|
||||
min-height: 28px;
|
||||
align-items: center;
|
||||
padding: 3px 8px;
|
||||
border-radius: 6px;
|
||||
background: var(--brand-soft);
|
||||
color: var(--brand);
|
||||
font-size: 12px;
|
||||
}
|
||||
.unlock {
|
||||
margin-top: 14px;
|
||||
color: var(--muted);
|
||||
font-size: 13px;
|
||||
}
|
||||
@media (max-width: 980px) {
|
||||
.topbar-inner {
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
padding: 8px 16px;
|
||||
}
|
||||
.nav-shell { grid-template-columns: 1fr; gap: 6px; }
|
||||
.report-mark { display: none; }
|
||||
.report-nav a { min-width: 72px; }
|
||||
.hero-grid, .section-head { grid-template-columns: 1fr; }
|
||||
.hero-grid { gap: 24px; }
|
||||
.score-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
.metrics-lead, .two-col, .metric-grid, .chart-grid, .roadmap { grid-template-columns: 1fr; }
|
||||
.metric-card { grid-template-columns: 86px minmax(0, 1fr); }
|
||||
h1 { font-size: 2.75rem; }
|
||||
}
|
||||
@media (max-width: 540px) {
|
||||
.wrap { padding: 34px 16px 72px; }
|
||||
.topbar-inner { gap: 10px; }
|
||||
.report-nav {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
}
|
||||
.report-nav a {
|
||||
min-width: 66px;
|
||||
min-height: 38px;
|
||||
padding: 0 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.language-switch button { min-width: 38px; min-height: 32px; padding: 0 8px; }
|
||||
.hero { padding-top: 8px; }
|
||||
h1 { max-width: 8em; font-size: 2.35rem; }
|
||||
.lead { font-size: 1rem; }
|
||||
.hero-meta span, .badges span { font-size: 12px; }
|
||||
.score-strip { grid-template-columns: 1fr; }
|
||||
section { margin-top: 34px; padding-top: 34px; }
|
||||
.panel, .metric-card, .roadmap-item, .chart-figure, .hero-card { padding: 18px; }
|
||||
.metric-card { grid-template-columns: 1fr; gap: 10px; }
|
||||
.metric-card strong { margin-bottom: 2px; }
|
||||
.metric-summary-list li { grid-template-columns: auto minmax(0, 1fr) auto; }
|
||||
table { font-size: 13px; }
|
||||
th, td { padding: 10px 7px; }
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
html { scroll-behavior: auto; }
|
||||
*, *::before, *::after { transition-duration: 0.01ms !important; }
|
||||
}
|
||||
""".strip()
|
||||
|
||||
|
||||
def skill_overview_script() -> str:
|
||||
return """
|
||||
(function () {
|
||||
var buttons = Array.prototype.slice.call(document.querySelectorAll("[data-set-lang]"));
|
||||
var navLinks = Array.prototype.slice.call(document.querySelectorAll(".report-nav a"));
|
||||
var sections = navLinks
|
||||
.map(function (link) { return document.querySelector(link.getAttribute("href")); })
|
||||
.filter(Boolean);
|
||||
var progressBar = document.querySelector(".progress-bar");
|
||||
function setLanguage(lang) {
|
||||
document.body.setAttribute("data-report-lang", lang);
|
||||
document.documentElement.setAttribute("lang", lang);
|
||||
buttons.forEach(function (button) {
|
||||
button.setAttribute("aria-pressed", button.getAttribute("data-set-lang") === lang ? "true" : "false");
|
||||
});
|
||||
}
|
||||
function updateProgress() {
|
||||
var scrollTop = window.scrollY || document.documentElement.scrollTop;
|
||||
var height = Math.max(1, document.documentElement.scrollHeight - window.innerHeight);
|
||||
var pct = Math.min(100, Math.max(0, (scrollTop / height) * 100));
|
||||
if (progressBar) progressBar.style.transform = "scaleX(" + pct / 100 + ")";
|
||||
var active = sections[0];
|
||||
sections.forEach(function (section) {
|
||||
if (section.getBoundingClientRect().top <= 110) active = section;
|
||||
});
|
||||
navLinks.forEach(function (link) {
|
||||
link.setAttribute("aria-current", link.getAttribute("href") === "#" + active.id ? "true" : "false");
|
||||
});
|
||||
}
|
||||
buttons.forEach(function (button) {
|
||||
button.addEventListener("click", function () {
|
||||
setLanguage(button.getAttribute("data-set-lang"));
|
||||
});
|
||||
});
|
||||
window.addEventListener("scroll", updateProgress, { passive: true });
|
||||
window.addEventListener("resize", updateProgress);
|
||||
setLanguage("zh-CN");
|
||||
updateProgress();
|
||||
})();
|
||||
""".strip()
|
||||
+14
-225
@@ -7,65 +7,29 @@ from pathlib import Path
|
||||
|
||||
from github_benchmark_scan import build_query
|
||||
from render_intent_confidence import assess_intent_confidence
|
||||
from yao_cli_config import (
|
||||
ARCHETYPE_MODE,
|
||||
archetype_guidance,
|
||||
baseline_compare_args,
|
||||
diagnose_skill_candidates,
|
||||
diagnosis_note,
|
||||
discovery_summary,
|
||||
infer_archetype,
|
||||
local_output_runner_command,
|
||||
recommendation_from_synthesis,
|
||||
reference_visibility,
|
||||
resolve_promotion_target,
|
||||
resolve_target,
|
||||
)
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
SCRIPTS = ROOT / "scripts"
|
||||
|
||||
TARGETS = {
|
||||
"root": {
|
||||
"description_file": ROOT / "SKILL.md",
|
||||
"baseline_description_file": ROOT / "evals" / "baseline_description.txt",
|
||||
"semantic_config": ROOT / "evals" / "semantic_config.json",
|
||||
"dev_cases": ROOT / "evals" / "dev" / "trigger_cases.json",
|
||||
"holdout_cases": ROOT / "evals" / "holdout" / "trigger_cases.json",
|
||||
"blind_holdout_cases": ROOT / "evals" / "blind_holdout" / "trigger_cases.json",
|
||||
"adversarial_cases": ROOT / "evals" / "adversarial" / "trigger_cases.json",
|
||||
"output_json": ROOT / "reports" / "description_optimization.json",
|
||||
"output_md": ROOT / "reports" / "description_optimization.md",
|
||||
"title": "Root Description Optimization",
|
||||
},
|
||||
"team-frontend-review": {
|
||||
"description_file": ROOT / "examples" / "team-frontend-review" / "generated-skill" / "SKILL.md",
|
||||
"baseline_description_file": ROOT / "examples" / "team-frontend-review" / "optimization" / "baseline_description.txt",
|
||||
"semantic_config": ROOT / "examples" / "team-frontend-review" / "optimization" / "semantic_config.json",
|
||||
"dev_cases": ROOT / "examples" / "team-frontend-review" / "optimization" / "dev" / "trigger_cases.json",
|
||||
"holdout_cases": ROOT / "examples" / "team-frontend-review" / "optimization" / "holdout" / "trigger_cases.json",
|
||||
"blind_holdout_cases": ROOT / "examples" / "team-frontend-review" / "optimization" / "blind_holdout" / "trigger_cases.json",
|
||||
"adversarial_cases": ROOT / "examples" / "team-frontend-review" / "optimization" / "adversarial" / "trigger_cases.json",
|
||||
"output_json": ROOT / "examples" / "team-frontend-review" / "optimization" / "reports" / "description_optimization.json",
|
||||
"output_md": ROOT / "examples" / "team-frontend-review" / "optimization" / "reports" / "description_optimization.md",
|
||||
"title": "Frontend Review Description Optimization",
|
||||
},
|
||||
"governed-incident-command": {
|
||||
"description_file": ROOT / "examples" / "governed-incident-command" / "generated-skill" / "SKILL.md",
|
||||
"baseline_description_file": ROOT / "examples" / "governed-incident-command" / "optimization" / "baseline_description.txt",
|
||||
"semantic_config": ROOT / "examples" / "governed-incident-command" / "optimization" / "semantic_config.json",
|
||||
"dev_cases": ROOT / "examples" / "governed-incident-command" / "optimization" / "dev" / "trigger_cases.json",
|
||||
"holdout_cases": ROOT / "examples" / "governed-incident-command" / "optimization" / "holdout" / "trigger_cases.json",
|
||||
"blind_holdout_cases": ROOT / "examples" / "governed-incident-command" / "optimization" / "blind_holdout" / "trigger_cases.json",
|
||||
"adversarial_cases": ROOT / "examples" / "governed-incident-command" / "optimization" / "adversarial" / "trigger_cases.json",
|
||||
"output_json": ROOT / "examples" / "governed-incident-command" / "optimization" / "reports" / "description_optimization.json",
|
||||
"output_md": ROOT / "examples" / "governed-incident-command" / "optimization" / "reports" / "description_optimization.md",
|
||||
"title": "Governed Incident Description Optimization",
|
||||
},
|
||||
}
|
||||
|
||||
PROMOTION_TARGETS = {
|
||||
"root": "yao-meta-skill",
|
||||
"team-frontend-review": "team-frontend-review",
|
||||
"governed-incident-command": "governed-incident-command",
|
||||
}
|
||||
|
||||
|
||||
def script_path(name: str) -> str:
|
||||
return str(SCRIPTS / name)
|
||||
|
||||
|
||||
def local_output_runner_command() -> str:
|
||||
return json.dumps(["python3", "scripts/local_output_eval_runner.py"])
|
||||
|
||||
|
||||
def load_json_maybe(text: str) -> dict | None:
|
||||
text = text.strip()
|
||||
if not text:
|
||||
@@ -94,33 +58,6 @@ def run_script(name: str, args: list[str], cwd: Path | None = None) -> dict:
|
||||
}
|
||||
|
||||
|
||||
def resolve_target(name: str) -> dict:
|
||||
if name not in TARGETS:
|
||||
raise KeyError(f"Unknown target: {name}")
|
||||
return TARGETS[name]
|
||||
|
||||
|
||||
def resolve_promotion_target(name: str) -> str:
|
||||
if name not in PROMOTION_TARGETS:
|
||||
raise KeyError(f"Unknown promotion target: {name}")
|
||||
return PROMOTION_TARGETS[name]
|
||||
|
||||
|
||||
def baseline_compare_args() -> list[str]:
|
||||
args = []
|
||||
for label, target in TARGETS.items():
|
||||
args.extend(["--entry", f"{label}::{target['output_json']}"])
|
||||
args.extend(
|
||||
[
|
||||
"--output-json",
|
||||
str(ROOT / "reports" / "baseline-compare.json"),
|
||||
"--output-md",
|
||||
str(ROOT / "reports" / "baseline-compare.md"),
|
||||
]
|
||||
)
|
||||
return args
|
||||
|
||||
|
||||
def prompt_with_default(label: str, default: str) -> str:
|
||||
sys.stderr.write(f"{label} [{default}]: ")
|
||||
sys.stderr.flush()
|
||||
@@ -165,154 +102,6 @@ def intent_confidence_note(summary: dict) -> str:
|
||||
return "\n".join(lines) + "\n"
|
||||
|
||||
|
||||
ARCHETYPE_MODE = {
|
||||
"scaffold": "scaffold",
|
||||
"production": "production",
|
||||
"library": "library",
|
||||
"governed": "governed",
|
||||
}
|
||||
|
||||
|
||||
def infer_archetype(job: str, description: str) -> tuple[str, str]:
|
||||
text = f"{job} {description}".lower()
|
||||
if any(token in text for token in ("incident", "compliance", "security", "release", "govern", "audit", "policy")):
|
||||
return "governed", "The request looks operationally sensitive, so governed is the safest default."
|
||||
if any(token in text for token in ("shared", "cross-team", "library", "portable", "platform", "reusable across")):
|
||||
return "library", "The request signals multi-team reuse or portability, so library is the better fit."
|
||||
if any(token in text for token in ("review", "checklist", "team", "workflow", "process", "standardize")):
|
||||
return "production", "The request looks team-reused and repeatable, so production fits better than scaffold."
|
||||
return "scaffold", "The request still looks exploratory or lightweight, so scaffold keeps the first package lean."
|
||||
|
||||
|
||||
def archetype_guidance(archetype: str) -> dict:
|
||||
mapping = {
|
||||
"scaffold": {
|
||||
"first_gate": "trigger and exclusions",
|
||||
"focus": "keep the first package small and avoid governance overhead",
|
||||
},
|
||||
"production": {
|
||||
"first_gate": "trigger plus one execution or eval asset",
|
||||
"focus": "make the package reliable for team reuse",
|
||||
},
|
||||
"library": {
|
||||
"first_gate": "trigger, portability, and packaging semantics",
|
||||
"focus": "treat the package as a shared capability with visible evidence",
|
||||
},
|
||||
"governed": {
|
||||
"first_gate": "trigger, governance, and review cadence",
|
||||
"focus": "treat the package as a high-trust asset from the start",
|
||||
},
|
||||
}
|
||||
return mapping.get(archetype, mapping["scaffold"])
|
||||
|
||||
|
||||
def discovery_summary(job: str, primary_output: str, archetype: str, guidance: dict) -> str:
|
||||
return (
|
||||
"\nHere's the shape I'm hearing so far:\n"
|
||||
f"- Repeated job: {job}\n"
|
||||
f"- Desired hand-back: {primary_output}\n"
|
||||
f"- Best starting archetype: {archetype}\n"
|
||||
f"- First gate: {guidance['first_gate']}\n"
|
||||
f"- Current focus: {guidance['focus']}\n"
|
||||
)
|
||||
|
||||
|
||||
def explicit_skill_request(job: str, description: str) -> bool:
|
||||
text = f"{job} {description}".lower()
|
||||
return any(token in text for token in ("skill", "workflow", "checklist", "package", "automate", "standardize"))
|
||||
|
||||
|
||||
def diagnose_skill_candidates(job: str, primary_output: str, archetype: str, confidence: dict) -> dict:
|
||||
fuzzy = not explicit_skill_request(job, primary_output) or confidence.get("score", 0) < 75
|
||||
candidates = [
|
||||
{
|
||||
"shape": archetype,
|
||||
"recommendation": "recommended",
|
||||
"why_it_fits": "This is the lightest shape that matches the current recurring job signal.",
|
||||
"limitation": "It should not deepen until the concrete output and exclusion boundary are clear.",
|
||||
"first_pass": "Create one routeable skill with honest boundaries, one review report, and one next-step direction.",
|
||||
}
|
||||
]
|
||||
if archetype != "scaffold":
|
||||
candidates.append(
|
||||
{
|
||||
"shape": "scaffold",
|
||||
"recommendation": "fallback",
|
||||
"why_it_fits": "Use this if the idea is still exploratory or personal.",
|
||||
"limitation": "It may under-serve team reuse, portability, or governance needs.",
|
||||
"first_pass": "Ship only SKILL.md, interface metadata, intent confidence, and review viewer.",
|
||||
}
|
||||
)
|
||||
if archetype not in {"production", "governed"}:
|
||||
candidates.append(
|
||||
{
|
||||
"shape": "production",
|
||||
"recommendation": "upgrade path",
|
||||
"why_it_fits": "Use this when the workflow will be repeated by a team or needs consistent outputs.",
|
||||
"limitation": "It adds validation and review cost that a personal scaffold may not need.",
|
||||
"first_pass": "Add one practical eval or execution check after the trigger boundary is stable.",
|
||||
}
|
||||
)
|
||||
if archetype != "governed" and any(token in f"{job} {primary_output}".lower() for token in ("risk", "audit", "release", "policy", "security", "compliance")):
|
||||
candidates.append(
|
||||
{
|
||||
"shape": "governed",
|
||||
"recommendation": "risk path",
|
||||
"why_it_fits": "Use this if the skill affects operational, compliance, security, or release decisions.",
|
||||
"limitation": "It is too heavy unless ownership and review cadence are real.",
|
||||
"first_pass": "Add owner, review cadence, lifecycle metadata, and reviewer-visible evidence.",
|
||||
}
|
||||
)
|
||||
return {
|
||||
"mode": "fuzzy-problem-diagnosis" if fuzzy else "direct-skill-shaping",
|
||||
"fuzzy": fuzzy,
|
||||
"candidates": candidates[:3],
|
||||
}
|
||||
|
||||
|
||||
def diagnosis_note(diagnosis: dict) -> str:
|
||||
lines = ["\nProblem-to-skill diagnosis:"]
|
||||
for candidate in diagnosis["candidates"]:
|
||||
lines.append(
|
||||
f"- {candidate['shape']} ({candidate['recommendation']}): {candidate['why_it_fits']} "
|
||||
f"First pass: {candidate['first_pass']}"
|
||||
)
|
||||
return "\n".join(lines) + "\n"
|
||||
|
||||
|
||||
def reference_visibility(reference_synthesis: dict) -> dict:
|
||||
synthesis = reference_synthesis.get("synthesis", {}) if isinstance(reference_synthesis, dict) else {}
|
||||
visibility = synthesis.get("visibility", {}) if isinstance(synthesis, dict) else {}
|
||||
reasons = list(visibility.get("reasons", []))
|
||||
mode = visibility.get("mode", "explicit" if reasons else "silent")
|
||||
return {
|
||||
"mode": mode,
|
||||
"user_decision_required": mode == "explicit",
|
||||
"reasons": reasons,
|
||||
"conflicts": synthesis.get("conflicts", []),
|
||||
}
|
||||
|
||||
|
||||
def recommendation_from_synthesis(reference_synthesis: dict, visibility: dict) -> dict:
|
||||
synthesis = reference_synthesis.get("synthesis", {}) if isinstance(reference_synthesis, dict) else {}
|
||||
recommendation = synthesis.get("recommendation", {}) if isinstance(synthesis, dict) else {}
|
||||
borrow_now = recommendation.get("borrow_now") or synthesis.get("borrow_now", [])
|
||||
avoid_now = recommendation.get("avoid_for_now") or synthesis.get("avoid_now", [])
|
||||
summary = recommendation.get("summary") or (
|
||||
f"Start with {borrow_now[0]} Avoid {avoid_now[0]} for the first pass."
|
||||
if borrow_now and avoid_now
|
||||
else "Start with the smallest high-confidence pattern and keep the first pass light."
|
||||
)
|
||||
why = recommendation.get("why") or "This recommendation comes from the benchmark synthesis and current intent confidence."
|
||||
return {
|
||||
"summary": summary,
|
||||
"borrow_now": borrow_now[:2],
|
||||
"avoid_for_now": avoid_now[:2],
|
||||
"why": why,
|
||||
"user_decision_required": visibility["user_decision_required"],
|
||||
}
|
||||
|
||||
|
||||
def maybe_emit_update_notice(args: argparse.Namespace) -> None:
|
||||
if getattr(args, "no_update_check", False):
|
||||
return
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Pure configuration and shaping helpers for the Yao CLI."""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
SCRIPT_INTERFACE = "internal-module"
|
||||
SCRIPT_INTERFACE_REASON = "Imported by yao.py for CLI target maps and side-effect-free shaping helpers."
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
|
||||
TARGETS = {
|
||||
"root": {
|
||||
"description_file": ROOT / "SKILL.md",
|
||||
"baseline_description_file": ROOT / "evals" / "baseline_description.txt",
|
||||
"semantic_config": ROOT / "evals" / "semantic_config.json",
|
||||
"dev_cases": ROOT / "evals" / "dev" / "trigger_cases.json",
|
||||
"holdout_cases": ROOT / "evals" / "holdout" / "trigger_cases.json",
|
||||
"blind_holdout_cases": ROOT / "evals" / "blind_holdout" / "trigger_cases.json",
|
||||
"adversarial_cases": ROOT / "evals" / "adversarial" / "trigger_cases.json",
|
||||
"output_json": ROOT / "reports" / "description_optimization.json",
|
||||
"output_md": ROOT / "reports" / "description_optimization.md",
|
||||
"title": "Root Description Optimization",
|
||||
},
|
||||
"team-frontend-review": {
|
||||
"description_file": ROOT / "examples" / "team-frontend-review" / "generated-skill" / "SKILL.md",
|
||||
"baseline_description_file": ROOT / "examples" / "team-frontend-review" / "optimization" / "baseline_description.txt",
|
||||
"semantic_config": ROOT / "examples" / "team-frontend-review" / "optimization" / "semantic_config.json",
|
||||
"dev_cases": ROOT / "examples" / "team-frontend-review" / "optimization" / "dev" / "trigger_cases.json",
|
||||
"holdout_cases": ROOT / "examples" / "team-frontend-review" / "optimization" / "holdout" / "trigger_cases.json",
|
||||
"blind_holdout_cases": ROOT / "examples" / "team-frontend-review" / "optimization" / "blind_holdout" / "trigger_cases.json",
|
||||
"adversarial_cases": ROOT / "examples" / "team-frontend-review" / "optimization" / "adversarial" / "trigger_cases.json",
|
||||
"output_json": ROOT / "examples" / "team-frontend-review" / "optimization" / "reports" / "description_optimization.json",
|
||||
"output_md": ROOT / "examples" / "team-frontend-review" / "optimization" / "reports" / "description_optimization.md",
|
||||
"title": "Frontend Review Description Optimization",
|
||||
},
|
||||
"governed-incident-command": {
|
||||
"description_file": ROOT / "examples" / "governed-incident-command" / "generated-skill" / "SKILL.md",
|
||||
"baseline_description_file": ROOT / "examples" / "governed-incident-command" / "optimization" / "baseline_description.txt",
|
||||
"semantic_config": ROOT / "examples" / "governed-incident-command" / "optimization" / "semantic_config.json",
|
||||
"dev_cases": ROOT / "examples" / "governed-incident-command" / "optimization" / "dev" / "trigger_cases.json",
|
||||
"holdout_cases": ROOT / "examples" / "governed-incident-command" / "optimization" / "holdout" / "trigger_cases.json",
|
||||
"blind_holdout_cases": ROOT / "examples" / "governed-incident-command" / "optimization" / "blind_holdout" / "trigger_cases.json",
|
||||
"adversarial_cases": ROOT / "examples" / "governed-incident-command" / "optimization" / "adversarial" / "trigger_cases.json",
|
||||
"output_json": ROOT / "examples" / "governed-incident-command" / "optimization" / "reports" / "description_optimization.json",
|
||||
"output_md": ROOT / "examples" / "governed-incident-command" / "optimization" / "reports" / "description_optimization.md",
|
||||
"title": "Governed Incident Description Optimization",
|
||||
},
|
||||
}
|
||||
|
||||
PROMOTION_TARGETS = {
|
||||
"root": "yao-meta-skill",
|
||||
"team-frontend-review": "team-frontend-review",
|
||||
"governed-incident-command": "governed-incident-command",
|
||||
}
|
||||
|
||||
ARCHETYPE_MODE = {
|
||||
"scaffold": "scaffold",
|
||||
"production": "production",
|
||||
"library": "library",
|
||||
"governed": "governed",
|
||||
}
|
||||
|
||||
|
||||
def local_output_runner_command() -> str:
|
||||
return json.dumps(["python3", "scripts/local_output_eval_runner.py"])
|
||||
|
||||
|
||||
def resolve_target(name: str) -> dict:
|
||||
if name not in TARGETS:
|
||||
raise KeyError(f"Unknown target: {name}")
|
||||
return TARGETS[name]
|
||||
|
||||
|
||||
def resolve_promotion_target(name: str) -> str:
|
||||
if name not in PROMOTION_TARGETS:
|
||||
raise KeyError(f"Unknown promotion target: {name}")
|
||||
return PROMOTION_TARGETS[name]
|
||||
|
||||
|
||||
def baseline_compare_args() -> list[str]:
|
||||
args = []
|
||||
for label, target in TARGETS.items():
|
||||
args.extend(["--entry", f"{label}::{target['output_json']}"])
|
||||
args.extend(
|
||||
[
|
||||
"--output-json",
|
||||
str(ROOT / "reports" / "baseline-compare.json"),
|
||||
"--output-md",
|
||||
str(ROOT / "reports" / "baseline-compare.md"),
|
||||
]
|
||||
)
|
||||
return args
|
||||
|
||||
|
||||
def infer_archetype(job: str, description: str) -> tuple[str, str]:
|
||||
text = f"{job} {description}".lower()
|
||||
if any(token in text for token in ("incident", "compliance", "security", "release", "govern", "audit", "policy")):
|
||||
return "governed", "The request looks operationally sensitive, so governed is the safest default."
|
||||
if any(token in text for token in ("shared", "cross-team", "library", "portable", "platform", "reusable across")):
|
||||
return "library", "The request signals multi-team reuse or portability, so library is the better fit."
|
||||
if any(token in text for token in ("review", "checklist", "team", "workflow", "process", "standardize")):
|
||||
return "production", "The request looks team-reused and repeatable, so production fits better than scaffold."
|
||||
return "scaffold", "The request still looks exploratory or lightweight, so scaffold keeps the first package lean."
|
||||
|
||||
|
||||
def archetype_guidance(archetype: str) -> dict:
|
||||
mapping = {
|
||||
"scaffold": {
|
||||
"first_gate": "trigger and exclusions",
|
||||
"focus": "keep the first package small and avoid governance overhead",
|
||||
},
|
||||
"production": {
|
||||
"first_gate": "trigger plus one execution or eval asset",
|
||||
"focus": "make the package reliable for team reuse",
|
||||
},
|
||||
"library": {
|
||||
"first_gate": "trigger, portability, and packaging semantics",
|
||||
"focus": "treat the package as a shared capability with visible evidence",
|
||||
},
|
||||
"governed": {
|
||||
"first_gate": "trigger, governance, and review cadence",
|
||||
"focus": "treat the package as a high-trust asset from the start",
|
||||
},
|
||||
}
|
||||
return mapping.get(archetype, mapping["scaffold"])
|
||||
|
||||
|
||||
def discovery_summary(job: str, primary_output: str, archetype: str, guidance: dict) -> str:
|
||||
return (
|
||||
"\nHere's the shape I'm hearing so far:\n"
|
||||
f"- Repeated job: {job}\n"
|
||||
f"- Desired hand-back: {primary_output}\n"
|
||||
f"- Best starting archetype: {archetype}\n"
|
||||
f"- First gate: {guidance['first_gate']}\n"
|
||||
f"- Current focus: {guidance['focus']}\n"
|
||||
)
|
||||
|
||||
|
||||
def explicit_skill_request(job: str, description: str) -> bool:
|
||||
text = f"{job} {description}".lower()
|
||||
return any(token in text for token in ("skill", "workflow", "checklist", "package", "automate", "standardize"))
|
||||
|
||||
|
||||
def diagnose_skill_candidates(job: str, primary_output: str, archetype: str, confidence: dict) -> dict:
|
||||
fuzzy = not explicit_skill_request(job, primary_output) or confidence.get("score", 0) < 75
|
||||
candidates = [
|
||||
{
|
||||
"shape": archetype,
|
||||
"recommendation": "recommended",
|
||||
"why_it_fits": "This is the lightest shape that matches the current recurring job signal.",
|
||||
"limitation": "It should not deepen until the concrete output and exclusion boundary are clear.",
|
||||
"first_pass": "Create one routeable skill with honest boundaries, one review report, and one next-step direction.",
|
||||
}
|
||||
]
|
||||
if archetype != "scaffold":
|
||||
candidates.append(
|
||||
{
|
||||
"shape": "scaffold",
|
||||
"recommendation": "fallback",
|
||||
"why_it_fits": "Use this if the idea is still exploratory or personal.",
|
||||
"limitation": "It may under-serve team reuse, portability, or governance needs.",
|
||||
"first_pass": "Ship only SKILL.md, interface metadata, intent confidence, and review viewer.",
|
||||
}
|
||||
)
|
||||
if archetype not in {"production", "governed"}:
|
||||
candidates.append(
|
||||
{
|
||||
"shape": "production",
|
||||
"recommendation": "upgrade path",
|
||||
"why_it_fits": "Use this when the workflow will be repeated by a team or needs consistent outputs.",
|
||||
"limitation": "It adds validation and review cost that a personal scaffold may not need.",
|
||||
"first_pass": "Add one practical eval or execution check after the trigger boundary is stable.",
|
||||
}
|
||||
)
|
||||
if archetype != "governed" and any(token in f"{job} {primary_output}".lower() for token in ("risk", "audit", "release", "policy", "security", "compliance")):
|
||||
candidates.append(
|
||||
{
|
||||
"shape": "governed",
|
||||
"recommendation": "risk path",
|
||||
"why_it_fits": "Use this if the skill affects operational, compliance, security, or release decisions.",
|
||||
"limitation": "It is too heavy unless ownership and review cadence are real.",
|
||||
"first_pass": "Add owner, review cadence, lifecycle metadata, and reviewer-visible evidence.",
|
||||
}
|
||||
)
|
||||
return {
|
||||
"mode": "fuzzy-problem-diagnosis" if fuzzy else "direct-skill-shaping",
|
||||
"fuzzy": fuzzy,
|
||||
"candidates": candidates[:3],
|
||||
}
|
||||
|
||||
|
||||
def diagnosis_note(diagnosis: dict) -> str:
|
||||
lines = ["\nProblem-to-skill diagnosis:"]
|
||||
for candidate in diagnosis["candidates"]:
|
||||
lines.append(
|
||||
f"- {candidate['shape']} ({candidate['recommendation']}): {candidate['why_it_fits']} "
|
||||
f"First pass: {candidate['first_pass']}"
|
||||
)
|
||||
return "\n".join(lines) + "\n"
|
||||
|
||||
|
||||
def reference_visibility(reference_synthesis: dict) -> dict:
|
||||
synthesis = reference_synthesis.get("synthesis", {}) if isinstance(reference_synthesis, dict) else {}
|
||||
visibility = synthesis.get("visibility", {}) if isinstance(synthesis, dict) else {}
|
||||
reasons = list(visibility.get("reasons", []))
|
||||
mode = visibility.get("mode", "explicit" if reasons else "silent")
|
||||
return {
|
||||
"mode": mode,
|
||||
"user_decision_required": mode == "explicit",
|
||||
"reasons": reasons,
|
||||
"conflicts": synthesis.get("conflicts", []),
|
||||
}
|
||||
|
||||
|
||||
def recommendation_from_synthesis(reference_synthesis: dict, visibility: dict) -> dict:
|
||||
synthesis = reference_synthesis.get("synthesis", {}) if isinstance(reference_synthesis, dict) else {}
|
||||
recommendation = synthesis.get("recommendation", {}) if isinstance(synthesis, dict) else {}
|
||||
borrow_now = recommendation.get("borrow_now") or synthesis.get("borrow_now", [])
|
||||
avoid_now = recommendation.get("avoid_for_now") or synthesis.get("avoid_now", [])
|
||||
summary = recommendation.get("summary") or (
|
||||
f"Start with {borrow_now[0]} Avoid {avoid_now[0]} for the first pass."
|
||||
if borrow_now and avoid_now
|
||||
else "Start with the smallest high-confidence pattern and keep the first pass light."
|
||||
)
|
||||
why = recommendation.get("why") or "This recommendation comes from the benchmark synthesis and current intent confidence."
|
||||
return {
|
||||
"summary": summary,
|
||||
"borrow_now": borrow_now[:2],
|
||||
"avoid_for_now": avoid_now[:2],
|
||||
"why": why,
|
||||
"user_decision_required": visibility["user_decision_required"],
|
||||
}
|
||||
@@ -154,6 +154,8 @@
|
||||
"scripts/render_social_preview.py",
|
||||
"scripts/render_system_model.py",
|
||||
"scripts/resource_boundary_check.py",
|
||||
"scripts/review_studio_formatting.py",
|
||||
"scripts/review_studio_layout.py",
|
||||
"scripts/run_conformance_suite.py",
|
||||
"scripts/run_description_optimization_suite.py",
|
||||
"scripts/run_eval_suite.py",
|
||||
@@ -161,6 +163,7 @@
|
||||
"scripts/run_output_execution.py",
|
||||
"scripts/simulate_install.py",
|
||||
"scripts/skill_report_charts.py",
|
||||
"scripts/skill_report_layout.py",
|
||||
"scripts/skill_report_metrics.py",
|
||||
"scripts/skill_report_model.py",
|
||||
"scripts/sync_local_install.py",
|
||||
@@ -169,7 +172,8 @@
|
||||
"scripts/upgrade_check.py",
|
||||
"scripts/validate_skill.py",
|
||||
"scripts/verify_package.py",
|
||||
"scripts/yao.py"
|
||||
"scripts/yao.py",
|
||||
"scripts/yao_cli_config.py"
|
||||
],
|
||||
"assets": [
|
||||
"templates/basic_skill.md.j2",
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
"scripts/render_social_preview.py",
|
||||
"scripts/render_system_model.py",
|
||||
"scripts/resource_boundary_check.py",
|
||||
"scripts/review_studio_formatting.py",
|
||||
"scripts/review_studio_layout.py",
|
||||
"scripts/run_conformance_suite.py",
|
||||
"scripts/run_description_optimization_suite.py",
|
||||
"scripts/run_eval_suite.py",
|
||||
@@ -72,6 +74,7 @@
|
||||
"scripts/run_output_execution.py",
|
||||
"scripts/simulate_install.py",
|
||||
"scripts/skill_report_charts.py",
|
||||
"scripts/skill_report_layout.py",
|
||||
"scripts/skill_report_metrics.py",
|
||||
"scripts/skill_report_model.py",
|
||||
"scripts/sync_local_install.py",
|
||||
@@ -81,6 +84,7 @@
|
||||
"scripts/validate_skill.py",
|
||||
"scripts/verify_package.py",
|
||||
"scripts/yao.py",
|
||||
"scripts/yao_cli_config.py",
|
||||
"references/artifact-design-doctrine.md",
|
||||
"references/authoring-discipline.md",
|
||||
"references/distribution-registry-method.md",
|
||||
|
||||
@@ -10,6 +10,8 @@ ROOT = Path(__file__).resolve().parent.parent
|
||||
SCRIPT = ROOT / "scripts" / "render_review_studio.py"
|
||||
sys.path.insert(0, str(ROOT / "scripts"))
|
||||
import render_review_studio as review_studio # noqa: E402
|
||||
import review_studio_formatting as review_formatting # noqa: E402
|
||||
import review_studio_layout as review_layout # noqa: E402
|
||||
|
||||
|
||||
def main() -> None:
|
||||
@@ -353,9 +355,30 @@ def main() -> None:
|
||||
assert "人工批准" in html, html[:8200]
|
||||
assert "权限批准" in html, html[:9000]
|
||||
assert "权限探针" in html, html[:9500]
|
||||
assert "kv-grid" in html, html
|
||||
assert "案例数" in html, html
|
||||
assert "命令执行" in html, html
|
||||
assert "包体哈希" in html, html
|
||||
assert "{'" not in html, html
|
||||
assert "'case_count'" not in html, html
|
||||
assert "'name'" not in html, html
|
||||
assert "reports/review_waivers.md" in output_json.read_text(encoding="utf-8"), output_json
|
||||
assert "upgrade minor declared / minor recommended" in html, html[:8000]
|
||||
assert str(ROOT) not in output_json.read_text(encoding="utf-8"), output_json
|
||||
formatted = review_formatting.render_kv_grid(
|
||||
{"case_count": 5, "package_sha256": "abc123"},
|
||||
["case_count", "package_sha256"],
|
||||
"missing",
|
||||
)
|
||||
assert "kv-grid" in formatted, formatted
|
||||
assert "案例数" in formatted, formatted
|
||||
assert "<code>abc123</code>" in formatted, formatted
|
||||
assert review_formatting.value_text({"case_count": 5}) == "案例数: 5"
|
||||
assert len(review_layout.REVIEW_STUDIO_NAV) == 15, review_layout.REVIEW_STUDIO_NAV
|
||||
assert "position: sticky" in review_layout.review_studio_css(), review_layout.review_studio_css()[:400]
|
||||
assert "#overview" in review_layout.render_review_nav(), review_layout.render_review_nav()
|
||||
assert "审查总览" in review_layout.render_review_nav(), review_layout.render_review_nav()
|
||||
assert review_layout.render_review_nav([]) == ""
|
||||
print(json.dumps({"ok": True}, ensure_ascii=False, indent=2))
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,10 @@ from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
CLI = ROOT / "scripts" / "yao.py"
|
||||
sys.path.insert(0, str(ROOT / "scripts"))
|
||||
|
||||
from skill_report_layout import render_language_switch, render_report_nav, skill_overview_css, skill_overview_script
|
||||
from skill_report_model import REPORT_NAV_V2
|
||||
|
||||
|
||||
def run(*args: str) -> dict:
|
||||
@@ -26,6 +30,30 @@ def run(*args: str) -> dict:
|
||||
|
||||
|
||||
def main() -> None:
|
||||
nav_contract = render_report_nav(REPORT_NAV_V2)
|
||||
assert nav_contract.count("<a ") == 9, nav_contract
|
||||
assert '#overview' in nav_contract, nav_contract
|
||||
assert ">技能概述</span>" in nav_contract, nav_contract
|
||||
assert ">Overview</span>" in nav_contract, nav_contract
|
||||
assert render_report_nav([]) == ""
|
||||
|
||||
language_switch_contract = render_language_switch()
|
||||
assert 'data-set-lang="zh-CN"' in language_switch_contract, language_switch_contract
|
||||
assert 'data-set-lang="en"' in language_switch_contract, language_switch_contract
|
||||
assert 'aria-pressed="true"' in language_switch_contract, language_switch_contract
|
||||
|
||||
css_contract = skill_overview_css()
|
||||
assert "position: sticky" in css_contract, css_contract[:1200]
|
||||
assert ".report-nav {" in css_contract, css_contract[:3200]
|
||||
assert "background: #ffffff" in css_contract, css_contract[:1600]
|
||||
assert ".metrics-lead" in css_contract, css_contract[:7000]
|
||||
assert "@media (max-width: 980px)" in css_contract, css_contract[-2200:]
|
||||
|
||||
script_contract = skill_overview_script()
|
||||
assert 'setLanguage("zh-CN")' in script_contract, script_contract[-1000:]
|
||||
assert "scaleX(" in script_contract, script_contract
|
||||
assert "aria-current" in script_contract, script_contract
|
||||
|
||||
tmp_root = ROOT / "tests" / "tmp_skill_overview"
|
||||
if tmp_root.exists():
|
||||
subprocess.run(["rm", "-rf", str(tmp_root)], check=True)
|
||||
|
||||
@@ -87,16 +87,24 @@ def main() -> None:
|
||||
assert "scripts/github_benchmark_scan.py" in payload["network_policy"]["covered_scripts"], payload["network_policy"]
|
||||
script_map = {item["path"]: item for item in payload["scripts"]}
|
||||
for internal_module in [
|
||||
"scripts/review_studio_formatting.py",
|
||||
"scripts/review_studio_layout.py",
|
||||
"scripts/skill_report_charts.py",
|
||||
"scripts/skill_report_layout.py",
|
||||
"scripts/skill_report_metrics.py",
|
||||
"scripts/skill_report_model.py",
|
||||
"scripts/yao_cli_config.py",
|
||||
]:
|
||||
assert script_map[internal_module]["interface"] == "internal-module", script_map[internal_module]
|
||||
assert script_map[internal_module]["interface_declared"], script_map[internal_module]
|
||||
warning_text = "\n".join(payload["warnings"])
|
||||
assert "review_studio_formatting.py" not in warning_text, payload["warnings"]
|
||||
assert "review_studio_layout.py" not in warning_text, payload["warnings"]
|
||||
assert "skill_report_charts.py" not in warning_text, payload["warnings"]
|
||||
assert "skill_report_layout.py" not in warning_text, payload["warnings"]
|
||||
assert "skill_report_metrics.py" not in warning_text, payload["warnings"]
|
||||
assert "skill_report_model.py" not in warning_text, payload["warnings"]
|
||||
assert "yao_cli_config.py" not in warning_text, payload["warnings"]
|
||||
assert "render_context_reports.py" not in warning_text, payload["warnings"]
|
||||
assert "render_social_preview.py" not in warning_text, payload["warnings"]
|
||||
assert "Network-capable scripts require bounded host policy" not in warning_text, payload["warnings"]
|
||||
|
||||
@@ -9,6 +9,8 @@ from pathlib import Path
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
CLI = ROOT / "scripts" / "yao.py"
|
||||
BENCHMARK_FIXTURE_DIR = ROOT / "tests" / "fixtures" / "github_benchmark_scan"
|
||||
sys.path.insert(0, str(ROOT / "scripts"))
|
||||
import yao_cli_config # noqa: E402
|
||||
|
||||
|
||||
def run(*args: str, input_text: str | None = None) -> dict:
|
||||
@@ -36,6 +38,11 @@ def main() -> None:
|
||||
tmp_root.mkdir(parents=True, exist_ok=True)
|
||||
remote_version = tmp_root / "remote-version.txt"
|
||||
remote_version.write_text("9.9.9\n", encoding="utf-8")
|
||||
assert yao_cli_config.resolve_target("root")["title"] == "Root Description Optimization"
|
||||
assert yao_cli_config.resolve_promotion_target("root") == "yao-meta-skill"
|
||||
assert yao_cli_config.infer_archetype("Standardize team review workflow.", "")[0] == "production"
|
||||
assert yao_cli_config.infer_archetype("Govern release policy.", "")[0] == "governed"
|
||||
assert "--entry" in yao_cli_config.baseline_compare_args()
|
||||
|
||||
init_result = run("init", "cli-demo-skill", "--description", "CLI demo skill.", "--output-dir", str(tmp_root))
|
||||
assert init_result["ok"], init_result
|
||||
|
||||
Reference in New Issue
Block a user