@event4u/agent-config 16.3.0 → 16.5.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 +178 -78
- package/README.md +2 -2
- package/agents/templates/.ai-council.yml.example +26 -8
- package/dist/agent-src/commands/analyze/inbox.md +10 -7
- package/dist/agent-src/commands/bug/investigate.md +1 -1
- package/dist/agent-src/commands/commit/in-chunks.md +40 -31
- package/dist/agent-src/commands/commit.md +72 -33
- package/dist/agent-src/commands/condense.md +2 -8
- package/dist/agent-src/commands/council/debate.md +11 -7
- package/dist/agent-src/commands/council/default.md +10 -9
- package/dist/agent-src/commands/council.md +1 -1
- package/dist/agent-src/commands/design.md +1 -1
- package/dist/agent-src/commands/estimate-ticket.md +1 -1
- package/dist/agent-src/commands/feature/explore.md +3 -3
- package/dist/agent-src/commands/feature/plan.md +1 -1
- package/dist/agent-src/commands/fix/ci.md +17 -3
- package/dist/agent-src/commands/fix/commit-messages.md +48 -23
- package/dist/agent-src/commands/fix/pr-comments.md +3 -6
- package/dist/agent-src/commands/implement-ticket.md +3 -3
- package/dist/agent-src/commands/memory/add.md +4 -16
- package/dist/agent-src/commands/memory/load.md +5 -6
- package/dist/agent-src/commands/memory/promote.md +3 -16
- package/dist/agent-src/commands/mission/upgrade.md +3 -2
- package/dist/agent-src/commands/optimize/agents-dir.md +2 -2
- package/dist/agent-src/commands/optimize/deep.md +4 -2
- package/dist/agent-src/commands/optimize/rtk.md +4 -26
- package/dist/agent-src/commands/pr/create/description-only.md +18 -15
- package/dist/agent-src/commands/pr/create.md +42 -34
- package/dist/agent-src/commands/pr/merge.md +136 -9
- package/dist/agent-src/commands/prepare-for-review.md +13 -11
- package/dist/agent-src/commands/project/analyze.md +7 -35
- package/dist/agent-src/commands/refine-ticket.md +1 -1
- package/dist/agent-src/commands/review/changes.md +14 -19
- package/dist/agent-src/commands/roadmap/next.md +10 -1
- package/dist/agent-src/commands/roadmap/process-full.md +52 -38
- package/dist/agent-src/commands/roadmap/resolve-blockers.md +64 -14
- package/dist/agent-src/commands/worktree/create.md +7 -3
- package/dist/agent-src/commands/worktree/verify.md +2 -1
- package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +5 -3
- package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +7 -9
- package/dist/agent-src/contexts/contracts/command-suggestion-flow.md +8 -6
- package/dist/agent-src/contexts/contracts/frugality-charter.md +8 -5
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +1 -1
- package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +0 -1
- package/dist/agent-src/contexts/execution/evidence-discipline.md +2 -2
- package/dist/agent-src/contexts/execution/non-interactive-contract.md +5 -8
- package/dist/agent-src/contexts/execution/rdp-gate.md +4 -4
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +9 -8
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +67 -52
- package/dist/agent-src/contexts/execution/subagent-routing.md +8 -8
- package/dist/agent-src/contexts/execution/subagent-steering.md +6 -4
- package/dist/agent-src/contexts/execution/terminal-states.md +2 -2
- package/dist/agent-src/contexts/execution/toolchain-resolver.md +4 -10
- package/dist/agent-src/contexts/subagent-configuration.md +1 -1
- package/dist/agent-src/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
- package/dist/agent-src/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
- package/dist/agent-src/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
- package/dist/agent-src/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
- package/dist/agent-src/guidelines/agent-infra/layered-settings.md +13 -1
- package/dist/agent-src/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
- package/dist/agent-src/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
- package/dist/agent-src/guidelines/agent-infra/size-and-scope.md +36 -0
- package/dist/agent-src/guidelines/design-antipatterns.md +1 -1
- package/dist/agent-src/guidelines/php/git.md +15 -2
- package/dist/agent-src/rules/active-remediation.md +0 -1
- package/dist/agent-src/rules/analysis-skill-routing.md +0 -1
- package/dist/agent-src/rules/architecture.md +0 -1
- package/dist/agent-src/rules/artifact-drafting-protocol.md +0 -1
- package/dist/agent-src/rules/artifact-engagement-recording.md +0 -1
- package/dist/agent-src/rules/augment-edit-discipline.md +0 -1
- package/dist/agent-src/rules/autonomous-execution.md +0 -1
- package/dist/agent-src/rules/brand-consistency.md +0 -1
- package/dist/agent-src/rules/brand-source-of-truth.md +0 -1
- package/dist/agent-src/rules/broken-access-control.md +0 -1
- package/dist/agent-src/rules/cli-output-handling.md +0 -1
- package/dist/agent-src/rules/code-comment-discipline.md +0 -1
- package/dist/agent-src/rules/code-provenance.md +0 -1
- package/dist/agent-src/rules/command-suggestion-policy.md +0 -1
- package/dist/agent-src/rules/commit-conventions.md +1 -2
- package/dist/agent-src/rules/communication-through-line.md +1 -2
- package/dist/agent-src/rules/content-quoting-floor.md +1 -2
- package/dist/agent-src/rules/context-hygiene.md +5 -5
- package/dist/agent-src/rules/copilot-routing.md +1 -2
- package/dist/agent-src/rules/council-availability.md +4 -4
- package/dist/agent-src/rules/cross-source-consistency.md +4 -6
- package/dist/agent-src/rules/decision-revisit-gate.md +2 -3
- package/dist/agent-src/rules/delegation-policy.md +2 -3
- package/dist/agent-src/rules/design-fidelity.md +0 -1
- package/dist/agent-src/rules/design-review-after-ui-write.md +3 -3
- package/dist/agent-src/rules/devcontainer-routing.md +1 -2
- package/dist/agent-src/rules/doc-screenshot-hygiene.md +0 -1
- package/dist/agent-src/rules/docker-commands.md +0 -1
- package/dist/agent-src/rules/domain-adoption-policy.md +0 -1
- package/dist/agent-src/rules/domain-safety-disclaimer.md +0 -1
- package/dist/agent-src/rules/domain-safety-pii.md +0 -1
- package/dist/agent-src/rules/domain-safety-retention.md +0 -1
- package/dist/agent-src/rules/downstream-changes.md +0 -1
- package/dist/agent-src/rules/engineering-safety-floor.md +0 -1
- package/dist/agent-src/rules/external-code-graph-interop.md +0 -1
- package/dist/agent-src/rules/external-reference-deep-dive.md +0 -1
- package/dist/agent-src/rules/fast-path-marker-visibility.md +1 -2
- package/dist/agent-src/rules/finance-safety-floor.md +0 -1
- package/dist/agent-src/rules/fix-what-you-see.md +6 -32
- package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +0 -1
- package/dist/agent-src/rules/git-history-discipline.md +1 -2
- package/dist/agent-src/rules/guidelines.md +0 -1
- package/dist/agent-src/rules/history-discipline.md +0 -1
- package/dist/agent-src/rules/icon-consistency.md +0 -1
- package/dist/agent-src/rules/image-likeness-and-rights.md +0 -1
- package/dist/agent-src/rules/improve-before-implement.md +0 -1
- package/dist/agent-src/rules/invite-challenge.md +0 -1
- package/dist/agent-src/rules/laravel-routing.md +1 -2
- package/dist/agent-src/rules/laravel-translations.md +0 -1
- package/dist/agent-src/rules/legal-safety-floor.md +0 -1
- package/dist/agent-src/rules/lethal-trifecta-guard.md +0 -1
- package/dist/agent-src/rules/linked-projects-onboarding-gate.md +0 -1
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +0 -1
- package/dist/agent-src/rules/markdown-safe-codeblocks.md +0 -1
- package/dist/agent-src/rules/media-governance-routing.md +1 -2
- package/dist/agent-src/rules/media-sync-ground-truth.md +0 -1
- package/dist/agent-src/rules/minimal-safe-diff.md +0 -1
- package/dist/agent-src/rules/missing-skill-recovery.md +0 -1
- package/dist/agent-src/rules/missing-tool-handling.md +0 -1
- package/dist/agent-src/rules/model-recommendation.md +0 -1
- package/dist/agent-src/rules/neighbour-precedence.md +64 -0
- package/dist/agent-src/rules/no-attribution-footers.md +0 -1
- package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +0 -1
- package/dist/agent-src/rules/no-pr-progress-comments.md +0 -1
- package/dist/agent-src/rules/no-roadmap-references.md +0 -1
- package/dist/agent-src/rules/notes-first-reasoning.md +0 -1
- package/dist/agent-src/rules/onboarding-gate.md +0 -1
- package/dist/agent-src/rules/output-discipline.md +0 -1
- package/dist/agent-src/rules/package-ci-checks.md +0 -1
- package/dist/agent-src/rules/persona-governance.md +2 -3
- package/dist/agent-src/rules/php-coding.md +0 -1
- package/dist/agent-src/rules/prefer-enums-over-literals.md +0 -1
- package/dist/agent-src/rules/preservation-guard.md +0 -1
- package/dist/agent-src/rules/provider-lifecycle-discipline.md +2 -3
- package/dist/agent-src/rules/question-not-instruction.md +0 -1
- package/dist/agent-src/rules/reviewer-awareness.md +0 -1
- package/dist/agent-src/rules/roadmap-ci-steps-policy.md +0 -1
- package/dist/agent-src/rules/roadmap-progress-sync.md +3 -6
- package/dist/agent-src/rules/role-mode-adherence.md +0 -1
- package/dist/agent-src/rules/rule-type-governance.md +0 -1
- package/dist/agent-src/rules/runtime-safety.md +0 -1
- package/dist/agent-src/rules/scale-discipline.md +0 -1
- package/dist/agent-src/rules/secret-vcs-guard.md +0 -1
- package/dist/agent-src/rules/security-sensitive-stop.md +0 -1
- package/dist/agent-src/rules/self-repair-loop.md +0 -1
- package/dist/agent-src/rules/senior-engineering-discipline.md +0 -1
- package/dist/agent-src/rules/session-canary.md +0 -1
- package/dist/agent-src/rules/settings-ask-protocol.md +5 -6
- package/dist/agent-src/rules/size-enforcement.md +0 -1
- package/dist/agent-src/rules/skill-improvement-trigger.md +2 -3
- package/dist/agent-src/rules/skill-quality.md +0 -1
- package/dist/agent-src/rules/slash-command-routing-policy.md +0 -1
- package/dist/agent-src/rules/source-confidentiality.md +0 -1
- package/dist/agent-src/rules/source-discovery-gate.md +0 -1
- package/dist/agent-src/rules/source-of-truth.md +0 -1
- package/dist/agent-src/rules/spreadsheet-source-quality.md +1 -2
- package/dist/agent-src/rules/strategy-safety-floor.md +0 -1
- package/dist/agent-src/rules/symfony-routing.md +1 -2
- package/dist/agent-src/rules/think-before-action.md +0 -1
- package/dist/agent-src/rules/token-budget-discipline.md +14 -48
- package/dist/agent-src/rules/token-efficiency.md +0 -1
- package/dist/agent-src/rules/token-optimizer-maintenance.md +0 -1
- package/dist/agent-src/rules/tool-safety.md +0 -1
- package/dist/agent-src/rules/ui-audit-gate.md +1 -2
- package/dist/agent-src/rules/untrusted-input-defense.md +0 -1
- package/dist/agent-src/rules/upstream-proposal.md +0 -1
- package/dist/agent-src/rules/user-interaction.md +0 -1
- package/dist/agent-src/rules/user-interrupt-priority.md +0 -1
- package/dist/agent-src/scripts/gate_budget.ts +47 -23
- package/dist/agent-src/scripts/gate_execute.ts +12 -4
- package/dist/agent-src/skills/accessibility-auditor/data/aria-patterns.csv +2 -0
- package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +3 -3
- package/dist/agent-src/skills/ai-council/SKILL.md +7 -4
- package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +21 -11
- package/dist/agent-src/skills/ai-council/references/procedure.md +12 -6
- package/dist/agent-src/skills/analysis-autonomous-mode/SKILL.md +1 -1
- package/dist/agent-src/skills/bug-analyzer/SKILL.md +1 -1
- package/dist/agent-src/skills/canvas-design/SKILL.md +4 -2
- package/dist/agent-src/skills/command-routing/SKILL.md +3 -4
- package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +127 -139
- package/dist/agent-src/skills/corpus-grounding/ATTRIBUTION.md +39 -0
- package/dist/agent-src/skills/corpus-grounding/SKILL.md +8 -2
- package/dist/agent-src/skills/database/data/manifest.json +2 -2
- package/dist/agent-src/skills/database/data/query-tuning.csv +13 -13
- package/dist/agent-src/skills/design-intelligence/references/integration-mapping.md +13 -10
- package/dist/agent-src/skills/design-system-capture/SKILL.md +0 -3
- package/dist/agent-src/skills/estimate-ticket/SKILL.md +1 -1
- package/dist/agent-src/skills/fe-design/references/design-patterns.md +49 -2
- package/dist/agent-src/skills/feature-planning/SKILL.md +1 -1
- package/dist/agent-src/skills/frontend-render-security/SKILL.md +9 -0
- package/dist/agent-src/skills/git-workflow/SKILL.md +44 -44
- package/dist/agent-src/skills/git-workflow/references/branch-update.md +312 -0
- package/dist/agent-src/skills/git-workflow/references/commit-subject.md +205 -0
- package/dist/agent-src/skills/iconography/SKILL.md +4 -2
- package/dist/agent-src/skills/image-provider-routing/SKILL.md +16 -5
- package/dist/agent-src/skills/jira-integration/SKILL.md +3 -3
- package/dist/agent-src/skills/logo-generation/SKILL.md +12 -8
- package/dist/agent-src/skills/merge-conflicts/SKILL.md +10 -4
- package/dist/agent-src/skills/po-discovery/SKILL.md +1 -1
- package/dist/agent-src/skills/refine-ticket/SKILL.md +4 -4
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +2 -2
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +4 -2
- package/dist/agent-src/skills/source-discovery/SKILL.md +1 -1
- package/dist/agent-src/skills/svg-authoring/SKILL.md +318 -0
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +3 -1
- package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
- package/dist/agent-src/skills/using-git-worktrees/SKILL.md +1 -1
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +2 -2
- package/dist/agent-src/skills/wireframe/SKILL.md +5 -2
- package/dist/agent-src/templates/AGENTS.md +1 -1
- package/dist/agent-src/templates/agent-settings.md +46 -129
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +3 -3
- package/dist/agent-src/templates/command.md +2 -2
- package/dist/agent-src/templates/roadmaps.md +6 -1
- package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
- package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
- package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
- package/dist/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
- package/dist/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
- package/dist/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
- package/dist/agent-src/templates/skill.md +1 -1
- package/dist/cli/commands/uiRender.js +201 -4
- package/dist/cli/commands/uiRenderAsset.js +1308 -0
- package/dist/cli/commands/uiRenderAssetCompare.js +752 -0
- package/dist/cli/commands/uiRenderAssetGrid.js +265 -0
- package/dist/cli/commands/uiRenderAssetGrounds.js +323 -0
- package/dist/cli/commands/uiRenderAssetIsolation.js +85 -0
- package/dist/cli/commands/uiRenderAssetTypes.js +145 -0
- package/dist/cli/main.js +47 -1
- package/dist/cli/registry.js +2 -1
- package/dist/cli-delegate/check_update_banner.js +195 -119
- package/dist/cli-delegate/{chunk-S4UMZNES.js → chunk-4DBG5K7M.js} +5 -5
- package/dist/cli-delegate/{chunk-TRI6DQZ6.js → chunk-5GPULQBE.js} +60 -42
- package/dist/cli-delegate/{chunk-JQVYKIZA.js → chunk-6SRJTYJS.js} +33 -177
- package/dist/cli-delegate/chunk-6V5FMA3P.js +186 -0
- package/dist/cli-delegate/chunk-6YQC2HLF.js +415 -0
- package/dist/cli-delegate/{chunk-E4XIZDIB.js → chunk-7HKRE54K.js} +1 -64
- package/dist/cli-delegate/{chunk-7HQ52DHU.js → chunk-AL3RZ22D.js} +1 -1
- package/dist/cli-delegate/{chunk-DBH4AHDK.js → chunk-ED7KCMLB.js} +9 -11
- package/dist/cli-delegate/{chunk-NXEILF2K.js → chunk-F3QDG2GT.js} +481 -72
- package/dist/cli-delegate/{chunk-CQWX336L.js → chunk-G5VVIZRC.js} +3 -3
- package/dist/cli-delegate/{chunk-JY2I2DXV.js → chunk-H76PHZBI.js} +137 -60
- package/dist/cli-delegate/chunk-IAYTIIQW.js +67 -0
- package/dist/cli-delegate/{chunk-LIYTLH6O.js → chunk-KXXWJTDO.js} +5 -10
- package/dist/cli-delegate/{chunk-T7L2QK3K.js → chunk-LQOCRFWT.js} +1 -1
- package/dist/cli-delegate/{chunk-S4YWNRKO.js → chunk-MDPPKQCQ.js} +34 -1
- package/dist/cli-delegate/chunk-OAFSJBHH.js +272 -0
- package/dist/cli-delegate/{chunk-GKE7ZVFA.js → chunk-PWX7CKMD.js} +1 -1
- package/dist/cli-delegate/{chunk-NDJLNC6Q.js → chunk-T6BP34WI.js} +1 -0
- package/dist/cli-delegate/{chunk-RQNNW7IF.js → chunk-T7XSJSUQ.js} +433 -632
- package/dist/cli-delegate/{chunk-NQ7WT43P.js → chunk-TMWYUOK4.js} +75 -12
- package/dist/cli-delegate/{chunk-EEHDXSYD.js → chunk-WQWXGIWB.js} +12 -273
- package/dist/cli-delegate/{chunk-QLDHIPWR.js → chunk-XQTPXKFA.js} +1 -1
- package/dist/cli-delegate/cmd_analyze_session.js +223 -43
- package/dist/cli-delegate/cmd_brand_status.js +3 -2
- package/dist/cli-delegate/cmd_conformance.js +489 -238
- package/dist/cli-delegate/cmd_converge.js +3 -3
- package/dist/cli-delegate/cmd_doctor.js +15 -12
- package/dist/cli-delegate/cmd_doctor_neighbours.js +11 -4
- package/dist/cli-delegate/cmd_explain.js +43 -19
- package/dist/cli-delegate/cmd_export.js +10 -10
- package/dist/cli-delegate/cmd_git_convention.js +1851 -0
- package/dist/cli-delegate/cmd_handoff.js +40 -21
- package/dist/cli-delegate/cmd_mcp_available.js +3 -2
- package/dist/cli-delegate/cmd_migrate.js +3 -3
- package/dist/cli-delegate/cmd_packs_active.js +4 -3
- package/dist/cli-delegate/cmd_prune.js +10 -10
- package/dist/cli-delegate/cmd_route_audit.js +7 -7
- package/dist/cli-delegate/cmd_route_explain.js +5 -5
- package/dist/cli-delegate/cmd_session_recycle.js +9 -7
- package/dist/cli-delegate/cmd_settings_check.js +54 -7
- package/dist/cli-delegate/cmd_settings_get.js +18 -8
- package/dist/cli-delegate/cmd_settings_migrate.js +10 -10
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +10 -10
- package/dist/cli-delegate/cmd_uninstall.js +10 -10
- package/dist/cli-delegate/cmd_update.js +7 -7
- package/dist/cli-delegate/cmd_upgrade.js +7 -7
- package/dist/cli-delegate/cmd_validate.js +10 -10
- package/dist/cli-delegate/cmd_versions.js +5 -5
- package/dist/cli-delegate/gate_budget.js +1 -1
- package/dist/cli-delegate/gate_execute.js +2 -2
- package/dist/cli-delegate/roadmap_gates.js +2 -2
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +171 -107
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +7 -7
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +41 -22
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +16 -11
- package/dist/hooks/dispatch.js +2520 -1924
- package/dist/hooks/dispatch.sha256 +1 -1
- package/dist/hooks/svg_rules.chunk.cjs +1626 -0
- package/dist/hooks/svg_rules.chunk.cjs.sha256 +1 -0
- package/dist/install/install.mjs +462 -431
- package/dist/install/installThinLayer.js +40 -12
- package/dist/install/installedRuleLinks.js +105 -19
- package/dist/mcp/awesome-mcp-servers.row.md +1 -1
- package/dist/mcp/mcp-cloudflare-catalogue.json +2 -2
- package/dist/mcp/registry-manifest.json +5 -5
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +3063 -2160
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_settings.js +15 -120
- package/dist/scripts/_lib/compile_time_toggles.js +12 -21
- package/dist/scripts/_lib/git_convention.js +232 -0
- package/dist/scripts/_lib/global_deploy_inventory.js +730 -0
- package/dist/scripts/_lib/installed_layer.js +344 -18
- package/dist/scripts/_lib/package_root.js +68 -0
- package/dist/scripts/_lib/rule_law_section.js +1 -1
- package/dist/scripts/_lib/scan_scope.js +105 -0
- package/dist/scripts/_lib/settings_removed_keys.js +168 -0
- package/dist/scripts/_lib/svg_dom.js +284 -0
- package/dist/scripts/_lib/svg_geometry.js +477 -0
- package/dist/scripts/_lib/svg_motion.js +179 -0
- package/dist/scripts/_lib/svg_rules.js +1337 -0
- package/dist/scripts/_lib/svg_urls.js +67 -0
- package/dist/scripts/_lib/thin_rules.js +80 -3
- package/dist/scripts/lint_svg_asset.js +324 -0
- package/dist/server/app.js +2 -1
- package/dist/server/gitKeysGate.js +105 -0
- package/dist/server/routes/settings.js +67 -8
- package/dist/server/routes/wizard.js +4 -0
- package/dist/server/schemas/settings.js +23 -81
- package/dist/shared/skillRanking.js +30 -4
- package/dist/ui/assets/{index-Cwq4d0hX.js → index-C3djEJah.js} +2 -2
- package/dist/ui/index.html +1 -1
- package/docs/MIGRATION.md +72 -1
- package/docs/contracts/settings-classes.md +35 -65
- package/docs/guidelines/agent-infra/active-remediation-mechanics.md +39 -0
- package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +1 -1
- package/docs/guidelines/agent-infra/cross-source-consistency-mechanics.md +8 -10
- package/docs/guidelines/agent-infra/frontier-reasoning-operating-profile.md +3 -2
- package/docs/guidelines/agent-infra/layered-settings.md +13 -1
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +1 -1
- package/docs/guidelines/agent-infra/self-improvement-pipeline.md +10 -3
- package/docs/guidelines/agent-infra/size-and-scope.md +36 -0
- package/docs/guidelines/design-antipatterns.md +1 -1
- package/docs/guidelines/php/git.md +15 -2
- package/package.json +4 -3
- package/src/agent-src/scripts/gate_budget.ts +47 -23
- package/src/agent-src/scripts/gate_execute.ts +12 -4
- package/src/agent-src/templates/AGENTS.md +1 -1
- package/src/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +0 -6
- package/src/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +11 -7
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +3 -2
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +2 -1
- package/src/agent-src/templates/scripts/work_engine/hooks/settings.ts +0 -6
- package/src/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +9 -12
- package/src/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +2 -1
- package/src/config/agent-settings.template.yml +79 -312
- package/src/config/agents-paths.yml +16 -0
- package/src/config/assurance-capability-registry.json +7 -3
- package/src/config/ci-local-parity.yml +3 -0
- package/src/config/continuity-surface.json +3 -3
- package/src/config/discovery/packs.yml +17 -1
- package/src/config/evaluator-budgets.json +19 -6
- package/src/config/gate-coverage.yml +65 -23
- package/src/config/gate-violation-baselines.json +56 -16
- package/src/config/gitignore-block.txt +19 -0
- package/src/config/hook-bundle-budget.json +1 -1
- package/src/config/release-gate-locality.yml +2 -1
- package/src/config/routing-coverage-seed.json +55 -6
- package/src/config/rule-law-ceilings.json +12 -6
- package/src/config/rule-obligations.json +833 -0
- package/src/install/installThinLayer.ts +76 -10
- package/src/install/installedRuleLinks.ts +105 -17
- package/src/scripts/_cli/cmd_analyze_session.ts +9 -15
- package/src/scripts/_cli/cmd_conformance.ts +13 -2
- package/src/scripts/_cli/cmd_doctor.ts +10 -10
- package/src/scripts/_cli/cmd_doctor_neighbours.ts +133 -0
- package/src/scripts/_cli/cmd_explain.ts +72 -14
- package/src/scripts/_cli/cmd_git_convention.ts +637 -0
- package/src/scripts/_cli/cmd_settings_check.ts +66 -8
- package/src/scripts/_cli/cmd_settings_get.ts +18 -3
- package/src/scripts/_cli/doctor_execution.ts +72 -1
- package/src/scripts/_dispatch.bash +37 -2
- package/src/scripts/_lib/agent_settings.ts +15 -124
- package/src/scripts/_lib/blocked_by_marker.ts +1 -1
- package/src/scripts/_lib/compile_time_toggles.ts +12 -21
- package/src/scripts/_lib/dispatch_import_closure.ts +163 -0
- package/src/scripts/_lib/git_base_ref.ts +92 -0
- package/src/scripts/_lib/git_convention.ts +291 -0
- package/src/scripts/_lib/git_convention_carrier.ts +389 -0
- package/src/scripts/_lib/git_convention_grammar.ts +246 -0
- package/src/scripts/_lib/git_convention_measure.ts +344 -0
- package/src/scripts/_lib/global_deploy_inventory.ts +74 -0
- package/src/scripts/_lib/graph_feeder_record.ts +236 -13
- package/src/scripts/_lib/installed_layer.ts +448 -23
- package/src/scripts/_lib/knowledge_global.ts +14 -1
- package/src/scripts/_lib/module_reach.ts +456 -0
- package/src/scripts/_lib/neighbour_contradictions.ts +236 -0
- package/src/scripts/_lib/neighbour_tool_use.ts +8 -10
- package/src/scripts/_lib/ratification_artifact.ts +220 -1
- package/src/scripts/_lib/ratification_subject.ts +92 -0
- package/src/scripts/_lib/release_findings_ingest.ts +15 -7
- package/src/scripts/_lib/release_highlights.ts +5 -0
- package/src/scripts/_lib/rule_law_section.ts +1 -1
- package/src/scripts/_lib/rule_obligations.ts +205 -0
- package/src/scripts/_lib/self_repair.ts +1 -1
- package/src/scripts/_lib/settings_removed_keys.ts +173 -0
- package/src/scripts/_lib/svg_dom.ts +318 -0
- package/src/scripts/_lib/svg_geometry.ts +480 -0
- package/src/scripts/_lib/svg_motion.ts +208 -0
- package/src/scripts/_lib/svg_rules.ts +1453 -0
- package/src/scripts/_lib/svg_urls.ts +72 -0
- package/src/scripts/_lib/test_red_state.ts +5 -0
- package/src/scripts/_lib/thin_rules.ts +83 -3
- package/src/scripts/_lib/touched_file_quality.ts +142 -6
- package/src/scripts/_lib/verification_command.ts +59 -0
- package/src/scripts/_lib/verify_clause.ts +27 -17
- package/src/scripts/_lib/worker_budget.ts +1 -1
- package/src/scripts/adr/regenerate_index.ts +16 -1
- package/src/scripts/ai_council/config.ts +7 -7
- package/src/scripts/ai_council/modification_review.ts +100 -0
- package/src/scripts/ai_council/modification_review_questions.ts +90 -0
- package/src/scripts/ai_council/orchestrator.ts +5 -5
- package/src/scripts/ai_council/spend_gate.ts +18 -7
- package/src/scripts/ai_team/config.ts +11 -16
- package/src/scripts/audit_user_type_axis.ts +20 -8
- package/src/scripts/bench_ab_clone.ts +1 -2
- package/src/scripts/bench_concern_spawn_path.ts +129 -0
- package/src/scripts/bench_graph_feeder_latency.ts +584 -0
- package/src/scripts/check_agent_artifact_location.ts +36 -0
- package/src/scripts/check_branch_freshness.ts +147 -24
- package/src/scripts/check_enforcement_coverage.ts +130 -0
- package/src/scripts/check_evaluator_budgets.ts +4 -0
- package/src/scripts/check_finding_dispositions.ts +88 -25
- package/src/scripts/check_gate_coverage.ts +4 -3
- package/src/scripts/check_gate_reachability.ts +48 -1
- package/src/scripts/check_generator_sync.ts +48 -0
- package/src/scripts/check_hook_bundle_composition.ts +107 -0
- package/src/scripts/check_kernel_edit_ratified.ts +86 -6
- package/src/scripts/check_pack_size.ts +1 -1
- package/src/scripts/check_release_manifest_content.ts +189 -0
- package/src/scripts/check_standing_rule_delivery.ts +96 -0
- package/src/scripts/check_suppression_hygiene.ts +2 -5
- package/src/scripts/ci_settle.ts +42 -5
- package/src/scripts/classify_merge_risk.ts +320 -0
- package/src/scripts/closure_scan.ts +91 -1
- package/src/scripts/command_suggester/settings.ts +8 -108
- package/src/scripts/command_suggester/types.ts +4 -5
- package/src/scripts/consumer_matrix.ts +102 -0
- package/src/scripts/context_hygiene_hook.ts +13 -23
- package/src/scripts/cost/preflight.mjs +12 -1
- package/src/scripts/council_cli.ts +7 -7
- package/src/scripts/dispatch_r2_reviewer.ts +24 -11
- package/src/scripts/explain_run.ts +8 -13
- package/src/scripts/generate_git_convention_grammar.ts +127 -0
- package/src/scripts/generate_host_cost_table.ts +20 -3
- package/src/scripts/handoff_context_hook.ts +86 -37
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +25 -6
- package/src/scripts/hooks/block_config_weakening.ts +48 -5
- package/src/scripts/hooks/block_plumbing_writes.ts +8 -4
- package/src/scripts/hooks/block_speaking_inbox_dir.ts +16 -1
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/delegation_nudge_hook.ts +2 -3
- package/src/scripts/hooks/design_pass_hook.ts +157 -3
- package/src/scripts/hooks/evidence_independence.ts +12 -4
- package/src/scripts/hooks/mcp_usage_observation_hook.ts +121 -0
- package/src/scripts/hooks/push_settle_hook.ts +4 -3
- package/src/scripts/hooks/rule_inject_hook.ts +44 -3
- package/src/scripts/hooks/state_io.ts +8 -4
- package/src/scripts/hooks/svg_obligation.ts +497 -0
- package/src/scripts/hooks/svg_rules_loader.ts +133 -0
- package/src/scripts/hooks/telemetry_usage_hook.ts +7 -46
- package/src/scripts/hooks/turn_end_gate_hook.ts +6 -3
- package/src/scripts/install-hooks.sh +42 -14
- package/src/scripts/install.ts +7 -31
- package/src/scripts/lint_blocker_citations.ts +198 -0
- package/src/scripts/lint_consolidation_lineage.ts +6 -3
- package/src/scripts/lint_design_quality.ts +60 -12
- package/src/scripts/lint_evidence_artifacts.ts +9 -0
- package/src/scripts/lint_hook_concern_budget.ts +10 -21
- package/src/scripts/lint_motion_authority_drift.ts +27 -0
- package/src/scripts/lint_pack_boundaries.ts +406 -28
- package/src/scripts/lint_roadmap_blockers.ts +282 -29
- package/src/scripts/lint_roadmap_complexity.ts +4 -2
- package/src/scripts/lint_rule_law_section.ts +151 -21
- package/src/scripts/lint_rule_skill_pack_reach.ts +17 -0
- package/src/scripts/lint_settings_classes.ts +1 -1
- package/src/scripts/lint_svg_asset.ts +365 -0
- package/src/scripts/lint_ticked_unmet_criteria.ts +165 -0
- package/src/scripts/lint_workflow_security.ts +12 -1
- package/src/scripts/measure_skill_ranker_baseline.ts +5 -0
- package/src/scripts/model_rule_injection.ts +3 -3
- package/src/scripts/onboarding_gate_hook.ts +7 -6
- package/src/scripts/print_required_checks.ts +15 -3
- package/src/scripts/probe_host_compliance.ts +33 -5
- package/src/scripts/probe_turnaround.ts +183 -3
- package/src/scripts/ratification_header.ts +77 -0
- package/src/scripts/refusal_envelope.ts +138 -0
- package/src/scripts/release_publication.ts +29 -3
- package/src/scripts/report_dispatch_import_closure.ts +76 -0
- package/src/scripts/report_installed_rule_links.ts +118 -1
- package/src/scripts/report_module_reach.ts +212 -0
- package/src/scripts/report_obligation_mechanism.ts +16 -18
- package/src/scripts/report_parked_blockers.ts +222 -0
- package/src/scripts/report_required_checks_drift.ts +196 -0
- package/src/scripts/report_skill_ranker_confusion.ts +103 -2
- package/src/scripts/report_standing_payload_by_host.ts +1 -1
- package/src/scripts/routing_doctor.ts +2 -2
- package/src/scripts/schemas/agent-settings.schema.json +17 -31
- package/src/scripts/schemas/command.schema.json +1 -1
- package/src/scripts/schemas/skill.schema.json +1 -1
- package/src/scripts/self_review_gate.ts +39 -2
- package/src/scripts/skill_tools/score_skill_relevance.ts +28 -19
- package/src/scripts/sync_pr_branch.ts +403 -132
- package/src/scripts/trigger_eval_grandfather.json +0 -16
- package/src/server/schemas/settings.ts +33 -177
- package/src/shared/skillRanking.ts +53 -4
- package/dist/cli-delegate/chunk-NYX3L2PZ.js +0 -99
- package/src/scripts/_lib/config_chain.ts +0 -477
- package/src/scripts/_lib/conformance_report.ts +0 -403
- package/src/scripts/_lib/eval_discrimination.ts +0 -95
- package/src/scripts/_lib/evaluator_promotion.ts +0 -225
- package/src/scripts/_lib/file_slicer.ts +0 -117
- package/src/scripts/_lib/legacy_boundary_map.ts +0 -228
- package/src/scripts/_lib/minimality_tiebreak.ts +0 -168
- package/src/scripts/_lib/overbuild_lens_contract.ts +0 -196
- package/src/scripts/_lib/role_split.ts +0 -338
|
@@ -63,6 +63,8 @@ const DOCS_ONLY_ALLOWED_TOP: ReadonlySet<string> = new Set([
|
|
|
63
63
|
|
|
64
64
|
// Check names below are the strings GitHub actually REPORTS, verified against
|
|
65
65
|
// `gh pr checks 1108` on 2026-08-02 (road-to-renewal-foundation Phase 1).
|
|
66
|
+
// `Standing payload delta + budget gate` was added to all three shapes on
|
|
67
|
+
// 2026-10-07, when it was found required by the ruleset and absent here.
|
|
66
68
|
//
|
|
67
69
|
// They previously named a matrix that had drifted into fiction — `Consistency`,
|
|
68
70
|
// `Skill Lint`, `Tests / install-tests`, `Tests / node-tests`,
|
|
@@ -79,6 +81,7 @@ const DOCS_ONLY_ALLOWED_TOP: ReadonlySet<string> = new Set([
|
|
|
79
81
|
// change — the exact failure this reconciliation removed.
|
|
80
82
|
const FEATURE_CHECKS = [
|
|
81
83
|
'Sync + Generate Tools Consistency',
|
|
84
|
+
'Standing payload delta + budget gate',
|
|
82
85
|
'Smoke — kernel',
|
|
83
86
|
'Smoke — router',
|
|
84
87
|
'Smoke — schema',
|
|
@@ -98,6 +101,7 @@ const FEATURE_CHECKS = [
|
|
|
98
101
|
|
|
99
102
|
const RELEASE_CHECKS = [
|
|
100
103
|
'Sync + Generate Tools Consistency',
|
|
104
|
+
'Standing payload delta + budget gate',
|
|
101
105
|
'Smoke — kernel',
|
|
102
106
|
'Smoke — router',
|
|
103
107
|
'Smoke — schema',
|
|
@@ -112,6 +116,7 @@ const RELEASE_CHECKS = [
|
|
|
112
116
|
|
|
113
117
|
const DOCS_ONLY_CHECKS = [
|
|
114
118
|
'Sync + Generate Tools Consistency',
|
|
119
|
+
'Standing payload delta + budget gate',
|
|
115
120
|
'Smoke — kernel',
|
|
116
121
|
'Smoke — router',
|
|
117
122
|
'Smoke — schema',
|
|
@@ -120,8 +125,11 @@ const DOCS_ONLY_CHECKS = [
|
|
|
120
125
|
|
|
121
126
|
/**
|
|
122
127
|
* The checks that mechanically BLOCK a merge, per the repository ruleset
|
|
123
|
-
* `main protection` (id 17749383)
|
|
124
|
-
*
|
|
128
|
+
* `main protection` (id 17749383), read on 2026-10-07: two required status
|
|
129
|
+
* contexts, the second added on 2026-09-11 (ADR-276, recorded by #2169).
|
|
130
|
+
* Everything else above runs and is visible on the PR but does not gate the
|
|
131
|
+
* merge button. `standing-payload-delta.yml` runs on every `pull_request`, so
|
|
132
|
+
* the second context appears in all three shapes.
|
|
125
133
|
*
|
|
126
134
|
* Deliberately a constant, not an API read: this script is contractually
|
|
127
135
|
* offline ("never invokes `gh`, never touches the network"). Re-verify with
|
|
@@ -129,7 +137,10 @@ const DOCS_ONLY_CHECKS = [
|
|
|
129
137
|
* changes — `docs/contracts/branch-protection-policy.md` § Change discipline
|
|
130
138
|
* owns that procedure.
|
|
131
139
|
*/
|
|
132
|
-
const ENFORCED_CHECKS = [
|
|
140
|
+
const ENFORCED_CHECKS = [
|
|
141
|
+
'Sync + Generate Tools Consistency',
|
|
142
|
+
'Standing payload delta + budget gate',
|
|
143
|
+
] as const;
|
|
133
144
|
|
|
134
145
|
/** `git rev-parse --abbrev-ref HEAD`, mirroring `_git(check=True)`. */
|
|
135
146
|
function current_branch(): string {
|
|
@@ -314,6 +325,7 @@ export {
|
|
|
314
325
|
FEATURE_CHECKS,
|
|
315
326
|
RELEASE_CHECKS,
|
|
316
327
|
DOCS_ONLY_CHECKS,
|
|
328
|
+
ENFORCED_CHECKS,
|
|
317
329
|
current_branch,
|
|
318
330
|
diff_files,
|
|
319
331
|
is_docs_only,
|
|
@@ -31,7 +31,7 @@ import * as path from 'node:path';
|
|
|
31
31
|
import process from 'node:process';
|
|
32
32
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
33
33
|
|
|
34
|
-
import { thin_entry } from './project_thin_rules.js';
|
|
34
|
+
import { has_body_pointer, is_thin_entry, thin_entry } from './project_thin_rules.js';
|
|
35
35
|
|
|
36
36
|
const _HERE = fileURLToPath(import.meta.url);
|
|
37
37
|
const REPO_ROOT = path.resolve(path.dirname(_HERE), '..', '..');
|
|
@@ -42,8 +42,6 @@ const CANARY = path.join(
|
|
|
42
42
|
const CANARY_ID = 'host-compliance-canary';
|
|
43
43
|
const SENTINEL = 'CANARY_BODY_SENTINEL_DO_NOT_INLINE';
|
|
44
44
|
const KEYWORD = 'xyzzy-canary-probe';
|
|
45
|
-
const POINTER_MARKER = 'Routed rule — load the body on trigger-match';
|
|
46
|
-
|
|
47
45
|
// The supported hosts whose live thin-compliance must be falsified.
|
|
48
46
|
const HOSTS = ['claude-code', 'cursor', 'augment'];
|
|
49
47
|
|
|
@@ -60,10 +58,40 @@ export function evaluate_demotion(
|
|
|
60
58
|
thinned: string,
|
|
61
59
|
opts: { sentinel: string; keyword: string } = { sentinel: SENTINEL, keyword: KEYWORD },
|
|
62
60
|
): DemotionResult {
|
|
63
|
-
|
|
61
|
+
// ONE SPELLING, ASKED OF THE WRITER — step 2.1 of
|
|
62
|
+
// `road-to-a-thinned-layer-measured-in-one-unit`. This file carried its own
|
|
63
|
+
// substring of the marker, without the blockquote prefix and the full stop,
|
|
64
|
+
// so the writer could be shortened and this detector would keep matching the
|
|
65
|
+
// old sentence — silently, and in the direction that matters: a stub a
|
|
66
|
+
// detector fails to recognise reads as a complete rule body.
|
|
67
|
+
const pointer_present = is_thin_entry(thinned);
|
|
64
68
|
const body_removed = !thinned.includes(opts.sentinel);
|
|
65
69
|
const trigger_hint_preserved = thinned.includes(opts.keyword);
|
|
66
|
-
|
|
70
|
+
// THE PATTERN COMES FROM THE WRITER — step 2.3. This was its own regex for
|
|
71
|
+
// the markdown-link form, so when the pointer became a bare path the gate
|
|
72
|
+
// would have reported every correct stub as missing its link.
|
|
73
|
+
const link_present = has_body_pointer(thinned);
|
|
74
|
+
// HONEST LIMIT OF THIS FUNCTION'S MECHANICAL HALF, stated rather than
|
|
75
|
+
// papered over. `pointer_present` and `link_present` are now computed from
|
|
76
|
+
// the writer's own exports, and this probe's only caller feeds them
|
|
77
|
+
// `thin_entry` output produced in the same process — so against writer output
|
|
78
|
+
// those two cannot return false, whatever the writer emits. They still
|
|
79
|
+
// falsify a stub from any OTHER source, which is what the live host half
|
|
80
|
+
// reads, but the mechanical half's real falsifying power is `body_removed`
|
|
81
|
+
// and `trigger_hint_preserved`.
|
|
82
|
+
//
|
|
83
|
+
// A structural check was tried here and removed: `/\S+\.md\s*$/m` adds
|
|
84
|
+
// nothing AGAINST WRITER OUTPUT, which is the only input this half ever sees.
|
|
85
|
+
// It is not implied by `link_present` in general — `Body: .md`, a two-space
|
|
86
|
+
// stem, matches the pointer pattern and fails `\S+` — but the writer composes
|
|
87
|
+
// the pointer from a non-empty prefix and a rule id, so that string is not
|
|
88
|
+
// reachable from `thin_entry` and the conjunct could never flip `ok` here. A
|
|
89
|
+
// conjunct that cannot fail is worse than an absent one: it reads as coverage.
|
|
90
|
+
//
|
|
91
|
+
// Restoring independence needs a second spelling of the marker, which is the
|
|
92
|
+
// drift step 2.1 removed. The suite keeps the detectors honest instead:
|
|
93
|
+
// `thin_marker_single_spelling` runs a non-stub past all three in the false
|
|
94
|
+
// direction, which is the direction this cannot check.
|
|
67
95
|
return {
|
|
68
96
|
ok: pointer_present && body_removed && trigger_hint_preserved && link_present,
|
|
69
97
|
pointer_present,
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
* - API calls per real user request (F1)
|
|
20
20
|
* - mean tool-call batch size (F1 — measured 1.00, i.e. fully serial)
|
|
21
21
|
* - the >60 s blocking tail and its share of tool time (F2)
|
|
22
|
+
* - that tail split by cause, `unknown` always printed (road-to-blocking-time-by-cause)
|
|
22
23
|
* - the first-call context floor (F3 cross-check)
|
|
23
24
|
*
|
|
24
25
|
* A MEASUREMENT, NOT A GATE — by default. `--against-baseline` compares against
|
|
@@ -53,6 +54,142 @@ export const BLOCKING_SECONDS = 60;
|
|
|
53
54
|
|
|
54
55
|
type Entry = Record<string, unknown>;
|
|
55
56
|
|
|
57
|
+
/**
|
|
58
|
+
* What a blocking call waited on. A CLOSED set, and `unknown` is a row of its
|
|
59
|
+
* own rather than a fallback folded into a named cause: a share hidden inside
|
|
60
|
+
* `ci-wait` would confirm whatever hypothesis it was folded into.
|
|
61
|
+
*/
|
|
62
|
+
export const BLOCKING_CAUSES = [
|
|
63
|
+
'ci-wait',
|
|
64
|
+
'subagent-wait',
|
|
65
|
+
'test',
|
|
66
|
+
'build',
|
|
67
|
+
'network',
|
|
68
|
+
'sleep-poll',
|
|
69
|
+
'mcp',
|
|
70
|
+
// Added by 2.2: the first reading's unknown share was mostly a question
|
|
71
|
+
// waiting on the human, which no agent-side mitigation can shorten.
|
|
72
|
+
'user-wait',
|
|
73
|
+
'unknown',
|
|
74
|
+
] as const;
|
|
75
|
+
export type BlockingCause = (typeof BLOCKING_CAUSES)[number];
|
|
76
|
+
|
|
77
|
+
/** Non-shell tools, by exact name. A shell call is classified by its command. */
|
|
78
|
+
const TOOL_CAUSE: Readonly<Record<string, BlockingCause>> = {
|
|
79
|
+
Agent: 'subagent-wait',
|
|
80
|
+
Task: 'subagent-wait',
|
|
81
|
+
TaskOutput: 'subagent-wait',
|
|
82
|
+
Monitor: 'sleep-poll',
|
|
83
|
+
WebFetch: 'network',
|
|
84
|
+
WebSearch: 'network',
|
|
85
|
+
AskUserQuestion: 'user-wait',
|
|
86
|
+
ExitPlanMode: 'user-wait',
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Shell rules, matched against each command SEGMENT's leading words in order.
|
|
91
|
+
* The first segment any rule matches decides; a segment no rule matches is
|
|
92
|
+
* skipped, so `cd ../lane; ./scripts-run …/ci_settle 12` reads as the settle it
|
|
93
|
+
* is and not as the `cd` in front of it.
|
|
94
|
+
*/
|
|
95
|
+
const SHELL_RULES: ReadonlyArray<readonly [RegExp, BlockingCause]> = [
|
|
96
|
+
[/^(\S*\/)?scripts-run \S*ci_settle\b/, 'ci-wait'],
|
|
97
|
+
[/^gh (run watch|pr checks)\b/, 'ci-wait'],
|
|
98
|
+
[/^(sleep|until|while|watch)\b/, 'sleep-poll'],
|
|
99
|
+
[/^((npx |\S*node_modules\/\.bin\/)?(vitest|jest|pytest|phpunit)\b|npm (run )?test\b|task (ci|test)\b)/, 'test'],
|
|
100
|
+
[/^(task (sync|generate-tools|build)\b|npm (ci|install|run build)\b|(npx )?tsc\b|make\b|esbuild\b)/, 'build'],
|
|
101
|
+
[/^(git (push|fetch|pull|clone)\b|curl\b|wget\b|gh (pr (merge|create)|api)\b)/, 'network'],
|
|
102
|
+
[/^(\S*\/)?scripts-run \S*council_cli run\b/, 'network'],
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
/** A segment that only changes directory or sets a variable waited on nothing. */
|
|
106
|
+
const NOISE_SEGMENT = /^(cd\b|export\b|set\b|[A-Za-z_][A-Za-z0-9_]*=\S*$)/;
|
|
107
|
+
|
|
108
|
+
/** A loop keyword in front of a body: `for …; do sleep 60` reads as the sleep. */
|
|
109
|
+
const LOOP_KEYWORD = /^(do|then|else)\s+/;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Split a shell command at `;`, `&&`, `||`, `|` and newlines that sit OUTSIDE
|
|
113
|
+
* quotes. A separator inside `"…"` or `'…'`, or escaped with a backslash, is
|
|
114
|
+
* part of an argument — splitting there would read a commit message as a
|
|
115
|
+
* command. Not a shell parser: subshells, `$(…)` and heredocs are not modelled.
|
|
116
|
+
*/
|
|
117
|
+
function shellSegments(cmd: string): string[] {
|
|
118
|
+
const out: string[] = [];
|
|
119
|
+
let cur = '';
|
|
120
|
+
let quote: '' | '"' | "'" = '';
|
|
121
|
+
for (let i = 0; i < cmd.length; i++) {
|
|
122
|
+
const ch = cmd[i] as string;
|
|
123
|
+
if (quote === '' && ch === '\\' && i + 1 < cmd.length) {
|
|
124
|
+
cur += ch + (cmd[i + 1] as string);
|
|
125
|
+
i++;
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (quote !== '') {
|
|
129
|
+
if (ch === quote) quote = '';
|
|
130
|
+
cur += ch;
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (ch === '"' || ch === "'") {
|
|
134
|
+
quote = ch;
|
|
135
|
+
cur += ch;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const two = cmd.slice(i, i + 2);
|
|
139
|
+
if (two === '&&' || two === '||') {
|
|
140
|
+
out.push(cur);
|
|
141
|
+
cur = '';
|
|
142
|
+
i++;
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
if (ch === ';' || ch === '|' || ch === '\n') {
|
|
146
|
+
out.push(cur);
|
|
147
|
+
cur = '';
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
cur += ch;
|
|
151
|
+
}
|
|
152
|
+
out.push(cur);
|
|
153
|
+
return out;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Exactly one cause per call; `unknown` when no rule matches. A compound
|
|
158
|
+
* command takes the cause of its FIRST matching segment, so `git commit && git
|
|
159
|
+
* push` reads as the push — the whole call's time lands on that one cause.
|
|
160
|
+
*/
|
|
161
|
+
export function classifyBlockingCall(tool: string, input: unknown): BlockingCause {
|
|
162
|
+
if (tool.startsWith('mcp__')) return 'mcp';
|
|
163
|
+
const byName = TOOL_CAUSE[tool];
|
|
164
|
+
if (byName !== undefined) return byName;
|
|
165
|
+
if (tool !== 'Bash' || !isObj(input) || typeof input['command'] !== 'string') return 'unknown';
|
|
166
|
+
for (const raw of shellSegments(input['command'])) {
|
|
167
|
+
const seg = raw.trim().replace(LOOP_KEYWORD, '');
|
|
168
|
+
if (seg === '' || NOISE_SEGMENT.test(seg)) continue;
|
|
169
|
+
for (const [re, cause] of SHELL_RULES) if (re.test(seg)) return cause;
|
|
170
|
+
}
|
|
171
|
+
return 'unknown';
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* The in-memory record of one blocking call. `summary` is bounded and never
|
|
176
|
+
* printed or serialised by `main`: command text names local paths and hosts,
|
|
177
|
+
* and the published reading carries counts and minutes only.
|
|
178
|
+
*/
|
|
179
|
+
export interface BlockingCall {
|
|
180
|
+
tool: string;
|
|
181
|
+
summary: string;
|
|
182
|
+
cause: BlockingCause;
|
|
183
|
+
seconds: number;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const SUMMARY_CHARS = 120;
|
|
187
|
+
|
|
188
|
+
function summarise(tool: string, input: unknown): string {
|
|
189
|
+
const body = isObj(input) && typeof input['command'] === 'string' ? input['command'] : JSON.stringify(input ?? {});
|
|
190
|
+
return `${tool}: ${body}`.slice(0, SUMMARY_CHARS);
|
|
191
|
+
}
|
|
192
|
+
|
|
56
193
|
function isObj(v: unknown): v is Record<string, unknown> {
|
|
57
194
|
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
58
195
|
}
|
|
@@ -72,6 +209,12 @@ export interface Turnaround {
|
|
|
72
209
|
blockingShare: number;
|
|
73
210
|
contextFloorMin: number;
|
|
74
211
|
contextFloorMax: number;
|
|
212
|
+
/** Blocking calls and seconds per cause; every cause present, `unknown` included. */
|
|
213
|
+
blockingByCause: Record<BlockingCause, { calls: number; seconds: number }>;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function emptyByCause(): Turnaround['blockingByCause'] {
|
|
217
|
+
return Object.fromEntries(BLOCKING_CAUSES.map((c) => [c, { calls: 0, seconds: 0 }])) as Turnaround['blockingByCause'];
|
|
75
218
|
}
|
|
76
219
|
|
|
77
220
|
const ZERO: Turnaround = {
|
|
@@ -88,6 +231,7 @@ const ZERO: Turnaround = {
|
|
|
88
231
|
blockingShare: 0,
|
|
89
232
|
contextFloorMin: 0,
|
|
90
233
|
contextFloorMax: 0,
|
|
234
|
+
blockingByCause: emptyByCause(),
|
|
91
235
|
};
|
|
92
236
|
|
|
93
237
|
function ms(iso: unknown): number | null {
|
|
@@ -133,12 +277,20 @@ export function recentSessions(store: string, limit: number, includeCurrent = fa
|
|
|
133
277
|
}
|
|
134
278
|
|
|
135
279
|
export function measure(files: readonly string[]): Turnaround {
|
|
280
|
+
return measureDetailed(files).turnaround;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/** `measure`, plus the per-call blocking records the cause table is built from. */
|
|
284
|
+
export function measureDetailed(files: readonly string[]): { turnaround: Turnaround; blocking: BlockingCall[] } {
|
|
136
285
|
const requestIds = new Set<string>();
|
|
137
286
|
/** requestId → tool_use blocks in it. */
|
|
138
287
|
const batch = new Map<string, number>();
|
|
139
288
|
/** tool_use id → the timestamp the assistant emitted it. */
|
|
140
289
|
const emittedAt = new Map<string, number>();
|
|
290
|
+
/** tool_use id → what was called, kept only until its result arrives. */
|
|
291
|
+
const calledWith = new Map<string, { tool: string; input: unknown }>();
|
|
141
292
|
const durations: number[] = [];
|
|
293
|
+
const blockingCalls: BlockingCall[] = [];
|
|
142
294
|
const contextFloors: number[] = [];
|
|
143
295
|
let userRequests = 0;
|
|
144
296
|
let sessions = 0;
|
|
@@ -172,8 +324,20 @@ export function measure(files: readonly string[]): Turnaround {
|
|
|
172
324
|
const id = String(b['tool_use_id'] ?? '');
|
|
173
325
|
const started = emittedAt.get(id);
|
|
174
326
|
if (started === undefined || at === null) continue;
|
|
175
|
-
|
|
327
|
+
const seconds = (at - started) / 1000;
|
|
328
|
+
durations.push(seconds);
|
|
176
329
|
emittedAt.delete(id);
|
|
330
|
+
const call = calledWith.get(id);
|
|
331
|
+
calledWith.delete(id);
|
|
332
|
+
if (seconds > BLOCKING_SECONDS) {
|
|
333
|
+
const tool = call?.tool ?? '';
|
|
334
|
+
blockingCalls.push({
|
|
335
|
+
tool,
|
|
336
|
+
summary: summarise(tool, call?.input),
|
|
337
|
+
cause: classifyBlockingCall(tool, call?.input),
|
|
338
|
+
seconds,
|
|
339
|
+
});
|
|
340
|
+
}
|
|
177
341
|
}
|
|
178
342
|
}
|
|
179
343
|
continue;
|
|
@@ -202,7 +366,10 @@ export function measure(files: readonly string[]): Turnaround {
|
|
|
202
366
|
if (!isObj(b) || b['type'] !== 'tool_use') continue;
|
|
203
367
|
n += 1;
|
|
204
368
|
const id = String(b['id'] ?? '');
|
|
205
|
-
if (id !== '' && at !== null)
|
|
369
|
+
if (id !== '' && at !== null) {
|
|
370
|
+
emittedAt.set(id, at);
|
|
371
|
+
calledWith.set(id, { tool: String(b['name'] ?? ''), input: b['input'] });
|
|
372
|
+
}
|
|
206
373
|
}
|
|
207
374
|
if (n > 0 && typeof rid === 'string' && rid !== '') {
|
|
208
375
|
batch.set(rid, (batch.get(rid) ?? 0) + n);
|
|
@@ -216,8 +383,14 @@ export function measure(files: readonly string[]): Turnaround {
|
|
|
216
383
|
const blocking = durations.filter((d) => d > BLOCKING_SECONDS);
|
|
217
384
|
const blockingSeconds = blocking.reduce((a, b) => a + b, 0);
|
|
218
385
|
const round = (x: number, p = 2): number => Math.round(x * 10 ** p) / 10 ** p;
|
|
386
|
+
const byCause = emptyByCause();
|
|
387
|
+
for (const c of blockingCalls) {
|
|
388
|
+
byCause[c.cause].calls += 1;
|
|
389
|
+
byCause[c.cause].seconds += c.seconds;
|
|
390
|
+
}
|
|
391
|
+
for (const c of BLOCKING_CAUSES) byCause[c].seconds = round(byCause[c].seconds, 1);
|
|
219
392
|
|
|
220
|
-
|
|
393
|
+
const turnaround: Turnaround = {
|
|
221
394
|
sessions,
|
|
222
395
|
userRequests,
|
|
223
396
|
apiCalls: requestIds.size,
|
|
@@ -231,7 +404,9 @@ export function measure(files: readonly string[]): Turnaround {
|
|
|
231
404
|
blockingShare: toolSeconds === 0 ? 0 : round(blockingSeconds / toolSeconds, 4),
|
|
232
405
|
contextFloorMin: contextFloors.length === 0 ? 0 : Math.min(...contextFloors),
|
|
233
406
|
contextFloorMax: contextFloors.length === 0 ? 0 : Math.max(...contextFloors),
|
|
407
|
+
blockingByCause: byCause,
|
|
234
408
|
};
|
|
409
|
+
return { turnaround, blocking: blockingCalls };
|
|
235
410
|
}
|
|
236
411
|
|
|
237
412
|
export interface Budget {
|
|
@@ -297,6 +472,11 @@ function render(t: Turnaround, store: string): string {
|
|
|
297
472
|
` mean tool-call batch size ${String(t.meanBatchSize)} (${String(t.toolCalls)} tool calls / ${String(t.toolUsingRequests)} tool-using requests)`,
|
|
298
473
|
` blocking tail (>${String(BLOCKING_SECONDS)}s) ${String(t.blockingCalls)} call(s), ${String(Math.round(t.blockingSeconds / 60))} min = ${pct(t.blockingShare)} of ${String(Math.round(t.toolSeconds / 60))} min tool time`,
|
|
299
474
|
` first-call context floor ${String(t.contextFloorMin)}–${String(t.contextFloorMax)} tokens`,
|
|
475
|
+
` blocking tail by cause`,
|
|
476
|
+
...BLOCKING_CAUSES.map((c) => {
|
|
477
|
+
const row = t.blockingByCause[c];
|
|
478
|
+
return ` ${c.padEnd(14)}${String(row.calls)} call(s), ${String(Math.round(row.seconds / 60))} min`;
|
|
479
|
+
}),
|
|
300
480
|
'',
|
|
301
481
|
].join('\n');
|
|
302
482
|
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* ratification_header — print a ratification artifact's `providers:`,
|
|
4
|
+
* `verdict:` and `seats:` frontmatter lines, derived from per-seat final
|
|
5
|
+
* verdicts.
|
|
6
|
+
*
|
|
7
|
+
* The two header fields used to be typed by the author, and three findings in
|
|
8
|
+
* one release were the header saying more than the seats had: `ratified` over a
|
|
9
|
+
* non-convergent seat, two providers over one closing seat. This is the writer
|
|
10
|
+
* side of the fix; `readRatification` refuses the same shapes on the reader
|
|
11
|
+
* side whenever `seats:` is recorded.
|
|
12
|
+
*
|
|
13
|
+
* Usage: ratification_header --seat <provider>=<final-verdict> [--seat …]
|
|
14
|
+
* final-verdict: ratified | confirmed-non-expanding | refused | non-convergent
|
|
15
|
+
* | no-final-verdict (the seat closed or was absent at the end)
|
|
16
|
+
*
|
|
17
|
+
* Exit codes: 0 = header printed · 2 = usage error.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import * as fs from 'node:fs';
|
|
21
|
+
import * as path from 'node:path';
|
|
22
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
23
|
+
|
|
24
|
+
import {
|
|
25
|
+
SEAT_PROVIDER_RE,
|
|
26
|
+
SEAT_VERDICTS,
|
|
27
|
+
renderRatificationHeader,
|
|
28
|
+
type SeatVerdict,
|
|
29
|
+
} from './_lib/ratification_artifact.js';
|
|
30
|
+
|
|
31
|
+
export function main(argv: readonly string[] = process.argv.slice(2)): number {
|
|
32
|
+
const seats = new Map<string, SeatVerdict>();
|
|
33
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
34
|
+
if (argv[i] !== '--seat') {
|
|
35
|
+
process.stderr.write(`error: unknown argument ${String(argv[i])}\n`);
|
|
36
|
+
return 2;
|
|
37
|
+
}
|
|
38
|
+
const raw = argv[i + 1] ?? '';
|
|
39
|
+
i += 1;
|
|
40
|
+
const eq = raw.indexOf('=');
|
|
41
|
+
const provider = raw.slice(0, eq);
|
|
42
|
+
const verdict = raw.slice(eq + 1);
|
|
43
|
+
if (eq <= 0 || !SEAT_PROVIDER_RE.test(provider) || !SEAT_VERDICTS.includes(verdict)) {
|
|
44
|
+
process.stderr.write(
|
|
45
|
+
`error: --seat needs <provider id ${String(SEAT_PROVIDER_RE)}>=<one of ` +
|
|
46
|
+
`${SEAT_VERDICTS.join('|')}>, got \`${raw}\`\n`,
|
|
47
|
+
);
|
|
48
|
+
return 2;
|
|
49
|
+
}
|
|
50
|
+
if (seats.has(provider)) {
|
|
51
|
+
process.stderr.write(`error: seat \`${provider}\` given twice\n`);
|
|
52
|
+
return 2;
|
|
53
|
+
}
|
|
54
|
+
seats.set(provider, verdict as SeatVerdict);
|
|
55
|
+
}
|
|
56
|
+
if (seats.size === 0) {
|
|
57
|
+
process.stderr.write('error: at least one --seat is required\n');
|
|
58
|
+
return 2;
|
|
59
|
+
}
|
|
60
|
+
process.stdout.write(`${renderRatificationHeader(seats)}\n`);
|
|
61
|
+
return 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function _isCliEntry(): boolean {
|
|
65
|
+
if (process.argv[1] === undefined) return false;
|
|
66
|
+
const here = fileURLToPath(import.meta.url);
|
|
67
|
+
if (import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) return true;
|
|
68
|
+
try {
|
|
69
|
+
return fs.realpathSync(here) === fs.realpathSync(path.resolve(process.argv[1]));
|
|
70
|
+
} catch {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (_isCliEntry()) {
|
|
76
|
+
process.exit(main());
|
|
77
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* refusal_envelope — the hand-off an agent writes when a HOST classifier
|
|
4
|
+
* refuses a step of an owner-directed task (ADR-282 § Part B).
|
|
5
|
+
*
|
|
6
|
+
* The repository cannot change the host classifier, and an agent must never
|
|
7
|
+
* route around a refused action. With the owner present it asks once for an
|
|
8
|
+
* explicit in-session authorization and re-runs the same step once; this
|
|
9
|
+
* envelope is the fallback when that is refused too or no owner is present.
|
|
10
|
+
* Write one ready-to-paste continuation prompt and name its path in one line,
|
|
11
|
+
* so the owner never has to ask for it.
|
|
12
|
+
*
|
|
13
|
+
* The envelope lands at `agents/tmp/<round-hex>/prompt.md`. The directory name
|
|
14
|
+
* is an opaque round id because `block-speaking-inbox-dir` refuses any other
|
|
15
|
+
* shape under `agents/tmp/`; the id is random, so an earlier envelope is never
|
|
16
|
+
* overwritten.
|
|
17
|
+
*
|
|
18
|
+
* Subagent lanes report refusals in the fixed `classifier_refusals` field;
|
|
19
|
+
* `batchLaneRefusals` folds every lane's field into ONE list so a drain ends in
|
|
20
|
+
* one envelope instead of N reports the owner collects by hand. A lane report
|
|
21
|
+
* WITHOUT the field is malformed — "no field" and "no refusals" must not read
|
|
22
|
+
* the same, or a lane that forgot to report looks like a lane that was clean.
|
|
23
|
+
*
|
|
24
|
+
* Usage:
|
|
25
|
+
* refusal_envelope --input <file.json> [--root DIR]
|
|
26
|
+
* The JSON is an `EnvelopeInput`. Prints the written path as the last line.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import { randomBytes } from 'node:crypto';
|
|
30
|
+
import * as fs from 'node:fs';
|
|
31
|
+
import * as path from 'node:path';
|
|
32
|
+
import { pathToFileURL } from 'node:url';
|
|
33
|
+
|
|
34
|
+
export interface Refusal {
|
|
35
|
+
action: string;
|
|
36
|
+
reason: string;
|
|
37
|
+
lane?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface EnvelopeInput {
|
|
41
|
+
task: string;
|
|
42
|
+
done: string[];
|
|
43
|
+
refusals: Refusal[];
|
|
44
|
+
remaining: string[];
|
|
45
|
+
/** Path of the owner-directive record that authorized the task, if any. */
|
|
46
|
+
ownerDirective?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface LaneReport {
|
|
50
|
+
lane: string;
|
|
51
|
+
classifier_refusals: Array<{ action: string; reason: string }>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const bullets = (items: readonly string[]): string => (items.length > 0 ? items.map((i) => `- ${i}`).join('\n') : '- none');
|
|
55
|
+
|
|
56
|
+
export function renderEnvelope(input: EnvelopeInput): string {
|
|
57
|
+
if (input.refusals.length === 0) {
|
|
58
|
+
throw new Error('an envelope needs at least one refusal — without one there is nothing to hand off');
|
|
59
|
+
}
|
|
60
|
+
const refused = input.refusals
|
|
61
|
+
.map((r) => `- ${r.lane !== undefined ? `[${r.lane}] ` : ''}${r.action} — refused: ${r.reason}`)
|
|
62
|
+
.join('\n');
|
|
63
|
+
const auth =
|
|
64
|
+
input.ownerDirective !== undefined
|
|
65
|
+
? `The repository owner directly ordered this task; the order is recorded verbatim in \`${input.ownerDirective}\`. I am the owner and I authorize the remaining steps below in this message.`
|
|
66
|
+
: 'I am the owner of this repository and I authorize the remaining steps below in this message.';
|
|
67
|
+
return [
|
|
68
|
+
'# Continuation prompt — paste into a fresh session',
|
|
69
|
+
'',
|
|
70
|
+
'## Task',
|
|
71
|
+
'',
|
|
72
|
+
input.task,
|
|
73
|
+
'',
|
|
74
|
+
'## Done',
|
|
75
|
+
'',
|
|
76
|
+
bullets(input.done),
|
|
77
|
+
'',
|
|
78
|
+
'## Refused by the host classifier',
|
|
79
|
+
'',
|
|
80
|
+
refused,
|
|
81
|
+
'',
|
|
82
|
+
'Do not retry or route around these refusals. If one recurs, stop and say so.',
|
|
83
|
+
'',
|
|
84
|
+
'## Remaining steps',
|
|
85
|
+
'',
|
|
86
|
+
input.remaining.map((s, i) => `${i + 1}. ${s}`).join('\n'),
|
|
87
|
+
'',
|
|
88
|
+
'## Owner authorization',
|
|
89
|
+
'',
|
|
90
|
+
auth,
|
|
91
|
+
'',
|
|
92
|
+
].join('\n');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function writeEnvelope(root: string, input: EnvelopeInput): string {
|
|
96
|
+
const body = renderEnvelope(input);
|
|
97
|
+
const dir = path.join(root, 'agents', 'tmp', `round-${randomBytes(4).toString('hex')}`);
|
|
98
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
99
|
+
const file = path.join(dir, 'prompt.md');
|
|
100
|
+
fs.writeFileSync(file, body, { flag: 'wx' });
|
|
101
|
+
return file;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function batchLaneRefusals(reports: readonly LaneReport[]): Refusal[] {
|
|
105
|
+
const out: Refusal[] = [];
|
|
106
|
+
for (const r of reports) {
|
|
107
|
+
if (!Array.isArray(r.classifier_refusals)) {
|
|
108
|
+
throw new Error(`lane ${r.lane} report is missing the classifier_refusals field`);
|
|
109
|
+
}
|
|
110
|
+
for (const x of r.classifier_refusals) {
|
|
111
|
+
out.push({ lane: r.lane, action: x.action, reason: x.reason });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return out;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function main(argv: readonly string[] = process.argv.slice(2)): number {
|
|
118
|
+
let root = process.cwd();
|
|
119
|
+
let input: string | undefined;
|
|
120
|
+
for (let i = 0; i < argv.length; i++) {
|
|
121
|
+
if (argv[i] === '--root') {
|
|
122
|
+
root = argv[++i] ?? root;
|
|
123
|
+
} else if (argv[i] === '--input') {
|
|
124
|
+
input = argv[++i];
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (input === undefined) {
|
|
128
|
+
process.stderr.write('usage: refusal_envelope --input <file.json> [--root DIR]\n');
|
|
129
|
+
return 2;
|
|
130
|
+
}
|
|
131
|
+
const file = writeEnvelope(root, JSON.parse(fs.readFileSync(input, 'utf8')) as EnvelopeInput);
|
|
132
|
+
process.stdout.write(`${path.relative(root, file)}\n`);
|
|
133
|
+
return 0;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (import.meta.url === pathToFileURL(process.argv[1] ?? '').href) {
|
|
137
|
+
process.exit(main());
|
|
138
|
+
}
|
|
@@ -466,20 +466,37 @@ export function local_release_gate_argv(): string[] {
|
|
|
466
466
|
* Returns `null` on any measurement failure — a shallow clone or a missing tag
|
|
467
467
|
* is an environment fact, and a release must not stop over one. `null` means
|
|
468
468
|
* the line is simply not rendered.
|
|
469
|
+
*
|
|
470
|
+
* Both ends are resolved to SHAs BEFORE measuring, and the rendered level
|
|
471
|
+
* carries them. The 16.3.0 line read `23 vs 1` while the measurer re-run on
|
|
472
|
+
* `16.2.0..16.3.0` reads `83 vs 3`: `HEAD` at write time was not the commit the
|
|
473
|
+
* tag later named, and the line recorded neither end, so nobody could say which
|
|
474
|
+
* range it had read. With both SHAs in the line, `measure_release_mix --from
|
|
475
|
+
* <from> --to <to>` reproduces it.
|
|
469
476
|
*/
|
|
470
477
|
export function measure_mix_obligation(
|
|
471
478
|
version: string,
|
|
472
479
|
fromRef?: string | null,
|
|
480
|
+
opts: { toRef?: string; cwd?: string } = {},
|
|
473
481
|
): MixObligation | null {
|
|
482
|
+
const cwd = opts.cwd ?? REPO_ROOT;
|
|
483
|
+
const toRef = opts.toRef ?? 'HEAD';
|
|
474
484
|
try {
|
|
475
|
-
const from = fromRef ?? previous_release_tag(
|
|
485
|
+
const from = fromRef ?? previous_release_tag(toRef, cwd);
|
|
476
486
|
if (!from) return null;
|
|
477
|
-
const
|
|
487
|
+
const from_sha = _resolve_commit(from, cwd);
|
|
488
|
+
const to_sha = _resolve_commit(toRef, cwd);
|
|
489
|
+
const reading = measureRange(from_sha, to_sha, loadTaxonomy(), version, cwd);
|
|
478
490
|
const o = reading.response_obligation;
|
|
479
491
|
return {
|
|
480
492
|
level:
|
|
481
493
|
`governance-only ${String(o.governance_only)} vs consumer-only ` +
|
|
482
|
-
`${String(o.consumer_only)} (taxonomy ${reading.taxonomy_version}
|
|
494
|
+
`${String(o.consumer_only)} (taxonomy ${reading.taxonomy_version}; ` +
|
|
495
|
+
`range ${from_sha.slice(0, 12)}..${to_sha.slice(0, 12)})`,
|
|
496
|
+
from_sha,
|
|
497
|
+
to_sha,
|
|
498
|
+
governance_only: o.governance_only,
|
|
499
|
+
consumer_only: o.consumer_only,
|
|
483
500
|
};
|
|
484
501
|
} catch (err) {
|
|
485
502
|
// Printed rather than swallowed. Nothing refuses over the reading any
|
|
@@ -494,6 +511,15 @@ export function measure_mix_obligation(
|
|
|
494
511
|
}
|
|
495
512
|
}
|
|
496
513
|
|
|
514
|
+
function _resolve_commit(ref: string, cwd: string): string {
|
|
515
|
+
const r = spawnSync('git', ['rev-parse', '--verify', `${ref}^{commit}`], { encoding: 'utf-8', cwd });
|
|
516
|
+
const sha = (r.stdout ?? '').trim();
|
|
517
|
+
if (r.status !== 0 || !/^[0-9a-f]{40}$/u.test(sha)) {
|
|
518
|
+
throw new Error(`cannot resolve \`${ref}\` to a commit`);
|
|
519
|
+
}
|
|
520
|
+
return sha;
|
|
521
|
+
}
|
|
522
|
+
|
|
497
523
|
/**
|
|
498
524
|
* Refuse the FIRST remote state of a release whose section is not publishable.
|
|
499
525
|
*
|