@event4u/agent-config 14.12.0 → 14.14.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 +118 -155
- 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 +145 -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/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-comment-discipline.md +6 -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 +252 -8
- package/dist/agent-src/scripts/guarded_baseline.ts +343 -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 +516 -0
- package/dist/agent-src/scripts/ticket_bundles.ts +84 -0
- package/dist/agent-src/scripts/update_roadmap_progress.ts +16 -12
- 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/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 +17 -1
- 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/react-shadcn-ui/SKILL.md +1 -1
- package/dist/agent-src/skills/skill-writing/references/procedure.md +5 -5
- 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/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 +45 -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-JCW7ZLHK.js → chunk-4FS4WRXP.js} +5 -0
- package/dist/cli-delegate/{chunk-OMIVVCG2.js → chunk-A4QJ6ENT.js} +24 -0
- package/dist/cli-delegate/{chunk-JJA2QEWA.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 +80 -11
- 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 +58 -58
- 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 +2900 -1049
- 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 +634 -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 +4895 -2627
- package/dist/server/schemas/settings.js +3 -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 +10 -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/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 +18 -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/llms.txt +2 -2
- package/package.json +5 -2
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +252 -8
- package/src/agent-src/scripts/guarded_baseline.ts +343 -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 +516 -0
- package/src/agent-src/scripts/ticket_bundles.ts +84 -0
- package/src/agent-src/scripts/update_roadmap_progress.ts +16 -12
- 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 +32 -3
- package/src/config/assurance-capability-registry.json +21 -9
- 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 +80 -0
- package/src/config/drafting-channels.yml +43 -0
- package/src/config/estate-count-budget.json +57 -36
- package/src/config/evaluator-budgets.json +14 -14
- package/src/config/gate-coverage.yml +729 -63
- package/src/config/gate-reachability-exemptions.json +21 -0
- package/src/config/gate-violation-baselines.json +42 -19
- 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 +16 -15
- package/src/config/preamble-payload-budget.json +12 -4
- 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 +16 -2
- package/src/config/rule-stub-ceilings.json +133 -112
- package/src/config/turnaround-budget.json +66 -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 +23 -0
- package/src/scripts/_lib/activation_ladder.ts +255 -0
- package/src/scripts/_lib/activation_receipt_producer.ts +341 -0
- package/src/scripts/_lib/activation_states.ts +88 -0
- package/src/scripts/_lib/adherence_detectors.ts +143 -0
- package/src/scripts/_lib/adr_frontmatter.ts +26 -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_pair_delta.ts +349 -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/carrier_status.ts +118 -0
- package/src/scripts/_lib/cascade_stage_enumeration.ts +92 -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/corpus_manifest.ts +726 -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 +282 -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/estate_carrier_cases.ts +72 -0
- package/src/scripts/_lib/eval_publication.ts +354 -0
- package/src/scripts/_lib/evaluation_cascade.ts +452 -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/evolution_roi.ts +562 -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/generated_by.ts +66 -0
- package/src/scripts/_lib/harness_evolution_guards.ts +239 -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/lexical_shortlist.ts +215 -0
- package/src/scripts/_lib/llm_candidate_proposer.ts +461 -0
- package/src/scripts/_lib/llm_proposer_transport.ts +153 -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/pathology_archive.ts +393 -0
- package/src/scripts/_lib/prefix_stable_surfaces.ts +123 -0
- package/src/scripts/_lib/privacy_class.ts +47 -0
- package/src/scripts/_lib/promotion_capability.ts +315 -0
- package/src/scripts/_lib/promotion_evidence.ts +414 -0
- package/src/scripts/_lib/promotion_review.ts +294 -0
- package/src/scripts/_lib/prompt_shape.ts +92 -0
- package/src/scripts/_lib/regression_neighbourhood.ts +259 -0
- package/src/scripts/_lib/release_highlights.ts +70 -1
- package/src/scripts/_lib/release_material.ts +125 -2
- 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/routing_corpus.ts +307 -0
- package/src/scripts/_lib/routing_index_input.ts +104 -0
- package/src/scripts/_lib/rule_injection.ts +22 -1
- package/src/scripts/_lib/runtime_journal.ts +1499 -0
- package/src/scripts/_lib/runtime_wiring_checks.ts +430 -0
- package/src/scripts/_lib/semantic_noop.ts +167 -0
- package/src/scripts/_lib/skill_catalogue.ts +11 -1
- 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/activation_receipt.ts +258 -0
- 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/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/cross_exam.ts +128 -0
- package/src/scripts/ai_council/disagreement_signal.ts +338 -0
- package/src/scripts/ai_council/explain_route.ts +157 -0
- package/src/scripts/ai_council/information_gain.ts +293 -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/leakage_corpus.ts +385 -0
- package/src/scripts/ai_council/leakage_patterns.ts +453 -0
- package/src/scripts/ai_council/minority_retention.ts +171 -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/recouncil_savings.ts +299 -0
- package/src/scripts/ai_council/replay_route.ts +223 -0
- package/src/scripts/ai_council/response_record.ts +50 -0
- package/src/scripts/ai_council/reviewer_assignment.ts +279 -0
- package/src/scripts/ai_council/routing_training_row.ts +197 -0
- package/src/scripts/ai_council/synthesis_strategy.ts +159 -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 +131 -10
- 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 +34 -1
- package/src/scripts/check_claims.ts +576 -6
- 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 +347 -25
- 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 +114 -3
- 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_release_highlights.ts +96 -13
- package/src/scripts/check_roadmap_trackable.ts +17 -2
- 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 +26 -3
- 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/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/corpus_manifest.ts +235 -0
- 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/dispatch_r2_reviewer.ts +46 -5
- package/src/scripts/evolution_lab.ts +1153 -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 -16
- 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/comment_discipline_hook.ts +146 -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 +10 -0
- package/src/scripts/hooks/turn_end_gate_hook.ts +9 -1
- 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/language_mirror_hook.ts +14 -2
- package/src/scripts/lint_adr_sweep_routing.ts +12 -0
- package/src/scripts/lint_canonical_terms.ts +604 -0
- package/src/scripts/lint_carrier_integrity.ts +820 -0
- package/src/scripts/lint_code_comments.ts +643 -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_plan_risk_register.ts +39 -19
- package/src/scripts/lint_promotion_paths.ts +779 -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 +426 -23
- package/src/scripts/lint_ticket_buildable.ts +17 -1
- package/src/scripts/llm_propose.ts +256 -0
- 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_delivery_sets.ts +361 -0
- package/src/scripts/measure_docs_dead_links.ts +348 -0
- package/src/scripts/measure_host_capture.ts +461 -0
- package/src/scripts/measure_routing_signal.ts +307 -0
- package/src/scripts/migration_status.ts +3 -3
- package/src/scripts/model_rule_injection.ts +76 -0
- package/src/scripts/orchestration_record.ts +14 -0
- package/src/scripts/preamble_byte_census.ts +139 -10
- package/src/scripts/prepack-check.mjs +4 -1
- package/src/scripts/probe_council_retention.ts +495 -0
- package/src/scripts/probe_turnaround.ts +384 -0
- package/src/scripts/probe_unblocked_ask.ts +279 -0
- package/src/scripts/release.ts +21 -37
- package/src/scripts/release_drill.ts +143 -0
- package/src/scripts/release_env.ts +35 -0
- package/src/scripts/release_publication.ts +84 -0
- package/src/scripts/render_benchmark_md.ts +1 -1
- 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/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 +3 -3
- package/src/scripts/trigger_eval_grandfather.json +202 -222
- package/src/scripts/utilization_report.ts +22 -2
- package/src/server/schemas/settings.ts +5 -0
- package/src/templates/marketing-copy.yml +1 -1
- package/dist/ui/assets/index-Cxgy63kz.js +0 -26
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* An undeclared lossy transform on a model-facing path fails
|
|
4
|
+
* (`road-to-runtime-context-floors` step 3.2).
|
|
5
|
+
*
|
|
6
|
+
* STRICTNESS — decided, not assumed
|
|
7
|
+
* ---------------------------------
|
|
8
|
+
* Council 2026-08-28 (2/2 convergent, anthropic + openai, 2 rounds) resolved the
|
|
9
|
+
* `how-strict-the-loss-class-lint-is` blocker as option (b): FAIL on transforms
|
|
10
|
+
* whose output reaches the model, WARN elsewhere. Option (a) — fail everywhere in
|
|
11
|
+
* `src/` — buys a first-run backlog whose usual answer is a broad allowlist, and
|
|
12
|
+
* this repository has a measured history of an allowlist emptying a gate. Option
|
|
13
|
+
* (c) — warn everywhere, ratchet later — is the shape this repository has
|
|
14
|
+
* measurably never ratcheted.
|
|
15
|
+
*
|
|
16
|
+
* Both seats added the same refinement, adopted here: **unknown reachability is
|
|
17
|
+
* classified as model-reaching.** Ambiguity must not become an accidental
|
|
18
|
+
* exemption.
|
|
19
|
+
*
|
|
20
|
+
* WHAT COUNTS AS MODEL-FACING
|
|
21
|
+
* ---------------------------
|
|
22
|
+
* A hook concern bound on a slot whose output can reach the model, whose script
|
|
23
|
+
* BOTH emits a context payload AND applies a lossy operation to content. Both
|
|
24
|
+
* halves are read from code with comments stripped — the first cut of this
|
|
25
|
+
* detector matched `truncat` inside three docblocks that describe truncation
|
|
26
|
+
* without performing any, and a gate that fires on prose about a defect rather
|
|
27
|
+
* than the defect is how a real corpus of one becomes a pro-forma corpus of four.
|
|
28
|
+
*
|
|
29
|
+
* Measured at landing: **1** module qualifies — `hot_context_hook`, which is
|
|
30
|
+
* exactly the `ephemeral-lossy` exemplar the contract classifies. A corpus of one
|
|
31
|
+
* is the honest state of this tree, not a broken detector; the gate fires the day
|
|
32
|
+
* a second lands.
|
|
33
|
+
*
|
|
34
|
+
* Exit codes: 0 clean (warnings allowed) · 1 an undeclared model-facing
|
|
35
|
+
* transform · 2 misuse / unreadable manifest.
|
|
36
|
+
*
|
|
37
|
+
* Usage:
|
|
38
|
+
* ./scripts-run src/scripts/check_loss_class_declared [--root <dir>] [--json] [--quiet]
|
|
39
|
+
* ./scripts-run src/scripts/check_loss_class_declared --self-test
|
|
40
|
+
*/
|
|
41
|
+
import { spawnSync } from 'node:child_process';
|
|
42
|
+
import * as fs from 'node:fs';
|
|
43
|
+
import * as os from 'node:os';
|
|
44
|
+
import * as path from 'node:path';
|
|
45
|
+
|
|
46
|
+
import { GateLedger } from './_lib/gate_ledger.js';
|
|
47
|
+
import { runGateCli, runSelfTest, type SelfTestCase } from './_lib/gate_self_test.js';
|
|
48
|
+
import { isProblem, parseLossDeclaration, type DeclarationProblem } from './_lib/loss_class.js';
|
|
49
|
+
import { DeadScopeError, reportScanned } from './_lib/scan_scope.js';
|
|
50
|
+
|
|
51
|
+
const HERE = path.dirname(new URL(import.meta.url).pathname);
|
|
52
|
+
const REPO_ROOT = path.resolve(HERE, '..', '..');
|
|
53
|
+
|
|
54
|
+
/** Slots whose output can reach the model. */
|
|
55
|
+
const MODEL_FACING_SLOTS = [
|
|
56
|
+
'session_start',
|
|
57
|
+
'user_prompt_submit',
|
|
58
|
+
'pre_compact',
|
|
59
|
+
'stop',
|
|
60
|
+
'post_tool_use',
|
|
61
|
+
'pre_tool_use',
|
|
62
|
+
] as const;
|
|
63
|
+
|
|
64
|
+
/** Emitting a context payload — the "reaches the model" half. */
|
|
65
|
+
const EMIT_PATTERNS = [/\bcontext\s*:/, /additionalContext/, /hookSpecificOutput/];
|
|
66
|
+
|
|
67
|
+
/** Shortening, redacting or capping content — the "lossy" half. */
|
|
68
|
+
const LOSSY_PATTERNS = [/\bredact/i, /\btruncat/i, /\b(?:WORD|CHAR|MAX)_(?:CAP|CHARS|LEN|WORDS)\b/];
|
|
69
|
+
|
|
70
|
+
export interface LossFinding {
|
|
71
|
+
concern: string;
|
|
72
|
+
script: string;
|
|
73
|
+
tier: 'fail' | 'warn';
|
|
74
|
+
problem: DeclarationProblem;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface LossVerdict {
|
|
78
|
+
scanned: number;
|
|
79
|
+
modelFacing: number;
|
|
80
|
+
findings: LossFinding[];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Strip block and line comments so the detector reads CODE, never prose about code. */
|
|
84
|
+
export function stripComments(src: string): string {
|
|
85
|
+
return src
|
|
86
|
+
.replace(/\/\*[\s\S]*?\*\//g, '')
|
|
87
|
+
.replace(/^\s*\/\/.*$/gm, '');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function emitsContext(codeOnly: string): boolean {
|
|
91
|
+
return EMIT_PATTERNS.some((p) => p.test(codeOnly));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function isLossy(codeOnly: string): boolean {
|
|
95
|
+
return LOSSY_PATTERNS.some((p) => p.test(codeOnly));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function loadManifest(root: string): { concerns: Record<string, { script?: unknown }>; platforms: Record<string, Record<string, string[]>> } {
|
|
99
|
+
const file = path.join(root, 'src', 'scripts', 'hook_manifest.yaml');
|
|
100
|
+
const raw = fs.readFileSync(file, 'utf-8');
|
|
101
|
+
const out = spawnSync(
|
|
102
|
+
process.execPath,
|
|
103
|
+
['-e', 'const y=require("js-yaml");let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{const d=y.load(s);process.stdout.write(JSON.stringify({concerns:d.concerns||{},platforms:d.platforms||{}}))})'],
|
|
104
|
+
{ input: raw, encoding: 'utf-8', cwd: REPO_ROOT, maxBuffer: 64 * 1024 * 1024 },
|
|
105
|
+
);
|
|
106
|
+
if (out.status !== 0 || !out.stdout) throw new Error(`hook_manifest.yaml could not be parsed: ${out.stderr || 'no output'}`);
|
|
107
|
+
return JSON.parse(out.stdout) as { concerns: Record<string, { script?: unknown }>; platforms: Record<string, Record<string, string[]>> };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Which concerns sit on a model-facing slot.
|
|
112
|
+
*
|
|
113
|
+
* A concern bound on NO slot this gate recognises is `unknown` reachability, and
|
|
114
|
+
* per the council refinement it is treated as model-facing rather than skipped.
|
|
115
|
+
*/
|
|
116
|
+
export function modelFacingConcerns(platforms: Record<string, Record<string, string[]>>): Set<string> {
|
|
117
|
+
const out = new Set<string>();
|
|
118
|
+
for (const slots of Object.values(platforms)) {
|
|
119
|
+
if (slots === null || typeof slots !== 'object') continue;
|
|
120
|
+
for (const [slot, names] of Object.entries(slots)) {
|
|
121
|
+
if (!Array.isArray(names)) continue;
|
|
122
|
+
const facing = (MODEL_FACING_SLOTS as readonly string[]).includes(slot);
|
|
123
|
+
for (const n of names) if (facing) out.add(n);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return out;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function evaluate(root: string = REPO_ROOT, ledger?: GateLedger): LossVerdict {
|
|
130
|
+
const { concerns, platforms } = loadManifest(root);
|
|
131
|
+
const facing = modelFacingConcerns(platforms);
|
|
132
|
+
const bound = new Set<string>();
|
|
133
|
+
for (const slots of Object.values(platforms)) {
|
|
134
|
+
if (slots === null || typeof slots !== 'object') continue;
|
|
135
|
+
for (const names of Object.values(slots)) if (Array.isArray(names)) for (const n of names) bound.add(n);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const findings: LossFinding[] = [];
|
|
139
|
+
let scanned = 0;
|
|
140
|
+
let modelFacing = 0;
|
|
141
|
+
|
|
142
|
+
ledger?.plan(Object.keys(concerns));
|
|
143
|
+
|
|
144
|
+
for (const [name, spec] of Object.entries(concerns)) {
|
|
145
|
+
const rel = typeof spec?.script === 'string' ? spec.script : null;
|
|
146
|
+
if (rel === null) {
|
|
147
|
+
ledger?.skip(name, 'manifest_absent');
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
const abs = path.join(root, rel);
|
|
151
|
+
if (!fs.existsSync(abs)) {
|
|
152
|
+
ledger?.skip(name, 'no_applicable_files');
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
scanned += 1;
|
|
156
|
+
|
|
157
|
+
const source = fs.readFileSync(abs, 'utf-8');
|
|
158
|
+
const code = stripComments(source);
|
|
159
|
+
if (!isLossy(code) || !emitsContext(code)) {
|
|
160
|
+
// Not a lossy model-facing transform: the check does not apply to it.
|
|
161
|
+
ledger?.outOfScope(name, 'not_applicable_kind');
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Unknown reachability fails closed: a bound concern this gate cannot
|
|
166
|
+
// place on a known slot is treated as model-reaching.
|
|
167
|
+
const reaches = facing.has(name) || !bound.has(name);
|
|
168
|
+
if (reaches) modelFacing += 1;
|
|
169
|
+
|
|
170
|
+
const decl = parseLossDeclaration(source);
|
|
171
|
+
if (!isProblem(decl)) {
|
|
172
|
+
ledger?.complete(name);
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
findings.push({ concern: name, script: rel, tier: reaches ? 'fail' : 'warn', problem: decl });
|
|
176
|
+
ledger?.fail(name, `undeclared or malformed loss_class (${decl.kind})`);
|
|
177
|
+
}
|
|
178
|
+
return { scanned, modelFacing, findings };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ---------------------------------------------------------------- self-test
|
|
182
|
+
|
|
183
|
+
const LOSSY_EMITTER = `
|
|
184
|
+
const WORD_CAP = 400;
|
|
185
|
+
export function run() {
|
|
186
|
+
const kept = redactLines(body).slice(0, WORD_CAP);
|
|
187
|
+
return { context: kept.join('\\n') };
|
|
188
|
+
}
|
|
189
|
+
`;
|
|
190
|
+
|
|
191
|
+
function plant(dir: string, header: string, body: string, slot = 'session_start'): void {
|
|
192
|
+
fs.mkdirSync(path.join(dir, 'src', 'scripts'), { recursive: true });
|
|
193
|
+
fs.writeFileSync(path.join(dir, 'src', 'scripts', 'fixture_hook.ts'), header + body);
|
|
194
|
+
fs.writeFileSync(
|
|
195
|
+
path.join(dir, 'src', 'scripts', 'hook_manifest.yaml'),
|
|
196
|
+
`schema_version: 1\nconcerns:\n fixture:\n script: src/scripts/fixture_hook.ts\nplatforms:\n claude:\n ${slot}:\n - fixture\n`,
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const NO_DECL = '';
|
|
201
|
+
const DECL_RECOVERABLE = '/**\n * loss_class: recoverable-lossy\n * loss_recovery: agents/knowledge/intake/<file>:<a>-<b>\n */\n';
|
|
202
|
+
const DECL_RECOVERABLE_NO_LOCATOR = '/**\n * loss_class: recoverable-lossy\n */\n';
|
|
203
|
+
const DECL_EPHEMERAL = '/**\n * loss_class: ephemeral-lossy\n */\n';
|
|
204
|
+
const DECL_TYPO = '/**\n * loss_class: recoverable_lossy\n */\n';
|
|
205
|
+
|
|
206
|
+
function selfTestCases(): SelfTestCase[] {
|
|
207
|
+
const mk = (name: string, expect: 'reject' | 'accept', header: string, body: string, slot?: string): SelfTestCase => ({
|
|
208
|
+
name,
|
|
209
|
+
expect,
|
|
210
|
+
run: () => {
|
|
211
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'lcd-'));
|
|
212
|
+
try {
|
|
213
|
+
plant(dir, header, body, slot);
|
|
214
|
+
return runGateCli(REPO_ROOT, 'src/scripts/check_loss_class_declared.ts', ['--root', dir, '--quiet'], REPO_ROOT);
|
|
215
|
+
} finally {
|
|
216
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
return [
|
|
221
|
+
mk('model-facing lossy transform with no declaration → reject', 'reject', NO_DECL, LOSSY_EMITTER),
|
|
222
|
+
mk('same transform with recoverable-lossy + locator → accept', 'accept', DECL_RECOVERABLE, LOSSY_EMITTER),
|
|
223
|
+
mk('recoverable-lossy WITHOUT a locator → reject', 'reject', DECL_RECOVERABLE_NO_LOCATOR, LOSSY_EMITTER),
|
|
224
|
+
mk('ephemeral-lossy (owes no locator) → accept', 'accept', DECL_EPHEMERAL, LOSSY_EMITTER),
|
|
225
|
+
mk('a misspelled class is not honoured → reject', 'reject', DECL_TYPO, LOSSY_EMITTER),
|
|
226
|
+
mk('non-lossy emitter needs no declaration → accept', 'accept', NO_DECL, `export function run(){return {context:'hi'};}`),
|
|
227
|
+
mk('lossy but emits no context → accept', 'accept', NO_DECL, `const WORD_CAP=5;export function run(){return body.slice(0,WORD_CAP);}`),
|
|
228
|
+
mk('prose about truncation is not truncation → accept', 'accept', NO_DECL, `/* we deliberately never truncate or redact here */\nexport function run(){return {context:'hi'};}`),
|
|
229
|
+
];
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// ---------------------------------------------------------------------- CLI
|
|
233
|
+
|
|
234
|
+
export function main(argv: string[] = process.argv.slice(2)): number {
|
|
235
|
+
if (argv.includes('--self-test')) {
|
|
236
|
+
return runSelfTest({ gate: 'check_loss_class_declared', cases: selfTestCases(), minCases: 7, minRejectCases: 3 });
|
|
237
|
+
}
|
|
238
|
+
const quiet = argv.includes('--quiet');
|
|
239
|
+
const json = argv.includes('--json');
|
|
240
|
+
const ri = argv.indexOf('--root');
|
|
241
|
+
const rootArg = ri !== -1 ? argv[ri + 1] : undefined;
|
|
242
|
+
const root = rootArg !== undefined ? path.resolve(rootArg) : REPO_ROOT;
|
|
243
|
+
|
|
244
|
+
const ledger = new GateLedger('check_loss_class_declared');
|
|
245
|
+
let v: LossVerdict;
|
|
246
|
+
try {
|
|
247
|
+
v = evaluate(root, ledger);
|
|
248
|
+
} catch (err) {
|
|
249
|
+
process.stderr.write(`❌ check_loss_class_declared: ${(err as Error).message}\n`);
|
|
250
|
+
return 2;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
try {
|
|
254
|
+
reportScanned({ gate: 'check_loss_class_declared', scanned: v.scanned, units: 'hook script(s)', roots: ['src/scripts/hook_manifest.yaml'] });
|
|
255
|
+
} catch (err) {
|
|
256
|
+
if (err instanceof DeadScopeError) {
|
|
257
|
+
process.stderr.write(`❌ check_loss_class_declared: ${err.message}\n`);
|
|
258
|
+
return 2;
|
|
259
|
+
}
|
|
260
|
+
throw err;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
ledger.report();
|
|
264
|
+
|
|
265
|
+
if (json) {
|
|
266
|
+
process.stdout.write(JSON.stringify(v, null, 2) + '\n');
|
|
267
|
+
return v.findings.some((f) => f.tier === 'fail') ? 1 : 0;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
const say = (f: LossFinding): string => {
|
|
271
|
+
switch (f.problem.kind) {
|
|
272
|
+
case 'missing':
|
|
273
|
+
return 'declares no loss_class';
|
|
274
|
+
case 'unknown-class':
|
|
275
|
+
return `declares loss_class: ${f.problem.value}, which is not one of the five`;
|
|
276
|
+
case 'missing-recovery':
|
|
277
|
+
return 'declares recoverable-lossy but no loss_recovery locator — without one the class is indistinguishable from ephemeral-lossy';
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
for (const f of v.findings) {
|
|
282
|
+
const stream = f.tier === 'fail' ? process.stderr : process.stdout;
|
|
283
|
+
stream.write(`${f.tier === 'fail' ? '❌' : '⚠️ '} ${f.concern} (${f.script}) shortens content on a model-facing path and ${say(f)}\n`);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (v.findings.some((f) => f.tier === 'fail')) {
|
|
287
|
+
process.stderr.write(
|
|
288
|
+
`\n Add a declaration to the module's own docblock:\n` +
|
|
289
|
+
` loss_class: exact | lossless | recoverable-lossy | ephemeral-lossy | forbidden\n` +
|
|
290
|
+
` loss_recovery: <where the original is retrievable> # recoverable-lossy only\n` +
|
|
291
|
+
` Contract: docs/contracts/loss-classes.md\n`,
|
|
292
|
+
);
|
|
293
|
+
return 1;
|
|
294
|
+
}
|
|
295
|
+
if (!quiet) {
|
|
296
|
+
process.stdout.write(
|
|
297
|
+
`✅ every model-facing lossy transform declares its loss class ` +
|
|
298
|
+
`(${String(v.modelFacing)} model-facing of ${String(v.scanned)} hook script(s)).\n`,
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
return 0;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (process.env['GATE_SELF_TEST_CHILD'] !== '1' || process.argv.includes('--root')) {
|
|
305
|
+
if (process.argv[1] !== undefined && import.meta.url === `file://${process.argv[1]}`) {
|
|
306
|
+
process.exit(main());
|
|
307
|
+
}
|
|
308
|
+
}
|
|
@@ -20,6 +20,7 @@ import * as fs from 'node:fs';
|
|
|
20
20
|
import * as path from 'node:path';
|
|
21
21
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
22
22
|
|
|
23
|
+
import { classifyMarkdownLines } from './_lib/md_prose_lines.js';
|
|
23
24
|
import { assertScanned, DeadScopeError } from './_lib/scan_scope.js';
|
|
24
25
|
|
|
25
26
|
// Umlauts and German-only characters.
|
|
@@ -52,9 +53,6 @@ function _escapeRegExp(s: string): string {
|
|
|
52
53
|
// Labeled bilingual anchor: lines starting with "DE:" or "- DE:" (and EN).
|
|
53
54
|
const DE_ANCHOR_RE = /^\s*[-*]?\s*(DE|EN):\s/i;
|
|
54
55
|
|
|
55
|
-
// Inline code spans.
|
|
56
|
-
const INLINE_CODE_RE = /`[^`]*`/g;
|
|
57
|
-
|
|
58
56
|
// Per-line escape marker.
|
|
59
57
|
const IGNORE_RE = /<!--\s*md-language-check:\s*ignore\s*-->/i;
|
|
60
58
|
|
|
@@ -66,120 +64,39 @@ export interface Violation {
|
|
|
66
64
|
context: string;
|
|
67
65
|
}
|
|
68
66
|
|
|
69
|
-
function _strip_inline_code(text: string): string {
|
|
70
|
-
return text.replace(INLINE_CODE_RE, '');
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/** Python `str.splitlines()` — universal-newline split, no trailing empty element. */
|
|
74
|
-
function splitlines(text: string): string[] {
|
|
75
|
-
if (text === '') return [];
|
|
76
|
-
const lines: string[] = [];
|
|
77
|
-
let current = '';
|
|
78
|
-
for (let i = 0; i < text.length; i++) {
|
|
79
|
-
const ch = text[i] as string;
|
|
80
|
-
const code = text.charCodeAt(i);
|
|
81
|
-
if (ch === '\r') {
|
|
82
|
-
lines.push(current);
|
|
83
|
-
current = '';
|
|
84
|
-
if (text[i + 1] === '\n') i += 1; // \r\n consumed as one
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
if (
|
|
88
|
-
ch === '\n' ||
|
|
89
|
-
code === 0x0b ||
|
|
90
|
-
code === 0x0c ||
|
|
91
|
-
code === 0x1c ||
|
|
92
|
-
code === 0x1d ||
|
|
93
|
-
code === 0x1e ||
|
|
94
|
-
code === 0x85 ||
|
|
95
|
-
code === 0x2028 ||
|
|
96
|
-
code === 0x2029
|
|
97
|
-
) {
|
|
98
|
-
lines.push(current);
|
|
99
|
-
current = '';
|
|
100
|
-
continue;
|
|
101
|
-
}
|
|
102
|
-
current += ch;
|
|
103
|
-
}
|
|
104
|
-
if (current !== '') lines.push(current);
|
|
105
|
-
return lines;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
67
|
export function scan_file(p: string): Violation[] {
|
|
109
68
|
const violations: Violation[] = [];
|
|
110
|
-
let
|
|
69
|
+
let content: string;
|
|
111
70
|
try {
|
|
112
|
-
|
|
71
|
+
content = fs.readFileSync(p, 'utf-8');
|
|
113
72
|
} catch (exc) {
|
|
114
73
|
const msg = exc instanceof Error ? exc.message : String(exc);
|
|
115
|
-
process.stderr.write(
|
|
74
|
+
process.stderr.write(`\u26a0\ufe0f Cannot read ${p}: ${msg}\n`);
|
|
116
75
|
return violations;
|
|
117
76
|
}
|
|
118
77
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
for
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
in_frontmatter = true;
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
if (in_frontmatter) {
|
|
132
|
-
if (stripped === '---') {
|
|
133
|
-
in_frontmatter = false;
|
|
134
|
-
}
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Fenced code blocks.
|
|
139
|
-
if (stripped.startsWith('```') || stripped.startsWith('~~~')) {
|
|
140
|
-
in_fence = !in_fence;
|
|
141
|
-
continue;
|
|
142
|
-
}
|
|
143
|
-
if (in_fence) {
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Indented code blocks (4+ leading spaces, non-list).
|
|
148
|
-
const listStarts = ['-', '*', '+', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
|
|
149
|
-
if (raw.startsWith(' ') && !listStarts.some((c) => stripped.startsWith(c))) {
|
|
150
|
-
continue;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Labeled bilingual anchor.
|
|
154
|
-
if (DE_ANCHOR_RE.test(raw)) {
|
|
155
|
-
continue;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Per-line opt-out marker.
|
|
159
|
-
if (IGNORE_RE.test(raw)) {
|
|
160
|
-
continue;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Strip inline code spans before scanning.
|
|
164
|
-
const scan_text = _strip_inline_code(raw);
|
|
165
|
-
const ctx = _rstrip(raw);
|
|
78
|
+
// Frontmatter / fence / indented-code / marker skipping is shared with
|
|
79
|
+
// `lint_canonical_terms` via `_lib/md_prose_lines` — see that module's
|
|
80
|
+
// header for why a second copy was refused. The classification is the same
|
|
81
|
+
// code this function used to carry inline; the DE:/EN: anchor and the
|
|
82
|
+
// per-line ignore marker are passed in as this gate's own markers.
|
|
83
|
+
for (const line of classifyMarkdownLines(content, { markers: [DE_ANCHOR_RE, IGNORE_RE] })) {
|
|
84
|
+
if (line.kind !== 'prose') continue;
|
|
85
|
+
const scan_text = line.text;
|
|
86
|
+
const ctx = _rstrip(line.raw);
|
|
166
87
|
|
|
167
88
|
for (const m of scan_text.matchAll(UMLAUT_RE)) {
|
|
168
|
-
violations.push({ file: p, line: lineno, kind: 'umlaut', match: m[0], context: ctx });
|
|
89
|
+
violations.push({ file: p, line: line.lineno, kind: 'umlaut', match: m[0], context: ctx });
|
|
169
90
|
}
|
|
170
91
|
|
|
171
92
|
for (const m of scan_text.matchAll(DE_WORD_RE)) {
|
|
172
|
-
violations.push({ file: p, line: lineno, kind: 'de_word', match: m[0], context: ctx });
|
|
93
|
+
violations.push({ file: p, line: line.lineno, kind: 'de_word', match: m[0], context: ctx });
|
|
173
94
|
}
|
|
174
95
|
}
|
|
175
96
|
|
|
176
97
|
return violations;
|
|
177
98
|
}
|
|
178
99
|
|
|
179
|
-
function _lstrip(s: string): string {
|
|
180
|
-
return s.replace(/^\s+/, '');
|
|
181
|
-
}
|
|
182
|
-
|
|
183
100
|
function _rstrip(s: string): string {
|
|
184
101
|
return s.replace(/\s+$/, '');
|
|
185
102
|
}
|
|
@@ -230,14 +230,24 @@ function parse_args(argv: readonly string[]): ParsedArgs {
|
|
|
230
230
|
let quiet = false;
|
|
231
231
|
for (let i = 0; i < argv.length; i++) {
|
|
232
232
|
const arg = argv[i]!;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
233
|
+
// Mutual exclusion is checked INLINE, at the second flag, and the error
|
|
234
|
+
// names the flag that arrived second. That is what argparse does with a
|
|
235
|
+
// mutually exclusive group, and this file mirrors argparse's messages
|
|
236
|
+
// exactly — the post-loop check it replaced was order-stable and always
|
|
237
|
+
// blamed `--proposal`, which inverts the blame when `--proposal` came
|
|
238
|
+
// first. Reconciled toward the TEMPLATE side (road-to-memory-twin
|
|
239
|
+
// -reconciliation 2.1): the copy that looked like the drift was the
|
|
240
|
+
// faithful one.
|
|
241
|
+
if (arg === '--intake-id' || arg.startsWith('--intake-id=')) {
|
|
242
|
+
if (proposal !== null) {
|
|
243
|
+
_argparse_error('argument --intake-id: not allowed with argument --proposal');
|
|
244
|
+
}
|
|
245
|
+
intake_id = arg === '--intake-id' ? _need(argv, ++i, '--intake-id') : arg.slice('--intake-id='.length);
|
|
246
|
+
} else if (arg === '--proposal' || arg.startsWith('--proposal=')) {
|
|
247
|
+
if (intake_id !== null) {
|
|
248
|
+
_argparse_error('argument --proposal: not allowed with argument --intake-id');
|
|
249
|
+
}
|
|
250
|
+
proposal = arg === '--proposal' ? _need(argv, ++i, '--proposal') : arg.slice('--proposal='.length);
|
|
241
251
|
} else if (arg === '--format') {
|
|
242
252
|
const v = _need(argv, ++i, '--format');
|
|
243
253
|
format = _checkFormat(v);
|
|
@@ -255,9 +265,6 @@ function parse_args(argv: readonly string[]): ParsedArgs {
|
|
|
255
265
|
_argparse_error(`unrecognized arguments: ${arg}`);
|
|
256
266
|
}
|
|
257
267
|
}
|
|
258
|
-
if (intake_id !== null && proposal !== null) {
|
|
259
|
-
_argparse_error('argument --proposal: not allowed with argument --intake-id');
|
|
260
|
-
}
|
|
261
268
|
if (intake_id === null && proposal === null) {
|
|
262
269
|
_argparse_error('one of the arguments --intake-id --proposal is required');
|
|
263
270
|
}
|