@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,860 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Council-topology benchmark — the frozen call manifest and its expander.
|
|
3
|
+
*
|
|
4
|
+
* `road-to-inbox-harvest-2026-08-e-council-topology-evidence` Phase 2. Carrier
|
|
5
|
+
* contract: `internal/bench/council-topology/README.md`.
|
|
6
|
+
*
|
|
7
|
+
* ── Why this module exists ──────────────────────────────────────────────────
|
|
8
|
+
* The AI council of 2026-08-31 answered Q2 as **(iii): Phase 2 is not
|
|
9
|
+
* executable as written** — not because the design is wrong, but because the
|
|
10
|
+
* roadmap defines experimental DIMENSIONS and never the PROVIDER-CALL GRAPH.
|
|
11
|
+
* Both seats converged on the same diagnosis: an experimental cell is not a
|
|
12
|
+
* provider call. Host-solo may spend nothing; a full debate is multi-call;
|
|
13
|
+
* ablation outputs may or may not be reusable; retries add calls; and the
|
|
14
|
+
* ceiling is `50 calls per provider per UTC day`, never a fungible pool of 100.
|
|
15
|
+
* Neither `1,200 cells` nor `120 observations` is a call total.
|
|
16
|
+
*
|
|
17
|
+
* This module is the missing artefact. It is a pure expander: a frozen arm
|
|
18
|
+
* spec in, a fully enumerated cell list plus a per-provider day partition out.
|
|
19
|
+
* It makes **zero** provider calls and imports no transport.
|
|
20
|
+
*
|
|
21
|
+
* ── What this module is NOT ─────────────────────────────────────────────────
|
|
22
|
+
* It is not the runner. Both council seats said explicitly: do not greenlight
|
|
23
|
+
* the runner yet. Nothing here executes an arm, and the completion status of
|
|
24
|
+
* every cell it emits is `pending`, which is deliberately NOT a member of the
|
|
25
|
+
* complete set.
|
|
26
|
+
*
|
|
27
|
+
* ── The completion invariant, encoded rather than asserted ──────────────────
|
|
28
|
+
* "Not run" is not a null. A null is what a measurement returns. That
|
|
29
|
+
* distinction is the whole reason Phase 2 cannot be closed by declaring the
|
|
30
|
+
* unexecuted arms empty, so it is enforced at the type layer
|
|
31
|
+
* (`PendingIsNotComplete`) and at module load (`auditCompletionStatuses`),
|
|
32
|
+
* following the two-layer, sabotage-proven pattern step 7.1 established for the
|
|
33
|
+
* topology vocabulary in `topology_vocabulary.ts:119-175`.
|
|
34
|
+
*
|
|
35
|
+
* ── Where the call counts come from ─────────────────────────────────────────
|
|
36
|
+
* Every pass below is one `consult()` per participating member, which is one
|
|
37
|
+
* provider call per member:
|
|
38
|
+
*
|
|
39
|
+
* - generation `orchestrator.ts:394` `consult(members, ...)`
|
|
40
|
+
* - peer critique `orchestrator.ts:1553` `consult([reviewer], ...)`
|
|
41
|
+
* - findings extraction `consensus_round.ts:107`
|
|
42
|
+
* - bounded re-ask `consensus_round.ts:141` — at most ONE per member
|
|
43
|
+
* per extraction pass; this is the retry reserve
|
|
44
|
+
* - consensus scoring `consensus_round.ts:191`
|
|
45
|
+
* - prose synthesis chairman only; the templated default path spends
|
|
46
|
+
* nothing (`prompts.ts:512-518`), so the synthesis
|
|
47
|
+
* STAGE is only observable with the prose path on
|
|
48
|
+
*
|
|
49
|
+
* Multi-round debate multiplies the generation pass by `rounds`
|
|
50
|
+
* (`orchestrator.ts:160-161`, `:246`: "across every billable member × rounds").
|
|
51
|
+
*
|
|
52
|
+
* The per-provider daily ceiling is `DEFAULT_CLI_CALLS_PER_DAY = 50`
|
|
53
|
+
* (`cli_call_budget.ts:60`), applied per provider, never aggregated.
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
/** Per-provider daily call ceiling. Mirrors `cli_call_budget.ts:60`. */
|
|
57
|
+
export const CALLS_PER_PROVIDER_PER_UTC_DAY = 50;
|
|
58
|
+
|
|
59
|
+
/** The two providers the shipped council configuration seats. */
|
|
60
|
+
export const BENCH_PROVIDERS = ['anthropic', 'openai'] as const;
|
|
61
|
+
export type BenchProvider = (typeof BENCH_PROVIDERS)[number];
|
|
62
|
+
|
|
63
|
+
/** Calls booked against each provider. */
|
|
64
|
+
export type ProviderCalls = Readonly<Record<BenchProvider, number>>;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Eligibility label, fixed by the resolved `blocker: maintainer-blind-ratings`
|
|
68
|
+
* (option (b) — scope to gradeable-only slices, publish the rubric arms as
|
|
69
|
+
* deferred). The three labels are NEVER pooled: that pooling is precisely what
|
|
70
|
+
* the blocker's resolution forbids.
|
|
71
|
+
*/
|
|
72
|
+
export const FAMILY_LABELS = [
|
|
73
|
+
'gradeable-confirmatory',
|
|
74
|
+
'human-rubric-deferred',
|
|
75
|
+
'model-graded-exploratory',
|
|
76
|
+
] as const;
|
|
77
|
+
export type FamilyLabel = (typeof FAMILY_LABELS)[number];
|
|
78
|
+
|
|
79
|
+
/** Completion status of one cell. */
|
|
80
|
+
export const CELL_STATUSES = [
|
|
81
|
+
'pending',
|
|
82
|
+
'success',
|
|
83
|
+
'declared_gap',
|
|
84
|
+
'observed_null',
|
|
85
|
+
'not_eligible',
|
|
86
|
+
] as const;
|
|
87
|
+
export type CellStatus = (typeof CELL_STATUSES)[number];
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* The ONLY statuses that let an eligible cell count towards Phase-2 completion.
|
|
91
|
+
*
|
|
92
|
+
* `pending` is absent by construction. An unexecuted arm is not a null and
|
|
93
|
+
* cannot be represented as one — see `PendingIsNotComplete` below.
|
|
94
|
+
*/
|
|
95
|
+
export const PHASE2_COMPLETE_STATUSES = ['success', 'declared_gap', 'observed_null'] as const;
|
|
96
|
+
export type CompleteStatus = (typeof PHASE2_COMPLETE_STATUSES)[number];
|
|
97
|
+
|
|
98
|
+
/** Type-layer half of the completion invariant: `pending` is not completable. */
|
|
99
|
+
type Assert<T extends true> = T;
|
|
100
|
+
type PendingIsNotComplete = Assert<'pending' extends CompleteStatus ? false : true>;
|
|
101
|
+
type NotEligibleIsNotComplete = Assert<'not_eligible' extends CompleteStatus ? false : true>;
|
|
102
|
+
export type _CompletionInvariants = [PendingIsNotComplete, NotEligibleIsNotComplete];
|
|
103
|
+
|
|
104
|
+
/** One pre-registered benchmark family. */
|
|
105
|
+
export interface BenchFamily {
|
|
106
|
+
readonly id: string;
|
|
107
|
+
/** The family as roadmap step 2.1 names it, verbatim. */
|
|
108
|
+
readonly roadmapPhrase: string;
|
|
109
|
+
readonly label: FamilyLabel;
|
|
110
|
+
/** The pre-registered success criterion. Committed before any arm runs. */
|
|
111
|
+
readonly criterion: string;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* All twelve families of step 2.1, in the order the roadmap lists them. The
|
|
116
|
+
* step enumerates exactly twelve, so none of these is derived — every
|
|
117
|
+
* `roadmapPhrase` is a quotation.
|
|
118
|
+
*/
|
|
119
|
+
export const BENCH_FAMILIES = [
|
|
120
|
+
{
|
|
121
|
+
id: 'architecture-trade-offs',
|
|
122
|
+
roadmapPhrase: 'architecture trade-offs',
|
|
123
|
+
label: 'model-graded-exploratory',
|
|
124
|
+
criterion:
|
|
125
|
+
'A named trade-off axis, both sides costed, and a disposition. Graded by rubric against a fixed key; no deterministic oracle exists, so the arm is exploratory and never pooled with a confirmatory result.',
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
id: 'roadmap-critique',
|
|
129
|
+
roadmapPhrase: 'roadmap critique',
|
|
130
|
+
label: 'model-graded-exploratory',
|
|
131
|
+
criterion:
|
|
132
|
+
'Seeded defects in a synthetic roadmap (a missing verify line, an unfalsifiable criterion, a step that closes nothing) are named. Recall against the seeded set is countable; severity ranking is rubric-judged, hence exploratory.',
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
id: 'adr-reopening',
|
|
136
|
+
roadmapPhrase: 'ADR reopening',
|
|
137
|
+
label: 'model-graded-exploratory',
|
|
138
|
+
criterion:
|
|
139
|
+
'The record is opened before it is cited, the mechanism-match question is answered, and the routing verdict (council vs owner-reserved) is stated. Graded against a fixed key per item.',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
id: 'requirements-completeness',
|
|
143
|
+
roadmapPhrase: 'requirements completeness',
|
|
144
|
+
label: 'model-graded-exploratory',
|
|
145
|
+
criterion:
|
|
146
|
+
'Seeded omissions in a synthetic requirement set are recovered. Recall against the seeded set is countable; the false-addition rate is rubric-judged, hence exploratory.',
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
id: 'code-review-seeded-defects',
|
|
150
|
+
roadmapPhrase: 'code review with seeded defects',
|
|
151
|
+
label: 'gradeable-confirmatory',
|
|
152
|
+
criterion:
|
|
153
|
+
'Each item carries n seeded defects at known file:line. Primary metric is recall over the seeded set; secondary is the false-positive count against a frozen key. Deterministic — string match on the seeded identifier.',
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
id: 'security-review-seeded-findings',
|
|
157
|
+
roadmapPhrase: 'security review with seeded true/false findings',
|
|
158
|
+
label: 'gradeable-confirmatory',
|
|
159
|
+
criterion:
|
|
160
|
+
'Each item carries both true and decoy findings at known locations. Primary metric is the true-positive rate paired with the decoy-acceptance rate; a run that finds everything by accusing everything scores zero. Deterministic against a frozen key.',
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
id: 'debugging-executable-oracle',
|
|
164
|
+
roadmapPhrase: 'debugging with an executable oracle',
|
|
165
|
+
label: 'gradeable-confirmatory',
|
|
166
|
+
criterion:
|
|
167
|
+
'A failing test is supplied with the defect. The arm passes iff the proposed patch turns the test green and breaks no other test in the fixture. The oracle is the test runner, not a judge.',
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
id: 'incident-diagnosis',
|
|
171
|
+
roadmapPhrase: 'incident diagnosis',
|
|
172
|
+
label: 'model-graded-exploratory',
|
|
173
|
+
criterion:
|
|
174
|
+
'From a synthetic log-and-timeline bundle with one planted root cause, the arm names that cause and the first diagnostic step. Cause identity is checkable against the key; the diagnostic step is rubric-judged, hence exploratory.',
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
id: 'probe-resolvable-factual-controls',
|
|
178
|
+
roadmapPhrase: 'probe-resolvable factual controls',
|
|
179
|
+
label: 'gradeable-confirmatory',
|
|
180
|
+
criterion:
|
|
181
|
+
'Questions a single cheap probe answers exactly. The control succeeds when the answer matches the probe output. Its PURPOSE is to detect topologies that spend a debate on a lookup — a correct answer at high cost is a finding, not a pass.',
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
id: 'direct-generation-controls',
|
|
185
|
+
roadmapPhrase: 'direct-generation controls where debate is expected to hurt',
|
|
186
|
+
label: 'gradeable-confirmatory',
|
|
187
|
+
criterion:
|
|
188
|
+
'Tasks with one correct short answer where deliberation is predicted to degrade it. Pre-registered DIRECTIONAL prediction: the debate arm scores at or below the single-model arm. A debate arm that wins here falsifies the prediction and is published as such.',
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
id: 'adversarial-misconception',
|
|
192
|
+
roadmapPhrase: 'adversarial misconception cases',
|
|
193
|
+
label: 'gradeable-confirmatory',
|
|
194
|
+
criterion:
|
|
195
|
+
'Items whose plausible answer is wrong and whose correct answer is documented. Primary metric is the rate at which the arm resists the misconception; majority corruption is measured on the same items.',
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
id: 'ambiguous-product-decisions-human-rubric',
|
|
199
|
+
roadmapPhrase: 'ambiguous product decisions with a human rubric',
|
|
200
|
+
label: 'human-rubric-deferred',
|
|
201
|
+
criterion:
|
|
202
|
+
'DEFERRED — no human raters are available. Per the resolved `blocker: maintainer-blind-ratings` option (b), this family is pre-registered in full and published as deferred; it runs no arm and spends no call in Phase 2. A model-graded substitute is NOT run in its place: the blocker forbids using one as a stand-in for blind human judgment.',
|
|
203
|
+
},
|
|
204
|
+
] as const satisfies readonly BenchFamily[];
|
|
205
|
+
|
|
206
|
+
/** Declared arity, so an append or a deletion reds the typecheck. */
|
|
207
|
+
export const BENCH_FAMILY_ARITY = 12;
|
|
208
|
+
type FamilyArityHolds = Assert<typeof BENCH_FAMILIES.length extends 12 ? true : false>;
|
|
209
|
+
export type _FamilyArity = [FamilyArityHolds];
|
|
210
|
+
|
|
211
|
+
/** Who participates in one pass. */
|
|
212
|
+
export type PassParticipants = 'all-members' | 'chairman' | 'anthropic-only' | 'openai-only';
|
|
213
|
+
|
|
214
|
+
/** One pass in an arm's call graph. */
|
|
215
|
+
export interface BenchPass {
|
|
216
|
+
readonly kind:
|
|
217
|
+
| 'generation'
|
|
218
|
+
| 'peer-critique'
|
|
219
|
+
| 'findings-extraction'
|
|
220
|
+
| 'consensus-scoring'
|
|
221
|
+
| 'prose-synthesis';
|
|
222
|
+
readonly participants: PassParticipants;
|
|
223
|
+
/** Repetitions of this pass. Generation repeats once per debate round. */
|
|
224
|
+
readonly repeat: number;
|
|
225
|
+
/**
|
|
226
|
+
* True where the pass carries the ONE bounded re-ask of
|
|
227
|
+
* `consensus_round.ts:141`. This is the entire retry reserve — no other
|
|
228
|
+
* pass retries, and the re-ask is bounded at one, never a loop.
|
|
229
|
+
*/
|
|
230
|
+
readonly retryEligible: boolean;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** One frozen experimental arm. */
|
|
234
|
+
export interface BenchArm {
|
|
235
|
+
readonly id: string;
|
|
236
|
+
readonly group: 'baseline' | 'ablation' | 'axis' | 'rounds';
|
|
237
|
+
/** Step 2.2 baseline name, or `null` where the arm is not a baseline. */
|
|
238
|
+
readonly baseline: string | null;
|
|
239
|
+
/** Step 2.4 ablation stage, or `null`. */
|
|
240
|
+
readonly stage: string | null;
|
|
241
|
+
/** A `CouncilTopology` name, `host-solo` where no external topology runs. */
|
|
242
|
+
readonly topology: string;
|
|
243
|
+
readonly modelSet: string;
|
|
244
|
+
readonly rounds: number;
|
|
245
|
+
readonly passes: readonly BenchPass[];
|
|
246
|
+
/**
|
|
247
|
+
* Arm whose result this arm REUSES rather than re-running, or `null`.
|
|
248
|
+
* Reuse is only ever explicit: an arm with `reuseOf` set books zero calls
|
|
249
|
+
* and must be scheduled into the same UTC-day batch as its source, so the
|
|
250
|
+
* shared observation cannot acquire a day-as-confounder.
|
|
251
|
+
*/
|
|
252
|
+
readonly reuseOf: string | null;
|
|
253
|
+
/** Why this arm exists, in the roadmap's own terms. */
|
|
254
|
+
readonly rationale: string;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const ALL_MEMBERS_GENERATION = (repeat: number): BenchPass => ({
|
|
258
|
+
kind: 'generation',
|
|
259
|
+
participants: 'all-members',
|
|
260
|
+
repeat,
|
|
261
|
+
retryEligible: false,
|
|
262
|
+
});
|
|
263
|
+
const PEER: BenchPass = {
|
|
264
|
+
kind: 'peer-critique',
|
|
265
|
+
participants: 'all-members',
|
|
266
|
+
repeat: 1,
|
|
267
|
+
retryEligible: false,
|
|
268
|
+
};
|
|
269
|
+
const EXTRACTION: BenchPass = {
|
|
270
|
+
kind: 'findings-extraction',
|
|
271
|
+
participants: 'all-members',
|
|
272
|
+
repeat: 1,
|
|
273
|
+
retryEligible: true,
|
|
274
|
+
};
|
|
275
|
+
const SCORING: BenchPass = {
|
|
276
|
+
kind: 'consensus-scoring',
|
|
277
|
+
participants: 'all-members',
|
|
278
|
+
repeat: 1,
|
|
279
|
+
retryEligible: false,
|
|
280
|
+
};
|
|
281
|
+
const SYNTHESIS: BenchPass = {
|
|
282
|
+
kind: 'prose-synthesis',
|
|
283
|
+
participants: 'chairman',
|
|
284
|
+
repeat: 1,
|
|
285
|
+
retryEligible: false,
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Model sets for the step-2.5 axis. Both seat exactly one member per provider,
|
|
290
|
+
* so `all-members` is one anthropic call plus one openai call in either set.
|
|
291
|
+
* `MS1` is the configured default pair; `MS2` is the cheaper pinned pair of the
|
|
292
|
+
* SAME two providers, so the axis varies model quality without varying the
|
|
293
|
+
* provider mix — which is the confound step 2.5 exists to separate out.
|
|
294
|
+
*/
|
|
295
|
+
export const MODEL_SETS = ['MS1-default', 'MS2-cheap'] as const;
|
|
296
|
+
|
|
297
|
+
/** The chairman provider for the synthesis pass. Pinned so it cannot drift. */
|
|
298
|
+
export const SYNTHESIS_CHAIRMAN: BenchProvider = 'anthropic';
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Every arm, frozen.
|
|
302
|
+
*
|
|
303
|
+
* ── The overlap question, answered explicitly ───────────────────────────────
|
|
304
|
+
* The council required a statement of whether the five baselines, five
|
|
305
|
+
* ablations, two axes and round arms overlap, with no implicit reuse. They
|
|
306
|
+
* overlap in exactly TWO places and nowhere else:
|
|
307
|
+
*
|
|
308
|
+
* - `axis-ms1-dual` is the same configuration as `baseline-default-council`
|
|
309
|
+
* and reuses it.
|
|
310
|
+
* - `rounds-1` is the same configuration as `baseline-default-council` and
|
|
311
|
+
* reuses it.
|
|
312
|
+
*
|
|
313
|
+
* Everything else re-runs. In particular the ablation ladder does NOT borrow
|
|
314
|
+
* `baseline-default-council`'s generation output for its `generation-only`
|
|
315
|
+
* rung, even though the two look interchangeable: an attribution claim needs
|
|
316
|
+
* all five rungs produced under identical conditions, and a rung borrowed from
|
|
317
|
+
* a baseline executed on a different UTC day would carry day-as-confounder
|
|
318
|
+
* into the one arm whose entire purpose is attribution.
|
|
319
|
+
*/
|
|
320
|
+
export const BENCH_ARMS = [
|
|
321
|
+
// ── Step 2.2 — the five mandatory baselines ─────────────────────────────
|
|
322
|
+
{
|
|
323
|
+
id: 'baseline-host-solo',
|
|
324
|
+
group: 'baseline',
|
|
325
|
+
baseline: 'host solo',
|
|
326
|
+
stage: null,
|
|
327
|
+
topology: 'host-solo',
|
|
328
|
+
modelSet: 'host',
|
|
329
|
+
rounds: 0,
|
|
330
|
+
passes: [],
|
|
331
|
+
reuseOf: null,
|
|
332
|
+
rationale:
|
|
333
|
+
'The zero-call floor. Its call count is 0 by construction, which is exactly why the roadmap total cannot be read off the cell count.',
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
id: 'baseline-single-strongest',
|
|
337
|
+
group: 'baseline',
|
|
338
|
+
baseline: 'strongest configured single external model',
|
|
339
|
+
stage: null,
|
|
340
|
+
topology: 'single_external',
|
|
341
|
+
modelSet: 'MS1-default',
|
|
342
|
+
rounds: 1,
|
|
343
|
+
passes: [{ ...ALL_MEMBERS_GENERATION(1), participants: 'anthropic-only' }],
|
|
344
|
+
reuseOf: null,
|
|
345
|
+
rationale:
|
|
346
|
+
'Step 2.2 verify: no result may claim "council improves quality" without a strong single-model baseline in the same table.',
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
id: 'baseline-single-cheapest',
|
|
350
|
+
group: 'baseline',
|
|
351
|
+
baseline: 'cheapest configured single external model',
|
|
352
|
+
stage: null,
|
|
353
|
+
topology: 'single_external',
|
|
354
|
+
modelSet: 'MS2-cheap',
|
|
355
|
+
rounds: 1,
|
|
356
|
+
passes: [{ ...ALL_MEMBERS_GENERATION(1), participants: 'openai-only' }],
|
|
357
|
+
reuseOf: null,
|
|
358
|
+
rationale:
|
|
359
|
+
'The cost floor of the external arms. Provider assignment follows the configured strongest/cheapest ranking and is pinned here so it cannot drift between batches.',
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
id: 'baseline-default-council',
|
|
363
|
+
group: 'baseline',
|
|
364
|
+
baseline: 'current default council path',
|
|
365
|
+
stage: null,
|
|
366
|
+
topology: 'dual_independent',
|
|
367
|
+
modelSet: 'MS1-default',
|
|
368
|
+
rounds: 1,
|
|
369
|
+
passes: [ALL_MEMBERS_GENERATION(1), EXTRACTION, SCORING],
|
|
370
|
+
reuseOf: null,
|
|
371
|
+
rationale: 'What the suite does today. Every improvement claim is measured against this.',
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
id: 'baseline-full-debate',
|
|
375
|
+
group: 'baseline',
|
|
376
|
+
baseline: 'full debate where applicable',
|
|
377
|
+
stage: null,
|
|
378
|
+
topology: 'full_debate',
|
|
379
|
+
modelSet: 'MS1-default',
|
|
380
|
+
rounds: 2,
|
|
381
|
+
passes: [ALL_MEMBERS_GENERATION(2), PEER, EXTRACTION, SCORING],
|
|
382
|
+
reuseOf: null,
|
|
383
|
+
rationale: 'The expensive ceiling. Its cost is the number the cheaper topologies must beat.',
|
|
384
|
+
},
|
|
385
|
+
|
|
386
|
+
// ── Step 2.4 — the five-rung ablation ladder ────────────────────────────
|
|
387
|
+
{
|
|
388
|
+
id: 'ablation-generation-only',
|
|
389
|
+
group: 'ablation',
|
|
390
|
+
baseline: null,
|
|
391
|
+
stage: 'generation only',
|
|
392
|
+
topology: 'dual_independent',
|
|
393
|
+
modelSet: 'MS1-default',
|
|
394
|
+
rounds: 1,
|
|
395
|
+
passes: [ALL_MEMBERS_GENERATION(1)],
|
|
396
|
+
reuseOf: null,
|
|
397
|
+
rationale: 'Rung 1. Step 2.4 verify: an improvement can be attributed to a named stage.',
|
|
398
|
+
},
|
|
399
|
+
{
|
|
400
|
+
id: 'ablation-plus-ranking',
|
|
401
|
+
group: 'ablation',
|
|
402
|
+
baseline: null,
|
|
403
|
+
stage: '+ ranking',
|
|
404
|
+
topology: 'dual_independent',
|
|
405
|
+
modelSet: 'MS1-default',
|
|
406
|
+
rounds: 1,
|
|
407
|
+
passes: [ALL_MEMBERS_GENERATION(1), SCORING],
|
|
408
|
+
reuseOf: null,
|
|
409
|
+
rationale: 'Rung 2 — adds the consensus scoring pass and nothing else.',
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
id: 'ablation-plus-peer-critique',
|
|
413
|
+
group: 'ablation',
|
|
414
|
+
baseline: null,
|
|
415
|
+
stage: '+ peer critique',
|
|
416
|
+
topology: 'peer_review',
|
|
417
|
+
modelSet: 'MS1-default',
|
|
418
|
+
rounds: 1,
|
|
419
|
+
passes: [ALL_MEMBERS_GENERATION(1), PEER, SCORING],
|
|
420
|
+
reuseOf: null,
|
|
421
|
+
rationale: 'Rung 3 — adds the anonymised peer-review pass.',
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
id: 'ablation-plus-synthesis',
|
|
425
|
+
group: 'ablation',
|
|
426
|
+
baseline: null,
|
|
427
|
+
stage: '+ synthesis',
|
|
428
|
+
topology: 'judge_synthesis',
|
|
429
|
+
modelSet: 'MS1-default',
|
|
430
|
+
rounds: 1,
|
|
431
|
+
passes: [ALL_MEMBERS_GENERATION(1), PEER, SCORING, SYNTHESIS],
|
|
432
|
+
reuseOf: null,
|
|
433
|
+
rationale:
|
|
434
|
+
'Rung 4. The templated synthesis path spends nothing, so the synthesis STAGE is only observable with the prose path on — which is one chairman call, and the only asymmetric pass in the ladder.',
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
id: 'ablation-full-pipeline',
|
|
438
|
+
group: 'ablation',
|
|
439
|
+
baseline: null,
|
|
440
|
+
stage: 'full pipeline',
|
|
441
|
+
topology: 'judge_synthesis',
|
|
442
|
+
modelSet: 'MS1-default',
|
|
443
|
+
rounds: 1,
|
|
444
|
+
passes: [ALL_MEMBERS_GENERATION(1), PEER, EXTRACTION, SCORING, SYNTHESIS],
|
|
445
|
+
reuseOf: null,
|
|
446
|
+
rationale: 'Rung 5 — every stage on, so rung 4 → rung 5 isolates findings extraction.',
|
|
447
|
+
},
|
|
448
|
+
|
|
449
|
+
// ── Step 2.5 — the two axes ─────────────────────────────────────────────
|
|
450
|
+
{
|
|
451
|
+
id: 'axis-ms1-dual',
|
|
452
|
+
group: 'axis',
|
|
453
|
+
baseline: null,
|
|
454
|
+
stage: null,
|
|
455
|
+
topology: 'dual_independent',
|
|
456
|
+
modelSet: 'MS1-default',
|
|
457
|
+
rounds: 1,
|
|
458
|
+
passes: [ALL_MEMBERS_GENERATION(1), EXTRACTION, SCORING],
|
|
459
|
+
reuseOf: 'baseline-default-council',
|
|
460
|
+
rationale:
|
|
461
|
+
'The shared corner of both axes. Declared reuse of the default-council baseline — identical configuration, so re-running it would buy a second sample of the same cell rather than a second cell.',
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
id: 'axis-ms1-peer',
|
|
465
|
+
group: 'axis',
|
|
466
|
+
baseline: null,
|
|
467
|
+
stage: null,
|
|
468
|
+
topology: 'peer_review',
|
|
469
|
+
modelSet: 'MS1-default',
|
|
470
|
+
rounds: 1,
|
|
471
|
+
passes: [ALL_MEMBERS_GENERATION(1), PEER, SCORING],
|
|
472
|
+
reuseOf: null,
|
|
473
|
+
rationale: 'Same model set, second topology — the topology axis.',
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
id: 'axis-ms2-dual',
|
|
477
|
+
group: 'axis',
|
|
478
|
+
baseline: null,
|
|
479
|
+
stage: null,
|
|
480
|
+
topology: 'dual_independent',
|
|
481
|
+
modelSet: 'MS2-cheap',
|
|
482
|
+
rounds: 1,
|
|
483
|
+
passes: [ALL_MEMBERS_GENERATION(1), EXTRACTION, SCORING],
|
|
484
|
+
reuseOf: null,
|
|
485
|
+
rationale: 'Same topology, second model set — the model-quality axis.',
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
id: 'axis-ms2-peer',
|
|
489
|
+
group: 'axis',
|
|
490
|
+
baseline: null,
|
|
491
|
+
stage: null,
|
|
492
|
+
topology: 'peer_review',
|
|
493
|
+
modelSet: 'MS2-cheap',
|
|
494
|
+
rounds: 1,
|
|
495
|
+
passes: [ALL_MEMBERS_GENERATION(1), PEER, SCORING],
|
|
496
|
+
reuseOf: null,
|
|
497
|
+
rationale:
|
|
498
|
+
'The fourth corner. Without it the two axes cannot be separated from their interaction.',
|
|
499
|
+
},
|
|
500
|
+
|
|
501
|
+
// ── Step 2.7 — the round-count arm ──────────────────────────────────────
|
|
502
|
+
{
|
|
503
|
+
id: 'rounds-1',
|
|
504
|
+
group: 'rounds',
|
|
505
|
+
baseline: null,
|
|
506
|
+
stage: null,
|
|
507
|
+
topology: 'dual_independent',
|
|
508
|
+
modelSet: 'MS1-default',
|
|
509
|
+
rounds: 1,
|
|
510
|
+
passes: [ALL_MEMBERS_GENERATION(1), EXTRACTION, SCORING],
|
|
511
|
+
reuseOf: 'baseline-default-council',
|
|
512
|
+
rationale:
|
|
513
|
+
'The rounds=1 leg. Declared reuse of the default-council baseline — identical configuration.',
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
id: 'rounds-2',
|
|
517
|
+
group: 'rounds',
|
|
518
|
+
baseline: null,
|
|
519
|
+
stage: null,
|
|
520
|
+
topology: 'dual_independent',
|
|
521
|
+
modelSet: 'MS1-default',
|
|
522
|
+
rounds: 2,
|
|
523
|
+
passes: [ALL_MEMBERS_GENERATION(2), EXTRACTION, SCORING],
|
|
524
|
+
reuseOf: null,
|
|
525
|
+
rationale:
|
|
526
|
+
'The rounds=2 leg. Grounded in arXiv 2505.19477 (round-1 debate bias amplification); step 2.7 accepts a published null as a valid outcome.',
|
|
527
|
+
},
|
|
528
|
+
] as const satisfies readonly BenchArm[];
|
|
529
|
+
|
|
530
|
+
/** The full step-2.3 metric set. A missing column is a declared gap, never silence. */
|
|
531
|
+
export const BENCH_METRICS = [
|
|
532
|
+
'deterministic-correctness',
|
|
533
|
+
'executable-test-result',
|
|
534
|
+
'rubric-quality',
|
|
535
|
+
'cost',
|
|
536
|
+
'latency',
|
|
537
|
+
'calls',
|
|
538
|
+
'tokens',
|
|
539
|
+
'parse-gradeability-rate',
|
|
540
|
+
'rerun-variance',
|
|
541
|
+
'disagreement-entropy',
|
|
542
|
+
'minority-rescue',
|
|
543
|
+
'majority-corruption',
|
|
544
|
+
'synthesis-delta',
|
|
545
|
+
'zero-marginal-value-call-rate',
|
|
546
|
+
] as const;
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Items per family, and trials per item.
|
|
550
|
+
*
|
|
551
|
+
* Both are DECLARED here rather than derived: the roadmap fixes neither, and
|
|
552
|
+
* the day count is linear in their product, so leaving them implicit is what
|
|
553
|
+
* made the phase unschedulable. One item per family is the minimum at which a
|
|
554
|
+
* family has an observation at all; N=2 is the roadmap's own floor.
|
|
555
|
+
*/
|
|
556
|
+
export const ITEMS_PER_FAMILY = 1;
|
|
557
|
+
export const TRIALS_PER_ITEM = 2;
|
|
558
|
+
|
|
559
|
+
/** One fully addressed manifest row. */
|
|
560
|
+
export interface ManifestCell {
|
|
561
|
+
readonly cell_id: string;
|
|
562
|
+
readonly family: string;
|
|
563
|
+
readonly family_label: FamilyLabel;
|
|
564
|
+
readonly item: string;
|
|
565
|
+
readonly trial: number;
|
|
566
|
+
readonly baseline: string | null;
|
|
567
|
+
readonly stage: string | null;
|
|
568
|
+
readonly topology: string;
|
|
569
|
+
readonly model_set: string;
|
|
570
|
+
readonly rounds: number;
|
|
571
|
+
readonly expected_calls: ProviderCalls;
|
|
572
|
+
readonly max_calls: ProviderCalls;
|
|
573
|
+
readonly reuse_source: string | null;
|
|
574
|
+
/**
|
|
575
|
+
* The step-2.3 metric set this cell emits, by REFERENCE to `metric_set` in
|
|
576
|
+
* the serialised manifest. Every eligible cell emits the full set, so
|
|
577
|
+
* inlining fourteen identical strings 384 times would add a third of a
|
|
578
|
+
* megabyte to a frozen artefact without adding a fact. A missing column at
|
|
579
|
+
* run time is recorded as a declared gap on the RESULT, never by quietly
|
|
580
|
+
* shortening this list.
|
|
581
|
+
*/
|
|
582
|
+
readonly metrics: 'full-2.3-set';
|
|
583
|
+
readonly status: CellStatus;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
const ZERO: ProviderCalls = Object.freeze({ anthropic: 0, openai: 0 });
|
|
587
|
+
|
|
588
|
+
function addCalls(a: ProviderCalls, b: ProviderCalls): ProviderCalls {
|
|
589
|
+
return { anthropic: a.anthropic + b.anthropic, openai: a.openai + b.openai };
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/** Calls one pass books, before any retry reserve. */
|
|
593
|
+
function passCalls(pass: BenchPass): ProviderCalls {
|
|
594
|
+
const n = pass.repeat;
|
|
595
|
+
switch (pass.participants) {
|
|
596
|
+
case 'all-members':
|
|
597
|
+
return { anthropic: n, openai: n };
|
|
598
|
+
case 'chairman':
|
|
599
|
+
return SYNTHESIS_CHAIRMAN === 'anthropic'
|
|
600
|
+
? { anthropic: n, openai: 0 }
|
|
601
|
+
: { anthropic: 0, openai: n };
|
|
602
|
+
case 'anthropic-only':
|
|
603
|
+
return { anthropic: n, openai: 0 };
|
|
604
|
+
case 'openai-only':
|
|
605
|
+
return { anthropic: 0, openai: n };
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* The retry reserve a pass adds: ONE re-ask per participating member, and only
|
|
611
|
+
* for the findings-extraction pass. Reserved up front rather than spent
|
|
612
|
+
* opportunistically — a retry that discovers the cap mid-cell has already
|
|
613
|
+
* breached it.
|
|
614
|
+
*/
|
|
615
|
+
function passRetryReserve(pass: BenchPass): ProviderCalls {
|
|
616
|
+
if (!pass.retryEligible) return ZERO;
|
|
617
|
+
return passCalls({ ...pass, repeat: pass.repeat });
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/** Expected and maximum provider calls for one arm. */
|
|
621
|
+
export function armCalls(arm: BenchArm): { expected: ProviderCalls; max: ProviderCalls } {
|
|
622
|
+
if (arm.reuseOf !== null) return { expected: ZERO, max: ZERO };
|
|
623
|
+
let expected = ZERO;
|
|
624
|
+
let reserve = ZERO;
|
|
625
|
+
for (const pass of arm.passes) {
|
|
626
|
+
expected = addCalls(expected, passCalls(pass));
|
|
627
|
+
reserve = addCalls(reserve, passRetryReserve(pass));
|
|
628
|
+
}
|
|
629
|
+
return { expected, max: addCalls(expected, reserve) };
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Expand the frozen spec into every cell. Deterministic and order-stable:
|
|
634
|
+
* family order, then item, then trial, then arm order.
|
|
635
|
+
*
|
|
636
|
+
* Every emitted cell is `pending` — or `not_eligible` for the deferred family,
|
|
637
|
+
* which is emitted rather than dropped so its exclusion is visible in the
|
|
638
|
+
* manifest instead of inferable from an absence.
|
|
639
|
+
*/
|
|
640
|
+
export function expandManifest(): ManifestCell[] {
|
|
641
|
+
const cells: ManifestCell[] = [];
|
|
642
|
+
for (const family of BENCH_FAMILIES) {
|
|
643
|
+
const eligible = family.label !== 'human-rubric-deferred';
|
|
644
|
+
for (let i = 1; i <= ITEMS_PER_FAMILY; i++) {
|
|
645
|
+
const item = `${family.id}-item-${String(i).padStart(2, '0')}`;
|
|
646
|
+
for (let trial = 1; trial <= TRIALS_PER_ITEM; trial++) {
|
|
647
|
+
for (const arm of BENCH_ARMS) {
|
|
648
|
+
const { expected, max } = armCalls(arm);
|
|
649
|
+
cells.push({
|
|
650
|
+
cell_id: `${item}/t${trial}/${arm.id}`,
|
|
651
|
+
family: family.id,
|
|
652
|
+
family_label: family.label,
|
|
653
|
+
item,
|
|
654
|
+
trial,
|
|
655
|
+
baseline: arm.baseline,
|
|
656
|
+
stage: arm.stage,
|
|
657
|
+
topology: arm.topology,
|
|
658
|
+
model_set: arm.modelSet,
|
|
659
|
+
rounds: arm.rounds,
|
|
660
|
+
expected_calls: eligible ? expected : ZERO,
|
|
661
|
+
max_calls: eligible ? max : ZERO,
|
|
662
|
+
reuse_source: arm.reuseOf,
|
|
663
|
+
metrics: 'full-2.3-set',
|
|
664
|
+
status: eligible ? 'pending' : 'not_eligible',
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
return cells;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/** One immutable UTC-day batch. */
|
|
674
|
+
export interface DayBatch {
|
|
675
|
+
readonly day: number;
|
|
676
|
+
readonly cell_ids: readonly string[];
|
|
677
|
+
readonly booked: ProviderCalls;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
/**
|
|
681
|
+
* Partition cells into UTC-day batches under the per-provider cap.
|
|
682
|
+
*
|
|
683
|
+
* Books **maximum** calls, never expected: the retry reserve has to be held
|
|
684
|
+
* before a cell starts, or a re-ask discovers the ceiling by crossing it. A
|
|
685
|
+
* cell is atomic — it never spans a day boundary, because a cell split across
|
|
686
|
+
* days acquires day-as-confounder inside a single observation.
|
|
687
|
+
*
|
|
688
|
+
* Greedy and deterministic in cell order, so the same spec yields the same
|
|
689
|
+
* schedule on every machine. Zero-call cells (host-solo, declared reuse, the
|
|
690
|
+
* deferred family) still land in a batch, since they must be observed on the
|
|
691
|
+
* same day as the arms they are compared with.
|
|
692
|
+
*/
|
|
693
|
+
export function partitionIntoDays(
|
|
694
|
+
cells: readonly ManifestCell[],
|
|
695
|
+
capPerProvider: number = CALLS_PER_PROVIDER_PER_UTC_DAY,
|
|
696
|
+
): DayBatch[] {
|
|
697
|
+
const batches: { day: number; cell_ids: string[]; booked: { anthropic: number; openai: number } }[] =
|
|
698
|
+
[];
|
|
699
|
+
let current = { day: 1, cell_ids: [] as string[], booked: { anthropic: 0, openai: 0 } };
|
|
700
|
+
for (const cell of cells) {
|
|
701
|
+
const fits =
|
|
702
|
+
current.booked.anthropic + cell.max_calls.anthropic <= capPerProvider &&
|
|
703
|
+
current.booked.openai + cell.max_calls.openai <= capPerProvider;
|
|
704
|
+
if (!fits) {
|
|
705
|
+
batches.push(current);
|
|
706
|
+
current = { day: batches.length + 1, cell_ids: [], booked: { anthropic: 0, openai: 0 } };
|
|
707
|
+
}
|
|
708
|
+
current.cell_ids.push(cell.cell_id);
|
|
709
|
+
current.booked.anthropic += cell.max_calls.anthropic;
|
|
710
|
+
current.booked.openai += cell.max_calls.openai;
|
|
711
|
+
}
|
|
712
|
+
batches.push(current);
|
|
713
|
+
return batches.map((b) => ({ day: b.day, cell_ids: b.cell_ids, booked: { ...b.booked } }));
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
/** The totals the council asked for, and the reason this module exists. */
|
|
717
|
+
export interface ManifestTotals {
|
|
718
|
+
readonly cells: number;
|
|
719
|
+
readonly eligible_cells: number;
|
|
720
|
+
readonly deferred_cells: number;
|
|
721
|
+
readonly reuse_cells: number;
|
|
722
|
+
readonly minimum_calls: ProviderCalls;
|
|
723
|
+
readonly worst_case_calls: ProviderCalls;
|
|
724
|
+
readonly minimum_total: number;
|
|
725
|
+
readonly worst_case_total: number;
|
|
726
|
+
readonly utc_days: number;
|
|
727
|
+
readonly cap_per_provider_per_day: number;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
export function summariseManifest(cells: readonly ManifestCell[]): ManifestTotals {
|
|
731
|
+
let min = ZERO;
|
|
732
|
+
let max = ZERO;
|
|
733
|
+
let eligible = 0;
|
|
734
|
+
let deferred = 0;
|
|
735
|
+
let reuse = 0;
|
|
736
|
+
for (const c of cells) {
|
|
737
|
+
min = addCalls(min, c.expected_calls);
|
|
738
|
+
max = addCalls(max, c.max_calls);
|
|
739
|
+
if (c.status === 'not_eligible') deferred++;
|
|
740
|
+
else eligible++;
|
|
741
|
+
if (c.reuse_source !== null) reuse++;
|
|
742
|
+
}
|
|
743
|
+
return {
|
|
744
|
+
cells: cells.length,
|
|
745
|
+
eligible_cells: eligible,
|
|
746
|
+
deferred_cells: deferred,
|
|
747
|
+
reuse_cells: reuse,
|
|
748
|
+
minimum_calls: min,
|
|
749
|
+
worst_case_calls: max,
|
|
750
|
+
minimum_total: min.anthropic + min.openai,
|
|
751
|
+
worst_case_total: max.anthropic + max.openai,
|
|
752
|
+
utc_days: partitionIntoDays(cells).length,
|
|
753
|
+
cap_per_provider_per_day: CALLS_PER_PROVIDER_PER_UTC_DAY,
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
* Is Phase 2 complete? Only when every ELIGIBLE cell carries an observed
|
|
759
|
+
* outcome. `pending` is never an outcome, which is the encoded form of "not
|
|
760
|
+
* run is not a null".
|
|
761
|
+
*/
|
|
762
|
+
export function phase2Complete(cells: readonly ManifestCell[]): boolean {
|
|
763
|
+
return cells
|
|
764
|
+
.filter((c) => c.status !== 'not_eligible')
|
|
765
|
+
.every((c) => (PHASE2_COMPLETE_STATUSES as readonly string[]).includes(c.status));
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
/** Runtime twin of the type-layer completion invariant. Types erase; this does not. */
|
|
769
|
+
export function auditCompletionStatuses(): void {
|
|
770
|
+
const complete = PHASE2_COMPLETE_STATUSES as readonly string[];
|
|
771
|
+
for (const forbidden of ['pending', 'not_eligible']) {
|
|
772
|
+
if (complete.includes(forbidden)) {
|
|
773
|
+
throw new Error(
|
|
774
|
+
`council-topology manifest: \`${forbidden}\` must never count as a completed cell — ` +
|
|
775
|
+
'an unexecuted arm is not a null.',
|
|
776
|
+
);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
if (BENCH_FAMILIES.length !== BENCH_FAMILY_ARITY) {
|
|
780
|
+
throw new Error(
|
|
781
|
+
`council-topology manifest: expected exactly ${BENCH_FAMILY_ARITY} pre-registered ` +
|
|
782
|
+
`families, found ${BENCH_FAMILIES.length}. Changing the family set weakens step 2.1 ` +
|
|
783
|
+
'and is owner-reserved.',
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
auditCompletionStatuses();
|
|
789
|
+
|
|
790
|
+
/** The committed manifest artefact, relative to the repo root. */
|
|
791
|
+
export const MANIFEST_PATH = 'internal/bench/council-topology/call-manifest.json';
|
|
792
|
+
|
|
793
|
+
/** The whole frozen manifest, as it is serialised. */
|
|
794
|
+
export function renderManifest(): string {
|
|
795
|
+
const cells = expandManifest();
|
|
796
|
+
return `${JSON.stringify(
|
|
797
|
+
{
|
|
798
|
+
schema_version: 1,
|
|
799
|
+
generated_by: 'src/scripts/ai_council/topology_bench_manifest.ts',
|
|
800
|
+
frozen: true,
|
|
801
|
+
note:
|
|
802
|
+
'Generated. Never hand-edit — regenerate from the frozen arm spec. ' +
|
|
803
|
+
'Editing a call count here without editing the spec would let the ' +
|
|
804
|
+
'schedule drift from the mechanics it claims to model.',
|
|
805
|
+
cap_per_provider_per_utc_day: CALLS_PER_PROVIDER_PER_UTC_DAY,
|
|
806
|
+
items_per_family: ITEMS_PER_FAMILY,
|
|
807
|
+
trials_per_item: TRIALS_PER_ITEM,
|
|
808
|
+
complete_statuses: PHASE2_COMPLETE_STATUSES,
|
|
809
|
+
metric_set: BENCH_METRICS,
|
|
810
|
+
families: BENCH_FAMILIES,
|
|
811
|
+
arms: BENCH_ARMS,
|
|
812
|
+
totals: summariseManifest(cells),
|
|
813
|
+
day_batches: partitionIntoDays(cells),
|
|
814
|
+
cells,
|
|
815
|
+
},
|
|
816
|
+
null,
|
|
817
|
+
2,
|
|
818
|
+
)}\n`;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
/** `./scripts-run src/scripts/ai_council/topology_bench_manifest --emit` */
|
|
822
|
+
export async function main(argv: readonly string[] = process.argv.slice(2)): Promise<number> {
|
|
823
|
+
const cells = expandManifest();
|
|
824
|
+
const totals = summariseManifest(cells);
|
|
825
|
+
if (argv.includes('--emit')) {
|
|
826
|
+
const fs = await import('node:fs');
|
|
827
|
+
fs.writeFileSync(MANIFEST_PATH, renderManifest(), 'utf8');
|
|
828
|
+
process.stdout.write(`wrote ${MANIFEST_PATH}\n`);
|
|
829
|
+
}
|
|
830
|
+
process.stdout.write(
|
|
831
|
+
`cells ${totals.cells} (eligible ${totals.eligible_cells}, deferred ${totals.deferred_cells}, reuse ${totals.reuse_cells})\n` +
|
|
832
|
+
`minimum ${totals.minimum_total} calls — anthropic ${totals.minimum_calls.anthropic}, openai ${totals.minimum_calls.openai}\n` +
|
|
833
|
+
`worst case ${totals.worst_case_total} calls — anthropic ${totals.worst_case_calls.anthropic}, openai ${totals.worst_case_calls.openai}\n` +
|
|
834
|
+
`UTC days ${totals.utc_days} at ${totals.cap_per_provider_per_day} calls/provider/day\n`,
|
|
835
|
+
);
|
|
836
|
+
return 0;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
// Self-execution guard.
|
|
840
|
+
// `run.ts` spawns the file directly, so the module runs its own entry point.
|
|
841
|
+
// realpath on both sides because argv[1] keeps the symlinked path while
|
|
842
|
+
// import.meta.url is already resolved -- the same comparison
|
|
843
|
+
// `check_council_references.ts:356-360` makes for the same reason.
|
|
844
|
+
{
|
|
845
|
+
const nodeFs = await import('node:fs');
|
|
846
|
+
const nodeUrl = await import('node:url');
|
|
847
|
+
const invoked = process.argv[1];
|
|
848
|
+
if (invoked !== undefined && invoked !== '') {
|
|
849
|
+
let here = '';
|
|
850
|
+
let there = ' ';
|
|
851
|
+
try {
|
|
852
|
+
here = nodeFs.realpathSync(nodeUrl.fileURLToPath(import.meta.url));
|
|
853
|
+
there = nodeFs.realpathSync(invoked);
|
|
854
|
+
} catch {
|
|
855
|
+
here = '';
|
|
856
|
+
there = ' ';
|
|
857
|
+
}
|
|
858
|
+
if (here === there) process.exit(await main());
|
|
859
|
+
}
|
|
860
|
+
}
|