@event4u/agent-config 14.12.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 +234 -0
- 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/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/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 +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 +57 -57
- 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 +1836 -712
- 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 +4818 -2645
- 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/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 +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 +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 +38 -36
- package/src/config/evaluator-budgets.json +14 -14
- package/src/config/gate-coverage.yml +579 -63
- package/src/config/gate-reachability-exemptions.json +21 -0
- package/src/config/gate-violation-baselines.json +37 -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 +8 -8
- 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 +126 -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 +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/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/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/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 +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 +142 -1
- 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_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/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 +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 +98 -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 +4 -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/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_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 +426 -23
- 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/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/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,402 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The deterministic candidate proposer — fixed recipes, no model in the loop.
|
|
3
|
+
*
|
|
4
|
+
* `road-to-governed-harness-evolution` Phase 3, step 3.5.
|
|
5
|
+
*
|
|
6
|
+
* > *Ship a deterministic proposer first. Fixed recipes for known defect
|
|
7
|
+
* > classes, so the loop is validated without model quality as a confound.*
|
|
8
|
+
* > verify: **the same input produces byte-identical candidates across two
|
|
9
|
+
* > runs.**
|
|
10
|
+
*
|
|
11
|
+
* The seam this plugs into already existed: `bench_ab_clone --candidate-record`
|
|
12
|
+
* consumes a validated candidate record file, so a proposer's whole job is to
|
|
13
|
+
* PRODUCE those files. Nothing here materialises a clone, spawns a process, or
|
|
14
|
+
* calls a model.
|
|
15
|
+
*
|
|
16
|
+
* ## What is being claimed, and what is not
|
|
17
|
+
*
|
|
18
|
+
* Claimed: the mapping from an observation set to a byte string is a pure
|
|
19
|
+
* function of that set plus the subject bytes it reads. Two runs over the same
|
|
20
|
+
* input produce the same bytes, on any machine, in any order, at any time.
|
|
21
|
+
*
|
|
22
|
+
* NOT claimed: that these three recipes improve anything. Whether a candidate
|
|
23
|
+
* is better than the baseline is the paired verdict's question in Phase 4, and
|
|
24
|
+
* a proposer that asserted its own efficacy would be answering it in the wrong
|
|
25
|
+
* place. The recipes are deliberately blunt, total, and idempotent — that is
|
|
26
|
+
* what makes them a control condition rather than a competitor.
|
|
27
|
+
*
|
|
28
|
+
* ## The four things that would break determinism, and where each is closed
|
|
29
|
+
*
|
|
30
|
+
* 1. **Wall-clock.** No timestamp is written into a record, and the id is not
|
|
31
|
+
* derived from one. {@link candidateId} hashes content.
|
|
32
|
+
* 2. **Filesystem iteration order.** The proposer never reads a directory.
|
|
33
|
+
* Its input is an explicit, ordered list; {@link proposeCandidates} sorts
|
|
34
|
+
* it before emitting.
|
|
35
|
+
* 3. **Locale-dependent ordering.** Every sort here is a byte-wise comparison
|
|
36
|
+
* via {@link byteCompare}. `String.prototype.localeCompare` is deliberately
|
|
37
|
+
* not used — it is ICU-dependent, so two machines can disagree about the
|
|
38
|
+
* order of two ids and produce two different files.
|
|
39
|
+
* 4. **Object key order.** {@link serialiseCandidateRecord} routes through
|
|
40
|
+
* `candidateRecordToJson`, which fixes key order in one place.
|
|
41
|
+
*
|
|
42
|
+
* A fifth would be randomness or a counter; there is neither.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
import { createHash } from 'node:crypto';
|
|
46
|
+
|
|
47
|
+
import {
|
|
48
|
+
CANDIDATE_RECORD_VERSION,
|
|
49
|
+
type CandidateRecord,
|
|
50
|
+
CandidateSchemaError,
|
|
51
|
+
type Mutation,
|
|
52
|
+
type MutationDimension,
|
|
53
|
+
assertMutationPathsOwned,
|
|
54
|
+
candidateRecordToJson,
|
|
55
|
+
isCandidateOwnedPath,
|
|
56
|
+
} from './candidate_record.js';
|
|
57
|
+
|
|
58
|
+
// --- The defect classes -----------------------------------------------------
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The three defect classes with a fixed recipe, one per mutation dimension.
|
|
62
|
+
*
|
|
63
|
+
* One per dimension is not a coincidence and is not a rule either: it is what
|
|
64
|
+
* makes the first proposer exercise all three arms of the alphabet step 3.3
|
|
65
|
+
* fixed. A fourth class would be legal as long as it lands on one of the three
|
|
66
|
+
* dimensions; a class needing a fourth DIMENSION is refused upstream by
|
|
67
|
+
* `parseCandidateRecord`, not here.
|
|
68
|
+
*/
|
|
69
|
+
export const DEFECT_CLASSES = [
|
|
70
|
+
'over-broad-activation',
|
|
71
|
+
'unrouted-obligation',
|
|
72
|
+
'unbacked-enforcement-claim',
|
|
73
|
+
] as const;
|
|
74
|
+
export type DefectClass = (typeof DEFECT_CLASSES)[number];
|
|
75
|
+
|
|
76
|
+
export function isDefectClass(v: unknown): v is DefectClass {
|
|
77
|
+
return typeof v === 'string' && (DEFECT_CLASSES as readonly string[]).includes(v);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** The pointer a truncated artefact carries, so the mutation is not a silent deletion. */
|
|
81
|
+
export const BAND_POINTER =
|
|
82
|
+
'<!-- candidate: leading band only; the full artefact is unchanged in the baseline clone -->';
|
|
83
|
+
|
|
84
|
+
/** The fixed honest-enforcement block the content recipe appends. */
|
|
85
|
+
export const HONEST_ENFORCEMENT_BLOCK =
|
|
86
|
+
'## Honest enforcement\n\n' +
|
|
87
|
+
'Nothing observes whether this obligation was met. It is model-carried, and\n' +
|
|
88
|
+
'saying so is cheaper than a check that would have to guess.';
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* One fixed recipe: a defect class, the dimension it mutates, and a TOTAL,
|
|
92
|
+
* IDEMPOTENT rewrite of the subject's bytes.
|
|
93
|
+
*
|
|
94
|
+
* Total: defined for every string, including the empty one. A recipe that can
|
|
95
|
+
* fail on some input makes the proposer's output depend on which subjects
|
|
96
|
+
* happen to be well-formed, which is a second determinism hazard wearing the
|
|
97
|
+
* costume of a validation error.
|
|
98
|
+
*
|
|
99
|
+
* Idempotent: `rewrite(rewrite(x)) === rewrite(x)`. Pinned by a test rather
|
|
100
|
+
* than by a comment, because it is the property that lets the same observation
|
|
101
|
+
* be re-proposed after a partial run without producing a different id.
|
|
102
|
+
*/
|
|
103
|
+
export interface Recipe {
|
|
104
|
+
readonly defectClass: DefectClass;
|
|
105
|
+
readonly dimension: MutationDimension;
|
|
106
|
+
/** Why this class is a defect, in one line, for the `explain` verb. */
|
|
107
|
+
readonly summary: string;
|
|
108
|
+
/** Does this class require an explicit route target on the observation? */
|
|
109
|
+
readonly needsRouteTo: boolean;
|
|
110
|
+
readonly rewrite: (body: string, routeTo: string) => string;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Keep the leading band, drop the rest.
|
|
115
|
+
*
|
|
116
|
+
* The band is everything before the first `## ` heading — this tree's own
|
|
117
|
+
* "rich artifacts lead with a non-negotiable band" shape. An artefact with no
|
|
118
|
+
* `## ` heading is already all band, so it comes back unchanged apart from the
|
|
119
|
+
* pointer.
|
|
120
|
+
*
|
|
121
|
+
* This is an ACTIVATION mutation and not a content one: it changes how much of
|
|
122
|
+
* the artefact is delivered per session, not what the delivered part says. The
|
|
123
|
+
* two are easy to confuse, which is exactly why step 3.2 refuses a candidate
|
|
124
|
+
* that does both.
|
|
125
|
+
*/
|
|
126
|
+
export function keepLeadingBand(body: string): string {
|
|
127
|
+
if (body.includes(BAND_POINTER)) {
|
|
128
|
+
return body;
|
|
129
|
+
}
|
|
130
|
+
const lines = body.split('\n');
|
|
131
|
+
let cut = lines.length;
|
|
132
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
133
|
+
if ((lines[i] as string).startsWith('## ')) {
|
|
134
|
+
cut = i;
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const band = lines.slice(0, cut).join('\n').replace(/\s+$/, '');
|
|
139
|
+
return `${band}\n\n${BAND_POINTER}\n`;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Append a route pointer naming where the obligation is discharged.
|
|
144
|
+
*
|
|
145
|
+
* The target comes from the observation, never from the subject's name. A
|
|
146
|
+
* proposer that guessed the route target from a filename would be inventing a
|
|
147
|
+
* claim about the tree, and an invented route reads exactly like a verified one
|
|
148
|
+
* once it is in the file.
|
|
149
|
+
*/
|
|
150
|
+
export function appendRoutePointer(body: string, routeTo: string): string {
|
|
151
|
+
const line = `- Routed to \`${routeTo}\` — the obligation above is discharged there.`;
|
|
152
|
+
if (body.includes(line)) {
|
|
153
|
+
return body;
|
|
154
|
+
}
|
|
155
|
+
return `${body.replace(/\s+$/, '')}\n\n## See also\n\n${line}\n`;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** Append the fixed honest-enforcement block, once. */
|
|
159
|
+
export function appendHonestEnforcement(body: string): string {
|
|
160
|
+
if (body.includes(HONEST_ENFORCEMENT_BLOCK)) {
|
|
161
|
+
return body;
|
|
162
|
+
}
|
|
163
|
+
return `${body.replace(/\s+$/, '')}\n\n${HONEST_ENFORCEMENT_BLOCK}\n`;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export const RECIPES: Readonly<Record<DefectClass, Recipe>> = {
|
|
167
|
+
'over-broad-activation': {
|
|
168
|
+
defectClass: 'over-broad-activation',
|
|
169
|
+
dimension: 'activation',
|
|
170
|
+
summary:
|
|
171
|
+
'the whole artefact is delivered every session when only its leading band is load-bearing',
|
|
172
|
+
needsRouteTo: false,
|
|
173
|
+
rewrite: (body) => keepLeadingBand(body),
|
|
174
|
+
},
|
|
175
|
+
'unrouted-obligation': {
|
|
176
|
+
defectClass: 'unrouted-obligation',
|
|
177
|
+
dimension: 'routing',
|
|
178
|
+
summary: 'the artefact states an obligation and names no artefact that discharges it',
|
|
179
|
+
needsRouteTo: true,
|
|
180
|
+
rewrite: (body, routeTo) => appendRoutePointer(body, routeTo),
|
|
181
|
+
},
|
|
182
|
+
'unbacked-enforcement-claim': {
|
|
183
|
+
defectClass: 'unbacked-enforcement-claim',
|
|
184
|
+
dimension: 'content',
|
|
185
|
+
summary: 'the artefact reads as enforced while nothing can observe a violation',
|
|
186
|
+
needsRouteTo: false,
|
|
187
|
+
rewrite: (body) => appendHonestEnforcement(body),
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
// --- Observations -----------------------------------------------------------
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* One observed defect: which class, which artefact, and (for `routing`) where
|
|
195
|
+
* the obligation is discharged.
|
|
196
|
+
*
|
|
197
|
+
* `subject` is repo-relative and must sit inside the candidate surface. That is
|
|
198
|
+
* checked HERE as well as in `parseCandidateRecord` and again in
|
|
199
|
+
* `apply_candidate_mutations`, because a proposer that emits an out-of-surface
|
|
200
|
+
* mutation has already written a bad record to disk by the time the clone
|
|
201
|
+
* refuses it, and an operator then holds a file that no verb will accept.
|
|
202
|
+
*/
|
|
203
|
+
export interface DefectObservation {
|
|
204
|
+
readonly defectClass: DefectClass;
|
|
205
|
+
readonly subject: string;
|
|
206
|
+
readonly routeTo?: string;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function requireString(obj: Record<string, unknown>, key: string): string {
|
|
210
|
+
const v = obj[key];
|
|
211
|
+
if (typeof v !== 'string' || v.trim() === '') {
|
|
212
|
+
throw new CandidateSchemaError(`observation '${key}' must be a non-empty string`);
|
|
213
|
+
}
|
|
214
|
+
return v;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Validate an untrusted observation list — the REFUSING path.
|
|
219
|
+
*
|
|
220
|
+
* Refuses, each with its own message: a non-array input; a class outside
|
|
221
|
+
* {@link DEFECT_CLASSES}; a subject outside the candidate surface; a missing
|
|
222
|
+
* `routeTo` on a class whose recipe needs one; a `routeTo` on a class whose
|
|
223
|
+
* recipe does not read it; and a duplicate `(defectClass, subject)` pair.
|
|
224
|
+
*
|
|
225
|
+
* The duplicate refusal is load-bearing rather than tidy: a duplicate pair
|
|
226
|
+
* hashes to the same id, so it would write the same filename twice. Silently
|
|
227
|
+
* de-duplicating would make the count of proposed candidates depend on the
|
|
228
|
+
* input's redundancy, and refusing says so.
|
|
229
|
+
*
|
|
230
|
+
* @throws {CandidateSchemaError} on the first violation.
|
|
231
|
+
*/
|
|
232
|
+
export function parseObservations(input: unknown): DefectObservation[] {
|
|
233
|
+
if (!Array.isArray(input)) {
|
|
234
|
+
throw new CandidateSchemaError(
|
|
235
|
+
'observations must be a JSON array of {defectClass, subject[, routeTo]} objects',
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
const out: DefectObservation[] = [];
|
|
239
|
+
const seen = new Set<string>();
|
|
240
|
+
for (const item of input) {
|
|
241
|
+
if (typeof item !== 'object' || item === null || Array.isArray(item)) {
|
|
242
|
+
throw new CandidateSchemaError('each observation must be a JSON object');
|
|
243
|
+
}
|
|
244
|
+
const obj = item as Record<string, unknown>;
|
|
245
|
+
const cls = requireString(obj, 'defectClass');
|
|
246
|
+
if (!isDefectClass(cls)) {
|
|
247
|
+
throw new CandidateSchemaError(
|
|
248
|
+
`'defectClass' must be one of ${DEFECT_CLASSES.join(', ')} (got ${JSON.stringify(cls)}). ` +
|
|
249
|
+
'A class with no fixed recipe has no deterministic proposal, and inventing one ' +
|
|
250
|
+
'is the model-quality confound this step exists to remove',
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
const subject = requireString(obj, 'subject');
|
|
254
|
+
if (!isCandidateOwnedPath(subject)) {
|
|
255
|
+
throw new CandidateSchemaError(
|
|
256
|
+
`observation subject '${subject}' is outside the candidate surface — a proposal ` +
|
|
257
|
+
'that rewrites a task-target file is a different experiment, not a harness variant',
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
const key = `${cls} ${subject}`;
|
|
261
|
+
if (seen.has(key)) {
|
|
262
|
+
throw new CandidateSchemaError(
|
|
263
|
+
`duplicate observation (${cls}, ${subject}) — it hashes to one candidate id, so the ` +
|
|
264
|
+
'second would silently overwrite the first',
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
seen.add(key);
|
|
268
|
+
const recipe = RECIPES[cls];
|
|
269
|
+
if (recipe.needsRouteTo) {
|
|
270
|
+
out.push({ defectClass: cls, subject, routeTo: requireString(obj, 'routeTo') });
|
|
271
|
+
} else {
|
|
272
|
+
if ('routeTo' in obj) {
|
|
273
|
+
throw new CandidateSchemaError(
|
|
274
|
+
`observation (${cls}, ${subject}) carries 'routeTo', which only the routing ` +
|
|
275
|
+
'recipe reads. An ignored field is an instruction the operator believes was followed',
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
out.push({ defectClass: cls, subject });
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return out;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// --- Proposing --------------------------------------------------------------
|
|
285
|
+
|
|
286
|
+
/** Reads a repo-relative subject's current bytes. Injected so tests need no tree. */
|
|
287
|
+
export type SubjectReader = (subject: string) => string;
|
|
288
|
+
|
|
289
|
+
/** Byte-wise, locale-independent string order. Never `localeCompare`. */
|
|
290
|
+
export function byteCompare(a: string, b: string): number {
|
|
291
|
+
if (a < b) {
|
|
292
|
+
return -1;
|
|
293
|
+
}
|
|
294
|
+
if (a > b) {
|
|
295
|
+
return 1;
|
|
296
|
+
}
|
|
297
|
+
return 0;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/** Short, stable per-dimension id tag, so an id says which arm it sits on. */
|
|
301
|
+
const DIMENSION_TAG: Readonly<Record<MutationDimension, string>> = {
|
|
302
|
+
activation: 'act',
|
|
303
|
+
routing: 'rou',
|
|
304
|
+
content: 'con',
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* The candidate id: a content hash, never a counter and never a clock.
|
|
309
|
+
*
|
|
310
|
+
* Hashed inputs are the defect class, the subject, and the exact bytes each
|
|
311
|
+
* mutation writes. Two consequences worth stating because both are relied on:
|
|
312
|
+
* re-proposing an unchanged observation over an unchanged tree yields the SAME
|
|
313
|
+
* id (so `run --refresh` rebuilds the same clone rather than accumulating
|
|
314
|
+
* near-duplicates), and a changed subject yields a DIFFERENT id (so a candidate
|
|
315
|
+
* built from stale bytes cannot be mistaken for one built from current bytes).
|
|
316
|
+
*
|
|
317
|
+
* Twelve hex characters is 48 bits. At the roadmap's exit-criterion scale —
|
|
318
|
+
* five candidates — a collision is ~5e-13 likely; the id is a directory name,
|
|
319
|
+
* not a security boundary, and `bench_ab_clone` refuses a repeated id outright
|
|
320
|
+
* rather than merging two candidates into one clone.
|
|
321
|
+
*/
|
|
322
|
+
export function candidateId(
|
|
323
|
+
defectClass: DefectClass,
|
|
324
|
+
subject: string,
|
|
325
|
+
mutations: readonly Mutation[],
|
|
326
|
+
): string {
|
|
327
|
+
const h = createHash('sha256');
|
|
328
|
+
h.update(defectClass);
|
|
329
|
+
h.update(' ');
|
|
330
|
+
h.update(subject);
|
|
331
|
+
for (const m of [...mutations].sort((x, y) => byteCompare(x.path, y.path))) {
|
|
332
|
+
h.update(' ');
|
|
333
|
+
h.update(m.path);
|
|
334
|
+
h.update(' ');
|
|
335
|
+
h.update(m.content);
|
|
336
|
+
}
|
|
337
|
+
return `${DIMENSION_TAG[RECIPES[defectClass].dimension]}-${h.digest('hex').slice(0, 12)}`;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Turn observations into candidate records. Pure given the same reader.
|
|
342
|
+
*
|
|
343
|
+
* Ordering is fixed EXACTLY ONCE, here, on the input. There is deliberately no
|
|
344
|
+
* second sort of the output: a run of the seen-red sweep showed that with the
|
|
345
|
+
* input sorted, neutralising an output sort changed nothing observable — it was
|
|
346
|
+
* a guard whose red could not be produced, which is indistinguishable from a
|
|
347
|
+
* guard that does not work. One ordering site, one guard, one red.
|
|
348
|
+
*
|
|
349
|
+
* Two properties follow from that single sort, and they are tested separately
|
|
350
|
+
* because they are different failures: the RETURNED order is independent of the
|
|
351
|
+
* caller's order, and the order subjects are READ in is too (read order is
|
|
352
|
+
* observable — with a throwing reader it decides whose error message surfaces).
|
|
353
|
+
*
|
|
354
|
+
* Every emitted record is `lifecycle: 'proposed'`, with no way to ask for
|
|
355
|
+
* another state. A proposer that could emit `promotion-eligible` would be
|
|
356
|
+
* grading its own output, which is the confusion step 3.4's lifecycle enum
|
|
357
|
+
* exists to make impossible.
|
|
358
|
+
*
|
|
359
|
+
* @throws {CandidateSchemaError} if a recipe produces an out-of-surface mutation.
|
|
360
|
+
*/
|
|
361
|
+
export function proposeCandidates(
|
|
362
|
+
observations: readonly DefectObservation[],
|
|
363
|
+
read: SubjectReader,
|
|
364
|
+
): CandidateRecord[] {
|
|
365
|
+
const ordered = [...observations].sort(
|
|
366
|
+
(a, b) => byteCompare(a.defectClass, b.defectClass) || byteCompare(a.subject, b.subject),
|
|
367
|
+
);
|
|
368
|
+
const records: CandidateRecord[] = [];
|
|
369
|
+
for (const obs of ordered) {
|
|
370
|
+
const recipe = RECIPES[obs.defectClass];
|
|
371
|
+
const before = read(obs.subject);
|
|
372
|
+
const after = recipe.rewrite(before, obs.routeTo ?? '');
|
|
373
|
+
const mutations: Mutation[] = [{ path: obs.subject, content: after }];
|
|
374
|
+
assertMutationPathsOwned(mutations);
|
|
375
|
+
records.push({
|
|
376
|
+
kind: 'candidate',
|
|
377
|
+
version: CANDIDATE_RECORD_VERSION,
|
|
378
|
+
id: candidateId(obs.defectClass, obs.subject, mutations),
|
|
379
|
+
dimension: recipe.dimension,
|
|
380
|
+
lifecycle: 'proposed',
|
|
381
|
+
mutations,
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
return records;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* The bytes written for one record.
|
|
389
|
+
*
|
|
390
|
+
* Two-space indent plus one trailing newline, matching what `bench_ab_clone`
|
|
391
|
+
* writes into the clone. The byte-identity acceptance test compares the output
|
|
392
|
+
* of THIS function, so the serialiser is part of the determinism claim rather
|
|
393
|
+
* than an incidental formatting choice at the call site.
|
|
394
|
+
*/
|
|
395
|
+
export function serialiseCandidateRecord(record: CandidateRecord): string {
|
|
396
|
+
return `${JSON.stringify(candidateRecordToJson(record), null, 2)}\n`;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/** `<id>.json` — the filename a record is written under. */
|
|
400
|
+
export function candidateRecordFilename(record: CandidateRecord): string {
|
|
401
|
+
return `${record.id}.json`;
|
|
402
|
+
}
|