@event4u/agent-config 16.5.0 → 17.0.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 +2 -2
- package/.claude-plugin/skills/install-agent-config/SKILL.md +4 -4
- package/CHANGELOG.md +463 -498
- package/CONTRIBUTING.md +47 -0
- package/README.md +25 -25
- package/dist/agent-src/commands/{design.md → agent-design.md} +10 -6
- package/dist/agent-src/commands/agents/init.md +66 -3
- package/dist/agent-src/commands/agents/user/init.md +3 -0
- package/dist/agent-src/commands/{optimize/deep.md → analyze/and-optimize.md} +72 -33
- package/dist/agent-src/commands/analyze/inbox.md +168 -37
- package/dist/agent-src/commands/analyze/pr.md +144 -0
- package/dist/agent-src/commands/analyze/{repo.md → reference.md} +85 -14
- package/dist/agent-src/commands/analyze/roadmap-repos.md +19 -10
- package/dist/agent-src/commands/analyze.md +28 -12
- package/dist/agent-src/commands/audit.md +115 -0
- package/dist/agent-src/commands/brand/review.md +13 -2
- package/dist/agent-src/commands/brand/tokens.md +3 -3
- package/dist/agent-src/commands/brand/voice.md +8 -5
- package/dist/agent-src/commands/brand.md +2 -2
- package/dist/agent-src/commands/challenge-me/closure.md +25 -0
- package/dist/agent-src/commands/design-system/import.md +8 -3
- package/dist/agent-src/commands/design-system/sync.md +98 -0
- package/dist/agent-src/commands/design-system.md +6 -1
- package/dist/agent-src/commands/evals/analyze.json +44 -0
- package/dist/agent-src/commands/evals/audit.json +12 -0
- package/dist/agent-src/commands/evals/retro.json +12 -0
- package/dist/agent-src/commands/fix/ci.md +10 -8
- package/dist/agent-src/commands/ghostwriter/write.md +22 -0
- package/dist/agent-src/commands/memory/learn-low-impact.md +70 -83
- package/dist/agent-src/commands/memory/propose.md +12 -0
- package/dist/agent-src/commands/memory.md +1 -1
- package/dist/agent-src/commands/optimize.md +4 -3
- package/dist/agent-src/commands/post-as/me.md +18 -0
- package/dist/agent-src/commands/pr/create.md +17 -342
- package/dist/agent-src/commands/pr/merge.md +129 -368
- package/dist/agent-src/commands/retro.md +121 -0
- package/dist/agent-src/commands/review/routing.md +1 -1
- package/dist/agent-src/commands/roadmap/next.md +4 -1
- package/dist/agent-src/commands/roadmap/process-full.md +46 -333
- package/dist/agent-src/commands/roadmap/triage-parked.md +6 -2
- package/dist/agent-src/commands/team-knowledge/consolidate.md +2 -2
- package/dist/agent-src/commands/team-knowledge.md +1 -1
- package/dist/agent-src/commands/threat-model.md +1 -1
- package/dist/agent-src/commands/upstream-contribute.md +91 -101
- package/dist/agent-src/commands/worktree/cleanup.md +18 -11
- package/dist/agent-src/contexts/contracts/consumer-agents-md-guide.md +54 -0
- package/dist/agent-src/contexts/execution/analysis-loop.md +137 -0
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +3 -3
- package/dist/agent-src/contexts/execution/decision-closure-execution.md +1 -1
- package/dist/agent-src/contexts/execution/host-capability-manifest.md +6 -0
- package/dist/agent-src/contexts/execution/orchestration-telemetry.md +11 -4
- package/dist/agent-src/contexts/execution/pr-create-branches-content.md +250 -0
- package/dist/agent-src/contexts/execution/pr-create-branches-freshness.md +150 -0
- package/dist/agent-src/contexts/execution/pr-merge-queue.md +287 -0
- package/dist/agent-src/contexts/execution/pr-merge-sync.md +276 -0
- package/dist/agent-src/contexts/execution/pr-merge-trust-boundary.md +69 -0
- package/dist/agent-src/contexts/execution/process-full-all.md +233 -0
- package/dist/agent-src/contexts/execution/process-full-delivery.md +231 -0
- package/dist/agent-src/contexts/execution/roadmap-execution-contract-branches.md +42 -0
- package/dist/agent-src/contexts/execution/roadmap-execution-contract.md +1 -35
- package/dist/agent-src/contexts/execution/roadmap-process-loop-close.md +235 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop-prescan.md +216 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop-run.md +253 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop-set.md +212 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +25 -864
- package/dist/agent-src/contexts/execution/subagent-spawn-contract.md +14 -2
- package/dist/agent-src/contexts/execution/subagent-steering.md +65 -8
- package/dist/agent-src/contexts/model-recommendations.md +5 -5
- package/dist/agent-src/contexts/subagent-configuration.md +1 -1
- package/dist/agent-src/guidelines/agent-infra/api-cost-levers.md +4 -3
- package/dist/agent-src/guidelines/agent-infra/model-recommendation.md +11 -5
- package/dist/agent-src/guidelines/agent-infra/rule-body-migration-inventory.md +1 -1
- package/dist/agent-src/guidelines/agent-infra/self-improvement-pipeline.md +47 -24
- package/dist/agent-src/guidelines/design-antipatterns.md +5 -0
- package/dist/agent-src/guidelines/design-asset-discipline.md +17 -0
- package/dist/agent-src/guidelines/design-fidelity-routing.md +1 -0
- package/dist/agent-src/guidelines/php/api-design.md +10 -1
- package/dist/agent-src/rules/brand-source-of-truth.md +7 -6
- package/dist/agent-src/rules/code-provenance.md +1 -1
- package/dist/agent-src/rules/context-hygiene.md +0 -1
- package/dist/agent-src/rules/design-fidelity.md +12 -13
- package/dist/agent-src/rules/external-reference-deep-dive.md +2 -2
- package/dist/agent-src/rules/fix-what-you-see.md +1 -1
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +14 -15
- package/dist/agent-src/rules/missing-skill-recovery.md +12 -11
- package/dist/agent-src/rules/neighbour-precedence.md +1 -1
- package/dist/agent-src/rules/recurring-criticism.md +1 -1
- package/dist/agent-src/rules/roadmap-ci-steps-policy.md +0 -2
- package/dist/agent-src/rules/self-repair-loop.md +2 -2
- package/dist/agent-src/rules/token-budget-discipline.md +1 -1
- package/dist/agent-src/scripts/dashboard_mode.ts +4 -1
- package/dist/agent-src/scripts/roadmap_age.ts +175 -0
- package/dist/agent-src/scripts/update_roadmap_progress.ts +10 -2
- package/dist/agent-src/skills/accessibility-auditor/SKILL.md +3 -3
- package/dist/agent-src/skills/agent-security-review/SKILL.md +2 -2
- package/dist/agent-src/skills/agents-md-thin-root/SKILL.md +12 -4
- package/dist/agent-src/skills/ai-code-blindspots/SKILL.md +7 -0
- package/dist/agent-src/skills/ai-council/references/advanced-modes.md +11 -1
- package/dist/agent-src/skills/ai-council/references/cost-and-redaction.md +7 -0
- package/dist/agent-src/skills/ai-council/references/execution-modes.md +7 -0
- package/dist/agent-src/skills/ai-council/references/output-and-synthesis.md +19 -0
- package/dist/agent-src/skills/ai-council/references/procedure.md +7 -0
- package/dist/agent-src/skills/api-design/SKILL.md +2 -2
- package/dist/agent-src/skills/api-endpoint/SKILL.md +2 -2
- package/dist/agent-src/skills/authz-review/SKILL.md +5 -3
- package/dist/agent-src/skills/blade-ui/SKILL.md +2 -2
- package/dist/agent-src/skills/brand/SKILL.md +7 -3
- package/dist/agent-src/skills/brand-asset-generation/SKILL.md +13 -6
- package/dist/agent-src/skills/brand-audit/SKILL.md +2 -1
- package/dist/agent-src/skills/brand-identity/SKILL.md +5 -4
- package/dist/agent-src/skills/brand-strategy/SKILL.md +5 -4
- package/dist/agent-src/skills/brand-to-tokens/SKILL.md +18 -39
- package/dist/agent-src/skills/brand-to-tokens/templates/marp-brand-deck.md.example +2 -2
- package/dist/agent-src/skills/brand-to-tokens/templates/reveal-brand-deck.yaml +2 -2
- package/dist/agent-src/skills/canvas-design/SKILL.md +12 -2
- package/dist/agent-src/skills/competitive-positioning/SKILL.md +2 -2
- package/dist/agent-src/skills/composer-packages/SKILL.md +18 -0
- package/dist/agent-src/skills/condense-memory/SKILL.md +1 -1
- package/dist/agent-src/skills/content-funnel-design/SKILL.md +8 -1
- package/dist/agent-src/skills/context-authoring/SKILL.md +1 -1
- package/dist/agent-src/skills/context-document/SKILL.md +2 -2
- package/dist/agent-src/skills/corpus-grounding/SKILL.md +6 -6
- package/dist/agent-src/skills/corpus-grounding/scripts/decision_engine.ts +13 -11
- package/dist/agent-src/skills/corpus-grounding/scripts/ground.mjs +1706 -0
- package/dist/agent-src/skills/corpus-grounding/scripts/schema_validator.ts +7 -1
- package/dist/agent-src/skills/dashboard-design/SKILL.md +1 -1
- package/dist/agent-src/skills/data-flow-mapper/SKILL.md +5 -2
- package/dist/agent-src/skills/database/SKILL.md +5 -4
- package/dist/agent-src/skills/decision-record/references/weighted-matrix.md +12 -0
- package/dist/agent-src/skills/deep-reading-analyst/SKILL.md +1 -1
- package/dist/agent-src/skills/dependency-upgrade/SKILL.md +61 -11
- package/dist/agent-src/skills/description-assist/SKILL.md +1 -1
- package/dist/agent-src/skills/design-intelligence/SKILL.md +1 -1
- package/dist/agent-src/skills/design-intelligence/data/landing.csv +1 -1
- package/dist/agent-src/skills/design-intelligence/references/context-and-registers.md +10 -2
- package/dist/agent-src/skills/design-intelligence/references/design-languages.md +1 -1
- package/dist/agent-src/skills/design-intelligence/references/design-rules-checklist.md +4 -3
- package/dist/agent-src/skills/design-intelligence/references/integration-mapping.md +14 -14
- package/dist/agent-src/skills/{wireframe → design-review}/references/story-beat-ledger.schema.json +1 -1
- package/dist/agent-src/skills/design-review/references/verification-automation.md +11 -3
- package/dist/agent-src/skills/design-system-capture/SKILL.md +15 -10
- package/dist/agent-src/skills/design-system-capture/references/design-system-json.md +20 -5
- package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +2 -2
- package/dist/agent-src/skills/design-tokens/SKILL.md +23 -23
- package/dist/agent-src/skills/design-tokens/scripts/tokens.mjs +1037 -0
- package/dist/agent-src/skills/design-tokens/scripts/tokens.ts +336 -13
- package/dist/agent-src/skills/design-tokens/templates/design-tokens-starter.json +52 -53
- package/dist/agent-src/skills/docker/SKILL.md +1 -1
- package/dist/agent-src/skills/estimate-ticket/SKILL.md +1 -1
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +14 -276
- package/dist/agent-src/skills/existing-ui-audit/procedure.yaml +44 -0
- package/dist/agent-src/skills/existing-ui-audit/references/anti-slop-cross-reference.md +1 -1
- package/dist/agent-src/skills/existing-ui-audit/references/steps/00-inspect-stack-and-input.md +4 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/01-enumerate-components.md +26 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/01b-detect-component-taxonomy.md +7 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/02-identify-design-system.md +12 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/03-detect-design-tokens.md +35 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/04-detect-shadcn-inventory.md +13 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/04b-live-storybook-read.md +26 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/05-list-reusable-patterns.md +14 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/06-match-candidates.md +52 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/07-greenfield-branch.md +29 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/08-a11y-baseline.md +40 -0
- package/dist/agent-src/skills/existing-ui-audit/references/steps/09-validate-and-write.md +5 -0
- package/dist/agent-src/skills/experiment-loop/SKILL.md +1 -1
- package/dist/agent-src/skills/fe-design/references/design-patterns.md +16 -2
- package/dist/agent-src/skills/fe-design/references/design-read-and-memory.md +1 -1
- package/dist/agent-src/skills/fe-design/references/source-led-port.md +1 -1
- package/dist/agent-src/skills/finishing-a-development-branch/SKILL.md +6 -6
- package/dist/agent-src/skills/flux/SKILL.md +1 -1
- package/dist/agent-src/skills/form-handler/SKILL.md +15 -2
- package/dist/agent-src/skills/git-workflow/SKILL.md +2 -2
- package/dist/agent-src/skills/git-workflow/references/branch-update.md +7 -0
- package/dist/agent-src/skills/git-workflow/references/commit-subject.md +12 -0
- package/dist/agent-src/skills/git-workflow/references/push-closes-its-loop.md +10 -0
- package/dist/agent-src/skills/gtm-launch/SKILL.md +8 -1
- package/dist/agent-src/skills/html-deck/SKILL.md +7 -2
- package/dist/agent-src/skills/humanizer/SKILL.md +16 -3
- package/dist/agent-src/skills/humanizer/references/anti-aiisms.md +13 -1
- package/dist/agent-src/skills/humanizer/references/fixtures.md +8 -0
- package/dist/agent-src/skills/js-library-packaging/SKILL.md +5 -4
- package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.mjs +197 -0
- package/dist/agent-src/skills/judge-artifact-completeness/SKILL.md +1 -1
- package/dist/agent-src/skills/judge-security-auditor/SKILL.md +2 -2
- package/dist/agent-src/skills/launch-readiness/SKILL.md +18 -22
- package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +5 -5
- package/dist/agent-src/skills/livewire/SKILL.md +1 -1
- package/dist/agent-src/skills/llm-provider-knowledge/SKILL.md +18 -0
- package/dist/agent-src/skills/logo-generation/SKILL.md +9 -3
- package/dist/agent-src/skills/market-entry-analysis/SKILL.md +6 -1
- package/dist/agent-src/skills/markitdown/SKILL.md +1 -1
- package/dist/agent-src/skills/memory-consolidation/SKILL.md +2 -2
- package/dist/agent-src/skills/messaging-architecture/SKILL.md +8 -1
- package/dist/agent-src/skills/motion-choreographer/SKILL.md +2 -2
- package/dist/agent-src/skills/playwright-testing/SKILL.md +2 -0
- package/dist/agent-src/skills/positioning-strategy/SKILL.md +10 -2
- package/dist/agent-src/skills/prediction-pool-optimizer/references/ev-fixtures.md +13 -0
- package/dist/agent-src/skills/prediction-pool-optimizer/references/odds-and-bonus.md +7 -0
- package/dist/agent-src/skills/project-analysis-core/SKILL.md +1 -1
- package/dist/agent-src/skills/project-analysis-hypothesis-driven/SKILL.md +1 -1
- package/dist/agent-src/skills/project-analyzer/SKILL.md +14 -75
- package/dist/agent-src/skills/project-analyzer/procedure.yaml +39 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/01-project-overview.md +9 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/02-architecture.md +7 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/03-data-layer.md +6 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/04-business-domains.md +7 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/05-api-surface.md +6 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/06-service-map.md +6 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/07-module-inventory.md +6 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/08-infrastructure-and-testing.md +5 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/09-agent-docs-audit.md +6 -0
- package/dist/agent-src/skills/project-analyzer/references/steps/10-gap-analysis.md +6 -0
- package/dist/agent-src/skills/quality-tools/references/js-ts-tools.md +10 -0
- package/dist/agent-src/skills/quality-tools/references/php-tools.md +13 -0
- package/dist/agent-src/skills/quality-tools/references/python-tools.md +11 -0
- package/dist/agent-src/skills/react-native-setup/SKILL.md +7 -2
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +5 -1
- package/dist/agent-src/skills/react-shadcn-ui/references/registry.md +13 -0
- package/dist/agent-src/skills/react-shadcn-ui/scripts/shadcn_add.mjs +315 -0
- package/dist/agent-src/skills/react-shadcn-ui/scripts/shadcn_add.ts +6 -6
- package/dist/agent-src/skills/receiving-code-review/SKILL.md +1 -1
- package/dist/agent-src/skills/refine-ticket/SKILL.md +2 -2
- package/dist/agent-src/skills/release-comms/SKILL.md +2 -1
- package/dist/agent-src/skills/repomix-packer/SKILL.md +2 -2
- package/dist/agent-src/skills/requesting-code-review/SKILL.md +3 -3
- package/dist/agent-src/skills/roadmap-management/references/archival.md +3 -3
- package/dist/agent-src/skills/roadmap-management/references/authoring.md +9 -2
- package/dist/agent-src/skills/roadmap-management/references/dashboard.md +3 -3
- package/dist/agent-src/skills/roadmap-management/references/lifecycle.md +3 -3
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +4 -4
- package/dist/agent-src/skills/rtk-output-filtering/SKILL.md +1 -1
- package/dist/agent-src/skills/rule-writing/SKILL.md +1 -2
- package/dist/agent-src/skills/security/SKILL.md +41 -5
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +5 -3
- package/dist/agent-src/skills/skill-reviewer/SKILL.md +1 -1
- package/dist/agent-src/skills/skill-writing/SKILL.md +23 -8
- package/dist/agent-src/skills/skill-writing/references/section-patterns.md +19 -1
- package/dist/agent-src/skills/source-discovery/SKILL.md +3 -3
- package/dist/agent-src/skills/sql-writing/SKILL.md +2 -2
- package/dist/agent-src/skills/standards-from-config/SKILL.md +2 -2
- package/dist/agent-src/skills/storybook-workshop/SKILL.md +5 -0
- package/dist/agent-src/skills/storybook-workshop/scripts/story_contrast_floor.mjs +99 -0
- package/dist/agent-src/skills/subagent-orchestration/SKILL.md +13 -13
- package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +4 -3
- package/dist/agent-src/skills/svg-authoring/SKILL.md +7 -1
- package/dist/agent-src/skills/systematic-debugging/SKILL.md +2 -2
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +8 -3
- package/dist/agent-src/skills/tailwind-engineer/scripts/tailwind_config_gen.mjs +482 -0
- package/dist/agent-src/skills/test-case-discovery/SKILL.md +1 -1
- package/dist/agent-src/skills/threat-modeling/SKILL.md +8 -1
- package/dist/agent-src/skills/threat-modeling/data/manifest.json +5 -2
- package/dist/agent-src/skills/threat-modeling/data/reasoning.csv +10 -10
- package/dist/agent-src/skills/threat-modeling/data/surfaces.csv +11 -10
- package/dist/agent-src/skills/threat-modeling/data/threats.csv +34 -20
- package/dist/agent-src/skills/type-design/SKILL.md +196 -0
- package/dist/agent-src/skills/type-design/references/font-spec.md +90 -0
- package/dist/agent-src/skills/type-design/references/gates.md +113 -0
- package/dist/agent-src/skills/type-design/references/toolchain.md +66 -0
- package/dist/agent-src/skills/typography-system/SKILL.md +21 -11
- package/dist/agent-src/skills/typography-system/references/worked-scales.md +85 -0
- package/dist/agent-src/skills/ui-apply-generic/SKILL.md +1 -1
- package/dist/agent-src/skills/universal-project-analysis/SKILL.md +1 -1
- package/dist/agent-src/skills/upstream-contribute/SKILL.md +120 -125
- package/dist/agent-src/skills/using-git-worktrees/SKILL.md +1 -0
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +1 -1
- package/dist/agent-src/skills/voice-and-tone-design/SKILL.md +71 -2
- package/dist/agent-src/skills/worktree-lifecycle/SKILL.md +16 -14
- package/dist/agent-src/templates/AGENTS.md +1 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/agents/proposal.example.md +1 -1
- package/dist/agent-src/templates/github-workflows/advisories-daily.yml +85 -0
- package/dist/agent-src/templates/roadmaps.md +39 -1
- package/dist/agent-src/templates/scripts/check_memory.ts +2 -2
- package/dist/agent-src/templates/scripts/historical-bug-patterns.example.yml +13 -1
- package/dist/agent-src/templates/scripts/work_engine/cli.ts +17 -0
- package/dist/agent-src/templates/scripts/work_engine/cli_args.ts +10 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +22 -13
- package/dist/agent-src/templates/scripts/work_engine/dispatcher.ts +18 -4
- package/dist/agent-src/templates/scripts/work_engine/procedure/checks.ts +283 -0
- package/dist/agent-src/templates/scripts/work_engine/procedure/run.ts +432 -0
- package/dist/agent-src/templates/scripts/work_engine/procedure/sidecar.ts +185 -0
- package/dist/agent-src/templates/scripts/work_engine/state.ts +3 -0
- package/dist/cli/commands/uiRender.js +72 -17
- package/dist/cli/commands/uiRenderAsset.js +10 -2
- package/dist/cli/commands/uiRenderAssetFonts.js +158 -0
- package/dist/cli/commands/uiRenderAssetTypes.js +8 -20
- package/dist/cli/initRouting.js +1 -1
- package/dist/cli/mcp/dispatch.js +31 -9
- package/dist/cli/python/knowledge_ingest.js +7 -39
- package/dist/cli/python/workspace_secrets.js +4 -177
- package/dist/cli/registry.js +4 -1
- package/dist/cli-delegate/archive_completed_roadmaps.js +3 -2
- package/dist/cli-delegate/check_update_banner.js +635 -266
- package/dist/cli-delegate/{chunk-TMWYUOK4.js → chunk-2CX7NWRB.js} +224 -437
- package/dist/cli-delegate/{chunk-F3QDG2GT.js → chunk-2SFOOFJJ.js} +259 -159
- package/dist/cli-delegate/chunk-2Y5AMLMY.js +136 -0
- package/dist/cli-delegate/{chunk-OKJUIAPS.js → chunk-4E2W63DA.js} +1 -62
- package/dist/cli-delegate/{chunk-6SRJTYJS.js → chunk-4SHNERBL.js} +37 -16
- package/dist/cli-delegate/chunk-5VO3RTMV.js +208 -0
- package/dist/cli-delegate/chunk-6E2LDY4F.js +27 -0
- package/dist/cli-delegate/{chunk-XQTPXKFA.js → chunk-6ZD2QZMN.js} +8 -17
- package/dist/cli-delegate/{chunk-6V5FMA3P.js → chunk-7CEI2YPS.js} +1 -1
- package/dist/cli-delegate/{chunk-DMSZHXZS.js → chunk-7DRWULEQ.js} +80 -7
- package/dist/cli-delegate/chunk-7NXCZSDL.js +54 -0
- package/dist/cli-delegate/chunk-AX3U3UWJ.js +328 -0
- package/dist/cli-delegate/{chunk-WOKWX5PL.js → chunk-BKALSTBZ.js} +18 -3
- package/dist/cli-delegate/chunk-BMGUGSY6.js +103 -0
- package/dist/cli-delegate/chunk-BYV46VRM.js +3309 -0
- package/dist/cli-delegate/{chunk-5GPULQBE.js → chunk-CAL76ADI.js} +4215 -682
- package/dist/cli-delegate/chunk-DSY6LLCQ.js +127 -0
- package/dist/cli-delegate/chunk-E6XNBVE4.js +581 -0
- package/dist/cli-delegate/{chunk-ZUZKZYCN.js → chunk-ESUNQ5XR.js} +46 -10
- package/dist/cli-delegate/{chunk-G5VVIZRC.js → chunk-F7HLSW6P.js} +1 -1
- package/dist/cli-delegate/chunk-FIEEOH5C.js +133 -0
- package/dist/cli-delegate/chunk-FKYZOWVD.js +719 -0
- package/dist/cli-delegate/chunk-GOMILC3O.js +918 -0
- package/dist/cli-delegate/chunk-I4KJYVPB.js +69 -0
- package/dist/cli-delegate/{chunk-JQOM7TTM.js → chunk-IDAOTDPE.js} +1 -100
- package/dist/cli-delegate/chunk-IROAQ77A.js +137 -0
- package/dist/cli-delegate/chunk-J2SJZICO.js +698 -0
- package/dist/cli-delegate/{chunk-6YQC2HLF.js → chunk-JHMMWNJ2.js} +54 -40
- package/dist/cli-delegate/{chunk-WQWXGIWB.js → chunk-M6CRG5O6.js} +165 -15
- package/dist/cli-delegate/{chunk-PHD7OOLE.js → chunk-MQ2UDEGV.js} +14 -3
- package/dist/cli-delegate/chunk-NTM7G2V4.js +220 -0
- package/dist/cli-delegate/chunk-PV7S5DPJ.js +175 -0
- package/dist/cli-delegate/{chunk-F7DQWYR5.js → chunk-RAXQOETZ.js} +6 -2
- package/dist/cli-delegate/{chunk-T7XSJSUQ.js → chunk-SIOMDAKL.js} +980 -784
- package/dist/cli-delegate/{chunk-KR6EM23A.js → chunk-TULVDQ4L.js} +3 -48
- package/dist/cli-delegate/chunk-UUYEKXKR.js +20 -0
- package/dist/cli-delegate/{chunk-7XGD2OEU.js → chunk-UXWHY6CQ.js} +2 -1
- package/dist/cli-delegate/{chunk-PWX7CKMD.js → chunk-VC3ECUEK.js} +1 -1
- package/dist/cli-delegate/{chunk-KXXWJTDO.js → chunk-WMNYVIYX.js} +1 -1
- package/dist/cli-delegate/chunk-XCY5KKUC.js +181 -0
- package/dist/cli-delegate/{chunk-H76PHZBI.js → chunk-XLY5G3CM.js} +14 -19
- package/dist/cli-delegate/cmd_adr_effective.js +41 -2
- package/dist/cli-delegate/cmd_analyze_session.js +7 -7
- package/dist/cli-delegate/cmd_brand_status.js +1287 -10
- package/dist/cli-delegate/cmd_ci_settle.js +330 -0
- package/dist/cli-delegate/cmd_conformance.js +483 -817
- package/dist/cli-delegate/cmd_doctor.js +26 -16
- package/dist/cli-delegate/cmd_doctor_neighbours.js +10 -7
- package/dist/cli-delegate/cmd_explain.js +9 -24
- package/dist/cli-delegate/cmd_export.js +14 -11
- package/dist/cli-delegate/cmd_fleet.js +5 -3
- package/dist/cli-delegate/cmd_git_convention.js +8 -4
- package/dist/cli-delegate/cmd_handoff.js +79 -242
- package/dist/cli-delegate/cmd_mcp_available.js +1 -1
- package/dist/cli-delegate/cmd_memory_get.js +4 -2
- package/dist/cli-delegate/cmd_migrate.js +2 -2
- package/dist/cli-delegate/cmd_packs_active.js +2 -2
- package/dist/cli-delegate/cmd_preflight.js +7 -5
- package/dist/cli-delegate/cmd_prune.js +16 -13
- package/dist/cli-delegate/cmd_route_audit.js +11 -8
- package/dist/cli-delegate/cmd_route_explain.js +649 -16
- package/dist/cli-delegate/cmd_session_recycle.js +15 -6
- package/dist/cli-delegate/cmd_settings_check.js +2 -2
- package/dist/cli-delegate/cmd_settings_get.js +1 -1
- package/dist/cli-delegate/cmd_settings_migrate.js +14 -11
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +16 -13
- package/dist/cli-delegate/cmd_uninstall.js +185 -31
- package/dist/cli-delegate/cmd_update.js +67 -3
- package/dist/cli-delegate/cmd_upgrade.js +38 -7
- package/dist/cli-delegate/cmd_validate.js +16 -13
- package/dist/cli-delegate/cmd_versions.js +1 -1
- package/dist/cli-delegate/dashboard_mode.js +1 -1
- package/dist/cli-delegate/gate_execute.js +4 -3
- package/dist/cli-delegate/roadmap_age.js +22 -0
- package/dist/cli-delegate/roadmap_gates.js +4 -3
- package/dist/cli-delegate/update_roadmap_progress.js +3 -2
- package/dist/cli-delegate/upgrade_unattended-VVL6JLSX.js +541 -0
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +373 -190
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +5 -5
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +21 -16
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +16 -11
- package/dist/hooks/chat_history.chunk.cjs +6852 -0
- package/dist/hooks/chat_history.chunk.cjs.sha256 +1 -0
- package/dist/hooks/dispatch.js +17506 -18692
- package/dist/hooks/dispatch.sha256 +1 -1
- package/dist/hooks/egress_engine.chunk.cjs +915 -0
- package/dist/hooks/egress_engine.chunk.cjs.sha256 +1 -0
- package/dist/hooks/svg_rules.chunk.cjs +281 -49
- package/dist/hooks/svg_rules.chunk.cjs.sha256 +1 -1
- package/dist/install/conflict.js +36 -6
- package/dist/install/conflictTracker.js +81 -7
- package/dist/install/detect.js +3 -3
- package/dist/install/hostPermissionsAdapter.js +106 -0
- package/dist/install/install.mjs +3117 -1949
- package/dist/install/installThinLayer.js +1 -1
- package/dist/install/manifestFiles.js +21 -0
- package/dist/install/noGoDenyRows.js +300 -0
- package/dist/install/noGoRules.js +368 -0
- package/dist/install/ownershipLedger.js +133 -0
- package/dist/install/plan.js +1 -1
- package/dist/install/preflight.js +39 -8
- package/dist/install/preserve.js +74 -12
- package/dist/install/recordedOwnership.js +88 -5
- package/dist/install/rule_scope.js +20 -3
- package/dist/install/stagedRuntime.js +455 -0
- package/dist/install/toolsArg.js +19 -0
- package/dist/install/userPin.js +47 -0
- package/dist/install/wizard-plan.js +26 -4
- package/dist/mcp/awesome-mcp-servers.row.md +1 -1
- package/dist/mcp/mcp-cloudflare-catalogue.json +3 -2
- package/dist/mcp/registry-manifest.json +6 -5
- package/dist/mcp/server.json +3 -3
- package/dist/mcp/server.mjs +9831 -5546
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_settings.js +7 -12
- package/dist/scripts/_lib/asset_render_record.js +219 -0
- package/dist/scripts/_lib/claude_builtin_names.js +9 -4
- package/dist/scripts/_lib/claude_settings_hooks.js +102 -34
- package/dist/scripts/_lib/egress_rules.js +766 -0
- package/dist/scripts/_lib/environment_detector.js +24 -33
- package/dist/scripts/_lib/global_deploy_inventory.js +146 -9
- package/dist/scripts/_lib/guidelines_lane.js +10 -1
- package/dist/scripts/_lib/identifier_redaction.js +24 -0
- package/dist/scripts/_lib/installed_layer.js +17 -0
- package/dist/scripts/_lib/installed_layer_normalise.js +72 -0
- package/dist/scripts/_lib/lean_projection_mode.js +34 -152
- package/dist/scripts/_lib/project_tree_form.js +118 -0
- package/dist/scripts/_lib/scoped_projection.js +133 -3
- package/dist/scripts/_lib/settings_removed_keys.js +29 -0
- package/dist/scripts/_lib/settings_renamed_keys.js +17 -5
- package/dist/scripts/_lib/subagent_native_fields.js +35 -0
- package/dist/scripts/_lib/svg_filled_counter.js +285 -0
- package/dist/scripts/_lib/svg_rules.js +2 -0
- package/dist/scripts/_lib/ui_surface.js +19 -0
- package/dist/scripts/_lib/verification_command.js +364 -0
- package/dist/scripts/_lib/workspace_secrets.js +229 -0
- package/dist/scripts/ai_council/seat_policy.js +27 -0
- package/dist/scripts/ai_council/transport_resolver.js +9 -10
- package/dist/scripts/condense.js +25 -29
- package/dist/server/io/substituteTemplate.js +2 -2
- package/dist/server/io/yamlIO.js +2 -2
- package/dist/server/routes/install.js +5 -1
- package/dist/server/routes/settings.js +2 -2
- package/dist/server/routes/wizard.js +1 -1
- package/dist/server/schemas/settings.js +22 -16
- package/dist/server/serverInfo.js +1 -1
- package/dist/shared/brandTokenDocument.js +47 -0
- package/dist/shared/brandTokenPaths.js +43 -0
- package/dist/shared/settingsCarveOut.js +0 -7
- package/dist/shared/skillRanking.js +103 -5
- package/dist/shared/userMd/formAdapter.js +16 -0
- package/dist/shared/userMd/schema.js +17 -0
- package/dist/ui/assets/index-w70Ado09.js +23 -0
- package/dist/ui/index.html +1 -1
- package/docs/MIGRATION.md +89 -2
- package/docs/THIRD-PARTY-NOTICES.md +27 -0
- package/docs/contracts/settings-classes.md +27 -9
- package/docs/guidelines/agent-infra/api-cost-levers.md +4 -3
- package/docs/guidelines/agent-infra/model-recommendation.md +11 -5
- package/docs/guidelines/agent-infra/rule-body-migration-inventory.md +1 -1
- package/docs/guidelines/agent-infra/self-improvement-pipeline.md +47 -24
- package/docs/guidelines/design-antipatterns.md +5 -0
- package/docs/guidelines/design-asset-discipline.md +17 -0
- package/docs/guidelines/design-fidelity-routing.md +1 -0
- package/docs/guidelines/php/api-design.md +10 -1
- package/llms.txt +12 -10
- package/package.json +13 -4
- package/src/agent-src/scripts/dashboard_mode.ts +4 -1
- package/src/agent-src/scripts/roadmap_age.ts +175 -0
- package/src/agent-src/scripts/update_roadmap_progress.ts +10 -2
- package/src/agent-src/templates/AGENTS.md +1 -1
- package/src/agent-src/templates/scripts/check_memory.ts +2 -2
- package/src/agent-src/templates/scripts/historical-bug-patterns.example.yml +13 -1
- package/src/agent-src/templates/scripts/work_engine/cli.ts +17 -0
- package/src/agent-src/templates/scripts/work_engine/cli_args.ts +10 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +22 -13
- package/src/agent-src/templates/scripts/work_engine/dispatcher.ts +18 -4
- package/src/agent-src/templates/scripts/work_engine/procedure/checks.ts +283 -0
- package/src/agent-src/templates/scripts/work_engine/procedure/run.ts +432 -0
- package/src/agent-src/templates/scripts/work_engine/procedure/sidecar.ts +185 -0
- package/src/agent-src/templates/scripts/work_engine/state.ts +3 -0
- package/src/config/agent-settings.template.yml +120 -57
- package/src/config/agents-paths.yml +13 -7
- package/src/config/ci-local-parity.yml +44 -0
- package/src/config/continuity-surface.json +51 -2
- package/src/config/depth-audit-samples.json +5 -0
- package/src/config/discovery/command-verbs.yml +1 -0
- package/src/config/dispatch-economy-metrics.json +1 -0
- package/src/config/egress-mutations/class-precedence-swapped.json +7 -0
- package/src/config/egress-mutations/credential-token-restores.json +7 -0
- package/src/config/egress-mutations/iban-checksum-disabled.json +7 -0
- package/src/config/egress-mutations/raw-value-in-the-count-record.json +7 -0
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +149 -3
- package/src/config/gate-reachability-exemptions.json +3 -5
- package/src/config/gate-violation-baselines.json +26 -22
- package/src/config/gitignore-block.txt +6 -3
- package/src/config/hook-bundle-budget.json +34 -3
- package/src/config/hook-carrier-probes.json +30 -0
- package/src/config/hook-latency-budget.json +4 -2
- package/src/config/host-injection-effect.json +8 -1
- package/src/config/host-skill-frontmatter-keys.json +56 -0
- package/src/config/layer-form-brakes.json +4 -0
- package/src/config/layer-form-comparison-corpus.json +42 -0
- package/src/config/loop-surfaces.yaml +28 -47
- package/src/config/memory-twin-verdicts.yml +9 -1
- package/src/config/metric-registry.yml +40 -3
- package/src/config/pack-size-budget.json +15 -0
- package/src/config/procedure-core-budget.json +21 -0
- package/src/config/profiles/minimal.ini +1 -1
- package/src/config/project-tree-form.json +24 -0
- package/src/config/reach-channels.yml +3 -3
- package/src/config/reach-prescriptions-intake.yml +1 -1
- package/src/config/roadmap-step-size-baseline.json +118 -0
- package/src/config/routing-coverage-seed.json +93 -2
- package/src/config/skill-body-budget.json +686 -0
- package/src/config/skill-fork-pilot.json +17 -0
- package/src/config/skill-lifecycle-probes-codex.json +57 -0
- package/src/config/skill-lifecycle-probes.json +57 -0
- package/src/config/skill-output-shape.json +316 -0
- package/src/config/step-depth-table.json +58 -0
- package/src/config/turnaround-budget.json +90 -0
- package/src/install/conflict.ts +38 -6
- package/src/install/conflictTracker.ts +126 -8
- package/src/install/detect.ts +3 -3
- package/src/install/hostPermissionsAdapter.ts +136 -0
- package/src/install/installThinLayer.ts +6 -1
- package/src/install/manifestFiles.ts +24 -0
- package/src/install/noGoDenyRows.ts +368 -0
- package/src/install/noGoRules.ts +438 -0
- package/src/install/ownershipLedger.ts +180 -0
- package/src/install/plan.ts +1 -1
- package/src/install/preflight.ts +42 -10
- package/src/install/preserve.ts +94 -12
- package/src/install/recordedOwnership.ts +121 -3
- package/src/install/rule_scope.ts +20 -3
- package/src/install/stagedRuntime.ts +528 -0
- package/src/install/toolsArg.ts +16 -0
- package/src/install/types.ts +23 -2
- package/src/install/userPin.ts +54 -0
- package/src/install/wizard-plan.ts +25 -4
- package/src/scripts/_cli/_doctor_emit.ts +24 -0
- package/src/scripts/_cli/cmd_brand_status.ts +223 -12
- package/src/scripts/_cli/cmd_ci_settle.ts +32 -0
- package/src/scripts/_cli/cmd_doctor.ts +23 -44
- package/src/scripts/_cli/cmd_route_explain.ts +176 -2
- package/src/scripts/_cli/cmd_uninstall.ts +270 -26
- package/src/scripts/_cli/cmd_update.ts +34 -1
- package/src/scripts/_cli/cmd_upgrade.ts +38 -2
- package/src/scripts/_cli/detection_report.ts +7 -0
- package/src/scripts/_cli/doctor_execution.ts +1 -2
- package/src/scripts/_cli/doctor_install_mode.ts +39 -0
- package/src/scripts/_cli/doctor_network_posture.ts +3 -3
- package/src/scripts/_cli/doctor_ownership_ledger.ts +126 -0
- package/src/scripts/_cli/doctor_update_verdict.ts +104 -0
- package/src/scripts/_cli/explain_last/scrubber.ts +9 -21
- package/src/scripts/_cli/upgrade_unattended.ts +548 -0
- package/src/scripts/_dispatch.bash +42 -9
- package/src/scripts/_lib/activation_ladder.ts +1 -1
- package/src/scripts/_lib/advisory_inventory.ts +405 -0
- package/src/scripts/_lib/advisory_notice.ts +270 -0
- package/src/scripts/_lib/advisory_sources.ts +752 -0
- package/src/scripts/_lib/advisory_verdicts.ts +363 -0
- package/src/scripts/_lib/agent_artifact_location.ts +177 -0
- package/src/scripts/_lib/agent_settings.ts +7 -12
- package/src/scripts/_lib/arrival_record.ts +217 -0
- package/src/scripts/_lib/asset_render_record.ts +247 -0
- package/src/scripts/_lib/billing_grant.ts +4 -2
- package/src/scripts/_lib/brand_voice_slot.ts +258 -0
- package/src/scripts/_lib/canary_status.ts +24 -0
- package/src/scripts/_lib/cc_transcript.ts +276 -0
- package/src/scripts/_lib/changelog_eras.ts +83 -0
- package/src/scripts/_lib/claim_phrases.ts +71 -0
- package/src/scripts/_lib/classify_update.ts +171 -0
- package/src/scripts/_lib/claude_builtin_names.ts +9 -4
- package/src/scripts/_lib/claude_hook_scope.ts +195 -0
- package/src/scripts/_lib/claude_settings_hooks.ts +118 -34
- package/src/scripts/_lib/codex_resident_set.ts +460 -0
- package/src/scripts/_lib/codex_skill_finder.ts +225 -0
- package/src/scripts/_lib/confusables.ts +19 -0
- package/src/scripts/_lib/consumer_impact.ts +199 -0
- package/src/scripts/_lib/content_class.ts +127 -0
- package/src/scripts/_lib/counted_probe.ts +68 -1
- package/src/scripts/_lib/credential_deny_rows.ts +151 -0
- package/src/scripts/_lib/credential_files.ts +367 -0
- package/src/scripts/_lib/delivery_arm_experiment.ts +2 -2
- package/src/scripts/_lib/depth_flip.ts +141 -0
- package/src/scripts/_lib/design_lock.ts +117 -0
- package/src/scripts/_lib/design_sync_ledger.ts +142 -0
- package/src/scripts/_lib/design_sync_plan.ts +177 -0
- package/src/scripts/_lib/design_sync_reconcile.ts +159 -0
- package/src/scripts/_lib/design_sync_verify.ts +99 -0
- package/src/scripts/_lib/design_system_claude_design.ts +323 -0
- package/src/scripts/_lib/design_system_import.ts +84 -6
- package/src/scripts/_lib/dispatch_import_closure.ts +42 -11
- package/src/scripts/_lib/egress_credential_env.ts +35 -0
- package/src/scripts/_lib/egress_engine.ts +22 -0
- package/src/scripts/_lib/egress_known_values.ts +223 -0
- package/src/scripts/_lib/egress_normalize.ts +67 -0
- package/src/scripts/_lib/egress_prefixes.ts +42 -0
- package/src/scripts/_lib/egress_rules.ts +896 -0
- package/src/scripts/_lib/egress_rules_linearity.ts +56 -0
- package/src/scripts/_lib/egress_sender_scan.ts +290 -0
- package/src/scripts/_lib/egress_session_table.ts +510 -0
- package/src/scripts/_lib/egress_text.ts +63 -0
- package/src/scripts/_lib/egress_token.ts +252 -0
- package/src/scripts/_lib/empty_cycles.ts +1 -1
- package/src/scripts/_lib/environment_detector.ts +45 -30
- package/src/scripts/_lib/exemption_shape.ts +75 -1
- package/src/scripts/_lib/floor_posture.ts +185 -0
- package/src/scripts/_lib/forge_protection.ts +140 -2
- package/src/scripts/_lib/global_deploy_inventory.ts +159 -6
- package/src/scripts/_lib/guidelines_lane.ts +12 -1
- package/src/scripts/_lib/hand_kinds.ts +65 -0
- package/src/scripts/_lib/headless_invocation.ts +3 -3
- package/src/scripts/_lib/host_capability.ts +34 -2
- package/src/scripts/_lib/host_env_write.ts +39 -18
- package/src/scripts/_lib/host_listing_model.ts +14 -7
- package/src/scripts/_lib/identifier_redaction.ts +26 -0
- package/src/scripts/_lib/impact_bump.ts +70 -0
- package/src/scripts/_lib/install_reach_checks.ts +53 -1
- package/src/scripts/_lib/installed_layer.ts +31 -0
- package/src/scripts/_lib/installed_layer_normalise.ts +75 -0
- package/src/scripts/_lib/instructions_loaded_classify.ts +75 -0
- package/src/scripts/_lib/instructions_loaded_event.ts +53 -0
- package/src/scripts/_lib/knowledge_global_redaction.ts +2 -2
- package/src/scripts/_lib/layer_form_corpus.ts +165 -0
- package/src/scripts/_lib/layer_form_decision.ts +248 -0
- package/src/scripts/_lib/layer_form_evidence.ts +112 -0
- package/src/scripts/_lib/lean_projection_mode.ts +32 -161
- package/src/scripts/_lib/llm_proposer_transport.ts +1 -0
- package/src/scripts/_lib/loop_guards.ts +8 -120
- package/src/scripts/_lib/major_surface.ts +207 -0
- package/src/scripts/_lib/mcp_bridge.ts +30 -69
- package/src/scripts/_lib/merge_clearance_record.ts +384 -0
- package/src/scripts/_lib/neighbour_census.ts +18 -1
- package/src/scripts/_lib/orchestration_record.ts +61 -0
- package/src/scripts/_lib/outcome_vocabularies.ts +15 -23
- package/src/scripts/_lib/pin_advice.ts +49 -0
- package/src/scripts/_lib/platform_anchor.ts +222 -0
- package/src/scripts/_lib/procedure_checks.ts +5 -0
- package/src/scripts/_lib/project_tree_form.ts +134 -0
- package/src/scripts/_lib/projection_key_migration.ts +122 -0
- package/src/scripts/_lib/prompt_shape.ts +13 -2
- package/src/scripts/_lib/provenance_verify.ts +272 -0
- package/src/scripts/_lib/quota_parked.ts +27 -1
- package/src/scripts/_lib/ratification_artifact.ts +64 -1
- package/src/scripts/_lib/ratification_subject.ts +508 -46
- package/src/scripts/_lib/release_findings_ingest.ts +52 -5
- package/src/scripts/_lib/release_highlights.ts +72 -2
- package/src/scripts/_lib/release_settings_surface.ts +392 -0
- package/src/scripts/_lib/review_round.ts +134 -0
- package/src/scripts/_lib/roadmap_checkboxes.ts +1 -1
- package/src/scripts/_lib/roadmap_slug_lock.ts +254 -0
- package/src/scripts/_lib/roadmap_step_size.ts +75 -0
- package/src/scripts/_lib/run_checkpoint.ts +60 -3
- package/src/scripts/_lib/runtime_wiring_checks.ts +15 -1
- package/src/scripts/_lib/scope_guard.sh +64 -5
- package/src/scripts/_lib/scoped_projection.ts +136 -3
- package/src/scripts/_lib/secret_detector.ts +24 -103
- package/src/scripts/_lib/security_fix.ts +429 -0
- package/src/scripts/_lib/security_fix_context.ts +133 -0
- package/src/scripts/_lib/self_repair.ts +69 -39
- package/src/scripts/_lib/self_repair_outgoing.ts +209 -0
- package/src/scripts/_lib/self_repair_payload.ts +86 -0
- package/src/scripts/_lib/session_eol.ts +3 -0
- package/src/scripts/_lib/session_pr_watch.ts +207 -0
- package/src/scripts/_lib/session_register.ts +51 -1
- package/src/scripts/_lib/session_tag.ts +51 -0
- package/src/scripts/_lib/settings_removed_keys.ts +30 -0
- package/src/scripts/_lib/settings_renamed_keys.ts +19 -5
- package/src/scripts/_lib/skill_catalogue.ts +66 -25
- package/src/scripts/_lib/skill_fork_pilot.ts +121 -0
- package/src/scripts/_lib/skill_leases.ts +203 -0
- package/src/scripts/_lib/skill_listing_overrides.ts +294 -0
- package/src/scripts/_lib/skill_materialisation.ts +388 -0
- package/src/scripts/_lib/skill_materialisation_gate.ts +210 -0
- package/src/scripts/_lib/skill_materialisation_lock.ts +149 -0
- package/src/scripts/_lib/skill_materialisation_triggers.ts +96 -0
- package/src/scripts/_lib/skill_origin.ts +21 -1
- package/src/scripts/_lib/skill_reach.ts +342 -0
- package/src/scripts/_lib/source_shape.ts +7 -2
- package/src/scripts/_lib/sqlite_guard.ts +1 -1
- package/src/scripts/_lib/step_anatomy.ts +330 -0
- package/src/scripts/_lib/subagent_capsule.ts +8 -2
- package/src/scripts/_lib/subagent_native_fields.ts +30 -0
- package/src/scripts/_lib/subagent_spawn.ts +36 -0
- package/src/scripts/_lib/subagent_steering.ts +367 -0
- package/src/scripts/_lib/svg_filled_counter.ts +287 -0
- package/src/scripts/_lib/svg_rules.ts +2 -0
- package/src/scripts/_lib/test_delta.ts +89 -6
- package/src/scripts/_lib/tier_downshift_verdict.ts +222 -0
- package/src/scripts/_lib/tool_result_census.ts +62 -0
- package/src/scripts/_lib/trigger_routers.ts +1 -0
- package/src/scripts/_lib/turnaround_throughput.ts +378 -0
- package/src/scripts/_lib/ui_surface.ts +22 -0
- package/src/scripts/_lib/unattended_gates.ts +100 -0
- package/src/scripts/_lib/undeployed_fixes.ts +34 -0
- package/src/scripts/_lib/update_check.ts +143 -12
- package/src/scripts/_lib/update_invite.ts +116 -0
- package/src/scripts/_lib/update_notice.ts +259 -0
- package/src/scripts/_lib/verify_clause.ts +4 -2
- package/src/scripts/_lib/version_order.ts +146 -0
- package/src/scripts/_lib/worker_reuse.ts +191 -0
- package/src/scripts/_lib/workspace_secrets.ts +273 -0
- package/src/scripts/_lib/worktree_git.ts +67 -0
- package/src/scripts/_lib/worktree_ignored.ts +116 -0
- package/src/scripts/adoption_status.ts +330 -3
- package/src/scripts/adr_cite_check.ts +93 -0
- package/src/scripts/advisories.ts +803 -0
- package/src/scripts/ai-image/adapters/flux.sh +1 -0
- package/src/scripts/ai-image/adapters/gemini-image.sh +1 -0
- package/src/scripts/ai-image/adapters/ideogram.sh +1 -0
- package/src/scripts/ai-image/adapters/recraft.sh +1 -0
- package/src/scripts/ai-video/adapters/comfyui.sh +1 -0
- package/src/scripts/ai-video/adapters/fal.sh +1 -0
- package/src/scripts/ai-video/adapters/gemini-veo.sh +1 -0
- package/src/scripts/ai-video/adapters/higgsfield.sh +1 -0
- package/src/scripts/ai-video/adapters/kling.sh +1 -0
- package/src/scripts/ai-video/adapters/musetalk.sh +1 -0
- package/src/scripts/ai-video/adapters/openai-images.sh +1 -0
- package/src/scripts/ai-video/adapters/replicate.sh +1 -0
- package/src/scripts/ai-video/adapters/sora.sh +1 -0
- package/src/scripts/ai-video/adapters/syncso.sh +1 -0
- package/src/scripts/ai-video/stitch.sh +115 -2
- package/src/scripts/ai_council/airgap.ts +1 -0
- package/src/scripts/ai_council/api_transport.ts +27 -4
- package/src/scripts/ai_council/budget_guard.ts +300 -11
- package/src/scripts/ai_council/bundler.ts +20 -29
- package/src/scripts/ai_council/chairman.ts +17 -2
- package/src/scripts/ai_council/cli_agency_bounds.ts +158 -0
- package/src/scripts/ai_council/cli_launch_env.ts +54 -0
- package/src/scripts/ai_council/cli_least_agency_canary.ts +18 -2
- package/src/scripts/ai_council/clients.ts +55 -73
- package/src/scripts/ai_council/config.ts +16 -22
- package/src/scripts/ai_council/council_egress.ts +167 -0
- package/src/scripts/ai_council/exposure_ledger.ts +117 -0
- package/src/scripts/ai_council/free_hand_shadow.ts +276 -0
- package/src/scripts/ai_council/free_route.ts +216 -0
- package/src/scripts/ai_council/free_route_catalog.ts +173 -0
- package/src/scripts/ai_council/free_route_client.ts +95 -0
- package/src/scripts/ai_council/free_rung.ts +61 -0
- package/src/scripts/ai_council/hand_payload.ts +230 -0
- package/src/scripts/ai_council/hand_schemas.ts +123 -0
- package/src/scripts/ai_council/jury_aggregate.ts +155 -1
- package/src/scripts/ai_council/kind_flip.ts +221 -0
- package/src/scripts/ai_council/kind_flip_state.ts +19 -0
- package/src/scripts/ai_council/learn_low_impact_preview.ts +50 -22
- package/src/scripts/ai_council/modification_review.ts +98 -5
- package/src/scripts/ai_council/necessity.ts +7 -0
- package/src/scripts/ai_council/orchestrator.ts +16 -16
- package/src/scripts/ai_council/pricing.ts +10 -0
- package/src/scripts/ai_council/redact_low_impact_entry.ts +5 -2
- package/src/scripts/ai_council/response_render.ts +27 -4
- package/src/scripts/ai_council/round_reservations.ts +119 -0
- package/src/scripts/ai_council/route_chooser.ts +161 -0
- package/src/scripts/ai_council/route_liveness.ts +152 -0
- package/src/scripts/ai_council/route_member.ts +52 -0
- package/src/scripts/ai_council/seat_policy.ts +40 -0
- package/src/scripts/ai_council/seat_resume.ts +40 -0
- package/src/scripts/ai_council/shadow_dispatch.ts +13 -3
- package/src/scripts/ai_council/spend_gate.ts +18 -2
- package/src/scripts/ai_council/status_surface.ts +37 -0
- package/src/scripts/ai_council/transport_resolver.ts +15 -18
- package/src/scripts/analysis_analysts.ts +226 -0
- package/src/scripts/analysis_anchors.ts +140 -0
- package/src/scripts/analysis_and_optimize.ts +44 -0
- package/src/scripts/analysis_emit.ts +150 -0
- package/src/scripts/analysis_exchange.ts +186 -0
- package/src/scripts/analysis_gate.ts +158 -0
- package/src/scripts/analysis_inbox_final.ts +173 -0
- package/src/scripts/analysis_ledger.ts +119 -0
- package/src/scripts/analysis_pr_optimize.ts +219 -0
- package/src/scripts/analysis_pr_review.ts +240 -0
- package/src/scripts/analysis_pr_target.ts +121 -0
- package/src/scripts/analysis_prompts.ts +130 -0
- package/src/scripts/analysis_publish.ts +358 -0
- package/src/scripts/analysis_questions.ts +78 -0
- package/src/scripts/analysis_run.ts +248 -0
- package/src/scripts/analysis_run_record.ts +210 -0
- package/src/scripts/analysis_target.ts +343 -0
- package/src/scripts/analysis_validate.ts +161 -0
- package/src/scripts/anchor_eval_falsify.ts +1 -1
- package/src/scripts/arrival_report.ts +115 -0
- package/src/scripts/ask_transport.ts +284 -35
- package/src/scripts/backfill_model_tier.ts +4 -5
- package/src/scripts/before_complete_hook.ts +48 -2
- package/src/scripts/bench_hook_latency.ts +3 -3
- package/src/scripts/bench_procedure_cursor.ts +440 -0
- package/src/scripts/bootstrap.sh +3 -3
- package/src/scripts/build_exit_code_register.ts +440 -0
- package/src/scripts/build_proof.ts +23 -1
- package/src/scripts/cache_realization_report.ts +155 -14
- package/src/scripts/canary_liveness.ts +117 -0
- package/src/scripts/chat_history.ts +12 -15
- package/src/scripts/check_account_surface.ts +318 -0
- package/src/scripts/check_agent_artifact_location.ts +17 -160
- package/src/scripts/check_bundle_path_leakage.ts +6 -0
- package/src/scripts/check_ci_local_parity.ts +21 -13
- package/src/scripts/check_claims.ts +77 -2
- package/src/scripts/check_completion_review.ts +34 -1
- package/src/scripts/check_concern_admissions.ts +41 -5
- package/src/scripts/check_consumer_scope_flip.ts +1 -1
- package/src/scripts/check_context_paths.ts +2 -0
- package/src/scripts/check_council_layout.ts +9 -0
- package/src/scripts/check_credential_spelling.ts +267 -0
- package/src/scripts/check_egress_mutations.ts +239 -0
- package/src/scripts/check_enforcement_coverage.ts +16 -3
- package/src/scripts/check_estate_count.ts +16 -1
- package/src/scripts/check_finding_dispositions.ts +147 -0
- package/src/scripts/check_gate_coverage.ts +123 -21
- package/src/scripts/check_gate_reachability.ts +16 -2
- package/src/scripts/check_generator_sync.ts +46 -0
- package/src/scripts/check_hook_bundle_composition.ts +139 -1
- package/src/scripts/check_host_docs_digest.ts +142 -5
- package/src/scripts/check_kernel_edit_ratified.ts +301 -76
- package/src/scripts/check_kernel_rule_bundle.ts +14 -10
- package/src/scripts/check_knowledge_cards.ts +83 -3
- package/src/scripts/check_memory.ts +13 -3
- package/src/scripts/check_pack_size.ts +1 -1
- package/src/scripts/check_permission_deny_syntax.ts +247 -0
- package/src/scripts/check_platform_anchor.ts +243 -0
- package/src/scripts/check_proposal.ts +183 -1
- package/src/scripts/check_reach_channels.ts +5 -3
- package/src/scripts/check_references.ts +5 -2
- package/src/scripts/check_release_manifest_content.ts +33 -0
- package/src/scripts/check_release_pr_shape.ts +5 -0
- package/src/scripts/check_rule_invariants.ts +9 -1
- package/src/scripts/check_skill_body_budget.ts +343 -0
- package/src/scripts/check_skill_requires.ts +137 -1
- package/src/scripts/check_step_receipts.ts +246 -0
- package/src/scripts/check_structural_breaking.ts +7 -1
- package/src/scripts/check_suppression_hygiene.ts +8 -0
- package/src/scripts/check_test_weakening.ts +14 -0
- package/src/scripts/check_token_quality_golden.ts +5 -1
- package/src/scripts/check_update_banner.ts +50 -3
- package/src/scripts/check_verify_expectation_delta.ts +2 -1
- package/src/scripts/check_voice_lexicon.ts +531 -0
- package/src/scripts/ci_os_attribution.ts +327 -0
- package/src/scripts/ci_platform_scope.ts +69 -0
- package/src/scripts/ci_settle.ts +4 -1
- package/src/scripts/ci_status.ts +0 -1
- package/src/scripts/ci_time_to_green.ts +748 -0
- package/src/scripts/classify_merge_risk.ts +407 -19
- package/src/scripts/code_graph/sqlite_store.ts +1 -1
- package/src/scripts/compile_trigger_evals.ts +353 -0
- package/src/scripts/condense.ts +25 -31
- package/src/scripts/consumer_matrix.ts +61 -3
- package/src/scripts/council_availability_hook.ts +12 -4
- package/src/scripts/council_cli.ts +48 -38
- package/src/scripts/cross_repo_retrieve.ts +9 -72
- package/src/scripts/design_lock.ts +106 -0
- package/src/scripts/design_slop_rules.ts +30 -0
- package/src/scripts/design_sync.ts +264 -0
- package/src/scripts/design_system_import.ts +30 -13
- package/src/scripts/dispatch_economy_report.ts +46 -1
- package/src/scripts/dispatch_r2_reviewer.ts +41 -5
- package/src/scripts/egress_canary.ts +166 -0
- package/src/scripts/egress_sender_census.ts +101 -0
- package/src/scripts/external_sources_denylist.json +94 -12
- package/src/scripts/generate_catalog.ts +6 -2
- package/src/scripts/generate_owned_digest.ts +163 -0
- package/src/scripts/generate_reference_toc.ts +143 -0
- package/src/scripts/generate_subagent_floor.ts +11 -1
- package/src/scripts/handoff_context_hook.ts +34 -0
- package/src/scripts/hook_carrier_census.ts +263 -0
- package/src/scripts/hook_chunks.d.mts +12 -0
- package/src/scripts/hook_chunks.mjs +114 -0
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +65 -42
- package/src/scripts/hooks/block_config_weakening.ts +127 -3
- package/src/scripts/hooks/block_credential_reads.ts +165 -0
- package/src/scripts/hooks/block_no_verify.ts +47 -23
- package/src/scripts/hooks/block_speaking_inbox_dir.ts +38 -7
- package/src/scripts/hooks/category_a.ts +202 -25
- package/src/scripts/hooks/concern_failure_policy.ts +6 -6
- package/src/scripts/hooks/concern_registry.ts +31 -6
- package/src/scripts/hooks/concern_registry_types.ts +11 -0
- package/src/scripts/hooks/delegation_nudge_hook.ts +105 -15
- package/src/scripts/hooks/design_pass_hook.ts +42 -10
- package/src/scripts/hooks/dispatch_hook.ts +13 -12
- package/src/scripts/hooks/egress_engine_loader.ts +125 -0
- package/src/scripts/hooks/egress_stage.ts +440 -0
- package/src/scripts/hooks/hook_stdin.ts +29 -4
- package/src/scripts/hooks/host_docs_pages.ts +194 -0
- package/src/scripts/hooks/host_docs_pages.yaml +75 -0
- package/src/scripts/hooks/host_lowering.json +1 -1
- package/src/scripts/hooks/host_lowering.yaml +22 -21
- package/src/scripts/hooks/host_rate_marker_hook.ts +73 -0
- package/src/scripts/hooks/instructions_observer_hook.ts +170 -0
- package/src/scripts/hooks/interruption_ledger_hook.ts +1 -1
- package/src/scripts/hooks/lazy_concern.ts +148 -0
- package/src/scripts/hooks/orchestration_record_hook.ts +80 -2
- package/src/scripts/hooks/payload_stub.ts +16 -6
- package/src/scripts/hooks/permission_gate.ts +7 -7
- package/src/scripts/hooks/push_settle_hook.ts +32 -3
- package/src/scripts/hooks/replay_hook.ts +43 -0
- package/src/scripts/hooks/reread_guard_hook.ts +87 -10
- package/src/scripts/hooks/rtk_wrap_hook.ts +4 -3
- package/src/scripts/hooks/rule_inject_hook.ts +8 -1
- package/src/scripts/hooks/session_eol_hook.ts +48 -1
- package/src/scripts/hooks/source_first_gate_hook.ts +6 -8
- package/src/scripts/hooks/spawn_guard_shadow_hook.ts +203 -10
- package/src/scripts/hooks/state_io.ts +2 -2
- package/src/scripts/hooks/svg_obligation.ts +75 -19
- package/src/scripts/hooks/tool_result_bytes_hook.ts +14 -5
- package/src/scripts/hooks/turn_end_gate_hook.ts +1 -1
- package/src/scripts/hooks/ui_route_nudge_hook.ts +2 -12
- package/src/scripts/hooks_doctor.ts +31 -0
- package/src/scripts/hooks_status.ts +58 -3
- package/src/scripts/inbox_source_census.ts +74 -13
- package/src/scripts/install +25 -3
- package/src/scripts/install.ts +60 -91
- package/src/scripts/interruption_report.ts +11 -1
- package/src/scripts/layer_baseline_report.ts +267 -0
- package/src/scripts/learning_sidecar.ts +1 -1
- package/src/scripts/lint_agents_layout.ts +3 -0
- package/src/scripts/lint_blocker_citations.ts +104 -0
- package/src/scripts/lint_breaking_changes_index.ts +40 -7
- package/src/scripts/lint_consolidation_lineage.ts +144 -16
- package/src/scripts/lint_consumer_internal_refs.ts +90 -42
- package/src/scripts/lint_context_spine_usage.ts +21 -0
- package/src/scripts/lint_design_antipattern_parity.ts +39 -7
- package/src/scripts/lint_evidence_artifacts.ts +31 -0
- package/src/scripts/lint_example_fences.ts +11 -2
- package/src/scripts/lint_ghostwriter_source.ts +42 -10
- package/src/scripts/lint_hook_manifest.ts +94 -0
- package/src/scripts/lint_marketplace_install_completeness.ts +4 -0
- package/src/scripts/lint_mcp_config_security.ts +9 -11
- package/src/scripts/lint_plan_risk_register.ts +28 -1
- package/src/scripts/lint_positioning.ts +4 -4
- package/src/scripts/lint_provenance.ts +1 -0
- package/src/scripts/lint_roadmap_blockers.ts +65 -4
- package/src/scripts/lint_roadmap_complexity.ts +98 -0
- package/src/scripts/lint_skill_link_reach.ts +251 -9
- package/src/scripts/lint_skill_procedures.ts +252 -0
- package/src/scripts/lint_skill_scripts_readonly.ts +12 -1
- package/src/scripts/lint_subagent_determinism.ts +14 -1
- package/src/scripts/lint_ticked_unmet_criteria.ts +300 -21
- package/src/scripts/mcp_registry_submit.sh +2 -2
- package/src/scripts/mcp_server/consumer_tool_catalog.json +4 -4
- package/src/scripts/mcp_server/suggest_skill.ts +89 -4
- package/src/scripts/mcp_server/tools.ts +2 -33
- package/src/scripts/measure_skill_ranker_baseline.ts +203 -5
- package/src/scripts/measure_turn_end_gate.ts +61 -1
- package/src/scripts/merge_clearance.ts +225 -0
- package/src/scripts/migrate_command_suggestions.ts +1 -1
- package/src/scripts/network_sources.ts +236 -0
- package/src/scripts/no_go_deny_rows.ts +225 -0
- package/src/scripts/orchestration_record.ts +15 -2
- package/src/scripts/plan_test_shards.ts +103 -0
- package/src/scripts/pr_url_reminder_hook.ts +10 -0
- package/src/scripts/print_required_checks.ts +5 -5
- package/src/scripts/probe_depth_shadow.ts +406 -0
- package/src/scripts/probe_turnaround.ts +342 -10
- package/src/scripts/ratification_subject.ts +176 -0
- package/src/scripts/rdp_gate_classify.ts +1 -0
- package/src/scripts/rdp_quality_eval.ts +1 -0
- package/src/scripts/release.ts +26 -55
- package/src/scripts/release_drill.ts +52 -23
- package/src/scripts/release_env.ts +37 -0
- package/src/scripts/release_publication.ts +11 -1
- package/src/scripts/report_consumer_gate_reach.ts +233 -0
- package/src/scripts/report_merge_gate_load.ts +295 -0
- package/src/scripts/report_project_contract.ts +123 -0
- package/src/scripts/report_reducible_classes.ts +342 -0
- package/src/scripts/report_required_checks_drift.ts +5 -3
- package/src/scripts/report_skill_host_census.ts +199 -0
- package/src/scripts/report_standing_payload_by_host.ts +7 -7
- package/src/scripts/retro.ts +758 -0
- package/src/scripts/retro_facts.ts +575 -0
- package/src/scripts/retro_queue.ts +739 -0
- package/src/scripts/retro_session_facts.ts +218 -0
- package/src/scripts/retro_sweep.ts +493 -0
- package/src/scripts/retro_triage.ts +126 -0
- package/src/scripts/roadmap_context.ts +2 -2
- package/src/scripts/roadmap_drain_queue.ts +601 -0
- package/src/scripts/run_supervise.ts +24 -2
- package/src/scripts/schemas/agent-settings.schema.json +0 -16
- package/src/scripts/schemas/command.schema.json +3 -3
- package/src/scripts/schemas/review-findings.schema.json +8 -0
- package/src/scripts/schemas/skill.schema.json +7 -6
- package/src/scripts/schemas/subagent.schema.json +33 -2
- package/src/scripts/score_skill_selection.ts +5 -2
- package/src/scripts/second_brain_retrieval.ts +1 -0
- package/src/scripts/second_brain_run.ts +1 -0
- package/src/scripts/self_repair_cli.ts +563 -87
- package/src/scripts/self_review_gate.ts +59 -4
- package/src/scripts/session_register_hook.ts +91 -4
- package/src/scripts/sessions_cli.ts +100 -5
- package/src/scripts/skill_collision_clusters.ts +1 -1
- package/src/scripts/skill_tools/score_skill_relevance.ts +31 -2
- package/src/scripts/skill_trigger_eval.ts +4 -2
- package/src/scripts/source_adapters.ts +183 -0
- package/src/scripts/step_receipt.ts +100 -0
- package/src/scripts/sync_pr_branch.ts +4 -0
- package/src/scripts/test_council_qualification.ts +1 -1
- package/src/scripts/trigger_eval_grandfather.json +3 -49
- package/src/scripts/trigger_eval_rotation.ts +31 -3
- package/src/scripts/ui_conformance_probe.ts +405 -1
- package/src/scripts/update_counts.ts +230 -11
- package/src/scripts/update_invite_hook.ts +245 -0
- package/src/scripts/update_notice_hook.ts +298 -0
- package/src/scripts/validate_frontmatter.ts +85 -0
- package/src/scripts/worker_reuse_shadow_report.ts +121 -0
- package/src/scripts/worktree_cleanup_check.ts +915 -121
- package/src/server/io/yamlIO.ts +2 -2
- package/src/server/schemas/settings.ts +37 -23
- package/src/shared/brandTokenDocument.ts +46 -0
- package/src/shared/brandTokenPaths.ts +43 -0
- package/src/shared/settingsCarveOut.ts +0 -8
- package/src/shared/skillRanking.ts +106 -5
- package/src/shared/userMd/formAdapter.ts +15 -1
- package/src/shared/userMd/schema.ts +22 -0
- package/src/templates/agent-user.md +4 -0
- package/src/templates/agent-user.yml +4 -0
- package/dist/cli-delegate/chunk-4DBG5K7M.js +0 -1123
- package/dist/cli-delegate/chunk-523HCFYO.js +0 -90
- package/dist/cli-delegate/chunk-AL3RZ22D.js +0 -74
- package/dist/cli-delegate/chunk-KB5FZ655.js +0 -208
- package/dist/cli-delegate/chunk-MDPPKQCQ.js +0 -875
- package/dist/cli-delegate/chunk-OAFSJBHH.js +0 -272
- package/dist/ui/assets/index-C3djEJah.js +0 -23
- package/src/scripts/_lib/continuation_ladder.ts +0 -335
- package/src/scripts/hooks/run_continuation_hook.ts +0 -1524
|
@@ -0,0 +1,896 @@
|
|
|
1
|
+
// The one rule table for values that must not leave for a model provider in
|
|
2
|
+
// plaintext (docs/contracts/egress-placeholders-v1.md). Every credential and
|
|
3
|
+
// identifier pattern is defined here and nowhere else; consumers decide policy
|
|
4
|
+
// (refuse, replace, report), this module only detects.
|
|
5
|
+
//
|
|
6
|
+
// Pure: no import, no I/O, no network. Every rule states why it is linear on a
|
|
7
|
+
// hostile input; the parity test pins what the move from secret_detector kept.
|
|
8
|
+
|
|
9
|
+
export type EgressClass = 'credential' | 'identifier';
|
|
10
|
+
|
|
11
|
+
export interface EgressRule {
|
|
12
|
+
readonly rule: string;
|
|
13
|
+
/** Placeholder type a replacement prints, e.g. `APIKEY`. */
|
|
14
|
+
readonly type: string;
|
|
15
|
+
readonly class: EgressClass;
|
|
16
|
+
/** Finding kind reported by the commit-time scanner; defaults to `rule`. */
|
|
17
|
+
readonly kind?: string;
|
|
18
|
+
/** MUST carry the global flag. */
|
|
19
|
+
readonly pattern: RegExp;
|
|
20
|
+
/**
|
|
21
|
+
* Which bytes a replacement must remove. `'detection'`: the detection span is
|
|
22
|
+
* the whole secret. A `through` function returns the end of the secret for a
|
|
23
|
+
* detection span, or null when that end cannot be proven; the replacer then
|
|
24
|
+
* refuses the whole text rather than replace part of it.
|
|
25
|
+
*/
|
|
26
|
+
readonly replacement: 'detection' | { readonly through: (text: string, span: SpanBounds) => number | null };
|
|
27
|
+
/**
|
|
28
|
+
* Capture group holding the value; the whole match when absent. A rule that
|
|
29
|
+
* sets it MUST carry the d flag. A list names alternatives of one value
|
|
30
|
+
* shape — the first group that participated in the match is the value — so
|
|
31
|
+
* a shape whose delimiter decides its extent stays one row.
|
|
32
|
+
*/
|
|
33
|
+
readonly valueGroup?: number | readonly number[];
|
|
34
|
+
/** `group` is the capture group the value came from, so a delimiter can change the test. */
|
|
35
|
+
readonly validator?: (value: string, group: number | 'whole-match') => boolean;
|
|
36
|
+
/** The rule fires only when `words` matches within `window` chars of the value. */
|
|
37
|
+
readonly context?: { readonly words: RegExp; readonly window: number };
|
|
38
|
+
readonly exclusions?: readonly RegExp[];
|
|
39
|
+
/**
|
|
40
|
+
* Literal vendor prefixes that mark a raw key by construction. Surfaces that
|
|
41
|
+
* act on shape alone (a config ref, a masked log value) read these instead of
|
|
42
|
+
* spelling their own list.
|
|
43
|
+
*/
|
|
44
|
+
readonly prefixes?: readonly string[];
|
|
45
|
+
/**
|
|
46
|
+
* The row matches only at a token start (its pattern opens with a lookbehind
|
|
47
|
+
* for a key character). A shape-only surface reading the prefixes holds them
|
|
48
|
+
* to a token start exactly when this is set; a test checks it against what the
|
|
49
|
+
* row actually matches.
|
|
50
|
+
*/
|
|
51
|
+
readonly tokenStart?: true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface SpanBounds {
|
|
55
|
+
readonly start: number;
|
|
56
|
+
readonly end: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** A detected value: offsets into the scanned text, never the value itself. */
|
|
60
|
+
export interface EgressSpan {
|
|
61
|
+
readonly rule: string;
|
|
62
|
+
readonly type: string;
|
|
63
|
+
readonly class: EgressClass;
|
|
64
|
+
readonly start: number;
|
|
65
|
+
readonly end: number;
|
|
66
|
+
readonly validated: boolean;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function shannonEntropy(value: string): number {
|
|
70
|
+
const freq = new Map<string, number>();
|
|
71
|
+
for (const ch of value) {
|
|
72
|
+
freq.set(ch, (freq.get(ch) ?? 0) + 1);
|
|
73
|
+
}
|
|
74
|
+
const n = value.length;
|
|
75
|
+
let entropy = 0;
|
|
76
|
+
for (const count of freq.values()) {
|
|
77
|
+
const p = count / n;
|
|
78
|
+
entropy -= p * Math.log2(p);
|
|
79
|
+
}
|
|
80
|
+
return entropy;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// A keyword-shaped assignment of a low-entropy word (`secret: moderate`) or of a
|
|
84
|
+
// code expression (`opts.apiKey`, `${API_KEY}`, `load()`) is not a credential.
|
|
85
|
+
const GENERIC_MIN_LENGTH = 16;
|
|
86
|
+
const GENERIC_MIN_ENTROPY = 3.3;
|
|
87
|
+
const CODE_EXPR = /[()$`{}<>[\];,]|->|=>|\.\w/;
|
|
88
|
+
|
|
89
|
+
export function looksLikeSecretValue(value: string): boolean {
|
|
90
|
+
if (value.length < GENERIC_MIN_LENGTH || CODE_EXPR.test(value)) {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
const hasDigit = /[0-9]/.test(value);
|
|
94
|
+
const mixedCase = /[a-z]/.test(value) && /[A-Z]/.test(value);
|
|
95
|
+
if (!hasDigit && !mixedCase) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
return shannonEntropy(value) >= GENERIC_MIN_ENTROPY;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* The keyword names a credential assignment is spelled with (`password =`,
|
|
103
|
+
* `api_key:`). They carry no vendor literal, so each consumer reads the ones it
|
|
104
|
+
* always read, in its own order, and keeps its own threshold for the value.
|
|
105
|
+
*/
|
|
106
|
+
export const ASSIGNMENT_KEYWORDS = {
|
|
107
|
+
password: 'password',
|
|
108
|
+
passwd: 'passwd',
|
|
109
|
+
pwd: 'pwd',
|
|
110
|
+
secret: 'secret',
|
|
111
|
+
apiKey: 'api[_-]?key',
|
|
112
|
+
apikey: 'apikey',
|
|
113
|
+
accessToken: 'access[_-]?token',
|
|
114
|
+
authToken: 'auth[_-]?token',
|
|
115
|
+
clientSecret: 'client[_-]?secret',
|
|
116
|
+
privateKey: 'private[_-]?key',
|
|
117
|
+
token: 'token',
|
|
118
|
+
bearer: 'bearer',
|
|
119
|
+
} as const;
|
|
120
|
+
|
|
121
|
+
export type AssignmentKeyword = keyof typeof ASSIGNMENT_KEYWORDS;
|
|
122
|
+
|
|
123
|
+
export interface AssignmentShape {
|
|
124
|
+
readonly keywords: readonly AssignmentKeyword[];
|
|
125
|
+
/** Spelled around the keyword group, e.g. `\b` or a Unicode non-word lookaround. */
|
|
126
|
+
readonly before?: string;
|
|
127
|
+
readonly after?: string;
|
|
128
|
+
/** The keyword group captures instead of `(?:…)`. */
|
|
129
|
+
readonly capture?: boolean;
|
|
130
|
+
/** What follows `\s*[:=]\s*`; absent, the shape ends at the operator. */
|
|
131
|
+
readonly value?: string;
|
|
132
|
+
/** The whitespace around the operator; `\s*` when absent, `[ \t]*` to stay on one line. */
|
|
133
|
+
readonly gap?: string;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** Source of a keyword-assignment shape: keyword group, operator, then the consumer's value. */
|
|
137
|
+
export function assignmentSource(shape: AssignmentShape): string {
|
|
138
|
+
const alt = shape.keywords.map((k) => ASSIGNMENT_KEYWORDS[k]).join('|');
|
|
139
|
+
const group = shape.capture === true ? `(${alt})` : `(?:${alt})`;
|
|
140
|
+
const gap = shape.gap ?? '\\s*';
|
|
141
|
+
const head = `${shape.before ?? ''}${group}${shape.after ?? ''}${gap}[:=]`;
|
|
142
|
+
return shape.value === undefined ? head : `${head}${gap}${shape.value}`;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function assignmentPattern(shape: AssignmentShape, flags: string): RegExp {
|
|
146
|
+
return new RegExp(assignmentSource(shape), flags);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** An HTTP `Authorization` header name; everything after its colon is the credential. */
|
|
150
|
+
export const AUTHORIZATION_HEADER = 'authorization';
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Raw-key prefix families spelled as a class, for a surface that keeps the
|
|
154
|
+
* prefix and drops the value: group 1 is the prefix stem. Wider than the rows on
|
|
155
|
+
* purpose (`pk-`, `rk-`); a test checks each family still covers the table
|
|
156
|
+
* prefixes it claims.
|
|
157
|
+
*/
|
|
158
|
+
export const CLASS_SPELLED_PREFIXES = {
|
|
159
|
+
dashKeys: { family: '(sk|pk|rk)-', covers: ['sk-'] },
|
|
160
|
+
tokens: {
|
|
161
|
+
family: '(gh[pousr]|github_pat|xox[baprs])[-_]',
|
|
162
|
+
covers: ['ghp_', 'gho_', 'ghu_', 'ghs_', 'ghr_', 'github_pat_', 'xoxb-', 'xoxp-', 'xoxa-', 'xoxr-', 'xoxs-'],
|
|
163
|
+
},
|
|
164
|
+
} as const satisfies Readonly<Record<string, { readonly family: string; readonly covers: readonly string[] }>>;
|
|
165
|
+
|
|
166
|
+
// The nearest key marker after the header decides: an END carrying the same
|
|
167
|
+
// label as the header ends the block; another BEGIN, an END with a different
|
|
168
|
+
// label, or no marker at all means the extent is unproven. One sticky scan from
|
|
169
|
+
// the header to the nearest marker keeps this linear even over many headers.
|
|
170
|
+
const KEY_MARKER = /-----(BEGIN|END) ([A-Z ]*)PRIVATE KEY-----/g;
|
|
171
|
+
const BEGIN_LABEL = /^-----BEGIN ([A-Z ]*)PRIVATE KEY-----/;
|
|
172
|
+
|
|
173
|
+
export function pemBlockEnd(text: string, span: SpanBounds): number | null {
|
|
174
|
+
const label = BEGIN_LABEL.exec(text.slice(span.start, span.end))?.[1];
|
|
175
|
+
if (label === undefined) return null;
|
|
176
|
+
KEY_MARKER.lastIndex = span.end;
|
|
177
|
+
const m = KEY_MARKER.exec(text);
|
|
178
|
+
if (m === null || m[1] !== 'END' || m[2] !== label) return null;
|
|
179
|
+
return m.index + m[0].length;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* End of the first key-end marker of any label after the header, or null. For a
|
|
184
|
+
* masking surface that cannot refuse: when the block's extent is unproven it
|
|
185
|
+
* masks too much rather than leaving the key body behind.
|
|
186
|
+
*/
|
|
187
|
+
export function pemMaskEnd(text: string, span: SpanBounds): number | null {
|
|
188
|
+
KEY_MARKER.lastIndex = span.end;
|
|
189
|
+
for (let m = KEY_MARKER.exec(text); m !== null; m = KEY_MARKER.exec(text)) {
|
|
190
|
+
if (m[1] === 'END') return m.index + m[0].length;
|
|
191
|
+
}
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Identifier validators. A shape alone is never enough to replace an identifier:
|
|
196
|
+
// each row carries a checksum, a context word, or both, because a false positive
|
|
197
|
+
// here damages ordinary code and review text.
|
|
198
|
+
|
|
199
|
+
// IBAN length per country (ISO 13616 registry), packed as `CCnn` pairs. A country
|
|
200
|
+
// missing here leaves its IBANs unmasked, so the table errs towards inclusion.
|
|
201
|
+
const IBAN_LENGTHS =
|
|
202
|
+
'AD24AE23AL28AT20AZ28BA20BE16BG22BH22BI27BR29BY28CH21CR22CY28CZ24DE22DJ27DK18DO28EE20EG29ES24FI18FK18FO18FR27GB22GE22GI23GL18GR27GT28HN28HR21HU28IE22IL23IQ23IS26IT27JO30KW30KZ20LB28LC32LI21LT20LU20LV21LY25MC27MD24ME22MK19MN20MR27MT31MU30NI28NL18NO15OM23PK24PL28PS29PT25QA29RO24RS22RU33SA24SC31SD18SE24SI19SK24SM27SO23ST25SV28TL23TN24TR26UA29VA22VG24XK20YE30';
|
|
203
|
+
|
|
204
|
+
export function isValidIban(value: string): boolean {
|
|
205
|
+
const iban = value.replace(/ /g, '').toUpperCase();
|
|
206
|
+
const at = IBAN_LENGTHS.indexOf(iban.slice(0, 2));
|
|
207
|
+
if (at === -1 || at % 4 !== 0 || Number(IBAN_LENGTHS.slice(at + 2, at + 4)) !== iban.length) return false;
|
|
208
|
+
if (!/^[A-Z]{2}[0-9]{2}[A-Z0-9]+$/.test(iban)) return false;
|
|
209
|
+
let rest = 0;
|
|
210
|
+
for (const ch of iban.slice(4) + iban.slice(0, 4)) {
|
|
211
|
+
const n = ch <= '9' ? ch.charCodeAt(0) - 48 : ch.charCodeAt(0) - 55;
|
|
212
|
+
rest = n > 9 ? (rest * 100 + n) % 97 : (rest * 10 + n) % 97;
|
|
213
|
+
}
|
|
214
|
+
return rest === 1;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export function passesLuhn(value: string): boolean {
|
|
218
|
+
const digits = value.replace(/[ -]/g, '');
|
|
219
|
+
if (!/^[0-9]{13,19}$/.test(digits) || /^(.)\1+$/.test(digits)) return false;
|
|
220
|
+
let sum = 0;
|
|
221
|
+
for (let i = 0; i < digits.length; i += 1) {
|
|
222
|
+
let d = digits.charCodeAt(digits.length - 1 - i) - 48;
|
|
223
|
+
if (i % 2 === 1) {
|
|
224
|
+
d *= 2;
|
|
225
|
+
if (d > 9) d -= 9;
|
|
226
|
+
}
|
|
227
|
+
sum += d;
|
|
228
|
+
}
|
|
229
|
+
return sum % 10 === 0;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/** E.164 bounds: a country code plus at most 15 digits in all; never a date after a diff marker. */
|
|
233
|
+
function phoneDigits(min: number, max: number): (value: string) => boolean {
|
|
234
|
+
return (value) => {
|
|
235
|
+
if (/^\+?[0-9]{4}-[0-9]{2}-[0-9]{2}/.test(value)) return false;
|
|
236
|
+
const n = value.replace(/[^0-9]/g, '').length;
|
|
237
|
+
return n >= min && n <= max;
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* German tax identification number: 11 digits, no leading zero, one digit of
|
|
243
|
+
* the first ten repeated two or three times and no other repeated, and an
|
|
244
|
+
* ISO 7064 MOD 11,10 check digit.
|
|
245
|
+
*/
|
|
246
|
+
export function isValidGermanTaxId(value: string): boolean {
|
|
247
|
+
const d = value.replace(/ /g, '');
|
|
248
|
+
if (!/^[1-9][0-9]{10}$/.test(d)) return false;
|
|
249
|
+
const counts = new Map<string, number>();
|
|
250
|
+
for (const ch of d.slice(0, 10)) counts.set(ch, (counts.get(ch) ?? 0) + 1);
|
|
251
|
+
const repeated = [...counts.values()].filter((c) => c > 1);
|
|
252
|
+
if (repeated.length !== 1 || (repeated[0] as number) > 3) return false;
|
|
253
|
+
let product = 10;
|
|
254
|
+
for (let i = 0; i < 10; i += 1) {
|
|
255
|
+
let sum = (d.charCodeAt(i) - 48 + product) % 10;
|
|
256
|
+
if (sum === 0) sum = 10;
|
|
257
|
+
product = (sum * 2) % 11;
|
|
258
|
+
}
|
|
259
|
+
const check = (11 - product) % 10;
|
|
260
|
+
return check === d.charCodeAt(10) - 48;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/** US social security number: no 000, 666 or 9xx area, no 00 group, no 0000 serial. */
|
|
264
|
+
export function isValidUsSsn(value: string): boolean {
|
|
265
|
+
const m = /^([0-9]{3})-([0-9]{2})-([0-9]{4})$/.exec(value);
|
|
266
|
+
if (m === null) return false;
|
|
267
|
+
const [area, group, serial] = [m[1] as string, m[2] as string, m[3] as string];
|
|
268
|
+
return area !== '000' && area !== '666' && !area.startsWith('9') && group !== '00' && serial !== '0000';
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Addresses that name no one: documentation and reserved domains (RFC 2606,
|
|
272
|
+
// RFC 6761), no-reply senders, and image-density file names (`logo@2x.png`).
|
|
273
|
+
const EMAIL_EXCLUSIONS: readonly RegExp[] = [
|
|
274
|
+
/^git@/i,
|
|
275
|
+
/@(?:[a-z0-9-]+\.)*(?:example\.(?:com|net|org)|example|test|invalid|localhost|local)$/i,
|
|
276
|
+
/^(?:no-?reply|do-?not-?reply|noreply\+[^@]*)@/i,
|
|
277
|
+
/@users\.noreply\.github\.com$/i,
|
|
278
|
+
/@[0-9]x\.[a-z]+$/i,
|
|
279
|
+
/\.(?:png|jpe?g|gif|svg|webp|ico|js|mjs|cjs|ts|tsx|css|json|ya?ml|lock)$/i,
|
|
280
|
+
];
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* The repository's own published identities (package author, copyright holder),
|
|
284
|
+
* held as keyed 64-bit FNV-1a digests of the lower-cased address so the list
|
|
285
|
+
* reads as noise. A digest hides an address from a reader, not from someone who
|
|
286
|
+
* guesses it; the list exists to keep the tree's own metadata out of a review's
|
|
287
|
+
* placeholder count.
|
|
288
|
+
*/
|
|
289
|
+
const EMAIL_ALLOWLIST_DIGESTS: ReadonlySet<string> = new Set(['924acfa874365f8a', '8066a43fc18158bf']);
|
|
290
|
+
|
|
291
|
+
export function emailAllowlistDigest(address: string): string {
|
|
292
|
+
let h = 0xcbf29ce484222325n;
|
|
293
|
+
for (const ch of `egress-email-allowlist-v1\u0000${address.toLowerCase()}`) {
|
|
294
|
+
h ^= BigInt(ch.codePointAt(0) as number);
|
|
295
|
+
h = (h * 0x100000001b3n) & 0xffffffffffffffffn;
|
|
296
|
+
}
|
|
297
|
+
return h.toString(16).padStart(16, '0');
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function isReportableEmail(value: string): boolean {
|
|
301
|
+
return !EMAIL_ALLOWLIST_DIGESTS.has(emailAllowlistDigest(value));
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Quantifiers are unbounded where the pattern is linear without a bound, so a
|
|
305
|
+
// long value is matched whole and no suffix survives a replacement. Each rule's
|
|
306
|
+
// argument for why it is linear lives in `egress_rules_linearity.ts`, kept out
|
|
307
|
+
// of this module because no runtime path reads it; a test refuses a row without
|
|
308
|
+
// one. A bound remains only where the unbounded form was quadratic, and what
|
|
309
|
+
// that bound loses is published in DETECTION_CEILINGS.
|
|
310
|
+
export const EGRESS_RULES: readonly EgressRule[] = [
|
|
311
|
+
{
|
|
312
|
+
rule: 'anthropic-api-key',
|
|
313
|
+
type: 'APIKEY',
|
|
314
|
+
prefixes: ['sk-ant-'],
|
|
315
|
+
class: 'credential',
|
|
316
|
+
replacement: 'detection',
|
|
317
|
+
kind: 'anthropic-api-key',
|
|
318
|
+
pattern: /sk-ant-[A-Za-z0-9_-]{20,}/g,
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
rule: 'anthropic-project-key',
|
|
322
|
+
type: 'APIKEY',
|
|
323
|
+
prefixes: ['sk-proj-'],
|
|
324
|
+
class: 'credential',
|
|
325
|
+
replacement: 'detection',
|
|
326
|
+
kind: 'anthropic-api-key',
|
|
327
|
+
pattern: /sk-proj-[A-Za-z0-9_-]{20,}/g,
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
rule: 'aws-access-key',
|
|
331
|
+
type: 'APIKEY',
|
|
332
|
+
prefixes: ['AKIA'],
|
|
333
|
+
class: 'credential',
|
|
334
|
+
replacement: 'detection',
|
|
335
|
+
pattern: /AKIA[0-9A-Z]{16}/g,
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
rule: 'google-api-key',
|
|
339
|
+
type: 'APIKEY',
|
|
340
|
+
prefixes: ['AIza'],
|
|
341
|
+
class: 'credential',
|
|
342
|
+
replacement: 'detection',
|
|
343
|
+
pattern: /AIza[0-9A-Za-z_-]{35}/g,
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
rule: 'github-pat',
|
|
347
|
+
type: 'TOKEN',
|
|
348
|
+
prefixes: ['ghp_'],
|
|
349
|
+
class: 'credential',
|
|
350
|
+
replacement: 'detection',
|
|
351
|
+
pattern: /ghp_[0-9A-Za-z]{36}/g,
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
rule: 'github-fine-grained-pat',
|
|
355
|
+
type: 'TOKEN',
|
|
356
|
+
prefixes: ['github_pat_'],
|
|
357
|
+
class: 'credential',
|
|
358
|
+
replacement: 'detection',
|
|
359
|
+
kind: 'github-pat',
|
|
360
|
+
pattern: /github_pat_[0-9A-Za-z_]{22,}/g,
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
rule: 'openai-api-key',
|
|
364
|
+
type: 'APIKEY',
|
|
365
|
+
prefixes: ['sk-'],
|
|
366
|
+
class: 'credential',
|
|
367
|
+
replacement: 'detection',
|
|
368
|
+
tokenStart: true,
|
|
369
|
+
pattern: /(?<![A-Za-z0-9])sk-[A-Za-z0-9]{20,}/g,
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
rule: 'google-oauth-token',
|
|
373
|
+
type: 'TOKEN',
|
|
374
|
+
prefixes: ['ya29.'],
|
|
375
|
+
class: 'credential',
|
|
376
|
+
replacement: 'detection',
|
|
377
|
+
tokenStart: true,
|
|
378
|
+
pattern: /(?<![A-Za-z0-9])ya29\.[0-9A-Za-z_-]{20,}/g,
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
rule: 'github-app-token',
|
|
382
|
+
type: 'TOKEN',
|
|
383
|
+
prefixes: ['gho_', 'ghu_', 'ghs_', 'ghr_'],
|
|
384
|
+
class: 'credential',
|
|
385
|
+
replacement: 'detection',
|
|
386
|
+
pattern: /gh[ousr]_[A-Za-z0-9]{36,}/g,
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
rule: 'xai-api-key',
|
|
390
|
+
type: 'APIKEY',
|
|
391
|
+
prefixes: ['xai-'],
|
|
392
|
+
class: 'credential',
|
|
393
|
+
replacement: 'detection',
|
|
394
|
+
tokenStart: true,
|
|
395
|
+
pattern: /(?<![A-Za-z0-9])xai-[A-Za-z0-9]{20,}/g,
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
rule: 'perplexity-api-key',
|
|
399
|
+
type: 'APIKEY',
|
|
400
|
+
prefixes: ['pplx-'],
|
|
401
|
+
class: 'credential',
|
|
402
|
+
replacement: 'detection',
|
|
403
|
+
pattern: /pplx-[A-Za-z0-9]{20,}/g,
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
rule: 'groq-api-key',
|
|
407
|
+
type: 'APIKEY',
|
|
408
|
+
prefixes: ['gsk_'],
|
|
409
|
+
class: 'credential',
|
|
410
|
+
replacement: 'detection',
|
|
411
|
+
tokenStart: true,
|
|
412
|
+
pattern: /(?<![A-Za-z0-9])gsk_[A-Za-z0-9]{20,}/g,
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
rule: 'huggingface-token',
|
|
416
|
+
type: 'TOKEN',
|
|
417
|
+
prefixes: ['hf_'],
|
|
418
|
+
class: 'credential',
|
|
419
|
+
replacement: 'detection',
|
|
420
|
+
tokenStart: true,
|
|
421
|
+
pattern: /(?<![A-Za-z0-9])hf_[A-Za-z0-9]{30,}/g,
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
rule: 'nvidia-api-key',
|
|
425
|
+
type: 'APIKEY',
|
|
426
|
+
prefixes: ['nvapi-'],
|
|
427
|
+
class: 'credential',
|
|
428
|
+
replacement: 'detection',
|
|
429
|
+
tokenStart: true,
|
|
430
|
+
pattern: /(?<![A-Za-z0-9])nvapi-[A-Za-z0-9_-]{40,}/g,
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
rule: 'replicate-api-token',
|
|
434
|
+
type: 'TOKEN',
|
|
435
|
+
prefixes: ['r8_'],
|
|
436
|
+
class: 'credential',
|
|
437
|
+
replacement: 'detection',
|
|
438
|
+
tokenStart: true,
|
|
439
|
+
pattern: /(?<![A-Za-z0-9])r8_[A-Za-z0-9]{30,}/g,
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
rule: 'jwt',
|
|
443
|
+
type: 'TOKEN',
|
|
444
|
+
class: 'credential',
|
|
445
|
+
replacement: 'detection',
|
|
446
|
+
pattern:
|
|
447
|
+
/(?<![A-Za-z0-9_-])(?=((?:(?!eyJ)[A-Za-z0-9_-])*))\1(eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,})/dg,
|
|
448
|
+
valueGroup: 2,
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
rule: 'stripe-secret-key',
|
|
452
|
+
type: 'APIKEY',
|
|
453
|
+
prefixes: ['sk_live_', 'sk_test_'],
|
|
454
|
+
class: 'credential',
|
|
455
|
+
replacement: 'detection',
|
|
456
|
+
pattern: /sk_(?:live|test)_[0-9A-Za-z]{16,}/g,
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
rule: 'slack-token',
|
|
460
|
+
type: 'TOKEN',
|
|
461
|
+
prefixes: ['xoxb-', 'xoxp-', 'xoxa-', 'xoxr-', 'xoxs-'],
|
|
462
|
+
class: 'credential',
|
|
463
|
+
replacement: 'detection',
|
|
464
|
+
pattern: /xox[baprs]-[0-9A-Za-z-]{10,}/g,
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
rule: 'pem-private-key',
|
|
468
|
+
type: 'PRIVATEKEY',
|
|
469
|
+
class: 'credential',
|
|
470
|
+
|
|
471
|
+
pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----/g,
|
|
472
|
+
replacement: { through: pemBlockEnd },
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
rule: 'db-connection-uri',
|
|
476
|
+
type: 'DBURI',
|
|
477
|
+
class: 'credential',
|
|
478
|
+
replacement: 'detection',
|
|
479
|
+
pattern: /(?<![a-z0-9+.-])(?=((?:(?!\b[a-z])[a-z0-9+.-])*))\1(\b[a-z][a-z0-9+.-]*:\/\/[^\s:/@]+:[^\s:/@]+@)/dg,
|
|
480
|
+
valueGroup: 2,
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
rule: 'generic-assignment',
|
|
484
|
+
type: 'SECRET',
|
|
485
|
+
class: 'credential',
|
|
486
|
+
replacement: 'detection',
|
|
487
|
+
pattern: assignmentPattern(
|
|
488
|
+
{
|
|
489
|
+
keywords: ['password', 'passwd', 'pwd', 'secret', 'apiKey', 'accessToken', 'authToken'],
|
|
490
|
+
value: `['"]?([^'"\\s]{8,})['"]?`,
|
|
491
|
+
},
|
|
492
|
+
'dgi',
|
|
493
|
+
),
|
|
494
|
+
valueGroup: 1,
|
|
495
|
+
validator: looksLikeSecretValue,
|
|
496
|
+
},
|
|
497
|
+
{
|
|
498
|
+
rule: 'iban',
|
|
499
|
+
type: 'IBAN',
|
|
500
|
+
class: 'identifier',
|
|
501
|
+
replacement: 'detection',
|
|
502
|
+
pattern: /(?<![A-Za-z0-9])[A-Z]{2}[0-9]{2}(?: ?[A-Z0-9]{4}){2,7}(?: ?[A-Z0-9]{1,3})?(?![A-Za-z0-9])/g,
|
|
503
|
+
validator: isValidIban,
|
|
504
|
+
},
|
|
505
|
+
{
|
|
506
|
+
rule: 'payment-card',
|
|
507
|
+
type: 'CARD',
|
|
508
|
+
class: 'identifier',
|
|
509
|
+
replacement: 'detection',
|
|
510
|
+
pattern: /(?<![0-9])[0-9](?:[ -]?[0-9]){12,18}(?![0-9])/g,
|
|
511
|
+
validator: passesLuhn,
|
|
512
|
+
context: {
|
|
513
|
+
words: /\b(?:card|credit|debit|visa|mastercard|amex|maestro|kreditkarte|karte|kartennummer|payment|zahlung)\b/i,
|
|
514
|
+
window: 48,
|
|
515
|
+
},
|
|
516
|
+
},
|
|
517
|
+
{
|
|
518
|
+
rule: 'email',
|
|
519
|
+
type: 'EMAIL',
|
|
520
|
+
class: 'identifier',
|
|
521
|
+
replacement: 'detection',
|
|
522
|
+
pattern:
|
|
523
|
+
/(?<![A-Za-z0-9._%+\\-])[A-Za-z0-9][A-Za-z0-9._%+-]{0,63}@(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.){1,8}[A-Za-z]{2,24}(?![A-Za-z0-9-])/g,
|
|
524
|
+
exclusions: EMAIL_EXCLUSIONS,
|
|
525
|
+
validator: isReportableEmail,
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
rule: 'phone-international',
|
|
529
|
+
type: 'PHONE',
|
|
530
|
+
class: 'identifier',
|
|
531
|
+
replacement: 'detection',
|
|
532
|
+
pattern: /(?<![A-Za-z0-9+])\+[1-9][0-9]{0,2}(?:[ ./-]?(?:\([0-9]{1,6}\)|(?=([0-9]{1,6}))\1)){1,5}(?![0-9])/g,
|
|
533
|
+
validator: phoneDigits(8, 15),
|
|
534
|
+
},
|
|
535
|
+
{
|
|
536
|
+
rule: 'phone-national',
|
|
537
|
+
type: 'PHONE',
|
|
538
|
+
class: 'identifier',
|
|
539
|
+
replacement: 'detection',
|
|
540
|
+
pattern: /(?<![A-Za-z0-9+(])(?:\(0[1-9][0-9]{1,4}\)|0[1-9][0-9]{1,4})(?:[ ./-]?(?=([0-9]{2,8}))\1){1,3}(?![0-9])/g,
|
|
541
|
+
validator: phoneDigits(7, 13),
|
|
542
|
+
context: { words: /\b(?:tel|telefon|telephone|phone|mobil|mobile|cell|fax|handy|call|ruf)\b/i, window: 32 },
|
|
543
|
+
},
|
|
544
|
+
{
|
|
545
|
+
rule: 'phone-nanp',
|
|
546
|
+
type: 'PHONE',
|
|
547
|
+
class: 'identifier',
|
|
548
|
+
replacement: 'detection',
|
|
549
|
+
pattern: /(?<![A-Za-z0-9+(-])(?:\+?1[ .-]?)?(?:\([2-9][0-9]{2}\) ?|[2-9][0-9]{2}[ .-]?)[2-9][0-9]{2}[ .-]?[0-9]{4}(?![0-9-])/g,
|
|
550
|
+
context: { words: /\b(?:tel|telephone|phone|mobile|cell|fax|call)\b/i, window: 32 },
|
|
551
|
+
},
|
|
552
|
+
{
|
|
553
|
+
rule: 'de-tax-id',
|
|
554
|
+
type: 'TAXID',
|
|
555
|
+
class: 'identifier',
|
|
556
|
+
replacement: 'detection',
|
|
557
|
+
pattern: /(?<![0-9])[1-9](?: ?[0-9]){10}(?![0-9])/g,
|
|
558
|
+
validator: isValidGermanTaxId,
|
|
559
|
+
context: {
|
|
560
|
+
words: /\b(?:steuer-?id|steuer-?identifikationsnummer|identifikationsnummer|idnr|tax[ -]?id|tin)\b/i,
|
|
561
|
+
window: 48,
|
|
562
|
+
},
|
|
563
|
+
},
|
|
564
|
+
{
|
|
565
|
+
rule: 'us-ssn',
|
|
566
|
+
type: 'SSN',
|
|
567
|
+
class: 'identifier',
|
|
568
|
+
replacement: 'detection',
|
|
569
|
+
pattern: /(?<![0-9-])[0-9]{3}-[0-9]{2}-[0-9]{4}(?![0-9-])/g,
|
|
570
|
+
validator: isValidUsSsn,
|
|
571
|
+
},
|
|
572
|
+
];
|
|
573
|
+
|
|
574
|
+
// A value that is a type word, a literal, a language keyword or a credential
|
|
575
|
+
// keyword itself (`password: 'password'`) is code, not a secret, whatever its key.
|
|
576
|
+
const TYPE_WORD =
|
|
577
|
+
/^(?:string|number|boolean|bigint|unknown|any|never|void|undefined|null|true|false|none|nil|new|typeof|keyof|await|async|function|const|let|var|return|this|self|class|import|require|readonly|export|default|yield|password|passwd|pwd|secret|token|bearer|api[_-]?key|apikey)$/i;
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* A credential keyword is a key, not a suffix: `mytoken=` and `notsecret=` are
|
|
581
|
+
* other words that happen to end in one. A separator is not a letter, so
|
|
582
|
+
* `client_secret` and `api-key` still read as the keyword they contain.
|
|
583
|
+
*/
|
|
584
|
+
const KEY_START = '(?<![A-Za-z0-9])';
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* One value, whichever delimiter bounds it, as four alternatives read in order
|
|
588
|
+
* by `valueGroup: [2, 3, 4, 5]`. The shape it replaces — an optional quote
|
|
589
|
+
* around a capture that forbade whitespace — matched `"correct` of
|
|
590
|
+
* `password = "correct horse battery staple"` and left the rest of the
|
|
591
|
+
* credential in the outbound body (council, 2026-10-21, both seats).
|
|
592
|
+
*
|
|
593
|
+
* A complete quoted value is captured without its quotes, so the validator
|
|
594
|
+
* still reads `password: 'password'` as the type word it is. An UNTERMINATED
|
|
595
|
+
* quote takes the rest of the line: its extent is unprovable, and the house
|
|
596
|
+
* rule for an unprovable extent is to cover too much rather than leave the
|
|
597
|
+
* value behind (`pemMaskEnd`). Each alternative is anchored at the same
|
|
598
|
+
* position and none can backtrack into another, so the shape stays linear.
|
|
599
|
+
*/
|
|
600
|
+
const QUOTED_OR_BARE_VALUE = `(?:"([^"\\n]*)"|'([^'\\n]*)'|["']([^\\n]+)|([^\\s'"]+))`;
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* Credential shapes at a reviewer's threshold, for a surface that REPLACES a
|
|
604
|
+
* value it would otherwise have masked with its whole line (the council
|
|
605
|
+
* bundle, step 3.3). Not in EGRESS_RULES: a refusing surface or the commit
|
|
606
|
+
* scanner would refuse ordinary code on them. Any value after a credential
|
|
607
|
+
* keyword that is not a code expression or a type word, on the same line, and
|
|
608
|
+
* every byte after the colon of a line that opens with an `Authorization`
|
|
609
|
+
* header.
|
|
610
|
+
*
|
|
611
|
+
* The header row being HERE and not in EGRESS_RULES is a stated gap of the
|
|
612
|
+
* main table: an `Authorization: Bearer <opaque token>` with no vendor prefix
|
|
613
|
+
* and no JWT shape passes the replacing and refusing surfaces unchanged, and
|
|
614
|
+
* so does any value under the `token`, `bearer`, `clientSecret` or
|
|
615
|
+
* `privateKey` keywords, which no EGRESS_RULES row reads.
|
|
616
|
+
*/
|
|
617
|
+
export const REVIEW_CREDENTIAL_ROWS: readonly EgressRule[] = [
|
|
618
|
+
{
|
|
619
|
+
rule: 'review-assignment',
|
|
620
|
+
type: 'SECRET',
|
|
621
|
+
class: 'credential',
|
|
622
|
+
replacement: 'detection',
|
|
623
|
+
pattern: assignmentPattern(
|
|
624
|
+
{
|
|
625
|
+
keywords: ['apiKey', 'secret', 'token', 'password'],
|
|
626
|
+
before: KEY_START,
|
|
627
|
+
capture: true,
|
|
628
|
+
gap: '[ \\t]*',
|
|
629
|
+
value: QUOTED_OR_BARE_VALUE,
|
|
630
|
+
},
|
|
631
|
+
'dgi',
|
|
632
|
+
),
|
|
633
|
+
valueGroup: [2, 3, 4, 5],
|
|
634
|
+
// Group 5 is the bare value. A quoted one is a literal, where `,` `$`
|
|
635
|
+
// or `.` is password punctuation rather than code, so only a bare value
|
|
636
|
+
// is read as a code expression.
|
|
637
|
+
validator: (v, g) => (g !== 5 || !CODE_EXPR.test(v)) && !TYPE_WORD.test(v),
|
|
638
|
+
},
|
|
639
|
+
{
|
|
640
|
+
rule: 'review-authorization-header',
|
|
641
|
+
type: 'TOKEN',
|
|
642
|
+
class: 'credential',
|
|
643
|
+
replacement: 'detection',
|
|
644
|
+
pattern: new RegExp(`^[ \\t]*${AUTHORIZATION_HEADER}:[ \\t]*(\\S[^\\n]*)`, 'dgim'),
|
|
645
|
+
valueGroup: 1,
|
|
646
|
+
},
|
|
647
|
+
];
|
|
648
|
+
|
|
649
|
+
/** The credential rows alone, for consumers whose verdict reads credentials only. */
|
|
650
|
+
export const CREDENTIAL_RULES: readonly EgressRule[] = EGRESS_RULES.filter((r) => r.class === 'credential');
|
|
651
|
+
export const IDENTIFIER_RULES: readonly EgressRule[] = EGRESS_RULES.filter((r) => r.class === 'identifier');
|
|
652
|
+
|
|
653
|
+
/** Every raw-key prefix the table declares, longest first. */
|
|
654
|
+
export const CREDENTIAL_PREFIXES: readonly string[] = EGRESS_RULES.flatMap((r) => r.prefixes ?? []).sort(
|
|
655
|
+
(a, b) => b.length - a.length,
|
|
656
|
+
);
|
|
657
|
+
|
|
658
|
+
/** The prefixes one row declares; throws on an unknown rule so a rename cannot go silent. */
|
|
659
|
+
export function prefixesOf(rule: string): readonly string[] {
|
|
660
|
+
const row = EGRESS_RULES.find((r) => r.rule === rule);
|
|
661
|
+
if (row === undefined) throw new Error(`egress rule ${rule}: no such row`);
|
|
662
|
+
return row.prefixes ?? [];
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/** A row's first declared prefix — the shape a key file of that vendor starts with. */
|
|
666
|
+
export function vendorPrefix(rule: string): string {
|
|
667
|
+
const first = prefixesOf(rule)[0];
|
|
668
|
+
if (first === undefined) throw new Error(`egress rule ${rule}: declares no prefix`);
|
|
669
|
+
return first;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
const TOKEN_START_PREFIXES: ReadonlySet<string> = new Set(
|
|
673
|
+
EGRESS_RULES.filter((r) => r.tokenStart === true).flatMap((r) => r.prefixes ?? []),
|
|
674
|
+
);
|
|
675
|
+
|
|
676
|
+
/**
|
|
677
|
+
* A raw-key prefix followed by at least `minTail` key characters. Coarser than
|
|
678
|
+
* the rows on purpose: it is for surfaces that refuse or mask on shape alone,
|
|
679
|
+
* where a short or truncated key must still be caught.
|
|
680
|
+
*
|
|
681
|
+
* `boundary: 'row'` (the default) holds a prefix to a token start exactly where
|
|
682
|
+
* its own row declares `tokenStart`, so the pattern never misses what the row
|
|
683
|
+
* would catch and a short prefix (`sk-`) does not fire inside a word.
|
|
684
|
+
* `boundary: 'never'` drops the token start for every prefix: it is for a
|
|
685
|
+
* consumer whose own pre-table reading matched mid-word, and dropping it there
|
|
686
|
+
* is what keeps that consumer from narrowing. `tail` narrows the key class.
|
|
687
|
+
*/
|
|
688
|
+
export function rawKeyPrefixPattern(
|
|
689
|
+
minTail: number,
|
|
690
|
+
prefixes: readonly string[] = CREDENTIAL_PREFIXES,
|
|
691
|
+
opts: { readonly boundary?: 'row' | 'never'; readonly tail?: string } = {},
|
|
692
|
+
): RegExp {
|
|
693
|
+
const alt = [...prefixes]
|
|
694
|
+
.sort((a, b) => b.length - a.length)
|
|
695
|
+
.map((p) => {
|
|
696
|
+
const lit = p.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
697
|
+
return opts.boundary !== 'never' && TOKEN_START_PREFIXES.has(p) ? `(?<![A-Za-z0-9])${lit}` : lit;
|
|
698
|
+
})
|
|
699
|
+
.join('|');
|
|
700
|
+
return new RegExp(`(?:${alt})[${opts.tail ?? 'A-Za-z0-9_-'}]{${minTail},}`, 'g');
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
/**
|
|
704
|
+
* End of the bytes a replacement of `span` must remove, or null when the row
|
|
705
|
+
* cannot prove it (the caller then decides: a refusing surface refuses, a
|
|
706
|
+
* masking surface masks the detection span).
|
|
707
|
+
*/
|
|
708
|
+
export function replacementEnd(text: string, span: EgressSpan): number | null {
|
|
709
|
+
const row = EGRESS_RULES.find((r) => r.rule === span.rule);
|
|
710
|
+
if (row === undefined) return null;
|
|
711
|
+
if (row.replacement === 'detection') return span.end;
|
|
712
|
+
const end = row.replacement.through(text, span);
|
|
713
|
+
return end === null || end < span.end ? null : end;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
* End of the bytes a MASKING surface removes for `span`. A surface that cannot
|
|
718
|
+
* refuse must not leave key material behind when the row cannot prove the extent:
|
|
719
|
+
* an unproven key block is masked through the nearest END marker of any label,
|
|
720
|
+
* and only a span with nothing better falls back to its detection span. Every
|
|
721
|
+
* masking consumer reads this, so the fallback is decided once.
|
|
722
|
+
*/
|
|
723
|
+
export function maskingEnd(text: string, span: EgressSpan): number {
|
|
724
|
+
return replacementEnd(text, span) ?? (span.rule === 'pem-private-key' ? pemMaskEnd(text, span) : null) ?? span.end;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* Returns a description of the first unbounded quantifier (`+`, `*`, `{n,}`)
|
|
729
|
+
* outside a character class, or null. Escapes and classes are skipped.
|
|
730
|
+
*/
|
|
731
|
+
export function findUnboundedQuantifier(pattern: RegExp): string | null {
|
|
732
|
+
const src = pattern.source;
|
|
733
|
+
let inClass = false;
|
|
734
|
+
for (let i = 0; i < src.length; i++) {
|
|
735
|
+
const ch = src[i];
|
|
736
|
+
if (ch === '\\') {
|
|
737
|
+
i++;
|
|
738
|
+
continue;
|
|
739
|
+
}
|
|
740
|
+
if (inClass) {
|
|
741
|
+
if (ch === ']') inClass = false;
|
|
742
|
+
continue;
|
|
743
|
+
}
|
|
744
|
+
if (ch === '[') {
|
|
745
|
+
inClass = true;
|
|
746
|
+
continue;
|
|
747
|
+
}
|
|
748
|
+
if (ch === '+' || ch === '*') {
|
|
749
|
+
return `'${ch}' at ${i}`;
|
|
750
|
+
}
|
|
751
|
+
if (ch === '{') {
|
|
752
|
+
const m = /^\{\d+,\}/.exec(src.slice(i));
|
|
753
|
+
if (m) return `'${m[0]}' at ${i}`;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
return null;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
const CLASS_RANK: Readonly<Record<EgressClass, number>> = {
|
|
760
|
+
credential: 1,
|
|
761
|
+
identifier: 0,
|
|
762
|
+
};
|
|
763
|
+
|
|
764
|
+
/** A global or sticky regex keeps lastIndex between calls; reset it so every call tests the whole value. */
|
|
765
|
+
function testWholeValue(re: RegExp, value: string): boolean {
|
|
766
|
+
re.lastIndex = 0;
|
|
767
|
+
return re.test(value);
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
/**
|
|
771
|
+
* Applies every field of a row to one regex match: value extraction from the
|
|
772
|
+
* engine's capture offsets, exclusions, the context window and the validator.
|
|
773
|
+
* The single place both readers of the table evaluate a candidate.
|
|
774
|
+
*/
|
|
775
|
+
/**
|
|
776
|
+
* The capture group this match put the value in. `'whole-match'` is a rule that
|
|
777
|
+
* declares none. `null` is a rule that declares alternatives and matched none
|
|
778
|
+
* of them — the match is then discarded, never silently read as the whole
|
|
779
|
+
* match, which would hand a replacer the keyword along with the value.
|
|
780
|
+
*/
|
|
781
|
+
function valueGroupOf(r: EgressRule, m: RegExpExecArray): number | 'whole-match' | null {
|
|
782
|
+
if (r.valueGroup === undefined) return 'whole-match';
|
|
783
|
+
if (typeof r.valueGroup === 'number') return r.valueGroup;
|
|
784
|
+
return r.valueGroup.find((g) => m[g] !== undefined) ?? null;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
export function evaluateMatch(
|
|
788
|
+
r: EgressRule,
|
|
789
|
+
text: string,
|
|
790
|
+
m: RegExpExecArray,
|
|
791
|
+
): { start: number; end: number; validated: boolean } | null {
|
|
792
|
+
const group = valueGroupOf(r, m);
|
|
793
|
+
if (group === null) return null;
|
|
794
|
+
const value = group === 'whole-match' ? m[0] : m[group];
|
|
795
|
+
if (value === undefined || value.length === 0) return null;
|
|
796
|
+
const start = group === 'whole-match' ? m.index : (m.indices?.[group]?.[0] ?? -1);
|
|
797
|
+
if (start < 0) {
|
|
798
|
+
throw new Error(`egress rule ${r.rule}: a valueGroup rule needs the d flag for capture offsets`);
|
|
799
|
+
}
|
|
800
|
+
const end = start + value.length;
|
|
801
|
+
if (r.exclusions?.some((x) => testWholeValue(x, value))) return null;
|
|
802
|
+
if (r.context) {
|
|
803
|
+
const lo = Math.max(0, start - r.context.window);
|
|
804
|
+
const hi = Math.min(text.length, end + r.context.window);
|
|
805
|
+
const around = text.slice(lo, start) + ' ' + text.slice(end, hi);
|
|
806
|
+
r.context.words.lastIndex = 0;
|
|
807
|
+
if (!r.context.words.test(around)) return null;
|
|
808
|
+
}
|
|
809
|
+
if (r.validator) {
|
|
810
|
+
return r.validator(value, group) ? { start, end, validated: true } : null;
|
|
811
|
+
}
|
|
812
|
+
return { start, end, validated: false };
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/** Candidate spans per rule, before overlap resolution. */
|
|
816
|
+
export function findSpans(text: string, rules: readonly EgressRule[] = EGRESS_RULES): EgressSpan[] {
|
|
817
|
+
const out: EgressSpan[] = [];
|
|
818
|
+
for (const r of rules) {
|
|
819
|
+
r.pattern.lastIndex = 0;
|
|
820
|
+
let m: RegExpExecArray | null;
|
|
821
|
+
while ((m = r.pattern.exec(text)) !== null) {
|
|
822
|
+
if (m[0].length === 0) {
|
|
823
|
+
r.pattern.lastIndex += 1;
|
|
824
|
+
continue;
|
|
825
|
+
}
|
|
826
|
+
const c = evaluateMatch(r, text, m);
|
|
827
|
+
if (c === null) continue;
|
|
828
|
+
const { start, end, validated } = c;
|
|
829
|
+
out.push({
|
|
830
|
+
rule: r.rule,
|
|
831
|
+
type: r.type,
|
|
832
|
+
class: r.class,
|
|
833
|
+
start,
|
|
834
|
+
end,
|
|
835
|
+
validated,
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
return out;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
/**
|
|
843
|
+
* Resolves overlaps: the more sensitive class wins, then the validated span,
|
|
844
|
+
* then the longer one, then the earlier one. Result is ordered by start.
|
|
845
|
+
*/
|
|
846
|
+
export function resolveOverlaps(spans: readonly EgressSpan[]): EgressSpan[] {
|
|
847
|
+
const ranked = [...spans].sort(
|
|
848
|
+
(a, b) =>
|
|
849
|
+
CLASS_RANK[b.class] - CLASS_RANK[a.class] ||
|
|
850
|
+
Number(b.validated) - Number(a.validated) ||
|
|
851
|
+
b.end - b.start - (a.end - a.start) ||
|
|
852
|
+
a.start - b.start,
|
|
853
|
+
);
|
|
854
|
+
const kept: EgressSpan[] = [];
|
|
855
|
+
for (const s of ranked) {
|
|
856
|
+
if (!kept.some((k) => s.start < k.end && k.start < s.end)) kept.push(s);
|
|
857
|
+
}
|
|
858
|
+
return kept.sort((a, b) => a.start - b.start);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
export function detect(text: string, rules: readonly EgressRule[] = EGRESS_RULES): EgressSpan[] {
|
|
862
|
+
return resolveOverlaps(findSpans(text, rules));
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
/**
|
|
866
|
+
* Replaces non-overlapping spans right to left, so every offset still refers
|
|
867
|
+
* to the original text. `index` is the span's position in start order.
|
|
868
|
+
*/
|
|
869
|
+
export function replaceSpans(
|
|
870
|
+
text: string,
|
|
871
|
+
spans: readonly EgressSpan[],
|
|
872
|
+
replacement: (span: EgressSpan, index: number) => string,
|
|
873
|
+
): string {
|
|
874
|
+
const ordered = [...spans].sort((a, b) => a.start - b.start);
|
|
875
|
+
for (let i = 1; i < ordered.length; i++) {
|
|
876
|
+
if ((ordered[i] as EgressSpan).start < (ordered[i - 1] as EgressSpan).end) {
|
|
877
|
+
throw new Error('replaceSpans: spans overlap; resolve them first');
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
let out = text;
|
|
881
|
+
for (let i = ordered.length - 1; i >= 0; i--) {
|
|
882
|
+
const s = ordered[i] as EgressSpan;
|
|
883
|
+
out = out.slice(0, s.start) + replacement(s, i) + out.slice(s.end);
|
|
884
|
+
}
|
|
885
|
+
return out;
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
/** A case the pre-move rule pack detected and this table deliberately does not. */
|
|
889
|
+
export interface DetectionCeiling {
|
|
890
|
+
readonly rule: string;
|
|
891
|
+
readonly ceiling: string;
|
|
892
|
+
/** Case ids in egress_rules_parity.test.ts that demonstrate the loss. */
|
|
893
|
+
readonly cases: readonly string[];
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
export const DETECTION_CEILINGS: readonly DetectionCeiling[] = [];
|