@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,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-judge position-consistency — order-swap over sampled pairwise judgments.
|
|
3
|
+
*
|
|
4
|
+
* `road-to-inbox-harvest-2026-08-e-council-topology-evidence` Phase 3, step 3.5:
|
|
5
|
+
* "repeat sampled pairwise judgments with candidate order reversed; emit a
|
|
6
|
+
* per-judge position-consistency metric", verified by "the metric exists per
|
|
7
|
+
* judge and is reported with the verdict".
|
|
8
|
+
*
|
|
9
|
+
* ── What already existed, and why this is not a second copy of it ────────────
|
|
10
|
+
* `check_quality_regression.evaluatePair` (`:84-108`) already judges every pair
|
|
11
|
+
* in both orders and resolves a flip to `inconsistent` rather than to a winner,
|
|
12
|
+
* and `_lib/judge_hygiene.ts:5-9` records that as stronger than the step that
|
|
13
|
+
* asked for it. Two things it does not do, and both are the point here:
|
|
14
|
+
*
|
|
15
|
+
* 1. It is SINGLE-JUDGE. `aggregate` returns one run-wide `inconsistency_rate`
|
|
16
|
+
* (`:216`), so two judges of differing reliability average into one number
|
|
17
|
+
* that describes neither. The step asks for the metric PER JUDGE, which is
|
|
18
|
+
* what makes it actionable: you can drop the flipper.
|
|
19
|
+
* 2. It reports presence, not DIRECTION. A judge that flips at random and a
|
|
20
|
+
* judge that always prefers whatever it was shown first produce the same
|
|
21
|
+
* inconsistency rate and need opposite remedies — the first is noise, the
|
|
22
|
+
* second is a systematic bias that survives averaging and quietly decides
|
|
23
|
+
* verdicts. `first_position_rate` separates them.
|
|
24
|
+
*
|
|
25
|
+
* That module is the thin-vs-eager token gate and is not council code; this one
|
|
26
|
+
* is council-side and stays a pure library — no transport, no fixture path, no
|
|
27
|
+
* `main`. The judge is an injected function, so the whole surface is testable
|
|
28
|
+
* against a scripted judge and costs nothing to exercise.
|
|
29
|
+
*
|
|
30
|
+
* ── Honest scope ────────────────────────────────────────────────────────────
|
|
31
|
+
* The shipped council has NO pairwise judging stage (`grep -rn pairwise
|
|
32
|
+
* src/scripts/ai_council` returns nothing): members deliberate, peer-review and
|
|
33
|
+
* are scored on findings, never compared two at a time. So this module is the
|
|
34
|
+
* metric and its renderer, exercised by the provider-leakage bench that Phase 3
|
|
35
|
+
* builds; it does not claim a live council verdict currently carries the line,
|
|
36
|
+
* because there is currently no live council judgment for it to describe.
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
import { _sha256_hex } from './blind_review.js';
|
|
40
|
+
|
|
41
|
+
/** A judge's preference between the two PRESENTED candidates — order-relative. */
|
|
42
|
+
export type PairwiseVerdict = 'first' | 'second' | 'tie';
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The pluggable judge. `first`/`second` are the candidate bodies in PRESENTED
|
|
46
|
+
* order, so a judge implementation cannot tell which arm it is looking at
|
|
47
|
+
* unless the bodies themselves leak it.
|
|
48
|
+
*/
|
|
49
|
+
export type PairwiseJudge = (ctx: { readonly id: string }, first: string, second: string) => PairwiseVerdict;
|
|
50
|
+
|
|
51
|
+
/** How a pair resolved once both orders were seen. */
|
|
52
|
+
export type PairResolution = 'a' | 'b' | 'tie' | 'inconsistent';
|
|
53
|
+
|
|
54
|
+
export interface SwapObservation {
|
|
55
|
+
readonly id: string;
|
|
56
|
+
/** Verdict with A presented first. */
|
|
57
|
+
readonly forward: PairwiseVerdict;
|
|
58
|
+
/** Verdict with B presented first. */
|
|
59
|
+
readonly reverse: PairwiseVerdict;
|
|
60
|
+
readonly resolution: PairResolution;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Judge one (a, b) pair in BOTH orders.
|
|
65
|
+
*
|
|
66
|
+
* A verdict that does not survive the swap resolves to `inconsistent`, never to
|
|
67
|
+
* a winner — a flagged tie would still be a tie in somebody's denominator,
|
|
68
|
+
* while `inconsistent` is its own bucket with its own reported rate.
|
|
69
|
+
*/
|
|
70
|
+
export function judgeBothOrders(id: string, a: string, b: string, judge: PairwiseJudge): SwapObservation {
|
|
71
|
+
const ctx = { id };
|
|
72
|
+
const forward = judge(ctx, a, b);
|
|
73
|
+
const reverse = judge(ctx, b, a);
|
|
74
|
+
// Normalise each verdict to the CANDIDATE it names, not the position.
|
|
75
|
+
const wf: PairResolution = forward === 'first' ? 'a' : forward === 'second' ? 'b' : 'tie';
|
|
76
|
+
const wr: PairResolution = reverse === 'first' ? 'b' : reverse === 'second' ? 'a' : 'tie';
|
|
77
|
+
const resolution: PairResolution = wf === wr ? wf : 'inconsistent';
|
|
78
|
+
return { id, forward, reverse, resolution };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface JudgeConsistency {
|
|
82
|
+
readonly judge: string;
|
|
83
|
+
/** Pairs actually repeated in both orders. */
|
|
84
|
+
readonly sampled: number;
|
|
85
|
+
/** Both orders named the same candidate, or both said tie. */
|
|
86
|
+
readonly consistent: number;
|
|
87
|
+
/** The two orders disagreed. */
|
|
88
|
+
readonly inconsistent: number;
|
|
89
|
+
/**
|
|
90
|
+
* `consistent / sampled`. `null` at zero pairs — a rate over an empty
|
|
91
|
+
* denominator is not 1.0, and reporting it as 1.0 would make an unrun swap
|
|
92
|
+
* indistinguishable from a perfectly stable judge.
|
|
93
|
+
*/
|
|
94
|
+
readonly position_consistency: number | null;
|
|
95
|
+
/**
|
|
96
|
+
* Share of DECISIVE verdicts (`first`/`second`, both orders pooled) that
|
|
97
|
+
* named whichever candidate was shown FIRST. ~0.5 is unbiased; near 1.0 is
|
|
98
|
+
* primacy, near 0.0 recency. `null` when nothing decisive was said.
|
|
99
|
+
*
|
|
100
|
+
* This is the direction an inconsistency rate cannot show, and the reason a
|
|
101
|
+
* judge that flips at random is a different problem from one that always
|
|
102
|
+
* prefers the top of the list.
|
|
103
|
+
*/
|
|
104
|
+
readonly first_position_rate: number | null;
|
|
105
|
+
/** Decisive verdicts counted for `first_position_rate`. */
|
|
106
|
+
readonly decisive_verdicts: number;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Per-judge metric over that judge's own swapped observations. */
|
|
110
|
+
export function positionConsistency(judge: string, obs: readonly SwapObservation[]): JudgeConsistency {
|
|
111
|
+
let consistent = 0;
|
|
112
|
+
let inconsistent = 0;
|
|
113
|
+
let firstWins = 0;
|
|
114
|
+
let decisive = 0;
|
|
115
|
+
for (const o of obs) {
|
|
116
|
+
if (o.resolution === 'inconsistent') {
|
|
117
|
+
inconsistent += 1;
|
|
118
|
+
} else {
|
|
119
|
+
consistent += 1;
|
|
120
|
+
}
|
|
121
|
+
for (const v of [o.forward, o.reverse]) {
|
|
122
|
+
if (v === 'first') {
|
|
123
|
+
decisive += 1;
|
|
124
|
+
firstWins += 1;
|
|
125
|
+
} else if (v === 'second') {
|
|
126
|
+
decisive += 1;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const sampled = obs.length;
|
|
131
|
+
return {
|
|
132
|
+
judge,
|
|
133
|
+
sampled,
|
|
134
|
+
consistent,
|
|
135
|
+
inconsistent,
|
|
136
|
+
position_consistency: sampled > 0 ? consistent / sampled : null,
|
|
137
|
+
first_position_rate: decisive > 0 ? firstWins / decisive : null,
|
|
138
|
+
decisive_verdicts: decisive,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Deterministic sample of `ids` at `rate`, seeded by `seed`.
|
|
144
|
+
*
|
|
145
|
+
* The step says "SAMPLED pairwise judgments", because the swap doubles judge
|
|
146
|
+
* calls and doubling every one of them to measure the judge is a cost the
|
|
147
|
+
* measurement does not need. Deterministic so a published consistency figure is
|
|
148
|
+
* reproducible from the report's own seed — a sample nobody can re-draw is a
|
|
149
|
+
* number nobody can check.
|
|
150
|
+
*
|
|
151
|
+
* `rate <= 0` samples nothing; `rate >= 1` samples everything.
|
|
152
|
+
*/
|
|
153
|
+
export function sampleForSwap(ids: readonly string[], rate: number, seed: string): string[] {
|
|
154
|
+
if (!(rate > 0)) {
|
|
155
|
+
return [];
|
|
156
|
+
}
|
|
157
|
+
if (rate >= 1) {
|
|
158
|
+
return [...ids];
|
|
159
|
+
}
|
|
160
|
+
return ids.filter((id) => _unitHash(`${seed} ${id}`) < rate);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Stable [0,1) hash of a string.
|
|
165
|
+
*
|
|
166
|
+
* Reuses `blind_review._sha256_hex` rather than carrying a local one. That
|
|
167
|
+
* export exists for exactly this reason — `blind_review.ts:38-44` records that
|
|
168
|
+
* two hashes of one input are two answers to one question and the second is the
|
|
169
|
+
* one nobody updates. A hand-rolled FNV-1a was tried here first and its low bits
|
|
170
|
+
* were skewed enough that a rate of 0.25 sampled half the corpus; the test that
|
|
171
|
+
* caught it is kept.
|
|
172
|
+
*/
|
|
173
|
+
function _unitHash(s: string): number {
|
|
174
|
+
return parseInt(_sha256_hex(s).slice(0, 8), 16) / 4294967296;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* One report line per judge, for emission BESIDE a verdict.
|
|
179
|
+
*
|
|
180
|
+
* `n/a` rather than a number when nothing was sampled: the step's verify is
|
|
181
|
+
* that the metric is reported, and a report that silently prints nothing for an
|
|
182
|
+
* unrun swap satisfies it only by looking like it ran.
|
|
183
|
+
*/
|
|
184
|
+
export function renderPositionConsistency(rows: readonly JudgeConsistency[]): string {
|
|
185
|
+
if (rows.length === 0) {
|
|
186
|
+
return 'position consistency: no judge sampled — order-swap NOT RUN.';
|
|
187
|
+
}
|
|
188
|
+
const pct = (v: number | null): string => (v === null ? 'n/a' : `${(v * 100).toFixed(0)}%`);
|
|
189
|
+
return rows
|
|
190
|
+
.map(
|
|
191
|
+
(r) =>
|
|
192
|
+
`position consistency · ${r.judge}: ${pct(r.position_consistency)} ` +
|
|
193
|
+
`(${String(r.consistent)}/${String(r.sampled)} pairs survived the swap; ` +
|
|
194
|
+
`first-position rate ${pct(r.first_position_rate)} over ${String(r.decisive_verdicts)} decisive verdicts)`,
|
|
195
|
+
)
|
|
196
|
+
.join('\n');
|
|
197
|
+
}
|
|
@@ -21,10 +21,14 @@
|
|
|
21
21
|
// Failure normalisation (one member's exception → `error`-set
|
|
22
22
|
// CouncilResponse, never raise) is unchanged.
|
|
23
23
|
|
|
24
|
-
import { ConsensusResult
|
|
25
|
-
import
|
|
24
|
+
import type { ConsensusResult } from './orchestrator_results.js';
|
|
25
|
+
import { CouncilQuestion, PeerReviewResult } from './orchestrator_results.js';
|
|
26
|
+
import type { RunPeerReviewOptions } from './orchestrator_results.js';
|
|
26
27
|
export { ConsensusResult, CouncilQuestion, PeerReviewResult } from './orchestrator_results.js';
|
|
27
28
|
export type { RunConsensusScoringOptions, RunPeerReviewOptions } from './orchestrator_results.js';
|
|
29
|
+
// Moved to its own module for the source-size budget; re-exported so every
|
|
30
|
+
// existing importer of `run_consensus_scoring` is untouched.
|
|
31
|
+
export { run_consensus_scoring } from './consensus_round.js';
|
|
28
32
|
import {
|
|
29
33
|
record_spend as _record_daily_spend,
|
|
30
34
|
today_spend_usd as _today_spend_usd,
|
|
@@ -39,16 +43,9 @@ import {
|
|
|
39
43
|
import type {
|
|
40
44
|
ConsensusMetadata,
|
|
41
45
|
Finding} from './consensus.js';
|
|
42
|
-
import {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
aggregate_scores,
|
|
46
|
-
anonymize_findings,
|
|
47
|
-
anonymize_responses,
|
|
48
|
-
bucket_by_threshold,
|
|
49
|
-
parse_findings_outcome,
|
|
50
|
-
parse_scores_response,
|
|
51
|
-
} from './consensus.js';
|
|
46
|
+
import type { ConsensusBucket } from './consensus.js';
|
|
47
|
+
import { anonymize_responses } from './consensus.js';
|
|
48
|
+
import { composeFinalRoundSuffix } from './inline_findings.js';
|
|
52
49
|
import type {
|
|
53
50
|
CostEstimate,
|
|
54
51
|
PriceTable} from './pricing.js';
|
|
@@ -64,9 +61,7 @@ import {
|
|
|
64
61
|
ANTI_CONFORMITY_DIRECTIVE,
|
|
65
62
|
describe_verdict_mismatch,
|
|
66
63
|
STANCE_LINE_CONTRACT,
|
|
67
|
-
build_extraction_user_prompt,
|
|
68
64
|
build_peer_review_user_prompt,
|
|
69
|
-
build_scoring_user_prompt,
|
|
70
65
|
peer_review_synthesis_addendum,
|
|
71
66
|
synthesis_template,
|
|
72
67
|
system_prompt_for,
|
|
@@ -366,6 +361,8 @@ export interface ConsultOptions {
|
|
|
366
361
|
* context). Default `null` → byte-identical to today.
|
|
367
362
|
*/
|
|
368
363
|
no_project_context_members?: ReadonlySet<string> | null;
|
|
364
|
+
/** Phase 1B — `composeFinalRoundSuffix`. Default `false` → prompt unchanged. */
|
|
365
|
+
inline_findings?: boolean;
|
|
369
366
|
/** Mid-flight cli→api fallback; absent → no retry. See `mid_flight_fallback`. */
|
|
370
367
|
cli_fallback?: CliFallbackOptions | null;
|
|
371
368
|
}
|
|
@@ -435,15 +432,13 @@ export function consult(
|
|
|
435
432
|
let current_suffix = '';
|
|
436
433
|
|
|
437
434
|
const stance_tally = opts.stance_tally ?? false;
|
|
435
|
+
const inline_findings = opts.inline_findings ?? false;
|
|
438
436
|
for (let round_idx = 0; round_idx < rounds; round_idx++) {
|
|
439
|
-
//
|
|
440
|
-
//
|
|
441
|
-
//
|
|
437
|
+
// The FINAL round carries the opt-in closing contracts (STANCE line,
|
|
438
|
+
// inline findings). Both off → the question flows through untouched,
|
|
439
|
+
// byte-identical to today. Order lives in the composer.
|
|
442
440
|
const is_final = round_idx === rounds - 1;
|
|
443
|
-
const suffix_for_round =
|
|
444
|
-
is_final && stance_tally
|
|
445
|
-
? `${current_suffix}\n\n---\n\n${STANCE_LINE_CONTRACT}`
|
|
446
|
-
: current_suffix;
|
|
441
|
+
const suffix_for_round = composeFinalRoundSuffix(current_suffix, { is_final, inline_findings, stance_tally });
|
|
447
442
|
const prompt_for_round = `${question.user_prompt}${suffix_for_round}`;
|
|
448
443
|
const round_question =
|
|
449
444
|
round_idx === 0 && prompt_for_round === question.user_prompt
|
|
@@ -1581,188 +1576,6 @@ export function run_peer_review(
|
|
|
1581
1576
|
|
|
1582
1577
|
|
|
1583
1578
|
|
|
1584
|
-
/**
|
|
1585
|
-
* Two-pass consensus round (Phase 4 / F3).
|
|
1586
|
-
*
|
|
1587
|
-
* Pass 1 — extraction: each member re-emits its own deliberation as
|
|
1588
|
-
* a JSON array of `{id, text}` findings. Pass 2 — scoring: each
|
|
1589
|
-
* member sees the *other* members' findings under anonymous labels
|
|
1590
|
-
* and rates them 1-10 + agree/disagree + reason.
|
|
1591
|
-
*
|
|
1592
|
-
* The cost budget is shared across both passes; the daily ledger
|
|
1593
|
-
* receives both. Errors in one member's extraction or scoring tag
|
|
1594
|
-
* that member but never abort the round.
|
|
1595
|
-
*/
|
|
1596
|
-
export function run_consensus_scoring(
|
|
1597
|
-
members: ExternalAIClient[],
|
|
1598
|
-
deliberation_responses: CouncilResponse[],
|
|
1599
|
-
opts: RunConsensusScoringOptions = {},
|
|
1600
|
-
): ConsensusResult {
|
|
1601
|
-
const budget = opts.budget ?? null;
|
|
1602
|
-
const table = opts.table ?? null;
|
|
1603
|
-
const on_overrun = opts.on_overrun ?? null;
|
|
1604
|
-
const project = opts.project ?? null;
|
|
1605
|
-
const original_ask = opts.original_ask ?? '';
|
|
1606
|
-
const max_tokens = opts.max_tokens ?? DEFAULT_MAX_TOKENS;
|
|
1607
|
-
const strong_threshold = opts.strong_threshold ?? 0.7;
|
|
1608
|
-
const minority_threshold = opts.minority_threshold ?? 0.4;
|
|
1609
|
-
|
|
1610
|
-
if (members.length === 0 || deliberation_responses.length === 0) {
|
|
1611
|
-
return new ConsensusResult({
|
|
1612
|
-
bucket: new ConsensusBucket(),
|
|
1613
|
-
findings: [],
|
|
1614
|
-
scores: [],
|
|
1615
|
-
metadata: new Map(),
|
|
1616
|
-
extraction_responses: [],
|
|
1617
|
-
scoring_responses: [],
|
|
1618
|
-
});
|
|
1619
|
-
}
|
|
1620
|
-
|
|
1621
|
-
// ── Pass 1: extraction ──────────────────────────────────────────
|
|
1622
|
-
const member_by_name = new Map<string, ExternalAIClient>();
|
|
1623
|
-
for (const m of members) {
|
|
1624
|
-
member_by_name.set(m.name, m);
|
|
1625
|
-
}
|
|
1626
|
-
const extraction_responses: CouncilResponse[] = [];
|
|
1627
|
-
const all_findings: Finding[] = [];
|
|
1628
|
-
// Per-member extraction outcome — step 2.2. Recorded rather than derived from the
|
|
1629
|
-
// findings count, because "zero findings" and "could not be read" are different facts
|
|
1630
|
-
// and the count cannot tell them apart. `parsed-after-reask` is kept distinct from
|
|
1631
|
-
// `parsed`: a member that needed a second ask is a signal about the prompt or the
|
|
1632
|
-
// member, and collapsing it into `parsed` would hide the only evidence that the
|
|
1633
|
-
// re-ask is doing anything.
|
|
1634
|
-
const parse_outcomes = new Map<string, string>();
|
|
1635
|
-
for (const resp of deliberation_responses) {
|
|
1636
|
-
const member = member_by_name.get(resp.provider);
|
|
1637
|
-
if (member === undefined || resp.error || !_pyStrip(resp.text)) {
|
|
1638
|
-
continue;
|
|
1639
|
-
}
|
|
1640
|
-
const question = new CouncilQuestion({
|
|
1641
|
-
mode: 'prompt',
|
|
1642
|
-
user_prompt: build_extraction_user_prompt(resp.text),
|
|
1643
|
-
max_tokens,
|
|
1644
|
-
});
|
|
1645
|
-
const extracted = consult([member], question, budget, {
|
|
1646
|
-
table,
|
|
1647
|
-
on_overrun,
|
|
1648
|
-
project,
|
|
1649
|
-
original_ask,
|
|
1650
|
-
});
|
|
1651
|
-
extraction_responses.push(...extracted);
|
|
1652
|
-
if (extracted.length === 0 || extracted[0]!.error) {
|
|
1653
|
-
continue;
|
|
1654
|
-
}
|
|
1655
|
-
const source = `${member.name}:${member.model}`;
|
|
1656
|
-
let ex = parse_findings_outcome(extracted[0]!.text, { source });
|
|
1657
|
-
|
|
1658
|
-
// Step 2.2 — ONE bounded re-ask on `parse_failed`, and one only.
|
|
1659
|
-
//
|
|
1660
|
-
// A member that said something no parser could read used to be indistinguishable
|
|
1661
|
-
// from a member that found nothing: `parse_findings_response` returned `[]` for
|
|
1662
|
-
// both, and this loop pushed the empty array with no branch. So an unparseable
|
|
1663
|
-
// answer counted as a clean zero-findings review.
|
|
1664
|
-
//
|
|
1665
|
-
// ONE re-ask, not a loop. A re-ask is a paid call, and an unbounded retry turns
|
|
1666
|
-
// one unparseable answer into open-ended spend — the failure mode the N=3
|
|
1667
|
-
// validation budget exists for, reached here by a different road. `empty` is NOT
|
|
1668
|
-
// re-asked: a member that said nothing has nothing to restate, and re-asking it
|
|
1669
|
-
// buys a second silence.
|
|
1670
|
-
if (ex.outcome === 'parse_failed') {
|
|
1671
|
-
const retry_q = new CouncilQuestion({
|
|
1672
|
-
mode: 'prompt',
|
|
1673
|
-
user_prompt:
|
|
1674
|
-
build_extraction_user_prompt(resp.text) +
|
|
1675
|
-
'\n\nYour previous answer could not be parsed. Reply with ONLY a JSON ' +
|
|
1676
|
-
'array of {"id": string, "text": string} objects, no prose before or ' +
|
|
1677
|
-
'after it. An empty array [] is a valid answer meaning you found nothing.',
|
|
1678
|
-
max_tokens,
|
|
1679
|
-
});
|
|
1680
|
-
const retried = consult([member], retry_q, budget, {
|
|
1681
|
-
table,
|
|
1682
|
-
on_overrun,
|
|
1683
|
-
project,
|
|
1684
|
-
original_ask,
|
|
1685
|
-
});
|
|
1686
|
-
extraction_responses.push(...retried);
|
|
1687
|
-
if (retried.length > 0 && !retried[0]!.error) {
|
|
1688
|
-
ex = parse_findings_outcome(retried[0]!.text, { source });
|
|
1689
|
-
}
|
|
1690
|
-
parse_outcomes.set(source, ex.outcome === 'parsed' ? 'parsed-after-reask' : 'parse_failed');
|
|
1691
|
-
} else {
|
|
1692
|
-
parse_outcomes.set(source, ex.outcome);
|
|
1693
|
-
}
|
|
1694
|
-
all_findings.push(...ex.findings);
|
|
1695
|
-
}
|
|
1696
|
-
|
|
1697
|
-
if (all_findings.length === 0) {
|
|
1698
|
-
return new ConsensusResult({
|
|
1699
|
-
bucket: new ConsensusBucket(),
|
|
1700
|
-
findings: [],
|
|
1701
|
-
scores: [],
|
|
1702
|
-
metadata: new Map(),
|
|
1703
|
-
parse_outcomes,
|
|
1704
|
-
extraction_responses,
|
|
1705
|
-
scoring_responses: [],
|
|
1706
|
-
});
|
|
1707
|
-
}
|
|
1708
|
-
|
|
1709
|
-
// ── Pass 2: scoring (each member rates the OTHERS' findings) ────
|
|
1710
|
-
const scoring_responses: CouncilResponse[] = [];
|
|
1711
|
-
const all_scores: FindingScore[] = [];
|
|
1712
|
-
for (const member of members) {
|
|
1713
|
-
const scorer = `${member.name}:${member.model}`;
|
|
1714
|
-
const others = all_findings.filter((f) => f.source !== scorer);
|
|
1715
|
-
if (others.length === 0) {
|
|
1716
|
-
continue;
|
|
1717
|
-
}
|
|
1718
|
-
const anon = anonymize_findings(others);
|
|
1719
|
-
const label_to_id = new Map<string, string>();
|
|
1720
|
-
const anon_text = new Map<string, string>();
|
|
1721
|
-
for (const [label, f] of anon) {
|
|
1722
|
-
label_to_id.set(label, f.id);
|
|
1723
|
-
anon_text.set(label, f.text);
|
|
1724
|
-
}
|
|
1725
|
-
const question = new CouncilQuestion({
|
|
1726
|
-
mode: 'prompt',
|
|
1727
|
-
user_prompt: build_scoring_user_prompt(anon_text),
|
|
1728
|
-
max_tokens,
|
|
1729
|
-
});
|
|
1730
|
-
const scored = consult([member], question, budget, {
|
|
1731
|
-
table,
|
|
1732
|
-
on_overrun,
|
|
1733
|
-
project,
|
|
1734
|
-
original_ask,
|
|
1735
|
-
});
|
|
1736
|
-
scoring_responses.push(...scored);
|
|
1737
|
-
if (scored.length === 0 || scored[0]!.error) {
|
|
1738
|
-
continue;
|
|
1739
|
-
}
|
|
1740
|
-
for (const s of parse_scores_response(scored[0]!.text, { scorer })) {
|
|
1741
|
-
const real_id = label_to_id.get(s.finding_id);
|
|
1742
|
-
if (real_id === undefined) {
|
|
1743
|
-
continue;
|
|
1744
|
-
}
|
|
1745
|
-
all_scores.push(
|
|
1746
|
-
new FindingScore(real_id, s.scorer, s.score, s.agree, s.reason),
|
|
1747
|
-
);
|
|
1748
|
-
}
|
|
1749
|
-
}
|
|
1750
|
-
|
|
1751
|
-
const metadata = aggregate_scores(all_findings, all_scores);
|
|
1752
|
-
const bucket = bucket_by_threshold(all_findings, metadata, {
|
|
1753
|
-
strong: strong_threshold,
|
|
1754
|
-
minority: minority_threshold,
|
|
1755
|
-
});
|
|
1756
|
-
return new ConsensusResult({
|
|
1757
|
-
bucket,
|
|
1758
|
-
findings: all_findings,
|
|
1759
|
-
scores: all_scores,
|
|
1760
|
-
metadata,
|
|
1761
|
-
parse_outcomes,
|
|
1762
|
-
extraction_responses,
|
|
1763
|
-
scoring_responses,
|
|
1764
|
-
});
|
|
1765
|
-
}
|
|
1766
1579
|
|
|
1767
1580
|
/**
|
|
1768
1581
|
* Format the per-member meta line — tokens, cost (or subscription), latency.
|
|
@@ -25,7 +25,14 @@ import type { ProjectContext } from './project_context.js';
|
|
|
25
25
|
// The alternative was leaving the two options interfaces behind, which would have meant
|
|
26
26
|
// finding 19 lines elsewhere for no design reason.
|
|
27
27
|
import type { OnOverrunCallback } from './orchestrator.js';
|
|
28
|
-
import type {
|
|
28
|
+
import type {
|
|
29
|
+
ConsensusBucket,
|
|
30
|
+
ConsensusMetadata,
|
|
31
|
+
Finding,
|
|
32
|
+
FindingScore,
|
|
33
|
+
FindingsExtraction,
|
|
34
|
+
} from './consensus.js';
|
|
35
|
+
import type { RecordedExtractionOutcome } from './inline_findings.js';
|
|
29
36
|
|
|
30
37
|
/**
|
|
31
38
|
* Bundle returned by `run_peer_review()` (Phase 5 / F1).
|
|
@@ -121,7 +128,7 @@ export class ConsensusResult {
|
|
|
121
128
|
*
|
|
122
129
|
* Additive and optional, so no existing constructor call changes.
|
|
123
130
|
*/
|
|
124
|
-
parse_outcomes: Map<string,
|
|
131
|
+
parse_outcomes: Map<string, RecordedExtractionOutcome>;
|
|
125
132
|
extraction_responses: CouncilResponse[];
|
|
126
133
|
scoring_responses: CouncilResponse[];
|
|
127
134
|
|
|
@@ -130,7 +137,7 @@ export class ConsensusResult {
|
|
|
130
137
|
findings: Finding[];
|
|
131
138
|
scores: FindingScore[];
|
|
132
139
|
metadata: Map<string, ConsensusMetadata>;
|
|
133
|
-
parse_outcomes?: Map<string,
|
|
140
|
+
parse_outcomes?: Map<string, RecordedExtractionOutcome>;
|
|
134
141
|
extraction_responses: CouncilResponse[];
|
|
135
142
|
scoring_responses: CouncilResponse[];
|
|
136
143
|
}) {
|
|
@@ -163,4 +170,17 @@ export interface RunConsensusScoringOptions {
|
|
|
163
170
|
max_tokens?: number;
|
|
164
171
|
strong_threshold?: number;
|
|
165
172
|
minority_threshold?: number;
|
|
173
|
+
/**
|
|
174
|
+
* Phase 1B: findings already harvested from each member's own deliberation
|
|
175
|
+
* reply by `harvest_inline_findings`, keyed `provider:model`. A member with
|
|
176
|
+
* an entry skips the separate extraction call entirely; a member without one
|
|
177
|
+
* takes the shipped extraction path unchanged. Absent → extraction-always,
|
|
178
|
+
* call-for-call identical to today.
|
|
179
|
+
*
|
|
180
|
+
* A pre-computed map rather than a boolean because the harvest must run
|
|
181
|
+
* BEFORE peer review and synthesis read the responses, which is upstream of
|
|
182
|
+
* this function — see `harvest_inline_findings` for why that ordering is
|
|
183
|
+
* load-bearing.
|
|
184
|
+
*/
|
|
185
|
+
inline_extractions?: ReadonlyMap<string, FindingsExtraction> | null;
|
|
166
186
|
}
|
|
@@ -148,6 +148,112 @@ export function estimate_cost(
|
|
|
148
148
|
};
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
+
// ── billable-aware aggregation ─────────────────────────────────────
|
|
152
|
+
//
|
|
153
|
+
// A vendor-official CLI seat (anthropic / openai / gemini) runs under the
|
|
154
|
+
// user's subscription auth and is `billable = false`; the contract states it
|
|
155
|
+
// in as many words (`docs/contracts/ai-council-config.md:173`). Pricing such
|
|
156
|
+
// an answer at API rates and reporting the figure as spend is the defect these
|
|
157
|
+
// two helpers exist to close, found 2026-08-27: `council_cli.ts` ran
|
|
158
|
+
// `estimate_cost` over every non-errored response with no `billable` check, so
|
|
159
|
+
// one run printed `TOTAL: $0.0000` from the pre-run path (which filters) and
|
|
160
|
+
// `actual $0.1055` from the post-run path, two lines apart.
|
|
161
|
+
//
|
|
162
|
+
// Why the coercion below is not paranoia: `_serialise_responses` stringifies
|
|
163
|
+
// every metadata value with `String(v)`, so a persisted artefact carries
|
|
164
|
+
// `"billable": "false"` — and `Boolean("false")` is `true` in JavaScript. A
|
|
165
|
+
// consumer reading the field back with a bare `Boolean()` sees a subscription
|
|
166
|
+
// seat as billable, which is the same wrong answer arrived at from the other
|
|
167
|
+
// direction.
|
|
168
|
+
|
|
169
|
+
/** The subset of a `CouncilResponse` the cost aggregation reads. */
|
|
170
|
+
export interface BillableCostInput {
|
|
171
|
+
provider: string;
|
|
172
|
+
model: string;
|
|
173
|
+
input_tokens: number;
|
|
174
|
+
output_tokens: number;
|
|
175
|
+
error?: string | null;
|
|
176
|
+
metadata?: Record<string, unknown> | null;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Does this response represent money actually spent?
|
|
181
|
+
*
|
|
182
|
+
* ABSENT means billable. A missing flag is not evidence of a free call, and
|
|
183
|
+
* defaulting the other way would let a client that forgot to stamp its
|
|
184
|
+
* transport silently zero its own spend.
|
|
185
|
+
*/
|
|
186
|
+
export function isBillableResponse(r: BillableCostInput): boolean {
|
|
187
|
+
const raw = (r.metadata ?? {})['billable'];
|
|
188
|
+
if (raw === undefined || raw === null) {
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
if (typeof raw === 'boolean') {
|
|
192
|
+
return raw;
|
|
193
|
+
}
|
|
194
|
+
if (typeof raw === 'string') {
|
|
195
|
+
// The persisted form. Only the two literals a `String(v)` round-trip
|
|
196
|
+
// can produce are interpreted; anything else falls through to the
|
|
197
|
+
// conservative default rather than being guessed at.
|
|
198
|
+
const t = raw.trim().toLowerCase();
|
|
199
|
+
if (t === 'false') {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
// Every other type is BILLABLE, not truthiness-of-value. The first draft of
|
|
205
|
+
// this function ended `return Boolean(raw)` while its own comment promised a
|
|
206
|
+
// conservative default, and a council review (2/2) caught the contradiction:
|
|
207
|
+
// `Boolean(0)` and `Boolean([])` are `false`, so a numeric or empty-array
|
|
208
|
+
// value would have zeroed a billable seat's spend. The serialiser should
|
|
209
|
+
// never emit those, which is exactly why guessing at them is wrong.
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Did every answered response come from a non-billable transport?
|
|
215
|
+
*
|
|
216
|
+
* Exported because the CLI's output line needs it and must NOT infer it from a
|
|
217
|
+
* zero total. A council review (2/2) rated that inference the highest-severity
|
|
218
|
+
* finding in the first draft, and the reasoning is concrete: `estimate_cost`
|
|
219
|
+
* returns `0.0` when `lookup` finds no price row, so an unpriced BILLABLE model
|
|
220
|
+
* produces a zero total. So do a billable seat that errored and one that
|
|
221
|
+
* reported zero tokens. All three would have printed "all seats
|
|
222
|
+
* subscription-authed" over real spend.
|
|
223
|
+
*
|
|
224
|
+
* Vacuously false on an empty or all-errored set: with nothing answered there is
|
|
225
|
+
* no transport to make a claim about, and silence is the honest output.
|
|
226
|
+
*/
|
|
227
|
+
export function allSeatsNonBillable(responses: BillableCostInput[]): boolean {
|
|
228
|
+
const answered = responses.filter((r) => !r.error);
|
|
229
|
+
if (answered.length === 0) {
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
return answered.every((r) => !isBillableResponse(r));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Total USD actually spent across a set of responses.
|
|
237
|
+
*
|
|
238
|
+
* Errored responses contribute nothing (no tokens were billed for an answer
|
|
239
|
+
* that never arrived), and non-billable transports contribute nothing (the
|
|
240
|
+
* subscription already paid). What remains is spend.
|
|
241
|
+
*/
|
|
242
|
+
export function sumBillableCost(responses: BillableCostInput[], table: PriceTable): number {
|
|
243
|
+
let total = 0.0;
|
|
244
|
+
for (const r of responses) {
|
|
245
|
+
if (r.error) {
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
if (!isBillableResponse(r)) {
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
const ce = estimate_cost(r.provider, r.model, r.input_tokens, r.output_tokens, table);
|
|
252
|
+
total += ce.input_usd + ce.output_usd;
|
|
253
|
+
}
|
|
254
|
+
return total;
|
|
255
|
+
}
|
|
256
|
+
|
|
151
257
|
// ── prompt-cache repricing ─────────────────────────────────────────
|
|
152
258
|
//
|
|
153
259
|
// Prompt-cache multipliers derived from the base input rate (Anthropic, GA —
|