@event4u/agent-config 7.5.0 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +8 -1
- package/AGENTS.md +9 -9
- package/CHANGELOG.md +325 -0
- package/README.md +35 -5
- package/dist/agent-src/commands/analytics/prune.md +1 -1
- package/dist/agent-src/commands/analytics/show.md +1 -1
- package/dist/agent-src/commands/analyze/decision.md +2 -2
- package/dist/agent-src/commands/analyze/incident.md +2 -2
- package/dist/agent-src/commands/analyze/near-miss.md +2 -2
- package/dist/agent-src/commands/analyze/postmortem.md +2 -2
- package/dist/agent-src/commands/analyze/premortem.md +2 -2
- package/dist/agent-src/commands/cost-report.md +25 -0
- package/dist/agent-src/commands/evals/analyze.json +30 -0
- package/dist/agent-src/commands/evals/mission-upgrade.json +30 -0
- package/dist/agent-src/commands/implement-ticket.md +1 -1
- package/dist/agent-src/commands/knowledge/forget.md +1 -1
- package/dist/agent-src/commands/knowledge/ingest.md +1 -1
- package/dist/agent-src/commands/knowledge/list.md +1 -1
- package/dist/agent-src/commands/memory/load.md +12 -11
- package/dist/agent-src/commands/memory/promote.md +30 -0
- package/dist/agent-src/commands/memory/propose.md +16 -2
- package/dist/agent-src/commands/mission/upgrade.md +1 -1
- package/dist/agent-src/commands/module/explore.md +11 -7
- package/dist/agent-src/commands/optimize-project.md +243 -0
- package/dist/agent-src/commands/optimize.md +5 -0
- package/dist/agent-src/commands/pr/create.md +37 -8
- package/dist/agent-src/commands/prediction-pool.md +2 -2
- package/dist/agent-src/commands/profile/activate.md +3 -3
- package/dist/agent-src/commands/profile/deactivate.md +2 -2
- package/dist/agent-src/commands/profile/show.md +3 -3
- package/dist/agent-src/commands/research/deep.md +5 -0
- package/dist/agent-src/commands/research/report.md +2 -1
- package/dist/agent-src/commands/roadmap/create.md +88 -10
- package/dist/agent-src/commands/roadmap/materialize.md +1 -1
- package/dist/agent-src/commands/roadmap/process-full.md +15 -2
- package/dist/agent-src/commands/roadmap/process-phase.md +18 -6
- package/dist/agent-src/commands/roadmap/process-step.md +4 -0
- package/dist/agent-src/commands/roadmap.md +1 -1
- package/dist/agent-src/commands/security-audit-config.md +1 -1
- package/dist/agent-src/commands/sync-agent-settings.md +1 -1
- package/dist/agent-src/commands/sync-gitignore/fix.md +42 -6
- package/dist/agent-src/commands/team-knowledge/bootstrap.md +106 -0
- package/dist/agent-src/commands/team-knowledge/consolidate.md +105 -0
- package/dist/agent-src/commands/team-knowledge.md +64 -0
- package/dist/agent-src/contexts/authority/commit-mechanics.md +8 -0
- package/dist/agent-src/contexts/authority/destructive-mechanics.md +11 -0
- package/dist/agent-src/contexts/authority/scope-mechanics.md +25 -0
- package/dist/agent-src/contexts/communication/rules-auto/reply-close-mechanics.md +43 -0
- package/dist/agent-src/contexts/contracts/agents-md-anatomy.md +1 -1
- package/dist/agent-src/contexts/contracts/artifact-engagement-flow.md +2 -2
- package/dist/agent-src/contexts/contracts/frugality-charter.md +1 -0
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +14 -4
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +11 -0
- package/dist/agent-src/contexts/execution/orchestration-telemetry.md +32 -8
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +107 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +71 -15
- package/dist/agent-src/contexts/execution/subagent-steering.md +41 -1
- package/dist/agent-src/contexts/override-system.md +1 -1
- package/dist/agent-src/personas/brand-strategist.md +0 -1
- package/dist/agent-src/personas/data-integrity.md +66 -0
- package/dist/agent-src/personas/design-director.md +0 -1
- package/dist/agent-src/personas/performance-engineer.md +66 -0
- package/dist/agent-src/personas/production-validator.md +73 -0
- package/dist/agent-src/rules/agent-authority.md +3 -4
- package/dist/agent-src/rules/analysis-skill-routing.md +3 -5
- package/dist/agent-src/rules/architecture.md +2 -4
- package/dist/agent-src/rules/artifact-drafting-protocol.md +35 -6
- package/dist/agent-src/rules/artifact-engagement-recording.md +2 -4
- package/dist/agent-src/rules/ask-when-uncertain.md +10 -14
- package/dist/agent-src/rules/augment-edit-discipline.md +3 -5
- package/dist/agent-src/rules/autonomous-execution.md +3 -5
- package/dist/agent-src/rules/brand-consistency.md +3 -5
- package/dist/agent-src/rules/brand-source-of-truth.md +3 -5
- package/dist/agent-src/rules/cli-output-handling.md +4 -6
- package/dist/agent-src/rules/command-suggestion-policy.md +3 -5
- package/dist/agent-src/rules/commit-conventions.md +3 -5
- package/dist/agent-src/rules/commit-policy.md +8 -10
- package/dist/agent-src/rules/content-quoting-floor.md +88 -0
- package/dist/agent-src/rules/context-hygiene.md +3 -5
- package/dist/agent-src/rules/copilot-routing.md +4 -6
- package/dist/agent-src/rules/decision-revisit-gate.md +120 -0
- package/dist/agent-src/rules/delegation-policy.md +10 -6
- package/dist/agent-src/rules/design-fidelity.md +3 -5
- package/dist/agent-src/rules/devcontainer-routing.md +4 -6
- package/dist/agent-src/rules/direct-answers.md +13 -17
- package/dist/agent-src/rules/docker-commands.md +3 -5
- package/dist/agent-src/rules/domain-adoption-policy.md +3 -5
- package/dist/agent-src/rules/domain-safety-disclaimer.md +3 -5
- package/dist/agent-src/rules/domain-safety-pii.md +3 -5
- package/dist/agent-src/rules/domain-safety-retention.md +3 -5
- package/dist/agent-src/rules/downstream-changes.md +3 -4
- package/dist/agent-src/rules/engineering-safety-floor.md +3 -5
- package/dist/agent-src/rules/external-reference-deep-dive.md +3 -5
- package/dist/agent-src/rules/fast-path-marker-visibility.md +3 -5
- package/dist/agent-src/rules/finance-safety-floor.md +3 -6
- package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +3 -5
- package/dist/agent-src/rules/git-history-discipline.md +3 -5
- package/dist/agent-src/rules/guidelines.md +2 -4
- package/dist/agent-src/rules/icon-consistency.md +3 -5
- package/dist/agent-src/rules/image-likeness-and-rights.md +3 -5
- package/dist/agent-src/rules/improve-before-implement.md +5 -5
- package/dist/agent-src/rules/invite-challenge.md +3 -5
- package/dist/agent-src/rules/language-and-tone.md +13 -15
- package/dist/agent-src/rules/laravel-routing.md +3 -5
- package/dist/agent-src/rules/laravel-translations.md +3 -5
- package/dist/agent-src/rules/legal-safety-floor.md +3 -5
- package/dist/agent-src/rules/lethal-trifecta-guard.md +3 -5
- package/dist/agent-src/rules/linked-projects-onboarding-gate.md +4 -7
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +3 -5
- package/dist/agent-src/rules/markdown-safe-codeblocks.md +2 -4
- package/dist/agent-src/rules/media-governance-routing.md +3 -5
- package/dist/agent-src/rules/media-sync-ground-truth.md +3 -5
- package/dist/agent-src/rules/minimal-safe-diff.md +5 -5
- package/dist/agent-src/rules/missing-tool-handling.md +3 -5
- package/dist/agent-src/rules/model-recommendation.md +4 -6
- package/dist/agent-src/rules/no-attribution-footers.md +3 -5
- package/dist/agent-src/rules/no-cheap-questions.md +5 -8
- package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +3 -6
- package/dist/agent-src/rules/no-pr-progress-comments.md +3 -6
- package/dist/agent-src/rules/no-roadmap-references.md +3 -5
- package/dist/agent-src/rules/non-destructive-by-default.md +11 -13
- package/dist/agent-src/rules/notes-first-reasoning.md +3 -5
- package/dist/agent-src/rules/onboarding-gate.md +4 -6
- package/dist/agent-src/rules/output-discipline.md +3 -5
- package/dist/agent-src/rules/package-ci-checks.md +3 -5
- package/dist/agent-src/rules/persona-governance.md +2 -4
- package/dist/agent-src/rules/php-coding.md +3 -5
- package/dist/agent-src/rules/preservation-guard.md +2 -4
- package/dist/agent-src/rules/provider-lifecycle-discipline.md +3 -5
- package/dist/agent-src/rules/reviewer-awareness.md +5 -6
- package/dist/agent-src/rules/roadmap-ci-steps-policy.md +3 -5
- package/dist/agent-src/rules/roadmap-progress-sync.md +5 -5
- package/dist/agent-src/rules/role-mode-adherence.md +2 -4
- package/dist/agent-src/rules/rule-type-governance.md +3 -5
- package/dist/agent-src/rules/runtime-safety.md +2 -4
- package/dist/agent-src/rules/scope-control.md +10 -11
- package/dist/agent-src/rules/security-sensitive-stop.md +4 -5
- package/dist/agent-src/rules/size-enforcement.md +2 -4
- package/dist/agent-src/rules/skill-improvement-trigger.md +3 -5
- package/dist/agent-src/rules/skill-quality.md +3 -5
- package/dist/agent-src/rules/slash-command-routing-policy.md +3 -5
- package/dist/agent-src/rules/source-confidentiality.md +3 -5
- package/dist/agent-src/rules/source-discovery-gate.md +3 -5
- package/dist/agent-src/rules/source-of-truth.md +3 -5
- package/dist/agent-src/rules/strategy-safety-floor.md +3 -5
- package/dist/agent-src/rules/symfony-routing.md +4 -6
- package/dist/agent-src/rules/telegraph-speak.md +4 -5
- package/dist/agent-src/rules/think-before-action.md +7 -4
- package/dist/agent-src/rules/token-budget-discipline.md +29 -5
- package/dist/agent-src/rules/token-efficiency.md +3 -5
- package/dist/agent-src/rules/token-optimizer-maintenance.md +3 -5
- package/dist/agent-src/rules/tool-safety.md +2 -4
- package/dist/agent-src/rules/ui-audit-gate.md +3 -6
- package/dist/agent-src/rules/untrusted-input-defense.md +3 -5
- package/dist/agent-src/rules/upstream-proposal.md +4 -6
- package/dist/agent-src/rules/user-interaction.md +7 -5
- package/dist/agent-src/rules/user-interrupt-priority.md +17 -8
- package/dist/agent-src/rules/verify-before-complete.md +12 -22
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +3 -3
- package/dist/agent-src/scripts/update_roadmap_progress.ts +197 -7
- package/dist/agent-src/skills/adr-create/SKILL.md +48 -42
- package/dist/agent-src/skills/agent-docs-writing/SKILL.md +18 -0
- package/dist/agent-src/skills/agent-security-review/SKILL.md +1 -1
- package/dist/agent-src/skills/ai-council/SKILL.md +14 -1
- package/dist/agent-src/skills/blameless-post-mortem/SKILL.md +0 -3
- package/dist/agent-src/skills/brand/SKILL.md +1 -1
- package/dist/agent-src/skills/brand-identity/SKILL.md +3 -3
- package/dist/agent-src/skills/brand-strategy/SKILL.md +1 -1
- package/dist/agent-src/skills/brand-to-tokens/SKILL.md +3 -3
- package/dist/agent-src/skills/canvas-design/SKILL.md +6 -0
- package/dist/agent-src/skills/check-refs/SKILL.md +7 -4
- package/dist/agent-src/skills/code-review/SKILL.md +1 -0
- package/dist/agent-src/skills/complexity-first-planning/SKILL.md +6 -5
- package/dist/agent-src/skills/condense-memory/SKILL.md +11 -11
- package/dist/agent-src/skills/context-document/SKILL.md +17 -0
- package/dist/agent-src/skills/corpus-grounding/SKILL.md +3 -3
- package/dist/agent-src/skills/decision-record/SKILL.md +6 -0
- package/dist/agent-src/skills/decision-review/SKILL.md +5 -3
- package/dist/agent-src/skills/deep-reading-analyst/SKILL.md +6 -1
- package/dist/agent-src/skills/design-intelligence/SKILL.md +5 -2
- package/dist/agent-src/skills/design-intelligence/references/design-languages.md +1 -1
- package/dist/agent-src/skills/design-tokens/SKILL.md +10 -4
- package/dist/agent-src/skills/design-variations/SKILL.md +127 -0
- package/dist/agent-src/skills/design-variations/evals/triggers.json +17 -0
- package/dist/agent-src/skills/emit-tickets/SKILL.md +4 -4
- package/dist/agent-src/skills/fe-design/SKILL.md +20 -0
- package/dist/agent-src/skills/html-deck/SKILL.md +123 -0
- package/dist/agent-src/skills/html-deck/evals/triggers.json +17 -0
- package/dist/agent-src/skills/html-deck/templates/deck-shell.html +77 -0
- package/dist/agent-src/skills/judge-code-quality/SKILL.md +1 -0
- package/dist/agent-src/skills/laravel/SKILL.md +0 -1
- package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +46 -0
- package/dist/agent-src/skills/lint-skills/SKILL.md +6 -6
- package/dist/agent-src/skills/md-language-check/SKILL.md +3 -3
- package/dist/agent-src/skills/memory-consolidation/SKILL.md +66 -1
- package/dist/agent-src/skills/migration-architect/SKILL.md +1 -0
- package/dist/agent-src/skills/module-detect-on-the-fly/SKILL.md +2 -2
- package/dist/agent-src/skills/performance-analysis/SKILL.md +2 -0
- package/dist/agent-src/skills/prediction-pool-optimizer/SKILL.md +4 -4
- package/dist/agent-src/skills/premortem/SKILL.md +0 -3
- package/dist/agent-src/skills/project-analysis-core/SKILL.md +16 -0
- package/dist/agent-src/skills/reasoning-orchestrator/SKILL.md +3 -1
- package/dist/agent-src/skills/release-comms/SKILL.md +46 -45
- package/dist/agent-src/skills/roadmap-management/SKILL.md +21 -0
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +32 -2
- package/dist/agent-src/skills/root-cause-frameworks/SKILL.md +0 -3
- package/dist/agent-src/skills/security-audit/SKILL.md +1 -0
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +4 -0
- package/dist/agent-src/skills/source-discovery/SKILL.md +22 -3
- package/dist/agent-src/skills/subagent-orchestration/SKILL.md +33 -14
- package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +11 -0
- package/dist/agent-src/skills/subagent-orchestration/prompts/do-in-steps.md +8 -0
- package/dist/agent-src/skills/systematic-debugging/SKILL.md +29 -0
- package/dist/agent-src/skills/threat-modeling/SKILL.md +2 -2
- package/dist/agent-src/skills/typography-system/SKILL.md +2 -2
- package/dist/agent-src/skills/verify-completion-evidence/SKILL.md +2 -0
- package/dist/agent-src/skills/wireframe/SKILL.md +118 -0
- package/dist/agent-src/skills/wireframe/evals/triggers.json +17 -0
- package/dist/agent-src/templates/agent-settings.md +22 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/command.md +2 -2
- package/dist/agent-src/templates/contexts/knowledge-pages.md +116 -0
- package/dist/agent-src/templates/hooks/pre-commit-frontmatter +1 -1
- package/dist/agent-src/templates/roadmaps.md +70 -2
- package/dist/agent-src/templates/rule.md +1 -1
- package/dist/agent-src/templates/scripts/README.md +3 -3
- package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +109 -0
- package/dist/agent-src/templates/tickets.md +8 -8
- package/dist/cli/commands/recordTriggerEval.test.js +1 -1
- package/dist/cli/commands/recordTriggerEval.test.js.map +1 -1
- package/dist/cli/initRouting.js +4 -2
- package/dist/cli/initRouting.js.map +1 -1
- package/dist/cli/registry.js +1 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +718 -240
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +8 -8
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +43 -28
- package/dist/discovery/trust-report.md +12 -11
- package/dist/discovery/workspaces.json +29 -18
- package/dist/install/preflight.js +173 -0
- package/dist/install/preflight.js.map +1 -0
- package/dist/mcp/registry-manifest.json +4 -4
- package/dist/router.json +1 -1
- package/dist/server/routes/settings.js +4 -0
- package/dist/server/routes/settings.js.map +1 -1
- package/dist/server/schemas/settings.js +3 -1
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/CLAIMS.md +108 -0
- package/docs/MIGRATION.md +3 -3
- package/docs/architecture.md +5 -5
- package/docs/benchmark.md +133 -2
- package/docs/benchmark.pinned.yml +31 -0
- package/docs/capability-matrix.md +1 -0
- package/docs/catalog.md +70 -60
- package/docs/command-flows.md +15 -3
- package/docs/comparison.yaml +35 -0
- package/docs/contracts/agents-layout.md +148 -0
- package/docs/contracts/brand-token-consumption.md +5 -0
- package/docs/contracts/capability-boundary.md +5 -0
- package/docs/contracts/command-category-governance.md +5 -0
- package/docs/contracts/command-clusters.md +1 -0
- package/docs/contracts/command-surface-tiers.md +1 -1
- package/docs/contracts/conformance.md +84 -0
- package/docs/contracts/creative-pack-boundary.md +5 -0
- package/docs/contracts/discovery-manifest.schema.json +5 -4
- package/docs/contracts/file-ownership-matrix.json +4605 -985
- package/docs/contracts/governance-enforcement-projection.md +5 -0
- package/docs/contracts/gui-wizard.md +1 -1
- package/docs/contracts/hook-architecture-v1.md +2 -2
- package/docs/contracts/implement-ticket-flow.md +1 -1
- package/docs/contracts/kernel-membership.md +13 -0
- package/docs/contracts/mcp-tool-inventory.md +23 -23
- package/docs/contracts/no-runtime-boundary.md +6 -1
- package/docs/contracts/review-lens-schema.md +5 -0
- package/docs/contracts/rule-router.md +102 -8
- package/docs/contracts/skill-bundled-assets.md +1 -1
- package/docs/contracts/skill-dry-run.md +1 -1
- package/docs/contracts/subagent-boundary.md +5 -0
- package/docs/contracts/ticket-bundle-format.md +9 -4
- package/docs/contracts/tier-3-contrib-plugin.md +2 -2
- package/docs/contracts/write-engine.md +3 -0
- package/docs/customization.md +87 -15
- package/docs/decisions/ADR-107-legal-domain-pack-adoption.md +1 -1
- package/docs/decisions/ADR-109-subagent-v1-contract.md +246 -0
- package/docs/decisions/ADR-110-discipline-profile-resolution-locus.md +105 -0
- package/docs/decisions/INDEX.md +2 -0
- package/docs/distribution/awesome-list-submission.md +46 -0
- package/docs/distribution/launch-story-draft.md +58 -0
- package/docs/end-to-end-walkthroughs.md +2 -2
- package/docs/getting-started.md +2 -2
- package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +24 -0
- package/docs/guidelines/agent-infra/corpus-grounding-authoring.md +1 -1
- package/docs/guidelines/agent-infra/linked-projects-onboarding-gate.md +2 -2
- package/docs/guidelines/agent-infra/missing-tool-handling.md +3 -3
- package/docs/guidelines/agent-infra/verify-before-complete-demos.md +2 -2
- package/docs/guidelines/augment-portability-patterns.md +1 -1
- package/docs/guidelines/code-clarity.md +19 -0
- package/docs/guidelines/design-antipatterns-triggers.json +2 -1
- package/docs/guidelines/design-antipatterns.md +10 -1
- package/docs/guidelines/design-modes.md +6 -0
- package/docs/guidelines/php/general.md +9 -1
- package/docs/guidelines/php/php-coding-patterns.md +7 -0
- package/docs/guides/cross-repo-retrieval.md +1 -1
- package/docs/guides/frontend-design-corpus-refresh.md +2 -2
- package/docs/guides/local-analytics.md +4 -4
- package/docs/guides/skill-discovery.md +1 -1
- package/docs/guides/skill-preview.md +1 -1
- package/docs/hook-payload-capture.md +6 -6
- package/docs/install-friction-report.md +66 -0
- package/docs/installation.md +1 -1
- package/docs/maintainers/optional-media-deps.md +50 -0
- package/docs/mcp-server.md +11 -12
- package/docs/media/proof-demo.cast +14 -0
- package/docs/media/proof-demo.gif +0 -0
- package/docs/migration/consumer-template-consumption-model.md +1 -1
- package/docs/migration/divergences/bench-stats-float-precision.md +1 -1
- package/docs/migration/node-floor.md +1 -1
- package/docs/migration/yaml-roundtrip-spike.md +1 -1
- package/docs/personas.md +16 -5
- package/docs/positioning-evidence.md +86 -0
- package/docs/proof.md +86 -0
- package/docs/skills-catalog.md +1 -1
- package/docs/troubleshooting.md +8 -8
- package/docs/wedge/production-validator/README.md +57 -0
- package/docs/wedge/production-validator/production-validator.md +56 -0
- package/docs/wizard.md +2 -2
- package/package.json +1 -1
- package/src/config/agent-settings.template.yml +59 -4
- package/src/config/agents-paths.yml +254 -0
- package/src/config/budgets.yml +16 -0
- package/src/config/discovery/packs.yml +1 -0
- package/src/config/discovery/unassigned-artefacts.yml +2 -0
- package/src/config/gitignore-block.txt +25 -0
- package/src/config/host-capabilities.yml +31 -0
- package/src/config/profiles/balanced.ini +4 -0
- package/src/config/profiles/full.ini +4 -0
- package/src/config/profiles/minimal.ini +4 -0
- package/src/scripts/_cli/cmd_conformance.ts +716 -0
- package/src/scripts/_cli/cmd_doctor.ts +23 -2
- package/src/scripts/_cli/cmd_fleet.ts +401 -0
- package/src/scripts/_cli/cmd_preflight.ts +159 -0
- package/src/scripts/_dispatch.bash +10 -0
- package/src/scripts/_lib/knowledge_events.ts +193 -0
- package/src/scripts/_lib/subagent_steering.ts +115 -3
- package/src/scripts/_lib/text_similarity.ts +75 -0
- package/src/scripts/ai-video/test-pipeline.sh +1 -1
- package/src/scripts/ai_council/clients.ts +19 -3
- package/src/scripts/append_contested.ts +112 -0
- package/src/scripts/audit_auto_rules.ts +11 -1
- package/src/scripts/audit_mcp_tools.ts +25 -11
- package/src/scripts/bench_ab_v2_run.ts +527 -40
- package/src/scripts/bench_ab_v2_stats.ts +6 -0
- package/src/scripts/bench_matrix.ts +266 -0
- package/src/scripts/bootstrap_knowledge.ts +267 -0
- package/src/scripts/build_discovery_manifest.ts +42 -2
- package/src/scripts/build_proof.ts +214 -0
- package/src/scripts/check_always_budget.ts +3 -0
- package/src/scripts/check_augment_description_cap.ts +2 -2
- package/src/scripts/check_claims.ts +270 -0
- package/src/scripts/check_comparison.ts +79 -0
- package/src/scripts/check_generated_artefact_headers.ts +109 -0
- package/src/scripts/check_generator_output_coverage.ts +142 -0
- package/src/scripts/check_gitignore_freshness.ts +127 -0
- package/src/scripts/check_knowledge_pages.ts +210 -0
- package/src/scripts/check_knowledge_sharing.ts +162 -0
- package/src/scripts/check_media_deps.ts +91 -0
- package/src/scripts/check_memory_contradiction.ts +280 -0
- package/src/scripts/check_memory_similarity.ts +134 -0
- package/src/scripts/check_quality_regression.ts +56 -10
- package/src/scripts/check_references.ts +3 -1
- package/src/scripts/check_release_pr_shape.ts +4 -0
- package/src/scripts/check_site_links.ts +135 -0
- package/src/scripts/check_skill_gaps.ts +99 -0
- package/src/scripts/check_token_quality_golden.ts +197 -11
- package/src/scripts/check_tracked_but_ignored.ts +67 -0
- package/src/scripts/cluster_near_miss_patterns.ts +0 -0
- package/src/scripts/compile_router.ts +30 -3
- package/src/scripts/condense.ts +350 -14
- package/src/scripts/consolidate_knowledge_events.ts +192 -0
- package/src/scripts/degrade_to_pointer.ts +136 -0
- package/src/scripts/design_slop_rules.test.ts +15 -0
- package/src/scripts/design_slop_rules.ts +28 -0
- package/src/scripts/emit_knowledge_event.ts +158 -0
- package/src/scripts/export_replay_corpus.ts +187 -0
- package/src/scripts/external_sources_denylist.json +7 -2
- package/src/scripts/fold_intake.ts +281 -0
- package/src/scripts/generate_capability_matrix.ts +9 -1
- package/src/scripts/generate_knowledge_index.ts +222 -0
- package/src/scripts/hook_manifest.yaml +26 -14
- package/src/scripts/hooks/dispatch_hook.ts +18 -0
- package/src/scripts/hot_context_hook.ts +372 -0
- package/src/scripts/install +47 -0
- package/src/scripts/install-hooks.sh +17 -0
- package/src/scripts/inventory_meta_layers.ts +11 -0
- package/src/scripts/janitor.ts +258 -0
- package/src/scripts/lint_agents_layout.ts +74 -15
- package/src/scripts/lint_bench_ab.ts +4 -1
- package/src/scripts/lint_featured_skills.ts +0 -0
- package/src/scripts/lint_framework_leakage_allowlist.json +26 -3
- package/src/scripts/lint_knowledge_scale.ts +250 -0
- package/src/scripts/lint_legal_pack.ts +67 -0
- package/src/scripts/lint_persona_governance.ts +8 -3
- package/src/scripts/lint_regression.ts +15 -0
- package/src/scripts/lint_roadmap_blockers.ts +202 -0
- package/src/scripts/lint_roadmap_complexity.ts +81 -2
- package/src/scripts/lint_subagent_determinism.ts +125 -0
- package/src/scripts/measure_augment_budget.ts +46 -6
- package/src/scripts/measure_patterns.ts +4 -3
- package/src/scripts/measure_skill_reduction.ts +6 -6
- package/src/scripts/migration_status.ts +6 -2
- package/src/scripts/mine_missing_guardrails.ts +189 -0
- package/src/scripts/parity/phase_gate.ts +1 -1
- package/src/scripts/parity/replay.ts +21 -0
- package/src/scripts/project_thin_rules.ts +120 -16
- package/src/scripts/release.ts +39 -1
- package/src/scripts/render_benchmark_composite.ts +378 -0
- package/src/scripts/roadmap_progress_hook.ts +101 -43
- package/src/scripts/schemas/skill.schema.json +27 -0
- package/src/scripts/schemas/subagent.schema.json +106 -0
- package/src/scripts/skill_linter.ts +1 -0
- package/src/scripts/smoke/kernel.sh +5 -4
- package/src/scripts/surface-tiers.yml +1 -0
- package/src/scripts/sync_gitignore.ts +4 -0
- package/src/scripts/update_skill_candidates.ts +172 -0
- package/src/scripts/validate_frontmatter.ts +1 -0
|
@@ -33,8 +33,17 @@
|
|
|
33
33
|
* ./scripts-run src/scripts/check_quality_regression # gate (inert w/o run data)
|
|
34
34
|
* ./scripts-run src/scripts/check_quality_regression --json
|
|
35
35
|
* ./scripts-run src/scripts/check_quality_regression --threshold 0.48
|
|
36
|
+
* ./scripts-run src/scripts/check_quality_regression --as-flip-gate
|
|
36
37
|
*
|
|
37
|
-
*
|
|
38
|
+
* Flip-gate hardening (token-proof-and-story Phase 0):
|
|
39
|
+
* - A report with `dry_run: true` is NEVER an unlock — exit 2 in every mode.
|
|
40
|
+
* A mock report must not be indistinguishable from a pass in a script chain.
|
|
41
|
+
* - `--as-flip-gate` (used by the falsification checklist / the thin/scoped
|
|
42
|
+
* flip decision): "no report" and "no decisive pairs — inconclusive" are
|
|
43
|
+
* NOT unlocks → exit 2. Without the flag the CI-inert path keeps exit 0.
|
|
44
|
+
*
|
|
45
|
+
* Exit codes: 0 ok / inert · 1 file error · 2 quality regression, dry-run
|
|
46
|
+
* report, or (under --as-flip-gate) missing/inconclusive report.
|
|
38
47
|
*/
|
|
39
48
|
import * as fs from 'node:fs';
|
|
40
49
|
import * as path from 'node:path';
|
|
@@ -166,16 +175,27 @@ export function gateVerdict(agg: QualityAggregate): 0 | 2 {
|
|
|
166
175
|
|
|
167
176
|
interface RunReport {
|
|
168
177
|
threshold?: number;
|
|
178
|
+
dry_run?: boolean;
|
|
169
179
|
results?: PairResult[];
|
|
170
180
|
}
|
|
171
181
|
|
|
172
182
|
function main(argv: string[]): number {
|
|
173
183
|
let asJson = false;
|
|
184
|
+
let asFlipGate = false;
|
|
174
185
|
let threshold = DEFAULT_THRESHOLD;
|
|
186
|
+
let reportPath = RUN_REPORT;
|
|
175
187
|
for (let i = 0; i < argv.length; i += 1) {
|
|
176
188
|
const a = argv[i];
|
|
177
189
|
if (a === '--json') asJson = true;
|
|
178
|
-
else if (a === '--
|
|
190
|
+
else if (a === '--as-flip-gate') asFlipGate = true;
|
|
191
|
+
else if (a === '--report') {
|
|
192
|
+
const v = argv[(i += 1)];
|
|
193
|
+
if (!v) {
|
|
194
|
+
process.stderr.write('error: --report requires a path\n');
|
|
195
|
+
return 1;
|
|
196
|
+
}
|
|
197
|
+
reportPath = path.resolve(v);
|
|
198
|
+
} else if (a === '--threshold') {
|
|
179
199
|
const v = Number(argv[(i += 1)]);
|
|
180
200
|
if (!Number.isFinite(v) || v < 0 || v > 1) {
|
|
181
201
|
process.stderr.write('error: --threshold must be in [0,1]\n');
|
|
@@ -183,7 +203,9 @@ function main(argv: string[]): number {
|
|
|
183
203
|
}
|
|
184
204
|
threshold = v;
|
|
185
205
|
} else if (a === '-h' || a === '--help') {
|
|
186
|
-
process.stdout.write(
|
|
206
|
+
process.stdout.write(
|
|
207
|
+
'usage: check_quality_regression [--json] [--threshold F] [--as-flip-gate] [--report PATH]\n',
|
|
208
|
+
);
|
|
187
209
|
return 0;
|
|
188
210
|
} else {
|
|
189
211
|
process.stderr.write(`error: unknown argument: ${a}\n`);
|
|
@@ -191,9 +213,17 @@ function main(argv: string[]): number {
|
|
|
191
213
|
}
|
|
192
214
|
}
|
|
193
215
|
|
|
194
|
-
if (!fs.existsSync(
|
|
216
|
+
if (!fs.existsSync(reportPath)) {
|
|
217
|
+
if (asFlipGate) {
|
|
218
|
+
const msg =
|
|
219
|
+
`❌ flip gate: no quality-run report (${path.relative(REPO_ROOT, reportPath)}) — ` +
|
|
220
|
+
'a flip requires a real judge run. NOT an unlock.';
|
|
221
|
+
if (asJson) process.stdout.write(JSON.stringify({ verdict: 'no-data', flip_gate: true, unlock: false }, null, 2) + '\n');
|
|
222
|
+
else process.stdout.write(msg + '\n');
|
|
223
|
+
return 2;
|
|
224
|
+
}
|
|
195
225
|
const msg =
|
|
196
|
-
`⚠️ no quality-run report (${path.relative(REPO_ROOT,
|
|
226
|
+
`⚠️ no quality-run report (${path.relative(REPO_ROOT, reportPath)}) — ` +
|
|
197
227
|
'gate inert. Produce it with a thin-vs-eager judge run (operator/cost gate).';
|
|
198
228
|
if (asJson) process.stdout.write(JSON.stringify({ verdict: 'no-data', inert: true }, null, 2) + '\n');
|
|
199
229
|
else process.stdout.write(msg + '\n');
|
|
@@ -202,17 +232,27 @@ function main(argv: string[]): number {
|
|
|
202
232
|
|
|
203
233
|
let report: RunReport;
|
|
204
234
|
try {
|
|
205
|
-
report = JSON.parse(fs.readFileSync(
|
|
235
|
+
report = JSON.parse(fs.readFileSync(reportPath, 'utf-8')) as RunReport;
|
|
206
236
|
} catch (e) {
|
|
207
|
-
process.stderr.write(`error: cannot parse ${path.relative(REPO_ROOT,
|
|
237
|
+
process.stderr.write(`error: cannot parse ${path.relative(REPO_ROOT, reportPath)}: ${(e as Error).message}\n`);
|
|
208
238
|
return 1;
|
|
209
239
|
}
|
|
240
|
+
|
|
241
|
+
if (report.dry_run === true) {
|
|
242
|
+
const msg =
|
|
243
|
+
'❌ quality-run report is a DRY-RUN mock (`dry_run: true`) — a mock is never an unlock.\n' +
|
|
244
|
+
' Re-run the judge live (bench_quality_run without --dry-run) or delete the mock report.';
|
|
245
|
+
if (asJson) process.stdout.write(JSON.stringify({ verdict: 'dry-run', unlock: false }, null, 2) + '\n');
|
|
246
|
+
else process.stdout.write(msg + '\n');
|
|
247
|
+
return 2;
|
|
248
|
+
}
|
|
249
|
+
|
|
210
250
|
const results = Array.isArray(report.results) ? report.results : [];
|
|
211
251
|
const thr = typeof report.threshold === 'number' ? report.threshold : threshold;
|
|
212
252
|
const agg = aggregate(results, thr);
|
|
213
253
|
|
|
214
254
|
if (asJson) {
|
|
215
|
-
process.stdout.write(JSON.stringify({ ...agg, threshold: thr }, null, 2) + '\n');
|
|
255
|
+
process.stdout.write(JSON.stringify({ ...agg, threshold: thr, flip_gate: asFlipGate }, null, 2) + '\n');
|
|
216
256
|
} else {
|
|
217
257
|
process.stdout.write(
|
|
218
258
|
`quality run: ${agg.total} pairs · thin ${agg.thin_wins} / eager ${agg.eager_wins} / ` +
|
|
@@ -225,12 +265,18 @@ function main(argv: string[]): number {
|
|
|
225
265
|
if (agg.verdict === 'regression') {
|
|
226
266
|
process.stdout.write(`❌ quality regression: thin win-rate below ${(thr * 100).toFixed(0)}%.\n`);
|
|
227
267
|
} else if (agg.verdict === 'no-data') {
|
|
228
|
-
|
|
268
|
+
if (asFlipGate) {
|
|
269
|
+
process.stdout.write(`❌ flip gate: no decisive pairs — inconclusive is NOT an unlock.\n`);
|
|
270
|
+
} else {
|
|
271
|
+
process.stdout.write(`⚠️ no decisive pairs — inconclusive.\n`);
|
|
272
|
+
}
|
|
229
273
|
} else {
|
|
230
274
|
process.stdout.write(`✅ quality held: thin win-rate within tolerance.\n`);
|
|
231
275
|
}
|
|
232
276
|
}
|
|
233
|
-
|
|
277
|
+
const code = gateVerdict(agg);
|
|
278
|
+
if (code === 0 && asFlipGate && agg.verdict === 'no-data') return 2;
|
|
279
|
+
return code;
|
|
234
280
|
}
|
|
235
281
|
|
|
236
282
|
const _IS_MAIN =
|
|
@@ -58,7 +58,8 @@ const SKIP_DIRS = [
|
|
|
58
58
|
'agents/reports', // transient run reports — historical/scratch refs, not stable artefacts
|
|
59
59
|
'agents/roadmaps/skipped', // skipped roadmaps — abandoned plans w/ forward-refs that never shipped
|
|
60
60
|
'agents/runtime', // volatile / machine-generated artefacts (gitignored)
|
|
61
|
-
'agents/tmp', //
|
|
61
|
+
'agents/tmp', // user inbox (gitignored) — user-dropped notes/todos; agents only read + move to tmp.old/
|
|
62
|
+
'agents/tmp.old', // processed inbox archive (gitignored) — consumed tmp/ files; janitor TTL 30 days
|
|
62
63
|
'agents/.harvest-local', // deliberate gitignored evidence store (source-confidentiality) — refs to it can never resolve in CI
|
|
63
64
|
];
|
|
64
65
|
|
|
@@ -167,6 +168,7 @@ const EXAMPLE_PATH_PATTERNS: RegExp[] = [
|
|
|
167
168
|
/agents\/ownership-map\.yml/, // consumer-project routing data
|
|
168
169
|
/agents\/historical-bug-patterns\.yml/, // consumer-project routing data
|
|
169
170
|
/agents\/memory\//, // consumer-project memory data
|
|
171
|
+
/agents\/knowledge\//, // consumer-project knowledge cards + typed pages (road-to-knowledge-system)
|
|
170
172
|
/agents\/learnings\//, // consumer-project learning notes
|
|
171
173
|
/agents\/proposals\//, // consumer-project self-improvement proposals
|
|
172
174
|
/agents\/drafts\//, // consumer-project artefact drafts
|
|
@@ -31,6 +31,10 @@ const ALLOWLIST_GLOBS = [
|
|
|
31
31
|
'src/domains/*/pack.yaml',
|
|
32
32
|
'src/domains/*/README.md',
|
|
33
33
|
'docs/archive/CHANGELOG-pre-*.md',
|
|
34
|
+
// Project-settings template pin — bumped by release.ts set_template_pin and
|
|
35
|
+
// its regenerated dist twin (kept in lockstep with package.json.version).
|
|
36
|
+
'src/agent-src/templates/agents/agent-project-settings.example.yml',
|
|
37
|
+
'dist/agent-src/templates/agents/agent-project-settings.example.yml',
|
|
34
38
|
] as const;
|
|
35
39
|
|
|
36
40
|
/**
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* B4 — CI link-checker for the built Starlight site (no new dependency).
|
|
4
|
+
*
|
|
5
|
+
* Astro `build` completes even with dangling internal links, so a plain build is
|
|
6
|
+
* NOT a link gate. This scans the built `site/dist/**` HTML for internal links
|
|
7
|
+
* (`href` / `src`) and verifies every one resolves to a real file in `dist/` —
|
|
8
|
+
* accounting for the `base` prefix (`/agent-config`), trailing-slash dirs
|
|
9
|
+
* (`…/x/` → `…/x/index.html`), and `#fragment` / `?query` stripping. External
|
|
10
|
+
* (`http(s):`, `mailto:`, `data:`, protocol-relative `//`) links and pure `#`
|
|
11
|
+
* anchors are skipped — this gate owns *internal* integrity only.
|
|
12
|
+
*
|
|
13
|
+
* Read-only. Exit 0 clean / 1 on any broken internal link, 2 if the site has not
|
|
14
|
+
* been built yet (run `cd site && npm run build` first).
|
|
15
|
+
*
|
|
16
|
+
* Usage:
|
|
17
|
+
* ./scripts-run src/scripts/check_site_links # scan site/dist
|
|
18
|
+
* ./scripts-run src/scripts/check_site_links --dist DIR --base /prefix
|
|
19
|
+
*/
|
|
20
|
+
import * as fs from 'node:fs';
|
|
21
|
+
import * as path from 'node:path';
|
|
22
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
23
|
+
|
|
24
|
+
const _FILE = fileURLToPath(import.meta.url);
|
|
25
|
+
export const REPO = path.resolve(path.dirname(_FILE), '..', '..');
|
|
26
|
+
|
|
27
|
+
/** Read `base:` from site/astro.config.mjs (default '/agent-config'). */
|
|
28
|
+
export function readBase(repo: string = REPO): string {
|
|
29
|
+
const cfg = path.join(repo, 'site', 'astro.config.mjs');
|
|
30
|
+
if (fs.existsSync(cfg)) {
|
|
31
|
+
const m = /base:\s*['"]([^'"]+)['"]/.exec(fs.readFileSync(cfg, 'utf-8'));
|
|
32
|
+
if (m && m[1]) return m[1].replace(/\/+$/, '');
|
|
33
|
+
}
|
|
34
|
+
return '/agent-config';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function _walkHtml(dir: string): string[] {
|
|
38
|
+
const out: string[] = [];
|
|
39
|
+
const stack = [dir];
|
|
40
|
+
while (stack.length > 0) {
|
|
41
|
+
const cur = stack.pop() as string;
|
|
42
|
+
let entries: fs.Dirent[];
|
|
43
|
+
try {
|
|
44
|
+
entries = fs.readdirSync(cur, { withFileTypes: true });
|
|
45
|
+
} catch {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
for (const e of entries.sort((a, b) => (a.name < b.name ? -1 : 1))) {
|
|
49
|
+
const full = path.join(cur, e.name);
|
|
50
|
+
if (e.isDirectory()) stack.push(full);
|
|
51
|
+
else if (e.isFile() && e.name.endsWith('.html')) out.push(full);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return out.sort();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const _LINK_RE = /(?:href|src)\s*=\s*"([^"]*)"/gi;
|
|
58
|
+
const _EXTERNAL = /^(?:[a-z][a-z0-9+.-]*:|\/\/|#|mailto:|tel:|data:)/i;
|
|
59
|
+
|
|
60
|
+
/** Resolve one internal link to a candidate dist-relative file, or null to skip. */
|
|
61
|
+
export function resolveTarget(link: string, base: string): string | null {
|
|
62
|
+
let l = link.trim();
|
|
63
|
+
if (l === '' || _EXTERNAL.test(l)) return null;
|
|
64
|
+
// Strip fragment + query.
|
|
65
|
+
l = l.split('#')[0]!.split('?')[0]!;
|
|
66
|
+
if (l === '') return null;
|
|
67
|
+
if (!l.startsWith('/')) return null; // relative links are rare in Astro output; skip (not internal-root)
|
|
68
|
+
// Strip the base prefix.
|
|
69
|
+
if (base && (l === base || l.startsWith(base + '/'))) {
|
|
70
|
+
l = l.slice(base.length);
|
|
71
|
+
}
|
|
72
|
+
if (l === '' || l === '/') return 'index.html';
|
|
73
|
+
l = l.replace(/^\/+/, '');
|
|
74
|
+
if (l.endsWith('/')) return l + 'index.html';
|
|
75
|
+
return l;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function findBrokenLinks(distDir: string, base: string): Array<{ page: string; link: string }> {
|
|
79
|
+
const broken: Array<{ page: string; link: string }> = [];
|
|
80
|
+
const seenOk = new Set<string>();
|
|
81
|
+
for (const html of _walkHtml(distDir)) {
|
|
82
|
+
const text = fs.readFileSync(html, 'utf-8');
|
|
83
|
+
const pageRel = path.relative(distDir, html);
|
|
84
|
+
let m: RegExpExecArray | null;
|
|
85
|
+
_LINK_RE.lastIndex = 0;
|
|
86
|
+
const linksInPage = new Set<string>();
|
|
87
|
+
while ((m = _LINK_RE.exec(text)) !== null) {
|
|
88
|
+
const raw = m[1] as string;
|
|
89
|
+
const target = resolveTarget(raw, base);
|
|
90
|
+
if (target === null) continue;
|
|
91
|
+
if (linksInPage.has(raw)) continue;
|
|
92
|
+
linksInPage.add(raw);
|
|
93
|
+
const cacheKey = target;
|
|
94
|
+
if (seenOk.has(cacheKey)) continue;
|
|
95
|
+
const candidates = [
|
|
96
|
+
path.join(distDir, target),
|
|
97
|
+
path.join(distDir, target, 'index.html'), // extensionless dir link
|
|
98
|
+
];
|
|
99
|
+
if (candidates.some((c) => fs.existsSync(c) && fs.statSync(c).isFile())) {
|
|
100
|
+
seenOk.add(cacheKey);
|
|
101
|
+
} else {
|
|
102
|
+
broken.push({ page: pageRel, link: raw });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return broken;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function main(argv: string[] = process.argv.slice(2)): number {
|
|
110
|
+
const quiet = argv.includes('--quiet');
|
|
111
|
+
const distArg = argv.indexOf('--dist');
|
|
112
|
+
const baseArg = argv.indexOf('--base');
|
|
113
|
+
const distDir = distArg !== -1 && argv[distArg + 1] ? path.resolve(argv[distArg + 1] as string) : path.join(REPO, 'site', 'dist');
|
|
114
|
+
const base = baseArg !== -1 && argv[baseArg + 1] ? (argv[baseArg + 1] as string).replace(/\/+$/, '') : readBase();
|
|
115
|
+
|
|
116
|
+
if (!fs.existsSync(distDir)) {
|
|
117
|
+
process.stderr.write(`❌ site not built: ${distDir} is missing. Run \`cd site && npm ci && npm run build\` first.\n`);
|
|
118
|
+
return 2;
|
|
119
|
+
}
|
|
120
|
+
const broken = findBrokenLinks(distDir, base);
|
|
121
|
+
if (broken.length > 0) {
|
|
122
|
+
process.stdout.write(`❌ ${broken.length} broken internal link(s) in the built site:\n`);
|
|
123
|
+
for (const b of broken) process.stdout.write(` - ${b.page}: ${b.link}\n`);
|
|
124
|
+
return 1;
|
|
125
|
+
}
|
|
126
|
+
if (!quiet) {
|
|
127
|
+
const pages = _walkHtml(distDir).length;
|
|
128
|
+
process.stdout.write(`✅ site links: ${pages} page(s), no broken internal links (base ${base}).\n`);
|
|
129
|
+
}
|
|
130
|
+
return 0;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const _isCli =
|
|
134
|
+
process.argv[1] !== undefined && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href;
|
|
135
|
+
if (_isCli) process.exit(main());
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* B6 — the falsifiability lock for per-skill honest-null `gaps:`.
|
|
4
|
+
*
|
|
5
|
+
* Every `gaps[].witness` in a skill's frontmatter must point at a test file that
|
|
6
|
+
* EXISTS (pointer integrity). The witness *passing* — and going red when the gap
|
|
7
|
+
* is fixed (the stale-gap audit) — is enforced by the ordinary test suite; this
|
|
8
|
+
* script guarantees the pointer never rots and the shape is well-formed, so the
|
|
9
|
+
* proof page's "Known Limits" can never cite a phantom witness.
|
|
10
|
+
*
|
|
11
|
+
* Read-only over `src/skills/*\/SKILL.md`. Exit 0 clean / 1 on any broken pointer
|
|
12
|
+
* or malformed entry.
|
|
13
|
+
*/
|
|
14
|
+
import * as fs from 'node:fs';
|
|
15
|
+
import * as path from 'node:path';
|
|
16
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
17
|
+
import { parse as parseYaml } from 'yaml';
|
|
18
|
+
|
|
19
|
+
const _HERE = fileURLToPath(import.meta.url);
|
|
20
|
+
export const ROOT = path.resolve(path.dirname(_HERE), '..', '..');
|
|
21
|
+
const SKILLS_DIR = path.join(ROOT, 'src', 'skills');
|
|
22
|
+
const FRONTMATTER_RE = /^---\n([\s\S]*?)\n---\n/;
|
|
23
|
+
|
|
24
|
+
export interface Gap {
|
|
25
|
+
description: string;
|
|
26
|
+
witness: string;
|
|
27
|
+
}
|
|
28
|
+
export interface SkillGaps {
|
|
29
|
+
skill: string;
|
|
30
|
+
file: string;
|
|
31
|
+
gaps: Gap[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Parse `gaps:` from every SKILL.md that declares them. */
|
|
35
|
+
export function collectSkillGaps(skillsDir: string = SKILLS_DIR): SkillGaps[] {
|
|
36
|
+
const out: SkillGaps[] = [];
|
|
37
|
+
let names: string[];
|
|
38
|
+
try {
|
|
39
|
+
names = fs.readdirSync(skillsDir).sort();
|
|
40
|
+
} catch {
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
for (const name of names) {
|
|
44
|
+
const file = path.join(skillsDir, name, 'SKILL.md');
|
|
45
|
+
if (!fs.existsSync(file)) continue;
|
|
46
|
+
const m = FRONTMATTER_RE.exec(fs.readFileSync(file, 'utf-8'));
|
|
47
|
+
if (!m) continue;
|
|
48
|
+
let fm: Record<string, unknown> | null;
|
|
49
|
+
try {
|
|
50
|
+
fm = parseYaml(m[1] as string) as Record<string, unknown> | null;
|
|
51
|
+
} catch {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (!fm || !Array.isArray(fm.gaps) || fm.gaps.length === 0) continue;
|
|
55
|
+
out.push({ skill: name, file, gaps: fm.gaps as Gap[] });
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function findBrokenPointers(entries: SkillGaps[], root: string = ROOT): string[] {
|
|
61
|
+
const errs: string[] = [];
|
|
62
|
+
for (const e of entries) {
|
|
63
|
+
e.gaps.forEach((g, i) => {
|
|
64
|
+
if (typeof g?.description !== 'string' || !g.description.trim()) {
|
|
65
|
+
errs.push(`${e.skill}: gaps[${i}] missing/empty description`);
|
|
66
|
+
}
|
|
67
|
+
if (typeof g?.witness !== 'string' || !g.witness.trim()) {
|
|
68
|
+
errs.push(`${e.skill}: gaps[${i}] missing/empty witness`);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (!fs.existsSync(path.join(root, g.witness))) {
|
|
72
|
+
errs.push(`${e.skill}: gaps[${i}] witness not found: ${g.witness}`);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return errs;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function main(argv: string[] = process.argv.slice(2)): number {
|
|
80
|
+
const quiet = argv.includes('--quiet');
|
|
81
|
+
const entries = collectSkillGaps();
|
|
82
|
+
const errs = findBrokenPointers(entries);
|
|
83
|
+
if (errs.length > 0) {
|
|
84
|
+
process.stdout.write('❌ skill gaps:\n');
|
|
85
|
+
for (const e of errs.sort()) process.stdout.write(` - ${e}\n`);
|
|
86
|
+
return 1;
|
|
87
|
+
}
|
|
88
|
+
const gapCount = entries.reduce((n, e) => n + e.gaps.length, 0);
|
|
89
|
+
if (!quiet) {
|
|
90
|
+
process.stdout.write(
|
|
91
|
+
`✅ skill gaps: ${gapCount} gap(s) across ${entries.length} skill(s), all witness pointers resolve.\n`,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const _isCli =
|
|
98
|
+
process.argv[1] !== undefined && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href;
|
|
99
|
+
if (_isCli) process.exit(main());
|