@event4u/agent-config 14.9.0 → 14.11.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 +384 -0
- package/README.md +1 -1
- package/dist/agent-src/commands/design.md +88 -0
- package/dist/agent-src/commands/project/analyze.md +47 -0
- package/dist/agent-src/commands/review/changes.md +67 -6
- package/dist/agent-src/commands/roadmap/create.md +49 -0
- package/dist/agent-src/commands/roadmap/next.md +27 -11
- package/dist/agent-src/commands/roadmap/process-full.md +14 -0
- package/dist/agent-src/commands/video/from-script.md +60 -3
- package/dist/agent-src/commands/video/stitch.md +14 -0
- package/dist/agent-src/contexts/communication/rules-auto/guidelines-mechanics.md +1 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +154 -2
- package/dist/agent-src/rules/active-remediation.md +3 -3
- package/dist/agent-src/rules/code-provenance.md +2 -2
- package/dist/agent-src/rules/context-hygiene.md +13 -33
- package/dist/agent-src/rules/council-availability.md +2 -2
- package/dist/agent-src/rules/decision-revisit-gate.md +3 -1
- package/dist/agent-src/rules/design-fidelity.md +18 -0
- package/dist/agent-src/rules/design-review-after-ui-write.md +2 -2
- package/dist/agent-src/rules/evaluator-independence.md +56 -44
- package/dist/agent-src/rules/fix-what-you-see.md +9 -1
- package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +1 -1
- package/dist/agent-src/rules/minimal-safe-diff.md +14 -20
- package/dist/agent-src/rules/missing-skill-recovery.md +13 -1
- package/dist/agent-src/rules/playbook-precedence.md +105 -0
- package/dist/agent-src/rules/recurring-criticism.md +3 -1
- package/dist/agent-src/rules/roadmap-progress-sync.md +14 -13
- package/dist/agent-src/rules/scale-discipline.md +24 -0
- package/dist/agent-src/rules/security-sensitive-stop.md +2 -2
- package/dist/agent-src/rules/settings-ask-protocol.md +2 -2
- package/dist/agent-src/rules/ui-audit-gate.md +27 -15
- package/dist/agent-src/rules/untrusted-input-defense.md +2 -2
- package/dist/agent-src/skills/accessibility-auditor/SKILL.md +19 -0
- package/dist/agent-src/skills/adr-create/SKILL.md +7 -0
- package/dist/agent-src/skills/agents-md-thin-root/SKILL.md +33 -0
- package/dist/agent-src/skills/ai-council/references/advanced-modes.md +17 -3
- package/dist/agent-src/skills/ai-council/references/output-and-synthesis.md +31 -0
- package/dist/agent-src/skills/ai-council/references/procedure.md +19 -0
- package/dist/agent-src/skills/alerting-doctrine/SKILL.md +225 -0
- package/dist/agent-src/skills/alerting-doctrine/evals/triggers.json +17 -0
- package/dist/agent-src/skills/async-python-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/authz-review/SKILL.md +0 -1
- package/dist/agent-src/skills/blast-radius-analyzer/SKILL.md +32 -0
- package/dist/agent-src/skills/brand/SKILL.md +3 -0
- package/dist/agent-src/skills/brand-asset-generation/SKILL.md +3 -0
- package/dist/agent-src/skills/brand-audit/SKILL.md +3 -0
- package/dist/agent-src/skills/brand-identity/SKILL.md +3 -0
- package/dist/agent-src/skills/brand-strategy/SKILL.md +3 -0
- package/dist/agent-src/skills/brand-to-tokens/SKILL.md +3 -0
- package/dist/agent-src/skills/check-refs/SKILL.md +3 -0
- package/dist/agent-src/skills/code-refactoring/SKILL.md +1 -1
- package/dist/agent-src/skills/code-review/SKILL.md +11 -0
- package/dist/agent-src/skills/command-routing/SKILL.md +6 -0
- package/dist/agent-src/skills/condense-memory/SKILL.md +4 -1
- package/dist/agent-src/skills/context-authoring/SKILL.md +1 -1
- package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +4 -1
- package/dist/agent-src/skills/copilot-agents-optimization/SKILL.md +10 -0
- package/dist/agent-src/skills/corpus-grounding/SKILL.md +3 -0
- package/dist/agent-src/skills/design-intelligence/SKILL.md +3 -0
- package/dist/agent-src/skills/design-intelligence/data/landing.csv +36 -35
- package/dist/agent-src/skills/design-intelligence/data/stacks/threejs.csv +1 -0
- package/dist/agent-src/skills/design-review/SKILL.md +80 -2
- package/dist/agent-src/skills/design-review/references/verification-automation.md +41 -0
- package/dist/agent-src/skills/design-system-capture/SKILL.md +35 -40
- package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +50 -0
- package/dist/agent-src/skills/design-tokens/SKILL.md +3 -0
- package/dist/agent-src/skills/design-variations/SKILL.md +3 -0
- package/dist/agent-src/skills/developer-like-execution/SKILL.md +3 -0
- package/dist/agent-src/skills/discovery-interview/SKILL.md +1 -1
- package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
- package/dist/agent-src/skills/docx-authoring/SKILL.md +1 -1
- package/dist/agent-src/skills/editorial-calendar/SKILL.md +1 -1
- package/dist/agent-src/skills/estimate-ticket/SKILL.md +3 -0
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +20 -3
- package/dist/agent-src/skills/fe-design/SKILL.md +74 -41
- package/dist/agent-src/skills/fe-design/evals/triggers.json +65 -53
- package/dist/agent-src/skills/fe-design/references/craft-floor.md +52 -0
- package/dist/agent-src/skills/fe-design/references/source-led-port.md +36 -0
- package/dist/agent-src/skills/file-editor/SKILL.md +5 -0
- package/dist/agent-src/skills/finishing-a-development-branch/SKILL.md +2 -2
- package/dist/agent-src/skills/git-workflow/SKILL.md +3 -0
- package/dist/agent-src/skills/github-ci/SKILL.md +1 -1
- package/dist/agent-src/skills/html-deck/SKILL.md +3 -0
- package/dist/agent-src/skills/iconography/SKILL.md +3 -0
- package/dist/agent-src/skills/image-editing/SKILL.md +3 -0
- package/dist/agent-src/skills/image-generation/SKILL.md +3 -0
- package/dist/agent-src/skills/image-provider-routing/SKILL.md +3 -0
- package/dist/agent-src/skills/incident-commander/SKILL.md +10 -0
- package/dist/agent-src/skills/js-library-packaging/SKILL.md +173 -0
- package/dist/agent-src/skills/js-library-packaging/evals/triggers.json +17 -0
- package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +270 -0
- package/dist/agent-src/skills/judge-artifact-completeness/SKILL.md +1 -1
- package/dist/agent-src/skills/judge-injection-defense/SKILL.md +1 -1
- package/dist/agent-src/skills/laravel-migration/SKILL.md +3 -0
- package/dist/agent-src/skills/laravel-validation/SKILL.md +1 -1
- package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +3 -0
- package/dist/agent-src/skills/legal-intake-triage/SKILL.md +1 -1
- package/dist/agent-src/skills/legal-practice-profile/SKILL.md +1 -1
- package/dist/agent-src/skills/lint-skills/SKILL.md +3 -0
- package/dist/agent-src/skills/llm-provider-knowledge/SKILL.md +3 -0
- package/dist/agent-src/skills/logging-monitoring/SKILL.md +234 -51
- package/dist/agent-src/skills/logo-generation/SKILL.md +3 -0
- package/dist/agent-src/skills/md-language-check/SKILL.md +3 -0
- package/dist/agent-src/skills/messaging-architecture/SKILL.md +1 -1
- package/dist/agent-src/skills/migration-architect/SKILL.md +1 -1
- package/dist/agent-src/skills/module-detect-on-the-fly/SKILL.md +1 -1
- package/dist/agent-src/skills/module-management/SKILL.md +1 -1
- package/dist/agent-src/skills/monorepo-workspace/SKILL.md +149 -0
- package/dist/agent-src/skills/monorepo-workspace/evals/triggers.json +17 -0
- package/dist/agent-src/skills/motion-choreographer/SKILL.md +7 -1
- package/dist/agent-src/skills/multi-tenancy/SKILL.md +4 -0
- package/dist/agent-src/skills/onboarding-program/SKILL.md +1 -1
- package/dist/agent-src/skills/operational-readiness/SKILL.md +184 -0
- package/dist/agent-src/skills/operational-readiness/evals/triggers.json +17 -0
- package/dist/agent-src/skills/override-management/SKILL.md +3 -0
- package/dist/agent-src/skills/perf-feedback-craft/SKILL.md +1 -1
- package/dist/agent-src/skills/persona-improvement/SKILL.md +3 -0
- package/dist/agent-src/skills/pest-testing/SKILL.md +3 -0
- package/dist/agent-src/skills/playbook-authoring/SKILL.md +162 -0
- package/dist/agent-src/skills/playwright-testing/SKILL.md +3 -0
- package/dist/agent-src/skills/privacy-review/SKILL.md +3 -0
- package/dist/agent-src/skills/prompt-engineering-image/SKILL.md +3 -0
- package/dist/agent-src/skills/prompt-optimizer/SKILL.md +1 -1
- package/dist/agent-src/skills/quality-tools/SKILL.md +5 -0
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +52 -21
- package/dist/agent-src/skills/readme-reviewer/SKILL.md +3 -0
- package/dist/agent-src/skills/readme-writing/SKILL.md +3 -0
- package/dist/agent-src/skills/readme-writing-package/SKILL.md +3 -0
- package/dist/agent-src/skills/receiving-code-review/SKILL.md +3 -3
- package/dist/agent-src/skills/refine-prompt/SKILL.md +3 -0
- package/dist/agent-src/skills/refine-ticket/SKILL.md +3 -0
- package/dist/agent-src/skills/requesting-code-review/SKILL.md +2 -2
- package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +23 -41
- package/dist/agent-src/skills/roadmap-writing/references/follow-up-roadmap-shape.md +47 -0
- package/dist/agent-src/skills/rtk-output-filtering/SKILL.md +22 -6
- package/dist/agent-src/skills/runway-cognition/SKILL.md +3 -0
- package/dist/agent-src/skills/scene-expander/SKILL.md +1 -1
- package/dist/agent-src/skills/scene-expander/scene-blueprint.schema.yaml +26 -0
- package/dist/agent-src/skills/secrets-management/SKILL.md +5 -1
- package/dist/agent-src/skills/server-hardening/SKILL.md +159 -0
- package/dist/agent-src/skills/server-hardening/evals/triggers.json +17 -0
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +3 -0
- package/dist/agent-src/skills/skill-management/SKILL.md +3 -0
- package/dist/agent-src/skills/skill-reviewer/SKILL.md +3 -0
- package/dist/agent-src/skills/skill-writing/SKILL.md +6 -0
- package/dist/agent-src/skills/spreadsheet-authoring/SKILL.md +3 -0
- package/dist/agent-src/skills/storybook-workshop/SKILL.md +194 -0
- package/dist/agent-src/skills/storybook-workshop/evals/triggers.json +17 -0
- package/dist/agent-src/skills/storybook-workshop/scripts/story_contrast_floor.ts +134 -0
- package/dist/agent-src/skills/subagent-orchestration/SKILL.md +1 -1
- package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +25 -0
- package/dist/agent-src/skills/supply-chain-intake/SKILL.md +12 -0
- package/dist/agent-src/skills/systematic-debugging/SKILL.md +1 -1
- package/dist/agent-src/skills/terraform/SKILL.md +3 -0
- package/dist/agent-src/skills/test-driven-development/SKILL.md +1 -1
- package/dist/agent-src/skills/threat-modeling/SKILL.md +0 -3
- package/dist/agent-src/skills/token-optimizer/SKILL.md +3 -0
- package/dist/agent-src/skills/typography-system/SKILL.md +3 -0
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +9 -1
- package/dist/agent-src/skills/upstream-contribute/SKILL.md +3 -0
- package/dist/agent-src/skills/using-git-worktrees/SKILL.md +1 -1
- package/dist/agent-src/skills/validate-feature-fit/SKILL.md +3 -0
- package/dist/agent-src/skills/verify-completion-evidence/SKILL.md +2 -2
- package/dist/agent-src/skills/wireframe/SKILL.md +3 -0
- package/dist/agent-src/skills/wireframe/references/story-beat-ledger.schema.json +115 -0
- package/dist/agent-src/skills/workspace-link/SKILL.md +131 -0
- package/dist/agent-src/skills/workspace-link/evals/triggers.json +17 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/playbook.md +75 -0
- package/dist/agent-src/templates/roadmaps.md +37 -0
- package/dist/agent-src/templates/scripts/check_playbook_invokes.ts +231 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +24 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.ts +216 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +159 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +73 -4
- package/dist/agent-src/templates/scripts/work_engine/stack/detect.ts +325 -40
- package/dist/cli/commands/uiAudit.js +221 -0
- package/dist/cli/commands/uiAudit.js.map +1 -0
- package/dist/cli/commands/uiRender.js +206 -0
- package/dist/cli/commands/uiRender.js.map +1 -0
- package/dist/cli/main.js +22 -1
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/mcp/content.js +64 -1
- package/dist/cli/mcp/content.js.map +1 -1
- package/dist/cli/mcp/dispatch.js +175 -10
- package/dist/cli/mcp/dispatch.js.map +1 -1
- package/dist/cli/registry.js +3 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/{chunk-H4VIVD4C.js → chunk-236PNQZK.js} +413 -391
- package/dist/cli-delegate/{chunk-G23AT6GD.js → chunk-DMSZHXZS.js} +57 -1
- package/dist/cli-delegate/{chunk-77GR3VD4.js → chunk-FF7WAFMR.js} +58 -3
- package/dist/cli-delegate/{chunk-PLSG6UL5.js → chunk-K4FFODTS.js} +341 -204
- package/dist/cli-delegate/{chunk-YM4GZDJG.js → chunk-L43NCYPB.js} +5 -0
- package/dist/cli-delegate/{chunk-B2ERU2VA.js → chunk-WOKWX5PL.js} +1 -1
- package/dist/cli-delegate/cmd_brand_status.js +8 -6
- package/dist/cli-delegate/cmd_conformance.js +3 -3
- package/dist/cli-delegate/cmd_doctor.js +3 -3
- package/dist/cli-delegate/cmd_export.js +4 -4
- 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 +4 -4
- package/dist/cli-delegate/cmd_session_recycle.js +70 -9
- package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +4 -4
- package/dist/cli-delegate/cmd_uninstall.js +4 -4
- package/dist/cli-delegate/cmd_validate.js +4 -4
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +380 -145
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +4 -4
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +18 -8
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +16 -6
- package/dist/hooks/dispatch.js +2337 -1436
- package/dist/install/install.mjs +795 -708
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +1685 -1250
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/lean_projection_mode.js +40 -0
- package/dist/scripts/_lib/lean_projection_mode.js.map +1 -0
- package/dist/scripts/_lib/scoped_projection.js +84 -0
- package/dist/scripts/_lib/scoped_projection.js.map +1 -1
- package/dist/scripts/_lib/ui_surface.js +89 -0
- package/dist/scripts/_lib/ui_surface.js.map +1 -0
- package/dist/scripts/condense.js +6 -10
- package/dist/scripts/condense.js.map +1 -1
- package/dist/scripts/project_thin_rules.js +40 -2
- package/dist/scripts/project_thin_rules.js.map +1 -1
- package/dist/server/schemas/settings.js +3 -0
- package/dist/server/schemas/settings.js.map +1 -1
- package/dist/shared/skillRanking.js +159 -0
- package/dist/shared/skillRanking.js.map +1 -0
- package/docs/contracts/provider-lifecycle.md +47 -18
- package/docs/contracts/settings-classes.md +14 -4
- package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +49 -0
- package/docs/guidelines/agent-infra/evaluator-independence-mechanics.md +92 -0
- package/docs/guidelines/agent-infra/minimal-safe-diff-mechanics.md +45 -1
- package/docs/guidelines/agent-infra/roadmap-deferred-resolution-provenance.md +54 -0
- package/docs/guidelines/design-antipatterns.md +4 -2
- package/docs/guidelines/design-asset-discipline.md +38 -0
- package/docs/guidelines/design-fidelity-mechanics.md +45 -29
- package/docs/guidelines/design-handover-extraction.md +35 -5
- package/docs/guidelines/design-modes.md +41 -1
- package/docs/guidelines/monorepo-antipatterns.md +141 -0
- package/llms.txt +50 -39
- package/package.json +1 -1
- package/src/agent-src/templates/scripts/check_playbook_invokes.ts +231 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +24 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/review.ts +216 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +159 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +73 -4
- package/src/agent-src/templates/scripts/work_engine/stack/detect.ts +325 -40
- package/src/config/agent-settings.template.yml +28 -0
- package/src/config/assurance-capability-registry.json +223 -0
- package/src/config/assurance-threshold-budget.json +65 -0
- package/src/config/ci-local-parity.yml +14 -0
- package/src/config/discovery/unassigned-artefacts.yml +2 -0
- package/src/config/dispatch-economy-metrics.json +4 -2
- package/src/config/evaluator-budgets.json +14 -14
- package/src/config/gate-coverage.yml +227 -8
- package/src/config/gate-violation-baselines.json +76 -72
- package/src/config/hook-latency-budget.json +1 -0
- package/src/config/hook-token-budget.json +137 -125
- package/src/config/pack-size-budget.json +4 -2
- package/src/config/preamble-payload-budget.json +71 -67
- package/src/config/quorum-attendance-budget.json +12 -4
- package/src/config/rule-activation-census.json +7 -3
- package/src/config/rule-enforcement-baseline.json +0 -1
- package/src/config/rule-stub-ceilings.json +112 -91
- package/src/scripts/_cli/cmd_doctor.ts +15 -16
- package/src/scripts/_cli/doctor_install_mode.ts +49 -0
- package/src/scripts/_cli/doctor_overrides.ts +154 -0
- package/src/scripts/_dispatch.bash +17 -0
- package/src/scripts/_lib/as_of.ts +412 -0
- package/src/scripts/_lib/exec_evidence.ts +7 -0
- package/src/scripts/_lib/hook_settings.ts +33 -0
- package/src/scripts/_lib/host_listing_model.ts +192 -0
- package/src/scripts/_lib/lean_projection_mode.ts +44 -0
- package/src/scripts/_lib/mcp_bridge.ts +199 -0
- package/src/scripts/_lib/review_independence.ts +62 -10
- package/src/scripts/_lib/rule_injection.ts +239 -0
- package/src/scripts/_lib/run_checkpoint.ts +54 -1
- package/src/scripts/_lib/scoped_projection.ts +96 -0
- package/src/scripts/_lib/session_register.ts +44 -2
- package/src/scripts/_lib/skill_catalogue.ts +38 -2
- package/src/scripts/_lib/transcript_reads.ts +207 -0
- package/src/scripts/_lib/ui_authority.test.ts +251 -0
- package/src/scripts/_lib/ui_authority.ts +343 -0
- package/src/scripts/ai-video/adapters/fal.sh +8 -3
- package/src/scripts/ai-video/adapters/gemini-veo.sh +10 -0
- package/src/scripts/ai-video/adapters/higgsfield.sh +10 -2
- package/src/scripts/ai-video/adapters/kling.sh +10 -0
- package/src/scripts/ai-video/adapters/sora.sh +10 -0
- package/src/scripts/ai-video/lib/calibrate-cost.sh +145 -0
- package/src/scripts/ai-video/lib/model-capabilities/README.md +53 -7
- package/src/scripts/ai-video/lib/model-capabilities/comfyui.json +15 -3
- package/src/scripts/ai-video/lib/model-capabilities/fal.json +36 -6
- package/src/scripts/ai-video/lib/model-capabilities/gemini-veo.json +23 -0
- package/src/scripts/ai-video/lib/model-capabilities/higgsfield.json +23 -0
- package/src/scripts/ai-video/lib/model-capabilities/kling.json +23 -0
- package/src/scripts/ai-video/lib/model-capabilities/musetalk.json +8 -2
- package/src/scripts/ai-video/lib/model-capabilities/replicate.json +36 -6
- package/src/scripts/ai-video/lib/model-capabilities/sora.json +45 -0
- package/src/scripts/ai-video/lib/model-capabilities/syncso.json +8 -2
- package/src/scripts/ai-video/lib/parse-blueprint.sh +52 -5
- package/src/scripts/ai-video/lib/resume-scan.sh +92 -3
- package/src/scripts/ai-video/lib/seam-plan.sh +212 -0
- package/src/scripts/ai-video/smoke-trace.sh +450 -2
- package/src/scripts/ai-video/stitch.sh +191 -10
- package/src/scripts/ai-video/test-pipeline.sh +84 -6
- package/src/scripts/ai_council/cli_agency_bounds.ts +139 -0
- package/src/scripts/ai_council/cli_least_agency_canary.ts +347 -0
- package/src/scripts/ai_council/clients.ts +3 -2
- package/src/scripts/ai_council/consensus.ts +63 -6
- package/src/scripts/ai_council/events_log.ts +46 -1
- package/src/scripts/ai_council/orchestrator.ts +103 -108
- package/src/scripts/ai_council/orchestrator_results.ts +166 -0
- package/src/scripts/ai_council/prompts.ts +12 -5
- package/src/scripts/ai_council/quorum.ts +82 -1
- package/src/scripts/ai_council/quorum_wiring.ts +82 -5
- package/src/scripts/ai_council/seating.ts +211 -0
- package/src/scripts/ai_council/stance_tally.ts +22 -0
- package/src/scripts/bench_hook_latency.ts +62 -0
- package/src/scripts/build_proof.ts +12 -1
- package/src/scripts/capture_skill_catalogue.ts +21 -0
- package/src/scripts/check_always_budget.ts +2 -1
- package/src/scripts/check_augmentignore.ts +2 -1
- package/src/scripts/check_beta_review_markers.ts +2 -1
- package/src/scripts/check_composite_arming.ts +364 -0
- package/src/scripts/check_corpus_staleness.ts +2 -1
- package/src/scripts/check_council_pin_staleness.ts +3 -1
- package/src/scripts/check_enforcement_coverage.ts +116 -3
- package/src/scripts/check_enforcement_denominator.ts +365 -0
- package/src/scripts/check_gate_coverage.ts +2 -1
- package/src/scripts/check_hook_bundle_freshness.ts +13 -1
- package/src/scripts/check_knowledge_cards.ts +2 -1
- package/src/scripts/check_knowledge_pages.ts +3 -2
- package/src/scripts/check_memory.ts +2 -1
- package/src/scripts/check_no_automerge_key.ts +287 -0
- package/src/scripts/check_pack_conformance_fixture.ts +565 -0
- package/src/scripts/check_pack_passport_reconciliation.ts +274 -0
- package/src/scripts/check_proposal.ts +2 -1
- package/src/scripts/check_reach_staleness.ts +2 -1
- package/src/scripts/check_release_adjacent_health.ts +2 -1
- package/src/scripts/check_release_pr_shape.ts +5 -0
- package/src/scripts/check_review_schema.ts +34 -1
- package/src/scripts/check_roadmap_trackable.ts +48 -3
- package/src/scripts/check_source_size_budget.ts +2 -1
- package/src/scripts/check_standing_payload_delta.ts +505 -0
- package/src/scripts/check_trigger_evals.ts +2 -1
- package/src/scripts/classify_change_risk.ts +281 -0
- package/src/scripts/compute_skill_tiers.ts +186 -0
- package/src/scripts/condense.ts +8 -13
- package/src/scripts/council_attendance_metrics.ts +183 -0
- package/src/scripts/council_cli.ts +10 -8
- package/src/scripts/council_parse_rate.ts +116 -0
- package/src/scripts/derive_playbooks.ts +406 -0
- package/src/scripts/design_slop_rules.test.ts +7 -0
- package/src/scripts/design_slop_rules.ts +56 -2
- package/src/scripts/dispatch_r2_reviewer.ts +16 -0
- package/src/scripts/frontend_corpus_hash.ts +116 -0
- package/src/scripts/generate_pack_manifests.ts +78 -0
- package/src/scripts/grade_target_readiness.ts +478 -0
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +97 -16
- package/src/scripts/hooks/concern_registry.ts +4 -0
- package/src/scripts/hooks/design_pass_hook.ts +356 -0
- package/src/scripts/hooks/rtk_wrap_hook.ts +30 -7
- package/src/scripts/hooks/rule_inject_hook.ts +318 -0
- package/src/scripts/hot_context_hook.ts +74 -7
- package/src/scripts/install.ts +40 -89
- package/src/scripts/lint_adapter_tier.ts +663 -0
- package/src/scripts/lint_archived_skills.ts +93 -0
- package/src/scripts/lint_budget_ownership.ts +2 -1
- package/src/scripts/lint_deterministic_time.ts +470 -0
- package/src/scripts/lint_framework_leakage.ts +5 -0
- package/src/scripts/lint_handoffs.ts +525 -1
- package/src/scripts/lint_judge_prompt_expectation.ts +155 -0
- package/src/scripts/lint_marketplace.ts +88 -0
- package/src/scripts/lint_media_policy_linkage.ts +140 -1
- package/src/scripts/lint_one_off_age.ts +6 -1
- package/src/scripts/lint_override_kernel_guard.ts +87 -5
- package/src/scripts/lint_roadmap_complexity.ts +56 -0
- package/src/scripts/lint_rule_enforcement_declaration.ts +24 -7
- package/src/scripts/lint_rule_norm_pin.ts +321 -0
- package/src/scripts/lint_spawn_payload.ts +42 -5
- package/src/scripts/lint_symptom_intake.ts +2 -1
- package/src/scripts/mcp_parity_smoke.ts +30 -4
- package/src/scripts/mcp_render.ts +66 -1
- package/src/scripts/mcp_tool_fingerprint.ts +241 -0
- package/src/scripts/measure_risk_class_drift.ts +140 -0
- package/src/scripts/measure_skill_ranker_baseline.ts +212 -0
- package/src/scripts/media/lib/adapter-common.sh +211 -1
- package/src/scripts/media/lib/adapter-contract.md +74 -6
- package/src/scripts/model_rule_injection.ts +907 -0
- package/src/scripts/project_thin_rules.ts +45 -2
- package/src/scripts/release.ts +66 -860
- package/src/scripts/release_drill.ts +59 -3
- package/src/scripts/release_env.ts +298 -0
- package/src/scripts/release_publication.ts +720 -0
- package/src/scripts/roadmap_context.ts +778 -0
- package/src/scripts/schemas/fidelity-measurement-sheet.schema.json +169 -0
- package/src/scripts/schemas/pack.schema.json +62 -4
- package/src/scripts/schemas/rule.schema.json +24 -2
- package/src/scripts/schemas/skill.schema.json +41 -2
- package/src/scripts/schemas/ui-authority.schema.json +114 -0
- package/src/scripts/session_register_hook.ts +29 -3
- package/src/scripts/sessions_cli.ts +67 -3
- package/src/scripts/skill_tools/score_skill_relevance.ts +36 -53
- package/src/scripts/tighten_skill_descriptions.ts +264 -0
- package/src/scripts/token_sink_report.ts +239 -0
- package/src/scripts/trigger_coverage.ts +122 -3
- package/src/scripts/update_counts.ts +7 -3
- package/src/scripts/validate_frontmatter.ts +66 -0
- package/src/server/schemas/settings.ts +5 -0
- package/src/shared/skillRanking.ts +183 -0
|
@@ -21,6 +21,10 @@
|
|
|
21
21
|
// Failure normalisation (one member's exception → `error`-set
|
|
22
22
|
// CouncilResponse, never raise) is unchanged.
|
|
23
23
|
|
|
24
|
+
import { ConsensusResult, CouncilQuestion, PeerReviewResult } from './orchestrator_results.js';
|
|
25
|
+
import type { RunConsensusScoringOptions, RunPeerReviewOptions } from './orchestrator_results.js';
|
|
26
|
+
export { ConsensusResult, CouncilQuestion, PeerReviewResult } from './orchestrator_results.js';
|
|
27
|
+
export type { RunConsensusScoringOptions, RunPeerReviewOptions } from './orchestrator_results.js';
|
|
24
28
|
import {
|
|
25
29
|
record_spend as _record_daily_spend,
|
|
26
30
|
today_spend_usd as _today_spend_usd,
|
|
@@ -42,7 +46,7 @@ import {
|
|
|
42
46
|
anonymize_findings,
|
|
43
47
|
anonymize_responses,
|
|
44
48
|
bucket_by_threshold,
|
|
45
|
-
|
|
49
|
+
parse_findings_outcome,
|
|
46
50
|
parse_scores_response,
|
|
47
51
|
} from './consensus.js';
|
|
48
52
|
import type {
|
|
@@ -119,9 +123,9 @@ import {
|
|
|
119
123
|
_setdefault,
|
|
120
124
|
} from './py_parity.js';
|
|
121
125
|
|
|
122
|
-
import { CHAIRMAN_FIELDS_ADDENDUM, render_deanonymization_block } from './blind_review.js';
|
|
126
|
+
import { CHAIRMAN_FIELDS_ADDENDUM, render_deanonymization_block, deterministic_shuffle_indices } from './blind_review.js';
|
|
123
127
|
import type { AbsentReason } from './transport_resolver.js';
|
|
124
|
-
import { isSoloConcluded, type QuorumResult } from './quorum.js';
|
|
128
|
+
import { formatAttendanceCaveats, isSoloConcluded, type QuorumResult } from './quorum.js';
|
|
125
129
|
import { isEmptyHandoff, type HandoffEnvelope } from './handoff.js';
|
|
126
130
|
|
|
127
131
|
|
|
@@ -150,17 +154,6 @@ function _label(idx: number): string {
|
|
|
150
154
|
|
|
151
155
|
// ── dataclasses ───────────────────────────────────────────────────────
|
|
152
156
|
|
|
153
|
-
export class CouncilQuestion {
|
|
154
|
-
mode: string; // one of: prompt, roadmap, diff, files
|
|
155
|
-
user_prompt: string; // bundled artefact text
|
|
156
|
-
max_tokens: number;
|
|
157
|
-
|
|
158
|
-
constructor(args: { mode: string; user_prompt: string; max_tokens?: number }) {
|
|
159
|
-
this.mode = args.mode;
|
|
160
|
-
this.user_prompt = args.user_prompt;
|
|
161
|
-
this.max_tokens = args.max_tokens ?? DEFAULT_MAX_TOKENS;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
157
|
|
|
165
158
|
// Callback signature: receive event → return True (proceed) or False (skip + tag error).
|
|
166
159
|
export type OnOverrunCallback = (event: OverrunEvent) => boolean;
|
|
@@ -1434,44 +1427,7 @@ export function run_debate(
|
|
|
1434
1427
|
return all_rounds;
|
|
1435
1428
|
}
|
|
1436
1429
|
|
|
1437
|
-
/**
|
|
1438
|
-
* Bundle returned by `run_peer_review()` (Phase 5 / F1).
|
|
1439
|
-
*
|
|
1440
|
-
* `responses` carries the per-reviewer critiques. `label_to_source`
|
|
1441
|
-
* is the anonymisation map captured server-side so the audit-trail
|
|
1442
|
-
* JSON can rehydrate it without leaking provider identity to the
|
|
1443
|
-
* member at prompt time.
|
|
1444
|
-
*
|
|
1445
|
-
* `persona_labels` is the (optional) Phase 6 / Step 3a wiring: when
|
|
1446
|
-
* the deliberation was an advisor-mode run, the source → persona
|
|
1447
|
-
* map flows through to the renderer so peer-review output can render
|
|
1448
|
-
* as `Response A (Contrarian)`. Plain-member runs leave it empty.
|
|
1449
|
-
*/
|
|
1450
|
-
export class PeerReviewResult {
|
|
1451
|
-
responses: CouncilResponse[];
|
|
1452
|
-
label_to_source: Map<string, string>;
|
|
1453
|
-
persona_labels: Map<string, string>;
|
|
1454
1430
|
|
|
1455
|
-
constructor(args: {
|
|
1456
|
-
responses: CouncilResponse[];
|
|
1457
|
-
label_to_source: Map<string, string>;
|
|
1458
|
-
persona_labels: Map<string, string>;
|
|
1459
|
-
}) {
|
|
1460
|
-
this.responses = args.responses;
|
|
1461
|
-
this.label_to_source = args.label_to_source;
|
|
1462
|
-
this.persona_labels = args.persona_labels;
|
|
1463
|
-
}
|
|
1464
|
-
}
|
|
1465
|
-
|
|
1466
|
-
export interface RunPeerReviewOptions {
|
|
1467
|
-
budget?: CostBudget | null;
|
|
1468
|
-
table?: PriceTable | null;
|
|
1469
|
-
on_overrun?: OnOverrunCallback | null;
|
|
1470
|
-
project?: ProjectContext | null;
|
|
1471
|
-
original_ask?: string;
|
|
1472
|
-
max_tokens?: number;
|
|
1473
|
-
persona_labels?: Map<string, string> | null;
|
|
1474
|
-
}
|
|
1475
1431
|
|
|
1476
1432
|
/**
|
|
1477
1433
|
* Karpathy peer-review pass (Phase 5 / F1).
|
|
@@ -1537,12 +1493,23 @@ export function run_peer_review(
|
|
|
1537
1493
|
|
|
1538
1494
|
const persona_labels = new Map<string, string>(opts.persona_labels ?? []);
|
|
1539
1495
|
const review_responses: CouncilResponse[] = [];
|
|
1540
|
-
// ──
|
|
1541
|
-
//
|
|
1542
|
-
//
|
|
1543
|
-
//
|
|
1544
|
-
//
|
|
1545
|
-
|
|
1496
|
+
// ── What is deterministic here, and what is NOT — corrected 2026-08-23 (step 1.3).
|
|
1497
|
+
//
|
|
1498
|
+
// DETERMINISTIC: the iteration order of `by_source`, and therefore the input order
|
|
1499
|
+
// handed to `anonymize_responses`. Two runs over the same config produce the same
|
|
1500
|
+
// per-reviewer mapping.
|
|
1501
|
+
//
|
|
1502
|
+
// NOT deterministic ACROSS REVIEWERS, and this is what the old comment got wrong by
|
|
1503
|
+
// calling it "the deterministic A/B mapping": every reviewer receives a different
|
|
1504
|
+
// self-filtered subset, and `anonymize_responses` restarts its label counter on each
|
|
1505
|
+
// call (`consensus.ts:437`). So `Response-A` denotes a DIFFERENT member for every
|
|
1506
|
+
// reviewer, by construction. A single map cannot express that, and the one that used
|
|
1507
|
+
// to live here was overwritten per reviewer — so the artefact carried the last
|
|
1508
|
+
// reviewer's mapping for every quote in it.
|
|
1509
|
+
//
|
|
1510
|
+
// `by_reviewer` is the authoritative structure. `last_label_to_source` survives only
|
|
1511
|
+
// as the serialised compatibility field (`council_cli.ts:1480`/`:1492`).
|
|
1512
|
+
const label_to_source_by_reviewer = new Map<string, Map<string, string>>();
|
|
1546
1513
|
|
|
1547
1514
|
for (const reviewer of members) {
|
|
1548
1515
|
const scorer = `${reviewer.name}:${reviewer.model}`;
|
|
@@ -1558,13 +1525,31 @@ export function run_peer_review(
|
|
|
1558
1525
|
if (others_pairs.length === 0) {
|
|
1559
1526
|
continue;
|
|
1560
1527
|
}
|
|
1561
|
-
|
|
1528
|
+
// Step 1.5 — SEEDED order, not input order.
|
|
1529
|
+
//
|
|
1530
|
+
// Before this, `others_pairs` reached `anonymize_responses` in `by_source`
|
|
1531
|
+
// iteration order, so which member became `Response-A` was a pure function of
|
|
1532
|
+
// config order: identical across runs AND inferable from position. That is the
|
|
1533
|
+
// leak `blind_review.ts:52-54` already argues against for its own path ("which
|
|
1534
|
+
// pair becomes `Response-A` is not simply input order, so position alone leaks
|
|
1535
|
+
// nothing") — the two paths contradicted each other in code until now.
|
|
1536
|
+
//
|
|
1537
|
+
// Seed = the original ask plus the deliberation bodies. Run-scoped and
|
|
1538
|
+
// REPLAYABLE from the artefact's own contents; never `Math.random`, never
|
|
1539
|
+
// `Date`, because a label order nobody can reproduce makes the de-anonymization
|
|
1540
|
+
// block unverifiable. The reviewer is deliberately NOT in the seed: one shuffle
|
|
1541
|
+
// per run, so a reader comparing two reviewers' critiques of the same member is
|
|
1542
|
+
// comparing the same label.
|
|
1543
|
+
const shuffle_seed = [opts.original_ask ?? '', ...[...by_source.values()].map((r) => r.text)].join('\0');
|
|
1544
|
+
const order = deterministic_shuffle_indices(shuffle_seed, others_pairs.length);
|
|
1545
|
+
const shuffled_pairs = order.map((i) => others_pairs[i]!);
|
|
1546
|
+
const [anon_text, label_to_source] = anonymize_responses(shuffled_pairs, {
|
|
1562
1547
|
persona_labels,
|
|
1563
1548
|
});
|
|
1564
1549
|
if (anon_text.size === 0) {
|
|
1565
1550
|
continue;
|
|
1566
1551
|
}
|
|
1567
|
-
|
|
1552
|
+
label_to_source_by_reviewer.set(scorer, label_to_source);
|
|
1568
1553
|
const question = new CouncilQuestion({
|
|
1569
1554
|
mode: 'prompt',
|
|
1570
1555
|
user_prompt: build_peer_review_user_prompt(anon_text),
|
|
@@ -1579,54 +1564,22 @@ export function run_peer_review(
|
|
|
1579
1564
|
review_responses.push(...reviewed);
|
|
1580
1565
|
}
|
|
1581
1566
|
|
|
1567
|
+
// DERIVED after the loop, never assigned inside it (step 1.2's verify is a grep for
|
|
1568
|
+
// exactly that). The compatibility field is the last reviewer's mapping, and deriving
|
|
1569
|
+
// it here rather than accumulating it makes that explicit: nothing in the loop
|
|
1570
|
+
// pretends to maintain a run-wide map.
|
|
1571
|
+
const reviewer_maps = [...label_to_source_by_reviewer.values()];
|
|
1572
|
+
const flat_compat = reviewer_maps.length === 0 ? new Map<string, string>() : reviewer_maps[reviewer_maps.length - 1]!;
|
|
1573
|
+
|
|
1582
1574
|
return new PeerReviewResult({
|
|
1583
1575
|
responses: review_responses,
|
|
1584
|
-
|
|
1576
|
+
label_to_source_by_reviewer,
|
|
1577
|
+
label_to_source: flat_compat,
|
|
1585
1578
|
persona_labels,
|
|
1586
1579
|
});
|
|
1587
1580
|
}
|
|
1588
1581
|
|
|
1589
|
-
/**
|
|
1590
|
-
* Bundle returned by `run_consensus_scoring()`.
|
|
1591
|
-
*
|
|
1592
|
-
* `bucket` is renderer-ready; `findings`, `scores`, and `metadata`
|
|
1593
|
-
* are kept for audit-trail JSON (council-sessions/*.json).
|
|
1594
|
-
*/
|
|
1595
|
-
export class ConsensusResult {
|
|
1596
|
-
bucket: ConsensusBucket;
|
|
1597
|
-
findings: Finding[];
|
|
1598
|
-
scores: FindingScore[];
|
|
1599
|
-
metadata: Map<string, ConsensusMetadata>;
|
|
1600
|
-
extraction_responses: CouncilResponse[];
|
|
1601
|
-
scoring_responses: CouncilResponse[];
|
|
1602
1582
|
|
|
1603
|
-
constructor(args: {
|
|
1604
|
-
bucket: ConsensusBucket;
|
|
1605
|
-
findings: Finding[];
|
|
1606
|
-
scores: FindingScore[];
|
|
1607
|
-
metadata: Map<string, ConsensusMetadata>;
|
|
1608
|
-
extraction_responses: CouncilResponse[];
|
|
1609
|
-
scoring_responses: CouncilResponse[];
|
|
1610
|
-
}) {
|
|
1611
|
-
this.bucket = args.bucket;
|
|
1612
|
-
this.findings = args.findings;
|
|
1613
|
-
this.scores = args.scores;
|
|
1614
|
-
this.metadata = args.metadata;
|
|
1615
|
-
this.extraction_responses = args.extraction_responses;
|
|
1616
|
-
this.scoring_responses = args.scoring_responses;
|
|
1617
|
-
}
|
|
1618
|
-
}
|
|
1619
|
-
|
|
1620
|
-
export interface RunConsensusScoringOptions {
|
|
1621
|
-
budget?: CostBudget | null;
|
|
1622
|
-
table?: PriceTable | null;
|
|
1623
|
-
on_overrun?: OnOverrunCallback | null;
|
|
1624
|
-
project?: ProjectContext | null;
|
|
1625
|
-
original_ask?: string;
|
|
1626
|
-
max_tokens?: number;
|
|
1627
|
-
strong_threshold?: number;
|
|
1628
|
-
minority_threshold?: number;
|
|
1629
|
-
}
|
|
1630
1583
|
|
|
1631
1584
|
/**
|
|
1632
1585
|
* Two-pass consensus round (Phase 4 / F3).
|
|
@@ -1672,6 +1625,13 @@ export function run_consensus_scoring(
|
|
|
1672
1625
|
}
|
|
1673
1626
|
const extraction_responses: CouncilResponse[] = [];
|
|
1674
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>();
|
|
1675
1635
|
for (const resp of deliberation_responses) {
|
|
1676
1636
|
const member = member_by_name.get(resp.provider);
|
|
1677
1637
|
if (member === undefined || resp.error || !_pyStrip(resp.text)) {
|
|
@@ -1693,9 +1653,45 @@ export function run_consensus_scoring(
|
|
|
1693
1653
|
continue;
|
|
1694
1654
|
}
|
|
1695
1655
|
const source = `${member.name}:${member.model}`;
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
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);
|
|
1699
1695
|
}
|
|
1700
1696
|
|
|
1701
1697
|
if (all_findings.length === 0) {
|
|
@@ -1704,6 +1700,7 @@ export function run_consensus_scoring(
|
|
|
1704
1700
|
findings: [],
|
|
1705
1701
|
scores: [],
|
|
1706
1702
|
metadata: new Map(),
|
|
1703
|
+
parse_outcomes,
|
|
1707
1704
|
extraction_responses,
|
|
1708
1705
|
scoring_responses: [],
|
|
1709
1706
|
});
|
|
@@ -1761,6 +1758,7 @@ export function run_consensus_scoring(
|
|
|
1761
1758
|
findings: all_findings,
|
|
1762
1759
|
scores: all_scores,
|
|
1763
1760
|
metadata,
|
|
1761
|
+
parse_outcomes,
|
|
1764
1762
|
extraction_responses,
|
|
1765
1763
|
scoring_responses,
|
|
1766
1764
|
});
|
|
@@ -2061,11 +2059,8 @@ function _render_quorum_line(q: QuorumResult): string {
|
|
|
2061
2059
|
// so 2-of-4 rendered as plain "concluded" with nothing to stop a reader
|
|
2062
2060
|
// inferring convergence. Same sentence as stdout on purpose — one wording,
|
|
2063
2061
|
// so neither surface can drift into being the softer one again.
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
? ` ⚠️ DEGRADED — ${String(q.total - q.present)} member(s) did not answer; this is not convergence.`
|
|
2067
|
-
: '';
|
|
2068
|
-
return `**Quorum:** ${q.present}/${q.total} present, needed ${q.threshold} — ${verdict}.${solo}${degraded}`;
|
|
2062
|
+
// Wording shared with the stdout mirror; `formatAttendanceCaveats` owns it.
|
|
2063
|
+
return `**Quorum:** ${q.present}/${q.total} present, needed ${q.threshold} — ${verdict}.${solo}${formatAttendanceCaveats(q)}`;
|
|
2069
2064
|
}
|
|
2070
2065
|
|
|
2071
2066
|
/**
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two result bundles `orchestrator.ts` returns — extracted, a PURE MOVE.
|
|
3
|
+
*
|
|
4
|
+
* The reason is arithmetic. `orchestrator.ts` sits ~850 lines above the 1,500-line
|
|
5
|
+
* ceiling, so `check_source_size_budget` refuses ANY net growth in it: Phases 1 and 2 of
|
|
6
|
+
* `road-to-council-evidence-integrity` added 122 lines and the gate said so, correctly.
|
|
7
|
+
* Raising the baseline is what that gate's own message calls a defect rather than a fix.
|
|
8
|
+
*
|
|
9
|
+
* These two classes are the cleanest movable unit in the file: they are data carriers with
|
|
10
|
+
* no logic and no dependency on anything else in the orchestrator, so moving them changes
|
|
11
|
+
* no behaviour. `orchestrator.ts` re-exports both, so every existing import path keeps
|
|
12
|
+
* resolving.
|
|
13
|
+
*
|
|
14
|
+
* Extracting a data carrier rather than shaving the new documentation was the choice: the
|
|
15
|
+
* alternative was compressing comments that explain WHY a per-reviewer map exists and why
|
|
16
|
+
* the re-ask is bounded at one, which buys the same green from worse code.
|
|
17
|
+
*/
|
|
18
|
+
import type { CouncilResponse } from './clients.js';
|
|
19
|
+
import { DEFAULT_MAX_TOKENS } from './clients.js';
|
|
20
|
+
import type { CostBudget } from './spend_gate.js';
|
|
21
|
+
import type { PriceTable } from './pricing.js';
|
|
22
|
+
import type { ProjectContext } from './project_context.js';
|
|
23
|
+
// TYPE-ONLY back-import. `OnOverrunCallback` is declared in orchestrator.ts, which also
|
|
24
|
+
// imports types from here — legal and runtime-free, because both directions are erased.
|
|
25
|
+
// The alternative was leaving the two options interfaces behind, which would have meant
|
|
26
|
+
// finding 19 lines elsewhere for no design reason.
|
|
27
|
+
import type { OnOverrunCallback } from './orchestrator.js';
|
|
28
|
+
import type { ConsensusBucket, ConsensusMetadata, Finding, FindingScore } from './consensus.js';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Bundle returned by `run_peer_review()` (Phase 5 / F1).
|
|
32
|
+
*
|
|
33
|
+
* `responses` carries the per-reviewer critiques. `label_to_source`
|
|
34
|
+
* is the anonymisation map captured server-side so the audit-trail
|
|
35
|
+
* JSON can rehydrate it without leaking provider identity to the
|
|
36
|
+
* member at prompt time.
|
|
37
|
+
*
|
|
38
|
+
* `persona_labels` is the (optional) Phase 6 / Step 3a wiring: when
|
|
39
|
+
* the deliberation was an advisor-mode run, the source → persona
|
|
40
|
+
* map flows through to the renderer so peer-review output can render
|
|
41
|
+
* as `Response A (Contrarian)`. Plain-member runs leave it empty.
|
|
42
|
+
*/
|
|
43
|
+
/**
|
|
44
|
+
* One question put to the council. Moved here with the result bundles: it is the same
|
|
45
|
+
* kind of thing — a data carrier with no logic — and `orchestrator.ts` re-exports it, so
|
|
46
|
+
* every import path is unchanged.
|
|
47
|
+
*/
|
|
48
|
+
export class CouncilQuestion {
|
|
49
|
+
mode: string; // one of: prompt, roadmap, diff, files
|
|
50
|
+
user_prompt: string; // bundled artefact text
|
|
51
|
+
max_tokens: number;
|
|
52
|
+
|
|
53
|
+
constructor(args: { mode: string; user_prompt: string; max_tokens?: number }) {
|
|
54
|
+
this.mode = args.mode;
|
|
55
|
+
this.user_prompt = args.user_prompt;
|
|
56
|
+
this.max_tokens = args.max_tokens ?? DEFAULT_MAX_TOKENS;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export class PeerReviewResult {
|
|
61
|
+
responses: CouncilResponse[];
|
|
62
|
+
/**
|
|
63
|
+
* PER-REVIEWER label→source attribution — the authoritative mapping.
|
|
64
|
+
*
|
|
65
|
+
* Keyed by `provider:model`, because that is the identity `by_source` uses and the
|
|
66
|
+
* identity a quote in the artefact has to resolve against. Added by step 1.2 of
|
|
67
|
+
* `road-to-council-evidence-integrity`: each reviewer sees a DIFFERENT
|
|
68
|
+
* self-filtered subset, and `anonymize_responses` restarts its label counter per
|
|
69
|
+
* call, so `Response-A` means a different member for every reviewer. One map
|
|
70
|
+
* cannot express that.
|
|
71
|
+
*/
|
|
72
|
+
label_to_source_by_reviewer: Map<string, Map<string, string>>;
|
|
73
|
+
/**
|
|
74
|
+
* Flat compatibility view — the LAST reviewer's mapping, kept only because
|
|
75
|
+
* `council_cli.ts:1480` serialises this field and `:1492` reads it back.
|
|
76
|
+
*
|
|
77
|
+
* It is wrong for any reviewer but the last, and it is retained rather than
|
|
78
|
+
* removed so the serialisation contract does not break in the same change that
|
|
79
|
+
* fixes the attribution. Read `label_to_source_by_reviewer` for anything that
|
|
80
|
+
* resolves a quote.
|
|
81
|
+
*/
|
|
82
|
+
label_to_source: Map<string, string>;
|
|
83
|
+
persona_labels: Map<string, string>;
|
|
84
|
+
|
|
85
|
+
constructor(args: {
|
|
86
|
+
responses: CouncilResponse[];
|
|
87
|
+
label_to_source_by_reviewer?: Map<string, Map<string, string>>;
|
|
88
|
+
label_to_source: Map<string, string>;
|
|
89
|
+
persona_labels: Map<string, string>;
|
|
90
|
+
}) {
|
|
91
|
+
this.responses = args.responses;
|
|
92
|
+
this.label_to_source_by_reviewer = args.label_to_source_by_reviewer ?? new Map();
|
|
93
|
+
this.label_to_source = args.label_to_source;
|
|
94
|
+
this.persona_labels = args.persona_labels;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Bundle returned by `run_consensus_scoring()`.
|
|
100
|
+
*
|
|
101
|
+
* `bucket` is renderer-ready; `findings`, `scores`, and `metadata`
|
|
102
|
+
* are kept for audit-trail JSON (council-sessions/*.json).
|
|
103
|
+
*/
|
|
104
|
+
export class ConsensusResult {
|
|
105
|
+
bucket: ConsensusBucket;
|
|
106
|
+
findings: Finding[];
|
|
107
|
+
scores: FindingScore[];
|
|
108
|
+
metadata: Map<string, ConsensusMetadata>;
|
|
109
|
+
/**
|
|
110
|
+
* Per-member extraction outcome, keyed by `provider:model` — step 2.2 of
|
|
111
|
+
* `road-to-council-evidence-integrity`.
|
|
112
|
+
*
|
|
113
|
+
* `parsed` · `parsed-after-reask` · `empty` · `parse_failed`. Recorded rather than
|
|
114
|
+
* derived from the findings count, because "found nothing" and "could not be read"
|
|
115
|
+
* are different facts and a count cannot tell them apart — which is exactly how an
|
|
116
|
+
* unparseable answer used to read as a clean zero-findings review.
|
|
117
|
+
*
|
|
118
|
+
* `parsed-after-reask` is deliberately distinct from `parsed`: a member needing a
|
|
119
|
+
* second ask is a signal about the prompt or the member, and folding it into `parsed`
|
|
120
|
+
* would hide the only evidence that the re-ask does anything.
|
|
121
|
+
*
|
|
122
|
+
* Additive and optional, so no existing constructor call changes.
|
|
123
|
+
*/
|
|
124
|
+
parse_outcomes: Map<string, string>;
|
|
125
|
+
extraction_responses: CouncilResponse[];
|
|
126
|
+
scoring_responses: CouncilResponse[];
|
|
127
|
+
|
|
128
|
+
constructor(args: {
|
|
129
|
+
bucket: ConsensusBucket;
|
|
130
|
+
findings: Finding[];
|
|
131
|
+
scores: FindingScore[];
|
|
132
|
+
metadata: Map<string, ConsensusMetadata>;
|
|
133
|
+
parse_outcomes?: Map<string, string>;
|
|
134
|
+
extraction_responses: CouncilResponse[];
|
|
135
|
+
scoring_responses: CouncilResponse[];
|
|
136
|
+
}) {
|
|
137
|
+
this.bucket = args.bucket;
|
|
138
|
+
this.findings = args.findings;
|
|
139
|
+
this.scores = args.scores;
|
|
140
|
+
this.metadata = args.metadata;
|
|
141
|
+
this.parse_outcomes = args.parse_outcomes ?? new Map();
|
|
142
|
+
this.extraction_responses = args.extraction_responses;
|
|
143
|
+
this.scoring_responses = args.scoring_responses;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export interface RunPeerReviewOptions {
|
|
148
|
+
budget?: CostBudget | null;
|
|
149
|
+
table?: PriceTable | null;
|
|
150
|
+
on_overrun?: OnOverrunCallback | null;
|
|
151
|
+
project?: ProjectContext | null;
|
|
152
|
+
original_ask?: string;
|
|
153
|
+
max_tokens?: number;
|
|
154
|
+
persona_labels?: Map<string, string> | null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export interface RunConsensusScoringOptions {
|
|
158
|
+
budget?: CostBudget | null;
|
|
159
|
+
table?: PriceTable | null;
|
|
160
|
+
on_overrun?: OnOverrunCallback | null;
|
|
161
|
+
project?: ProjectContext | null;
|
|
162
|
+
original_ask?: string;
|
|
163
|
+
max_tokens?: number;
|
|
164
|
+
strong_threshold?: number;
|
|
165
|
+
minority_threshold?: number;
|
|
166
|
+
}
|
|
@@ -120,9 +120,11 @@ MUST:
|
|
|
120
120
|
suggestion. No hand-wave "this is probably slow".
|
|
121
121
|
3. State at least one suggestion you explicitly REJECT as
|
|
122
122
|
low-leverage, so the user does not over-engineer.
|
|
123
|
-
4. Mark at least one suggestion
|
|
124
|
-
before committing)
|
|
125
|
-
evidence
|
|
123
|
+
4. Mark at least one suggestion \`evidence: speculative\` (requires
|
|
124
|
+
measurement before committing) against at least one marked
|
|
125
|
+
\`evidence: confirmed\` (already supported by the artefact). Use the
|
|
126
|
+
same three-term scale as every other lens — \`confirmed\` |
|
|
127
|
+
\`inferred\` | \`speculative\` — never a lens-local synonym.`;
|
|
126
128
|
|
|
127
129
|
export const ANALYSIS_MODE = `The artefact is a local analysis output (from a project analyzer,
|
|
128
130
|
audit script, or codebase scan). Critique the **analysis itself**, not
|
|
@@ -315,8 +317,13 @@ metadata shape as Top-10.
|
|
|
315
317
|
|
|
316
318
|
### Outliers
|
|
317
319
|
Single-reviewer findings the others did not engage with. Keep them
|
|
318
|
-
— they are signal for a future deeper analysis pass —
|
|
319
|
-
as \`
|
|
320
|
+
— they are signal for a future deeper analysis pass — and give each
|
|
321
|
+
the SAME metadata shape as Top-10, including its \`evidence:\` term.
|
|
322
|
+
The heading is the corroboration statement: everything under it was
|
|
323
|
+
raised by one reviewer and engaged with by none. Do not invent a
|
|
324
|
+
separate certainty word for that; \`evidence:\` measures how well a
|
|
325
|
+
finding is supported, and being alone in raising it is a different
|
|
326
|
+
property the section already carries.
|
|
320
327
|
|
|
321
328
|
### Kill criteria
|
|
322
329
|
Observable conditions that would falsify the analysis's leading finding
|
|
@@ -37,6 +37,23 @@ export interface QuorumResult {
|
|
|
37
37
|
readonly total: number;
|
|
38
38
|
/** Members that actually produced a usable response. */
|
|
39
39
|
readonly present: number;
|
|
40
|
+
/**
|
|
41
|
+
* Members that answered with something no parser could read.
|
|
42
|
+
*
|
|
43
|
+
* Deliberately OPTIONAL and omitted when zero, never defaulted to `0`. Every
|
|
44
|
+
* assertion over a `QuorumResult` in this tree is an exact-shape `toEqual`,
|
|
45
|
+
* and the field also rides into `payload['quorum']`, so a defaulted key would
|
|
46
|
+
* be a silent breaking change to a serialized surface for the overwhelmingly
|
|
47
|
+
* common case where nothing was unparseable.
|
|
48
|
+
*
|
|
49
|
+
* Such a member is NOT in `present`: the byte check that admits it
|
|
50
|
+
* (`text.trim() !== ''`) is true of a prose refusal, which is exactly the
|
|
51
|
+
* "looked more settled than the run was" shape the empty-body fix already
|
|
52
|
+
* closed one case of. It is not plainly absent either — it answered, and the
|
|
53
|
+
* distinction is what a reader needs to tell "found nothing" from
|
|
54
|
+
* "said something unreadable".
|
|
55
|
+
*/
|
|
56
|
+
readonly unparsed?: number;
|
|
40
57
|
}
|
|
41
58
|
|
|
42
59
|
/**
|
|
@@ -76,11 +93,75 @@ export function evaluateQuorum(
|
|
|
76
93
|
total: number,
|
|
77
94
|
present: number,
|
|
78
95
|
setting: QuorumSetting = 'majority',
|
|
96
|
+
unparsed = 0,
|
|
79
97
|
): QuorumResult {
|
|
80
98
|
const threshold = resolveQuorumThreshold(total, setting);
|
|
81
99
|
const clampedPresent = Math.min(Math.max(present, 0), total);
|
|
82
100
|
const status: QuorumStatus = clampedPresent >= threshold ? 'concluded' : 'inconclusive';
|
|
83
|
-
|
|
101
|
+
const clampedUnparsed = Math.min(Math.max(unparsed, 0), total - clampedPresent);
|
|
102
|
+
// Spread-on-condition rather than a defaulted key — see `QuorumResult.unparsed`.
|
|
103
|
+
return { status, threshold, total, present: clampedPresent, ...(clampedUnparsed > 0 ? { unparsed: clampedUnparsed } : {}) };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Move `n` members out of `present` and into the unparsed bucket.
|
|
108
|
+
*
|
|
109
|
+
* The run path derives findings-parse outcomes only AFTER `_postRunQuorum` has
|
|
110
|
+
* emitted the post-run attendance event, and that ordering is deliberate: the
|
|
111
|
+
* event is a TRANSPORT-level reading and stays one, so a consumer computing an
|
|
112
|
+
* attendance rate over the log keeps the denominator it has always had. The
|
|
113
|
+
* rendered artefact is where AC-2 asks for the distinction, and this is how it
|
|
114
|
+
* gets there — the same reading, re-derived once the parser has spoken.
|
|
115
|
+
*
|
|
116
|
+
* `threshold` is not recomputed: it resolves from `total` and the configured
|
|
117
|
+
* setting, neither of which this function touches. `status` IS recomputed,
|
|
118
|
+
* because moving a member out of `present` can legitimately turn a concluded
|
|
119
|
+
* pass inconclusive — which is the whole point, and the same consequence the
|
|
120
|
+
* empty-body fix already accepted.
|
|
121
|
+
*/
|
|
122
|
+
export function withUnparsed(q: QuorumResult, unparsed: number): QuorumResult {
|
|
123
|
+
if (unparsed <= 0) {
|
|
124
|
+
return q;
|
|
125
|
+
}
|
|
126
|
+
const present = Math.max(0, q.present - unparsed);
|
|
127
|
+
const moved = q.present - present;
|
|
128
|
+
return {
|
|
129
|
+
status: present >= q.threshold ? 'concluded' : 'inconclusive',
|
|
130
|
+
threshold: q.threshold,
|
|
131
|
+
total: q.total,
|
|
132
|
+
present,
|
|
133
|
+
...(moved > 0 ? { unparsed: moved } : {}),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* The attendance caveats both banners append — ONE wording, one place.
|
|
139
|
+
*
|
|
140
|
+
* `orchestrator.ts::_render_quorum_line` and `quorum_wiring.ts::_format_quorum_line`
|
|
141
|
+
* are deliberate mirrors, and the DEGRADED sentence carries a note explaining
|
|
142
|
+
* that they must stay byte-identical "so neither surface can drift into being
|
|
143
|
+
* the softer one again". Two copies of a sentence with that requirement is a
|
|
144
|
+
* drift waiting to happen, so Step 2.3 extracted it here rather than adding a
|
|
145
|
+
* third clause to each copy by hand.
|
|
146
|
+
*
|
|
147
|
+
* Two caveats, and they are disjoint on purpose:
|
|
148
|
+
*
|
|
149
|
+
* - `did not answer` counts only the SILENT members. An unparsed member
|
|
150
|
+
* answered, so counting it here would make the line contradict itself — the
|
|
151
|
+
* exact "says something the run did not establish" failure this roadmap is
|
|
152
|
+
* about, in the sentence written to prevent it.
|
|
153
|
+
* - `present-unparsed` counts the members whose answer no parser could read.
|
|
154
|
+
*/
|
|
155
|
+
export function formatAttendanceCaveats(q: QuorumResult): string {
|
|
156
|
+
const unparsed = q.unparsed ?? 0;
|
|
157
|
+
const silent = q.total - q.present - unparsed;
|
|
158
|
+
const degraded =
|
|
159
|
+
silent > 0 ? ` ⚠️ DEGRADED — ${String(silent)} member(s) did not answer; this is not convergence.` : '';
|
|
160
|
+
const unreadable =
|
|
161
|
+
unparsed > 0
|
|
162
|
+
? ` ⚠️ ${String(unparsed)} present-unparsed — answered, and no parser could read it; not counted toward attendance.`
|
|
163
|
+
: '';
|
|
164
|
+
return `${degraded}${unreadable}`;
|
|
84
165
|
}
|
|
85
166
|
|
|
86
167
|
/**
|