@event4u/agent-config 8.4.0 → 8.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +73 -0
- package/README.md +17 -5
- package/dist/agent-src/README.md +1 -1
- package/dist/agent-src/commands/{analyze-reference-repo.md → analyze/reference-repo.md} +3 -1
- package/dist/agent-src/commands/analyze.md +9 -6
- package/dist/agent-src/commands/{bug-fix.md → bug/fix.md} +3 -1
- package/dist/agent-src/commands/{bug-investigate.md → bug/investigate.md} +4 -2
- package/dist/agent-src/commands/bug.md +59 -0
- package/dist/agent-src/commands/{set-cost-profile.md → cost/profile.md} +9 -6
- package/dist/agent-src/commands/{cost-report.md → cost/report.md} +18 -17
- package/dist/agent-src/commands/cost.md +57 -0
- package/dist/agent-src/commands/evals/{review-changes.json → review.json} +12 -8
- package/dist/agent-src/commands/{quality-fix.md → fix/quality.md} +5 -2
- package/dist/agent-src/commands/fix.md +7 -4
- package/dist/agent-src/commands/optimize/project.md +250 -0
- package/dist/agent-src/commands/{optimize-prompt.md → optimize/prompt.md} +3 -2
- package/dist/agent-src/commands/optimize.md +17 -12
- package/dist/agent-src/commands/{package-reset.md → package/reset.md} +2 -0
- package/dist/agent-src/commands/{package-test.md → package/test.md} +3 -1
- package/dist/agent-src/commands/package.md +56 -0
- package/dist/agent-src/commands/{project-analyze.md → project/analyze.md} +10 -8
- package/dist/agent-src/commands/{project-health.md → project/health.md} +2 -0
- package/dist/agent-src/commands/project.md +60 -0
- package/dist/agent-src/commands/{review-changes.md → review/changes.md} +26 -24
- package/dist/agent-src/commands/{review-routing.md → review/routing.md} +21 -17
- package/dist/agent-src/commands/review.md +61 -0
- package/dist/agent-src/commands/security-audit-config.md +24 -23
- package/dist/agent-src/commands/{sync-agent-settings.md → sync/agent-settings.md} +11 -7
- package/dist/agent-src/commands/{sync-gitignore → sync/gitignore}/fix.md +36 -27
- package/dist/agent-src/commands/{sync-gitignore.md → sync/gitignore.md} +22 -21
- package/dist/agent-src/commands/sync.md +58 -0
- package/dist/agent-src/commands/{e2e-heal.md → tests/e2e-heal.md} +5 -2
- package/dist/agent-src/commands/{e2e-plan.md → tests/e2e-plan.md} +5 -2
- package/dist/agent-src/commands/tests.md +11 -5
- package/dist/agent-src/contexts/augment-infrastructure.md +3 -3
- package/dist/agent-src/contexts/execution/toolchain-resolver.md +1 -1
- package/dist/agent-src/contexts/skills-and-commands.md +2 -2
- package/dist/agent-src/rules/external-reference-deep-dive.md +1 -1
- package/dist/agent-src/skills/finishing-a-development-branch/SKILL.md +2 -2
- package/dist/agent-src/skills/judge-artifact-completeness/SKILL.md +1 -1
- package/dist/agent-src/skills/judge-bug-hunter/SKILL.md +1 -1
- package/dist/agent-src/skills/judge-code-quality/SKILL.md +1 -1
- package/dist/agent-src/skills/judge-security-auditor/SKILL.md +1 -1
- package/dist/agent-src/skills/judge-synthesis/SKILL.md +1 -1
- package/dist/agent-src/skills/judge-test-coverage/SKILL.md +1 -1
- package/dist/agent-src/skills/markitdown/SKILL.md +1 -1
- package/dist/agent-src/skills/mobile-e2e-strategy/SKILL.md +5 -5
- package/dist/agent-src/skills/prompt-optimizer/SKILL.md +2 -2
- package/dist/agent-src/skills/quality-tools/SKILL.md +1 -1
- package/dist/agent-src/skills/repomix-packer/SKILL.md +1 -1
- package/dist/agent-src/skills/requesting-code-review/SKILL.md +2 -2
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +2 -2
- package/dist/agent-src/templates/agent-settings.md +1 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +2 -2
- package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +1 -1
- package/dist/cli/commands/config.js +44 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/uiServe.js +1 -0
- package/dist/cli/commands/uiServe.js.map +1 -1
- package/dist/cli/help.js +38 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/initRouting.js +16 -1
- package/dist/cli/initRouting.js.map +1 -1
- package/dist/cli/main.js +43 -37
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/registry.js +45 -44
- package/dist/cli/registry.js.map +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +419 -210
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +4 -4
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +31 -25
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +30 -24
- package/dist/install/install.mjs +6064 -159
- package/dist/install/selectedTools.js +39 -10
- package/dist/install/selectedTools.js.map +1 -1
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/server/app.js +15 -3
- package/dist/server/app.js.map +1 -1
- package/dist/server/routes/ping.js +16 -0
- package/dist/server/routes/ping.js.map +1 -1
- package/dist/server/routes/settings.js +42 -6
- package/dist/server/routes/settings.js.map +1 -1
- package/dist/server/routes/settingsChanges.js +55 -0
- package/dist/server/routes/settingsChanges.js.map +1 -0
- package/dist/server/routes/userMd.js +7 -2
- package/dist/server/routes/userMd.js.map +1 -1
- package/dist/server/routes/wizard.js +76 -14
- package/dist/server/routes/wizard.js.map +1 -1
- package/dist/server/writeRoot.js +17 -0
- package/dist/server/writeRoot.js.map +1 -1
- package/dist/shared/settingsSurface.js +120 -0
- package/dist/shared/settingsSurface.js.map +1 -0
- package/dist/ui/assets/index-BPFMZWUs.css +1 -0
- package/dist/ui/assets/index-BiEZiZ31.js +40 -0
- package/dist/ui/assets/index-BiEZiZ31.js.map +1 -0
- package/dist/ui/index.html +15 -2
- package/docs/CLAIMS.md +20 -15
- package/docs/architecture.md +1 -1
- package/docs/catalog.md +37 -31
- package/docs/command-flows.md +22 -16
- package/docs/contracts/command-clusters.md +39 -9
- package/docs/contracts/file-ownership-matrix.json +21 -0
- package/docs/contracts/frontmatter-contract.md +1 -1
- package/docs/contracts/gui-wizard.md +16 -4
- package/docs/contracts/iron-law-overrides.txt +1 -0
- package/docs/contracts/rule-classification.md +2 -2
- package/docs/contracts/settings-api.md +58 -2
- package/docs/contracts/surface-matrix.md +5 -0
- package/docs/cookbook.md +7 -7
- package/docs/decisions/ADR-114-commit-policy-iron-law-override.md +74 -0
- package/docs/decisions/ADR-115-command-cluster-consolidation-phase-4.md +91 -0
- package/docs/decisions/INDEX.md +2 -0
- package/docs/featured-commands.md +1 -1
- package/docs/featured-skills.md +4 -4
- package/docs/flows.md +2 -2
- package/docs/getting-started-by-role.md +1 -1
- package/docs/getting-started-laravel.md +1 -1
- package/docs/getting-started.md +6 -3
- package/docs/governance-advantage.md +1 -1
- package/docs/guidelines/agent-infra/5w2h-analysis.md +1 -1
- package/docs/guidelines/agent-infra/ios-simulator-guide.md +1 -1
- package/docs/proof.md +11 -2
- package/package.json +6 -1
- package/src/agent-src/README.md +64 -0
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +497 -0
- package/src/agent-src/scripts/scan-seeder-violations.php +145 -0
- package/src/agent-src/scripts/update_roadmap_progress.ts +1087 -0
- package/src/agent-src/templates/AGENTS.md +34 -0
- package/src/agent-src/templates/scripts/README.md +195 -0
- package/src/agent-src/templates/scripts/check_memory.ts +662 -0
- package/src/agent-src/templates/scripts/check_memory_proposal.ts +370 -0
- package/src/agent-src/templates/scripts/historical-bug-patterns.example.yml +84 -0
- package/src/agent-src/templates/scripts/implement_ticket/__main__.ts +27 -0
- package/src/agent-src/templates/scripts/memory_hash.ts +355 -0
- package/src/agent-src/templates/scripts/memory_lookup.ts +1089 -0
- package/src/agent-src/templates/scripts/memory_report.ts +868 -0
- package/src/agent-src/templates/scripts/memory_signal.ts +444 -0
- package/src/agent-src/templates/scripts/memory_status.ts +215 -0
- package/src/agent-src/templates/scripts/ownership-map.example.yml +87 -0
- package/src/agent-src/templates/scripts/pr-risk-config.example.yml +76 -0
- package/src/agent-src/templates/scripts/pr_review_routing.ts +544 -0
- package/src/agent-src/templates/scripts/pr_risk_review.ts +0 -0
- package/src/agent-src/templates/scripts/telemetry/aggregator.ts +0 -0
- package/src/agent-src/templates/scripts/telemetry/boundary.ts +164 -0
- package/src/agent-src/templates/scripts/telemetry/engagement.ts +479 -0
- package/src/agent-src/templates/scripts/telemetry/report_renderer.ts +394 -0
- package/src/agent-src/templates/scripts/telemetry/settings.ts +210 -0
- package/src/agent-src/templates/scripts/telemetry_record.ts +276 -0
- package/src/agent-src/templates/scripts/telemetry_report.ts +211 -0
- package/src/agent-src/templates/scripts/telemetry_status.ts +333 -0
- package/src/agent-src/templates/scripts/tier_usage_report.ts +619 -0
- package/src/agent-src/templates/scripts/work_engine/__main__.ts +14 -0
- package/src/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +1261 -0
- package/src/agent-src/templates/scripts/work_engine/_lib/user_global_paths.ts +329 -0
- package/src/agent-src/templates/scripts/work_engine/cli.ts +206 -0
- package/src/agent-src/templates/scripts/work_engine/cli_args.ts +249 -0
- package/src/agent-src/templates/scripts/work_engine/delivery_state.ts +225 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/analyze.ts +125 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +189 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/index.ts +94 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/memory.ts +193 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/plan.ts +267 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/refine.ts +518 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/report.ts +379 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +268 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +258 -0
- package/src/agent-src/templates/scripts/work_engine/directives/index.ts +32 -0
- package/src/agent-src/templates/scripts/work_engine/directives/mixed/contract.ts +243 -0
- package/src/agent-src/templates/scripts/work_engine/directives/mixed/index.ts +108 -0
- package/src/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +259 -0
- package/src/agent-src/templates/scripts/work_engine/directives/mixed/ui.ts +216 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/_passthrough.ts +40 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +241 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +216 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +506 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/design.ts +325 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/index.ts +102 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +462 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/review.ts +474 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +352 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui_trivial/_skipped.ts +33 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui_trivial/apply.ts +213 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui_trivial/index.ts +111 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui_trivial/refine.ts +126 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui_trivial/report.ts +112 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui_trivial/test.ts +164 -0
- package/src/agent-src/templates/scripts/work_engine/dispatcher.ts +515 -0
- package/src/agent-src/templates/scripts/work_engine/emitters.ts +119 -0
- package/src/agent-src/templates/scripts/work_engine/errors.ts +24 -0
- package/src/agent-src/templates/scripts/work_engine/hook_bootstrap.ts +104 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/_chat_history_base.ts +189 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_append.ts +41 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_halt_append.ts +89 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/decision_gate.ts +193 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +304 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/directive_set_guard.ts +110 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/halt_surface_audit.ts +118 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/index.ts +17 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +161 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/state_shape_validation.ts +45 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/builtin/trace.ts +134 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/context.ts +94 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/events.ts +58 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/exceptions.ts +85 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/index.ts +27 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/registry.ts +66 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/runner.ts +90 -0
- package/src/agent-src/templates/scripts/work_engine/hooks/settings.ts +260 -0
- package/src/agent-src/templates/scripts/work_engine/input_builders.ts +260 -0
- package/src/agent-src/templates/scripts/work_engine/intent/classify.ts +466 -0
- package/src/agent-src/templates/scripts/work_engine/migration/v0_to_v1.ts +531 -0
- package/src/agent-src/templates/scripts/work_engine/orchestration.ts +366 -0
- package/src/agent-src/templates/scripts/work_engine/persona_policy.ts +97 -0
- package/src/agent-src/templates/scripts/work_engine/resolvers/diff.ts +135 -0
- package/src/agent-src/templates/scripts/work_engine/resolvers/file.ts +175 -0
- package/src/agent-src/templates/scripts/work_engine/resolvers/prompt.ts +115 -0
- package/src/agent-src/templates/scripts/work_engine/scoring/confidence.ts +415 -0
- package/src/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +466 -0
- package/src/agent-src/templates/scripts/work_engine/scoring/decision_trace.ts +298 -0
- package/src/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +444 -0
- package/src/agent-src/templates/scripts/work_engine/stack/detect.ts +252 -0
- package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +745 -0
- package/src/agent-src/templates/scripts/work_engine/state.ts +1151 -0
- package/src/agent-src/templates/scripts/work_engine/state_io.ts +413 -0
- package/src/config/agent-settings.template.yml +1 -1
- package/src/install/atomic.ts +111 -0
- package/src/install/conflict.ts +226 -0
- package/src/install/detect.ts +280 -0
- package/src/install/paths.ts +90 -0
- package/src/install/plan.ts +205 -0
- package/src/install/preflight.ts +210 -0
- package/src/install/selectedTools.ts +80 -0
- package/src/install/toolDetection.ts +120 -0
- package/src/install/txlog.ts +161 -0
- package/src/install/types.ts +175 -0
- package/src/install/wizard-plan.ts +216 -0
- package/src/scripts/_cli/cmd_converge.ts +38 -0
- package/src/scripts/_cli/cmd_doctor.ts +113 -2
- package/src/scripts/_cli/cmd_explain.ts +2 -2
- package/src/scripts/_cli/cmd_export.ts +3 -3
- package/src/scripts/_cli/cmd_fleet.ts +13 -1
- package/src/scripts/_cli/cmd_migrate.ts +3 -3
- package/src/scripts/_cli/cmd_prune.ts +2 -2
- package/src/scripts/_cli/cmd_refresh.ts +4 -4
- package/src/scripts/_cli/cmd_settings_check.ts +2 -2
- package/src/scripts/_cli/cmd_settings_migrate.ts +2 -2
- package/src/scripts/_cli/cmd_sync.ts +2 -2
- package/src/scripts/_cli/cmd_uninstall.ts +2 -2
- package/src/scripts/_cli/cmd_update.ts +8 -8
- package/src/scripts/_cli/cmd_upgrade.ts +4 -3
- package/src/scripts/_cli/cmd_validate.ts +3 -3
- package/src/scripts/_cli/cmd_versions.ts +2 -2
- package/src/scripts/_cli/explain_last/assumptions.ts +2 -2
- package/src/scripts/_cli/explain_last/council.ts +2 -2
- package/src/scripts/_cli/explain_last/halt.ts +2 -2
- package/src/scripts/_cli/explain_last/index.ts +2 -2
- package/src/scripts/_cli/explain_last/inputs.ts +4 -4
- package/src/scripts/_cli/explain_last/memory.ts +2 -2
- package/src/scripts/_cli/explain_last/provider.ts +2 -2
- package/src/scripts/_cli/explain_last/render.ts +2 -2
- package/src/scripts/_cli/explain_last/route.ts +2 -2
- package/src/scripts/_cli/explain_last/scrubber.ts +2 -2
- package/src/scripts/_cli/explain_last/sections/assumptions.ts +2 -2
- package/src/scripts/_cli/explain_last/sections/council.ts +2 -2
- package/src/scripts/_cli/explain_last/sections/halt.ts +2 -2
- package/src/scripts/_cli/explain_last/sections/header.ts +2 -2
- package/src/scripts/_cli/explain_last/sections/index.ts +1 -1
- package/src/scripts/_cli/explain_last/sections/inputs.ts +2 -2
- package/src/scripts/_cli/explain_last/sections/memory.ts +2 -2
- package/src/scripts/_cli/explain_last/sections/pack.ts +2 -2
- package/src/scripts/_cli/explain_last/sections/provider.ts +2 -2
- package/src/scripts/_cli/explain_last/sections/route.ts +2 -2
- package/src/scripts/_cli/explain_last/state_loader.ts +2 -2
- package/src/scripts/_dispatch.bash +20 -1
- package/src/scripts/_lib/agent_settings.ts +1 -1
- package/src/scripts/_lib/agent_src.ts +7 -7
- package/src/scripts/_lib/agents_overlay.ts +1 -1
- package/src/scripts/_lib/bench_ab_cache.ts +1 -1
- package/src/scripts/_lib/bench_ab_scoring.ts +1 -1
- package/src/scripts/_lib/bench_ab_scoring_v2.ts +3 -3
- package/src/scripts/_lib/bench_cost.ts +1 -1
- package/src/scripts/_lib/bench_quality.ts +3 -3
- package/src/scripts/_lib/bench_report.ts +4 -4
- package/src/scripts/_lib/bench_telegraph.ts +1 -1
- package/src/scripts/_lib/bench_telegraph_report.ts +4 -4
- package/src/scripts/_lib/changelog_eras.ts +1 -1
- package/src/scripts/_lib/claude_desktop_bundler.ts +1 -1
- package/src/scripts/_lib/cli_wrapper.ts +1 -1
- package/src/scripts/_lib/fs_atomic.ts +1 -1
- package/src/scripts/_lib/global_deploy_inventory.ts +1 -1
- package/src/scripts/_lib/install_layout.ts +1 -1
- package/src/scripts/_lib/install_regenerator.ts +1 -1
- package/src/scripts/_lib/installed_lock.ts +1 -1
- package/src/scripts/_lib/installed_tools.ts +1 -1
- package/src/scripts/_lib/json_pointers.ts +1 -1
- package/src/scripts/_lib/knowledge_global.ts +1 -1
- package/src/scripts/_lib/knowledge_global_promote.ts +2 -2
- package/src/scripts/_lib/knowledge_global_redaction.ts +2 -2
- package/src/scripts/_lib/link_crypto.ts +4 -4
- package/src/scripts/_lib/linked_projects.ts +4 -4
- package/src/scripts/_lib/model_tier.ts +1 -1
- package/src/scripts/_lib/module_detection.ts +2 -2
- package/src/scripts/_lib/pin_resolver.ts +1 -1
- package/src/scripts/_lib/script_output.ts +1 -1
- package/src/scripts/_lib/security_lint.ts +1 -1
- package/src/scripts/_lib/surface_tiers.ts +1 -1
- package/src/scripts/_lib/text_similarity.ts +1 -1
- package/src/scripts/_lib/update_check.ts +2 -2
- package/src/scripts/_lib/user_global_paths.ts +1 -1
- package/src/scripts/_lib/value_ladder.ts +1 -1
- package/src/scripts/_lib/value_report.ts +1 -1
- package/src/scripts/_lib/zip_min.ts +2 -2
- package/src/scripts/adoption_report.ts +3 -3
- package/src/scripts/adoption_snapshot.ts +3 -3
- package/src/scripts/adoption_status.ts +2 -2
- package/src/scripts/adr/regenerate_index.ts +3 -3
- package/src/scripts/ai_council/_default_prices.ts +2 -3
- package/src/scripts/ai_council/advisors.ts +1 -1
- package/src/scripts/ai_council/airgap.ts +1 -1
- package/src/scripts/ai_council/budget_guard.ts +1 -1
- package/src/scripts/ai_council/bundler.ts +1 -1
- package/src/scripts/ai_council/cli_hints.ts +1 -1
- package/src/scripts/ai_council/clients.ts +5 -5
- package/src/scripts/ai_council/compile_corpus.ts +1 -1
- package/src/scripts/ai_council/confidence_gate.ts +1 -1
- package/src/scripts/ai_council/config.ts +1 -1
- package/src/scripts/ai_council/consensus.ts +1 -1
- package/src/scripts/ai_council/events_log.ts +1 -1
- package/src/scripts/ai_council/learn_low_impact_preview.ts +1 -1
- package/src/scripts/ai_council/low_impact_corpus.ts +1 -1
- package/src/scripts/ai_council/low_impact_intake.ts +1 -1
- package/src/scripts/ai_council/modes.ts +1 -1
- package/src/scripts/ai_council/orchestrator.ts +3 -3
- package/src/scripts/ai_council/pricing.ts +2 -2
- package/src/scripts/ai_council/probation_gate.ts +2 -2
- package/src/scripts/ai_council/project_context.ts +1 -1
- package/src/scripts/ai_council/prompts.ts +1 -1
- package/src/scripts/ai_council/redact_low_impact_entry.ts +2 -2
- package/src/scripts/ai_council/session.ts +1 -1
- package/src/scripts/ai_council/shadow_dispatch.ts +1 -1
- package/src/scripts/ai_council/solo_dispatch.ts +1 -1
- package/src/scripts/analysis_freshness.ts +2 -2
- package/src/scripts/annotate_discovery.ts +2 -2
- package/src/scripts/apply_modules_config.ts +2 -2
- package/src/scripts/audit_adr_coverage.ts +3 -3
- package/src/scripts/audit_auto_rules.ts +2 -2
- package/src/scripts/audit_cloud_compatibility.ts +3 -3
- package/src/scripts/audit_command_surface.ts +2 -2
- package/src/scripts/audit_initial_context.ts +7 -6
- package/src/scripts/audit_likelihood.ts +5 -5
- package/src/scripts/audit_mcp_tools.ts +3 -3
- package/src/scripts/audit_overlap.ts +2 -2
- package/src/scripts/audit_skill_descriptions.ts +2 -2
- package/src/scripts/audit_skill_overlap.ts +5 -5
- package/src/scripts/audit_user_type_axis.ts +4 -4
- package/src/scripts/backfill_model_tier.ts +1 -1
- package/src/scripts/bench_ab_cache_dispatch.ts +2 -2
- package/src/scripts/bench_ab_clone.ts +2 -2
- package/src/scripts/bench_ab_diff.ts +3 -3
- package/src/scripts/bench_ab_integrity.ts +2 -2
- package/src/scripts/bench_ab_run.ts +4 -4
- package/src/scripts/bench_ab_task_runner.ts +1 -1
- package/src/scripts/bench_ab_tracka_run.ts +2 -2
- package/src/scripts/bench_ab_v2_run.ts +1 -1
- package/src/scripts/bench_ab_v2_stats.ts +2 -2
- package/src/scripts/bench_baseline_ready.ts +1 -1
- package/src/scripts/bench_condense_memory.ts +4 -4
- package/src/scripts/bench_drift_check.ts +3 -3
- package/src/scripts/bench_per_tool.ts +1 -1
- package/src/scripts/bench_rtk_savings.ts +4 -4
- package/src/scripts/bench_run.ts +4 -4
- package/src/scripts/bench_runner.ts +1 -1
- package/src/scripts/build_cloud_bundle.ts +3 -3
- package/src/scripts/build_discovery_manifest.ts +13 -15
- package/src/scripts/build_linear_digest.ts +2 -2
- package/src/scripts/build_mcp_registry_manifest.ts +3 -3
- package/src/scripts/build_proof.ts +6 -0
- package/src/scripts/build_rule_trigger_matrix.ts +2 -2
- package/src/scripts/capture_showcase_session.ts +3 -3
- package/src/scripts/chat_history.ts +1 -1
- package/src/scripts/check_always_budget.ts +1 -1
- package/src/scripts/check_artefact_checksums.ts +4 -4
- package/src/scripts/check_artefact_count_messaging.ts +197 -0
- package/src/scripts/check_augment_description_cap.ts +3 -3
- package/src/scripts/check_augmentignore.ts +1 -1
- package/src/scripts/check_beta_review_markers.ts +3 -3
- package/src/scripts/check_bite_sized_granularity.ts +1 -1
- package/src/scripts/check_cluster_patterns.ts +47 -3
- package/src/scripts/check_command_count_messaging.ts +2 -2
- package/src/scripts/check_condensation.ts +2 -2
- package/src/scripts/check_condensed_paths.ts +6 -6
- package/src/scripts/check_context_paths.ts +1 -1
- package/src/scripts/check_council_config_location.ts +3 -3
- package/src/scripts/check_council_layout.ts +2 -2
- package/src/scripts/check_council_references.ts +2 -2
- package/src/scripts/check_discovery_determinism.ts +3 -3
- package/src/scripts/check_gate_paths.ts +4 -4
- package/src/scripts/check_iron_law_prominence.ts +2 -2
- package/src/scripts/check_kernel_rule_bundle.ts +3 -3
- package/src/scripts/check_knowledge_cards.ts +4 -4
- package/src/scripts/check_knowledge_pages.ts +1 -1
- package/src/scripts/check_md_language.ts +3 -3
- package/src/scripts/check_memory.ts +3 -3
- package/src/scripts/check_memory_proposal.ts +2 -2
- package/src/scripts/check_module_management_neutral.ts +1 -1
- package/src/scripts/check_no_conflict_markers.ts +1 -1
- package/src/scripts/check_no_external_sources.ts +1 -1
- package/src/scripts/check_no_local_settings_committed.ts +2 -2
- package/src/scripts/check_no_new_legacy_path.ts +3 -3
- package/src/scripts/check_no_roadmap_refs.ts +3 -3
- package/src/scripts/check_one_off_location.ts +3 -3
- package/src/scripts/check_overlay_cascade_subdirs.ts +3 -3
- package/src/scripts/check_portability.ts +3 -3
- package/src/scripts/check_proposal.ts +0 -0
- package/src/scripts/check_public_catalog_links.ts +1 -1
- package/src/scripts/check_public_links.ts +2 -2
- package/src/scripts/check_references.ts +3 -3
- package/src/scripts/check_release_includes_discovery.ts +2 -2
- package/src/scripts/check_release_pr_shape.ts +2 -2
- package/src/scripts/check_release_published.ts +1 -1
- package/src/scripts/check_release_trunk_sync.ts +3 -3
- package/src/scripts/check_reply_consistency.ts +1 -1
- package/src/scripts/check_roadmap_trackable.ts +2 -2
- package/src/scripts/check_role_doc_links.ts +2 -2
- package/src/scripts/check_safety_floor_untouched.ts +3 -3
- package/src/scripts/check_skill_requires.ts +2 -2
- package/src/scripts/check_structural_breaking.ts +2 -2
- package/src/scripts/check_surface_tiers.ts +2 -2
- package/src/scripts/check_template_pin_drift.ts +1 -1
- package/src/scripts/check_test_coverage_diff.ts +2 -2
- package/src/scripts/check_token_optimizer_freshness.ts +3 -3
- package/src/scripts/check_trigger_evals.ts +2 -2
- package/src/scripts/check_update_banner.ts +1 -1
- package/src/scripts/ci_status.ts +0 -0
- package/src/scripts/ci_summary.ts +3 -3
- package/src/scripts/ci_time_ratio.ts +1 -1
- package/src/scripts/command_suggester/cooldown.ts +1 -1
- package/src/scripts/command_suggester/index.ts +1 -1
- package/src/scripts/command_suggester/loader.ts +1 -1
- package/src/scripts/command_suggester/match.ts +1 -1
- package/src/scripts/command_suggester/rank.ts +1 -1
- package/src/scripts/command_suggester/render.ts +1 -1
- package/src/scripts/command_suggester/sanitize.ts +1 -1
- package/src/scripts/command_suggester/settings.ts +1 -1
- package/src/scripts/command_suggester/types.ts +0 -0
- package/src/scripts/compile_router.ts +4 -4
- package/src/scripts/condense.ts +3 -3
- package/src/scripts/condense_memory.ts +1 -1
- package/src/scripts/config/index.ts +1 -1
- package/src/scripts/config/packs.ts +1 -1
- package/src/scripts/config/presets.ts +1 -1
- package/src/scripts/config/profile_explain.ts +1 -1
- package/src/scripts/config/profiles.ts +1 -1
- package/src/scripts/config/session_profiles.ts +1 -1
- package/src/scripts/context_hygiene_hook.ts +2 -2
- package/src/scripts/cost_by_conversation.ts +1 -1
- package/src/scripts/cost_summary.ts +2 -2
- package/src/scripts/council_cli.ts +1 -1
- package/src/scripts/council_prune.ts +1 -1
- package/src/scripts/cross_repo_retrieve.ts +2 -2
- package/src/scripts/discovery_stats.ts +3 -3
- package/src/scripts/evidence_report.ts +4 -4
- package/src/scripts/extract_audit_patterns.ts +2 -2
- package/src/scripts/first_run_gate_hook.ts +1 -1
- package/src/scripts/gen_discovery_baseline.ts +2 -2
- package/src/scripts/generate_capabilities_index.ts +2 -2
- package/src/scripts/generate_capability_matrix.ts +2 -2
- package/src/scripts/generate_catalog.ts +2 -2
- package/src/scripts/generate_command_flows.ts +2 -2
- package/src/scripts/generate_cookbook.ts +1 -1
- package/src/scripts/generate_index.ts +3 -3
- package/src/scripts/generate_ownership_matrix.ts +2 -2
- package/src/scripts/generate_pack_manifests.ts +2 -2
- package/src/scripts/generate_role_experiences_catalog.ts +3 -3
- package/src/scripts/hooks/block_no_verify.ts +2 -2
- package/src/scripts/hooks/dispatch_hook.ts +2 -2
- package/src/scripts/hooks/dispatch_issues.ts +1 -1
- package/src/scripts/hooks/envelope.ts +1 -1
- package/src/scripts/hooks/replay_hook.ts +1 -1
- package/src/scripts/hooks/state_io.ts +1 -1
- package/src/scripts/hooks_doctor.ts +1 -1
- package/src/scripts/hooks_status.ts +1 -1
- package/src/scripts/injection_scan_hook.ts +1 -1
- package/src/scripts/install.ts +145 -3
- package/src/scripts/inventory_abstraction_budget.ts +5 -5
- package/src/scripts/inventory_frontmatter.ts +1 -1
- package/src/scripts/inventory_meta_layers.ts +1 -1
- package/src/scripts/iron_law_sha.ts +1 -1
- package/src/scripts/knowledge_global_cli.ts +3 -3
- package/src/scripts/linked_projects_list.ts +1 -1
- package/src/scripts/lint_agent_security.ts +4 -4
- package/src/scripts/lint_agent_skill_names.ts +1 -1
- package/src/scripts/lint_agents_layout.ts +2 -2
- package/src/scripts/lint_agents_md.ts +3 -3
- package/src/scripts/lint_archived_skills.ts +2 -2
- package/src/scripts/lint_artefact_frontmatter.ts +2 -2
- package/src/scripts/lint_bench_ab.ts +2 -2
- package/src/scripts/lint_bench_corpus.ts +1 -1
- package/src/scripts/lint_command_flow_coverage.ts +1 -1
- package/src/scripts/lint_command_routing.ts +2 -2
- package/src/scripts/lint_command_tiers.ts +1 -1
- package/src/scripts/lint_command_verbs.ts +4 -4
- package/src/scripts/lint_commit_subjects.ts +2 -2
- package/src/scripts/lint_context_spine_usage.ts +3 -3
- package/src/scripts/lint_discovery_manifest.ts +4 -4
- package/src/scripts/lint_discovery_vocabulary.ts +2 -2
- package/src/scripts/lint_empty_roadmaps.ts +3 -3
- package/src/scripts/lint_eval_freshness.ts +2 -2
- package/src/scripts/lint_examples.ts +2 -2
- package/src/scripts/lint_explain_trace.ts +2 -2
- package/src/scripts/lint_featured_skills.ts +0 -0
- package/src/scripts/lint_flows.ts +5 -5
- package/src/scripts/lint_framework_leakage.ts +1 -1
- package/src/scripts/lint_framework_leakage_allowlist.json +10 -2
- package/src/scripts/lint_frontmatter_boilerplate.ts +2 -2
- package/src/scripts/lint_ghostwriter_source.ts +3 -3
- package/src/scripts/lint_global_paths.ts +1 -1
- package/src/scripts/lint_handoffs.ts +1 -1
- package/src/scripts/lint_hidden_unicode.ts +1 -1
- package/src/scripts/lint_hook_concern_budget.ts +2 -2
- package/src/scripts/lint_hook_manifest.ts +2 -2
- package/src/scripts/lint_instruction_smuggling.ts +1 -1
- package/src/scripts/lint_load_context.ts +2 -2
- package/src/scripts/lint_marketplace.ts +1 -1
- package/src/scripts/lint_marketplace_install_completeness.ts +2 -2
- package/src/scripts/lint_mcp_config_security.ts +1 -1
- package/src/scripts/lint_mcp_registry_manifest.ts +1 -1
- package/src/scripts/lint_media_policy_linkage.ts +3 -3
- package/src/scripts/lint_missions.ts +3 -3
- package/src/scripts/lint_model_tier_coverage.ts +3 -3
- package/src/scripts/lint_namespace.ts +2 -2
- package/src/scripts/lint_namespace_collisions.ts +2 -2
- package/src/scripts/lint_new_skill_gate.ts +3 -3
- package/src/scripts/lint_no_new_atomic_commands.ts +9 -6
- package/src/scripts/lint_no_python_twin_rationale.ts +102 -0
- package/src/scripts/lint_one_off_age.ts +2 -2
- package/src/scripts/lint_orchestration_dsl.ts +3 -3
- package/src/scripts/lint_orchestrator_auto_detect.ts +1 -1
- package/src/scripts/lint_pack_boundaries.ts +2 -2
- package/src/scripts/lint_pack_dependencies.ts +2 -2
- package/src/scripts/lint_pack_first_win.ts +2 -2
- package/src/scripts/lint_persona_governance.ts +3 -3
- package/src/scripts/lint_positioning.ts +1 -1
- package/src/scripts/lint_profile_overlay_set_only.ts +2 -2
- package/src/scripts/lint_readme_jargon.ts +2 -2
- package/src/scripts/lint_readme_size.ts +2 -2
- package/src/scripts/lint_regression.ts +3 -3
- package/src/scripts/lint_roadmap_ci_steps.ts +3 -3
- package/src/scripts/lint_roadmap_complexity.ts +1 -1
- package/src/scripts/lint_roadmap_later_disposition.ts +2 -2
- package/src/scripts/lint_role_experiences.ts +2 -2
- package/src/scripts/lint_rule_interactions.ts +1 -1
- package/src/scripts/lint_rule_tiers.ts +1 -1
- package/src/scripts/lint_showcase_sessions.ts +2 -2
- package/src/scripts/lint_skill_frontmatter_safety.ts +1 -1
- package/src/scripts/lint_skill_originality.ts +1 -1
- package/src/scripts/lint_skill_tools.ts +3 -3
- package/src/scripts/lint_ticket_buildable.ts +2 -2
- package/src/scripts/lint_topics_yaml.ts +3 -3
- package/src/scripts/lint_trust_coherence.ts +3 -3
- package/src/scripts/lint_value_dashboard.ts +3 -3
- package/src/scripts/lint_workflow_security.ts +3 -3
- package/src/scripts/lint_workspace_boundary.ts +2 -2
- package/src/scripts/mcp_parity_smoke.ts +1 -1
- package/src/scripts/mcp_render.ts +1 -1
- package/src/scripts/mcp_server/catalog.ts +1 -1
- package/src/scripts/mcp_server/index.ts +1 -1
- package/src/scripts/mcp_server/metadata.ts +1 -1
- package/src/scripts/mcp_server/prompts.ts +1 -1
- package/src/scripts/mcp_server/resources.ts +1 -1
- package/src/scripts/mcp_server/server.ts +1 -1
- package/src/scripts/mcp_server/telemetry.ts +1 -1
- package/src/scripts/mcp_server/tools.ts +1 -1
- package/src/scripts/mcp_telemetry_health.ts +1 -1
- package/src/scripts/mcp_telemetry_query.ts +3 -3
- package/src/scripts/mcp_telemetry_store.ts +3 -3
- package/src/scripts/measure_augment_budget.ts +2 -2
- package/src/scripts/measure_density.ts +2 -2
- package/src/scripts/measure_frugality_savings.ts +3 -3
- package/src/scripts/measure_markitdown_lift.ts +1 -1
- package/src/scripts/measure_patterns.ts +1 -1
- package/src/scripts/measure_projection_bytes.ts +1 -1
- package/src/scripts/measure_rule_budget.ts +1 -1
- package/src/scripts/measure_skill_reduction.ts +1 -1
- package/src/scripts/memory_hash.ts +1 -1
- package/src/scripts/memory_lookup.ts +6 -6
- package/src/scripts/memory_report.ts +1 -1
- package/src/scripts/memory_signal.ts +1 -1
- package/src/scripts/memory_status.ts +2 -2
- package/src/scripts/migrate_command_suggestions.ts +1 -1
- package/src/scripts/migrate_frontmatter_defaults.ts +1 -1
- package/src/scripts/mine_session.ts +3 -3
- package/src/scripts/minimal_safe_diff_hook.ts +2 -2
- package/src/scripts/move_artefact.ts +3 -3
- package/src/scripts/new_skill.ts +3 -3
- package/src/scripts/onboarding_gate_hook.ts +2 -2
- package/src/scripts/pack_mcp_content.ts +1 -1
- package/src/scripts/parity/replay.ts +3 -2
- package/src/scripts/pattern_share.ts +2 -2
- package/src/scripts/plan_physical_move.ts +3 -3
- package/src/scripts/prediction-pool/poisson_sim.ts +2 -2
- package/src/scripts/prediction-pool/pool_winsim.ts +2 -2
- package/src/scripts/prediction-pool/score_ev.ts +2 -2
- package/src/scripts/prepack-check.mjs +108 -5
- package/src/scripts/print_required_checks.ts +2 -2
- package/src/scripts/probe_projection_fidelity.ts +2 -2
- package/src/scripts/probe_skill_registration.ts +2 -2
- package/src/scripts/profile_staleness_hook.ts +2 -2
- package/src/scripts/profile_use.ts +2 -2
- package/src/scripts/project_thin_rules.ts +3 -3
- package/src/scripts/propose_modules_config.ts +2 -2
- package/src/scripts/prototype_lint_contradictions.ts +2 -2
- package/src/scripts/prove_pack_extractable.ts +1 -1
- package/src/scripts/readme_linter.ts +4 -4
- package/src/scripts/redact_hook_capture.ts +2 -2
- package/src/scripts/refine_ticket_detect.ts +1 -1
- package/src/scripts/release.ts +30 -19
- package/src/scripts/render_benchmark_md.ts +2 -2
- package/src/scripts/render_value_md.ts +2 -2
- package/src/scripts/roadmap_progress_hook.ts +1 -1
- package/src/scripts/router_telemetry.ts +1 -1
- package/src/scripts/run_skill_evals.ts +2 -2
- package/src/scripts/runtime_dispatcher.ts +1 -1
- package/src/scripts/runtime_handler.ts +1 -1
- package/src/scripts/runtime_registry.ts +3 -3
- package/src/scripts/score_skill_selection.ts +1 -1
- package/src/scripts/security_audit_config.ts +2 -2
- package/src/scripts/skill_collision_clusters.ts +1 -1
- package/src/scripts/skill_discovery.ts +1 -1
- package/src/scripts/skill_linter.ts +8 -7
- package/src/scripts/skill_overlap.ts +2 -2
- package/src/scripts/skill_preview.ts +1 -1
- package/src/scripts/skill_tools/audit_persona_coverage.ts +3 -3
- package/src/scripts/skill_tools/audit_user_type_coverage.ts +3 -3
- package/src/scripts/skill_tools/index.ts +1 -1
- package/src/scripts/skill_tools/run_block_d_eval.ts +3 -3
- package/src/scripts/skill_tools/score_skill_relevance.ts +3 -3
- package/src/scripts/skill_tools/suggest_skill_for_task.ts +3 -3
- package/src/scripts/skill_trigger_eval.ts +2 -2
- package/src/scripts/skill_usage_collect.ts +2 -2
- package/src/scripts/skill_usage_report.ts +2 -2
- package/src/scripts/smoke_path_resolution.ts +2 -2
- package/src/scripts/smoke_quickstart.ts +4 -4
- package/src/scripts/snapshot_agent_outputs.ts +2 -2
- package/src/scripts/spotcheck_thin_root.ts +2 -2
- package/src/scripts/surface-tiers.yml +1 -0
- package/src/scripts/sync_agent_settings.ts +2 -2
- package/src/scripts/sync_github_metadata.ts +4 -4
- package/src/scripts/sync_gitignore.ts +3 -3
- package/src/scripts/sync_yaml_rt.ts +2 -2
- package/src/scripts/telegraph_stats.ts +1 -1
- package/src/scripts/tool_registry.ts +2 -2
- package/src/scripts/tools/adapter_errors.ts +1 -1
- package/src/scripts/tools/base_adapter.ts +1 -1
- package/src/scripts/tools/github_adapter.ts +1 -1
- package/src/scripts/tools/jira_adapter.ts +1 -1
- package/src/scripts/trigger_coverage.ts +2 -2
- package/src/scripts/update_counts.ts +68 -6
- package/src/scripts/update_prices.ts +3 -3
- package/src/scripts/validate_agent_settings.ts +3 -3
- package/src/scripts/validate_decision_engine.ts +2 -2
- package/src/scripts/validate_discovery_manifest.ts +3 -3
- package/src/scripts/validate_frontmatter.ts +5 -5
- package/src/scripts/validate_pack_yaml.ts +0 -0
- package/src/scripts/validate_safe_paths.ts +2 -2
- package/src/scripts/validate_telegraph_carveouts.ts +3 -3
- package/src/scripts/verify_before_complete_hook.ts +2 -2
- package/src/scripts/verify_physical_move.ts +2 -2
- package/src/scripts/wrapper_freshness_hook.ts +3 -3
- package/src/server/schemas/settings.ts +426 -0
- package/src/shared/settingsSurface.ts +184 -0
- package/src/shared/userMd/formAdapter.ts +86 -0
- package/src/shared/userMd/schema.ts +59 -0
- package/src/shared/userMd/utils.ts +91 -0
- package/dist/agent-src/commands/optimize-project.md +0 -243
- package/dist/ui/assets/index-BbWWuFrF.css +0 -1
- package/dist/ui/assets/index-UjcTG_9O.js +0 -40
- package/dist/ui/assets/index-UjcTG_9O.js.map +0 -1
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Producer-side helpers for the memory-visibility line.
|
|
3
|
+
*
|
|
4
|
+
* TypeScript twin of `work_engine/scoring/memory_visibility.py` (ADR-200 py2ts
|
|
5
|
+
* Phase 1 — work_engine scoring subpackage). Public API names stay snake_case
|
|
6
|
+
* to mirror the Python module 1:1 (per ADR-200 — Python style is part of the
|
|
7
|
+
* contract).
|
|
8
|
+
*
|
|
9
|
+
* Implements the v1 line shape from
|
|
10
|
+
* `docs/contracts/memory-visibility-v1.md`:
|
|
11
|
+
*
|
|
12
|
+
* 🧠 Memory: <hits>/<asks> · ids=[<comma-separated-ids>]
|
|
13
|
+
* 🧠 Memory: <hits>/<asks> · ids=[<...>] · affected: <keys>
|
|
14
|
+
*
|
|
15
|
+
* The optional `· affected: <keys>` trailing segment surfaces which
|
|
16
|
+
* closed-list decision-trace keys diverged because memory was
|
|
17
|
+
* consulted — see `docs/contracts/decision-trace-v1.md` "Memory
|
|
18
|
+
* consequence keys".
|
|
19
|
+
*
|
|
20
|
+
* The semantics matched to the work-engine model:
|
|
21
|
+
*
|
|
22
|
+
* - The `memory` step retrieves across the four allowed memory types
|
|
23
|
+
* (`MEMORY_TYPES` in `directives.backend.memory`). Each type is
|
|
24
|
+
* one `ask` from the visibility-line perspective.
|
|
25
|
+
* - `hits` counts distinct types that returned at least one entry.
|
|
26
|
+
* - `ids` is the deduped list of returned entry ids preserving the
|
|
27
|
+
* retrieval order encoded in `state.memory`.
|
|
28
|
+
*
|
|
29
|
+
* Privacy floor: this module never emits entry bodies, summaries,
|
|
30
|
+
* `path`/`source` fields, or anything beyond `id` and `type`.
|
|
31
|
+
* The privacy regression test (`tests/contracts/test_memory_
|
|
32
|
+
* visibility_redaction.py`) keeps this guarantee enforced.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
import { derive_confidence_band, derive_risk_class } from './decision_trace.js';
|
|
36
|
+
|
|
37
|
+
/** Arbitrary JSON-ish value, mirroring the Python `Any` fields. */
|
|
38
|
+
export type Any = unknown;
|
|
39
|
+
|
|
40
|
+
export const ICON = '\u{1F9E0}'; // 🧠
|
|
41
|
+
export const DEFAULT_MAX_INLINE_IDS = 5;
|
|
42
|
+
export const DEFAULT_ASKED_TYPES: readonly string[] = [
|
|
43
|
+
'domain-invariants',
|
|
44
|
+
'incident-learnings',
|
|
45
|
+
'historical-patterns',
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
export const CONSEQUENCE_KEYS: readonly string[] = [
|
|
49
|
+
'confidence_band',
|
|
50
|
+
'risk_class',
|
|
51
|
+
'applied_rules',
|
|
52
|
+
'test_plan',
|
|
53
|
+
] as const;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Reduce `state.memory` into the visibility-line slice.
|
|
57
|
+
*
|
|
58
|
+
* `memory` is the list of hit dicts produced by
|
|
59
|
+
* `directives.backend.memory`. Returns `{"asks", "hits", "ids"}`
|
|
60
|
+
* with privacy-safe values only.
|
|
61
|
+
*/
|
|
62
|
+
export function summarise_visibility(
|
|
63
|
+
memory: Any,
|
|
64
|
+
args: { asked_types?: Iterable<string> } = {},
|
|
65
|
+
): Record<string, Any> {
|
|
66
|
+
const asked = [...(args.asked_types ?? DEFAULT_ASKED_TYPES)];
|
|
67
|
+
if (!_pyTruthy(memory) || !Array.isArray(memory)) {
|
|
68
|
+
return { asks: 0, hits: 0, ids: [] };
|
|
69
|
+
}
|
|
70
|
+
const asks = asked.length;
|
|
71
|
+
const seen_types = new Set<string>();
|
|
72
|
+
const ids: string[] = [];
|
|
73
|
+
const seen_ids = new Set<string>();
|
|
74
|
+
for (const entry of memory) {
|
|
75
|
+
if (!_isPlainDict(entry)) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const e = entry as Record<string, unknown>;
|
|
79
|
+
const type_value = e['type'];
|
|
80
|
+
if (typeof type_value === 'string') {
|
|
81
|
+
seen_types.add(type_value);
|
|
82
|
+
}
|
|
83
|
+
const entry_id = _pyOr(_get(e, 'id', undefined), _get(e, 'rule_id', undefined));
|
|
84
|
+
if (!(typeof entry_id === 'string' || _isIntLike(entry_id))) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const sid = _pyStr(entry_id);
|
|
88
|
+
if (seen_ids.has(sid)) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
seen_ids.add(sid);
|
|
92
|
+
ids.push(sid);
|
|
93
|
+
}
|
|
94
|
+
const hits = seen_types.size > 0 ? seen_types.size : ids.length > 0 ? 1 : 0;
|
|
95
|
+
return { asks, hits, ids };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Return a comparable shape for a consequence-key value.
|
|
100
|
+
*
|
|
101
|
+
* List-shaped keys (`applied_rules`, `test_plan`) compare as
|
|
102
|
+
* sorted tuples so order is not a divergence; scalar keys
|
|
103
|
+
* (`confidence_band`, `risk_class`) compare as-is.
|
|
104
|
+
*/
|
|
105
|
+
function _normalise_key_value(value: Any): Any {
|
|
106
|
+
if (Array.isArray(value)) {
|
|
107
|
+
// `tuple(sorted(str(item) for item in value))`
|
|
108
|
+
return _sortedStr(value.map((item) => _pyStr(item)));
|
|
109
|
+
}
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Return sorted keys whose values diverge between two traces.
|
|
115
|
+
*
|
|
116
|
+
* Iterates the closed `CONSEQUENCE_KEYS` list defined in
|
|
117
|
+
* `docs/contracts/decision-trace-v1.md`. A key is considered
|
|
118
|
+
* *diverged* when its normalised value differs between the two
|
|
119
|
+
* traces. Per the contract, when both sides are `None` the key
|
|
120
|
+
* is suppressed from the diff entirely.
|
|
121
|
+
*/
|
|
122
|
+
export function diff_consequence_keys(
|
|
123
|
+
trace_with: Record<string, Any>,
|
|
124
|
+
trace_without: Record<string, Any>,
|
|
125
|
+
): string[] {
|
|
126
|
+
const affected: string[] = [];
|
|
127
|
+
for (const key of CONSEQUENCE_KEYS) {
|
|
128
|
+
const a = _get(trace_with, key, undefined);
|
|
129
|
+
const b = _get(trace_without, key, undefined);
|
|
130
|
+
if (_isNone(a) && _isNone(b)) {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (!_pyEqual(_normalise_key_value(a), _normalise_key_value(b))) {
|
|
134
|
+
affected.push(key);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return _sortedStr(affected);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Compute the `affected` consequence keys for the visibility line.
|
|
142
|
+
*
|
|
143
|
+
* Returns:
|
|
144
|
+
* - `null` when no memory was consulted (`memory_hits <= 0`)
|
|
145
|
+
* — caller MUST omit the `· affected: …` segment.
|
|
146
|
+
* - `[]` when memory was consulted but no closed-list key
|
|
147
|
+
* diverged — caller MUST render `· affected: none`.
|
|
148
|
+
* - sorted list of keys otherwise.
|
|
149
|
+
*
|
|
150
|
+
* The counterfactual trace is "what the heuristics would have
|
|
151
|
+
* emitted if `memory_hits` had been `0`". v1 covers
|
|
152
|
+
* `confidence_band` and `risk_class` via the existing scoring
|
|
153
|
+
* helpers; `applied_rules` and `test_plan` pass through
|
|
154
|
+
* unchanged because they are not yet memory-derived in the
|
|
155
|
+
* engine — the keys stay in the closed list so the diff
|
|
156
|
+
* infrastructure is in place when they wire in.
|
|
157
|
+
*/
|
|
158
|
+
export function compute_affected(args: {
|
|
159
|
+
memory_hits: number;
|
|
160
|
+
verify_claims?: number;
|
|
161
|
+
verify_first_try_passes?: number;
|
|
162
|
+
ambiguity_flag?: boolean;
|
|
163
|
+
changes?: Any;
|
|
164
|
+
applied_rules?: string[] | null;
|
|
165
|
+
test_plan?: string[] | null;
|
|
166
|
+
}): string[] | null {
|
|
167
|
+
const memory_hits = args.memory_hits;
|
|
168
|
+
const verify_claims = args.verify_claims ?? 0;
|
|
169
|
+
const verify_first_try_passes = args.verify_first_try_passes ?? 0;
|
|
170
|
+
const ambiguity_flag = args.ambiguity_flag ?? false;
|
|
171
|
+
const changes = args.changes ?? null;
|
|
172
|
+
const applied_rules = args.applied_rules ?? null;
|
|
173
|
+
const test_plan = args.test_plan ?? null;
|
|
174
|
+
|
|
175
|
+
if (memory_hits <= 0) {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
const trace_with: Record<string, Any> = {
|
|
179
|
+
confidence_band: derive_confidence_band({
|
|
180
|
+
memory_hits,
|
|
181
|
+
verify_claims,
|
|
182
|
+
verify_first_try_passes,
|
|
183
|
+
ambiguity_flag,
|
|
184
|
+
}),
|
|
185
|
+
risk_class: derive_risk_class(changes),
|
|
186
|
+
applied_rules: _pyTruthy(applied_rules) ? [...(applied_rules as string[])] : null,
|
|
187
|
+
test_plan: _pyTruthy(test_plan) ? [...(test_plan as string[])] : null,
|
|
188
|
+
};
|
|
189
|
+
const trace_without: Record<string, Any> = {
|
|
190
|
+
confidence_band: derive_confidence_band({
|
|
191
|
+
memory_hits: 0,
|
|
192
|
+
verify_claims,
|
|
193
|
+
verify_first_try_passes,
|
|
194
|
+
ambiguity_flag,
|
|
195
|
+
}),
|
|
196
|
+
risk_class: derive_risk_class(changes),
|
|
197
|
+
applied_rules: _pyTruthy(applied_rules) ? [...(applied_rules as string[])] : null,
|
|
198
|
+
test_plan: _pyTruthy(test_plan) ? [...(test_plan as string[])] : null,
|
|
199
|
+
};
|
|
200
|
+
return diff_consequence_keys(trace_with, trace_without);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Render the visibility line; return `null` when `asks == 0`.
|
|
205
|
+
*
|
|
206
|
+
* Cap inline ids at `max_inline_ids` and append `…+N` when the
|
|
207
|
+
* list is longer. Returning `null` enforces the contract clause
|
|
208
|
+
* "If `asks == 0`, the engine MUST suppress the line entirely".
|
|
209
|
+
*
|
|
210
|
+
* When `affected` is not `null`, append the
|
|
211
|
+
* `· affected: <keys>` trailing segment from
|
|
212
|
+
* `docs/contracts/memory-visibility-v1.md`: empty list renders as
|
|
213
|
+
* `affected: none` (consulted but no key diverged);
|
|
214
|
+
* non-empty list renders the comma-separated keys.
|
|
215
|
+
*/
|
|
216
|
+
export function format_line(
|
|
217
|
+
summary: Record<string, Any>,
|
|
218
|
+
args: { max_inline_ids?: number; affected?: string[] | null } = {},
|
|
219
|
+
): string | null {
|
|
220
|
+
let max_inline_ids = args.max_inline_ids ?? DEFAULT_MAX_INLINE_IDS;
|
|
221
|
+
const affected = args.affected ?? null;
|
|
222
|
+
|
|
223
|
+
const asks = _pyInt(_pyOr(_get(summary, 'asks', 0), 0));
|
|
224
|
+
if (asks <= 0) {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
const hits = _pyInt(_pyOr(_get(summary, 'hits', 0), 0));
|
|
228
|
+
const raw_ids = (_pyOr(_get(summary, 'ids', undefined), []) as unknown[]) ?? [];
|
|
229
|
+
const ids = (raw_ids as unknown[])
|
|
230
|
+
.filter((i) => typeof i === 'string' || _isIntLike(i))
|
|
231
|
+
.map((i) => _pyStr(i));
|
|
232
|
+
if (max_inline_ids < 0) {
|
|
233
|
+
max_inline_ids = 0;
|
|
234
|
+
}
|
|
235
|
+
const inline = ids.slice(0, max_inline_ids);
|
|
236
|
+
const overflow = ids.length - inline.length;
|
|
237
|
+
let rendered_ids = inline.join(', ');
|
|
238
|
+
if (overflow > 0) {
|
|
239
|
+
const suffix = rendered_ids ? ', ' : '';
|
|
240
|
+
rendered_ids = `${rendered_ids}${suffix}…+${overflow}`;
|
|
241
|
+
}
|
|
242
|
+
let line = `${ICON} Memory: ${hits}/${asks} · ids=[${rendered_ids}]`;
|
|
243
|
+
if (affected !== null) {
|
|
244
|
+
const rendered_affected = affected.length > 0 ? affected.join(',') : 'none';
|
|
245
|
+
line = `${line} · affected: ${rendered_affected}`;
|
|
246
|
+
}
|
|
247
|
+
return line;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Render the end-of-run "Memory changed decisions" report block.
|
|
252
|
+
*
|
|
253
|
+
* Per `docs/contracts/memory-visibility-v1.md`: lists
|
|
254
|
+
* `<id> → <key>` rows derived from the same diff source as the
|
|
255
|
+
* visibility line's `affected` segment. Returns `null` when
|
|
256
|
+
* no key diverged (`affected` empty / `null`) so the caller
|
|
257
|
+
* suppresses the block entirely.
|
|
258
|
+
*
|
|
259
|
+
* Attribution in v1 is aggregate: each consulted id pairs with
|
|
260
|
+
* each affected key. Per-id attribution is captured as a
|
|
261
|
+
* follow-up risk in the roadmap Risk register.
|
|
262
|
+
*/
|
|
263
|
+
export function format_changed_decisions_block(
|
|
264
|
+
ids: Iterable<string>,
|
|
265
|
+
affected: Iterable<string> | null | undefined,
|
|
266
|
+
): string | null {
|
|
267
|
+
if (!_pyTruthy(affected)) {
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
const affected_list = _sortedStr([...(affected as Iterable<string>)]);
|
|
271
|
+
const id_list = [...ids].filter((i) => typeof i === 'string' || _isIntLike(i)).map((i) => _pyStr(i));
|
|
272
|
+
if (id_list.length === 0) {
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
const lines = ['Memory changed decisions:'];
|
|
276
|
+
for (const entry_id of id_list) {
|
|
277
|
+
for (const key of affected_list) {
|
|
278
|
+
lines.push(`- ${entry_id} → ${key}`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return lines.join('\n');
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Apply the cadence + opt-out gates from the contract.
|
|
286
|
+
*
|
|
287
|
+
* `memory_cadence` is the `memory.cadence` cadence key:
|
|
288
|
+
*
|
|
289
|
+
* - `always` (default) — emit whenever `asks >= 1`.
|
|
290
|
+
* - `auto` — emit only when `asks >= 3` (reduces noise on
|
|
291
|
+
* shallow-retrieval steps).
|
|
292
|
+
* - `never` — suppress the line entirely.
|
|
293
|
+
*
|
|
294
|
+
* `visibility_off` is the legacy `memory.visibility: off` master
|
|
295
|
+
* switch and still wins over any `memory_cadence` value.
|
|
296
|
+
*/
|
|
297
|
+
export function should_emit(
|
|
298
|
+
summary: Record<string, Any>,
|
|
299
|
+
args: { memory_cadence?: string; visibility_off?: boolean } = {},
|
|
300
|
+
): boolean {
|
|
301
|
+
const memory_cadence = args.memory_cadence ?? 'always';
|
|
302
|
+
const visibility_off = args.visibility_off ?? false;
|
|
303
|
+
if (visibility_off) {
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
const asks = _pyInt(_pyOr(_get(summary, 'asks', 0), 0));
|
|
307
|
+
if (asks <= 0) {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
const status = (memory_cadence || 'always').trim().toLowerCase();
|
|
311
|
+
if (status === 'never') {
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
if (status === 'auto') {
|
|
315
|
+
return asks >= 3;
|
|
316
|
+
}
|
|
317
|
+
return true;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// ── Python-parity primitives ────────────────────────────────────────────
|
|
321
|
+
|
|
322
|
+
/** `dict.get(key, default)` for a plain object. */
|
|
323
|
+
function _get(obj: Record<string, unknown>, key: string, dflt: unknown): unknown {
|
|
324
|
+
return key in obj ? obj[key] : dflt;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/** Python `a or b`. */
|
|
328
|
+
function _pyOr(a: unknown, b: unknown): unknown {
|
|
329
|
+
return _pyTruthy(a) ? a : b;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/** Python `x is None`. */
|
|
333
|
+
function _isNone(value: unknown): boolean {
|
|
334
|
+
return value === null || value === undefined;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Python `int` / `bool` (not `bool` masquerading) test used by the
|
|
339
|
+
* `isinstance(entry_id, (str, int))` guards. In Python `bool` is a subclass
|
|
340
|
+
* of `int`, so `True`/`False` pass; mirror that.
|
|
341
|
+
*/
|
|
342
|
+
function _isIntLike(value: unknown): boolean {
|
|
343
|
+
if (typeof value === 'boolean') {
|
|
344
|
+
return true;
|
|
345
|
+
}
|
|
346
|
+
return typeof value === 'number' && Number.isInteger(value);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/** Python `bool(x)` truthiness. */
|
|
350
|
+
function _pyTruthy(value: unknown): boolean {
|
|
351
|
+
if (value === null || value === undefined || value === false) {
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
if (value === true) {
|
|
355
|
+
return true;
|
|
356
|
+
}
|
|
357
|
+
if (typeof value === 'number') {
|
|
358
|
+
return value !== 0;
|
|
359
|
+
}
|
|
360
|
+
if (typeof value === 'string') {
|
|
361
|
+
return value.length > 0;
|
|
362
|
+
}
|
|
363
|
+
if (Array.isArray(value)) {
|
|
364
|
+
return value.length > 0;
|
|
365
|
+
}
|
|
366
|
+
if (value instanceof Map || value instanceof Set) {
|
|
367
|
+
return value.size > 0;
|
|
368
|
+
}
|
|
369
|
+
if (typeof value === 'object') {
|
|
370
|
+
return Object.keys(value as Record<string, unknown>).length > 0;
|
|
371
|
+
}
|
|
372
|
+
return true;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/** Python `int(x)` for the dict-scalar / `or 0` shapes this module passes. */
|
|
376
|
+
function _pyInt(value: unknown): number {
|
|
377
|
+
if (value === true) {
|
|
378
|
+
return 1;
|
|
379
|
+
}
|
|
380
|
+
if (value === false) {
|
|
381
|
+
return 0;
|
|
382
|
+
}
|
|
383
|
+
if (typeof value === 'number') {
|
|
384
|
+
return Math.trunc(value);
|
|
385
|
+
}
|
|
386
|
+
if (typeof value === 'string') {
|
|
387
|
+
const trimmed = value.trim();
|
|
388
|
+
const n = Number(trimmed);
|
|
389
|
+
if (trimmed !== '' && Number.isFinite(n)) {
|
|
390
|
+
return Math.trunc(n);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
throw new Error(`invalid literal for int(): ${String(value)}`);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/** Python `str(x)` for the id / list-item shapes. */
|
|
397
|
+
function _pyStr(value: unknown): string {
|
|
398
|
+
if (value === null || value === undefined) {
|
|
399
|
+
return 'None';
|
|
400
|
+
}
|
|
401
|
+
if (value === true) {
|
|
402
|
+
return 'True';
|
|
403
|
+
}
|
|
404
|
+
if (value === false) {
|
|
405
|
+
return 'False';
|
|
406
|
+
}
|
|
407
|
+
return String(value);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/** Python `isinstance(x, dict)` — plain object only. */
|
|
411
|
+
function _isPlainDict(value: unknown): boolean {
|
|
412
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/** Python `sorted(list_of_str)` — code-point ascending. */
|
|
416
|
+
function _sortedStr(values: string[]): string[] {
|
|
417
|
+
return [...values].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Equality matching Python `!=` for the normalised consequence-key values:
|
|
422
|
+
* scalars compare by value; lists (post-`_normalise_key_value` they are
|
|
423
|
+
* already string arrays) compare element-wise; `None` distinct from a value.
|
|
424
|
+
*/
|
|
425
|
+
function _pyEqual(a: unknown, b: unknown): boolean {
|
|
426
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
427
|
+
if (a.length !== b.length) {
|
|
428
|
+
return false;
|
|
429
|
+
}
|
|
430
|
+
for (let i = 0; i < a.length; i += 1) {
|
|
431
|
+
if (!_pyEqual(a[i], b[i])) {
|
|
432
|
+
return false;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
return true;
|
|
436
|
+
}
|
|
437
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
438
|
+
return false;
|
|
439
|
+
}
|
|
440
|
+
if (_isNone(a) && _isNone(b)) {
|
|
441
|
+
return true;
|
|
442
|
+
}
|
|
443
|
+
return a === b;
|
|
444
|
+
}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frontend-stack detection from project manifests.
|
|
3
|
+
*
|
|
4
|
+
* TypeScript twin of `work_engine/stack/detect.py` (ADR-200 py2ts). Leaf
|
|
5
|
+
* module — stdlib only, NO intra-`work_engine` imports — so the public API
|
|
6
|
+
* names stay snake_case to mirror the Python module 1:1 (per ADR-200: Python
|
|
7
|
+
* style is part of the contract).
|
|
8
|
+
*
|
|
9
|
+
* The detector reads `composer.json` and `package.json` from a project
|
|
10
|
+
* root, applies the heuristic table below in priority order, and returns a
|
|
11
|
+
* {@link StackResult} carrying the labelled frontend plus the manifest
|
|
12
|
+
* `mtime` it was computed against. The dispatcher caches the result on
|
|
13
|
+
* `state.stack` and re-runs detection whenever the recorded `mtime`
|
|
14
|
+
* no longer matches what the filesystem reports.
|
|
15
|
+
*
|
|
16
|
+
* Heuristics (priority order — first match wins):
|
|
17
|
+
*
|
|
18
|
+
* 1. `composer.json` lists `livewire/livewire` AND `livewire/flux` →
|
|
19
|
+
* `blade-livewire-flux`
|
|
20
|
+
* 2. `package.json` lists `react` AND any of `@radix-ui/*`,
|
|
21
|
+
* `shadcn-ui` or has a `components.json` (the shadcn marker file)
|
|
22
|
+
* → `react-shadcn`
|
|
23
|
+
* 3. `package.json` lists `vue` (any major) → `vue`
|
|
24
|
+
* 4. Otherwise → `plain`
|
|
25
|
+
*
|
|
26
|
+
* Detection is filesystem-cheap: at most three small JSON reads per
|
|
27
|
+
* project root. Errors (missing file, malformed JSON, missing `require`
|
|
28
|
+
* section) downgrade to `plain` rather than raising — a wrong stack
|
|
29
|
+
* label is recoverable (audit catches it, user can override), but a
|
|
30
|
+
* crash mid-dispatch is not.
|
|
31
|
+
*/
|
|
32
|
+
import * as fs from 'node:fs';
|
|
33
|
+
import * as path from 'node:path';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* All stack labels the detector can return.
|
|
37
|
+
*
|
|
38
|
+
* Kept as a set so consumers (state schema, fixtures, tests) can
|
|
39
|
+
* validate against a single source of truth without re-deriving.
|
|
40
|
+
*
|
|
41
|
+
* Mirrors Python's `frozenset` — the membership semantics are what
|
|
42
|
+
* matter; the literal set construction order is irrelevant.
|
|
43
|
+
*/
|
|
44
|
+
export const KNOWN_STACKS: ReadonlySet<string> = new Set([
|
|
45
|
+
'blade-livewire-flux',
|
|
46
|
+
'react-shadcn',
|
|
47
|
+
'vue',
|
|
48
|
+
'plain',
|
|
49
|
+
]);
|
|
50
|
+
|
|
51
|
+
/** Fallback when no manifest signal matches. */
|
|
52
|
+
export const DEFAULT_STACK = 'plain';
|
|
53
|
+
|
|
54
|
+
const _SHADCN_RADIX_PREFIX = '@radix-ui/';
|
|
55
|
+
const _SHADCN_PACKAGE_NAMES: ReadonlySet<string> = new Set(['shadcn-ui', 'shadcn']);
|
|
56
|
+
const _FLUX_PACKAGE = 'livewire/flux';
|
|
57
|
+
const _LIVEWIRE_PACKAGE = 'livewire/livewire';
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* A heterogeneous JSON object, mirroring a Python `dict[str, object]`.
|
|
61
|
+
* A `null` prototype is not required — the only access is `.get(key)`-style
|
|
62
|
+
* lookup plus `isinstance(section, dict)` checks, both reproduced below.
|
|
63
|
+
*/
|
|
64
|
+
type Manifest = { [key: string]: unknown };
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Outcome of one detection pass.
|
|
68
|
+
*
|
|
69
|
+
* `mtime` is the latest mtime among the manifests actually consulted
|
|
70
|
+
* (`composer.json` and `package.json`), in POSIX seconds. Callers
|
|
71
|
+
* cache the result keyed on this value; a stale cache is invalidated
|
|
72
|
+
* by the next dispatch when the recorded mtime is older than what
|
|
73
|
+
* {@link latest_manifest_mtime} returns.
|
|
74
|
+
*
|
|
75
|
+
* Mirrors the Python `@dataclass(frozen=True)`: a plain immutable value
|
|
76
|
+
* carrier with `frontend` + `mtime` fields, constructed positionally /
|
|
77
|
+
* by keyword.
|
|
78
|
+
*/
|
|
79
|
+
export class StackResult {
|
|
80
|
+
readonly frontend: string;
|
|
81
|
+
readonly mtime: number;
|
|
82
|
+
|
|
83
|
+
constructor(args: { frontend: string; mtime: number }) {
|
|
84
|
+
this.frontend = args.frontend;
|
|
85
|
+
this.mtime = args.mtime;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Inspect `project_root` and label the frontend stack.
|
|
91
|
+
*
|
|
92
|
+
* @param project_root
|
|
93
|
+
* Directory that should contain a `composer.json` or `package.json` at
|
|
94
|
+
* its top level. Other layouts (monorepos, nested workspaces) call this
|
|
95
|
+
* with the workspace root that carries the manifest you care about — the
|
|
96
|
+
* caller picks the scope, the detector does not walk upwards.
|
|
97
|
+
* @returns
|
|
98
|
+
* A {@link StackResult} whose `frontend` is one of {@link KNOWN_STACKS};
|
|
99
|
+
* `mtime` is the latest manifest mtime among the files actually
|
|
100
|
+
* consulted, or `0.0` when no manifests exist (greenfield project).
|
|
101
|
+
*/
|
|
102
|
+
export function detect_stack(project_root: string): StackResult {
|
|
103
|
+
const composer = _read_json(path.join(project_root, 'composer.json'));
|
|
104
|
+
const pkg = _read_json(path.join(project_root, 'package.json'));
|
|
105
|
+
const components_json = _is_file(path.join(project_root, 'components.json'));
|
|
106
|
+
const mtime = latest_manifest_mtime(project_root);
|
|
107
|
+
|
|
108
|
+
if (_is_blade_livewire_flux(composer)) {
|
|
109
|
+
return new StackResult({ frontend: 'blade-livewire-flux', mtime });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (_is_react_shadcn(pkg, components_json)) {
|
|
113
|
+
return new StackResult({ frontend: 'react-shadcn', mtime });
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (_has_vue(pkg)) {
|
|
117
|
+
return new StackResult({ frontend: 'vue', mtime });
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return new StackResult({ frontend: DEFAULT_STACK, mtime });
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Return the latest mtime across the manifests we consult.
|
|
125
|
+
*
|
|
126
|
+
* Used by the dispatcher's cache check: when the persisted
|
|
127
|
+
* `state.stack.mtime` no longer matches the live value, the cached
|
|
128
|
+
* label is invalidated and detection re-runs. Returns `0.0` when no
|
|
129
|
+
* manifest is present so a fresh greenfield repo produces a stable
|
|
130
|
+
* sentinel rather than a missing-file error.
|
|
131
|
+
*/
|
|
132
|
+
export function latest_manifest_mtime(project_root: string): number {
|
|
133
|
+
const candidates = ['composer.json', 'package.json'];
|
|
134
|
+
const mtimes: number[] = [];
|
|
135
|
+
for (const name of candidates) {
|
|
136
|
+
const p = path.join(project_root, name);
|
|
137
|
+
if (_is_file(p)) {
|
|
138
|
+
mtimes.push(_stat_mtime(p));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return mtimes.length > 0 ? Math.max(...mtimes) : 0.0;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Read a JSON manifest, returning `{}` on any error.
|
|
146
|
+
*
|
|
147
|
+
* Wrong-but-recoverable beats crash-mid-dispatch. Audit and the
|
|
148
|
+
* refine step will surface the real shape of the project; the
|
|
149
|
+
* detector's job is just to pick a routing label.
|
|
150
|
+
*/
|
|
151
|
+
function _read_json(p: string): Manifest {
|
|
152
|
+
if (!_is_file(p)) {
|
|
153
|
+
return {};
|
|
154
|
+
}
|
|
155
|
+
let payload: unknown;
|
|
156
|
+
try {
|
|
157
|
+
payload = JSON.parse(fs.readFileSync(p, { encoding: 'utf-8' }));
|
|
158
|
+
} catch {
|
|
159
|
+
// Mirrors Python's `except (OSError, json.JSONDecodeError)`: any read
|
|
160
|
+
// or parse failure degrades to the empty manifest.
|
|
161
|
+
return {};
|
|
162
|
+
}
|
|
163
|
+
return _isDict(payload) ? payload : {};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Merge the dependency-style sections of a manifest into one map.
|
|
168
|
+
*
|
|
169
|
+
* composer.json uses `require` and `require-dev`; package.json uses
|
|
170
|
+
* `dependencies`, `devDependencies`, `peerDependencies`, and
|
|
171
|
+
* `optionalDependencies`. We only care whether a name is present
|
|
172
|
+
* anywhere — version pinning is the audit step's concern.
|
|
173
|
+
*/
|
|
174
|
+
function _all_dependencies(manifest: Manifest, ...keys: string[]): Manifest {
|
|
175
|
+
const merged: Manifest = {};
|
|
176
|
+
for (const key of keys) {
|
|
177
|
+
const section = manifest[key];
|
|
178
|
+
if (_isDict(section)) {
|
|
179
|
+
// `dict.update` overwrites with later keys but preserves the
|
|
180
|
+
// insertion order of first-seen keys; we only test membership,
|
|
181
|
+
// so a plain assign reproduces the relevant semantics.
|
|
182
|
+
Object.assign(merged, section);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return merged;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function _is_blade_livewire_flux(composer: Manifest): boolean {
|
|
189
|
+
const deps = _all_dependencies(composer, 'require', 'require-dev');
|
|
190
|
+
return _LIVEWIRE_PACKAGE in deps && _FLUX_PACKAGE in deps;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function _is_react_shadcn(pkg: Manifest, components_json: boolean): boolean {
|
|
194
|
+
const deps = _all_dependencies(
|
|
195
|
+
pkg,
|
|
196
|
+
'dependencies',
|
|
197
|
+
'devDependencies',
|
|
198
|
+
'peerDependencies',
|
|
199
|
+
'optionalDependencies',
|
|
200
|
+
);
|
|
201
|
+
if (!('react' in deps)) {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
const names = Object.keys(deps);
|
|
205
|
+
const has_radix = names.some((name) => name.startsWith(_SHADCN_RADIX_PREFIX));
|
|
206
|
+
const has_shadcn_pkg = names.some((name) => _SHADCN_PACKAGE_NAMES.has(name));
|
|
207
|
+
return has_radix || has_shadcn_pkg || components_json;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function _has_vue(pkg: Manifest): boolean {
|
|
211
|
+
const deps = _all_dependencies(
|
|
212
|
+
pkg,
|
|
213
|
+
'dependencies',
|
|
214
|
+
'devDependencies',
|
|
215
|
+
'peerDependencies',
|
|
216
|
+
'optionalDependencies',
|
|
217
|
+
);
|
|
218
|
+
return 'vue' in deps;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ── stdlib parity helpers ───────────────────────────────────────────────
|
|
222
|
+
|
|
223
|
+
/** Python `Path.is_file()` — true only for a regular file (follows symlinks). */
|
|
224
|
+
function _is_file(p: string): boolean {
|
|
225
|
+
try {
|
|
226
|
+
return fs.statSync(p).isFile();
|
|
227
|
+
} catch {
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Python `Path.stat().st_mtime` in POSIX seconds.
|
|
234
|
+
*
|
|
235
|
+
* Python derives `st_mtime` (a float) from the OS nanosecond timestamp.
|
|
236
|
+
* Reading `mtimeNs` (an integer, byte-identical to Python's `st_mtime_ns`)
|
|
237
|
+
* and dividing by `1e9` reproduces the same value closely. Note: the exact
|
|
238
|
+
* float byte-repr of `st_mtime` can differ between CPython and V8 for some
|
|
239
|
+
* sub-second timestamps — callers that *serialize* mtime (only
|
|
240
|
+
* `runner.to_config` does) treat it as non-deterministic and the parity
|
|
241
|
+
* tests normalize the field. The detection logic compares `mtime` only for
|
|
242
|
+
* cache-invalidation (numeric `!=`), where this precision is sufficient.
|
|
243
|
+
*/
|
|
244
|
+
function _stat_mtime(p: string): number {
|
|
245
|
+
const st = fs.statSync(p, { bigint: true });
|
|
246
|
+
return Number(st.mtimeNs) / 1e9;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/** Python `isinstance(x, dict)` — a plain (non-array, non-null) object. */
|
|
250
|
+
function _isDict(v: unknown): v is Manifest {
|
|
251
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
252
|
+
}
|