@event4u/agent-config 14.11.0 → 14.13.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/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +368 -516
- package/CONTRIBUTING.md +38 -0
- package/CREDITS.md +135 -0
- package/NOTICE +13 -0
- package/README.md +8 -6
- package/dist/agent-src/commands/analyze/inbox.md +109 -2
- package/dist/agent-src/commands/feature/dev.md +7 -2
- package/dist/agent-src/commands/ghostwriter/write.md +5 -1
- package/dist/agent-src/commands/implement-ticket.md +1 -1
- package/dist/agent-src/commands/mission/upgrade.md +1 -1
- package/dist/agent-src/commands/orchestrate.md +2 -2
- package/dist/agent-src/commands/post-as/me.md +5 -1
- package/dist/agent-src/commands/pr/merge.md +19 -6
- package/dist/agent-src/commands/roadmap/process-full.md +19 -5
- package/dist/agent-src/commands/tdd/red.md +12 -2
- package/dist/agent-src/commands/work.md +1 -1
- package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +40 -0
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +5 -2
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +21 -0
- package/dist/agent-src/contexts/execution/evidence-discipline.md +26 -0
- package/dist/agent-src/contexts/execution/orchestration-telemetry.md +1 -0
- package/dist/agent-src/contexts/execution/subagent-response-contract.md +40 -0
- package/dist/agent-src/contexts/execution/subagent-steering.md +13 -1
- package/dist/agent-src/contexts/execution/terminal-states.md +96 -0
- package/dist/agent-src/rules/artifact-drafting-protocol.md +1 -1
- package/dist/agent-src/rules/broken-access-control.md +4 -0
- package/dist/agent-src/rules/code-provenance.md +4 -0
- package/dist/agent-src/rules/design-fidelity.md +1 -1
- package/dist/agent-src/rules/domain-safety-pii.md +4 -0
- package/dist/agent-src/rules/domain-safety-retention.md +4 -0
- package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
- package/dist/agent-src/rules/external-code-graph-interop.md +14 -12
- package/dist/agent-src/rules/improve-before-implement.md +6 -8
- package/dist/agent-src/rules/laravel-routing.md +1 -1
- package/dist/agent-src/rules/lethal-trifecta-guard.md +4 -0
- package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
- package/dist/agent-src/rules/security-sensitive-stop.md +2 -0
- package/dist/agent-src/rules/source-confidentiality.md +12 -34
- package/dist/agent-src/rules/symfony-routing.md +1 -1
- package/dist/agent-src/rules/token-efficiency.md +14 -0
- package/dist/agent-src/rules/tool-safety.md +4 -0
- package/dist/agent-src/rules/untrusted-input-defense.md +4 -0
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +247 -3
- package/dist/agent-src/scripts/guarded_baseline.ts +328 -0
- package/dist/agent-src/scripts/roadmap_set_step.ts +253 -0
- package/dist/agent-src/scripts/stub_queue.ts +82 -0
- package/dist/agent-src/scripts/stubs_due.ts +400 -0
- package/dist/agent-src/scripts/ticket_bundles.ts +84 -0
- package/dist/agent-src/scripts/update_roadmap_progress.ts +8 -4
- package/dist/agent-src/skills/brand-asset-generation/SKILL.md +17 -4
- package/dist/agent-src/skills/brand-audit/SKILL.md +33 -0
- package/dist/agent-src/skills/code-intelligence/SKILL.md +57 -0
- package/dist/agent-src/skills/code-refactoring/SKILL.md +45 -1
- package/dist/agent-src/skills/code-review/SKILL.md +65 -6
- package/dist/agent-src/skills/command-writing/SKILL.md +35 -0
- package/dist/agent-src/skills/database/SKILL.md +8 -0
- package/dist/agent-src/skills/dependency-upgrade/SKILL.md +27 -0
- package/dist/agent-src/skills/design-review/SKILL.md +1 -1
- package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +25 -2
- package/dist/agent-src/skills/feature-planning/SKILL.md +9 -2
- package/dist/agent-src/skills/frontend-render-security/SKILL.md +44 -0
- package/dist/agent-src/skills/git-workflow/SKILL.md +1 -1
- package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +38 -4
- package/dist/agent-src/skills/judge-artifact-completeness/rubrics/ticket-quality-score.json +2 -2
- package/dist/agent-src/skills/laravel/SKILL.md +35 -0
- package/dist/agent-src/skills/laravel-migration/SKILL.md +57 -3
- package/dist/agent-src/skills/monorepo-workspace/SKILL.md +26 -0
- package/dist/agent-src/skills/playbook-authoring/SKILL.md +28 -1
- package/dist/agent-src/skills/project-analysis-core/SKILL.md +23 -0
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +30 -13
- package/dist/agent-src/skills/skill-writing/references/procedure.md +29 -7
- package/dist/agent-src/skills/sql-writing/SKILL.md +7 -1
- package/dist/agent-src/skills/standards-from-config/SKILL.md +27 -4
- package/dist/agent-src/skills/storybook-workshop/SKILL.md +9 -0
- package/dist/agent-src/skills/supply-chain-intake/SKILL.md +11 -4
- package/dist/agent-src/skills/symfony-workflow/SKILL.md +35 -0
- package/dist/agent-src/skills/test-case-discovery/SKILL.md +85 -0
- package/dist/agent-src/skills/test-driven-development/SKILL.md +33 -9
- package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +37 -0
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +53 -2
- package/dist/agent-src/skills/upstream-contribute/SKILL.md +38 -1
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +9 -4
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +97 -3
- package/dist/agent-src/templates/scripts/check_memory.ts +258 -17
- package/dist/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
- package/dist/agent-src/templates/scripts/memory_lookup.ts +86 -0
- package/dist/agent-src/templates/scripts/memory_signal.ts +44 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
- package/dist/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
- package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
- package/dist/cli/commands/uiAudit.js +124 -5
- package/dist/cli/registry.js +2 -0
- package/dist/cli-delegate/{chunk-HYWSRNUX.js → chunk-2DK2VJWG.js} +3 -3
- package/dist/cli-delegate/{chunk-L43NCYPB.js → chunk-4FS4WRXP.js} +10 -0
- package/dist/cli-delegate/{chunk-OMIVVCG2.js → chunk-A4QJ6ENT.js} +24 -0
- package/dist/cli-delegate/{chunk-236PNQZK.js → chunk-AKJGUQNO.js} +466 -285
- package/dist/cli-delegate/{chunk-E46KPN6K.js → chunk-BTWUYDGN.js} +424 -363
- package/dist/cli-delegate/{chunk-K4FFODTS.js → chunk-ILMUPLGW.js} +1227 -316
- package/dist/cli-delegate/{chunk-FF7WAFMR.js → chunk-KPBWFOPZ.js} +5 -1
- package/dist/cli-delegate/cmd_adr_effective.js +102 -0
- package/dist/cli-delegate/cmd_conformance.js +42 -10
- package/dist/cli-delegate/cmd_doctor.js +3 -3
- package/dist/cli-delegate/cmd_export.js +3 -2
- package/dist/cli-delegate/cmd_fleet.js +2 -2
- package/dist/cli-delegate/cmd_handoff.js +1 -1
- package/dist/cli-delegate/cmd_preflight.js +2 -2
- package/dist/cli-delegate/cmd_prune.js +3 -2
- package/dist/cli-delegate/cmd_settings_get.js +1 -1
- package/dist/cli-delegate/cmd_settings_migrate.js +3 -2
- package/dist/cli-delegate/cmd_settings_set.js +2 -2
- package/dist/cli-delegate/cmd_sync.js +3 -2
- package/dist/cli-delegate/cmd_uninstall.js +3 -2
- package/dist/cli-delegate/cmd_validate.js +3 -2
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +62 -62
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +2413 -1087
- package/dist/install/claudeRuleRewrite.js +254 -0
- package/dist/install/detect.js +29 -16
- package/dist/install/detect_php_shape.js +159 -0
- package/dist/install/install.mjs +639 -428
- package/dist/mcp/awesome-mcp-servers.row.md +1 -1
- package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +3 -3
- package/dist/mcp/server.mjs +4818 -2645
- package/dist/server/schemas/settings.js +6 -0
- package/dist/ui/assets/index-D0jaCRPM.js +29 -0
- package/dist/ui/index.html +1 -1
- package/docs/MIGRATION.md +1 -1
- package/docs/THIRD-PARTY-NOTICES.md +25 -0
- package/docs/contracts/provider-lifecycle.md +1 -1
- package/docs/contracts/settings-classes.md +30 -4
- package/docs/guidelines/agent-infra/5w2h-analysis.md +3 -3
- package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +1 -0
- package/docs/guidelines/agent-infra/artifact-drafting-protocol-mechanics.md +58 -3
- package/docs/guidelines/agent-infra/ask-when-uncertain-demos.md +2 -2
- package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +3 -3
- package/docs/guidelines/agent-infra/break-glass-usage.md +7 -7
- package/docs/guidelines/agent-infra/carve-out-predicates.md +3 -3
- package/docs/guidelines/agent-infra/comparison-matrix.md +1 -1
- package/docs/guidelines/agent-infra/critical-thinking.md +4 -4
- package/docs/guidelines/agent-infra/direct-answers-demos.md +2 -2
- package/docs/guidelines/agent-infra/domain-eval-anti-pattern.md +1 -1
- package/docs/guidelines/agent-infra/downstream-changes-mechanics.md +91 -0
- package/docs/guidelines/agent-infra/engineering-memory-data-format.md +3 -3
- package/docs/guidelines/agent-infra/existence-question-verdicts.md +80 -0
- package/docs/guidelines/agent-infra/first-principles.md +2 -2
- package/docs/guidelines/agent-infra/framework-neutrality-patterns.md +2 -2
- package/docs/guidelines/agent-infra/guarded-baseline.md +39 -0
- package/docs/guidelines/agent-infra/inversion-thinking.md +5 -5
- package/docs/guidelines/agent-infra/language-and-tone-examples.md +1 -1
- package/docs/guidelines/agent-infra/layered-settings.md +10 -10
- package/docs/guidelines/agent-infra/memory-access.md +1 -1
- package/docs/guidelines/agent-infra/mental-models.md +3 -3
- package/docs/guidelines/agent-infra/reuse-verdict-mechanics.md +71 -0
- package/docs/guidelines/agent-infra/review-routing-data-format.md +7 -7
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +13 -7
- package/docs/guidelines/agent-infra/role-contracts.md +2 -2
- package/docs/guidelines/agent-infra/role-mode-router.md +3 -3
- package/docs/guidelines/agent-infra/rule-type-governance.md +2 -2
- package/docs/guidelines/agent-infra/scqa-framework.md +5 -5
- package/docs/guidelines/agent-infra/self-improvement-pipeline.md +6 -6
- package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +2 -2
- package/docs/guidelines/agent-infra/six-hats.md +3 -3
- package/docs/guidelines/agent-infra/skill-quality-checklist.md +6 -6
- package/docs/guidelines/agent-infra/source-confidentiality-mechanics.md +109 -0
- package/docs/guidelines/agent-infra/systems-thinking.md +1 -1
- package/docs/guidelines/agent-infra/verify-before-complete-demos.md +2 -2
- package/docs/guidelines/augment-portability-patterns.md +6 -4
- package/docs/guidelines/code-clarity.md +21 -0
- package/docs/guidelines/component-oriented-and-oop-development.md +3 -2
- package/docs/guidelines/cross-role-handoff.md +2 -2
- package/docs/guidelines/design-fidelity-mechanics.md +1 -1
- package/docs/guidelines/docs/readme-size-and-splitting.md +3 -3
- package/docs/guidelines/php/database.md +90 -7
- package/docs/guidelines/prompt-templates.md +7 -7
- package/docs/guidelines/redundancy-taxonomy.md +180 -0
- package/llms.txt +2 -2
- package/package.json +10 -3
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +247 -3
- package/src/agent-src/scripts/guarded_baseline.ts +328 -0
- package/src/agent-src/scripts/roadmap_set_step.ts +253 -0
- package/src/agent-src/scripts/stub_queue.ts +82 -0
- package/src/agent-src/scripts/stubs_due.ts +400 -0
- package/src/agent-src/scripts/ticket_bundles.ts +84 -0
- package/src/agent-src/scripts/update_roadmap_progress.ts +8 -4
- package/src/agent-src/templates/scripts/check_memory.ts +258 -17
- package/src/agent-src/templates/scripts/check_memory_proposal.ts +9 -3
- package/src/agent-src/templates/scripts/memory_lookup.ts +86 -0
- package/src/agent-src/templates/scripts/memory_signal.ts +44 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +90 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/index.ts +11 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +23 -1
- package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +10 -1
- package/src/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +5 -1
- package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +102 -14
- package/src/config/agent-settings.template.yml +48 -3
- package/src/config/assurance-capability-registry.json +21 -9
- package/src/config/budgets.yml +19 -0
- package/src/config/canonical-terms.yml +119 -0
- package/src/config/capability-native-outcome-bars.json +81 -0
- package/src/config/ci-local-parity.yml +95 -0
- package/src/config/discovery/prompt-patterns.yml +56 -0
- package/src/config/drafting-channels.yml +43 -0
- package/src/config/estate-count-budget.json +38 -31
- package/src/config/evaluator-budgets.json +14 -14
- package/src/config/gate-coverage.yml +731 -30
- package/src/config/gate-reachability-exemptions.json +21 -0
- package/src/config/gate-violation-baselines.json +38 -20
- package/src/config/harness-evolution-budget.json +25 -0
- package/src/config/lapsed-beta-baseline.json +96 -0
- package/src/config/memory-twin-verdicts.yml +129 -0
- package/src/config/metric-registry.yml +124 -0
- package/src/config/pack-size-budget.json +35 -7
- package/src/config/preamble-payload-budget.json +97 -71
- package/src/config/profiles/balanced.ini +27 -0
- package/src/config/profiles/full.ini +27 -0
- package/src/config/profiles/minimal.ini +27 -0
- package/src/config/publish-surface.json +9 -2
- package/src/config/routing-coverage-seed.json +43 -0
- package/src/config/rule-stub-ceilings.json +126 -112
- package/src/config/suggestion-capture.json +28 -0
- package/src/config/surface-matrix.yml +21 -2
- package/src/config/turnaround-budget.json +66 -0
- package/src/config/web-launch-readiness.json +188 -0
- package/src/install/claudeRuleRewrite.ts +288 -0
- package/src/install/detect.ts +60 -17
- package/src/install/detect_php_shape.ts +191 -0
- package/src/scripts/_cli/cmd_doctor.ts +27 -112
- package/src/scripts/_dispatch.bash +27 -0
- package/src/scripts/_lib/activation_ladder.ts +211 -0
- package/src/scripts/_lib/activation_states.ts +88 -0
- package/src/scripts/_lib/adherence_detectors.ts +143 -0
- package/src/scripts/_lib/arith_claims.ts +181 -0
- package/src/scripts/_lib/arm_ranking.ts +62 -0
- package/src/scripts/_lib/asset_delivery_ledger.ts +303 -0
- package/src/scripts/_lib/audit_field_provenance.ts +54 -0
- package/src/scripts/_lib/auto_dispatch.ts +32 -3
- package/src/scripts/_lib/bench_ab_size_claim.ts +98 -4
- package/src/scripts/_lib/benchmark_cache_fields.ts +158 -0
- package/src/scripts/_lib/candidate_proposer.ts +402 -0
- package/src/scripts/_lib/candidate_record.ts +601 -0
- package/src/scripts/_lib/capture_rate.ts +319 -0
- package/src/scripts/_lib/collector_denominator.ts +771 -0
- package/src/scripts/_lib/collector_record.ts +340 -0
- package/src/scripts/_lib/collector_store.ts +664 -0
- package/src/scripts/_lib/collector_supervision.ts +827 -0
- package/src/scripts/_lib/concern_estate.ts +77 -0
- package/src/scripts/_lib/config_chain.ts +477 -0
- package/src/scripts/_lib/config_cost.ts +209 -0
- package/src/scripts/_lib/council_settings_block.ts +6 -0
- package/src/scripts/_lib/curator_ops.ts +172 -0
- package/src/scripts/_lib/delivery_arm_experiment.ts +266 -0
- package/src/scripts/_lib/delivery_criticality.ts +126 -0
- package/src/scripts/_lib/doctor_runtime_checks.ts +70 -0
- package/src/scripts/_lib/empty_cycles.ts +88 -0
- package/src/scripts/_lib/eval_publication.ts +354 -0
- package/src/scripts/_lib/evaluation_vector.ts +283 -0
- package/src/scripts/_lib/evaluator_promotion.ts +225 -0
- package/src/scripts/_lib/evidence_basis.ts +118 -0
- package/src/scripts/_lib/exec_evidence.ts +8 -0
- package/src/scripts/_lib/experience_card.ts +272 -0
- package/src/scripts/_lib/experience_report.ts +151 -0
- package/src/scripts/_lib/experiment_freeze.ts +112 -0
- package/src/scripts/_lib/gate_baseline.ts +150 -1
- package/src/scripts/_lib/generated_by.ts +66 -0
- package/src/scripts/_lib/harness_evolution_guards.ts +229 -0
- package/src/scripts/_lib/hook_effect_probe.ts +141 -0
- package/src/scripts/_lib/host_denominator.ts +687 -0
- package/src/scripts/_lib/host_projection_reach.ts +157 -0
- package/src/scripts/_lib/ignored_blocker.ts +148 -0
- package/src/scripts/_lib/install_reach_checks.ts +495 -0
- package/src/scripts/_lib/json_duplicate_keys.ts +150 -0
- package/src/scripts/_lib/judge_hygiene.ts +228 -0
- package/src/scripts/_lib/legacy_boundary_map.ts +228 -0
- package/src/scripts/_lib/loop_guards.ts +299 -0
- package/src/scripts/_lib/loss_class.ts +129 -0
- package/src/scripts/_lib/machine_wake.ts +51 -0
- package/src/scripts/_lib/md_prose_lines.ts +177 -0
- package/src/scripts/_lib/minimality_tiebreak.ts +168 -0
- package/src/scripts/_lib/one_resolver_invariant.ts +449 -0
- package/src/scripts/_lib/orchestration_record.ts +253 -5
- package/src/scripts/_lib/outcome_envelope.ts +227 -0
- package/src/scripts/_lib/outcome_vocabularies.ts +125 -0
- package/src/scripts/_lib/paired_stats.ts +245 -0
- package/src/scripts/_lib/paired_verdict.ts +226 -0
- package/src/scripts/_lib/prefix_stable_surfaces.ts +123 -0
- package/src/scripts/_lib/privacy_class.ts +47 -0
- package/src/scripts/_lib/regression_neighbourhood.ts +259 -0
- package/src/scripts/_lib/repeated_failure.ts +105 -0
- package/src/scripts/_lib/repo_root.ts +111 -0
- package/src/scripts/_lib/review_skipped_record.ts +37 -0
- package/src/scripts/_lib/role_split.ts +338 -0
- package/src/scripts/_lib/runtime_journal.ts +1499 -0
- package/src/scripts/_lib/runtime_wiring_checks.ts +430 -0
- package/src/scripts/_lib/skill_catalogue.ts +11 -1
- package/src/scripts/_lib/skill_estate.ts +115 -0
- package/src/scripts/_lib/source_digest.ts +200 -0
- package/src/scripts/_lib/source_redact.ts +260 -0
- package/src/scripts/_lib/source_shape.ts +502 -0
- package/src/scripts/_lib/source_snapshot_dedup.ts +199 -0
- package/src/scripts/_lib/strip_comments.d.mts +8 -0
- package/src/scripts/_lib/strip_comments.mjs +65 -0
- package/src/scripts/_lib/test_red_state.ts +154 -0
- package/src/scripts/_lib/trigger_shift.ts +144 -0
- package/src/scripts/_lib/untrusted_content.ts +82 -7
- package/src/scripts/adoption_report.ts +1 -1
- package/src/scripts/adr/evidence_census.ts +1 -1
- package/src/scripts/adr/regenerate_index.ts +26 -2
- package/src/scripts/adr_cite_check.ts +164 -1
- package/src/scripts/ai_council/argument_exhaustion.ts +130 -0
- package/src/scripts/ai_council/blind_review.ts +11 -1
- package/src/scripts/ai_council/clients.ts +4 -0
- package/src/scripts/ai_council/config.ts +3 -0
- package/src/scripts/ai_council/consensus.ts +28 -8
- package/src/scripts/ai_council/consensus_round.ts +226 -0
- package/src/scripts/ai_council/disagreement_signal.ts +338 -0
- package/src/scripts/ai_council/inline_findings.ts +340 -0
- package/src/scripts/ai_council/judge_position_bias.ts +197 -0
- package/src/scripts/ai_council/orchestrator.ts +16 -203
- package/src/scripts/ai_council/orchestrator_results.ts +23 -3
- package/src/scripts/ai_council/pricing.ts +106 -0
- package/src/scripts/ai_council/prompts.ts +74 -7
- package/src/scripts/ai_council/provider_leakage_bench.ts +327 -0
- package/src/scripts/ai_council/py_format.ts +14 -3
- package/src/scripts/ai_council/recouncil_guard.ts +293 -0
- package/src/scripts/ai_council/response_record.ts +50 -0
- package/src/scripts/ai_council/topology_bench_manifest.ts +860 -0
- package/src/scripts/ai_council/topology_vocabulary.ts +175 -0
- package/src/scripts/asset_delivery_ledger.ts +157 -0
- package/src/scripts/attest_artifact.ts +193 -0
- package/src/scripts/audit_auto_rules.ts +2 -1
- package/src/scripts/audit_command_surface.ts +1 -1
- package/src/scripts/audit_mcp_tools.ts +2 -2
- package/src/scripts/audit_skill_overlap_allowlist.json +6 -1
- package/src/scripts/audit_user_type_axis.ts +2 -1
- package/src/scripts/bench_ab_clone.ts +215 -10
- package/src/scripts/bench_ab_integrity.ts +119 -5
- package/src/scripts/bench_ab_v2_stats.ts +40 -213
- package/src/scripts/build_archive_index.ts +1 -1
- package/src/scripts/build_linear_digest.ts +1 -1
- package/src/scripts/build_proof.ts +11 -4
- package/src/scripts/build_rule_trigger_matrix.ts +1 -1
- package/src/scripts/build_source_digests.ts +157 -0
- package/src/scripts/cache_realization_report.ts +103 -0
- package/src/scripts/check_adr_frontmatter.ts +126 -0
- package/src/scripts/check_benchmark_report_fields.ts +207 -0
- package/src/scripts/check_beta_review_markers.ts +235 -6
- package/src/scripts/check_bundle_path_leakage.ts +195 -7
- package/src/scripts/check_claims.ts +576 -6
- package/src/scripts/check_command_examples.ts +557 -0
- package/src/scripts/check_composite_arming.ts +35 -0
- package/src/scripts/check_concern_admissions.ts +365 -0
- package/src/scripts/check_enforcement_coverage.ts +28 -0
- package/src/scripts/check_estate_count.ts +263 -3
- package/src/scripts/check_gate_reachability.ts +383 -0
- package/src/scripts/check_host_loadability.ts +104 -0
- package/src/scripts/check_loss_class_declared.ts +308 -0
- package/src/scripts/check_md_language.ts +15 -98
- package/src/scripts/check_memory_proposal.ts +18 -11
- package/src/scripts/check_no_currency_in_cost_surfaces.ts +225 -0
- package/src/scripts/check_no_external_sources.ts +281 -6
- package/src/scripts/check_pack_conformance_fixture.ts +11 -1
- package/src/scripts/check_pack_size.ts +59 -2
- package/src/scripts/check_preamble_payload_budget.ts +144 -6
- package/src/scripts/check_prefix_stable_mutation.ts +372 -0
- package/src/scripts/check_publish_surface.ts +10 -1
- package/src/scripts/check_references.ts +24 -1
- package/src/scripts/check_routing_coverage.ts +352 -0
- package/src/scripts/check_rule_evidence_declaration.ts +316 -0
- package/src/scripts/check_rule_projection_integrity.ts +14 -4
- package/src/scripts/check_score_contract.ts +528 -0
- package/src/scripts/check_skill_admissions.ts +514 -0
- package/src/scripts/check_static_parity.ts +285 -0
- package/src/scripts/check_supervision_claim_atomicity.ts +498 -0
- package/src/scripts/check_suppression_hygiene.ts +15 -0
- package/src/scripts/check_web_launch_readiness.ts +705 -0
- package/src/scripts/ci_settle.ts +39 -2
- package/src/scripts/code_graph/build.ts +60 -3
- package/src/scripts/code_graph/extract.ts +44 -0
- package/src/scripts/code_graph/types.ts +24 -0
- package/src/scripts/collector_daemon.ts +714 -0
- package/src/scripts/config_cost_report.ts +302 -0
- package/src/scripts/consumer_matrix.ts +74 -1
- package/src/scripts/cost/budget.mjs +10 -3
- package/src/scripts/cost/track.mjs +10 -3
- package/src/scripts/council_cli.ts +37 -54
- package/src/scripts/description_route_check.ts +494 -0
- package/src/scripts/dispatch_r2_reviewer.ts +46 -5
- package/src/scripts/evolution_lab.ts +980 -0
- package/src/scripts/external_sources_denylist.json +5 -18
- package/src/scripts/extract_audit_patterns.ts +21 -0
- package/src/scripts/fold_intake.ts +12 -1
- package/src/scripts/gen_discovery_baseline.ts +1 -1
- package/src/scripts/generate_capabilities_index.ts +12 -5
- package/src/scripts/generate_capability_matrix.ts +3 -3
- package/src/scripts/generate_command_flows.ts +2 -2
- package/src/scripts/generate_cookbook.ts +2 -2
- package/src/scripts/generate_index.ts +8 -1
- package/src/scripts/generate_knowledge_index.ts +2 -1
- package/src/scripts/generate_ownership_matrix.ts +2 -1
- package/src/scripts/generate_pack_manifests.ts +10 -2
- package/src/scripts/generate_role_experiences_catalog.ts +2 -2
- package/src/scripts/generate_settings_reference.ts +1 -1
- package/src/scripts/git_authorization_hook.ts +22 -1
- package/src/scripts/grade_target_readiness.ts +48 -5
- package/src/scripts/hook_effect_doctor.ts +261 -0
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +125 -11
- package/src/scripts/hooks/block_speaking_inbox_dir.ts +271 -0
- package/src/scripts/hooks/block_unauthorized_git.ts +18 -0
- package/src/scripts/hooks/concern_registry.ts +6 -0
- package/src/scripts/hooks/dispatch_hook.ts +32 -0
- package/src/scripts/hooks/journal_record_hook.ts +345 -0
- package/src/scripts/hooks/prepush_metadata_sources.sh +110 -0
- package/src/scripts/hooks/run_continuation_hook.ts +44 -9
- package/src/scripts/hooks/shims/install.sh +61 -0
- package/src/scripts/hooks/shims/php +101 -0
- package/src/scripts/hooks/suggestion_capture_hook.ts +378 -0
- package/src/scripts/hot_context_hook.ts +16 -0
- package/src/scripts/install-hooks.sh +20 -5
- package/src/scripts/install.ts +17 -35
- package/src/scripts/inventory_frontmatter.ts +2 -1
- package/src/scripts/lint_adr_sweep_routing.ts +12 -0
- package/src/scripts/lint_budget_ownership.ts +54 -4
- package/src/scripts/lint_canonical_terms.ts +604 -0
- package/src/scripts/lint_composition_review.ts +619 -0
- package/src/scripts/lint_consolidation_lineage.ts +666 -0
- package/src/scripts/lint_eval_specs.ts +593 -0
- package/src/scripts/lint_hook_manifest.ts +19 -0
- package/src/scripts/lint_host_portability.ts +373 -0
- package/src/scripts/lint_judge_prompt_expectation.ts +27 -1
- package/src/scripts/lint_memory_twin_parity.ts +335 -0
- package/src/scripts/lint_metric_consumers.ts +355 -0
- package/src/scripts/lint_skill_descriptions.ts +18 -1
- package/src/scripts/lint_skill_frontmatter_safety.ts +58 -0
- package/src/scripts/lint_skill_link_reach.ts +252 -0
- package/src/scripts/lint_skill_trigger_corpus.ts +752 -0
- package/src/scripts/lint_ticket_buildable.ts +17 -1
- package/src/scripts/mcp_server/consumer_tool_catalog.json +1 -1
- package/src/scripts/mcp_server/tool_catalog_source.ts +1 -1
- package/src/scripts/measure_docs_dead_links.ts +348 -0
- package/src/scripts/measure_host_capture.ts +461 -0
- package/src/scripts/migration_status.ts +3 -3
- package/src/scripts/model_rule_injection.ts +60 -0
- package/src/scripts/orchestration_record.ts +14 -0
- package/src/scripts/pack_install_smoke.ts +363 -0
- package/src/scripts/pr_conflict_census.ts +187 -0
- package/src/scripts/preamble_byte_census.ts +139 -10
- package/src/scripts/prepack-check.mjs +4 -1
- package/src/scripts/probe_turnaround.ts +384 -0
- package/src/scripts/probe_unblocked_ask.ts +279 -0
- package/src/scripts/render_benchmark_md.ts +1 -1
- package/src/scripts/report_pack_delta.ts +204 -0
- package/src/scripts/rule_activation_census.ts +70 -9
- package/src/scripts/rule_backlinks.ts +1 -1
- package/src/scripts/run_lifecycle_suite.ts +208 -0
- package/src/scripts/run_skill_evals.ts +40 -0
- package/src/scripts/schemas/delivery-manifest.schema.json +43 -0
- package/src/scripts/schemas/drafting-channels.schema.json +43 -0
- package/src/scripts/schemas/evals.schema.json +24 -1
- package/src/scripts/schemas/rule.schema.json +52 -1
- package/src/scripts/schemas/skill.schema.json +17 -2
- package/src/scripts/select_analysis_mode.ts +112 -0
- package/src/scripts/skill_overlap.ts +7 -1
- package/src/scripts/skill_tools/run_block_d_eval.ts +8 -1
- package/src/scripts/skill_tools/score_skill_relevance.ts +84 -3
- package/src/scripts/skill_tools/suggest_skill_for_task.ts +8 -1
- package/src/scripts/skill_usage_report.ts +2 -1
- package/src/scripts/stubs_due.ts +211 -0
- package/src/scripts/sweep_source_surfaces.ts +678 -0
- package/src/scripts/sync_pr_branch.ts +40 -1
- package/src/scripts/trigger_eval_grandfather.json +202 -222
- package/src/scripts/utilization_report.ts +22 -2
- package/src/server/schemas/settings.ts +10 -0
- package/src/templates/marketing-copy.yml +1 -1
- package/dist/agent-src/skills/accessibility-auditor/evals/evals.json +0 -15
- package/dist/agent-src/skills/agent-security-review/evals/triggers.json +0 -52
- package/dist/agent-src/skills/ai-code-blindspots/evals/triggers.json +0 -52
- package/dist/agent-src/skills/alerting-doctrine/evals/triggers.json +0 -17
- package/dist/agent-src/skills/analysis-skill-router/evals/evals.json +0 -13
- package/dist/agent-src/skills/brand/evals/triggers.json +0 -17
- package/dist/agent-src/skills/brand-asset-generation/evals/triggers.json +0 -17
- package/dist/agent-src/skills/brand-audit/evals/triggers.json +0 -17
- package/dist/agent-src/skills/brand-identity/evals/triggers.json +0 -17
- package/dist/agent-src/skills/brand-strategy/evals/triggers.json +0 -17
- package/dist/agent-src/skills/brand-to-tokens/evals/triggers.json +0 -17
- package/dist/agent-src/skills/bug-analyzer/evals/evals.json +0 -13
- package/dist/agent-src/skills/canvas-design/evals/triggers.json +0 -17
- package/dist/agent-src/skills/character-consistency/evals/evals.json +0 -16
- package/dist/agent-src/skills/code-intelligence/evals/triggers.json +0 -52
- package/dist/agent-src/skills/code-review/evals/evals.json +0 -100
- package/dist/agent-src/skills/command-routing/evals/evals.json +0 -14
- package/dist/agent-src/skills/complexity-first-planning/evals/triggers.json +0 -17
- package/dist/agent-src/skills/contract-review/evals/triggers.json +0 -17
- package/dist/agent-src/skills/conventional-commits-writing/evals/evals.json +0 -15
- package/dist/agent-src/skills/corpus-grounding/evals/triggers.json +0 -17
- package/dist/agent-src/skills/dashboard-design/evals/evals.json +0 -16
- package/dist/agent-src/skills/dcf-modeling/evals/domain-truth.json +0 -29
- package/dist/agent-src/skills/dcf-modeling/evals/evals.json +0 -20
- package/dist/agent-src/skills/decision-record/evals/evals.json +0 -20
- package/dist/agent-src/skills/decision-record/evals/triggers.json +0 -87
- package/dist/agent-src/skills/design-intelligence/evals/evals.json +0 -14
- package/dist/agent-src/skills/design-intelligence/evals/triggers.json +0 -17
- package/dist/agent-src/skills/design-system-capture/evals/evals.json +0 -15
- package/dist/agent-src/skills/design-tokens/evals/triggers.json +0 -17
- package/dist/agent-src/skills/design-variations/evals/triggers.json +0 -17
- package/dist/agent-src/skills/developer-like-execution/evals/evals.json +0 -16
- package/dist/agent-src/skills/doc-coauthoring/evals/evals.json +0 -16
- package/dist/agent-src/skills/doc-coauthoring/evals/triggers.json +0 -17
- package/dist/agent-src/skills/docx-authoring/evals/triggers.json +0 -52
- package/dist/agent-src/skills/dpa-review/evals/triggers.json +0 -17
- package/dist/agent-src/skills/editorial-calendar/evals/domain-truth.json +0 -16
- package/dist/agent-src/skills/editorial-calendar/evals/evals.json +0 -16
- package/dist/agent-src/skills/eloquent/evals/triggers.json +0 -17
- package/dist/agent-src/skills/estimate-ticket/evals/evals.json +0 -16
- package/dist/agent-src/skills/estimate-ticket/evals/output-schema.yml +0 -20
- package/dist/agent-src/skills/estimate-ticket/evals/triggers.json +0 -19
- package/dist/agent-src/skills/evaluate-llm-feature/evals/triggers.json +0 -52
- package/dist/agent-src/skills/existing-ui-audit/evals/triggers.json +0 -47
- package/dist/agent-src/skills/experiment-loop/evals/output-schema.yml +0 -27
- package/dist/agent-src/skills/experiment-loop/evals/triggers.json +0 -17
- package/dist/agent-src/skills/fe-design/evals/triggers.json +0 -67
- package/dist/agent-src/skills/forecasting/evals/domain-truth.json +0 -29
- package/dist/agent-src/skills/forecasting/evals/evals.json +0 -20
- package/dist/agent-src/skills/forensics-report/evals/triggers.json +0 -17
- package/dist/agent-src/skills/frontend-render-security/evals/triggers.json +0 -52
- package/dist/agent-src/skills/fundraising-narrative/evals/domain-truth.json +0 -16
- package/dist/agent-src/skills/fundraising-narrative/evals/evals.json +0 -16
- package/dist/agent-src/skills/gated-reach/evals/triggers.json +0 -72
- package/dist/agent-src/skills/github-ci/evals/evals.json +0 -25
- package/dist/agent-src/skills/history-design/evals/triggers.json +0 -17
- package/dist/agent-src/skills/html-deck/evals/triggers.json +0 -17
- package/dist/agent-src/skills/humanizer/evals/strip_fixtures.json +0 -57
- package/dist/agent-src/skills/humanizer/evals/triggers.json +0 -17
- package/dist/agent-src/skills/iconography/evals/triggers.json +0 -17
- package/dist/agent-src/skills/image-analyser/evals/triggers.json +0 -17
- package/dist/agent-src/skills/image-creator/evals/triggers.json +0 -17
- package/dist/agent-src/skills/image-editing/evals/triggers.json +0 -17
- package/dist/agent-src/skills/image-generation/evals/triggers.json +0 -17
- package/dist/agent-src/skills/image-provider-routing/evals/triggers.json +0 -17
- package/dist/agent-src/skills/incident-commander/evals/domain-truth.json +0 -16
- package/dist/agent-src/skills/incident-commander/evals/evals.json +0 -20
- package/dist/agent-src/skills/js-library-packaging/evals/triggers.json +0 -17
- package/dist/agent-src/skills/judge-artifact-completeness/evals/triggers.json +0 -17
- package/dist/agent-src/skills/judge-injection-defense/evals/triggers.json +0 -17
- package/dist/agent-src/skills/judge-synthesis/evals/triggers.json +0 -17
- package/dist/agent-src/skills/launch-readiness/evals/evals.json +0 -21
- package/dist/agent-src/skills/learning-tutor/evals/triggers.json +0 -52
- package/dist/agent-src/skills/legal-intake-triage/evals/triggers.json +0 -17
- package/dist/agent-src/skills/legal-practice-profile/evals/triggers.json +0 -17
- package/dist/agent-src/skills/license-compliance-audit/evals/triggers.json +0 -52
- package/dist/agent-src/skills/license-compliance-borrow-check/evals/triggers.json +0 -52
- package/dist/agent-src/skills/license-compliance-credits/evals/triggers.json +0 -52
- package/dist/agent-src/skills/llm-provider-knowledge/evals/triggers.json +0 -20
- package/dist/agent-src/skills/logging-monitoring/evals/evals.json +0 -16
- package/dist/agent-src/skills/logo-generation/evals/triggers.json +0 -17
- package/dist/agent-src/skills/messaging-architecture/evals/domain-truth.json +0 -16
- package/dist/agent-src/skills/messaging-architecture/evals/evals.json +0 -16
- package/dist/agent-src/skills/monorepo-workspace/evals/triggers.json +0 -17
- package/dist/agent-src/skills/nda-triage/evals/triggers.json +0 -17
- package/dist/agent-src/skills/operational-readiness/evals/triggers.json +0 -17
- package/dist/agent-src/skills/pdf-tools/evals/triggers.json +0 -52
- package/dist/agent-src/skills/perf-feedback-craft/evals/evals.json +0 -16
- package/dist/agent-src/skills/persona-improvement/evals/triggers.json +0 -52
- package/dist/agent-src/skills/php-coder/evals/triggers.json +0 -17
- package/dist/agent-src/skills/prediction-pool-optimizer/evals/triggers.json +0 -21
- package/dist/agent-src/skills/prompt-engineering-image/evals/triggers.json +0 -17
- package/dist/agent-src/skills/prompt-engineering-patterns/evals/evals.json +0 -16
- package/dist/agent-src/skills/prompt-validator/evals/triggers.json +0 -17
- package/dist/agent-src/skills/quality-tools/evals/evals.json +0 -15
- package/dist/agent-src/skills/reasoning-orchestrator/evals/triggers.json +0 -17
- package/dist/agent-src/skills/refine-prompt/evals/evals.json +0 -16
- package/dist/agent-src/skills/refine-ticket/evals/evals.json +0 -16
- package/dist/agent-src/skills/refine-ticket/evals/output-schema.yml +0 -16
- package/dist/agent-src/skills/refine-ticket/evals/triggers.json +0 -17
- package/dist/agent-src/skills/release-comms/evals/evals.json +0 -16
- package/dist/agent-src/skills/rice-prioritization/evals/evals.json +0 -20
- package/dist/agent-src/skills/runway-cognition/evals/domain-truth.json +0 -29
- package/dist/agent-src/skills/runway-cognition/evals/evals.json +0 -20
- package/dist/agent-src/skills/scenario-modeling/evals/domain-truth.json +0 -29
- package/dist/agent-src/skills/scenario-modeling/evals/evals.json +0 -20
- package/dist/agent-src/skills/schema-review/evals/triggers.json +0 -17
- package/dist/agent-src/skills/screenshot-hygiene/evals/triggers.json +0 -52
- package/dist/agent-src/skills/security-maturity-assessment/evals/triggers.json +0 -52
- package/dist/agent-src/skills/server-hardening/evals/triggers.json +0 -17
- package/dist/agent-src/skills/skill-writing/evals/triggers.json +0 -17
- package/dist/agent-src/skills/spreadsheet-authoring/evals/triggers.json +0 -47
- package/dist/agent-src/skills/storybook-workshop/evals/triggers.json +0 -17
- package/dist/agent-src/skills/subagent-orchestration/evals/evals.json +0 -60
- package/dist/agent-src/skills/supply-chain-intake/evals/triggers.json +0 -52
- package/dist/agent-src/skills/systematic-debugging/evals/evals.json +0 -20
- package/dist/agent-src/skills/test-case-discovery/evals/triggers.json +0 -52
- package/dist/agent-src/skills/test-driven-development/evals/evals.json +0 -16
- package/dist/agent-src/skills/threat-modeling/evals/evals.json +0 -21
- package/dist/agent-src/skills/typography-system/evals/evals.json +0 -14
- package/dist/agent-src/skills/typography-system/evals/triggers.json +0 -17
- package/dist/agent-src/skills/unit-economics-modeling/evals/domain-truth.json +0 -40
- package/dist/agent-src/skills/unit-economics-modeling/evals/evals.json +0 -24
- package/dist/agent-src/skills/verify-completion-evidence/evals/evals.json +0 -16
- package/dist/agent-src/skills/verify-repair-loop/evals/output-schema.yml +0 -20
- package/dist/agent-src/skills/verify-repair-loop/evals/triggers.json +0 -17
- package/dist/agent-src/skills/vision-articulation/evals/evals.json +0 -16
- package/dist/agent-src/skills/voice-and-tone-design/evals/evals.json +0 -16
- package/dist/agent-src/skills/wireframe/evals/triggers.json +0 -17
- package/dist/agent-src/skills/workspace-link/evals/triggers.json +0 -17
- package/dist/agent-src/skills/worktree-lifecycle/evals/evals.json +0 -38
- package/dist/agent-src/skills/worktree-lifecycle/evals/triggers.json +0 -52
- package/dist/cli/agent-config.js.map +0 -1
- package/dist/cli/bash/runBash.js.map +0 -1
- package/dist/cli/commands/commands.js.map +0 -1
- package/dist/cli/commands/config.js.map +0 -1
- package/dist/cli/commands/doctorShell.js.map +0 -1
- package/dist/cli/commands/mcpServer.js.map +0 -1
- package/dist/cli/commands/packs.js.map +0 -1
- package/dist/cli/commands/profiles.js.map +0 -1
- package/dist/cli/commands/recordTriggerEval.js.map +0 -1
- package/dist/cli/commands/rtkDetect.js.map +0 -1
- package/dist/cli/commands/settings.js.map +0 -1
- package/dist/cli/commands/uiAudit.js.map +0 -1
- package/dist/cli/commands/uiRender.js.map +0 -1
- package/dist/cli/commands/uiServe.js.map +0 -1
- package/dist/cli/commands/versions.js.map +0 -1
- package/dist/cli/commands/workspaces.js.map +0 -1
- package/dist/cli/configRoot.js.map +0 -1
- package/dist/cli/discovery/loadManifest.js.map +0 -1
- package/dist/cli/firstRunNotice.js.map +0 -1
- package/dist/cli/help.js.map +0 -1
- package/dist/cli/initRouting.js.map +0 -1
- package/dist/cli/log/logger.js.map +0 -1
- package/dist/cli/main.js.map +0 -1
- package/dist/cli/mcp/content.js.map +0 -1
- package/dist/cli/mcp/dispatch.js.map +0 -1
- package/dist/cli/mcp/stdio.js.map +0 -1
- package/dist/cli/paths.js.map +0 -1
- package/dist/cli/python/knowledge_ingest.js.map +0 -1
- package/dist/cli/python/workspace_analytics.js.map +0 -1
- package/dist/cli/python/workspace_crypto.js.map +0 -1
- package/dist/cli/python/workspace_documents.js.map +0 -1
- package/dist/cli/python/workspace_drive.js.map +0 -1
- package/dist/cli/python/workspace_drive_health.js.map +0 -1
- package/dist/cli/python/workspace_explain.js.map +0 -1
- package/dist/cli/python/workspace_hosts.js.map +0 -1
- package/dist/cli/python/workspace_inbox.js.map +0 -1
- package/dist/cli/python/workspace_render.js.map +0 -1
- package/dist/cli/python/workspace_roles.js.map +0 -1
- package/dist/cli/python/workspace_secrets.js.map +0 -1
- package/dist/cli/python/workspace_sessions.js.map +0 -1
- package/dist/cli/python/workspace_skills.js.map +0 -1
- package/dist/cli/registry.js.map +0 -1
- package/dist/install/agentSwitchDetection.js.map +0 -1
- package/dist/install/agentSwitchProfile.js.map +0 -1
- package/dist/install/atomic.js.map +0 -1
- package/dist/install/claudePathsPlan.js.map +0 -1
- package/dist/install/conflict.js.map +0 -1
- package/dist/install/detect.js.map +0 -1
- package/dist/install/emit_host_rules_cli.js.map +0 -1
- package/dist/install/globalRuleLayers.js.map +0 -1
- package/dist/install/hostLayerFingerprint.js.map +0 -1
- package/dist/install/partitionEligibility.js.map +0 -1
- package/dist/install/paths.js.map +0 -1
- package/dist/install/plan.js.map +0 -1
- package/dist/install/preflight.js.map +0 -1
- package/dist/install/rtkDetection.js.map +0 -1
- package/dist/install/ruleInScope.js.map +0 -1
- package/dist/install/ruleLayerPartition.js.map +0 -1
- package/dist/install/rule_scope.js.map +0 -1
- package/dist/install/rule_scope_cli.js.map +0 -1
- package/dist/install/selectedTools.js.map +0 -1
- package/dist/install/toolDetection.js.map +0 -1
- package/dist/install/txlog.js.map +0 -1
- package/dist/install/types.js.map +0 -1
- package/dist/install/wizard-plan.js.map +0 -1
- package/dist/install/wizardDismissals.js.map +0 -1
- package/dist/scripts/_lib/agent_settings.js.map +0 -1
- package/dist/scripts/_lib/agent_src.js.map +0 -1
- package/dist/scripts/_lib/claude_builtin_names.js.map +0 -1
- package/dist/scripts/_lib/claude_plugin.js.map +0 -1
- package/dist/scripts/_lib/claude_settings_hooks.js.map +0 -1
- package/dist/scripts/_lib/compile_time_toggles.js.map +0 -1
- package/dist/scripts/_lib/environment_detector.js.map +0 -1
- package/dist/scripts/_lib/host_launch.js.map +0 -1
- package/dist/scripts/_lib/install_layout.js.map +0 -1
- package/dist/scripts/_lib/installed_lock.js.map +0 -1
- package/dist/scripts/_lib/lean_projection_mode.js.map +0 -1
- package/dist/scripts/_lib/model_tier.js.map +0 -1
- package/dist/scripts/_lib/prune_empty_dirs.js.map +0 -1
- package/dist/scripts/_lib/scoped_projection.js.map +0 -1
- package/dist/scripts/_lib/script_output.js.map +0 -1
- package/dist/scripts/_lib/spawn_env.js.map +0 -1
- package/dist/scripts/_lib/surface_tiers.js.map +0 -1
- package/dist/scripts/_lib/token_count.js.map +0 -1
- package/dist/scripts/_lib/trigger_eval_floors.js.map +0 -1
- package/dist/scripts/_lib/ui_surface.js.map +0 -1
- package/dist/scripts/_lib/user_global_paths.js.map +0 -1
- package/dist/scripts/ai_council/modes.js.map +0 -1
- package/dist/scripts/ai_council/transport_resolver.js.map +0 -1
- package/dist/scripts/condense.js.map +0 -1
- package/dist/scripts/project_thin_rules.js.map +0 -1
- package/dist/server/app.js.map +0 -1
- package/dist/server/io/atomicMultiWrite.js.map +0 -1
- package/dist/server/io/atomicWrite.js.map +0 -1
- package/dist/server/io/sharedWriteCheck.js.map +0 -1
- package/dist/server/io/substituteTemplate.js.map +0 -1
- package/dist/server/io/yamlIO.js.map +0 -1
- package/dist/server/nicknameResolver.js.map +0 -1
- package/dist/server/port.js.map +0 -1
- package/dist/server/routes/discovery.js.map +0 -1
- package/dist/server/routes/install.js.map +0 -1
- package/dist/server/routes/ping.js.map +0 -1
- package/dist/server/routes/schema.js.map +0 -1
- package/dist/server/routes/settings.js.map +0 -1
- package/dist/server/routes/settingsChanges.js.map +0 -1
- package/dist/server/routes/userMd.js.map +0 -1
- package/dist/server/routes/wizard.js.map +0 -1
- package/dist/server/routes/workspace.js.map +0 -1
- package/dist/server/schemas/settings.js.map +0 -1
- package/dist/server/serverInfo.js.map +0 -1
- package/dist/server/token.js.map +0 -1
- package/dist/server/writeRoot.js.map +0 -1
- package/dist/shared/capabilities.js.map +0 -1
- package/dist/shared/interactiveContext.js.map +0 -1
- package/dist/shared/nicknamePrefill.js.map +0 -1
- package/dist/shared/settingsAsks.js.map +0 -1
- package/dist/shared/settingsCarveOut.js.map +0 -1
- package/dist/shared/settingsClasses.js.map +0 -1
- package/dist/shared/settingsConsent.js.map +0 -1
- package/dist/shared/settingsSurface.js.map +0 -1
- package/dist/shared/skillRanking.js.map +0 -1
- package/dist/shared/userMd/formAdapter.js.map +0 -1
- package/dist/shared/userMd/schema.js.map +0 -1
- package/dist/shared/userMd/utils.js.map +0 -1
- package/dist/ui/assets/index-Cxgy63kz.js +0 -26
- package/dist/ui/assets/index-Cxgy63kz.js.map +0 -1
- package/src/scripts/_lib/adr_frontmatter.test.ts +0 -365
- package/src/scripts/_lib/adversarial_council_gate.test.ts +0 -112
- package/src/scripts/_lib/adversarial_reconcile.test.ts +0 -197
- package/src/scripts/_lib/auto_dispatch.corpus.test.ts +0 -150
- package/src/scripts/_lib/secret_detector.test.ts +0 -108
- package/src/scripts/_lib/secret_detector_adversarial.test.ts +0 -116
- package/src/scripts/_lib/ui_authority.test.ts +0 -251
- package/src/scripts/_lib/untrusted_content.test.ts +0 -175
- package/src/scripts/check_secret_leak.test.ts +0 -90
- package/src/scripts/design_slop_rules.test.ts +0 -246
- package/src/scripts/self_review_gate.test.ts +0 -296
- package/src/shared/capabilities.test.ts +0 -43
|
@@ -0,0 +1,705 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* `check_web_launch_readiness` — the web-surface pre-ship audit, as a COMMAND.
|
|
4
|
+
*
|
|
5
|
+
* NOT a skill, and the container is a recorded decision rather than a default.
|
|
6
|
+
* AI council 2/2 on 2026-08-25 (`road-to-web-launch-readiness`
|
|
7
|
+
* § `b-estate-decision-web-launch`): the G0 evidence establishes a COVERAGE gap,
|
|
8
|
+
* not a SKILL-SHAPED one. A site-type-conditional config, deterministic checks,
|
|
9
|
+
* tiers and a hard pass/fail gate are *"the signature of a linter, not a skill"*,
|
|
10
|
+
* and `production-validator` carries unscoped `Bash`, so it can invoke this
|
|
11
|
+
* directly instead of depending on skill activation — which demonstrably is NOT
|
|
12
|
+
* firing for web-facing deploys, since `launch-readiness` already exists and
|
|
13
|
+
* scores 0 of 8 on these axes.
|
|
14
|
+
*
|
|
15
|
+
* CONDITIONAL, NOT FLAT. Every check declares `applies_to`, and a check that does
|
|
16
|
+
* not apply is reported as **skipped with the site type as the reason** — never
|
|
17
|
+
* silently dropped and never as a finding. A reader must be able to tell "this
|
|
18
|
+
* does not apply to you" from "this passed", which a flat audit cannot express.
|
|
19
|
+
*
|
|
20
|
+
* DEFAULT-OFF until the pre-registered benchmark returns positive
|
|
21
|
+
* (`claim:web-launch-readiness-finds-more`, status `unbacked`). Absent the
|
|
22
|
+
* opt-in, this exits 0 and says why rather than auditing.
|
|
23
|
+
*
|
|
24
|
+
* Exit codes: 0 = no critical/high finding (or not enabled) · 1 = a blocking
|
|
25
|
+
* finding · 2 = usage or a dead scan scope.
|
|
26
|
+
*/
|
|
27
|
+
import * as fs from 'node:fs';
|
|
28
|
+
import * as path from 'node:path';
|
|
29
|
+
import process from 'node:process';
|
|
30
|
+
import { fileURLToPath } from 'node:url';
|
|
31
|
+
|
|
32
|
+
import { DeadScopeError, reportScanned } from './_lib/scan_scope.js';
|
|
33
|
+
|
|
34
|
+
const HERE = fileURLToPath(import.meta.url);
|
|
35
|
+
const REPO_ROOT = path.resolve(path.dirname(HERE), '..', '..');
|
|
36
|
+
export const CONFIG_REL = 'src/config/web-launch-readiness.json';
|
|
37
|
+
|
|
38
|
+
export type SiteType = 'local-business' | 'marketing-site' | 'saas-app' | 'docs' | 'internal-tool';
|
|
39
|
+
export type Tier = 'critical' | 'high' | 'medium' | 'situational';
|
|
40
|
+
/**
|
|
41
|
+
* The region axis (2.3), and it is deliberately NOT a second `applies_to`.
|
|
42
|
+
*
|
|
43
|
+
* `applies_to` decides WHETHER a check applies; a region decides HOW SEVERELY.
|
|
44
|
+
* A legal page is not more or less *applicable* in Germany — it is more or less
|
|
45
|
+
* *optional*, because TMG 5 and DSGVO Art. 13 make it owed rather than advisable.
|
|
46
|
+
* Modelling it as a tier escalation keeps one check with one implementation and
|
|
47
|
+
* puts the jurisdiction where it belongs: on the consequence.
|
|
48
|
+
*/
|
|
49
|
+
export type Region = 'de' | 'eu' | 'us' | 'unspecified';
|
|
50
|
+
|
|
51
|
+
export interface CheckDef {
|
|
52
|
+
id: string;
|
|
53
|
+
title: string;
|
|
54
|
+
applies_to: SiteType[];
|
|
55
|
+
tier: Tier;
|
|
56
|
+
why: string;
|
|
57
|
+
remediation: string;
|
|
58
|
+
verification: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface Finding {
|
|
62
|
+
check: string;
|
|
63
|
+
tier: Tier;
|
|
64
|
+
/** `path:line` — the step's own verify line requires a location, not a name. */
|
|
65
|
+
location: string;
|
|
66
|
+
evidence: string;
|
|
67
|
+
remediation: string;
|
|
68
|
+
verification: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface Skipped {
|
|
72
|
+
check: string;
|
|
73
|
+
tier: Tier;
|
|
74
|
+
/** The SITE TYPE, verbatim — 2.3 requires the type to be the stated reason. */
|
|
75
|
+
reason: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** A tier the region axis moved, and why. Reported so the axis is visible. */
|
|
79
|
+
export interface Escalated {
|
|
80
|
+
check: string;
|
|
81
|
+
from: Tier;
|
|
82
|
+
to: Tier;
|
|
83
|
+
why: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface Report {
|
|
87
|
+
site_type: SiteType;
|
|
88
|
+
region: Region;
|
|
89
|
+
enabled: boolean;
|
|
90
|
+
findings: Finding[];
|
|
91
|
+
skipped: Skipped[];
|
|
92
|
+
/** Checks that applied and found nothing. */
|
|
93
|
+
passed: string[];
|
|
94
|
+
/** Applicable checks with no implementation yet — never counted as passed. */
|
|
95
|
+
unimplemented: string[];
|
|
96
|
+
/** Tiers the region axis raised. Empty on `unspecified`, by construction. */
|
|
97
|
+
escalated: Escalated[];
|
|
98
|
+
scanned_files: number;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface Escalation {
|
|
102
|
+
check: string;
|
|
103
|
+
region: Region;
|
|
104
|
+
to: Tier;
|
|
105
|
+
why: string;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function loadConfig(root = REPO_ROOT): {
|
|
109
|
+
checks: CheckDef[];
|
|
110
|
+
siteTypes: SiteType[];
|
|
111
|
+
regions: Region[];
|
|
112
|
+
escalations: Escalation[];
|
|
113
|
+
} {
|
|
114
|
+
const abs = path.join(root, CONFIG_REL);
|
|
115
|
+
let raw: string;
|
|
116
|
+
try {
|
|
117
|
+
raw = fs.readFileSync(abs, 'utf-8');
|
|
118
|
+
} catch {
|
|
119
|
+
throw new DeadScopeError(
|
|
120
|
+
'check_web_launch_readiness',
|
|
121
|
+
`${CONFIG_REL} is missing — the config IS this command's corpus, and an absent ` +
|
|
122
|
+
'one cannot be read as "no checks to run".',
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
const doc = JSON.parse(raw) as {
|
|
126
|
+
checks?: CheckDef[];
|
|
127
|
+
site_types?: { values?: SiteType[] };
|
|
128
|
+
regions?: { values?: Region[]; escalations?: Escalation[] };
|
|
129
|
+
};
|
|
130
|
+
const checks = doc.checks ?? [];
|
|
131
|
+
const siteTypes = doc.site_types?.values ?? [];
|
|
132
|
+
if (checks.length === 0 || siteTypes.length === 0) {
|
|
133
|
+
throw new DeadScopeError(
|
|
134
|
+
'check_web_launch_readiness',
|
|
135
|
+
`${CONFIG_REL} carries no checks or no site types — an empty corpus checks nothing.`,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
const regions = doc.regions?.values ?? [];
|
|
139
|
+
const escalations = doc.regions?.escalations ?? [];
|
|
140
|
+
if (regions.length === 0) {
|
|
141
|
+
throw new DeadScopeError(
|
|
142
|
+
'check_web_launch_readiness',
|
|
143
|
+
`${CONFIG_REL} carries no region axis — a DE site would silently get the ` +
|
|
144
|
+
'situational tier for a legally owed page.',
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
return { checks, siteTypes, regions, escalations };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Apply the region escalation to a check's tier.
|
|
152
|
+
*
|
|
153
|
+
* Returns the escalated tier and the reason, or the original tier and null. The
|
|
154
|
+
* reason travels with the tier because a reader seeing `required-legal-pages`
|
|
155
|
+
* as CRITICAL on one run and SITUATIONAL on another needs the axis that moved
|
|
156
|
+
* it, not just the outcome.
|
|
157
|
+
*/
|
|
158
|
+
export function tierFor(
|
|
159
|
+
c: CheckDef,
|
|
160
|
+
region: Region,
|
|
161
|
+
escalations: readonly Escalation[],
|
|
162
|
+
): { tier: Tier; escalatedBy: string | null } {
|
|
163
|
+
const e = escalations.find((x) => x.check === c.id && x.region === region);
|
|
164
|
+
return e === undefined ? { tier: c.tier, escalatedBy: null } : { tier: e.to, escalatedBy: e.why };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** `web_launch_readiness.enabled: true` in `.agent-settings.yml` — default OFF. */
|
|
168
|
+
export function enabled(root: string): boolean {
|
|
169
|
+
let raw: string;
|
|
170
|
+
try {
|
|
171
|
+
raw = fs.readFileSync(path.join(root, '.agent-settings.yml'), 'utf-8');
|
|
172
|
+
} catch {
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
let inSection = false;
|
|
176
|
+
for (const line of raw.split('\n')) {
|
|
177
|
+
if (/^web_launch_readiness:\s*$/.test(line)) {
|
|
178
|
+
inSection = true;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
if (/^\S/.test(line)) {
|
|
182
|
+
inSection = false;
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (inSection && /^\s{2}enabled:\s*true\s*$/.test(line)) return true;
|
|
186
|
+
}
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/* ── the one implemented check: staging indexability ───────────────────────── */
|
|
191
|
+
|
|
192
|
+
const NOINDEX_RE = /<meta[^>]+name\s*=\s*["']robots["'][^>]*content\s*=\s*["'][^"']*noindex/i;
|
|
193
|
+
const XROBOTS_RE = /x-robots-tag[^\n]*noindex/i;
|
|
194
|
+
/** `Disallow: /` with nothing after it — a blanket block, not a path rule. */
|
|
195
|
+
const BLANKET_DISALLOW_RE = /^\s*Disallow:\s*\/\s*$/im;
|
|
196
|
+
|
|
197
|
+
export interface Located {
|
|
198
|
+
file: string;
|
|
199
|
+
line: number;
|
|
200
|
+
text: string;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Walk a build directory for indexability leftovers.
|
|
205
|
+
*
|
|
206
|
+
* Returns a LOCATION per hit, because the step's verify line asks for a
|
|
207
|
+
* `file:line` and a finding without one cannot be acted on.
|
|
208
|
+
*/
|
|
209
|
+
export function scanIndexability(buildDir: string): { hits: Located[]; files: number } {
|
|
210
|
+
const hits: Located[] = [];
|
|
211
|
+
let files = 0;
|
|
212
|
+
const walk = (dir: string): void => {
|
|
213
|
+
let entries: fs.Dirent[];
|
|
214
|
+
try {
|
|
215
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
216
|
+
} catch {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
for (const e of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
220
|
+
const p = path.join(dir, e.name);
|
|
221
|
+
if (e.isDirectory()) {
|
|
222
|
+
if (e.name === 'node_modules' || e.name === '.git') continue;
|
|
223
|
+
walk(p);
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (!/\.(html?|txt|xml|js|jsx|ts|tsx|vue|svelte|astro)$/i.test(e.name)) continue;
|
|
227
|
+
files += 1;
|
|
228
|
+
let text: string;
|
|
229
|
+
try {
|
|
230
|
+
text = fs.readFileSync(p, 'utf-8');
|
|
231
|
+
} catch {
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
const isRobots = path.basename(p).toLowerCase() === 'robots.txt';
|
|
235
|
+
text.split('\n').forEach((line, i) => {
|
|
236
|
+
const rel = path.relative(buildDir, p);
|
|
237
|
+
if (NOINDEX_RE.test(line) || XROBOTS_RE.test(line)) {
|
|
238
|
+
hits.push({ file: rel, line: i + 1, text: line.trim().slice(0, 160) });
|
|
239
|
+
} else if (isRobots && BLANKET_DISALLOW_RE.test(line)) {
|
|
240
|
+
hits.push({ file: rel, line: i + 1, text: line.trim().slice(0, 160) });
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
walk(buildDir);
|
|
246
|
+
return { hits, files };
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
/* ── the remaining checks (2.2 and 2.3) ─────────────────────────────────────── */
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Every scannable file in a build directory, read once.
|
|
254
|
+
*
|
|
255
|
+
* The single walk replaces the per-check walk the one-check version could get
|
|
256
|
+
* away with: eight checks each walking the tree is eight times the IO for the
|
|
257
|
+
* same bytes, and — worse — eight chances for the walkers to disagree about
|
|
258
|
+
* what counts as a file.
|
|
259
|
+
*/
|
|
260
|
+
export interface SourceFile {
|
|
261
|
+
rel: string;
|
|
262
|
+
base: string;
|
|
263
|
+
text: string;
|
|
264
|
+
lines: string[];
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const SCANNABLE_RE = /\.(html?|txt|xml|js|jsx|ts|tsx|vue|svelte|astro|md)$/i;
|
|
268
|
+
|
|
269
|
+
export function readTree(buildDir: string): SourceFile[] {
|
|
270
|
+
const out: SourceFile[] = [];
|
|
271
|
+
const walk = (dir: string): void => {
|
|
272
|
+
let entries: fs.Dirent[];
|
|
273
|
+
try {
|
|
274
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
275
|
+
} catch {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
for (const e of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
279
|
+
const abs = path.join(dir, e.name);
|
|
280
|
+
if (e.isDirectory()) {
|
|
281
|
+
if (e.name === 'node_modules' || e.name === '.git') continue;
|
|
282
|
+
walk(abs);
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
if (!SCANNABLE_RE.test(e.name)) continue;
|
|
286
|
+
let text: string;
|
|
287
|
+
try {
|
|
288
|
+
text = fs.readFileSync(abs, 'utf-8');
|
|
289
|
+
} catch {
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
out.push({
|
|
293
|
+
rel: path.relative(buildDir, abs),
|
|
294
|
+
base: e.name.toLowerCase(),
|
|
295
|
+
text,
|
|
296
|
+
lines: text.split('\n'),
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
walk(buildDir);
|
|
301
|
+
return out;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/** An HTML page, as opposed to a robots.txt or a source module. */
|
|
305
|
+
function isPage(f: SourceFile): boolean {
|
|
306
|
+
return /\.html?$/i.test(f.base);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* A check's implementation: files in, located hits out.
|
|
311
|
+
*
|
|
312
|
+
* Returning an EMPTY array means "applied and found nothing" — which is a pass.
|
|
313
|
+
* A check that cannot decide must not return an empty array; it must not be in
|
|
314
|
+
* `IMPLEMENTED` at all, so it reports as unimplemented instead. That is the one
|
|
315
|
+
* rule keeping the silent-green defect out of this table.
|
|
316
|
+
*/
|
|
317
|
+
type Impl = (files: readonly SourceFile[]) => Located[];
|
|
318
|
+
|
|
319
|
+
/** `http://` on a host we serve, excluding the XML/DTD namespace URLs. */
|
|
320
|
+
const INSECURE_ASSET_RE =
|
|
321
|
+
/(?:src|href|action)\s*=\s*["']http:\/\/(?!localhost|127\.0\.0\.1|schemas?\.|www\.w3\.org)/i;
|
|
322
|
+
|
|
323
|
+
const httpsEnforcement: Impl = (files) => {
|
|
324
|
+
const hits: Located[] = [];
|
|
325
|
+
for (const f of files) {
|
|
326
|
+
if (!isPage(f)) continue;
|
|
327
|
+
f.lines.forEach((line, i) => {
|
|
328
|
+
if (INSECURE_ASSET_RE.test(line)) {
|
|
329
|
+
hits.push({ file: f.rel, line: i + 1, text: line.trim().slice(0, 160) });
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
return hits;
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* A custom 404 page exists somewhere in the build.
|
|
338
|
+
*
|
|
339
|
+
* A whole-tree question, not a per-file one, so the hit it reports is located at
|
|
340
|
+
* the build root rather than at a file — an absence has no line number, and
|
|
341
|
+
* inventing one would be worse than admitting the shape of the finding.
|
|
342
|
+
*/
|
|
343
|
+
const customErrorRoute: Impl = (files) => {
|
|
344
|
+
const found = files.some((f) => /^(404|not-found)(\.html?|\/index\.html?)?$/i.test(f.rel.replace(/\\/g, '/')) || /(^|\/)404\.html?$/i.test(f.rel));
|
|
345
|
+
return found ? [] : [{ file: '.', line: 0, text: 'no 404.html or not-found page in the build output' }];
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
const TITLE_RE = /<title[^>]*>\s*([^<]{1,200}?)\s*<\/title>/i;
|
|
349
|
+
const DESC_RE = /<meta[^>]+name\s*=\s*["']description["'][^>]*content\s*=\s*["']\s*([^"']{1,400}?)\s*["']/i;
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Per-route title and description, and the DUPLICATE case counts.
|
|
353
|
+
*
|
|
354
|
+
* The obvious implementation checks presence. Presence is the easy half: a
|
|
355
|
+
* layout that puts one hard-coded title on every route passes a presence check
|
|
356
|
+
* and is exactly the defect the step names ("per-route"). So a title shared by
|
|
357
|
+
* more than one page is a hit, with both locations reported.
|
|
358
|
+
*/
|
|
359
|
+
const perRouteMetadata: Impl = (files) => {
|
|
360
|
+
const hits: Located[] = [];
|
|
361
|
+
const titles = new Map<string, string[]>();
|
|
362
|
+
for (const f of files) {
|
|
363
|
+
if (!isPage(f)) continue;
|
|
364
|
+
const tm = TITLE_RE.exec(f.text);
|
|
365
|
+
if (tm === null) {
|
|
366
|
+
hits.push({ file: f.rel, line: lineOf(f, '<title'), text: 'no <title> on this page' });
|
|
367
|
+
} else {
|
|
368
|
+
const key = (tm[1] ?? '').toLowerCase();
|
|
369
|
+
titles.set(key, [...(titles.get(key) ?? []), f.rel]);
|
|
370
|
+
}
|
|
371
|
+
if (!DESC_RE.test(f.text)) {
|
|
372
|
+
hits.push({
|
|
373
|
+
file: f.rel,
|
|
374
|
+
line: lineOf(f, 'name="description"'),
|
|
375
|
+
text: 'no <meta name="description"> on this page',
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
for (const [title, where] of titles) {
|
|
380
|
+
if (where.length < 2) continue;
|
|
381
|
+
hits.push({
|
|
382
|
+
file: where[0] ?? '.',
|
|
383
|
+
line: 0,
|
|
384
|
+
text: `title "${title}" is shared by ${String(where.length)} pages (${where.join(', ')}) — present, but not per-route`,
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
return hits;
|
|
388
|
+
};
|
|
389
|
+
|
|
390
|
+
/** Content images without alt. `alt=""` is DECORATIVE and deliberately valid. */
|
|
391
|
+
const IMG_RE = /<img\b[^>]*>/gi;
|
|
392
|
+
const imageAlternativeText: Impl = (files) => {
|
|
393
|
+
const hits: Located[] = [];
|
|
394
|
+
for (const f of files) {
|
|
395
|
+
if (!isPage(f)) continue;
|
|
396
|
+
f.lines.forEach((line, i) => {
|
|
397
|
+
for (const tag of line.match(IMG_RE) ?? []) {
|
|
398
|
+
// `alt=""` is the ARIA-correct marking for a decorative image
|
|
399
|
+
// and must NOT be a finding: flagging it would push authors to
|
|
400
|
+
// write filler alt text, which is worse for a screen reader
|
|
401
|
+
// than the empty string that tells it to skip.
|
|
402
|
+
if (/\balt\s*=/i.test(tag)) continue;
|
|
403
|
+
hits.push({ file: f.rel, line: i + 1, text: tag.slice(0, 160) });
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
return hits;
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
const documentHeadBasics: Impl = (files) => {
|
|
411
|
+
const hits: Located[] = [];
|
|
412
|
+
for (const f of files) {
|
|
413
|
+
if (!isPage(f)) continue;
|
|
414
|
+
if (!/<html[^>]+\blang\s*=\s*["'][a-z]/i.test(f.text)) {
|
|
415
|
+
hits.push({ file: f.rel, line: lineOf(f, '<html'), text: 'no lang on <html>' });
|
|
416
|
+
}
|
|
417
|
+
if (!/<meta[^>]+charset\s*=/i.test(f.text)) {
|
|
418
|
+
hits.push({ file: f.rel, line: lineOf(f, '<head'), text: 'no <meta charset>' });
|
|
419
|
+
}
|
|
420
|
+
if (!/<meta[^>]+name\s*=\s*["']viewport["']/i.test(f.text)) {
|
|
421
|
+
hits.push({ file: f.rel, line: lineOf(f, '<head'), text: 'no <meta name="viewport">' });
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
return hits;
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Canonical and sitemap agree with each other.
|
|
429
|
+
*
|
|
430
|
+
* Two failure shapes, and the second is the one a presence check misses: a
|
|
431
|
+
* canonical pointing at a host the sitemap never mentions means one of the two
|
|
432
|
+
* was copied from another project, and the page that ends up indexed is not the
|
|
433
|
+
* page anyone chose.
|
|
434
|
+
*/
|
|
435
|
+
const canonicalAndSitemap: Impl = (files) => {
|
|
436
|
+
const hits: Located[] = [];
|
|
437
|
+
const sitemap = files.find((f) => f.base === 'sitemap.xml');
|
|
438
|
+
for (const f of files) {
|
|
439
|
+
if (!isPage(f)) continue;
|
|
440
|
+
const m = /<link[^>]+rel\s*=\s*["']canonical["'][^>]*href\s*=\s*["']([^"']+)["']/i.exec(f.text);
|
|
441
|
+
if (m === null) {
|
|
442
|
+
hits.push({ file: f.rel, line: lineOf(f, '<head'), text: 'no rel="canonical"' });
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
const href = m[1] ?? '';
|
|
446
|
+
const host = /^https?:\/\/([^/]+)/i.exec(href)?.[1];
|
|
447
|
+
if (sitemap !== undefined && host !== undefined && !sitemap.text.includes(host)) {
|
|
448
|
+
hits.push({
|
|
449
|
+
file: f.rel,
|
|
450
|
+
line: lineOf(f, 'rel="canonical"'),
|
|
451
|
+
text: `canonical host ${host} appears nowhere in sitemap.xml`,
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
return hits;
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
const LEGAL_DE = [/impressum/i, /datenschutz/i];
|
|
459
|
+
const LEGAL_GENERIC = [/privacy/i, /(terms|imprint|legal)/i];
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* The legally owed pages exist.
|
|
463
|
+
*
|
|
464
|
+
* Matched on the PATH, never on page text: a link to `/impressum` from a footer
|
|
465
|
+
* is not an Impressum, and a check that accepted the link would pass every site
|
|
466
|
+
* that links to a page it never built.
|
|
467
|
+
*/
|
|
468
|
+
const requiredLegalPages: Impl = (files) => {
|
|
469
|
+
const paths = files.map((f) => f.rel.replace(/\\/g, '/'));
|
|
470
|
+
const missing: string[] = [];
|
|
471
|
+
const has = (res: RegExp[]): boolean => res.every((re) => paths.some((p) => re.test(p)));
|
|
472
|
+
if (!has(LEGAL_DE) && !has(LEGAL_GENERIC)) {
|
|
473
|
+
if (!paths.some((p) => /impressum|imprint|legal/i.test(p))) missing.push('imprint/Impressum');
|
|
474
|
+
if (!paths.some((p) => /datenschutz|privacy/i.test(p))) missing.push('privacy/Datenschutz');
|
|
475
|
+
}
|
|
476
|
+
return missing.length === 0
|
|
477
|
+
? []
|
|
478
|
+
: [{ file: '.', line: 0, text: `no page found for: ${missing.join(', ')}` }];
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Analytics loads only behind consent.
|
|
483
|
+
*
|
|
484
|
+
* The finding is analytics present with NO consent mechanism anywhere in the
|
|
485
|
+
* build — never "analytics present", which would flag every site that does
|
|
486
|
+
* consent correctly. The gate cannot see the wiring order, and says so in the
|
|
487
|
+
* evidence rather than implying it checked.
|
|
488
|
+
*/
|
|
489
|
+
const ANALYTICS_RE = /(googletagmanager\.com|google-analytics\.com|gtag\(|plausible\.io|matomo|segment\.com|hotjar)/i;
|
|
490
|
+
const CONSENT_RE = /(consent|cookiebanner|cookie-banner|cookieconsent|klaro|usercentrics|borlabs|osano)/i;
|
|
491
|
+
const analyticsAndConsent: Impl = (files) => {
|
|
492
|
+
const hits: Located[] = [];
|
|
493
|
+
// Prose is excluded from BOTH sides, and the fixture is why: a `.md` file
|
|
494
|
+
// in the build tree describing the consent banner matched CONSENT_RE, so
|
|
495
|
+
// the check reported a pass on a fixture seeded to fire it. Documentation
|
|
496
|
+
// saying a thing exists is not the thing existing — and the same argument
|
|
497
|
+
// runs the other way, so an analytics name mentioned in a README must not
|
|
498
|
+
// count as analytics either.
|
|
499
|
+
const code = files.filter((f) => !/\.md$/i.test(f.base));
|
|
500
|
+
const anyConsent = code.some((f) => CONSENT_RE.test(f.text));
|
|
501
|
+
if (anyConsent) return hits;
|
|
502
|
+
for (const f of code) {
|
|
503
|
+
f.lines.forEach((line, i) => {
|
|
504
|
+
if (!ANALYTICS_RE.test(line)) return;
|
|
505
|
+
hits.push({
|
|
506
|
+
file: f.rel,
|
|
507
|
+
line: i + 1,
|
|
508
|
+
text:
|
|
509
|
+
`${line.trim().slice(0, 120)} — analytics present and no consent mechanism ` +
|
|
510
|
+
'found anywhere in the build. Load order is NOT checked here.',
|
|
511
|
+
});
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
return hits;
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
/** First line containing `needle`, 1-indexed; 1 when absent (an absence has no line). */
|
|
518
|
+
function lineOf(f: SourceFile, needle: string): number {
|
|
519
|
+
const i = f.lines.findIndex((l) => l.toLowerCase().includes(needle.toLowerCase()));
|
|
520
|
+
return i < 0 ? 1 : i + 1;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
export const IMPLS: Readonly<Record<string, Impl>> = {
|
|
524
|
+
'https-enforcement': httpsEnforcement,
|
|
525
|
+
'custom-error-route': customErrorRoute,
|
|
526
|
+
'per-route-metadata': perRouteMetadata,
|
|
527
|
+
'image-alternative-text': imageAlternativeText,
|
|
528
|
+
'document-head-basics': documentHeadBasics,
|
|
529
|
+
'canonical-and-sitemap-coherence': canonicalAndSitemap,
|
|
530
|
+
'required-legal-pages': requiredLegalPages,
|
|
531
|
+
'analytics-and-consent-wiring': analyticsAndConsent,
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
/** Checks with a real implementation. Everything else reports UNIMPLEMENTED. */
|
|
535
|
+
export const IMPLEMENTED: readonly string[] = [
|
|
536
|
+
'staging-noindex-leftover',
|
|
537
|
+
...Object.keys(IMPLS),
|
|
538
|
+
];
|
|
539
|
+
|
|
540
|
+
export function audit(
|
|
541
|
+
buildDir: string,
|
|
542
|
+
siteType: SiteType,
|
|
543
|
+
root = REPO_ROOT,
|
|
544
|
+
region: Region = 'unspecified',
|
|
545
|
+
): Report {
|
|
546
|
+
const { checks, siteTypes, regions, escalations } = loadConfig(root);
|
|
547
|
+
if (!siteTypes.includes(siteType)) {
|
|
548
|
+
throw new DeadScopeError(
|
|
549
|
+
'check_web_launch_readiness',
|
|
550
|
+
`unknown site type "${siteType}" — registered: ${siteTypes.join(', ')}`,
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
if (!regions.includes(region)) {
|
|
554
|
+
throw new DeadScopeError(
|
|
555
|
+
'check_web_launch_readiness',
|
|
556
|
+
`unknown region "${region}" — registered: ${regions.join(', ')}`,
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
const findings: Finding[] = [];
|
|
560
|
+
const skipped: Skipped[] = [];
|
|
561
|
+
const passed: string[] = [];
|
|
562
|
+
const unimplemented: string[] = [];
|
|
563
|
+
const escalated: Escalated[] = [];
|
|
564
|
+
// ONE walk for every check. Eight walkers over the same bytes is eight
|
|
565
|
+
// times the IO and eight chances to disagree about what counts as a file.
|
|
566
|
+
const files = readTree(buildDir);
|
|
567
|
+
|
|
568
|
+
for (const c of checks) {
|
|
569
|
+
const { tier, escalatedBy } = tierFor(c, region, escalations);
|
|
570
|
+
if (escalatedBy !== null) {
|
|
571
|
+
escalated.push({ check: c.id, from: c.tier, to: tier, why: escalatedBy });
|
|
572
|
+
}
|
|
573
|
+
if (!c.applies_to.includes(siteType)) {
|
|
574
|
+
// The site type IS the reason, verbatim. 2.3 requires exactly this.
|
|
575
|
+
skipped.push({ check: c.id, tier, reason: `site type is ${siteType}` });
|
|
576
|
+
continue;
|
|
577
|
+
}
|
|
578
|
+
if (!IMPLEMENTED.includes(c.id)) {
|
|
579
|
+
// Never counted as passed: an unimplemented check that reported
|
|
580
|
+
// "clean" would be the silent-green defect this repository names.
|
|
581
|
+
unimplemented.push(c.id);
|
|
582
|
+
continue;
|
|
583
|
+
}
|
|
584
|
+
const impl = IMPLS[c.id];
|
|
585
|
+
const hits =
|
|
586
|
+
impl === undefined
|
|
587
|
+
? scanIndexability(buildDir).hits
|
|
588
|
+
: impl(files);
|
|
589
|
+
if (hits.length === 0) {
|
|
590
|
+
passed.push(c.id);
|
|
591
|
+
continue;
|
|
592
|
+
}
|
|
593
|
+
for (const h of hits) {
|
|
594
|
+
findings.push({
|
|
595
|
+
check: c.id,
|
|
596
|
+
tier,
|
|
597
|
+
location: `${h.file}:${String(h.line)}`,
|
|
598
|
+
evidence: h.text,
|
|
599
|
+
remediation: c.remediation,
|
|
600
|
+
verification: c.verification,
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
return {
|
|
605
|
+
site_type: siteType,
|
|
606
|
+
region,
|
|
607
|
+
enabled: enabled(root),
|
|
608
|
+
findings,
|
|
609
|
+
skipped,
|
|
610
|
+
passed,
|
|
611
|
+
unimplemented,
|
|
612
|
+
escalated,
|
|
613
|
+
scanned_files: files.length,
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
const TIER_ORDER: readonly Tier[] = ['critical', 'high', 'medium', 'situational'];
|
|
618
|
+
|
|
619
|
+
/** Report order: critical → high → medium → situational-applicable → skipped. */
|
|
620
|
+
export function render(r: Report): string {
|
|
621
|
+
const out: string[] = [];
|
|
622
|
+
out.push(`site type: ${r.site_type} · region: ${r.region}`);
|
|
623
|
+
for (const e of r.escalated) {
|
|
624
|
+
// Printed BEFORE the findings, because a reader who sees a check at
|
|
625
|
+
// CRITICAL on one run and SITUATIONAL on another needs the axis that
|
|
626
|
+
// moved it, not just the outcome.
|
|
627
|
+
out.push(` escalated by region: ${e.check} ${e.from} → ${e.to} — ${e.why}`);
|
|
628
|
+
}
|
|
629
|
+
for (const tier of TIER_ORDER) {
|
|
630
|
+
const f = r.findings.filter((x) => x.tier === tier);
|
|
631
|
+
if (f.length === 0) continue;
|
|
632
|
+
out.push('', `${tier.toUpperCase()} (${String(f.length)})`);
|
|
633
|
+
for (const x of f) {
|
|
634
|
+
out.push(` ${x.location} ${x.check}`);
|
|
635
|
+
out.push(` evidence: ${x.evidence}`);
|
|
636
|
+
out.push(` remediation: ${x.remediation}`);
|
|
637
|
+
out.push(` verification: ${x.verification}`);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
if (r.passed.length > 0) out.push('', `PASSED: ${r.passed.join(', ')}`);
|
|
641
|
+
if (r.unimplemented.length > 0) {
|
|
642
|
+
out.push('', `NOT YET IMPLEMENTED (applicable, not audited): ${r.unimplemented.join(', ')}`);
|
|
643
|
+
}
|
|
644
|
+
if (r.skipped.length > 0) {
|
|
645
|
+
out.push('', 'SKIPPED — not applicable to this site type');
|
|
646
|
+
for (const s of r.skipped) out.push(` ${s.check}: ${s.reason}`);
|
|
647
|
+
}
|
|
648
|
+
return out.join('\n');
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
export function main(argv: string[] = process.argv.slice(2), root = REPO_ROOT): number {
|
|
652
|
+
const arg = (f: string): string | undefined => {
|
|
653
|
+
const i = argv.indexOf(f);
|
|
654
|
+
return i >= 0 ? argv[i + 1] : undefined;
|
|
655
|
+
};
|
|
656
|
+
const build = arg('--build');
|
|
657
|
+
const siteType = arg('--site-type') as SiteType | undefined;
|
|
658
|
+
const region = (arg('--region') ?? 'unspecified') as Region;
|
|
659
|
+
if (build === undefined || siteType === undefined) {
|
|
660
|
+
process.stderr.write(
|
|
661
|
+
'usage: check_web_launch_readiness --build <dir> --site-type <type> ' +
|
|
662
|
+
'[--region <de|eu|us|unspecified>] [--json]\n',
|
|
663
|
+
);
|
|
664
|
+
return 2;
|
|
665
|
+
}
|
|
666
|
+
if (!enabled(root) && !argv.includes('--force')) {
|
|
667
|
+
process.stdout.write(
|
|
668
|
+
'web-launch-readiness is DEFAULT-OFF until the pre-registered benchmark returns\n' +
|
|
669
|
+
'positive (claim:web-launch-readiness-finds-more, status unbacked). Enable with\n' +
|
|
670
|
+
'`web_launch_readiness.enabled: true` in .agent-settings.yml, or pass --force.\n',
|
|
671
|
+
);
|
|
672
|
+
return 0;
|
|
673
|
+
}
|
|
674
|
+
let r: Report;
|
|
675
|
+
try {
|
|
676
|
+
r = audit(build, siteType, root, region);
|
|
677
|
+
reportScanned({
|
|
678
|
+
gate: 'check_web_launch_readiness',
|
|
679
|
+
scanned: r.scanned_files,
|
|
680
|
+
units: 'build file(s)',
|
|
681
|
+
roots: [build],
|
|
682
|
+
allowEmpty:
|
|
683
|
+
'OPTIONAL_INPUT: a build directory may legitimately hold no scannable file ' +
|
|
684
|
+
'when the caller points at an unbuilt tree; a missing config is a separate ' +
|
|
685
|
+
'hard error in loadConfig()',
|
|
686
|
+
});
|
|
687
|
+
} catch (e) {
|
|
688
|
+
if (e instanceof DeadScopeError) {
|
|
689
|
+
process.stderr.write(`❌ ${e.message}\n`);
|
|
690
|
+
return 2;
|
|
691
|
+
}
|
|
692
|
+
throw e;
|
|
693
|
+
}
|
|
694
|
+
if (argv.includes('--json')) {
|
|
695
|
+
process.stdout.write(`${JSON.stringify(r, null, 2)}\n`);
|
|
696
|
+
} else {
|
|
697
|
+
process.stdout.write(`${render(r)}\n`);
|
|
698
|
+
}
|
|
699
|
+
const blocking = r.findings.filter((f) => f.tier === 'critical' || f.tier === 'high');
|
|
700
|
+
return blocking.length > 0 ? 1 : 0;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
if (path.resolve(process.argv[1] ?? '') === path.resolve(HERE)) {
|
|
704
|
+
process.exit(main());
|
|
705
|
+
}
|