@event4u/agent-config 16.1.0 → 16.3.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 +98 -257
- package/README.md +14 -12
- package/dist/agent-src/commands/analyze/inbox.md +1 -1
- package/dist/agent-src/commands/analyze/roadmap-repos.md +1 -1
- package/dist/agent-src/commands/bug/fix.md +17 -2
- package/dist/agent-src/commands/feature/plan.md +1 -1
- package/dist/agent-src/commands/feature/roadmap.md +1 -1
- package/dist/agent-src/commands/fix/ci.md +1 -1
- package/dist/agent-src/commands/implement-ticket.md +1 -1
- package/dist/agent-src/commands/jira-ticket.md +1 -1
- package/dist/agent-src/commands/roadmap/create.md +1 -1
- package/dist/agent-src/commands/roadmap/materialize.md +1 -1
- package/dist/agent-src/commands/roadmap/process-full.md +5 -5
- package/dist/agent-src/commands/roadmap/resolve-blockers.md +361 -0
- package/dist/agent-src/commands/roadmap/triage-parked.md +325 -0
- package/dist/agent-src/commands/roadmap.md +18 -4
- package/dist/agent-src/commands/tests/create.md +17 -3
- package/dist/agent-src/commands/tests/execute.md +22 -5
- package/dist/agent-src/commands/work.md +4 -0
- package/dist/agent-src/contexts/authority/decision-revisit-gate-enforcement.md +43 -0
- package/dist/agent-src/contexts/communication/rules-auto/design-fidelity-enforcement.md +24 -0
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +6 -6
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +4 -8
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +32 -2
- package/dist/agent-src/contexts/execution/session-canary-enforcement-history.md +67 -0
- package/dist/agent-src/contexts/execution/toolchain-resolver.md +101 -7
- package/dist/agent-src/rules/active-remediation.md +1 -1
- package/dist/agent-src/rules/autonomous-execution.md +1 -0
- package/dist/agent-src/rules/broken-access-control.md +1 -0
- package/dist/agent-src/rules/command-suggestion-policy.md +1 -0
- package/dist/agent-src/rules/context-hygiene.md +1 -1
- package/dist/agent-src/rules/decision-revisit-gate.md +16 -33
- package/dist/agent-src/rules/design-fidelity.md +13 -16
- package/dist/agent-src/rules/doc-screenshot-hygiene.md +1 -0
- package/dist/agent-src/rules/domain-safety-disclaimer.md +1 -0
- package/dist/agent-src/rules/domain-safety-pii.md +1 -0
- package/dist/agent-src/rules/domain-safety-retention.md +1 -0
- package/dist/agent-src/rules/engineering-safety-floor.md +1 -0
- package/dist/agent-src/rules/evaluator-independence.md +3 -2
- package/dist/agent-src/rules/fast-path-marker-visibility.md +1 -0
- package/dist/agent-src/rules/finance-safety-floor.md +1 -0
- package/dist/agent-src/rules/git-history-discipline.md +1 -0
- package/dist/agent-src/rules/image-likeness-and-rights.md +1 -0
- package/dist/agent-src/rules/legal-safety-floor.md +3 -2
- package/dist/agent-src/rules/lethal-trifecta-guard.md +1 -0
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +1 -0
- package/dist/agent-src/rules/media-governance-routing.md +14 -17
- package/dist/agent-src/rules/persona-governance.md +2 -2
- package/dist/agent-src/rules/provider-lifecycle-discipline.md +1 -1
- package/dist/agent-src/rules/question-not-instruction.md +1 -0
- package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
- package/dist/agent-src/rules/runtime-safety.md +1 -0
- package/dist/agent-src/rules/secret-vcs-guard.md +1 -0
- package/dist/agent-src/rules/security-sensitive-stop.md +3 -2
- package/dist/agent-src/rules/session-canary.md +8 -62
- package/dist/agent-src/rules/settings-ask-protocol.md +1 -0
- package/dist/agent-src/rules/source-confidentiality.md +1 -0
- package/dist/agent-src/rules/strategy-safety-floor.md +1 -0
- package/dist/agent-src/rules/tool-safety.md +1 -0
- package/dist/agent-src/rules/ui-audit-gate.md +1 -2
- package/dist/agent-src/rules/untrusted-input-defense.md +1 -0
- package/dist/agent-src/rules/user-interrupt-priority.md +1 -0
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
- package/dist/agent-src/scripts/deferral_carry.ts +339 -0
- package/dist/agent-src/scripts/update_roadmap_progress.ts +4 -1
- package/dist/agent-src/skills/accessibility-auditor/data/aria-patterns.csv +1 -1
- package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +2 -2
- package/dist/agent-src/skills/api-design/data/manifest.json +2 -2
- package/dist/agent-src/skills/api-testing/SKILL.md +17 -0
- package/dist/agent-src/skills/code-intelligence/SKILL.md +14 -2
- package/dist/agent-src/skills/design-review/SKILL.md +30 -4
- package/dist/agent-src/skills/design-review/references/verification-automation.md +32 -0
- package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +1 -1
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +18 -3
- package/dist/agent-src/skills/existing-ui-audit/references/component-taxonomy-detection.md +56 -0
- package/dist/agent-src/skills/fe-design/SKILL.md +1 -1
- package/dist/agent-src/skills/iconography/SKILL.md +1 -1
- package/dist/agent-src/skills/js-library-packaging/SKILL.md +2 -2
- package/dist/agent-src/skills/markitdown/SKILL.md +4 -0
- package/dist/agent-src/skills/monorepo-workspace/SKILL.md +1 -1
- package/dist/agent-src/skills/playwright-testing/SKILL.md +30 -6
- package/dist/agent-src/skills/quality-tools/SKILL.md +11 -1
- package/dist/agent-src/skills/quality-tools/references/go-tools.md +76 -0
- package/dist/agent-src/skills/quality-tools/references/python-tools.md +104 -0
- package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +1 -1
- package/dist/agent-src/skills/storybook-workshop/SKILL.md +3 -3
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +1 -1
- package/dist/agent-src/skills/test-case-discovery/SKILL.md +7 -0
- package/dist/agent-src/skills/test-driven-development/SKILL.md +17 -0
- package/dist/agent-src/skills/test-performance/SKILL.md +19 -1
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +25 -2
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +30 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +10 -4
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +302 -21
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +22 -3
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +6 -1
- package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
- package/dist/agent-src/templates/scripts/work_engine/state.ts +57 -7
- package/dist/agent-src/templates/scripts/work_engine/taxonomy/detect.ts +500 -0
- package/dist/agent-src/templates/scripts/work_engine/taxonomy/place.ts +183 -0
- package/dist/cli/python/knowledge_ingest.js +1 -1
- package/dist/cli/python/workspace_drive.js +1 -1
- package/dist/cli/registry.js +1 -1
- package/dist/cli-delegate/archive_completed_roadmaps.js +92 -12
- package/dist/cli-delegate/check_update_banner.js +12 -1
- package/dist/cli-delegate/chunk-523HCFYO.js +90 -0
- package/dist/cli-delegate/{chunk-M2DPGFZ4.js → chunk-6V6TA25H.js} +22 -152
- package/dist/cli-delegate/chunk-7IQE3D5S.js +191 -0
- package/dist/cli-delegate/{chunk-6KFEC3G7.js → chunk-CQWX336L.js} +1 -1
- package/dist/cli-delegate/chunk-DEIV7XP7.js +108 -0
- package/dist/cli-delegate/chunk-EEHDXSYD.js +2040 -0
- package/dist/cli-delegate/{chunk-P6ZHP5W2.js → chunk-GKE7ZVFA.js} +4 -4
- package/dist/cli-delegate/chunk-JQOM7TTM.js +1201 -0
- package/dist/cli-delegate/{chunk-UNCRJBT3.js → chunk-JQVYKIZA.js} +41 -0
- package/dist/cli-delegate/{chunk-FC75PGJE.js → chunk-JY2I2DXV.js} +12 -1
- package/dist/cli-delegate/chunk-KB5FZ655.js +208 -0
- package/dist/cli-delegate/{chunk-YUM5KURG.js → chunk-KR6EM23A.js} +235 -1455
- package/dist/cli-delegate/{chunk-LTYVIY76.js → chunk-LIYTLH6O.js} +1 -1
- package/dist/cli-delegate/chunk-NQ7WT43P.js +2729 -0
- package/dist/cli-delegate/chunk-NXEILF2K.js +2160 -0
- package/dist/cli-delegate/{chunk-5R7HOLAF.js → chunk-NYX3L2PZ.js} +1 -1
- package/dist/cli-delegate/{chunk-4E2W63DA.js → chunk-OKJUIAPS.js} +62 -1
- package/dist/cli-delegate/{chunk-QAJS5YWY.js → chunk-PHD7OOLE.js} +2 -1
- package/dist/cli-delegate/{chunk-RGNIWTEA.js → chunk-QLDHIPWR.js} +1 -1
- package/dist/cli-delegate/{chunk-HDVVGPQW.js → chunk-RQNNW7IF.js} +1405 -567
- package/dist/cli-delegate/{chunk-S3VFXMTM.js → chunk-S4UMZNES.js} +1 -1
- package/dist/cli-delegate/{chunk-6KM6ORRY.js → chunk-S4YWNRKO.js} +24 -8
- package/dist/cli-delegate/{chunk-GJCBB2UG.js → chunk-TRI6DQZ6.js} +3054 -325
- package/dist/cli-delegate/chunk-ULQRUR23.js +208 -0
- package/dist/cli-delegate/{chunk-NUHLI2RX.js → chunk-YCU3TIXH.js} +2 -0
- package/dist/cli-delegate/chunk-ZBZV2G5R.js +210 -0
- package/dist/cli-delegate/{chunk-WGXTVKCQ.js → chunk-ZUZKZYCN.js} +5 -3
- package/dist/cli-delegate/cmd_analyze_session.js +1 -1
- package/dist/cli-delegate/cmd_brand_status.js +1 -1
- package/dist/cli-delegate/cmd_conformance.js +1862 -809
- package/dist/cli-delegate/cmd_doctor.js +13 -6
- package/dist/cli-delegate/cmd_doctor_neighbours.js +23 -0
- package/dist/cli-delegate/cmd_explain.js +5 -5
- package/dist/cli-delegate/cmd_export.js +11 -8
- package/dist/cli-delegate/cmd_fleet.js +3 -3
- package/dist/cli-delegate/cmd_handoff.js +10 -7
- package/dist/cli-delegate/cmd_mcp_available.js +1 -1
- package/dist/cli-delegate/cmd_memory_get.js +3 -1
- package/dist/cli-delegate/cmd_migrate.js +2 -2
- package/dist/cli-delegate/cmd_packs_active.js +3 -3
- package/dist/cli-delegate/cmd_preflight.js +6 -6
- package/dist/cli-delegate/cmd_prune.js +11 -8
- package/dist/cli-delegate/cmd_refresh.js +2 -1
- package/dist/cli-delegate/cmd_route_audit.js +8 -6
- package/dist/cli-delegate/cmd_route_explain.js +4 -4
- package/dist/cli-delegate/cmd_session_recycle.js +4 -3
- package/dist/cli-delegate/cmd_settings_get.js +1 -1
- package/dist/cli-delegate/cmd_settings_migrate.js +11 -8
- package/dist/cli-delegate/cmd_settings_set.js +4 -4
- package/dist/cli-delegate/cmd_sync.js +11 -8
- package/dist/cli-delegate/cmd_uninstall.js +11 -8
- package/dist/cli-delegate/cmd_update.js +1 -1
- package/dist/cli-delegate/cmd_upgrade.js +3 -2
- package/dist/cli-delegate/cmd_validate.js +11 -8
- package/dist/cli-delegate/cmd_versions.js +1 -1
- package/dist/cli-delegate/deferral_carry.js +16 -0
- package/dist/cli-delegate/gate_execute.js +2 -2
- package/dist/cli-delegate/roadmap_gates.js +5 -5
- package/dist/cli-delegate/update_roadmap_progress.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +132 -80
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +7 -5
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +6 -4
- package/dist/hooks/dispatch.js +7972 -5186
- package/dist/hooks/dispatch.sha256 +1 -0
- package/dist/install/claudePathsPlan.js +47 -6
- package/dist/install/claudeRuleRewrite.js +7 -0
- package/dist/install/emit_host_rules_cli.js +39 -36
- package/dist/install/globalRuleScope.js +87 -0
- package/dist/install/host_rule_ownership.js +160 -0
- package/dist/install/install.mjs +2226 -1055
- package/dist/install/installThinLayer.js +261 -0
- package/dist/install/installedRuleLinks.js +176 -0
- package/dist/install/wizard-plan.js +24 -0
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +40913 -34865
- package/dist/scripts/_lib/agent_settings.js +11 -0
- package/dist/scripts/_lib/claude_settings_hooks.js +10 -8
- package/dist/scripts/_lib/installed_layer.js +378 -0
- package/dist/scripts/_lib/lean_projection_mode.js +218 -15
- package/dist/scripts/_lib/rule_consequence_class.js +45 -0
- package/dist/scripts/_lib/rule_injection.js +67 -10
- package/dist/scripts/_lib/rule_law_section.js +122 -0
- package/dist/scripts/_lib/thin_rules.js +458 -0
- package/dist/scripts/_lib/windsurf_render.js +60 -0
- package/dist/scripts/condense.js +14 -26
- package/dist/scripts/project_thin_rules.js +14 -294
- package/dist/server/schemas/settings.js +29 -0
- package/dist/shared/skillRanking.js +74 -13
- package/dist/ui/assets/index-Cwq4d0hX.js +23 -0
- package/dist/ui/assets/index-Cyjy8bWO.css +1 -0
- package/dist/ui/index.html +2 -2
- package/docs/contracts/settings-classes.md +10 -6
- package/package.json +4 -4
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
- package/src/agent-src/scripts/deferral_carry.ts +339 -0
- package/src/agent-src/scripts/update_roadmap_progress.ts +4 -1
- package/src/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +10 -4
- package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +302 -21
- package/src/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +22 -3
- package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +6 -1
- package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
- package/src/agent-src/templates/scripts/work_engine/state.ts +57 -7
- package/src/agent-src/templates/scripts/work_engine/taxonomy/detect.ts +500 -0
- package/src/agent-src/templates/scripts/work_engine/taxonomy/place.ts +183 -0
- package/src/config/agent-settings.template.yml +91 -22
- package/src/config/ci-local-parity.yml +18 -0
- package/src/config/continuity-surface.json +9 -2
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +327 -3
- package/src/config/gate-violation-baselines.json +21 -9
- package/src/config/hook-bundle-budget.json +25 -0
- package/src/config/hook-latency-budget.json +21 -0
- package/src/config/hook-token-budget.json +8 -3
- package/src/config/host-instruction-limits.json +33 -0
- package/src/config/metric-registry.yml +114 -0
- package/src/config/placeholder-drift-budget.json +10 -0
- package/src/config/routing-coverage-seed.json +38 -3
- package/src/config/rule-activation-census.json +7 -3
- package/src/config/rule-consequence-class.json +161 -0
- package/src/config/rule-law-ceilings.json +99 -0
- package/src/install/claudePathsPlan.ts +46 -4
- package/src/install/claudeRuleRewrite.ts +10 -1
- package/src/install/emit_host_rules_cli.ts +43 -34
- package/src/install/globalRuleScope.ts +109 -0
- package/src/install/host_rule_ownership.ts +170 -0
- package/src/install/installThinLayer.ts +312 -0
- package/src/install/installedRuleLinks.ts +220 -0
- package/src/install/wizard-plan.ts +24 -0
- package/src/scripts/_cli/cmd_doctor.ts +28 -90
- package/src/scripts/_cli/cmd_doctor_neighbours.ts +293 -0
- package/src/scripts/_cli/doctor_execution.ts +100 -17
- package/src/scripts/_cli/doctor_network_posture.ts +226 -0
- package/src/scripts/_dispatch.bash +16 -2
- package/src/scripts/_lib/agent_settings.ts +11 -0
- package/src/scripts/_lib/body_portable.ts +102 -0
- package/src/scripts/_lib/cc_transcript.ts +132 -1
- package/src/scripts/_lib/claude_settings_hooks.ts +10 -8
- package/src/scripts/_lib/concern_sla_window.ts +200 -0
- package/src/scripts/_lib/estate_offsets.ts +241 -0
- package/src/scripts/_lib/exemption_shape.ts +143 -0
- package/src/scripts/_lib/fnv.ts +23 -0
- package/src/scripts/_lib/foreign_scan.ts +106 -0
- package/src/scripts/_lib/forge_protection.ts +114 -0
- package/src/scripts/_lib/forge_reader.ts +558 -0
- package/src/scripts/_lib/gitignore_block.ts +314 -0
- package/src/scripts/_lib/global_deploy_inventory.ts +32 -0
- package/src/scripts/_lib/graph_feeder_record.ts +214 -0
- package/src/scripts/_lib/hook_settings.ts +73 -0
- package/src/scripts/_lib/host_capability.ts +40 -19
- package/src/scripts/_lib/host_env_write.ts +111 -0
- package/src/scripts/_lib/host_hook_merge.ts +165 -0
- package/src/scripts/_lib/installed_layer.ts +538 -0
- package/src/scripts/_lib/json_merge.ts +82 -0
- package/src/scripts/_lib/json_pointers.ts +93 -11
- package/src/scripts/_lib/lean_projection_mode.ts +275 -15
- package/src/scripts/_lib/llm_proposer_transport.ts +14 -4
- package/src/scripts/_lib/machine_wake.ts +16 -3
- package/src/scripts/_lib/neighbour_census.ts +760 -0
- package/src/scripts/_lib/neighbour_scan.ts +122 -0
- package/src/scripts/_lib/neighbour_tool_use.ts +189 -0
- package/src/scripts/_lib/obligations.ts +119 -8
- package/src/scripts/_lib/probe_inputs.ts +271 -0
- package/src/scripts/_lib/prompt_shape.ts +46 -0
- package/src/scripts/_lib/read_surface_scan.ts +322 -0
- package/src/scripts/_lib/release_highlights.ts +2 -1
- package/src/scripts/_lib/release_migration_gate.ts +19 -3
- package/src/scripts/_lib/reserved_name_sweep.ts +73 -0
- package/src/scripts/_lib/retrieval_sanitize.ts +77 -16
- package/src/scripts/_lib/review_coverage.ts +134 -0
- package/src/scripts/_lib/rule_consequence_class.ts +71 -0
- package/src/scripts/_lib/rule_injection.ts +130 -10
- package/src/scripts/_lib/rule_law_section.ts +147 -0
- package/src/scripts/_lib/rule_layer_overlap.ts +58 -0
- package/src/scripts/_lib/shell_write_shapes.ts +108 -0
- package/src/scripts/_lib/skill_origin.ts +254 -0
- package/src/scripts/_lib/structural_hiding.ts +622 -0
- package/src/scripts/_lib/structured_ask.ts +64 -21
- package/src/scripts/_lib/thin_rules.ts +540 -0
- package/src/scripts/_lib/touched_file_quality.ts +434 -0
- package/src/scripts/_lib/turn_end_refusals.ts +600 -4
- package/src/scripts/_lib/turn_end_transcript.ts +216 -0
- package/src/scripts/_lib/verification_command.ts +324 -0
- package/src/scripts/_lib/verification_evidence.ts +647 -0
- package/src/scripts/_lib/verify_clause.ts +280 -0
- package/src/scripts/_lib/windsurf_render.ts +63 -0
- package/src/scripts/ai_council/cli_call_budget.ts +13 -5
- package/src/scripts/ai_council/clients.ts +26 -57
- package/src/scripts/ai_council/config.ts +1 -1
- package/src/scripts/ai_council/vendor_defaults.ts +45 -0
- package/src/scripts/ai_team/team_dispatch.ts +4 -0
- package/src/scripts/audit_skill_overlap.ts +261 -0
- package/src/scripts/before_complete_hook.ts +573 -25
- package/src/scripts/bench_hook_latency.ts +412 -5
- package/src/scripts/bench_touched_file_quality.ts +238 -0
- package/src/scripts/cache_realization_report.ts +61 -1
- package/src/scripts/check_argument_hint.ts +287 -0
- package/src/scripts/check_claims.ts +125 -1
- package/src/scripts/check_enforcement_coverage.ts +38 -9
- package/src/scripts/check_enforcement_matrix.ts +621 -22
- package/src/scripts/check_estate_count.ts +130 -153
- package/src/scripts/check_finding_dispositions.ts +138 -7
- package/src/scripts/check_generator_sync.ts +71 -0
- package/src/scripts/check_hook_bundle_composition.ts +370 -0
- package/src/scripts/check_host_docs_digest.ts +786 -0
- package/src/scripts/check_host_format_column.ts +559 -0
- package/src/scripts/check_input_references.ts +228 -0
- package/src/scripts/check_inputs_parity.ts +235 -0
- package/src/scripts/check_kernel_edit_ratified.ts +89 -9
- package/src/scripts/check_kill_switch_table.ts +294 -0
- package/src/scripts/check_memory.ts +7 -1
- package/src/scripts/check_placeholder_drift.ts +221 -0
- package/src/scripts/check_read_surface_coverage.ts +515 -0
- package/src/scripts/check_release_highlights.ts +10 -0
- package/src/scripts/check_release_holds.ts +2 -1
- package/src/scripts/check_release_pr_shape.ts +38 -15
- package/src/scripts/check_routing_coverage.ts +378 -11
- package/src/scripts/check_standing_rule_delivery.ts +33 -13
- package/src/scripts/check_static_parity.ts +17 -0
- package/src/scripts/check_verify_expectation_delta.ts +521 -0
- package/src/scripts/ci_settle.ts +145 -19
- package/src/scripts/closure_scan.ts +115 -1
- package/src/scripts/code_graph/detect.ts +127 -7
- package/src/scripts/code_graph/foreign.ts +194 -0
- package/src/scripts/code_graph/query.ts +217 -4
- package/src/scripts/code_graph/types.ts +26 -2
- package/src/scripts/code_graph/validate.ts +3 -1
- package/src/scripts/code_graph/verbs.ts +103 -0
- package/src/scripts/compile_hook_manifest.ts +90 -14
- package/src/scripts/condense.ts +14 -27
- package/src/scripts/estate_exemption_shape.ts +202 -0
- package/src/scripts/external_sources_denylist.json +29 -4
- package/src/scripts/generate_host_cost_table.ts +1 -1
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +192 -14
- package/src/scripts/hooks/block_config_weakening.ts +294 -4
- package/src/scripts/hooks/block_kernel_rule_writes.ts +9 -78
- package/src/scripts/hooks/block_plumbing_writes.ts +342 -0
- package/src/scripts/hooks/bundle_integrity.ts +291 -0
- package/src/scripts/hooks/chain_nudge_hook.ts +1 -2
- package/src/scripts/hooks/code_graph_context_hook.ts +253 -25
- package/src/scripts/hooks/comment_discipline_hook.ts +1 -3
- package/src/scripts/hooks/concern_failure_policy.ts +280 -0
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/concern_timings.ts +94 -0
- package/src/scripts/hooks/delegation_nudge_hook.ts +1 -2
- package/src/scripts/hooks/design_pass_hook.ts +100 -9
- package/src/scripts/hooks/design_slop_hook.ts +1 -2
- package/src/scripts/hooks/dispatch_hook.ts +77 -71
- package/src/scripts/hooks/edit_shape_hook.ts +1 -2
- package/src/scripts/hooks/end_review_nudge_hook.ts +1 -1
- package/src/scripts/hooks/evidence_independence.ts +1 -2
- package/src/scripts/hooks/exit_codes.ts +129 -0
- package/src/scripts/hooks/host_lowering.json +1 -0
- package/src/scripts/hooks/host_lowering.ts +146 -3
- package/src/scripts/hooks/host_lowering.yaml +262 -46
- package/src/scripts/hooks/host_semantics.ts +30 -2
- package/src/scripts/hooks/injection_budget.ts +9 -2
- package/src/scripts/hooks/interruption_ledger_hook.ts +1 -2
- package/src/scripts/hooks/journal_record_hook.ts +1 -2
- package/src/scripts/hooks/memory_recall_hook.ts +1 -2
- package/src/scripts/hooks/obligation_settle_hook.ts +151 -5
- package/src/scripts/hooks/one_question_per_ask_hook.ts +43 -6
- package/src/scripts/hooks/orchestration_record_hook.ts +1 -2
- package/src/scripts/hooks/payload_stub.ts +10 -1
- package/src/scripts/hooks/permission_gate.ts +1 -2
- package/src/scripts/hooks/push_settle_hook.ts +1 -3
- package/src/scripts/hooks/replay_hook.ts +2 -1
- package/src/scripts/hooks/reread_guard_hook.ts +1 -2
- package/src/scripts/hooks/review_baseline_hook.ts +1 -2
- package/src/scripts/hooks/rtk_wrap_hook.ts +1 -2
- package/src/scripts/hooks/rule_inject_hook.ts +765 -68
- package/src/scripts/hooks/run_continuation_hook.ts +13 -15
- package/src/scripts/hooks/skill_route_hook.ts +1 -2
- package/src/scripts/hooks/source_first_gate_hook.ts +1 -2
- package/src/scripts/hooks/spawn_guard_shadow_hook.ts +1 -2
- package/src/scripts/hooks/subagent_ledger_hook.ts +1 -2
- package/src/scripts/hooks/suggestion_capture_hook.ts +1 -1
- package/src/scripts/hooks/table_fingerprint.ts +70 -0
- package/src/scripts/hooks/telemetry_flush_hook.ts +1 -2
- package/src/scripts/hooks/telemetry_usage_hook.ts +65 -10
- package/src/scripts/hooks/tool_result_bytes_hook.ts +93 -9
- package/src/scripts/hooks/turn_end_gate_hook.ts +421 -324
- package/src/scripts/hooks/ui_route_nudge_hook.ts +1 -2
- package/src/scripts/hooks_status.ts +112 -0
- package/src/scripts/injection_scan_hook.ts +7 -0
- package/src/scripts/install.ts +75 -189
- package/src/scripts/installed_layer_report.ts +103 -0
- package/src/scripts/language_mirror_hook.ts +15 -6
- package/src/scripts/learning_sidecar.ts +119 -8
- package/src/scripts/lint_deny_text.ts +419 -0
- package/src/scripts/lint_exit_codes.ts +262 -0
- package/src/scripts/lint_hook_manifest.ts +108 -0
- package/src/scripts/lint_major_migration_sections.ts +156 -26
- package/src/scripts/lint_pack_boundaries.ts +63 -5
- package/src/scripts/lint_roadmap_blockers.ts +78 -12
- package/src/scripts/lint_rule_law_section.ts +517 -0
- package/src/scripts/lint_skill_descriptions.ts +1 -1
- package/src/scripts/lint_skill_scripts_readonly.ts +1 -1
- package/src/scripts/lint_workflow_security.ts +161 -5
- package/src/scripts/mcp_server/consumer_tool_catalog.json +53 -0
- package/src/scripts/mcp_server/graph_tools.ts +72 -3
- package/src/scripts/mcp_server/prompts.ts +142 -1
- package/src/scripts/measure_routing_signal.ts +54 -16
- package/src/scripts/measure_skill_ranker_baseline.ts +515 -53
- package/src/scripts/measure_turn_end_gate.ts +193 -0
- package/src/scripts/memory_learn_hook.ts +91 -6
- package/src/scripts/memory_lookup.ts +1 -1
- package/src/scripts/model_rule_injection.ts +52 -5
- package/src/scripts/prepack-check.mjs +53 -0
- package/src/scripts/project_thin_rules.ts +34 -327
- package/src/scripts/release_publication.ts +13 -1
- package/src/scripts/report_evidence_temperature.ts +657 -0
- package/src/scripts/report_installed_rule_links.ts +157 -0
- package/src/scripts/report_invocation_surface.ts +383 -0
- package/src/scripts/report_label_agreement.ts +233 -0
- package/src/scripts/report_obligation_carriers.ts +699 -0
- package/src/scripts/report_obligation_mechanism.ts +230 -0
- package/src/scripts/report_obligation_writer_split.ts +236 -0
- package/src/scripts/report_single_token_triggers.ts +277 -0
- package/src/scripts/report_skill_menu_census.ts +208 -0
- package/src/scripts/report_skill_ranker_confusion.ts +442 -0
- package/src/scripts/report_standing_payload_by_host.ts +188 -15
- package/src/scripts/report_verification_record_coverage.ts +306 -0
- package/src/scripts/roadmap_verify_share.ts +213 -0
- package/src/scripts/rule_activation_census.ts +5 -2
- package/src/scripts/rule_trigger_eval.ts +9 -9
- package/src/scripts/schemas/command.schema.json +44 -0
- package/src/scripts/schemas/review-findings.schema.json +7 -2
- package/src/scripts/schemas/rule.schema.json +5 -0
- package/src/scripts/schemas/skill.schema.json +44 -0
- package/src/scripts/self_review_gate.ts +421 -17
- package/src/scripts/semantic_parity_census.ts +314 -0
- package/src/scripts/session_eol_report.ts +54 -1
- package/src/scripts/skill_tools/score_skill_relevance.ts +290 -25
- package/src/scripts/sweep_dead_scan_roots.ts +1 -1
- package/src/scripts/sweep_skill_ranker_signals.ts +129 -0
- package/src/scripts/sync_gitignore.ts +29 -235
- package/src/scripts/trigger_eval_grandfather.json +0 -7
- package/src/scripts/trigger_eval_rotation.ts +122 -27
- package/src/scripts/ui_conformance_probe.ts +156 -4
- package/src/scripts/update_prices.ts +85 -3
- package/src/scripts/write_bundle_digest.mjs +74 -0
- package/src/server/schemas/settings.ts +41 -0
- package/src/shared/skillRanking.ts +117 -11
- package/src/templates/consumer-settings/ONBOARDING.md +1 -0
- package/dist/cli-delegate/chunk-FXYUYU4N.js +0 -4416
- package/dist/cli-delegate/chunk-QJWAUMJW.js +0 -1072
- package/dist/cli-delegate/chunk-YDPILCOL.js +0 -152
- package/dist/ui/assets/index-DH1xc62v.js +0 -29
- package/dist/ui/assets/index-jSfMW8_t.css +0 -1
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a CHANGE touches the roadmap estate — the diff half, read once.
|
|
3
|
+
*
|
|
4
|
+
* `check_estate_count` answers two different questions with two different
|
|
5
|
+
* inputs. The count half reads the TREE and ratchets it against the base ref's
|
|
6
|
+
* tree. This module is the other half: it reads the DIFF and says what the
|
|
7
|
+
* change did — which roadmaps entered the active top level, which left it, which
|
|
8
|
+
* of the arrivals declared an exemption, and what that exemption says.
|
|
9
|
+
*
|
|
10
|
+
* WHY IT LIVES HERE AND NOT IN THE GATE. `check_source_size_budget` scores
|
|
11
|
+
* `Σ max(0, lines(f) − 1500)` over `src/**` and the gate crossed the ceiling
|
|
12
|
+
* when the exemption-shape work landed. That gate does not object to new code;
|
|
13
|
+
* it objects to new code in the file that is already too big to read, and the
|
|
14
|
+
* ratchet was right about which file that was. The seam it forced is the one a
|
|
15
|
+
* reader would draw anyway — tree-reading on one side of it, diff-reading on the
|
|
16
|
+
* other — so the extraction is a correction rather than a concession.
|
|
17
|
+
*
|
|
18
|
+
* `exemptionReason` sits here rather than beside the vocabulary it feeds
|
|
19
|
+
* (`exemption_shape.ts`) because this is the module that READS a change; that
|
|
20
|
+
* one is the module that JUDGES a reason. The split is read-then-judge, and
|
|
21
|
+
* keeping it means the vocabulary module imports no filesystem and no git.
|
|
22
|
+
*/
|
|
23
|
+
import * as path from 'node:path';
|
|
24
|
+
|
|
25
|
+
import {
|
|
26
|
+
is_roadmap_candidate as isRoadmapCandidate,
|
|
27
|
+
parse_frontmatter as parseFrontmatter,
|
|
28
|
+
} from '../../agent-src/scripts/update_roadmap_progress.js';
|
|
29
|
+
|
|
30
|
+
/** How a change touched the active roadmap tree, as git reports it. */
|
|
31
|
+
export interface OffsetLedger {
|
|
32
|
+
/** Files that entered the active top level: new files, and un-parked ones. */
|
|
33
|
+
added: string[];
|
|
34
|
+
/** Files that left it: deleted, archived, parked or merged away. */
|
|
35
|
+
offsets: string[];
|
|
36
|
+
/** Added files carrying an `estate_offset_exempt:` reason, with the reason. */
|
|
37
|
+
exempt: Array<{ file: string; reason: string }>;
|
|
38
|
+
/**
|
|
39
|
+
* The subset of `offsets` that went to `later/`.
|
|
40
|
+
*
|
|
41
|
+
* Tracked separately because parking is the one offset that RAISES another
|
|
42
|
+
* gated count: active falls by one and later rises by one, which under an
|
|
43
|
+
* exact floor is growth in `later_roadmaps` unless this allowance exists.
|
|
44
|
+
* Kept out of a general "any offset raises any allowance" rule on purpose —
|
|
45
|
+
* an archived roadmap must not buy a new `later/` file.
|
|
46
|
+
*/
|
|
47
|
+
parked: string[];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** An `estate_growth_exempt:` reason ADDED to a roadmap in this change. */
|
|
51
|
+
export interface GrowthClaim {
|
|
52
|
+
/** The roadmap the claim was added to, as git reports the path. */
|
|
53
|
+
file: string;
|
|
54
|
+
reason: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** `agents/roadmaps/<name>.md` — the active top level. code-comment-allow provenance-comment -- operand, not provenance */
|
|
58
|
+
function isActiveTopLevel(rel: string): boolean {
|
|
59
|
+
const norm = rel.split(path.sep).join('/');
|
|
60
|
+
if (!norm.startsWith('agents/roadmaps/') || !norm.endsWith('.md')) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
const tail = norm.slice('agents/roadmaps/'.length);
|
|
64
|
+
return !tail.includes('/') && isRoadmapCandidate(norm);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* A disposition directory — where an offset sends a roadmap.
|
|
69
|
+
*
|
|
70
|
+
* `stubs/` is in the set, and it was missing from the first version. Un-stubbing
|
|
71
|
+
* is the documented promotion path, so a stub moved to the top level is an
|
|
72
|
+
* ADDITION that T3 must charge, and a roadmap demoted to a stub is an offset.
|
|
73
|
+
* With `stubs/` unrecognised, a promotion was classified as neither and the lint
|
|
74
|
+
* could never charge it — the one hole that let an active roadmap arrive for free.
|
|
75
|
+
*/
|
|
76
|
+
function isDisposed(rel: string): boolean {
|
|
77
|
+
const norm = rel.split(path.sep).join('/');
|
|
78
|
+
return /^agents\/roadmaps\/(archive|later|skipped|stubs)\//.test(norm);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** A roadmap parked for later — the one disposition that grows another count. */
|
|
82
|
+
function isParked(rel: string): boolean {
|
|
83
|
+
return rel.split(path.sep).join('/').startsWith('agents/roadmaps/later/');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Read the exemption reason a newly added roadmap declares, if any.
|
|
88
|
+
*
|
|
89
|
+
* The key lives in the file's own frontmatter rather than in a config or a
|
|
90
|
+
* commit trailer, for the reason `RATCHET_RESET_KEY` gives for living inside the
|
|
91
|
+
* baseline JSON: the claim then shows up in the diff of the change that makes
|
|
92
|
+
* it, and a reviewer sees it without being told to look.
|
|
93
|
+
*
|
|
94
|
+
* THE BLOCK SCALAR IS READ HERE AND NOT BY `parseFrontmatter`, which is a flat
|
|
95
|
+
* line parser with no YAML block support: it returns the value as everything
|
|
96
|
+
* after the first colon. Measured 2026-10-01 across the three roadmap trees,
|
|
97
|
+
* **38 of 221 exemptions are written `estate_offset_exempt: >-` with the reason
|
|
98
|
+
* indented beneath**, and for every one of them this function used to return
|
|
99
|
+
* the literal two-character string `>-`. That is non-empty, so the gate
|
|
100
|
+
* accepted it — a key whose whole purpose is that a reviewer sees the claim was
|
|
101
|
+
* being checked against a YAML punctuation mark on one file in six. The fix
|
|
102
|
+
* belongs here rather than in the shared parser because every other caller of
|
|
103
|
+
* that parser reads single-token values (`status`, `complexity`) where block
|
|
104
|
+
* support buys nothing and a rewrite risks the dashboard.
|
|
105
|
+
*/
|
|
106
|
+
export function exemptionReason(text: string): string | null {
|
|
107
|
+
const block = blockScalar(text, 'estate_offset_exempt');
|
|
108
|
+
if (block !== null) return block === '' ? null : block;
|
|
109
|
+
const fm = parseFrontmatter(text);
|
|
110
|
+
const raw = (fm as Record<string, unknown>)['estate_offset_exempt'];
|
|
111
|
+
if (typeof raw !== 'string') {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
const reason = raw.trim().replace(/^["']|["']$/g, '').trim();
|
|
115
|
+
return reason === '' ? null : reason;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* The folded body of `<key>: >-` / `<key>: |`, or `null` when not that form.
|
|
120
|
+
*
|
|
121
|
+
* Returns `''` — not `null` — for a block header with no body, so the caller can
|
|
122
|
+
* tell "declared and empty" from "not a block scalar". An empty block is the
|
|
123
|
+
* blank-reason case the key already refuses, and collapsing it into `null` here
|
|
124
|
+
* would send it back to the flat parser, which would hand back `>-` and accept it.
|
|
125
|
+
*/
|
|
126
|
+
function blockScalar(text: string, key: string): string | null {
|
|
127
|
+
const m = /^---\r?\n([\s\S]*?)\r?\n---/.exec(text);
|
|
128
|
+
if (m === null) return null;
|
|
129
|
+
const lines = (m[1] as string).split(/\r?\n/);
|
|
130
|
+
const head = new RegExp(`^${key}:[ \\t]*(.*)$`);
|
|
131
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
132
|
+
const hm = head.exec(lines[i] as string);
|
|
133
|
+
if (hm === null) continue;
|
|
134
|
+
// Only the block indicators. A quoted or bare value is the flat form and
|
|
135
|
+
// stays with the flat parser, which already handles it.
|
|
136
|
+
//
|
|
137
|
+
// THE TRAILING COMMENT IS PART OF THE HEADER, and omitting it was a
|
|
138
|
+
// BYPASS rather than a parse gap. `estate_offset_exempt: >- # offset`
|
|
139
|
+
// failed this test, fell through to the flat parser, and came back as
|
|
140
|
+
// the string `">- # offset"` — which the shape rule then searched for a
|
|
141
|
+
// disposition word and found one, IN THE COMMENT, over a body it never
|
|
142
|
+
// read. The indicator may also be written `>2-` as well as `>-2`, so
|
|
143
|
+
// both orders are accepted; an indentation indicator is never `0`.
|
|
144
|
+
if (!/^[>|](?:[1-9][-+]?|[-+]?[1-9]?)(?:[ \t]+#.*)?$/.test((hm[1] as string).trim())) return null;
|
|
145
|
+
const body: string[] = [];
|
|
146
|
+
for (let j = i + 1; j < lines.length; j += 1) {
|
|
147
|
+
const line = lines[j] as string;
|
|
148
|
+
if (line.trim() === '') continue;
|
|
149
|
+
// The first unindented line ends the block — the next key.
|
|
150
|
+
if (!/^[ \t]/.test(line)) break;
|
|
151
|
+
body.push(line.trim());
|
|
152
|
+
}
|
|
153
|
+
return body.join(' ').replace(/\s+/g, ' ').trim();
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Classify the change's effect on the active roadmap tree.
|
|
160
|
+
*
|
|
161
|
+
* Renames carry information a name-only diff loses: `road-to-x.md` →
|
|
162
|
+
* `archive/road-to-x.md` is the wanted direction and counts as an offset, while
|
|
163
|
+
* `later/road-to-x.md` → `road-to-x.md` is an un-parking and counts as an
|
|
164
|
+
* addition. A top-level-to-top-level rename is neither.
|
|
165
|
+
*/
|
|
166
|
+
export function classifyDiff(
|
|
167
|
+
nameStatus: string,
|
|
168
|
+
readFile: (rel: string) => string | null,
|
|
169
|
+
): OffsetLedger {
|
|
170
|
+
const added: string[] = [];
|
|
171
|
+
const offsets: string[] = [];
|
|
172
|
+
const exempt: Array<{ file: string; reason: string }> = [];
|
|
173
|
+
const parked: string[] = [];
|
|
174
|
+
for (const line of nameStatus.split('\n')) {
|
|
175
|
+
if (line.trim() === '') continue;
|
|
176
|
+
const cols = line.split('\t');
|
|
177
|
+
const status = (cols[0] ?? '').trim();
|
|
178
|
+
if (status.startsWith('R') || status.startsWith('C')) {
|
|
179
|
+
const from = cols[1] ?? '';
|
|
180
|
+
const to = cols[2] ?? '';
|
|
181
|
+
if (isActiveTopLevel(from) && isDisposed(to)) {
|
|
182
|
+
offsets.push(from);
|
|
183
|
+
if (isParked(to)) parked.push(to);
|
|
184
|
+
} else if (isDisposed(from) && isActiveTopLevel(to)) {
|
|
185
|
+
added.push(to);
|
|
186
|
+
}
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
const file = cols[1] ?? '';
|
|
190
|
+
if (!isActiveTopLevel(file)) continue;
|
|
191
|
+
if (status === 'A') {
|
|
192
|
+
added.push(file);
|
|
193
|
+
} else if (status === 'D') {
|
|
194
|
+
offsets.push(file);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
for (const file of added) {
|
|
198
|
+
const text = readFile(file);
|
|
199
|
+
if (text === null) continue;
|
|
200
|
+
const reason = exemptionReason(text);
|
|
201
|
+
if (reason !== null) {
|
|
202
|
+
exempt.push({ file, reason });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return { added, offsets, exempt, parked };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* The `estate_growth_exempt:` reasons this change ADDS, read from the patch.
|
|
210
|
+
*
|
|
211
|
+
* Read from the diff rather than from the file, and that is the point: a claim
|
|
212
|
+
* sitting in a roadmap authorises nothing on a later change, so an exemption
|
|
213
|
+
* cannot be banked the way surplus in a stored baseline could. It also means a
|
|
214
|
+
* newly added roadmap and an edited one need no separate handling — in a
|
|
215
|
+
* `base...HEAD` patch both arrive as `+` lines.
|
|
216
|
+
*
|
|
217
|
+
* `--unified=0` keeps context lines out, so a claim that merely sits NEAR an
|
|
218
|
+
* edited line is not read as added. Deliberately tolerant of leading whitespace
|
|
219
|
+
* and of quoted values, matching `exemptionReason`; deliberately NOT tolerant of
|
|
220
|
+
* an empty reason, because an exemption whose reason is blank is the silent
|
|
221
|
+
* exception the key exists to replace.
|
|
222
|
+
*/
|
|
223
|
+
export function growthClaims(patch: string): GrowthClaim[] {
|
|
224
|
+
const out: GrowthClaim[] = [];
|
|
225
|
+
let file = '';
|
|
226
|
+
for (const line of patch.split('\n')) {
|
|
227
|
+
// `+++ b/<path>` names the file the following `+` lines belong to. The
|
|
228
|
+
// `/dev/null` form is a deletion, which cannot carry a claim.
|
|
229
|
+
const head = /^\+\+\+ b\/(.+)$/.exec(line);
|
|
230
|
+
if (head !== null) {
|
|
231
|
+
file = (head[1] ?? '').trim();
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
if (!line.startsWith('+') || line.startsWith('+++')) continue;
|
|
235
|
+
const m = /^\+\s*estate_growth_exempt:\s*(.+?)\s*$/.exec(line);
|
|
236
|
+
if (m === null) continue;
|
|
237
|
+
const reason = (m[1] ?? '').trim().replace(/^["']|["']$/g, '').trim();
|
|
238
|
+
if (reason !== '') out.push({ file, reason });
|
|
239
|
+
}
|
|
240
|
+
return out;
|
|
241
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What an `estate_offset_exempt` reason has to SAY — one vocabulary, two readers.
|
|
3
|
+
*
|
|
4
|
+
* THE DEFECT THIS EXISTS TO NAME. The one-in-one-out rule charges every added
|
|
5
|
+
* active roadmap against a disposed one, and `estate_offset_exempt: <reason>`
|
|
6
|
+
* is the escape hatch that costs "one reviewable line instead of a silent
|
|
7
|
+
* exception". `exemptionReason` accepted any non-empty string, so the line was
|
|
8
|
+
* reviewable in the sense that it existed. Measured 2026-10-01 over the active,
|
|
9
|
+
* `later/` and `archive/` trees: 221 files carry the key, and 43 of them name
|
|
10
|
+
* no alternative disposition at all under the three-lemma set the roadmap named
|
|
11
|
+
* from memory, and 6 under the measured one below — including three that say only
|
|
12
|
+
* `lane N of <parent>`. The escape hatch was free.
|
|
13
|
+
*
|
|
14
|
+
* WHAT A SHAPED REASON SAYS. It names at least one disposition the author
|
|
15
|
+
* considered instead of adding a file: archiving something, parking it in
|
|
16
|
+
* `later/`, merging into an existing roadmap, or any of the words this tree
|
|
17
|
+
* actually uses for those three. The requirement is deliberately NOT "explain
|
|
18
|
+
* yourself well" — that is unjudgeable — but "name what you rejected", which is
|
|
19
|
+
* a word that is either present or absent.
|
|
20
|
+
*
|
|
21
|
+
* WHY THE VOCABULARY IS MEASURED AND NOT CHOSEN. The commissioning roadmap
|
|
22
|
+
* named three lemmas, archive / park / merge, from memory. Over the real
|
|
23
|
+
* population those three cover 178 of 221; the measured ten below cover 215.
|
|
24
|
+
* The 37-file gap is not boilerplate — "Offsetting it individually is not
|
|
25
|
+
* possible without splitting the set" and "no completed roadmap to retire
|
|
26
|
+
* against this addition" both name a rejected alternative in words the
|
|
27
|
+
* three-lemma set does not carry. A refusal vocabulary that reds one added
|
|
28
|
+
* roadmap in five on the house style gets weakened until it finds nothing, so
|
|
29
|
+
* the set here is the one the tree writes. Every number above carries its
|
|
30
|
+
* producing command: `./scripts-run src/scripts/estate_exemption_shape`.
|
|
31
|
+
*
|
|
32
|
+
* `close` is excluded on purpose, and it is the most common verb in these
|
|
33
|
+
* reasons: it almost always refers to closing WORK, not to disposing of a file,
|
|
34
|
+
* so accepting it would make the check pass on a sentence that named nothing.
|
|
35
|
+
*
|
|
36
|
+
* WHAT THIS DOES NOT DO, stated because a reviewer called it HIGH and the
|
|
37
|
+
* disagreement is worth recording rather than resolving silently. The cheapest
|
|
38
|
+
* string that passes is the single word `park`, and `park 1` / `park 2` are two
|
|
39
|
+
* distinct reasons to the duplicate rule. So this verifies that a disposition
|
|
40
|
+
* word APPEARS; it does not verify that the author thought about one, and no
|
|
41
|
+
* check can. The claim the gate's message makes is therefore "name what you
|
|
42
|
+
* rejected", which is what a word either does or does not do — not "explain
|
|
43
|
+
* yourself well", which is unjudgeable. A reason gamed down to one word is
|
|
44
|
+
* visible to a human reviewer in the diff, which is where the key's own stated
|
|
45
|
+
* purpose puts the real control; what this removes is the case where there was
|
|
46
|
+
* nothing to look at because the reason was free text nobody had read.
|
|
47
|
+
*
|
|
48
|
+
* WHY ONE MODULE. Two readers consume this — the estate gate, which refuses,
|
|
49
|
+
* and the measurement script, which reports. A second copy of the lemma list is
|
|
50
|
+
* how a gate and its own evidence drift apart, and a drifted vocabulary fails
|
|
51
|
+
* silently: the report says the tree conforms while the gate refuses it.
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The dispositions a reason may name, as source strings.
|
|
56
|
+
*
|
|
57
|
+
* Exported individually rather than as one baked regex so the measurement
|
|
58
|
+
* script can report per-lemma counts against the same list the gate refuses on.
|
|
59
|
+
*/
|
|
60
|
+
export const DISPOSITION_LEMMAS: readonly { readonly name: string; readonly source: string }[] = [
|
|
61
|
+
{ name: 'archive', source: String.raw`archiv\w*` },
|
|
62
|
+
// `park` is the one stem with a common false friend, and a reviewer named
|
|
63
|
+
// it: `park\w*` matches `parkour` at a word boundary, so a reason saying
|
|
64
|
+
// nothing about dispositions passes on a word that is not one. Enumerated
|
|
65
|
+
// instead of stemmed — the inflections this tree writes, and no more. Every
|
|
66
|
+
// other lemma keeps its stem; none of them has a false friend in English
|
|
67
|
+
// that could plausibly appear in a sentence about roadmap dispositions.
|
|
68
|
+
{ name: 'park', source: String.raw`unpark(?:ed|ing|s)?\b|park(?:ed|ing|s)?\b` },
|
|
69
|
+
{ name: 'merge', source: String.raw`merg\w*` },
|
|
70
|
+
{ name: 'later', source: String.raw`later\/` },
|
|
71
|
+
{ name: 'offset', source: String.raw`offset\w*` },
|
|
72
|
+
{ name: 'defer', source: String.raw`defer\w*` },
|
|
73
|
+
{ name: 'fold', source: String.raw`fold\w*` },
|
|
74
|
+
{ name: 'consolidate', source: String.raw`consolidat\w*` },
|
|
75
|
+
{ name: 'absorb', source: String.raw`absorb\w*` },
|
|
76
|
+
{ name: 'retire', source: String.raw`retir\w*` },
|
|
77
|
+
];
|
|
78
|
+
|
|
79
|
+
/** The whole vocabulary as one alternation — the gate's own test. */
|
|
80
|
+
export const DISPOSITION_SOURCE = `\\b(?:${DISPOSITION_LEMMAS.map((l) => l.source).join('|')})`;
|
|
81
|
+
|
|
82
|
+
const DISPOSITION_RE = new RegExp(DISPOSITION_SOURCE, 'i');
|
|
83
|
+
|
|
84
|
+
/** Does this reason name at least one rejected alternative? */
|
|
85
|
+
export function namesDisposition(reason: string): boolean {
|
|
86
|
+
return DISPOSITION_RE.test(reason);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Which lemmas a reason names, for the reader's per-file column. */
|
|
90
|
+
export function lemmasNamed(reason: string): string[] {
|
|
91
|
+
return DISPOSITION_LEMMAS.filter((l) => new RegExp(`\\b(?:${l.source})`, 'i').test(reason)).map((l) => l.name);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* The comparison key for "two added files say the same thing".
|
|
96
|
+
*
|
|
97
|
+
* Case and whitespace are folded because a reason pasted into a second file and
|
|
98
|
+
* re-wrapped by an editor is the same reason. Nothing else is folded: a reason
|
|
99
|
+
* that differs by one clause is a different reason, and a normaliser clever
|
|
100
|
+
* enough to call those equal would start refusing reasons that genuinely differ.
|
|
101
|
+
*/
|
|
102
|
+
export function reasonKey(reason: string): string {
|
|
103
|
+
return reason.toLowerCase().replace(/\s+/g, ' ').trim();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** One added file whose exemption reason does not hold up. */
|
|
107
|
+
export interface ExemptionFinding {
|
|
108
|
+
readonly file: string;
|
|
109
|
+
readonly kind: 'shapeless' | 'duplicate';
|
|
110
|
+
/** For `duplicate`, the other added file carrying the same reason. */
|
|
111
|
+
readonly twin: string | null;
|
|
112
|
+
readonly reason: string;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Judge the exemptions a single change ADDS — never the ones already in the tree.
|
|
117
|
+
*
|
|
118
|
+
* Grandfathering is load-bearing rather than polite. 43 of the 221 existing
|
|
119
|
+
* reasons name no disposition; re-reading them would land this check red on a
|
|
120
|
+
* fifth of the corpus, which is a backlog wearing a control's clothes. The
|
|
121
|
+
* input is `classifyDiff`'s exempt ledger, which by construction lists only the
|
|
122
|
+
* files this change added.
|
|
123
|
+
*/
|
|
124
|
+
export function exemptionFindings(
|
|
125
|
+
exempt: readonly { readonly file: string; readonly reason: string }[],
|
|
126
|
+
): ExemptionFinding[] {
|
|
127
|
+
const out: ExemptionFinding[] = [];
|
|
128
|
+
const seen = new Map<string, string>();
|
|
129
|
+
for (const e of exempt) {
|
|
130
|
+
if (!namesDisposition(e.reason)) {
|
|
131
|
+
out.push({ file: e.file, kind: 'shapeless', twin: null, reason: e.reason });
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
const key = reasonKey(e.reason);
|
|
135
|
+
const twin = seen.get(key);
|
|
136
|
+
if (twin === undefined) {
|
|
137
|
+
seen.set(key, e.file);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
out.push({ file: e.file, kind: 'duplicate', twin, reason: e.reason });
|
|
141
|
+
}
|
|
142
|
+
return out;
|
|
143
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FNV-1a, 32-bit — the one definition in this tree.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from `rule_trigger_eval.ts`, which still re-exports it under its
|
|
5
|
+
* own name so its suite keeps importing the symbol it always did. The reason
|
|
6
|
+
* for the extraction is the reason this file carries a doc block at all: a
|
|
7
|
+
* second consumer arrived (`measure_skill_ranker_baseline`'s held-out
|
|
8
|
+
* partition), and two copies of a hash that decides which rows a measurement
|
|
9
|
+
* reads is the shape in which a partition quietly stops being the same
|
|
10
|
+
* partition. One definition, two callers.
|
|
11
|
+
*
|
|
12
|
+
* Pure — no imports, no I/O, no clock.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** FNV-1a over UTF-16 code units, returned as an unsigned 32-bit integer. */
|
|
16
|
+
export function fnv1a(s: string): number {
|
|
17
|
+
let h = 0x811c9dc5;
|
|
18
|
+
for (let i = 0; i < s.length; i += 1) {
|
|
19
|
+
h ^= s.charCodeAt(i);
|
|
20
|
+
h = Math.imul(h, 0x01000193) >>> 0;
|
|
21
|
+
}
|
|
22
|
+
return h >>> 0;
|
|
23
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The unclaimed-file scan under this package's own deploy roots.
|
|
3
|
+
*
|
|
4
|
+
* Moved verbatim out of `src/scripts/_cli/cmd_doctor.ts`
|
|
5
|
+
* (road-to-a-tree-that-keeps-its-neighbours Phase 2.6). The behaviour is
|
|
6
|
+
* unchanged — this is a module boundary, not a rewrite.
|
|
7
|
+
*
|
|
8
|
+
* Two reasons it earns its own file. `cmd_doctor.ts` is 2,100 lines above the
|
|
9
|
+
* `check_source_size_budget` ceiling, so the census line that now links this
|
|
10
|
+
* listing is paid for by a MOVE rather than by raising the tree-wide excess.
|
|
11
|
+
* And the neighbour census answers a strictly larger question than this scan
|
|
12
|
+
* does — this one lists FILES under paths this package deploys to, the census
|
|
13
|
+
* lists ARTEFACTS wherever a host keeps them — so the two belong beside each
|
|
14
|
+
* other rather than nested inside a doctor renderer.
|
|
15
|
+
*
|
|
16
|
+
* What this scan does NOT do, stated because the two listings look alike: it
|
|
17
|
+
* never leaves a deploy root, so a neighbour's skill in `~/.claude/skills` or
|
|
18
|
+
* hook entry in `.cursor/hooks.json` is invisible to it. That gap is the
|
|
19
|
+
* census's subject, and the census links back here rather than repeating the
|
|
20
|
+
* paths this one already prints.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import * as fs from 'node:fs';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* `Path.rglob("*")` — every descendant path (dirs + files), recursively.
|
|
27
|
+
*
|
|
28
|
+
* Order is not relied upon by callers (they sort the matched set), but the
|
|
29
|
+
* walk is deterministic (sorted per directory) to keep behaviour stable.
|
|
30
|
+
*/
|
|
31
|
+
export function rglob(root: string, isDir: (p: string) => boolean, join: (a: string, b: string) => string): string[] {
|
|
32
|
+
const out: string[] = [];
|
|
33
|
+
const walk = (dir: string): void => {
|
|
34
|
+
let entries: fs.Dirent[];
|
|
35
|
+
try {
|
|
36
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
37
|
+
} catch {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
entries.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
41
|
+
for (const ent of entries) {
|
|
42
|
+
const full = join(dir, ent.name);
|
|
43
|
+
out.push(full);
|
|
44
|
+
let dirLike = ent.isDirectory();
|
|
45
|
+
if (ent.isSymbolicLink()) {
|
|
46
|
+
// pathlib rglob follows into symlinked dirs.
|
|
47
|
+
dirLike = isDir(full);
|
|
48
|
+
}
|
|
49
|
+
if (dirLike) {
|
|
50
|
+
walk(full);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
walk(root);
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface ForeignScanDeps {
|
|
59
|
+
pathExists: (p: string) => boolean;
|
|
60
|
+
isDir: (p: string) => boolean;
|
|
61
|
+
isFile: (p: string) => boolean;
|
|
62
|
+
resolvePath: (p: string) => string;
|
|
63
|
+
join: (a: string, b: string) => string;
|
|
64
|
+
/** Resolve one declared deploy root against the consumer root. */
|
|
65
|
+
resolveRoot: (projectRoot: string, rel: string) => string;
|
|
66
|
+
defaultRoots: readonly string[];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Walk every declared deploy root and surface unclaimed files. Only regular
|
|
71
|
+
* files under `deploy_roots` count; bookkeeping is on the resolved final path.
|
|
72
|
+
*/
|
|
73
|
+
export function scanForeign(
|
|
74
|
+
projectRoot: string,
|
|
75
|
+
manifest: Record<string, unknown>,
|
|
76
|
+
known: Set<string>,
|
|
77
|
+
deps: ForeignScanDeps,
|
|
78
|
+
): string[] {
|
|
79
|
+
const roots = (manifest['deploy_roots'] as unknown[] | undefined) || Array.from(deps.defaultRoots);
|
|
80
|
+
const foreign: string[] = [];
|
|
81
|
+
const seen = new Set<string>();
|
|
82
|
+
for (const root_rel of roots) {
|
|
83
|
+
const root = deps.resolveRoot(projectRoot, String(root_rel));
|
|
84
|
+
if (!deps.pathExists(root) || !deps.isDir(root)) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
for (const child of rglob(root, deps.isDir, deps.join)) {
|
|
88
|
+
if (!deps.isFile(child)) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
let resolved: string;
|
|
92
|
+
try {
|
|
93
|
+
resolved = deps.resolvePath(child);
|
|
94
|
+
} catch {
|
|
95
|
+
resolved = child;
|
|
96
|
+
}
|
|
97
|
+
if (known.has(resolved) || seen.has(resolved)) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
seen.add(resolved);
|
|
101
|
+
foreign.push(child);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
foreign.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
105
|
+
return foreign;
|
|
106
|
+
}
|
|
@@ -73,6 +73,120 @@ export interface ForgeReading {
|
|
|
73
73
|
readonly deployRestricted: boolean | null;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
/**
|
|
77
|
+
* The all-null reading: nothing was queried.
|
|
78
|
+
*
|
|
79
|
+
* Lives here, beside {@link ForgeReading}, rather than in the `doctor` caller
|
|
80
|
+
* that first needed it — `_lib/forge_reader.ts` returns it on every failure
|
|
81
|
+
* path, and a second hand-written all-null literal is exactly the drift that
|
|
82
|
+
* makes "offline output is unchanged" an assertion instead of a fact.
|
|
83
|
+
*
|
|
84
|
+
* It MOVED from `_cli/doctor_execution.ts`, which no longer exports it in any
|
|
85
|
+
* form. Nothing broke, because nothing outside that file imported it — but an
|
|
86
|
+
* earlier draft of this comment claimed a re-export kept every caller in place,
|
|
87
|
+
* and no such shim was ever written. Corrected rather than quietly deleted: a
|
|
88
|
+
* comment describing a compatibility layer that does not exist is the next
|
|
89
|
+
* reader's false premise.
|
|
90
|
+
*/
|
|
91
|
+
export const UNREAD_FORGE: ForgeReading = {
|
|
92
|
+
rulesets: null,
|
|
93
|
+
defaultBranch: null,
|
|
94
|
+
allowAutoMerge: null,
|
|
95
|
+
deployRestricted: null,
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The two fields of an environment this row reads, as
|
|
100
|
+
* `GET repos/{owner}/{repo}/environments` returns them.
|
|
101
|
+
*
|
|
102
|
+
* A NARROW PROJECTION, not the full payload: the real response also carries
|
|
103
|
+
* `id`, `protection_rules`, `can_admins_bypass`, timestamps and more. Declared
|
|
104
|
+
* this way on purpose — a caller passes the real object and structural typing
|
|
105
|
+
* accepts the superset, while the interface states exactly which fields this
|
|
106
|
+
* decision depends on. Calling it "the shape" would overstate it.
|
|
107
|
+
*
|
|
108
|
+
* `null` is GitHub's encoding for *no restriction at all* — every branch may
|
|
109
|
+
* deploy. It is therefore the one shape that refutes the row.
|
|
110
|
+
*/
|
|
111
|
+
export interface EnvironmentPolicy {
|
|
112
|
+
readonly name: string;
|
|
113
|
+
readonly deployment_branch_policy: {
|
|
114
|
+
readonly protected_branches?: boolean;
|
|
115
|
+
readonly custom_branch_policies?: boolean;
|
|
116
|
+
} | null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Derive `deployRestricted` from the environments payload.
|
|
121
|
+
*
|
|
122
|
+
* **Both restriction mechanisms count, and reading only one is the defect this
|
|
123
|
+
* function exists to close.** GitHub restricts deployment branches two ways:
|
|
124
|
+
* `protected_branches` (whatever the forge currently treats as protected) and
|
|
125
|
+
* `custom_branch_policies` (an explicit named list). A checker that reads only
|
|
126
|
+
* the first reports "accepts a deployment from any branch" for an environment
|
|
127
|
+
* pinned to exactly one named branch — which is the opposite of what the
|
|
128
|
+
* payload says, and is precisely the misreading recorded against this
|
|
129
|
+
* repository on 2026-09-13: `github-pages` carried
|
|
130
|
+
* `custom_branch_policies: true` with a single policy, `main`, and was written
|
|
131
|
+
* up as unrestricted because only `protected_branches` was consulted.
|
|
132
|
+
*
|
|
133
|
+
* The named-list mechanism is also the STRICTER of the two here, which is why
|
|
134
|
+
* the row is satisfied without changing the forge: `protected_branches` widens
|
|
135
|
+
* with the protected set, while a custom list names one branch and stays there.
|
|
136
|
+
* On a ruleset-protected repository it is additionally the safer mechanism —
|
|
137
|
+
* `protected_branches` resolves against a notion of protection whose classic
|
|
138
|
+
* endpoint 404s here (see the module header), so switching to it would trade a
|
|
139
|
+
* precise restriction for one whose evaluation is exactly the ambiguity the
|
|
140
|
+
* `forge-protection-settings` re-scope forbids relying on.
|
|
141
|
+
*
|
|
142
|
+
* **An empty environment set returns `null`, not `true`.** The first draft
|
|
143
|
+
* returned `true` on the reasoning that with no environment there is no
|
|
144
|
+
* deployment surface to leave open. That is sound about a *confirmed* empty
|
|
145
|
+
* set and wrong about the value actually reaching this function: an empty
|
|
146
|
+
* array is what a failed fetch, a truncated page, or a caller that never
|
|
147
|
+
* queried also produces, and collapsing those into `satisfied` is exactly the
|
|
148
|
+
* quiet false-positive the three-state row exists to prevent. `null` maps to
|
|
149
|
+
* `unread`, which is the state this module already reserves for a value nobody
|
|
150
|
+
* established. A caller that has genuinely confirmed zero environments can say
|
|
151
|
+
* so by passing `true` itself; it cannot be inferred from the array alone.
|
|
152
|
+
*
|
|
153
|
+
* **Wildcard patterns.** A custom policy's NAMES live behind a second call
|
|
154
|
+
* (`GET .../environments/{name}/deployment-branch-policies`) and accept globs,
|
|
155
|
+
* so `custom_branch_policies: true` alone cannot distinguish a policy pinned to
|
|
156
|
+
* `main` from one whose pattern is `*`. Pass `patternsByEnv` when those names
|
|
157
|
+
* have been read: an environment whose patterns admit everything is reported
|
|
158
|
+
* unrestricted. Omit it and the flag is trusted — the narrower guarantee was
|
|
159
|
+
* not checked, which is stated here rather than left for a reader to discover.
|
|
160
|
+
*
|
|
161
|
+
* **A confirmed-EMPTY pattern list also yields `false`, and it is NOT the same
|
|
162
|
+
* case as a wildcard.** With `custom_branch_policies: true` and zero named
|
|
163
|
+
* patterns nothing matches, so nothing can deploy — strictly the most
|
|
164
|
+
* restrictive posture there is, and the exact opposite of `*`. Both land on
|
|
165
|
+
* `false` deliberately, because this row feeds an ACTION line rather than a
|
|
166
|
+
* permission: an environment configured to accept no deployment at all is a
|
|
167
|
+
* misconfiguration worth a human look, and `false` surfaces it where `true`
|
|
168
|
+
* would silently bless it. The direction is the safe one — it can under-report
|
|
169
|
+
* satisfaction, never over-report it. Written down because the two states are
|
|
170
|
+
* genuinely opposite, and a reader deriving the behaviour from the expression
|
|
171
|
+
* alone would reasonably take it for a bug.
|
|
172
|
+
*/
|
|
173
|
+
export function deployRestrictedFrom(
|
|
174
|
+
environments: readonly EnvironmentPolicy[],
|
|
175
|
+
patternsByEnv?: Readonly<Record<string, readonly string[]>>,
|
|
176
|
+
): boolean | null {
|
|
177
|
+
if (environments.length === 0) return null;
|
|
178
|
+
return environments.every((env) => {
|
|
179
|
+
const policy = env.deployment_branch_policy;
|
|
180
|
+
if (policy === null || policy === undefined) return false;
|
|
181
|
+
if (policy.protected_branches === true) return true;
|
|
182
|
+
if (policy.custom_branch_policies !== true) return false;
|
|
183
|
+
const patterns = patternsByEnv?.[env.name];
|
|
184
|
+
if (patterns === undefined) return true;
|
|
185
|
+
// A policy admitting every ref restricts nothing, whatever the flag says.
|
|
186
|
+
return patterns.length > 0 && !patterns.some((p) => p === '*' || p === '**');
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
76
190
|
const SOURCE = {
|
|
77
191
|
rulesets: 'GET repos/{owner}/{repo}/rulesets + GET .../rulesets/{id}',
|
|
78
192
|
repo: 'GET repos/{owner}/{repo} (allow_auto_merge)',
|