@event4u/agent-config 14.11.0 → 14.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +156 -538
- package/README.md +1 -1
- package/dist/agent-src/contexts/execution/evidence-discipline.md +26 -0
- package/dist/agent-src/skills/code-refactoring/SKILL.md +45 -1
- package/dist/agent-src/skills/code-review/SKILL.md +65 -6
- package/dist/agent-src/skills/command-writing/SKILL.md +35 -0
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +8 -1
- package/dist/agent-src/skills/project-analysis-core/SKILL.md +23 -0
- package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +29 -12
- package/dist/agent-src/skills/skill-writing/references/procedure.md +24 -2
- package/dist/agent-src/skills/storybook-workshop/SKILL.md +9 -0
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +8 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli-delegate/{chunk-L43NCYPB.js → chunk-JCW7ZLHK.js} +5 -0
- package/dist/cli-delegate/{chunk-236PNQZK.js → chunk-JJA2QEWA.js} +1 -1
- package/dist/cli-delegate/cmd_export.js +2 -2
- package/dist/cli-delegate/cmd_prune.js +2 -2
- package/dist/cli-delegate/cmd_settings_migrate.js +2 -2
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +2 -2
- package/dist/cli-delegate/cmd_uninstall.js +2 -2
- package/dist/cli-delegate/cmd_validate.js +2 -2
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +10 -10
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +1081 -879
- package/dist/install/install.mjs +5 -0
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/server/schemas/settings.js +3 -0
- package/docs/contracts/settings-classes.md +24 -4
- package/docs/guidelines/agent-infra/downstream-changes-mechanics.md +91 -0
- package/docs/guidelines/code-clarity.md +21 -0
- package/docs/guidelines/redundancy-taxonomy.md +180 -0
- package/package.json +6 -2
- package/src/config/agent-settings.template.yml +16 -0
- package/src/config/budgets.yml +19 -0
- package/src/config/ci-local-parity.yml +15 -0
- package/src/config/discovery/prompt-patterns.yml +56 -0
- package/src/config/estate-count-budget.json +8 -3
- package/src/config/gate-coverage.yml +191 -6
- package/src/config/gate-violation-baselines.json +3 -3
- package/src/config/pack-size-budget.json +39 -12
- package/src/config/preamble-payload-budget.json +97 -71
- package/src/config/routing-coverage-seed.json +29 -0
- package/src/config/suggestion-capture.json +28 -0
- package/src/config/surface-matrix.yml +21 -2
- package/src/config/web-launch-readiness.json +188 -0
- package/src/scripts/_lib/gate_baseline.ts +150 -1
- package/src/scripts/_lib/skill_estate.ts +115 -0
- package/src/scripts/ai_council/argument_exhaustion.ts +130 -0
- package/src/scripts/check_bundle_path_leakage.ts +162 -7
- package/src/scripts/check_command_examples.ts +557 -0
- package/src/scripts/check_estate_count.ts +122 -3
- package/src/scripts/check_preamble_payload_budget.ts +30 -3
- package/src/scripts/check_routing_coverage.ts +352 -0
- package/src/scripts/check_score_contract.ts +505 -0
- package/src/scripts/check_skill_admissions.ts +514 -0
- package/src/scripts/check_web_launch_readiness.ts +705 -0
- package/src/scripts/description_route_check.ts +494 -0
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +29 -2
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/suggestion_capture_hook.ts +368 -0
- package/src/scripts/lint_budget_ownership.ts +54 -4
- package/src/scripts/lint_skill_trigger_corpus.ts +349 -0
- package/src/scripts/pack_install_smoke.ts +363 -0
- package/src/scripts/pr_conflict_census.ts +187 -0
- package/src/scripts/report_pack_delta.ts +204 -0
- package/src/scripts/select_analysis_mode.ts +112 -0
- package/src/scripts/sync_pr_branch.ts +40 -1
- package/src/server/schemas/settings.ts +5 -0
- package/dist/agent-src/skills/accessibility-auditor/evals/evals.json +0 -15
- package/dist/agent-src/skills/agent-security-review/evals/triggers.json +0 -52
- package/dist/agent-src/skills/ai-code-blindspots/evals/triggers.json +0 -52
- package/dist/agent-src/skills/alerting-doctrine/evals/triggers.json +0 -17
- package/dist/agent-src/skills/analysis-skill-router/evals/evals.json +0 -13
- package/dist/agent-src/skills/brand/evals/triggers.json +0 -17
- package/dist/agent-src/skills/brand-asset-generation/evals/triggers.json +0 -17
- package/dist/agent-src/skills/brand-audit/evals/triggers.json +0 -17
- package/dist/agent-src/skills/brand-identity/evals/triggers.json +0 -17
- package/dist/agent-src/skills/brand-strategy/evals/triggers.json +0 -17
- package/dist/agent-src/skills/brand-to-tokens/evals/triggers.json +0 -17
- package/dist/agent-src/skills/bug-analyzer/evals/evals.json +0 -13
- package/dist/agent-src/skills/canvas-design/evals/triggers.json +0 -17
- package/dist/agent-src/skills/character-consistency/evals/evals.json +0 -16
- package/dist/agent-src/skills/code-intelligence/evals/triggers.json +0 -52
- package/dist/agent-src/skills/code-review/evals/evals.json +0 -100
- package/dist/agent-src/skills/command-routing/evals/evals.json +0 -14
- package/dist/agent-src/skills/complexity-first-planning/evals/triggers.json +0 -17
- package/dist/agent-src/skills/contract-review/evals/triggers.json +0 -17
- package/dist/agent-src/skills/conventional-commits-writing/evals/evals.json +0 -15
- package/dist/agent-src/skills/corpus-grounding/evals/triggers.json +0 -17
- package/dist/agent-src/skills/dashboard-design/evals/evals.json +0 -16
- package/dist/agent-src/skills/dcf-modeling/evals/domain-truth.json +0 -29
- package/dist/agent-src/skills/dcf-modeling/evals/evals.json +0 -20
- package/dist/agent-src/skills/decision-record/evals/evals.json +0 -20
- package/dist/agent-src/skills/decision-record/evals/triggers.json +0 -87
- package/dist/agent-src/skills/design-intelligence/evals/evals.json +0 -14
- package/dist/agent-src/skills/design-intelligence/evals/triggers.json +0 -17
- package/dist/agent-src/skills/design-system-capture/evals/evals.json +0 -15
- package/dist/agent-src/skills/design-tokens/evals/triggers.json +0 -17
- package/dist/agent-src/skills/design-variations/evals/triggers.json +0 -17
- package/dist/agent-src/skills/developer-like-execution/evals/evals.json +0 -16
- package/dist/agent-src/skills/doc-coauthoring/evals/evals.json +0 -16
- package/dist/agent-src/skills/doc-coauthoring/evals/triggers.json +0 -17
- package/dist/agent-src/skills/docx-authoring/evals/triggers.json +0 -52
- package/dist/agent-src/skills/dpa-review/evals/triggers.json +0 -17
- package/dist/agent-src/skills/editorial-calendar/evals/domain-truth.json +0 -16
- package/dist/agent-src/skills/editorial-calendar/evals/evals.json +0 -16
- package/dist/agent-src/skills/eloquent/evals/triggers.json +0 -17
- package/dist/agent-src/skills/estimate-ticket/evals/evals.json +0 -16
- package/dist/agent-src/skills/estimate-ticket/evals/output-schema.yml +0 -20
- package/dist/agent-src/skills/estimate-ticket/evals/triggers.json +0 -19
- package/dist/agent-src/skills/evaluate-llm-feature/evals/triggers.json +0 -52
- package/dist/agent-src/skills/existing-ui-audit/evals/triggers.json +0 -47
- package/dist/agent-src/skills/experiment-loop/evals/output-schema.yml +0 -27
- package/dist/agent-src/skills/experiment-loop/evals/triggers.json +0 -17
- package/dist/agent-src/skills/fe-design/evals/triggers.json +0 -67
- package/dist/agent-src/skills/forecasting/evals/domain-truth.json +0 -29
- package/dist/agent-src/skills/forecasting/evals/evals.json +0 -20
- package/dist/agent-src/skills/forensics-report/evals/triggers.json +0 -17
- package/dist/agent-src/skills/frontend-render-security/evals/triggers.json +0 -52
- package/dist/agent-src/skills/fundraising-narrative/evals/domain-truth.json +0 -16
- package/dist/agent-src/skills/fundraising-narrative/evals/evals.json +0 -16
- package/dist/agent-src/skills/gated-reach/evals/triggers.json +0 -72
- package/dist/agent-src/skills/github-ci/evals/evals.json +0 -25
- package/dist/agent-src/skills/history-design/evals/triggers.json +0 -17
- package/dist/agent-src/skills/html-deck/evals/triggers.json +0 -17
- package/dist/agent-src/skills/humanizer/evals/strip_fixtures.json +0 -57
- package/dist/agent-src/skills/humanizer/evals/triggers.json +0 -17
- package/dist/agent-src/skills/iconography/evals/triggers.json +0 -17
- package/dist/agent-src/skills/image-analyser/evals/triggers.json +0 -17
- package/dist/agent-src/skills/image-creator/evals/triggers.json +0 -17
- package/dist/agent-src/skills/image-editing/evals/triggers.json +0 -17
- package/dist/agent-src/skills/image-generation/evals/triggers.json +0 -17
- package/dist/agent-src/skills/image-provider-routing/evals/triggers.json +0 -17
- package/dist/agent-src/skills/incident-commander/evals/domain-truth.json +0 -16
- package/dist/agent-src/skills/incident-commander/evals/evals.json +0 -20
- package/dist/agent-src/skills/js-library-packaging/evals/triggers.json +0 -17
- package/dist/agent-src/skills/judge-artifact-completeness/evals/triggers.json +0 -17
- package/dist/agent-src/skills/judge-injection-defense/evals/triggers.json +0 -17
- package/dist/agent-src/skills/judge-synthesis/evals/triggers.json +0 -17
- package/dist/agent-src/skills/launch-readiness/evals/evals.json +0 -21
- package/dist/agent-src/skills/learning-tutor/evals/triggers.json +0 -52
- package/dist/agent-src/skills/legal-intake-triage/evals/triggers.json +0 -17
- package/dist/agent-src/skills/legal-practice-profile/evals/triggers.json +0 -17
- package/dist/agent-src/skills/license-compliance-audit/evals/triggers.json +0 -52
- package/dist/agent-src/skills/license-compliance-borrow-check/evals/triggers.json +0 -52
- package/dist/agent-src/skills/license-compliance-credits/evals/triggers.json +0 -52
- package/dist/agent-src/skills/llm-provider-knowledge/evals/triggers.json +0 -20
- package/dist/agent-src/skills/logging-monitoring/evals/evals.json +0 -16
- package/dist/agent-src/skills/logo-generation/evals/triggers.json +0 -17
- package/dist/agent-src/skills/messaging-architecture/evals/domain-truth.json +0 -16
- package/dist/agent-src/skills/messaging-architecture/evals/evals.json +0 -16
- package/dist/agent-src/skills/monorepo-workspace/evals/triggers.json +0 -17
- package/dist/agent-src/skills/nda-triage/evals/triggers.json +0 -17
- package/dist/agent-src/skills/operational-readiness/evals/triggers.json +0 -17
- package/dist/agent-src/skills/pdf-tools/evals/triggers.json +0 -52
- package/dist/agent-src/skills/perf-feedback-craft/evals/evals.json +0 -16
- package/dist/agent-src/skills/persona-improvement/evals/triggers.json +0 -52
- package/dist/agent-src/skills/php-coder/evals/triggers.json +0 -17
- package/dist/agent-src/skills/prediction-pool-optimizer/evals/triggers.json +0 -21
- package/dist/agent-src/skills/prompt-engineering-image/evals/triggers.json +0 -17
- package/dist/agent-src/skills/prompt-engineering-patterns/evals/evals.json +0 -16
- package/dist/agent-src/skills/prompt-validator/evals/triggers.json +0 -17
- package/dist/agent-src/skills/quality-tools/evals/evals.json +0 -15
- package/dist/agent-src/skills/reasoning-orchestrator/evals/triggers.json +0 -17
- package/dist/agent-src/skills/refine-prompt/evals/evals.json +0 -16
- package/dist/agent-src/skills/refine-ticket/evals/evals.json +0 -16
- package/dist/agent-src/skills/refine-ticket/evals/output-schema.yml +0 -16
- package/dist/agent-src/skills/refine-ticket/evals/triggers.json +0 -17
- package/dist/agent-src/skills/release-comms/evals/evals.json +0 -16
- package/dist/agent-src/skills/rice-prioritization/evals/evals.json +0 -20
- package/dist/agent-src/skills/runway-cognition/evals/domain-truth.json +0 -29
- package/dist/agent-src/skills/runway-cognition/evals/evals.json +0 -20
- package/dist/agent-src/skills/scenario-modeling/evals/domain-truth.json +0 -29
- package/dist/agent-src/skills/scenario-modeling/evals/evals.json +0 -20
- package/dist/agent-src/skills/schema-review/evals/triggers.json +0 -17
- package/dist/agent-src/skills/screenshot-hygiene/evals/triggers.json +0 -52
- package/dist/agent-src/skills/security-maturity-assessment/evals/triggers.json +0 -52
- package/dist/agent-src/skills/server-hardening/evals/triggers.json +0 -17
- package/dist/agent-src/skills/skill-writing/evals/triggers.json +0 -17
- package/dist/agent-src/skills/spreadsheet-authoring/evals/triggers.json +0 -47
- package/dist/agent-src/skills/storybook-workshop/evals/triggers.json +0 -17
- package/dist/agent-src/skills/subagent-orchestration/evals/evals.json +0 -60
- package/dist/agent-src/skills/supply-chain-intake/evals/triggers.json +0 -52
- package/dist/agent-src/skills/systematic-debugging/evals/evals.json +0 -20
- package/dist/agent-src/skills/test-case-discovery/evals/triggers.json +0 -52
- package/dist/agent-src/skills/test-driven-development/evals/evals.json +0 -16
- package/dist/agent-src/skills/threat-modeling/evals/evals.json +0 -21
- package/dist/agent-src/skills/typography-system/evals/evals.json +0 -14
- package/dist/agent-src/skills/typography-system/evals/triggers.json +0 -17
- package/dist/agent-src/skills/unit-economics-modeling/evals/domain-truth.json +0 -40
- package/dist/agent-src/skills/unit-economics-modeling/evals/evals.json +0 -24
- package/dist/agent-src/skills/verify-completion-evidence/evals/evals.json +0 -16
- package/dist/agent-src/skills/verify-repair-loop/evals/output-schema.yml +0 -20
- package/dist/agent-src/skills/verify-repair-loop/evals/triggers.json +0 -17
- package/dist/agent-src/skills/vision-articulation/evals/evals.json +0 -16
- package/dist/agent-src/skills/voice-and-tone-design/evals/evals.json +0 -16
- package/dist/agent-src/skills/wireframe/evals/triggers.json +0 -17
- package/dist/agent-src/skills/workspace-link/evals/triggers.json +0 -17
- package/dist/agent-src/skills/worktree-lifecycle/evals/evals.json +0 -38
- package/dist/agent-src/skills/worktree-lifecycle/evals/triggers.json +0 -52
- package/dist/cli/agent-config.js.map +0 -1
- package/dist/cli/bash/runBash.js.map +0 -1
- package/dist/cli/commands/commands.js.map +0 -1
- package/dist/cli/commands/config.js.map +0 -1
- package/dist/cli/commands/doctorShell.js.map +0 -1
- package/dist/cli/commands/mcpServer.js.map +0 -1
- package/dist/cli/commands/packs.js.map +0 -1
- package/dist/cli/commands/profiles.js.map +0 -1
- package/dist/cli/commands/recordTriggerEval.js.map +0 -1
- package/dist/cli/commands/rtkDetect.js.map +0 -1
- package/dist/cli/commands/settings.js.map +0 -1
- package/dist/cli/commands/uiAudit.js.map +0 -1
- package/dist/cli/commands/uiRender.js.map +0 -1
- package/dist/cli/commands/uiServe.js.map +0 -1
- package/dist/cli/commands/versions.js.map +0 -1
- package/dist/cli/commands/workspaces.js.map +0 -1
- package/dist/cli/configRoot.js.map +0 -1
- package/dist/cli/discovery/loadManifest.js.map +0 -1
- package/dist/cli/firstRunNotice.js.map +0 -1
- package/dist/cli/help.js.map +0 -1
- package/dist/cli/initRouting.js.map +0 -1
- package/dist/cli/log/logger.js.map +0 -1
- package/dist/cli/main.js.map +0 -1
- package/dist/cli/mcp/content.js.map +0 -1
- package/dist/cli/mcp/dispatch.js.map +0 -1
- package/dist/cli/mcp/stdio.js.map +0 -1
- package/dist/cli/paths.js.map +0 -1
- package/dist/cli/python/knowledge_ingest.js.map +0 -1
- package/dist/cli/python/workspace_analytics.js.map +0 -1
- package/dist/cli/python/workspace_crypto.js.map +0 -1
- package/dist/cli/python/workspace_documents.js.map +0 -1
- package/dist/cli/python/workspace_drive.js.map +0 -1
- package/dist/cli/python/workspace_drive_health.js.map +0 -1
- package/dist/cli/python/workspace_explain.js.map +0 -1
- package/dist/cli/python/workspace_hosts.js.map +0 -1
- package/dist/cli/python/workspace_inbox.js.map +0 -1
- package/dist/cli/python/workspace_render.js.map +0 -1
- package/dist/cli/python/workspace_roles.js.map +0 -1
- package/dist/cli/python/workspace_secrets.js.map +0 -1
- package/dist/cli/python/workspace_sessions.js.map +0 -1
- package/dist/cli/python/workspace_skills.js.map +0 -1
- package/dist/cli/registry.js.map +0 -1
- package/dist/install/agentSwitchDetection.js.map +0 -1
- package/dist/install/agentSwitchProfile.js.map +0 -1
- package/dist/install/atomic.js.map +0 -1
- package/dist/install/claudePathsPlan.js.map +0 -1
- package/dist/install/conflict.js.map +0 -1
- package/dist/install/detect.js.map +0 -1
- package/dist/install/emit_host_rules_cli.js.map +0 -1
- package/dist/install/globalRuleLayers.js.map +0 -1
- package/dist/install/hostLayerFingerprint.js.map +0 -1
- package/dist/install/partitionEligibility.js.map +0 -1
- package/dist/install/paths.js.map +0 -1
- package/dist/install/plan.js.map +0 -1
- package/dist/install/preflight.js.map +0 -1
- package/dist/install/rtkDetection.js.map +0 -1
- package/dist/install/ruleInScope.js.map +0 -1
- package/dist/install/ruleLayerPartition.js.map +0 -1
- package/dist/install/rule_scope.js.map +0 -1
- package/dist/install/rule_scope_cli.js.map +0 -1
- package/dist/install/selectedTools.js.map +0 -1
- package/dist/install/toolDetection.js.map +0 -1
- package/dist/install/txlog.js.map +0 -1
- package/dist/install/types.js.map +0 -1
- package/dist/install/wizard-plan.js.map +0 -1
- package/dist/install/wizardDismissals.js.map +0 -1
- package/dist/scripts/_lib/agent_settings.js.map +0 -1
- package/dist/scripts/_lib/agent_src.js.map +0 -1
- package/dist/scripts/_lib/claude_builtin_names.js.map +0 -1
- package/dist/scripts/_lib/claude_plugin.js.map +0 -1
- package/dist/scripts/_lib/claude_settings_hooks.js.map +0 -1
- package/dist/scripts/_lib/compile_time_toggles.js.map +0 -1
- package/dist/scripts/_lib/environment_detector.js.map +0 -1
- package/dist/scripts/_lib/host_launch.js.map +0 -1
- package/dist/scripts/_lib/install_layout.js.map +0 -1
- package/dist/scripts/_lib/installed_lock.js.map +0 -1
- package/dist/scripts/_lib/lean_projection_mode.js.map +0 -1
- package/dist/scripts/_lib/model_tier.js.map +0 -1
- package/dist/scripts/_lib/prune_empty_dirs.js.map +0 -1
- package/dist/scripts/_lib/scoped_projection.js.map +0 -1
- package/dist/scripts/_lib/script_output.js.map +0 -1
- package/dist/scripts/_lib/spawn_env.js.map +0 -1
- package/dist/scripts/_lib/surface_tiers.js.map +0 -1
- package/dist/scripts/_lib/token_count.js.map +0 -1
- package/dist/scripts/_lib/trigger_eval_floors.js.map +0 -1
- package/dist/scripts/_lib/ui_surface.js.map +0 -1
- package/dist/scripts/_lib/user_global_paths.js.map +0 -1
- package/dist/scripts/ai_council/modes.js.map +0 -1
- package/dist/scripts/ai_council/transport_resolver.js.map +0 -1
- package/dist/scripts/condense.js.map +0 -1
- package/dist/scripts/project_thin_rules.js.map +0 -1
- package/dist/server/app.js.map +0 -1
- package/dist/server/io/atomicMultiWrite.js.map +0 -1
- package/dist/server/io/atomicWrite.js.map +0 -1
- package/dist/server/io/sharedWriteCheck.js.map +0 -1
- package/dist/server/io/substituteTemplate.js.map +0 -1
- package/dist/server/io/yamlIO.js.map +0 -1
- package/dist/server/nicknameResolver.js.map +0 -1
- package/dist/server/port.js.map +0 -1
- package/dist/server/routes/discovery.js.map +0 -1
- package/dist/server/routes/install.js.map +0 -1
- package/dist/server/routes/ping.js.map +0 -1
- package/dist/server/routes/schema.js.map +0 -1
- package/dist/server/routes/settings.js.map +0 -1
- package/dist/server/routes/settingsChanges.js.map +0 -1
- package/dist/server/routes/userMd.js.map +0 -1
- package/dist/server/routes/wizard.js.map +0 -1
- package/dist/server/routes/workspace.js.map +0 -1
- package/dist/server/schemas/settings.js.map +0 -1
- package/dist/server/serverInfo.js.map +0 -1
- package/dist/server/token.js.map +0 -1
- package/dist/server/writeRoot.js.map +0 -1
- package/dist/shared/capabilities.js.map +0 -1
- package/dist/shared/interactiveContext.js.map +0 -1
- package/dist/shared/nicknamePrefill.js.map +0 -1
- package/dist/shared/settingsAsks.js.map +0 -1
- package/dist/shared/settingsCarveOut.js.map +0 -1
- package/dist/shared/settingsClasses.js.map +0 -1
- package/dist/shared/settingsConsent.js.map +0 -1
- package/dist/shared/settingsSurface.js.map +0 -1
- package/dist/shared/skillRanking.js.map +0 -1
- package/dist/shared/userMd/formAdapter.js.map +0 -1
- package/dist/shared/userMd/schema.js.map +0 -1
- package/dist/shared/userMd/utils.js.map +0 -1
- package/dist/ui/assets/index-Cxgy63kz.js.map +0 -1
- package/src/scripts/_lib/adr_frontmatter.test.ts +0 -365
- package/src/scripts/_lib/adversarial_council_gate.test.ts +0 -112
- package/src/scripts/_lib/adversarial_reconcile.test.ts +0 -197
- package/src/scripts/_lib/auto_dispatch.corpus.test.ts +0 -150
- package/src/scripts/_lib/secret_detector.test.ts +0 -108
- package/src/scripts/_lib/secret_detector_adversarial.test.ts +0 -116
- package/src/scripts/_lib/ui_authority.test.ts +0 -251
- package/src/scripts/_lib/untrusted_content.test.ts +0 -175
- package/src/scripts/check_secret_leak.test.ts +0 -90
- package/src/scripts/design_slop_rules.test.ts +0 -246
- package/src/scripts/self_review_gate.test.ts +0 -296
- package/src/shared/capabilities.test.ts +0 -43
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Deterministic `parallelizable:` classifier recall + false-positive measurement
|
|
3
|
-
* against the orchestration corpus (road-to-orchestration-scope-decision Phase 2
|
|
4
|
-
* / road-to-subagent-value-realization-followup Phase 1 Step 3).
|
|
5
|
-
*
|
|
6
|
-
* The corpus tasks (`internal/bench/orchestration/corpus/*.md`) each document a
|
|
7
|
-
* "Classification signal" and an expected dispatch mode. This encodes those
|
|
8
|
-
* documented signals as `TaskSignals` and asserts `classifyTask` (the pure v1
|
|
9
|
-
* classifier) fires the expected mode — recall on the modes v1 covers
|
|
10
|
-
* (`do-in-parallel`, `do-in-steps`), FP=0 on the negative control, and the
|
|
11
|
-
* documented scope gap (v1 has no `do-competitively` / verdict mode).
|
|
12
|
-
*
|
|
13
|
-
* This is the durable, reproducible "record actual hit/miss counts" deliverable
|
|
14
|
-
* + a regression guard for the classifier. Deterministic — no spend, no agents.
|
|
15
|
-
*/
|
|
16
|
-
import { describe, expect, it } from 'vitest';
|
|
17
|
-
|
|
18
|
-
import {
|
|
19
|
-
classifyLookup,
|
|
20
|
-
classifyTask,
|
|
21
|
-
type ActivationInputs,
|
|
22
|
-
type LookupClass,
|
|
23
|
-
type TaskSignals,
|
|
24
|
-
} from './auto_dispatch.js';
|
|
25
|
-
|
|
26
|
-
const ON: ActivationInputs = { halted: false, subagent_spawn: true };
|
|
27
|
-
|
|
28
|
-
/** Corpus signals transcribed from each task's documented "Classification signal". */
|
|
29
|
-
const CORPUS: Array<{
|
|
30
|
-
id: string;
|
|
31
|
-
signals: TaskSignals;
|
|
32
|
-
expectMode: 'do-in-parallel' | 'do-in-steps' | null;
|
|
33
|
-
note: string;
|
|
34
|
-
}> = [
|
|
35
|
-
{
|
|
36
|
-
id: 'orch-01',
|
|
37
|
-
signals: { parallelizable: 'files', independent_slices: 4, size_estimate: 4, ordered_plan: false },
|
|
38
|
-
expectMode: 'do-in-parallel',
|
|
39
|
-
note: 'N independent files, same analysis shape',
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
id: 'orch-02',
|
|
43
|
-
signals: { ordered_plan: true, size_estimate: 5, independent_slices: 0 },
|
|
44
|
-
expectMode: 'do-in-steps',
|
|
45
|
-
note: 'explicit ordered numbered plan',
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
id: 'orch-03',
|
|
49
|
-
signals: { size_estimate: 3, independent_slices: 0, ordered_plan: false },
|
|
50
|
-
expectMode: null,
|
|
51
|
-
note: 'do-competitively — NOT a v1 DispatchMode (documented scope gap)',
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
id: 'pv-01',
|
|
55
|
-
signals: { size_estimate: 2, independent_slices: 0, ordered_plan: false },
|
|
56
|
-
expectMode: null,
|
|
57
|
-
note: 'verdict dispatch — out of the v1 parallel/steps scope',
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
id: 'pv-02',
|
|
61
|
-
signals: { size_estimate: 1, independent_slices: 0, ordered_plan: false },
|
|
62
|
-
expectMode: null,
|
|
63
|
-
note: 'negative control — a clean one-file task MUST NOT dispatch',
|
|
64
|
-
},
|
|
65
|
-
];
|
|
66
|
-
|
|
67
|
-
describe('parallelizable classifier — corpus recall', () => {
|
|
68
|
-
for (const c of CORPUS) {
|
|
69
|
-
it(`${c.id}: ${c.note}`, () => {
|
|
70
|
-
const r = classifyTask(c.signals, ON);
|
|
71
|
-
expect(r.mode).toBe(c.expectMode);
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
it('recall on v1-covered modes is 2/2 (orch-01 parallel, orch-02 steps)', () => {
|
|
76
|
-
const covered = CORPUS.filter((c) => c.expectMode !== null);
|
|
77
|
-
const hits = covered.filter((c) => classifyTask(c.signals, ON).mode === c.expectMode);
|
|
78
|
-
expect(covered).toHaveLength(2);
|
|
79
|
-
expect(hits).toHaveLength(2);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('false-positive rate is 0 — the negative control (pv-02) never dispatches', () => {
|
|
83
|
-
const pv02 = CORPUS.find((c) => c.id === 'pv-02')!;
|
|
84
|
-
expect(classifyTask(pv02.signals, ON).action).not.toBe('dispatch');
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('documents the v1 scope gap: do-competitively (orch-03) + verdict (pv-01) are not classified', () => {
|
|
88
|
-
for (const id of ['orch-03', 'pv-01']) {
|
|
89
|
-
const c = CORPUS.find((x) => x.id === id)!;
|
|
90
|
-
expect(classifyTask(c.signals, ON).mode).toBeNull();
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Lookup-class corpus (L0 — road-to-lean-agent-init Phase 1). The first four
|
|
97
|
-
* entries are the live-observed 2026-07-28 task shapes that burned ~1.21M
|
|
98
|
-
* subagent tokens; each must route to a primitive, never a spawn. The
|
|
99
|
-
* negative controls are non-lookup tasks that must escalate unchanged.
|
|
100
|
-
*/
|
|
101
|
-
const LOOKUP_CORPUS: Array<{ id: string; text: string; expect: LookupClass | null }> = [
|
|
102
|
-
// ── the four observed shapes (live evidence, 2026-07-28 session) ──
|
|
103
|
-
{ id: 'lk-01', text: 'Confirming ExternalApiProviderEnum definition location', expect: 'definition' },
|
|
104
|
-
{ id: 'lk-02', text: 'Confirming GWInput import call sites', expect: 'references' },
|
|
105
|
-
{ id: 'lk-03', text: 'Running check_enforcement_coverage report', expect: 'report-run' },
|
|
106
|
-
{ id: 'lk-04', text: 'Probing candidate strings with tsx', expect: 'string-existence' },
|
|
107
|
-
// ── generalizations of the same shapes ──
|
|
108
|
-
{ id: 'lk-05', text: 'Where is classifyTask defined?', expect: 'definition' },
|
|
109
|
-
{ id: 'lk-06', text: 'Who calls readOrchestrationMetrics across the repo?', expect: 'references' },
|
|
110
|
-
{ id: 'lk-07', text: 'Does the string "lean-init-2026" exist anywhere in src/?', expect: 'string-existence' },
|
|
111
|
-
{ id: 'lk-08', text: 'Run the roadmap:progress-check report and summarize', expect: 'report-run' },
|
|
112
|
-
{ id: 'lk-09', text: 'Find all usages of InferredTier in tests', expect: 'references' },
|
|
113
|
-
{ id: 'lk-10', text: 'Locate the enum that lists the dispatch actions', expect: 'definition' },
|
|
114
|
-
// ── negative controls — must escalate, never route to a primitive ──
|
|
115
|
-
{ id: 'lk-n1', text: 'Refactor the auth middleware to use the new session store', expect: null },
|
|
116
|
-
{ id: 'lk-n2', text: 'Fix the failing corpus test and explain the root cause', expect: null },
|
|
117
|
-
{ id: 'lk-n3', text: 'Design a migration plan for the audit schema', expect: null },
|
|
118
|
-
{ id: 'lk-n4', text: 'Review this diff for security issues', expect: null },
|
|
119
|
-
];
|
|
120
|
-
|
|
121
|
-
describe('lookup-class routing — corpus recall + FP=0 (lean-init L0)', () => {
|
|
122
|
-
for (const c of LOOKUP_CORPUS) {
|
|
123
|
-
it(`${c.id}: ${c.text}`, () => {
|
|
124
|
-
const r = classifyLookup(c.text);
|
|
125
|
-
expect(r.lookup_class).toBe(c.expect);
|
|
126
|
-
expect(r.route).toBe(c.expect === null ? 'escalate' : 'primitive');
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
it('recall on the four live-observed shapes is 4/4', () => {
|
|
131
|
-
const observed = LOOKUP_CORPUS.filter((c) => c.id.startsWith('lk-0') && Number(c.id.slice(3)) <= 4);
|
|
132
|
-
expect(observed).toHaveLength(4);
|
|
133
|
-
for (const c of observed) {
|
|
134
|
-
expect(classifyLookup(c.text).route).toBe('primitive');
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
it('false-positive rate is 0 — no negative control routes to a primitive', () => {
|
|
139
|
-
for (const c of LOOKUP_CORPUS.filter((x) => x.expect === null)) {
|
|
140
|
-
expect(classifyLookup(c.text).route).toBe('escalate');
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
it('unknown resolves to escalate with a non-degradation reason', () => {
|
|
145
|
-
const r = classifyLookup('Do something clever with the codebase');
|
|
146
|
-
expect(r.route).toBe('escalate');
|
|
147
|
-
expect(r.primitive).toBeNull();
|
|
148
|
-
expect(r.reason).toContain('never down-guessed');
|
|
149
|
-
});
|
|
150
|
-
});
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* secret_detector — coverage (secret-hygiene-guardrail Phase 0).
|
|
3
|
-
*
|
|
4
|
-
* Positive fixtures: each labelled line carries one fake secret; expectations
|
|
5
|
-
* come from an in-test label→kind map, NOT from detector output.
|
|
6
|
-
* Negative fixtures: every line must be free of high/medium findings (low is
|
|
7
|
-
* only for placeholder-shaped lines; the `secret-allow` line yields nothing).
|
|
8
|
-
*/
|
|
9
|
-
import * as fs from 'node:fs';
|
|
10
|
-
import * as path from 'node:path';
|
|
11
|
-
import { fileURLToPath } from 'node:url';
|
|
12
|
-
|
|
13
|
-
import { describe, expect, it } from 'vitest';
|
|
14
|
-
|
|
15
|
-
import { scanText, type SecretFinding } from './secret_detector.js';
|
|
16
|
-
|
|
17
|
-
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
18
|
-
const FIXTURES = path.join(HERE, 'fixtures', 'secret-detector');
|
|
19
|
-
|
|
20
|
-
function readFixture(name: string): string {
|
|
21
|
-
return fs.readFileSync(path.join(FIXTURES, name), 'utf-8');
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Label → expected kind. Keyed by the leading `<label>|` token, so a reordered
|
|
25
|
-
// fixture cannot silently pass.
|
|
26
|
-
const EXPECTED_KIND: Readonly<Record<string, string>> = {
|
|
27
|
-
aws: 'aws-access-key',
|
|
28
|
-
github: 'github-pat',
|
|
29
|
-
stripe: 'stripe-secret-key',
|
|
30
|
-
google: 'google-api-key',
|
|
31
|
-
slack: 'slack-token',
|
|
32
|
-
pem: 'pem-private-key',
|
|
33
|
-
jwt: 'jwt',
|
|
34
|
-
dburl: 'db-connection-uri',
|
|
35
|
-
assignment: 'generic-assignment',
|
|
36
|
-
// adversarial-corpus additions (road-to-feedback-9.8.0-followups Phase 3)
|
|
37
|
-
'github-fine-grained': 'github-pat',
|
|
38
|
-
'env-db-password': 'generic-assignment',
|
|
39
|
-
'env-api-key': 'generic-assignment',
|
|
40
|
-
'dburl-mysql': 'db-connection-uri',
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
function isReal(f: SecretFinding): boolean {
|
|
44
|
-
return f.confidence === 'high' || f.confidence === 'medium';
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
describe('scanText — positives', () => {
|
|
48
|
-
const text = readFixture('positives.txt');
|
|
49
|
-
const lines = text.split(/\r\n|\r|\n/);
|
|
50
|
-
const findings = scanText(text);
|
|
51
|
-
|
|
52
|
-
for (let i = 0; i < lines.length; i++) {
|
|
53
|
-
const line = lines[i] as string;
|
|
54
|
-
if (!line.includes('|') || line.startsWith('#')) {
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
const label = line.slice(0, line.indexOf('|'));
|
|
58
|
-
const expectedKind = EXPECTED_KIND[label];
|
|
59
|
-
const lineNo = i + 1;
|
|
60
|
-
|
|
61
|
-
it(`flags ${label} as ${expectedKind}`, () => {
|
|
62
|
-
expect(expectedKind, `no expected kind mapped for label "${label}"`).toBeDefined();
|
|
63
|
-
const onLine = findings.filter((f) => f.line === lineNo && isReal(f));
|
|
64
|
-
const kinds = onLine.map((f) => f.kind);
|
|
65
|
-
expect(
|
|
66
|
-
kinds,
|
|
67
|
-
`line ${lineNo} (${label}) expected kind ${expectedKind}, got ${JSON.stringify(onLine)}`,
|
|
68
|
-
).toContain(expectedKind);
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
describe('scanText — negatives', () => {
|
|
74
|
-
const text = readFixture('negatives.txt');
|
|
75
|
-
const lines = text.split(/\r\n|\r|\n/);
|
|
76
|
-
const findings = scanText(text);
|
|
77
|
-
|
|
78
|
-
for (let i = 0; i < lines.length; i++) {
|
|
79
|
-
const line = lines[i] as string;
|
|
80
|
-
if (line.trim() === '' || line.startsWith('#')) {
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
83
|
-
const lineNo = i + 1;
|
|
84
|
-
it(`no high/medium finding on line ${lineNo}`, () => {
|
|
85
|
-
const real = findings.filter((f) => f.line === lineNo && isReal(f));
|
|
86
|
-
expect(real, `unexpected real findings: ${JSON.stringify(real)}`).toHaveLength(0);
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
it('the secret-allow line yields zero findings of any confidence', () => {
|
|
91
|
-
const allowLineNo = lines.findIndex((l) => l.includes('secret-allow')) + 1;
|
|
92
|
-
expect(allowLineNo, 'no secret-allow line in fixture').toBeGreaterThan(0);
|
|
93
|
-
const onLine = findings.filter((f) => f.line === allowLineNo);
|
|
94
|
-
expect(onLine).toHaveLength(0);
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
describe('scanText — masking', () => {
|
|
99
|
-
it('never reproduces the raw secret in `masked`', () => {
|
|
100
|
-
const raw = 'AKIA1234567890ABCDEF';
|
|
101
|
-
const findings = scanText(`aws_key = "${raw}"`);
|
|
102
|
-
const hit = findings.find((f) => f.kind === 'aws-access-key');
|
|
103
|
-
expect(hit, 'expected an aws-access-key finding').toBeDefined();
|
|
104
|
-
const masked = (hit as SecretFinding).masked;
|
|
105
|
-
expect(masked).not.toBe(raw);
|
|
106
|
-
expect(masked.includes(raw)).toBe(false);
|
|
107
|
-
});
|
|
108
|
-
});
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
// Adversarial precision/recall measurement for the secret detector
|
|
2
|
-
// (road-to-feedback-9.8.0-followups Phase 3). Runs the REAL scanText over
|
|
3
|
-
// the committed fixture corpus plus runtime-constructed multiline cases
|
|
4
|
-
// (assembled from parts so nothing key-shaped beyond the existing corpus
|
|
5
|
-
// convention lands in the tree), computes precision / recall / FP-rate, and
|
|
6
|
-
// publishes the rates to internal/reports/secret-scanner-adversarial.json.
|
|
7
|
-
//
|
|
8
|
-
// Hard floor: recall = 100% on positives, FP-rate = 0% on negative controls.
|
|
9
|
-
// A genuine detector miss must NOT be papered over by weakening a fixture —
|
|
10
|
-
// it gets a known_gap entry excluded from the hard assertion and REPORTED.
|
|
11
|
-
import * as fs from 'node:fs';
|
|
12
|
-
import * as path from 'node:path';
|
|
13
|
-
import { fileURLToPath } from 'node:url';
|
|
14
|
-
import { describe, expect, it } from 'vitest';
|
|
15
|
-
|
|
16
|
-
import { scanText, type SecretFinding } from './secret_detector.js';
|
|
17
|
-
|
|
18
|
-
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
19
|
-
const FIXTURES = path.join(HERE, 'fixtures', 'secret-detector');
|
|
20
|
-
const REPO = path.resolve(HERE, '..', '..', '..');
|
|
21
|
-
const REPORT = path.join(REPO, 'internal', 'reports', 'secret-scanner-adversarial.json');
|
|
22
|
-
|
|
23
|
-
/** Measured, documented gaps — excluded from the hard floor, published. */
|
|
24
|
-
const KNOWN_GAPS: string[] = [];
|
|
25
|
-
|
|
26
|
-
const isReal = (f: SecretFinding): boolean => f.confidence === 'high' || f.confidence === 'medium';
|
|
27
|
-
|
|
28
|
-
interface Case { id: string; text: string; expect_hit: boolean }
|
|
29
|
-
|
|
30
|
-
function corpusCases(): Case[] {
|
|
31
|
-
const cases: Case[] = [];
|
|
32
|
-
for (const [file, expectHit] of [['positives.txt', true], ['negatives.txt', false]] as const) {
|
|
33
|
-
const lines = fs.readFileSync(path.join(FIXTURES, file), 'utf-8').split('\n');
|
|
34
|
-
lines.forEach((line, i) => {
|
|
35
|
-
if (line.trim().length === 0 || line.startsWith('#')) return;
|
|
36
|
-
const value = expectHit ? (line.split('|')[1] ?? line) : line;
|
|
37
|
-
cases.push({ id: `${file}:${i + 1}`, text: value, expect_hit: expectHit });
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
return cases;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/** Multiline / wrapped positives assembled at runtime. */
|
|
44
|
-
function constructedCases(): Case[] {
|
|
45
|
-
// A fake PEM body: base64-ish filler between real BEGIN/END framing.
|
|
46
|
-
const pem = [
|
|
47
|
-
['-----BEGIN', 'RSA PRIVATE KEY-----'].join(' '),
|
|
48
|
-
'MIIEpAIBAAKCAQEA7fakebodyfakebodyfakebodyfakebodyfakebody12345678',
|
|
49
|
-
'q7fakebodyfakebodyfakebodyfakebodyfakebodyfakebodyfakebody901234',
|
|
50
|
-
['-----END', 'RSA PRIVATE KEY-----'].join(' '),
|
|
51
|
-
].join('\n');
|
|
52
|
-
// A base64-WRAPPED credential next to a keyword: the wrapped payload is a
|
|
53
|
-
// fake AWS key; the wrapper alone must still trip entropy+keyword.
|
|
54
|
-
const wrapped = `api_key = "${Buffer.from('AKIA' + '1234567890ABCDEF').toString('base64')}"`;
|
|
55
|
-
// .env multiline block (several assignments in one scan call).
|
|
56
|
-
const envBlock = ['APP_ENV=production', 'DB_PASSWORD=q7Xp2Vr9kLm4Nt8wYz3BdF6h', 'MAIL_FROM=noreply@example.com'].join('\n');
|
|
57
|
-
return [
|
|
58
|
-
{ id: 'constructed:pem-multiline', text: pem, expect_hit: true },
|
|
59
|
-
{ id: 'constructed:base64-wrapped-key', text: wrapped, expect_hit: true },
|
|
60
|
-
{ id: 'constructed:env-block', text: envBlock, expect_hit: true },
|
|
61
|
-
// Negative: random base64 with NO credential keyword nearby.
|
|
62
|
-
{ id: 'constructed:naked-base64-no-keyword-short', text: 'blob dGhpcyBpcyBmaWxsZXI=', expect_hit: false },
|
|
63
|
-
];
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
describe('secret detector — adversarial corpus measurement', () => {
|
|
67
|
-
const cases = [...corpusCases(), ...constructedCases()];
|
|
68
|
-
const rows = cases.map((c) => {
|
|
69
|
-
const real = scanText(c.text).filter(isReal);
|
|
70
|
-
return { ...c, hit: real.length > 0, kinds: [...new Set(real.map((f) => f.kind))] };
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
const positives = rows.filter((r) => r.expect_hit);
|
|
74
|
-
const negatives = rows.filter((r) => !r.expect_hit);
|
|
75
|
-
const detected = positives.filter((r) => r.hit);
|
|
76
|
-
const missed = positives.filter((r) => !r.hit).map((r) => r.id);
|
|
77
|
-
const falsePositives = negatives.filter((r) => r.hit).map((r) => r.id);
|
|
78
|
-
const recall = positives.length > 0 ? detected.length / positives.length : 1;
|
|
79
|
-
const fpRate = negatives.length > 0 ? falsePositives.length / negatives.length : 0;
|
|
80
|
-
const precision =
|
|
81
|
-
detected.length + falsePositives.length > 0
|
|
82
|
-
? detected.length / (detected.length + falsePositives.length)
|
|
83
|
-
: 1;
|
|
84
|
-
|
|
85
|
-
it('publishes the measured rates', () => {
|
|
86
|
-
const report = {
|
|
87
|
-
_doc:
|
|
88
|
-
'Adversarial fixture measurement of the secret detector (scanText). ' +
|
|
89
|
-
'Regenerated by src/scripts/_lib/secret_detector_adversarial.test.ts on every run; ' +
|
|
90
|
-
'hard floor asserted there (recall 100% / FP 0% outside known_gaps).',
|
|
91
|
-
generated: new Date().toISOString().slice(0, 10),
|
|
92
|
-
corpus_size: rows.length,
|
|
93
|
-
positives: positives.length,
|
|
94
|
-
negatives: negatives.length,
|
|
95
|
-
detected: detected.length,
|
|
96
|
-
missed,
|
|
97
|
-
false_positives: falsePositives,
|
|
98
|
-
known_gaps: KNOWN_GAPS,
|
|
99
|
-
precision: +precision.toFixed(3),
|
|
100
|
-
recall: +recall.toFixed(3),
|
|
101
|
-
fp_rate: +fpRate.toFixed(3),
|
|
102
|
-
};
|
|
103
|
-
fs.mkdirSync(path.dirname(REPORT), { recursive: true });
|
|
104
|
-
fs.writeFileSync(REPORT, `${JSON.stringify(report, null, 2)}\n`);
|
|
105
|
-
expect(fs.existsSync(REPORT)).toBe(true);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it('recall floor: every positive outside known_gaps is detected', () => {
|
|
109
|
-
const hardMisses = missed.filter((id) => !KNOWN_GAPS.includes(id));
|
|
110
|
-
expect(hardMisses, `detector missed: ${hardMisses.join(', ')}`).toHaveLength(0);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it('FP floor: no negative control fires high/medium', () => {
|
|
114
|
-
expect(falsePositives, `false positives: ${falsePositives.join(', ')}`).toHaveLength(0);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
@@ -1,251 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A1.1-A1.5 behaviour, pinned against the frontend corpus fixtures.
|
|
3
|
-
*
|
|
4
|
-
* Every case name here is a real directory under `tests/eval/frontend-corpus/`,
|
|
5
|
-
* authored and hashed BEFORE this resolver existed (`34f7dc400`). That ordering
|
|
6
|
-
* is the point: the fixtures state what the right answer is, and the resolver is
|
|
7
|
-
* scored against them rather than the reverse.
|
|
8
|
-
*/
|
|
9
|
-
import { describe, expect, it } from 'vitest';
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
DEFAULTS,
|
|
13
|
-
OPERATIONS,
|
|
14
|
-
PRESERVE_DELTA_DIMENSIONS,
|
|
15
|
-
degrade,
|
|
16
|
-
operationConflicts,
|
|
17
|
-
preserveViolations,
|
|
18
|
-
resolveUiAuthority,
|
|
19
|
-
type Signals,
|
|
20
|
-
} from './ui_authority.js';
|
|
21
|
-
|
|
22
|
-
describe('A1.1 — one object, fully populated', () => {
|
|
23
|
-
it('always emits every required field', () => {
|
|
24
|
-
const a = resolveUiAuthority();
|
|
25
|
-
for (const k of [
|
|
26
|
-
'surface_mode',
|
|
27
|
-
'register',
|
|
28
|
-
'change_intent',
|
|
29
|
-
'reference_maturity',
|
|
30
|
-
'primary_source',
|
|
31
|
-
'constraints',
|
|
32
|
-
'conflicts',
|
|
33
|
-
'provenance',
|
|
34
|
-
'verification',
|
|
35
|
-
]) {
|
|
36
|
-
expect(a).toHaveProperty(k);
|
|
37
|
-
}
|
|
38
|
-
expect(a.verification).toBe('verified');
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('records provenance for every resolved field, so a wrong answer is traceable', () => {
|
|
42
|
-
const a = resolveUiAuthority({ brief: { register: 'brand', path: 'brief.md' } });
|
|
43
|
-
expect(a.provenance.map((p) => p.field)).toEqual(
|
|
44
|
-
expect.arrayContaining(['surface_mode', 'register', 'change_intent', 'reference_maturity']),
|
|
45
|
-
);
|
|
46
|
-
expect(a.provenance.find((p) => p.field === 'register')).toMatchObject({
|
|
47
|
-
source: 'surface-brief',
|
|
48
|
-
detail: 'brief.md',
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('carries fidelity_mandate rather than deriving one', () => {
|
|
53
|
-
expect(resolveUiAuthority({ fidelity_mandate: 'phase-0-output' }).fidelity_mandate).toBe('phase-0-output');
|
|
54
|
-
expect(resolveUiAuthority().fidelity_mandate).toBeNull();
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
describe('A1.2 — explicit user authority wins; quoted text does not', () => {
|
|
59
|
-
it('cases/explicit-redesign: the user’s change_intent beats every inference', () => {
|
|
60
|
-
const a = resolveUiAuthority({
|
|
61
|
-
user: { change_intent: 'redesign', register: 'brand', surface_mode: 'persuade' },
|
|
62
|
-
incumbent: { coherent: true },
|
|
63
|
-
});
|
|
64
|
-
expect(a.change_intent).toBe('redesign');
|
|
65
|
-
expect(a.provenance.find((p) => p.field === 'change_intent')?.source).toBe('user-instruction');
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('quoted text inside a supplied document is data, not authorisation', () => {
|
|
69
|
-
const quoted: Signals = {
|
|
70
|
-
user: { change_intent: 'redesign', register: 'brand', quoted: true },
|
|
71
|
-
incumbent: { coherent: true },
|
|
72
|
-
};
|
|
73
|
-
const a = resolveUiAuthority(quoted);
|
|
74
|
-
// The incumbent wins, exactly as if the quoted directive were absent.
|
|
75
|
-
expect(a.change_intent).toBe('extend');
|
|
76
|
-
expect(a.provenance.find((p) => p.field === 'change_intent')?.source).toBe('incumbent-scan');
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('a registered hard constraint outranks a user release', () => {
|
|
80
|
-
const a = resolveUiAuthority({
|
|
81
|
-
user: { change_intent: 'redesign' },
|
|
82
|
-
hard_constraints: ['preserve_palette'],
|
|
83
|
-
});
|
|
84
|
-
expect(a.constraints.preserve_palette).toBe(true);
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
describe('A1.3 — a missing DESIGN.md is not new-world', () => {
|
|
89
|
-
it('cases/no-design-md-coherent-incumbent resolves extend with incumbent authority', () => {
|
|
90
|
-
const a = resolveUiAuthority({
|
|
91
|
-
incumbent: { coherent: true, type_families: ['ibm plex sans'] },
|
|
92
|
-
design_md: { present: false },
|
|
93
|
-
});
|
|
94
|
-
expect(a.change_intent).toBe('extend');
|
|
95
|
-
expect(a.primary_source.kind).toBe('incumbent');
|
|
96
|
-
// The provenance assertion is load-bearing, not decoration. `extend` is
|
|
97
|
-
// ALSO the declared default, so a value-only assertion cannot tell
|
|
98
|
-
// "resolved from the coherent incumbent" from "fell through to the
|
|
99
|
-
// default". A sabotage probe that disabled the A1.3 branch left this
|
|
100
|
-
// test green until the source was asserted.
|
|
101
|
-
expect(a.provenance.find((p) => p.field === 'change_intent')).toMatchObject({
|
|
102
|
-
source: 'incumbent-scan',
|
|
103
|
-
detail: expect.stringContaining('A1.3'),
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it('cases/greenfield — genuinely empty resolves new-world', () => {
|
|
108
|
-
expect(resolveUiAuthority({ design_md: { present: false } }).change_intent).toBe('new-world');
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('an incoherent incumbent falls to the declared default, not to new-world', () => {
|
|
112
|
-
const a = resolveUiAuthority({ incumbent: { coherent: false } });
|
|
113
|
-
expect(a.change_intent).toBe(DEFAULTS.change_intent);
|
|
114
|
-
expect(a.change_intent).not.toBe('new-world');
|
|
115
|
-
// Same discriminator in the other direction: this one MUST read
|
|
116
|
-
// `default`, so the pair separates the two paths that both yield
|
|
117
|
-
// `extend`.
|
|
118
|
-
expect(a.provenance.find((p) => p.field === 'change_intent')?.source).toBe('default');
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
describe('A1.4 / A2.1 — surface-local stays local', () => {
|
|
123
|
-
it('near-miss/surface-mode-not-product-mode: the brief outranks PRODUCT.md', () => {
|
|
124
|
-
const a = resolveUiAuthority({
|
|
125
|
-
brief: { surface_mode: 'persuade', register: 'brand', path: 'brief.md' },
|
|
126
|
-
product_md: { present: true, register: 'product' },
|
|
127
|
-
incumbent: { coherent: true },
|
|
128
|
-
});
|
|
129
|
-
expect(a.surface_mode).toBe('persuade');
|
|
130
|
-
expect(a.register).toBe('brand');
|
|
131
|
-
expect(a.provenance.find((p) => p.field === 'register')?.source).toBe('surface-brief');
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
it('PRODUCT.md never supplies surface_mode — only the brief or the user does', () => {
|
|
135
|
-
const a = resolveUiAuthority({ product_md: { present: true, register: 'product' } });
|
|
136
|
-
expect(a.provenance.find((p) => p.field === 'surface_mode')?.source).toBe('default');
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
describe('A1.5 — the intent-aware gate, against the pre-registered threshold', () => {
|
|
141
|
-
const incumbent = {
|
|
142
|
-
palette: ['#16181d', '#ffffff', '#5b616b', '#e3e5e9'],
|
|
143
|
-
type_families: ['newsreader', 'inter'],
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
it('near-miss/refine-preserves-world: a palette delta under preserve blocks', () => {
|
|
147
|
-
const a = resolveUiAuthority({ user: { change_intent: 'preserve' }, incumbent: { coherent: true } });
|
|
148
|
-
const v = preserveViolations(a, incumbent, { palette: ['#16181d', '#ff6a3d'], type_families: ['newsreader'] });
|
|
149
|
-
expect(v).toHaveLength(1);
|
|
150
|
-
expect(v[0]).toContain('palette');
|
|
151
|
-
expect(v[0]).toContain('#ff6a3d');
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
it('a type-family delta under preserve blocks', () => {
|
|
155
|
-
const a = resolveUiAuthority({ user: { change_intent: 'preserve' } });
|
|
156
|
-
const v = preserveViolations(a, incumbent, { palette: [], type_families: ['fraunces'] });
|
|
157
|
-
expect(v).toHaveLength(1);
|
|
158
|
-
expect(v[0]).toContain('type_family');
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it('near-miss/refine-preserves-world: spacing-only refinement does NOT block', () => {
|
|
162
|
-
// The whole point of the verb. Spacing, rhythm, weight and size are
|
|
163
|
-
// outside the threshold, so a refine that touches only those passes.
|
|
164
|
-
const a = resolveUiAuthority({ user: { change_intent: 'preserve' }, incumbent: { coherent: true } });
|
|
165
|
-
expect(preserveViolations(a, incumbent, incumbent)).toEqual([]);
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
it('cases/explicit-redesign: the same delta under redesign does NOT block', () => {
|
|
169
|
-
const a = resolveUiAuthority({ user: { change_intent: 'redesign' } });
|
|
170
|
-
expect(preserveViolations(a, incumbent, { palette: ['#ff6a3d'], type_families: ['fraunces'] })).toEqual([]);
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
it('transparent / currentColor / inherit are never a palette delta', () => {
|
|
174
|
-
const a = resolveUiAuthority({ user: { change_intent: 'preserve' } });
|
|
175
|
-
expect(
|
|
176
|
-
preserveViolations(a, incumbent, {
|
|
177
|
-
palette: ['transparent', 'currentColor', 'inherit'],
|
|
178
|
-
type_families: [],
|
|
179
|
-
}),
|
|
180
|
-
).toEqual([]);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
it('the threshold covers exactly the two pre-registered dimensions', () => {
|
|
184
|
-
expect([...PRESERVE_DELTA_DIMENSIONS]).toEqual(['palette', 'type_family']);
|
|
185
|
-
});
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
describe('A4.1 — six operations as one field, with a conflict path', () => {
|
|
189
|
-
it('exposes exactly the six the step names', () => {
|
|
190
|
-
expect(Object.keys(OPERATIONS).sort()).toEqual([
|
|
191
|
-
'bolder',
|
|
192
|
-
'clarify',
|
|
193
|
-
'distill',
|
|
194
|
-
'harden',
|
|
195
|
-
'polish',
|
|
196
|
-
'quieter',
|
|
197
|
-
]);
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
it('bolder under preserve surfaces a conflict instead of mutating', () => {
|
|
201
|
-
const a = resolveUiAuthority({ user: { change_intent: 'preserve' } });
|
|
202
|
-
const c = operationConflicts(a, 'bolder');
|
|
203
|
-
expect(c.length).toBeGreaterThan(0);
|
|
204
|
-
expect(c.map((x) => x.dimension).sort()).toEqual(['palette', 'type_family']);
|
|
205
|
-
expect(c[0]!.blocked_by).toMatch(/^preserve_/);
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
it('polish under preserve is clean — it touches no locked dimension', () => {
|
|
209
|
-
const a = resolveUiAuthority({ user: { change_intent: 'preserve' } });
|
|
210
|
-
expect(operationConflicts(a, 'polish')).toEqual([]);
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
it('bolder under redesign is clean', () => {
|
|
214
|
-
expect(operationConflicts(resolveUiAuthority({ user: { change_intent: 'redesign' } }), 'bolder')).toEqual([]);
|
|
215
|
-
});
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
describe('graft 2 — a pass that could not run says so', () => {
|
|
219
|
-
it('degrade carries a reason', () => {
|
|
220
|
-
const d = degrade(resolveUiAuthority(), 'render artefact absent');
|
|
221
|
-
expect(d.verification).toBe('degraded');
|
|
222
|
-
expect(d.degradation_reason).toBe('render artefact absent');
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
it('refuses a reason-free degrade by construction', () => {
|
|
226
|
-
expect(() => degrade(resolveUiAuthority(), ' ')).toThrow(/non-empty degradation_reason/);
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
it('supports unverified as a distinct state', () => {
|
|
230
|
-
expect(degrade(resolveUiAuthority(), 'no host capability', 'unverified').verification).toBe('unverified');
|
|
231
|
-
});
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
describe('reference maturity — the wireframe trap', () => {
|
|
235
|
-
it('cases/wireframe: a wireframe is recorded as structure, never as a pixel mandate', () => {
|
|
236
|
-
const a = resolveUiAuthority({ reference: { maturity: 'wireframe', path: 'wireframe.md' } });
|
|
237
|
-
expect(a.reference_maturity).toBe('wireframe');
|
|
238
|
-
// `brief`, not `comp`: a wireframe does not become the visual source.
|
|
239
|
-
expect(a.primary_source.kind).toBe('brief');
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
it('cases/supplied-runnable-html: a runnable artifact IS the source', () => {
|
|
243
|
-
const a = resolveUiAuthority({ reference: { maturity: 'runnable-artifact', path: 'design.html' } });
|
|
244
|
-
expect(a.primary_source).toStrictEqual({ kind: 'artifact', path: 'design.html' });
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
it('cases/supplied-finished-comp: a comp is translated, not adopted as code', () => {
|
|
248
|
-
const a = resolveUiAuthority({ reference: { maturity: 'finished-comp', path: 'HANDOVER.md' } });
|
|
249
|
-
expect(a.primary_source.kind).toBe('comp');
|
|
250
|
-
});
|
|
251
|
-
});
|