@event4u/agent-config 16.1.0 → 16.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +98 -257
- package/README.md +14 -12
- package/dist/agent-src/commands/analyze/inbox.md +1 -1
- package/dist/agent-src/commands/analyze/roadmap-repos.md +1 -1
- package/dist/agent-src/commands/bug/fix.md +17 -2
- package/dist/agent-src/commands/feature/plan.md +1 -1
- package/dist/agent-src/commands/feature/roadmap.md +1 -1
- package/dist/agent-src/commands/fix/ci.md +1 -1
- package/dist/agent-src/commands/implement-ticket.md +1 -1
- package/dist/agent-src/commands/jira-ticket.md +1 -1
- package/dist/agent-src/commands/roadmap/create.md +1 -1
- package/dist/agent-src/commands/roadmap/materialize.md +1 -1
- package/dist/agent-src/commands/roadmap/process-full.md +5 -5
- package/dist/agent-src/commands/roadmap/resolve-blockers.md +361 -0
- package/dist/agent-src/commands/roadmap/triage-parked.md +325 -0
- package/dist/agent-src/commands/roadmap.md +18 -4
- package/dist/agent-src/commands/tests/create.md +17 -3
- package/dist/agent-src/commands/tests/execute.md +22 -5
- package/dist/agent-src/commands/work.md +4 -0
- package/dist/agent-src/contexts/authority/decision-revisit-gate-enforcement.md +43 -0
- package/dist/agent-src/contexts/communication/rules-auto/design-fidelity-enforcement.md +24 -0
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +6 -6
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +4 -8
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +32 -2
- package/dist/agent-src/contexts/execution/session-canary-enforcement-history.md +67 -0
- package/dist/agent-src/contexts/execution/toolchain-resolver.md +101 -7
- package/dist/agent-src/rules/active-remediation.md +1 -1
- package/dist/agent-src/rules/autonomous-execution.md +1 -0
- package/dist/agent-src/rules/broken-access-control.md +1 -0
- package/dist/agent-src/rules/command-suggestion-policy.md +1 -0
- package/dist/agent-src/rules/context-hygiene.md +1 -1
- package/dist/agent-src/rules/decision-revisit-gate.md +16 -33
- package/dist/agent-src/rules/design-fidelity.md +13 -16
- package/dist/agent-src/rules/doc-screenshot-hygiene.md +1 -0
- package/dist/agent-src/rules/domain-safety-disclaimer.md +1 -0
- package/dist/agent-src/rules/domain-safety-pii.md +1 -0
- package/dist/agent-src/rules/domain-safety-retention.md +1 -0
- package/dist/agent-src/rules/engineering-safety-floor.md +1 -0
- package/dist/agent-src/rules/evaluator-independence.md +3 -2
- package/dist/agent-src/rules/fast-path-marker-visibility.md +1 -0
- package/dist/agent-src/rules/finance-safety-floor.md +1 -0
- package/dist/agent-src/rules/git-history-discipline.md +1 -0
- package/dist/agent-src/rules/image-likeness-and-rights.md +1 -0
- package/dist/agent-src/rules/legal-safety-floor.md +3 -2
- package/dist/agent-src/rules/lethal-trifecta-guard.md +1 -0
- package/dist/agent-src/rules/low-impact-corpus-privacy-floor.md +1 -0
- package/dist/agent-src/rules/media-governance-routing.md +14 -17
- package/dist/agent-src/rules/persona-governance.md +2 -2
- package/dist/agent-src/rules/provider-lifecycle-discipline.md +1 -1
- package/dist/agent-src/rules/question-not-instruction.md +1 -0
- package/dist/agent-src/rules/roadmap-progress-sync.md +1 -1
- package/dist/agent-src/rules/runtime-safety.md +1 -0
- package/dist/agent-src/rules/secret-vcs-guard.md +1 -0
- package/dist/agent-src/rules/security-sensitive-stop.md +3 -2
- package/dist/agent-src/rules/session-canary.md +8 -62
- package/dist/agent-src/rules/settings-ask-protocol.md +1 -0
- package/dist/agent-src/rules/source-confidentiality.md +1 -0
- package/dist/agent-src/rules/strategy-safety-floor.md +1 -0
- package/dist/agent-src/rules/tool-safety.md +1 -0
- package/dist/agent-src/rules/ui-audit-gate.md +1 -2
- package/dist/agent-src/rules/untrusted-input-defense.md +1 -0
- package/dist/agent-src/rules/user-interrupt-priority.md +1 -0
- package/dist/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
- package/dist/agent-src/scripts/deferral_carry.ts +339 -0
- package/dist/agent-src/scripts/update_roadmap_progress.ts +4 -1
- package/dist/agent-src/skills/accessibility-auditor/data/aria-patterns.csv +1 -1
- package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +2 -2
- package/dist/agent-src/skills/api-design/data/manifest.json +2 -2
- package/dist/agent-src/skills/api-testing/SKILL.md +17 -0
- package/dist/agent-src/skills/code-intelligence/SKILL.md +14 -2
- package/dist/agent-src/skills/design-review/SKILL.md +30 -4
- package/dist/agent-src/skills/design-review/references/verification-automation.md +32 -0
- package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +1 -1
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +18 -3
- package/dist/agent-src/skills/existing-ui-audit/references/component-taxonomy-detection.md +56 -0
- package/dist/agent-src/skills/fe-design/SKILL.md +1 -1
- package/dist/agent-src/skills/iconography/SKILL.md +1 -1
- package/dist/agent-src/skills/js-library-packaging/SKILL.md +2 -2
- package/dist/agent-src/skills/markitdown/SKILL.md +4 -0
- package/dist/agent-src/skills/monorepo-workspace/SKILL.md +1 -1
- package/dist/agent-src/skills/playwright-testing/SKILL.md +30 -6
- package/dist/agent-src/skills/quality-tools/SKILL.md +11 -1
- package/dist/agent-src/skills/quality-tools/references/go-tools.md +76 -0
- package/dist/agent-src/skills/quality-tools/references/python-tools.md +104 -0
- package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +1 -1
- package/dist/agent-src/skills/storybook-workshop/SKILL.md +3 -3
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +1 -1
- package/dist/agent-src/skills/test-case-discovery/SKILL.md +7 -0
- package/dist/agent-src/skills/test-driven-development/SKILL.md +17 -0
- package/dist/agent-src/skills/test-performance/SKILL.md +19 -1
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +25 -2
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +30 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +10 -4
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +302 -21
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +22 -3
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +6 -1
- package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
- package/dist/agent-src/templates/scripts/work_engine/state.ts +57 -7
- package/dist/agent-src/templates/scripts/work_engine/taxonomy/detect.ts +500 -0
- package/dist/agent-src/templates/scripts/work_engine/taxonomy/place.ts +183 -0
- package/dist/cli/python/knowledge_ingest.js +1 -1
- package/dist/cli/python/workspace_drive.js +1 -1
- package/dist/cli/registry.js +1 -1
- package/dist/cli-delegate/archive_completed_roadmaps.js +92 -12
- package/dist/cli-delegate/check_update_banner.js +12 -1
- package/dist/cli-delegate/chunk-523HCFYO.js +90 -0
- package/dist/cli-delegate/{chunk-M2DPGFZ4.js → chunk-6V6TA25H.js} +22 -152
- package/dist/cli-delegate/chunk-7IQE3D5S.js +191 -0
- package/dist/cli-delegate/{chunk-6KFEC3G7.js → chunk-CQWX336L.js} +1 -1
- package/dist/cli-delegate/chunk-DEIV7XP7.js +108 -0
- package/dist/cli-delegate/chunk-EEHDXSYD.js +2040 -0
- package/dist/cli-delegate/{chunk-P6ZHP5W2.js → chunk-GKE7ZVFA.js} +4 -4
- package/dist/cli-delegate/chunk-JQOM7TTM.js +1201 -0
- package/dist/cli-delegate/{chunk-UNCRJBT3.js → chunk-JQVYKIZA.js} +41 -0
- package/dist/cli-delegate/{chunk-FC75PGJE.js → chunk-JY2I2DXV.js} +12 -1
- package/dist/cli-delegate/chunk-KB5FZ655.js +208 -0
- package/dist/cli-delegate/{chunk-YUM5KURG.js → chunk-KR6EM23A.js} +235 -1455
- package/dist/cli-delegate/{chunk-LTYVIY76.js → chunk-LIYTLH6O.js} +1 -1
- package/dist/cli-delegate/chunk-NQ7WT43P.js +2729 -0
- package/dist/cli-delegate/chunk-NXEILF2K.js +2160 -0
- package/dist/cli-delegate/{chunk-5R7HOLAF.js → chunk-NYX3L2PZ.js} +1 -1
- package/dist/cli-delegate/{chunk-4E2W63DA.js → chunk-OKJUIAPS.js} +62 -1
- package/dist/cli-delegate/{chunk-QAJS5YWY.js → chunk-PHD7OOLE.js} +2 -1
- package/dist/cli-delegate/{chunk-RGNIWTEA.js → chunk-QLDHIPWR.js} +1 -1
- package/dist/cli-delegate/{chunk-HDVVGPQW.js → chunk-RQNNW7IF.js} +1405 -567
- package/dist/cli-delegate/{chunk-S3VFXMTM.js → chunk-S4UMZNES.js} +1 -1
- package/dist/cli-delegate/{chunk-6KM6ORRY.js → chunk-S4YWNRKO.js} +24 -8
- package/dist/cli-delegate/{chunk-GJCBB2UG.js → chunk-TRI6DQZ6.js} +3054 -325
- package/dist/cli-delegate/chunk-ULQRUR23.js +208 -0
- package/dist/cli-delegate/{chunk-NUHLI2RX.js → chunk-YCU3TIXH.js} +2 -0
- package/dist/cli-delegate/chunk-ZBZV2G5R.js +210 -0
- package/dist/cli-delegate/{chunk-WGXTVKCQ.js → chunk-ZUZKZYCN.js} +5 -3
- package/dist/cli-delegate/cmd_analyze_session.js +1 -1
- package/dist/cli-delegate/cmd_brand_status.js +1 -1
- package/dist/cli-delegate/cmd_conformance.js +1862 -809
- package/dist/cli-delegate/cmd_doctor.js +13 -6
- package/dist/cli-delegate/cmd_doctor_neighbours.js +23 -0
- package/dist/cli-delegate/cmd_explain.js +5 -5
- package/dist/cli-delegate/cmd_export.js +11 -8
- package/dist/cli-delegate/cmd_fleet.js +3 -3
- package/dist/cli-delegate/cmd_handoff.js +10 -7
- package/dist/cli-delegate/cmd_mcp_available.js +1 -1
- package/dist/cli-delegate/cmd_memory_get.js +3 -1
- package/dist/cli-delegate/cmd_migrate.js +2 -2
- package/dist/cli-delegate/cmd_packs_active.js +3 -3
- package/dist/cli-delegate/cmd_preflight.js +6 -6
- package/dist/cli-delegate/cmd_prune.js +11 -8
- package/dist/cli-delegate/cmd_refresh.js +2 -1
- package/dist/cli-delegate/cmd_route_audit.js +8 -6
- package/dist/cli-delegate/cmd_route_explain.js +4 -4
- package/dist/cli-delegate/cmd_session_recycle.js +4 -3
- package/dist/cli-delegate/cmd_settings_get.js +1 -1
- package/dist/cli-delegate/cmd_settings_migrate.js +11 -8
- package/dist/cli-delegate/cmd_settings_set.js +4 -4
- package/dist/cli-delegate/cmd_sync.js +11 -8
- package/dist/cli-delegate/cmd_uninstall.js +11 -8
- package/dist/cli-delegate/cmd_update.js +1 -1
- package/dist/cli-delegate/cmd_upgrade.js +3 -2
- package/dist/cli-delegate/cmd_validate.js +11 -8
- package/dist/cli-delegate/cmd_versions.js +1 -1
- package/dist/cli-delegate/deferral_carry.js +16 -0
- package/dist/cli-delegate/gate_execute.js +2 -2
- package/dist/cli-delegate/roadmap_gates.js +5 -5
- package/dist/cli-delegate/update_roadmap_progress.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +132 -80
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +7 -5
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +6 -4
- package/dist/hooks/dispatch.js +7972 -5186
- package/dist/hooks/dispatch.sha256 +1 -0
- package/dist/install/claudePathsPlan.js +47 -6
- package/dist/install/claudeRuleRewrite.js +7 -0
- package/dist/install/emit_host_rules_cli.js +39 -36
- package/dist/install/globalRuleScope.js +87 -0
- package/dist/install/host_rule_ownership.js +160 -0
- package/dist/install/install.mjs +2226 -1055
- package/dist/install/installThinLayer.js +261 -0
- package/dist/install/installedRuleLinks.js +176 -0
- package/dist/install/wizard-plan.js +24 -0
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +40913 -34865
- package/dist/scripts/_lib/agent_settings.js +11 -0
- package/dist/scripts/_lib/claude_settings_hooks.js +10 -8
- package/dist/scripts/_lib/installed_layer.js +378 -0
- package/dist/scripts/_lib/lean_projection_mode.js +218 -15
- package/dist/scripts/_lib/rule_consequence_class.js +45 -0
- package/dist/scripts/_lib/rule_injection.js +67 -10
- package/dist/scripts/_lib/rule_law_section.js +122 -0
- package/dist/scripts/_lib/thin_rules.js +458 -0
- package/dist/scripts/_lib/windsurf_render.js +60 -0
- package/dist/scripts/condense.js +14 -26
- package/dist/scripts/project_thin_rules.js +14 -294
- package/dist/server/schemas/settings.js +29 -0
- package/dist/shared/skillRanking.js +74 -13
- package/dist/ui/assets/index-Cwq4d0hX.js +23 -0
- package/dist/ui/assets/index-Cyjy8bWO.css +1 -0
- package/dist/ui/index.html +2 -2
- package/docs/contracts/settings-classes.md +10 -6
- package/package.json +4 -4
- package/src/agent-src/scripts/archive_completed_roadmaps.ts +115 -20
- package/src/agent-src/scripts/deferral_carry.ts +339 -0
- package/src/agent-src/scripts/update_roadmap_progress.ts +4 -1
- package/src/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +10 -4
- package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +302 -21
- package/src/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +22 -3
- package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +6 -1
- package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
- package/src/agent-src/templates/scripts/work_engine/state.ts +57 -7
- package/src/agent-src/templates/scripts/work_engine/taxonomy/detect.ts +500 -0
- package/src/agent-src/templates/scripts/work_engine/taxonomy/place.ts +183 -0
- package/src/config/agent-settings.template.yml +91 -22
- package/src/config/ci-local-parity.yml +18 -0
- package/src/config/continuity-surface.json +9 -2
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +327 -3
- package/src/config/gate-violation-baselines.json +21 -9
- package/src/config/hook-bundle-budget.json +25 -0
- package/src/config/hook-latency-budget.json +21 -0
- package/src/config/hook-token-budget.json +8 -3
- package/src/config/host-instruction-limits.json +33 -0
- package/src/config/metric-registry.yml +114 -0
- package/src/config/placeholder-drift-budget.json +10 -0
- package/src/config/routing-coverage-seed.json +38 -3
- package/src/config/rule-activation-census.json +7 -3
- package/src/config/rule-consequence-class.json +161 -0
- package/src/config/rule-law-ceilings.json +99 -0
- package/src/install/claudePathsPlan.ts +46 -4
- package/src/install/claudeRuleRewrite.ts +10 -1
- package/src/install/emit_host_rules_cli.ts +43 -34
- package/src/install/globalRuleScope.ts +109 -0
- package/src/install/host_rule_ownership.ts +170 -0
- package/src/install/installThinLayer.ts +312 -0
- package/src/install/installedRuleLinks.ts +220 -0
- package/src/install/wizard-plan.ts +24 -0
- package/src/scripts/_cli/cmd_doctor.ts +28 -90
- package/src/scripts/_cli/cmd_doctor_neighbours.ts +293 -0
- package/src/scripts/_cli/doctor_execution.ts +100 -17
- package/src/scripts/_cli/doctor_network_posture.ts +226 -0
- package/src/scripts/_dispatch.bash +16 -2
- package/src/scripts/_lib/agent_settings.ts +11 -0
- package/src/scripts/_lib/body_portable.ts +102 -0
- package/src/scripts/_lib/cc_transcript.ts +132 -1
- package/src/scripts/_lib/claude_settings_hooks.ts +10 -8
- package/src/scripts/_lib/concern_sla_window.ts +200 -0
- package/src/scripts/_lib/estate_offsets.ts +241 -0
- package/src/scripts/_lib/exemption_shape.ts +143 -0
- package/src/scripts/_lib/fnv.ts +23 -0
- package/src/scripts/_lib/foreign_scan.ts +106 -0
- package/src/scripts/_lib/forge_protection.ts +114 -0
- package/src/scripts/_lib/forge_reader.ts +558 -0
- package/src/scripts/_lib/gitignore_block.ts +314 -0
- package/src/scripts/_lib/global_deploy_inventory.ts +32 -0
- package/src/scripts/_lib/graph_feeder_record.ts +214 -0
- package/src/scripts/_lib/hook_settings.ts +73 -0
- package/src/scripts/_lib/host_capability.ts +40 -19
- package/src/scripts/_lib/host_env_write.ts +111 -0
- package/src/scripts/_lib/host_hook_merge.ts +165 -0
- package/src/scripts/_lib/installed_layer.ts +538 -0
- package/src/scripts/_lib/json_merge.ts +82 -0
- package/src/scripts/_lib/json_pointers.ts +93 -11
- package/src/scripts/_lib/lean_projection_mode.ts +275 -15
- package/src/scripts/_lib/llm_proposer_transport.ts +14 -4
- package/src/scripts/_lib/machine_wake.ts +16 -3
- package/src/scripts/_lib/neighbour_census.ts +760 -0
- package/src/scripts/_lib/neighbour_scan.ts +122 -0
- package/src/scripts/_lib/neighbour_tool_use.ts +189 -0
- package/src/scripts/_lib/obligations.ts +119 -8
- package/src/scripts/_lib/probe_inputs.ts +271 -0
- package/src/scripts/_lib/prompt_shape.ts +46 -0
- package/src/scripts/_lib/read_surface_scan.ts +322 -0
- package/src/scripts/_lib/release_highlights.ts +2 -1
- package/src/scripts/_lib/release_migration_gate.ts +19 -3
- package/src/scripts/_lib/reserved_name_sweep.ts +73 -0
- package/src/scripts/_lib/retrieval_sanitize.ts +77 -16
- package/src/scripts/_lib/review_coverage.ts +134 -0
- package/src/scripts/_lib/rule_consequence_class.ts +71 -0
- package/src/scripts/_lib/rule_injection.ts +130 -10
- package/src/scripts/_lib/rule_law_section.ts +147 -0
- package/src/scripts/_lib/rule_layer_overlap.ts +58 -0
- package/src/scripts/_lib/shell_write_shapes.ts +108 -0
- package/src/scripts/_lib/skill_origin.ts +254 -0
- package/src/scripts/_lib/structural_hiding.ts +622 -0
- package/src/scripts/_lib/structured_ask.ts +64 -21
- package/src/scripts/_lib/thin_rules.ts +540 -0
- package/src/scripts/_lib/touched_file_quality.ts +434 -0
- package/src/scripts/_lib/turn_end_refusals.ts +600 -4
- package/src/scripts/_lib/turn_end_transcript.ts +216 -0
- package/src/scripts/_lib/verification_command.ts +324 -0
- package/src/scripts/_lib/verification_evidence.ts +647 -0
- package/src/scripts/_lib/verify_clause.ts +280 -0
- package/src/scripts/_lib/windsurf_render.ts +63 -0
- package/src/scripts/ai_council/cli_call_budget.ts +13 -5
- package/src/scripts/ai_council/clients.ts +26 -57
- package/src/scripts/ai_council/config.ts +1 -1
- package/src/scripts/ai_council/vendor_defaults.ts +45 -0
- package/src/scripts/ai_team/team_dispatch.ts +4 -0
- package/src/scripts/audit_skill_overlap.ts +261 -0
- package/src/scripts/before_complete_hook.ts +573 -25
- package/src/scripts/bench_hook_latency.ts +412 -5
- package/src/scripts/bench_touched_file_quality.ts +238 -0
- package/src/scripts/cache_realization_report.ts +61 -1
- package/src/scripts/check_argument_hint.ts +287 -0
- package/src/scripts/check_claims.ts +125 -1
- package/src/scripts/check_enforcement_coverage.ts +38 -9
- package/src/scripts/check_enforcement_matrix.ts +621 -22
- package/src/scripts/check_estate_count.ts +130 -153
- package/src/scripts/check_finding_dispositions.ts +138 -7
- package/src/scripts/check_generator_sync.ts +71 -0
- package/src/scripts/check_hook_bundle_composition.ts +370 -0
- package/src/scripts/check_host_docs_digest.ts +786 -0
- package/src/scripts/check_host_format_column.ts +559 -0
- package/src/scripts/check_input_references.ts +228 -0
- package/src/scripts/check_inputs_parity.ts +235 -0
- package/src/scripts/check_kernel_edit_ratified.ts +89 -9
- package/src/scripts/check_kill_switch_table.ts +294 -0
- package/src/scripts/check_memory.ts +7 -1
- package/src/scripts/check_placeholder_drift.ts +221 -0
- package/src/scripts/check_read_surface_coverage.ts +515 -0
- package/src/scripts/check_release_highlights.ts +10 -0
- package/src/scripts/check_release_holds.ts +2 -1
- package/src/scripts/check_release_pr_shape.ts +38 -15
- package/src/scripts/check_routing_coverage.ts +378 -11
- package/src/scripts/check_standing_rule_delivery.ts +33 -13
- package/src/scripts/check_static_parity.ts +17 -0
- package/src/scripts/check_verify_expectation_delta.ts +521 -0
- package/src/scripts/ci_settle.ts +145 -19
- package/src/scripts/closure_scan.ts +115 -1
- package/src/scripts/code_graph/detect.ts +127 -7
- package/src/scripts/code_graph/foreign.ts +194 -0
- package/src/scripts/code_graph/query.ts +217 -4
- package/src/scripts/code_graph/types.ts +26 -2
- package/src/scripts/code_graph/validate.ts +3 -1
- package/src/scripts/code_graph/verbs.ts +103 -0
- package/src/scripts/compile_hook_manifest.ts +90 -14
- package/src/scripts/condense.ts +14 -27
- package/src/scripts/estate_exemption_shape.ts +202 -0
- package/src/scripts/external_sources_denylist.json +29 -4
- package/src/scripts/generate_host_cost_table.ts +1 -1
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +192 -14
- package/src/scripts/hooks/block_config_weakening.ts +294 -4
- package/src/scripts/hooks/block_kernel_rule_writes.ts +9 -78
- package/src/scripts/hooks/block_plumbing_writes.ts +342 -0
- package/src/scripts/hooks/bundle_integrity.ts +291 -0
- package/src/scripts/hooks/chain_nudge_hook.ts +1 -2
- package/src/scripts/hooks/code_graph_context_hook.ts +253 -25
- package/src/scripts/hooks/comment_discipline_hook.ts +1 -3
- package/src/scripts/hooks/concern_failure_policy.ts +280 -0
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/hooks/concern_timings.ts +94 -0
- package/src/scripts/hooks/delegation_nudge_hook.ts +1 -2
- package/src/scripts/hooks/design_pass_hook.ts +100 -9
- package/src/scripts/hooks/design_slop_hook.ts +1 -2
- package/src/scripts/hooks/dispatch_hook.ts +77 -71
- package/src/scripts/hooks/edit_shape_hook.ts +1 -2
- package/src/scripts/hooks/end_review_nudge_hook.ts +1 -1
- package/src/scripts/hooks/evidence_independence.ts +1 -2
- package/src/scripts/hooks/exit_codes.ts +129 -0
- package/src/scripts/hooks/host_lowering.json +1 -0
- package/src/scripts/hooks/host_lowering.ts +146 -3
- package/src/scripts/hooks/host_lowering.yaml +262 -46
- package/src/scripts/hooks/host_semantics.ts +30 -2
- package/src/scripts/hooks/injection_budget.ts +9 -2
- package/src/scripts/hooks/interruption_ledger_hook.ts +1 -2
- package/src/scripts/hooks/journal_record_hook.ts +1 -2
- package/src/scripts/hooks/memory_recall_hook.ts +1 -2
- package/src/scripts/hooks/obligation_settle_hook.ts +151 -5
- package/src/scripts/hooks/one_question_per_ask_hook.ts +43 -6
- package/src/scripts/hooks/orchestration_record_hook.ts +1 -2
- package/src/scripts/hooks/payload_stub.ts +10 -1
- package/src/scripts/hooks/permission_gate.ts +1 -2
- package/src/scripts/hooks/push_settle_hook.ts +1 -3
- package/src/scripts/hooks/replay_hook.ts +2 -1
- package/src/scripts/hooks/reread_guard_hook.ts +1 -2
- package/src/scripts/hooks/review_baseline_hook.ts +1 -2
- package/src/scripts/hooks/rtk_wrap_hook.ts +1 -2
- package/src/scripts/hooks/rule_inject_hook.ts +765 -68
- package/src/scripts/hooks/run_continuation_hook.ts +13 -15
- package/src/scripts/hooks/skill_route_hook.ts +1 -2
- package/src/scripts/hooks/source_first_gate_hook.ts +1 -2
- package/src/scripts/hooks/spawn_guard_shadow_hook.ts +1 -2
- package/src/scripts/hooks/subagent_ledger_hook.ts +1 -2
- package/src/scripts/hooks/suggestion_capture_hook.ts +1 -1
- package/src/scripts/hooks/table_fingerprint.ts +70 -0
- package/src/scripts/hooks/telemetry_flush_hook.ts +1 -2
- package/src/scripts/hooks/telemetry_usage_hook.ts +65 -10
- package/src/scripts/hooks/tool_result_bytes_hook.ts +93 -9
- package/src/scripts/hooks/turn_end_gate_hook.ts +421 -324
- package/src/scripts/hooks/ui_route_nudge_hook.ts +1 -2
- package/src/scripts/hooks_status.ts +112 -0
- package/src/scripts/injection_scan_hook.ts +7 -0
- package/src/scripts/install.ts +75 -189
- package/src/scripts/installed_layer_report.ts +103 -0
- package/src/scripts/language_mirror_hook.ts +15 -6
- package/src/scripts/learning_sidecar.ts +119 -8
- package/src/scripts/lint_deny_text.ts +419 -0
- package/src/scripts/lint_exit_codes.ts +262 -0
- package/src/scripts/lint_hook_manifest.ts +108 -0
- package/src/scripts/lint_major_migration_sections.ts +156 -26
- package/src/scripts/lint_pack_boundaries.ts +63 -5
- package/src/scripts/lint_roadmap_blockers.ts +78 -12
- package/src/scripts/lint_rule_law_section.ts +517 -0
- package/src/scripts/lint_skill_descriptions.ts +1 -1
- package/src/scripts/lint_skill_scripts_readonly.ts +1 -1
- package/src/scripts/lint_workflow_security.ts +161 -5
- package/src/scripts/mcp_server/consumer_tool_catalog.json +53 -0
- package/src/scripts/mcp_server/graph_tools.ts +72 -3
- package/src/scripts/mcp_server/prompts.ts +142 -1
- package/src/scripts/measure_routing_signal.ts +54 -16
- package/src/scripts/measure_skill_ranker_baseline.ts +515 -53
- package/src/scripts/measure_turn_end_gate.ts +193 -0
- package/src/scripts/memory_learn_hook.ts +91 -6
- package/src/scripts/memory_lookup.ts +1 -1
- package/src/scripts/model_rule_injection.ts +52 -5
- package/src/scripts/prepack-check.mjs +53 -0
- package/src/scripts/project_thin_rules.ts +34 -327
- package/src/scripts/release_publication.ts +13 -1
- package/src/scripts/report_evidence_temperature.ts +657 -0
- package/src/scripts/report_installed_rule_links.ts +157 -0
- package/src/scripts/report_invocation_surface.ts +383 -0
- package/src/scripts/report_label_agreement.ts +233 -0
- package/src/scripts/report_obligation_carriers.ts +699 -0
- package/src/scripts/report_obligation_mechanism.ts +230 -0
- package/src/scripts/report_obligation_writer_split.ts +236 -0
- package/src/scripts/report_single_token_triggers.ts +277 -0
- package/src/scripts/report_skill_menu_census.ts +208 -0
- package/src/scripts/report_skill_ranker_confusion.ts +442 -0
- package/src/scripts/report_standing_payload_by_host.ts +188 -15
- package/src/scripts/report_verification_record_coverage.ts +306 -0
- package/src/scripts/roadmap_verify_share.ts +213 -0
- package/src/scripts/rule_activation_census.ts +5 -2
- package/src/scripts/rule_trigger_eval.ts +9 -9
- package/src/scripts/schemas/command.schema.json +44 -0
- package/src/scripts/schemas/review-findings.schema.json +7 -2
- package/src/scripts/schemas/rule.schema.json +5 -0
- package/src/scripts/schemas/skill.schema.json +44 -0
- package/src/scripts/self_review_gate.ts +421 -17
- package/src/scripts/semantic_parity_census.ts +314 -0
- package/src/scripts/session_eol_report.ts +54 -1
- package/src/scripts/skill_tools/score_skill_relevance.ts +290 -25
- package/src/scripts/sweep_dead_scan_roots.ts +1 -1
- package/src/scripts/sweep_skill_ranker_signals.ts +129 -0
- package/src/scripts/sync_gitignore.ts +29 -235
- package/src/scripts/trigger_eval_grandfather.json +0 -7
- package/src/scripts/trigger_eval_rotation.ts +122 -27
- package/src/scripts/ui_conformance_probe.ts +156 -4
- package/src/scripts/update_prices.ts +85 -3
- package/src/scripts/write_bundle_digest.mjs +74 -0
- package/src/server/schemas/settings.ts +41 -0
- package/src/shared/skillRanking.ts +117 -11
- package/src/templates/consumer-settings/ONBOARDING.md +1 -0
- package/dist/cli-delegate/chunk-FXYUYU4N.js +0 -4416
- package/dist/cli-delegate/chunk-QJWAUMJW.js +0 -1072
- package/dist/cli-delegate/chunk-YDPILCOL.js +0 -152
- package/dist/ui/assets/index-DH1xc62v.js +0 -29
- package/dist/ui/assets/index-jSfMW8_t.css +0 -1
|
@@ -2,20 +2,17 @@ import { createRequire as __acCreateRequire } from 'node:module'; const require
|
|
|
2
2
|
import {
|
|
3
3
|
ZodFirstPartyTypeKind,
|
|
4
4
|
settingsSchema
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-JQVYKIZA.js";
|
|
6
6
|
import {
|
|
7
7
|
main
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-CQWX336L.js";
|
|
9
9
|
import {
|
|
10
|
+
GLOBAL_DEPLOY_SOURCES,
|
|
10
11
|
RULE_SOURCE_REL
|
|
11
12
|
} from "./chunk-WOKWX5PL.js";
|
|
12
|
-
import {
|
|
13
|
-
classifyOwnership,
|
|
14
|
-
recordedHashesForRoot
|
|
15
|
-
} from "./chunk-YDPILCOL.js";
|
|
16
13
|
import {
|
|
17
14
|
appendTxLog
|
|
18
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-NYX3L2PZ.js";
|
|
19
16
|
import {
|
|
20
17
|
SCOPE_DETECT_AI_DIRS,
|
|
21
18
|
SCOPE_DETECT_MANIFESTS
|
|
@@ -31,8 +28,12 @@ import {
|
|
|
31
28
|
reap_stale,
|
|
32
29
|
reap_tagged_orphans,
|
|
33
30
|
record_deploy,
|
|
31
|
+
recorded_rel_files,
|
|
34
32
|
save_inventory
|
|
35
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-S4YWNRKO.js";
|
|
34
|
+
import {
|
|
35
|
+
write_managed_block
|
|
36
|
+
} from "./chunk-ULQRUR23.js";
|
|
36
37
|
import {
|
|
37
38
|
check_version,
|
|
38
39
|
classify_mismatch,
|
|
@@ -56,19 +57,31 @@ import {
|
|
|
56
57
|
ruleScopeFromSettings
|
|
57
58
|
} from "./chunk-DMSZHXZS.js";
|
|
58
59
|
import {
|
|
60
|
+
HOOK_SIGNATURES,
|
|
61
|
+
deepMerge,
|
|
62
|
+
isManagedEntry,
|
|
63
|
+
isPlainObject,
|
|
64
|
+
jsonEqual,
|
|
65
|
+
mergeHostConfig
|
|
66
|
+
} from "./chunk-DEIV7XP7.js";
|
|
67
|
+
import {
|
|
68
|
+
NO_RECORDED_HASHES,
|
|
59
69
|
ScopeMismatchError,
|
|
70
|
+
classifyOwnership,
|
|
60
71
|
manifest_path,
|
|
72
|
+
readRecordedHashes,
|
|
61
73
|
read_manifest,
|
|
74
|
+
recordedHashesForRoot,
|
|
62
75
|
upsert_tool,
|
|
63
76
|
write_manifest
|
|
64
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-OKJUIAPS.js";
|
|
65
78
|
import {
|
|
66
79
|
require_dist
|
|
67
80
|
} from "./chunk-OY53J6II.js";
|
|
68
81
|
import {
|
|
69
82
|
find_project_root_with_anchor,
|
|
70
83
|
load_agent_settings
|
|
71
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-JY2I2DXV.js";
|
|
72
85
|
import {
|
|
73
86
|
event4u_root,
|
|
74
87
|
legacy_xdg_root,
|
|
@@ -181,6 +194,7 @@ function _is_plain_object(value) {
|
|
|
181
194
|
function collect_pointers(overlay, options = {}) {
|
|
182
195
|
const prefix = options.prefix ?? "";
|
|
183
196
|
const include_arrays = options.include_arrays ?? true;
|
|
197
|
+
const entry_signature = options.entry_signature ?? "";
|
|
184
198
|
const entries = [];
|
|
185
199
|
for (const [key, value] of Object.entries(overlay)) {
|
|
186
200
|
const pointer = `${prefix}/${_escape_segment(String(key))}`;
|
|
@@ -189,14 +203,26 @@ function collect_pointers(overlay, options = {}) {
|
|
|
189
203
|
entries.push({ json_pointer: pointer, value_hash: null });
|
|
190
204
|
} else {
|
|
191
205
|
entries.push(
|
|
192
|
-
...collect_pointers(value, {
|
|
206
|
+
...collect_pointers(value, {
|
|
207
|
+
prefix: pointer,
|
|
208
|
+
include_arrays,
|
|
209
|
+
entry_signature
|
|
210
|
+
})
|
|
193
211
|
);
|
|
194
212
|
}
|
|
195
213
|
} else if (Array.isArray(value)) {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
214
|
+
if (entry_signature !== "" && pointer.startsWith("/hooks/")) {
|
|
215
|
+
entries.push({
|
|
216
|
+
json_pointer: pointer,
|
|
217
|
+
value_hash: null,
|
|
218
|
+
entry_signature
|
|
219
|
+
});
|
|
220
|
+
} else {
|
|
221
|
+
entries.push({
|
|
222
|
+
json_pointer: pointer,
|
|
223
|
+
value_hash: include_arrays ? value_hash(value) : null
|
|
224
|
+
});
|
|
225
|
+
}
|
|
200
226
|
} else {
|
|
201
227
|
entries.push({ json_pointer: pointer, value_hash: null });
|
|
202
228
|
}
|
|
@@ -207,11 +233,14 @@ function collect_pointers(overlay, options = {}) {
|
|
|
207
233
|
return entries;
|
|
208
234
|
}
|
|
209
235
|
function build_merge_entries(file_label, overlay) {
|
|
210
|
-
const pointers = collect_pointers(overlay
|
|
236
|
+
const pointers = collect_pointers(overlay, {
|
|
237
|
+
entry_signature: HOOK_SIGNATURES[file_label] ?? ""
|
|
238
|
+
});
|
|
211
239
|
return pointers.map((entry) => ({
|
|
212
240
|
file: file_label,
|
|
213
241
|
json_pointer: entry.json_pointer,
|
|
214
|
-
value_hash: entry.value_hash
|
|
242
|
+
value_hash: entry.value_hash,
|
|
243
|
+
...entry.entry_signature === void 0 ? {} : { entry_signature: entry.entry_signature }
|
|
215
244
|
}));
|
|
216
245
|
}
|
|
217
246
|
function _split_segments(pointer) {
|
|
@@ -251,7 +280,33 @@ function subtract_pointers(doc, entries) {
|
|
|
251
280
|
continue;
|
|
252
281
|
}
|
|
253
282
|
const [parent, leaf] = nav;
|
|
254
|
-
|
|
283
|
+
const signature = entry.entry_signature ?? "";
|
|
284
|
+
if (signature !== "") {
|
|
285
|
+
const current = parent[leaf];
|
|
286
|
+
if (!Array.isArray(current)) {
|
|
287
|
+
warnings.push({
|
|
288
|
+
pointer,
|
|
289
|
+
reason: "missing",
|
|
290
|
+
expected_hash: null,
|
|
291
|
+
actual_hash: null
|
|
292
|
+
});
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
const kept = current.filter((item) => !isManagedEntry(item, signature));
|
|
296
|
+
if (kept.length === current.length) {
|
|
297
|
+
warnings.push({
|
|
298
|
+
pointer,
|
|
299
|
+
reason: "missing",
|
|
300
|
+
expected_hash: null,
|
|
301
|
+
actual_hash: null
|
|
302
|
+
});
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
if (kept.length > 0) {
|
|
306
|
+
parent[leaf] = kept;
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
} else if (expected !== null) {
|
|
255
310
|
const actual = value_hash(parent[leaf]);
|
|
256
311
|
if (actual !== expected) {
|
|
257
312
|
warnings.push({
|
|
@@ -283,11 +338,89 @@ function subtract_pointers(doc, entries) {
|
|
|
283
338
|
// src/scripts/install.ts
|
|
284
339
|
import { spawn, spawnSync } from "node:child_process";
|
|
285
340
|
import * as crypto5 from "node:crypto";
|
|
286
|
-
import * as
|
|
287
|
-
import * as
|
|
288
|
-
import * as
|
|
341
|
+
import * as fs20 from "node:fs";
|
|
342
|
+
import * as os6 from "node:os";
|
|
343
|
+
import * as path20 from "node:path";
|
|
289
344
|
import process2 from "node:process";
|
|
290
|
-
import { fileURLToPath as
|
|
345
|
+
import { fileURLToPath as fileURLToPath4, pathToFileURL } from "node:url";
|
|
346
|
+
|
|
347
|
+
// src/scripts/_lib/reserved_name_sweep.ts
|
|
348
|
+
import * as fs from "node:fs";
|
|
349
|
+
import * as path from "node:path";
|
|
350
|
+
function sweepReservedNames(commandsDir, currentFiles, isBuiltinName, recordedFiles) {
|
|
351
|
+
const reserved = [];
|
|
352
|
+
const foreign = [];
|
|
353
|
+
let entries = [];
|
|
354
|
+
try {
|
|
355
|
+
entries = fs.readdirSync(commandsDir).filter((f) => f.endsWith(".md"));
|
|
356
|
+
} catch {
|
|
357
|
+
return { reserved, foreign };
|
|
358
|
+
}
|
|
359
|
+
for (const fname of entries.sort()) {
|
|
360
|
+
const slug = fname.slice(0, -".md".length);
|
|
361
|
+
if (!isBuiltinName(slug)) continue;
|
|
362
|
+
const rel = `commands/${fname}`;
|
|
363
|
+
const ours = currentFiles.has(rel) || recordedFiles.has(rel);
|
|
364
|
+
if (!ours) {
|
|
365
|
+
foreign.push(slug);
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
fs.rmSync(path.join(commandsDir, fname), { force: true });
|
|
369
|
+
currentFiles.delete(rel);
|
|
370
|
+
reserved.push(slug);
|
|
371
|
+
}
|
|
372
|
+
return { reserved, foreign };
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// src/scripts/_lib/host_env_write.ts
|
|
376
|
+
var YAML = __toESM(require_dist(), 1);
|
|
377
|
+
import * as fs2 from "node:fs";
|
|
378
|
+
import * as path2 from "node:path";
|
|
379
|
+
var WRITABLE_HOST_ENV = [
|
|
380
|
+
{ variable: "BASH_MAX_OUTPUT_LENGTH", settingsKey: "bash_max_output_length" },
|
|
381
|
+
{ variable: "MAX_MCP_OUTPUT_TOKENS", settingsKey: "max_mcp_output_tokens" }
|
|
382
|
+
];
|
|
383
|
+
var SETTINGS_CANDIDATES = [
|
|
384
|
+
["agents", "settings", ".agent-settings.yml"],
|
|
385
|
+
[".agent-settings.yml"]
|
|
386
|
+
];
|
|
387
|
+
function readSettingsDoc(projectRoot) {
|
|
388
|
+
for (const parts of SETTINGS_CANDIDATES) {
|
|
389
|
+
const p = path2.join(projectRoot, ...parts);
|
|
390
|
+
let text;
|
|
391
|
+
try {
|
|
392
|
+
text = fs2.readFileSync(p, "utf-8");
|
|
393
|
+
} catch {
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
let doc;
|
|
397
|
+
try {
|
|
398
|
+
doc = YAML.parse(text, { version: "1.1" });
|
|
399
|
+
} catch {
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
return doc === null || doc === void 0 || typeof doc !== "object" ? null : doc;
|
|
403
|
+
}
|
|
404
|
+
return null;
|
|
405
|
+
}
|
|
406
|
+
function hostEnvBlock(settings) {
|
|
407
|
+
const root = settings;
|
|
408
|
+
const he = root?.["host_environment"];
|
|
409
|
+
const caps = he?.["request_size_caps"];
|
|
410
|
+
if (caps === void 0) return null;
|
|
411
|
+
const out = {};
|
|
412
|
+
for (const { variable, settingsKey } of WRITABLE_HOST_ENV) {
|
|
413
|
+
const v = caps[settingsKey];
|
|
414
|
+
if (typeof v === "number" && Number.isInteger(v) && v > 0) out[variable] = String(v);
|
|
415
|
+
}
|
|
416
|
+
return Object.keys(out).length === 0 ? null : out;
|
|
417
|
+
}
|
|
418
|
+
function withHostEnv(bridge, projectRoot, announce) {
|
|
419
|
+
const env = hostEnvBlock(readSettingsDoc(projectRoot));
|
|
420
|
+
if (env === null) return bridge;
|
|
421
|
+
announce(`.claude/settings.json: wrote ${Object.keys(env).join(", ")} (request-size caps)`);
|
|
422
|
+
return { ...bridge, env };
|
|
423
|
+
}
|
|
291
424
|
|
|
292
425
|
// src/scripts/_lib/json_python_parity.ts
|
|
293
426
|
function jsonStrNoAscii(s) {
|
|
@@ -497,8 +630,8 @@ function is_claude_builtin_name(slug) {
|
|
|
497
630
|
}
|
|
498
631
|
|
|
499
632
|
// src/scripts/_lib/mcp_bridge.ts
|
|
500
|
-
import * as
|
|
501
|
-
import * as
|
|
633
|
+
import * as fs3 from "node:fs";
|
|
634
|
+
import * as path3 from "node:path";
|
|
502
635
|
var MCP_SERVER_KEY = "agent-config";
|
|
503
636
|
var MCP_PACKAGE_NAME = "@event4u/agent-config";
|
|
504
637
|
function mcpBridgeEntry(packageRoot) {
|
|
@@ -515,7 +648,7 @@ function mcpBridgeEntry(packageRoot) {
|
|
|
515
648
|
}
|
|
516
649
|
function readPackageVersion(packageRoot) {
|
|
517
650
|
try {
|
|
518
|
-
const raw =
|
|
651
|
+
const raw = fs3.readFileSync(path3.join(packageRoot, "package.json"), "utf-8");
|
|
519
652
|
const v = JSON.parse(raw).version;
|
|
520
653
|
return typeof v === "string" && v.trim() !== "" ? v : null;
|
|
521
654
|
} catch {
|
|
@@ -524,7 +657,7 @@ function readPackageVersion(packageRoot) {
|
|
|
524
657
|
}
|
|
525
658
|
function makeEnsureMcpBridge(mergeJsonFile) {
|
|
526
659
|
return (projectRoot, force, packageRoot = projectRoot) => mergeJsonFile(
|
|
527
|
-
|
|
660
|
+
path3.join(projectRoot, ".mcp.json"),
|
|
528
661
|
mcpBridgeEntry(packageRoot),
|
|
529
662
|
force,
|
|
530
663
|
".mcp.json"
|
|
@@ -550,7 +683,7 @@ function makeEnsureMcpRegistrations(mergeJsonFile) {
|
|
|
550
683
|
const merged = {};
|
|
551
684
|
for (const t of targets) {
|
|
552
685
|
merged[t.toolId] = mergeJsonFile(
|
|
553
|
-
|
|
686
|
+
path3.join(projectRoot, ...t.relPath.split("/")),
|
|
554
687
|
mcpBridgeEntry(packageRoot),
|
|
555
688
|
force,
|
|
556
689
|
t.relPath
|
|
@@ -581,10 +714,10 @@ function projectionModeOf(raw) {
|
|
|
581
714
|
return raw === "scoped" ? "scoped" : raw === "tiered" ? "tiered" : "legacy-all";
|
|
582
715
|
}
|
|
583
716
|
function resolveTierB(packageRoot) {
|
|
584
|
-
const p =
|
|
585
|
-
if (!
|
|
717
|
+
const p = path3.join(packageRoot, "agents", "runtime", "state", "skill-tiers.json");
|
|
718
|
+
if (!fs3.existsSync(p)) return null;
|
|
586
719
|
try {
|
|
587
|
-
const parsed = JSON.parse(
|
|
720
|
+
const parsed = JSON.parse(fs3.readFileSync(p, "utf-8"));
|
|
588
721
|
if (!Array.isArray(parsed.tier_b)) return null;
|
|
589
722
|
return new Set(parsed.tier_b.filter((n) => typeof n === "string"));
|
|
590
723
|
} catch {
|
|
@@ -592,7 +725,7 @@ function resolveTierB(packageRoot) {
|
|
|
592
725
|
}
|
|
593
726
|
}
|
|
594
727
|
function tierBPrunePredicate(tierB) {
|
|
595
|
-
return (mdPath) => tierB.has(
|
|
728
|
+
return (mdPath) => tierB.has(path3.basename(path3.dirname(mdPath)));
|
|
596
729
|
}
|
|
597
730
|
function tierBAdvisory(packageRoot) {
|
|
598
731
|
const tierB = resolveTierB(packageRoot);
|
|
@@ -621,35 +754,35 @@ function applyTieredPrune(deployResults, packageRoot, pruneBy) {
|
|
|
621
754
|
|
|
622
755
|
// src/install/conflictTracker.ts
|
|
623
756
|
import * as crypto2 from "node:crypto";
|
|
624
|
-
import * as
|
|
625
|
-
import * as
|
|
757
|
+
import * as fs5 from "node:fs";
|
|
758
|
+
import * as path5 from "node:path";
|
|
626
759
|
|
|
627
760
|
// src/install/fsPrimitives.ts
|
|
628
761
|
import * as crypto from "node:crypto";
|
|
629
|
-
import * as
|
|
630
|
-
import * as
|
|
762
|
+
import * as fs4 from "node:fs";
|
|
763
|
+
import * as path4 from "node:path";
|
|
631
764
|
function resolvePath(p) {
|
|
632
765
|
try {
|
|
633
|
-
return
|
|
766
|
+
return fs4.realpathSync(path4.resolve(p));
|
|
634
767
|
} catch {
|
|
635
|
-
return
|
|
768
|
+
return path4.resolve(p);
|
|
636
769
|
}
|
|
637
770
|
}
|
|
638
771
|
function pathExists(p) {
|
|
639
772
|
try {
|
|
640
|
-
|
|
773
|
+
fs4.statSync(p);
|
|
641
774
|
return true;
|
|
642
775
|
} catch {
|
|
643
776
|
return false;
|
|
644
777
|
}
|
|
645
778
|
}
|
|
646
779
|
function mkdirp(p) {
|
|
647
|
-
|
|
780
|
+
fs4.mkdirSync(p, { recursive: true });
|
|
648
781
|
}
|
|
649
782
|
function sha256OfFile(p) {
|
|
650
783
|
let data;
|
|
651
784
|
try {
|
|
652
|
-
data =
|
|
785
|
+
data = fs4.readFileSync(p);
|
|
653
786
|
} catch {
|
|
654
787
|
return null;
|
|
655
788
|
}
|
|
@@ -690,20 +823,20 @@ function createConflictTracker(host) {
|
|
|
690
823
|
function recordedHashFor(target) {
|
|
691
824
|
if (conflictState.root === null) return void 0;
|
|
692
825
|
conflictState.recorded ??= recordedHashesForRoot(conflictState.root);
|
|
693
|
-
const plain =
|
|
826
|
+
const plain = path5.resolve(target);
|
|
694
827
|
if (conflictState.recorded.has(plain)) return conflictState.recorded.get(plain);
|
|
695
828
|
const real = resolvePath(target);
|
|
696
829
|
return real === plain ? void 0 : conflictState.recorded.get(real);
|
|
697
830
|
}
|
|
698
831
|
function stageInto(target, sidecar, produce) {
|
|
699
|
-
mkdirp(
|
|
700
|
-
const tmp =
|
|
701
|
-
|
|
702
|
-
`.${
|
|
832
|
+
mkdirp(path5.dirname(sidecar));
|
|
833
|
+
const tmp = path5.join(
|
|
834
|
+
path5.dirname(sidecar),
|
|
835
|
+
`.${path5.basename(sidecar)}.${process.pid}.${crypto2.randomBytes(6).toString("hex")}${path5.extname(target)}`
|
|
703
836
|
);
|
|
704
837
|
const discard = () => {
|
|
705
838
|
try {
|
|
706
|
-
|
|
839
|
+
fs5.unlinkSync(tmp);
|
|
707
840
|
} catch {
|
|
708
841
|
}
|
|
709
842
|
};
|
|
@@ -730,7 +863,7 @@ function createConflictTracker(host) {
|
|
|
730
863
|
}
|
|
731
864
|
}
|
|
732
865
|
try {
|
|
733
|
-
|
|
866
|
+
fs5.renameSync(tmp, sidecar);
|
|
734
867
|
} catch (exc) {
|
|
735
868
|
discard();
|
|
736
869
|
host.fail(
|
|
@@ -779,7 +912,7 @@ function createConflictTracker(host) {
|
|
|
779
912
|
preserve(target, source, packageRoot) {
|
|
780
913
|
const sidecar = sidecarPathFor(target);
|
|
781
914
|
stageInto(target, sidecar, (tmp) => {
|
|
782
|
-
|
|
915
|
+
fs5.copyFileSync(source, tmp);
|
|
783
916
|
host.tagDeployed(tmp, source, packageRoot);
|
|
784
917
|
});
|
|
785
918
|
record(target, sidecar);
|
|
@@ -795,7 +928,7 @@ function createConflictTracker(host) {
|
|
|
795
928
|
*/
|
|
796
929
|
preserveContent(target, content) {
|
|
797
930
|
const sidecar = sidecarPathFor(target);
|
|
798
|
-
stageInto(target, sidecar, (tmp) =>
|
|
931
|
+
stageInto(target, sidecar, (tmp) => fs5.writeFileSync(tmp, content, "utf-8"));
|
|
799
932
|
record(target, sidecar);
|
|
800
933
|
},
|
|
801
934
|
/**
|
|
@@ -814,10 +947,10 @@ function createConflictTracker(host) {
|
|
|
814
947
|
}
|
|
815
948
|
|
|
816
949
|
// src/install/manifestFiles.ts
|
|
817
|
-
var
|
|
818
|
-
import { existsSync as existsSync2, readFileSync as
|
|
950
|
+
var YAML2 = __toESM(require_dist(), 1);
|
|
951
|
+
import { existsSync as existsSync2, readFileSync as readFileSync4 } from "node:fs";
|
|
819
952
|
import { homedir } from "node:os";
|
|
820
|
-
import { isAbsolute, join as
|
|
953
|
+
import { isAbsolute, join as join5, resolve as resolve3 } from "node:path";
|
|
821
954
|
function fileEntry(p, kind, hashContent) {
|
|
822
955
|
return { path: p, kind, sha256: hashContent ? sha256OfFile(p) : null };
|
|
823
956
|
}
|
|
@@ -840,7 +973,7 @@ function filesByToolFromBridges(tools, projectRoot, scope, bridgeMarker) {
|
|
|
840
973
|
for (const toolId of [...tools].sort()) {
|
|
841
974
|
const marker = bridgeMarker(toolId, scope);
|
|
842
975
|
if (!marker) continue;
|
|
843
|
-
const markerPath = isAbsolute(marker) ? marker :
|
|
976
|
+
const markerPath = isAbsolute(marker) ? marker : join5(projectRoot, marker);
|
|
844
977
|
out[toolId] = [fileEntry(markerPath, "bridge", false)];
|
|
845
978
|
}
|
|
846
979
|
return out;
|
|
@@ -848,7 +981,7 @@ function filesByToolFromBridges(tools, projectRoot, scope, bridgeMarker) {
|
|
|
848
981
|
function expanduser(p) {
|
|
849
982
|
if (p === "~") return homedir();
|
|
850
983
|
if (p.startsWith("~/") || process.platform === "win32" && p.startsWith("~\\")) {
|
|
851
|
-
return
|
|
984
|
+
return join5(homedir(), p.slice(2));
|
|
852
985
|
}
|
|
853
986
|
return p;
|
|
854
987
|
}
|
|
@@ -861,7 +994,7 @@ function readRecordedByTool(manifestPath, projectRoot) {
|
|
|
861
994
|
if (!existsSync2(manifestPath)) return out;
|
|
862
995
|
let doc;
|
|
863
996
|
try {
|
|
864
|
-
doc =
|
|
997
|
+
doc = YAML2.parse(readFileSync4(manifestPath, "utf8"));
|
|
865
998
|
} catch {
|
|
866
999
|
return out;
|
|
867
1000
|
}
|
|
@@ -940,8 +1073,9 @@ function preservedIndex(preservedTargets, staged) {
|
|
|
940
1073
|
}
|
|
941
1074
|
|
|
942
1075
|
// src/scripts/_lib/rule_layer_overlap.ts
|
|
943
|
-
import * as
|
|
944
|
-
import * as
|
|
1076
|
+
import * as fs6 from "node:fs";
|
|
1077
|
+
import * as os from "node:os";
|
|
1078
|
+
import * as path6 from "node:path";
|
|
945
1079
|
var INSTALLER_PROVENANCE_KEYS = ["package", "source_path"];
|
|
946
1080
|
function stripProvenance(text) {
|
|
947
1081
|
const lines = text.split("\n");
|
|
@@ -992,17 +1126,23 @@ function compareLayers(global_layer, project_layer) {
|
|
|
992
1126
|
redundant_chars
|
|
993
1127
|
};
|
|
994
1128
|
}
|
|
1129
|
+
function hostRuleLayerDirs(projectRoot) {
|
|
1130
|
+
return [
|
|
1131
|
+
path6.join(os.homedir(), ".claude", "rules"),
|
|
1132
|
+
path6.join(projectRoot, ".claude", "rules")
|
|
1133
|
+
];
|
|
1134
|
+
}
|
|
995
1135
|
function readRuleLayer(dir) {
|
|
996
1136
|
let names;
|
|
997
1137
|
try {
|
|
998
|
-
names =
|
|
1138
|
+
names = fs6.readdirSync(dir);
|
|
999
1139
|
} catch {
|
|
1000
1140
|
return null;
|
|
1001
1141
|
}
|
|
1002
1142
|
const files = /* @__PURE__ */ new Map();
|
|
1003
1143
|
for (const name of names.filter((n) => n.endsWith(".md")).sort()) {
|
|
1004
1144
|
try {
|
|
1005
|
-
files.set(name,
|
|
1145
|
+
files.set(name, fs6.readFileSync(path6.join(dir, name), "utf-8"));
|
|
1006
1146
|
} catch {
|
|
1007
1147
|
continue;
|
|
1008
1148
|
}
|
|
@@ -1010,7 +1150,7 @@ function readRuleLayer(dir) {
|
|
|
1010
1150
|
return { dir, files };
|
|
1011
1151
|
}
|
|
1012
1152
|
function claudeMdExcludesGlob(dir) {
|
|
1013
|
-
return `${
|
|
1153
|
+
return `${path6.resolve(dir).replace(/\/+$/, "")}/**`;
|
|
1014
1154
|
}
|
|
1015
1155
|
function mergeClaudeMdExcludes(existing, entry) {
|
|
1016
1156
|
if (!Array.isArray(existing)) return [entry];
|
|
@@ -1041,25 +1181,25 @@ function decideLayerAction(report, choice, global_dir, project_dir) {
|
|
|
1041
1181
|
// src/scripts/_lib/install_drift.ts
|
|
1042
1182
|
var import_yaml = __toESM(require_dist(), 1);
|
|
1043
1183
|
import * as crypto3 from "node:crypto";
|
|
1044
|
-
import * as
|
|
1045
|
-
import * as
|
|
1046
|
-
import * as
|
|
1184
|
+
import * as fs7 from "node:fs";
|
|
1185
|
+
import * as os2 from "node:os";
|
|
1186
|
+
import * as path7 from "node:path";
|
|
1047
1187
|
function expanduser2(p) {
|
|
1048
1188
|
if (p === "~") {
|
|
1049
|
-
return
|
|
1189
|
+
return os2.homedir();
|
|
1050
1190
|
}
|
|
1051
1191
|
if (p.startsWith("~/") || process.platform === "win32" && p.startsWith("~\\")) {
|
|
1052
|
-
return
|
|
1192
|
+
return path7.join(os2.homedir(), p.slice(2));
|
|
1053
1193
|
}
|
|
1054
1194
|
return p;
|
|
1055
1195
|
}
|
|
1056
1196
|
function resolve_entry_path(project_root, raw) {
|
|
1057
1197
|
const p = expanduser2(raw);
|
|
1058
|
-
return
|
|
1198
|
+
return path7.isAbsolute(p) ? p : path7.join(project_root, p);
|
|
1059
1199
|
}
|
|
1060
1200
|
function sha256_of_file(p) {
|
|
1061
1201
|
try {
|
|
1062
|
-
return crypto3.createHash("sha256").update(
|
|
1202
|
+
return crypto3.createHash("sha256").update(fs7.readFileSync(p)).digest("hex");
|
|
1063
1203
|
} catch {
|
|
1064
1204
|
return null;
|
|
1065
1205
|
}
|
|
@@ -1068,7 +1208,7 @@ function collect_drift(project_root, env) {
|
|
|
1068
1208
|
const target = manifest_path(project_root, env);
|
|
1069
1209
|
let text;
|
|
1070
1210
|
try {
|
|
1071
|
-
text =
|
|
1211
|
+
text = fs7.readFileSync(target, "utf-8");
|
|
1072
1212
|
} catch {
|
|
1073
1213
|
return null;
|
|
1074
1214
|
}
|
|
@@ -1113,7 +1253,7 @@ function collect_drift(project_root, env) {
|
|
|
1113
1253
|
continue;
|
|
1114
1254
|
}
|
|
1115
1255
|
const resolved = resolve_entry_path(project_root, raw_path);
|
|
1116
|
-
if (!
|
|
1256
|
+
if (!fs7.existsSync(resolved)) {
|
|
1117
1257
|
out.push({
|
|
1118
1258
|
tool_id,
|
|
1119
1259
|
path: resolved,
|
|
@@ -1166,15 +1306,15 @@ function format_drift_report(entries) {
|
|
|
1166
1306
|
}
|
|
1167
1307
|
|
|
1168
1308
|
// src/scripts/_lib/skill_catalogue.ts
|
|
1169
|
-
import * as
|
|
1170
|
-
import * as
|
|
1309
|
+
import * as fs8 from "node:fs";
|
|
1310
|
+
import * as path8 from "node:path";
|
|
1171
1311
|
var PROJECT_CATALOGUE_ROOTS = ["src/skills", ".claude/skills"];
|
|
1172
1312
|
var HOST_CATALOGUE_ROOT = ".claude/skills";
|
|
1173
1313
|
var DEFAULT_CATALOGUE_ROOTS = [
|
|
1174
1314
|
...PROJECT_CATALOGUE_ROOTS,
|
|
1175
1315
|
`~/${HOST_CATALOGUE_ROOT}`
|
|
1176
1316
|
];
|
|
1177
|
-
var OBSERVATION_LOG =
|
|
1317
|
+
var OBSERVATION_LOG = path8.join(
|
|
1178
1318
|
"agents",
|
|
1179
1319
|
"evidence",
|
|
1180
1320
|
"metrics",
|
|
@@ -1218,9 +1358,9 @@ function descriptionOf(frontmatter) {
|
|
|
1218
1358
|
return "";
|
|
1219
1359
|
}
|
|
1220
1360
|
function readProjectedCatalogue(root) {
|
|
1221
|
-
const names =
|
|
1361
|
+
const names = fs8.readdirSync(root).filter((n) => fs8.existsSync(path8.join(root, n, "SKILL.md"))).sort();
|
|
1222
1362
|
return names.map((name, index) => {
|
|
1223
|
-
const content =
|
|
1363
|
+
const content = fs8.readFileSync(path8.join(root, name, "SKILL.md"), "utf-8");
|
|
1224
1364
|
const frontmatter = frontmatterOf(content);
|
|
1225
1365
|
const description = descriptionOf(frontmatter);
|
|
1226
1366
|
return {
|
|
@@ -1237,12 +1377,12 @@ function truncationModeOf(record) {
|
|
|
1237
1377
|
return record.truncation_mode ?? "per-entry";
|
|
1238
1378
|
}
|
|
1239
1379
|
function markdownFilesUnder(root) {
|
|
1240
|
-
if (!
|
|
1380
|
+
if (!fs8.existsSync(root)) return [];
|
|
1241
1381
|
const out = [];
|
|
1242
1382
|
const walk = (dir) => {
|
|
1243
|
-
for (const entry of
|
|
1244
|
-
const full =
|
|
1245
|
-
if (
|
|
1383
|
+
for (const entry of fs8.readdirSync(dir, { withFileTypes: true })) {
|
|
1384
|
+
const full = path8.join(dir, entry.name);
|
|
1385
|
+
if (fs8.statSync(full).isDirectory()) walk(full);
|
|
1246
1386
|
else if (entry.name.endsWith(".md")) out.push(full);
|
|
1247
1387
|
}
|
|
1248
1388
|
};
|
|
@@ -1250,9 +1390,9 @@ function markdownFilesUnder(root) {
|
|
|
1250
1390
|
return out;
|
|
1251
1391
|
}
|
|
1252
1392
|
function measureCatalogueVolume(host, root) {
|
|
1253
|
-
const skillsRoot =
|
|
1254
|
-
const skills =
|
|
1255
|
-
const commandEntries = markdownFilesUnder(
|
|
1393
|
+
const skillsRoot = path8.join(root, "skills");
|
|
1394
|
+
const skills = fs8.existsSync(skillsRoot) ? readProjectedCatalogue(skillsRoot) : [];
|
|
1395
|
+
const commandEntries = markdownFilesUnder(path8.join(root, "commands")).length;
|
|
1256
1396
|
return {
|
|
1257
1397
|
host,
|
|
1258
1398
|
root,
|
|
@@ -1330,9 +1470,9 @@ function migrationPromptLines(host, eligibility, settingsPath) {
|
|
|
1330
1470
|
];
|
|
1331
1471
|
}
|
|
1332
1472
|
function readObservationLog(logPath) {
|
|
1333
|
-
if (!
|
|
1473
|
+
if (!fs8.existsSync(logPath)) return [];
|
|
1334
1474
|
const out = [];
|
|
1335
|
-
for (const line of
|
|
1475
|
+
for (const line of fs8.readFileSync(logPath, "utf-8").split("\n")) {
|
|
1336
1476
|
const trimmed = line.trim();
|
|
1337
1477
|
if (trimmed.length === 0) continue;
|
|
1338
1478
|
try {
|
|
@@ -1373,8 +1513,8 @@ function isInteractiveSession(probe) {
|
|
|
1373
1513
|
|
|
1374
1514
|
// src/scripts/_lib/claude_desktop_bundler.ts
|
|
1375
1515
|
import * as crypto4 from "node:crypto";
|
|
1376
|
-
import * as
|
|
1377
|
-
import * as
|
|
1516
|
+
import * as fs9 from "node:fs";
|
|
1517
|
+
import * as path9 from "node:path";
|
|
1378
1518
|
|
|
1379
1519
|
// src/scripts/_lib/zip_min.ts
|
|
1380
1520
|
import * as zlib from "node:zlib";
|
|
@@ -1481,7 +1621,7 @@ function _is_excluded(rel_parts) {
|
|
|
1481
1621
|
}
|
|
1482
1622
|
function _is_dir(p) {
|
|
1483
1623
|
try {
|
|
1484
|
-
return
|
|
1624
|
+
return fs9.statSync(p).isDirectory();
|
|
1485
1625
|
} catch {
|
|
1486
1626
|
return false;
|
|
1487
1627
|
}
|
|
@@ -1493,12 +1633,12 @@ function _compare_rel_parts(a, b) {
|
|
|
1493
1633
|
}
|
|
1494
1634
|
function _walk_skill_files(skill_dir) {
|
|
1495
1635
|
const out = [];
|
|
1496
|
-
const resolved =
|
|
1636
|
+
const resolved = fs9.realpathSync(skill_dir);
|
|
1497
1637
|
const walk = (root, relRoot) => {
|
|
1498
1638
|
const dirNames = [];
|
|
1499
1639
|
const fileNames = [];
|
|
1500
|
-
for (const dirent of
|
|
1501
|
-
const full =
|
|
1640
|
+
for (const dirent of fs9.readdirSync(root, { withFileTypes: true })) {
|
|
1641
|
+
const full = path9.join(root, dirent.name);
|
|
1502
1642
|
const isDir2 = dirent.isDirectory() || dirent.isSymbolicLink() && _is_dir(full);
|
|
1503
1643
|
if (isDir2) {
|
|
1504
1644
|
dirNames.push(dirent.name);
|
|
@@ -1511,13 +1651,13 @@ function _walk_skill_files(skill_dir) {
|
|
|
1511
1651
|
if (_is_excluded(rel_parts)) {
|
|
1512
1652
|
continue;
|
|
1513
1653
|
}
|
|
1514
|
-
out.push([
|
|
1654
|
+
out.push([path9.join(root, fname), rel_parts]);
|
|
1515
1655
|
}
|
|
1516
1656
|
for (const dname of dirNames) {
|
|
1517
1657
|
if (_is_excluded([dname])) {
|
|
1518
1658
|
continue;
|
|
1519
1659
|
}
|
|
1520
|
-
walk(
|
|
1660
|
+
walk(path9.join(root, dname), [...relRoot, dname]);
|
|
1521
1661
|
}
|
|
1522
1662
|
};
|
|
1523
1663
|
walk(resolved, []);
|
|
@@ -1530,53 +1670,53 @@ function _manifest_digest(files) {
|
|
|
1530
1670
|
const rel = rel_parts.join("/");
|
|
1531
1671
|
h.update(Buffer.from(rel, "utf-8"));
|
|
1532
1672
|
h.update(Buffer.from([0]));
|
|
1533
|
-
h.update(crypto4.createHash("sha256").update(
|
|
1673
|
+
h.update(crypto4.createHash("sha256").update(fs9.readFileSync(abs_path)).digest());
|
|
1534
1674
|
h.update(Buffer.from([0]));
|
|
1535
1675
|
}
|
|
1536
1676
|
return h.digest("hex");
|
|
1537
1677
|
}
|
|
1538
1678
|
function _atomic_write_zip(zip_path, files) {
|
|
1539
|
-
|
|
1540
|
-
const stem =
|
|
1541
|
-
const tmp_path =
|
|
1542
|
-
|
|
1679
|
+
fs9.mkdirSync(path9.dirname(zip_path), { recursive: true });
|
|
1680
|
+
const stem = path9.basename(zip_path, path9.extname(zip_path));
|
|
1681
|
+
const tmp_path = path9.join(
|
|
1682
|
+
path9.dirname(zip_path),
|
|
1543
1683
|
`.${stem}.${crypto4.randomBytes(6).toString("hex")}.zip.tmp`
|
|
1544
1684
|
);
|
|
1545
1685
|
try {
|
|
1546
1686
|
const entries = files.map(([abs_path, rel_parts]) => ({
|
|
1547
1687
|
name: rel_parts.join("/"),
|
|
1548
|
-
data:
|
|
1688
|
+
data: fs9.readFileSync(abs_path)
|
|
1549
1689
|
}));
|
|
1550
|
-
|
|
1551
|
-
|
|
1690
|
+
fs9.writeFileSync(tmp_path, zip_write_sync(entries));
|
|
1691
|
+
fs9.renameSync(tmp_path, zip_path);
|
|
1552
1692
|
} finally {
|
|
1553
|
-
if (
|
|
1554
|
-
|
|
1693
|
+
if (fs9.existsSync(tmp_path)) {
|
|
1694
|
+
fs9.unlinkSync(tmp_path);
|
|
1555
1695
|
}
|
|
1556
1696
|
}
|
|
1557
1697
|
}
|
|
1558
1698
|
function _write_if_changed(dest_dir, slug, files, force, written) {
|
|
1559
1699
|
const digest = _manifest_digest(files);
|
|
1560
|
-
const zip_path =
|
|
1561
|
-
const digest_path =
|
|
1562
|
-
const recorded =
|
|
1563
|
-
if (!force && recorded === digest &&
|
|
1700
|
+
const zip_path = path9.join(dest_dir, `${slug}.zip`);
|
|
1701
|
+
const digest_path = path9.join(dest_dir, `${slug}.sha256`);
|
|
1702
|
+
const recorded = fs9.existsSync(digest_path) ? fs9.readFileSync(digest_path, "utf-8").trim() : "";
|
|
1703
|
+
if (!force && recorded === digest && fs9.existsSync(zip_path)) {
|
|
1564
1704
|
return;
|
|
1565
1705
|
}
|
|
1566
1706
|
_atomic_write_zip(zip_path, files);
|
|
1567
|
-
|
|
1707
|
+
fs9.writeFileSync(digest_path, digest + "\n", "utf-8");
|
|
1568
1708
|
written.push(zip_path);
|
|
1569
1709
|
}
|
|
1570
1710
|
function build_skill_bundles(package_root, dest_dir, force = false, curation = null) {
|
|
1571
|
-
const skills_root =
|
|
1711
|
+
const skills_root = path9.join(package_root, "dist/agent-src", "skills");
|
|
1572
1712
|
if (!_is_dir(skills_root)) {
|
|
1573
1713
|
return [];
|
|
1574
1714
|
}
|
|
1575
|
-
|
|
1715
|
+
fs9.mkdirSync(dest_dir, { recursive: true });
|
|
1576
1716
|
const written = [];
|
|
1577
|
-
for (const name of
|
|
1578
|
-
const entry =
|
|
1579
|
-
const isSymlink2 =
|
|
1717
|
+
for (const name of fs9.readdirSync(skills_root).sort()) {
|
|
1718
|
+
const entry = path9.join(skills_root, name);
|
|
1719
|
+
const isSymlink2 = fs9.lstatSync(entry).isSymbolicLink();
|
|
1580
1720
|
if (!(_is_dir(entry) || isSymlink2)) {
|
|
1581
1721
|
continue;
|
|
1582
1722
|
}
|
|
@@ -1584,8 +1724,8 @@ function build_skill_bundles(package_root, dest_dir, force = false, curation = n
|
|
|
1584
1724
|
if (curation !== null && !curation.includes(skill_name)) {
|
|
1585
1725
|
continue;
|
|
1586
1726
|
}
|
|
1587
|
-
const skill_md =
|
|
1588
|
-
if (!
|
|
1727
|
+
const skill_md = path9.join(entry, "SKILL.md");
|
|
1728
|
+
if (!fs9.existsSync(skill_md)) {
|
|
1589
1729
|
continue;
|
|
1590
1730
|
}
|
|
1591
1731
|
const files = _walk_skill_files(entry);
|
|
@@ -1597,15 +1737,15 @@ function build_skill_bundles(package_root, dest_dir, force = false, curation = n
|
|
|
1597
1737
|
return written;
|
|
1598
1738
|
}
|
|
1599
1739
|
function _command_slug(source_file, commands_root) {
|
|
1600
|
-
const rel =
|
|
1601
|
-
const noExt = rel.slice(0, rel.length -
|
|
1602
|
-
return noExt.split(
|
|
1740
|
+
const rel = path9.relative(commands_root, source_file);
|
|
1741
|
+
const noExt = rel.slice(0, rel.length - path9.extname(rel).length);
|
|
1742
|
+
return noExt.split(path9.sep).join("-");
|
|
1603
1743
|
}
|
|
1604
1744
|
function _iter_command_files(commands_root) {
|
|
1605
1745
|
const found = [];
|
|
1606
1746
|
const walk = (dir) => {
|
|
1607
|
-
for (const dirent of
|
|
1608
|
-
const full =
|
|
1747
|
+
for (const dirent of fs9.readdirSync(dir, { withFileTypes: true })) {
|
|
1748
|
+
const full = path9.join(dir, dirent.name);
|
|
1609
1749
|
if (dirent.isDirectory() || dirent.isSymbolicLink() && _is_dir(full)) {
|
|
1610
1750
|
walk(full);
|
|
1611
1751
|
} else if (dirent.name.endsWith(".md")) {
|
|
@@ -1615,21 +1755,21 @@ function _iter_command_files(commands_root) {
|
|
|
1615
1755
|
};
|
|
1616
1756
|
walk(commands_root);
|
|
1617
1757
|
found.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
1618
|
-
return found.filter((source_file) =>
|
|
1758
|
+
return found.filter((source_file) => path9.basename(source_file) !== "AGENTS.md");
|
|
1619
1759
|
}
|
|
1620
1760
|
function build_command_bundles(package_root, dest_dir, force = false, curation = null) {
|
|
1621
|
-
const commands_root =
|
|
1761
|
+
const commands_root = path9.join(package_root, "dist/agent-src", "commands");
|
|
1622
1762
|
if (!_is_dir(commands_root)) {
|
|
1623
1763
|
return [];
|
|
1624
1764
|
}
|
|
1625
|
-
const skills_root =
|
|
1765
|
+
const skills_root = path9.join(package_root, "dist/agent-src", "skills");
|
|
1626
1766
|
let skill_names = /* @__PURE__ */ new Set();
|
|
1627
1767
|
if (_is_dir(skills_root)) {
|
|
1628
1768
|
skill_names = new Set(
|
|
1629
|
-
|
|
1769
|
+
fs9.readdirSync(skills_root).filter((name) => _is_dir(path9.join(skills_root, name)))
|
|
1630
1770
|
);
|
|
1631
1771
|
}
|
|
1632
|
-
|
|
1772
|
+
fs9.mkdirSync(dest_dir, { recursive: true });
|
|
1633
1773
|
const written = [];
|
|
1634
1774
|
for (const source_file of _iter_command_files(commands_root)) {
|
|
1635
1775
|
const slug = _command_slug(source_file, commands_root);
|
|
@@ -1639,7 +1779,7 @@ function build_command_bundles(package_root, dest_dir, force = false, curation =
|
|
|
1639
1779
|
if (curation !== null && !curation.includes(slug)) {
|
|
1640
1780
|
continue;
|
|
1641
1781
|
}
|
|
1642
|
-
const files = [[
|
|
1782
|
+
const files = [[fs9.realpathSync(source_file), ["SKILL.md"]]];
|
|
1643
1783
|
_write_if_changed(dest_dir, slug, files, force, written);
|
|
1644
1784
|
}
|
|
1645
1785
|
return written;
|
|
@@ -1647,15 +1787,25 @@ function build_command_bundles(package_root, dest_dir, force = false, curation =
|
|
|
1647
1787
|
|
|
1648
1788
|
// src/scripts/hooks/host_lowering.ts
|
|
1649
1789
|
var import_yaml2 = __toESM(require_dist(), 1);
|
|
1650
|
-
import * as
|
|
1651
|
-
import * as
|
|
1790
|
+
import * as fs10 from "node:fs";
|
|
1791
|
+
import * as path10 from "node:path";
|
|
1652
1792
|
import { fileURLToPath } from "node:url";
|
|
1793
|
+
|
|
1794
|
+
// src/scripts/hooks/table_fingerprint.ts
|
|
1795
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
1796
|
+
function tableFingerprint(text) {
|
|
1797
|
+
const digest = createHash5("sha256").update(text, "utf-8").digest("hex");
|
|
1798
|
+
return `${digest}:${String(text.length)}`;
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
// src/scripts/hooks/host_lowering.ts
|
|
1653
1802
|
var _IN_BUNDLE = true;
|
|
1654
|
-
var _REPO_ROOT =
|
|
1655
|
-
|
|
1803
|
+
var _REPO_ROOT = path10.resolve(
|
|
1804
|
+
path10.dirname(fileURLToPath(import.meta.url)),
|
|
1656
1805
|
..._IN_BUNDLE ? ["..", ".."] : ["..", "..", ".."]
|
|
1657
1806
|
);
|
|
1658
|
-
var HOST_LOWERING_PATH =
|
|
1807
|
+
var HOST_LOWERING_PATH = path10.join(_REPO_ROOT, "src", "scripts", "hooks", "host_lowering.yaml");
|
|
1808
|
+
var HOST_LOWERING_JSON_PATH = path10.join(_REPO_ROOT, "src", "scripts", "hooks", "host_lowering.json");
|
|
1659
1809
|
var DEFAULT_SURFACE = "any";
|
|
1660
1810
|
function _asString(v) {
|
|
1661
1811
|
if (v === null || v === void 0) return null;
|
|
@@ -1663,7 +1813,9 @@ function _asString(v) {
|
|
|
1663
1813
|
return String(v);
|
|
1664
1814
|
}
|
|
1665
1815
|
function _parse(text) {
|
|
1666
|
-
|
|
1816
|
+
return _structure((0, import_yaml2.parse)(text));
|
|
1817
|
+
}
|
|
1818
|
+
function _structure(raw) {
|
|
1667
1819
|
const hostsRaw = raw?.["hosts"];
|
|
1668
1820
|
if (typeof hostsRaw !== "object" || hostsRaw === null) {
|
|
1669
1821
|
throw new Error("host_lowering.yaml: missing `hosts:` map");
|
|
@@ -1687,6 +1839,7 @@ function _parse(text) {
|
|
|
1687
1839
|
verified = {
|
|
1688
1840
|
docs_at: _asString(verifiedRaw["docs_at"]),
|
|
1689
1841
|
docs_url: _asString(verifiedRaw["docs_url"]),
|
|
1842
|
+
docs_digest: _asString(verifiedRaw["docs_digest"]),
|
|
1690
1843
|
probe_at: _asString(verifiedRaw["probe_at"]),
|
|
1691
1844
|
host_version: _asString(verifiedRaw["host_version"]),
|
|
1692
1845
|
expires
|
|
@@ -1700,7 +1853,9 @@ function _parse(text) {
|
|
|
1700
1853
|
const be = rv["block_exit"];
|
|
1701
1854
|
const row = {
|
|
1702
1855
|
native,
|
|
1703
|
-
block_exit: typeof be === "number" ? be : null
|
|
1856
|
+
block_exit: typeof be === "number" ? be : null,
|
|
1857
|
+
answered_at: _asString(rv["answered_at"]),
|
|
1858
|
+
docs_url: _asString(rv["docs_url"])
|
|
1704
1859
|
};
|
|
1705
1860
|
if (typeof rv["matcher"] === "string") row.matcher = rv["matcher"];
|
|
1706
1861
|
slots.set(slot, row);
|
|
@@ -1721,9 +1876,47 @@ function _parse(text) {
|
|
|
1721
1876
|
}
|
|
1722
1877
|
var _cache = null;
|
|
1723
1878
|
function loadHostLowering() {
|
|
1724
|
-
if (_cache
|
|
1879
|
+
if (_cache !== null) return _cache;
|
|
1880
|
+
const text = fs10.readFileSync(HOST_LOWERING_PATH, "utf-8");
|
|
1881
|
+
let compiled;
|
|
1882
|
+
try {
|
|
1883
|
+
compiled = fs10.readFileSync(HOST_LOWERING_JSON_PATH, "utf-8");
|
|
1884
|
+
} catch {
|
|
1885
|
+
compiled = null;
|
|
1886
|
+
}
|
|
1887
|
+
_cache = resolveTable(text, compiled);
|
|
1725
1888
|
return _cache;
|
|
1726
1889
|
}
|
|
1890
|
+
function resolveTable(yamlText, compiledText) {
|
|
1891
|
+
if (compiledText !== null) {
|
|
1892
|
+
try {
|
|
1893
|
+
const raw = JSON.parse(compiledText);
|
|
1894
|
+
const table = raw["table"];
|
|
1895
|
+
if (raw["fingerprint"] === tableFingerprint(yamlText) && typeof table === "object" && table !== null && // road-to-blocking-severities 2.3 — the BODY, not only its
|
|
1896
|
+
// label. `fingerprint` above says the file was compiled from
|
|
1897
|
+
// the YAML as it stands; it says nothing about whether the
|
|
1898
|
+
// body underneath was edited afterwards, and an edited body
|
|
1899
|
+
// with an untouched label was served. `body_fingerprint` is
|
|
1900
|
+
// the fingerprint of the exact bytes the compiler emitted, so
|
|
1901
|
+
// re-stringifying what we just parsed recovers them.
|
|
1902
|
+
//
|
|
1903
|
+
// A compiled file WITHOUT the field — one written before 2.3 —
|
|
1904
|
+
// falls through here, which is slow and correct: accepting it
|
|
1905
|
+
// would make the check optional and therefore absent.
|
|
1906
|
+
//
|
|
1907
|
+
// What it covers is a partial edit, never an author: anyone
|
|
1908
|
+
// who edits the body can recompute this as easily as the
|
|
1909
|
+
// compiler. The deny in `block_plumbing_writes` and the
|
|
1910
|
+
// ratification record are the mechanisms aimed at an author;
|
|
1911
|
+
// this one is aimed at a mistake.
|
|
1912
|
+
raw["body_fingerprint"] === tableFingerprint(JSON.stringify(table))) {
|
|
1913
|
+
return _structure(table);
|
|
1914
|
+
}
|
|
1915
|
+
} catch {
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
return _parse(yamlText);
|
|
1919
|
+
}
|
|
1727
1920
|
function surfaceRow(host, surface = DEFAULT_SURFACE, table = loadHostLowering()) {
|
|
1728
1921
|
return table.get(host)?.get(surface) ?? table.get(host)?.get(DEFAULT_SURFACE) ?? null;
|
|
1729
1922
|
}
|
|
@@ -1740,26 +1933,26 @@ function hostBindings(host, table = loadHostLowering()) {
|
|
|
1740
1933
|
}
|
|
1741
1934
|
|
|
1742
1935
|
// src/install/partitionEligibility.ts
|
|
1743
|
-
import * as
|
|
1744
|
-
import * as
|
|
1936
|
+
import * as fs12 from "node:fs";
|
|
1937
|
+
import * as os3 from "node:os";
|
|
1745
1938
|
|
|
1746
1939
|
// src/install/hostLayerFingerprint.ts
|
|
1747
|
-
import { createHash as
|
|
1748
|
-
import * as
|
|
1749
|
-
import * as
|
|
1940
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
1941
|
+
import * as fs11 from "node:fs";
|
|
1942
|
+
import * as path11 from "node:path";
|
|
1750
1943
|
var FINGERPRINT_SCHEMA = 1;
|
|
1751
1944
|
function collectFiles(dir) {
|
|
1752
1945
|
const out = [];
|
|
1753
1946
|
const walk = (d) => {
|
|
1754
1947
|
let entries;
|
|
1755
1948
|
try {
|
|
1756
|
-
entries =
|
|
1949
|
+
entries = fs11.readdirSync(d, { withFileTypes: true });
|
|
1757
1950
|
} catch {
|
|
1758
1951
|
return;
|
|
1759
1952
|
}
|
|
1760
1953
|
const sorted = [...entries].sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
1761
1954
|
for (const e of sorted) {
|
|
1762
|
-
const p =
|
|
1955
|
+
const p = path11.join(d, e.name);
|
|
1763
1956
|
if (e.isDirectory()) {
|
|
1764
1957
|
walk(p);
|
|
1765
1958
|
} else if (e.isFile()) {
|
|
@@ -1771,15 +1964,15 @@ function collectFiles(dir) {
|
|
|
1771
1964
|
return out.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
1772
1965
|
}
|
|
1773
1966
|
function fingerprintLayers(layers) {
|
|
1774
|
-
const h =
|
|
1967
|
+
const h = createHash6("sha256");
|
|
1775
1968
|
h.update(`v${FINGERPRINT_SCHEMA}\0`);
|
|
1776
1969
|
for (const layer of layers) {
|
|
1777
1970
|
h.update(`layer:${layer.label}\0`);
|
|
1778
1971
|
for (const file of collectFiles(layer.root)) {
|
|
1779
|
-
h.update(
|
|
1972
|
+
h.update(path11.relative(layer.root, file));
|
|
1780
1973
|
h.update("\0");
|
|
1781
1974
|
try {
|
|
1782
|
-
h.update(
|
|
1975
|
+
h.update(fs11.readFileSync(file));
|
|
1783
1976
|
} catch {
|
|
1784
1977
|
h.update("\0unreadable\0");
|
|
1785
1978
|
}
|
|
@@ -1789,11 +1982,11 @@ function fingerprintLayers(layers) {
|
|
|
1789
1982
|
return h.digest("hex");
|
|
1790
1983
|
}
|
|
1791
1984
|
function hostLayerInputs(userHome) {
|
|
1792
|
-
const claude =
|
|
1985
|
+
const claude = path11.join(userHome, ".claude");
|
|
1793
1986
|
return [
|
|
1794
|
-
{ label: "rules", root:
|
|
1795
|
-
{ label: "skills", root:
|
|
1796
|
-
{ label: "commands", root:
|
|
1987
|
+
{ label: "rules", root: path11.join(claude, "rules") },
|
|
1988
|
+
{ label: "skills", root: path11.join(claude, "skills") },
|
|
1989
|
+
{ label: "commands", root: path11.join(claude, "commands") }
|
|
1797
1990
|
];
|
|
1798
1991
|
}
|
|
1799
1992
|
|
|
@@ -1802,7 +1995,7 @@ var MAINTAINER_WORKSPACE = "agent-config-maintainer";
|
|
|
1802
1995
|
function isExclusivelyPackageOnly(source_path) {
|
|
1803
1996
|
let meta;
|
|
1804
1997
|
try {
|
|
1805
|
-
[meta] = parseFrontmatter(
|
|
1998
|
+
[meta] = parseFrontmatter(fs12.readFileSync(source_path, "utf-8"));
|
|
1806
1999
|
} catch {
|
|
1807
2000
|
return false;
|
|
1808
2001
|
}
|
|
@@ -1817,7 +2010,7 @@ function stampHostLayerFingerprint(installedVersion, tools, lockfilePath, skip2,
|
|
|
1817
2010
|
return null;
|
|
1818
2011
|
}
|
|
1819
2012
|
try {
|
|
1820
|
-
const fingerprint = fingerprintLayers(hostLayerInputs(
|
|
2013
|
+
const fingerprint = fingerprintLayers(hostLayerInputs(os3.homedir()));
|
|
1821
2014
|
write_lockfile(installedVersion, [...tools], {
|
|
1822
2015
|
path: lockfilePath,
|
|
1823
2016
|
host_layer_fingerprint: fingerprint
|
|
@@ -1833,8 +2026,8 @@ function stampHostLayerFingerprint(installedVersion, tools, lockfilePath, skip2,
|
|
|
1833
2026
|
}
|
|
1834
2027
|
|
|
1835
2028
|
// src/install/claudeRuleRewrite.ts
|
|
1836
|
-
import * as
|
|
1837
|
-
import * as
|
|
2029
|
+
import * as fs13 from "node:fs";
|
|
2030
|
+
import * as path12 from "node:path";
|
|
1838
2031
|
|
|
1839
2032
|
// src/install/claudePathsPlan.ts
|
|
1840
2033
|
function derive_trigger_globs(meta) {
|
|
@@ -1874,14 +2067,22 @@ function _expanded_pattern_count(pattern) {
|
|
|
1874
2067
|
return n;
|
|
1875
2068
|
}
|
|
1876
2069
|
var CLAUDE_PATHS_PATTERN_BUDGET = 1e3;
|
|
2070
|
+
var PATH_SHAPED_TRIGGER_KEYS = /* @__PURE__ */ new Set(["file_pattern", "path_prefix"]);
|
|
2071
|
+
var NON_MATCHING_TRIGGER_KEYS = /* @__PURE__ */ new Set(["reason"]);
|
|
1877
2072
|
function _has_non_path_trigger(meta) {
|
|
1878
2073
|
const triggers = meta["triggers"];
|
|
1879
2074
|
if (!Array.isArray(triggers)) return false;
|
|
1880
2075
|
for (const t of triggers) {
|
|
1881
2076
|
if (t === null || typeof t !== "object" || Array.isArray(t)) continue;
|
|
1882
2077
|
const obj = t;
|
|
1883
|
-
|
|
1884
|
-
|
|
2078
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
2079
|
+
if (PATH_SHAPED_TRIGGER_KEYS.has(key) || NON_MATCHING_TRIGGER_KEYS.has(key)) continue;
|
|
2080
|
+
if (typeof value === "string") {
|
|
2081
|
+
if (value.trim() !== "") return true;
|
|
2082
|
+
} else if (value !== void 0 && value !== null) {
|
|
2083
|
+
return true;
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
1885
2086
|
}
|
|
1886
2087
|
return false;
|
|
1887
2088
|
}
|
|
@@ -1949,6 +2150,11 @@ function rewriteAndReport(rulesDir, quiet, info2, warn2, wrappers, preserved = /
|
|
|
1949
2150
|
` claude-code: ${wrappers.reserved.length} flat command(s) withheld \u2014 name is a Claude Code built-in (${wrappers.reserved.join(", ")}); nested /cluster:sub commands remain available`
|
|
1950
2151
|
);
|
|
1951
2152
|
}
|
|
2153
|
+
if (wrappers.foreign !== void 0 && wrappers.foreign.length > 0) {
|
|
2154
|
+
info2(
|
|
2155
|
+
` claude-code: kept ${wrappers.foreign.length} neighbour command file(s) whose name is a Claude Code built-in (${wrappers.foreign.join(", ")}); not ours to remove`
|
|
2156
|
+
);
|
|
2157
|
+
}
|
|
1952
2158
|
}
|
|
1953
2159
|
if (result.rewritten > 0 && !quiet) {
|
|
1954
2160
|
info2(
|
|
@@ -1990,23 +2196,23 @@ function rewriteClaudeRules(rulesDir, preserved = /* @__PURE__ */ new Set()) {
|
|
|
1990
2196
|
const result = { rewritten: 0, scoped: [], dropped: [], failed: [] };
|
|
1991
2197
|
let entries;
|
|
1992
2198
|
try {
|
|
1993
|
-
entries =
|
|
2199
|
+
entries = fs13.readdirSync(rulesDir);
|
|
1994
2200
|
} catch {
|
|
1995
2201
|
return result;
|
|
1996
2202
|
}
|
|
1997
2203
|
for (const name of entries.filter((n) => n.endsWith(".md")).sort()) {
|
|
1998
|
-
const full =
|
|
1999
|
-
if (preserved.has(
|
|
2204
|
+
const full = path12.join(rulesDir, name);
|
|
2205
|
+
if (preserved.has(path12.resolve(full))) continue;
|
|
2000
2206
|
let stat;
|
|
2001
2207
|
try {
|
|
2002
|
-
stat =
|
|
2208
|
+
stat = fs13.lstatSync(full);
|
|
2003
2209
|
} catch {
|
|
2004
2210
|
continue;
|
|
2005
2211
|
}
|
|
2006
2212
|
if (!stat.isFile() || stat.isSymbolicLink()) continue;
|
|
2007
2213
|
let text;
|
|
2008
2214
|
try {
|
|
2009
|
-
text =
|
|
2215
|
+
text = fs13.readFileSync(full, "utf-8");
|
|
2010
2216
|
} catch {
|
|
2011
2217
|
continue;
|
|
2012
2218
|
}
|
|
@@ -2016,7 +2222,7 @@ function rewriteClaudeRules(rulesDir, preserved = /* @__PURE__ */ new Set()) {
|
|
|
2016
2222
|
const withOwnership = _withPreservedKeys(rendered.text, text);
|
|
2017
2223
|
if (withOwnership !== text) {
|
|
2018
2224
|
try {
|
|
2019
|
-
|
|
2225
|
+
fs13.writeFileSync(full, withOwnership, "utf-8");
|
|
2020
2226
|
} catch (e) {
|
|
2021
2227
|
result.failed.push({
|
|
2022
2228
|
rule: name.slice(0, -3),
|
|
@@ -2035,6 +2241,744 @@ function rewriteClaudeRules(rulesDir, preserved = /* @__PURE__ */ new Set()) {
|
|
|
2035
2241
|
return result;
|
|
2036
2242
|
}
|
|
2037
2243
|
|
|
2244
|
+
// src/install/installThinLayer.ts
|
|
2245
|
+
import * as fs17 from "node:fs";
|
|
2246
|
+
import * as path17 from "node:path";
|
|
2247
|
+
import * as os5 from "node:os";
|
|
2248
|
+
|
|
2249
|
+
// src/scripts/_lib/installed_layer.ts
|
|
2250
|
+
import * as fs14 from "node:fs";
|
|
2251
|
+
import * as path14 from "node:path";
|
|
2252
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
2253
|
+
|
|
2254
|
+
// src/install/globalRuleLayers.ts
|
|
2255
|
+
import * as os4 from "node:os";
|
|
2256
|
+
import * as path13 from "node:path";
|
|
2257
|
+
var GLOBAL_RULE_DIRS = {
|
|
2258
|
+
"claude-code": ".claude/rules",
|
|
2259
|
+
cursor: ".cursor/rules",
|
|
2260
|
+
augment: ".augment/rules",
|
|
2261
|
+
// Windsurf's scope root is `~/.codeium/windsurf/`, not `~/.windsurf/`.
|
|
2262
|
+
windsurf: ".codeium/windsurf/rules",
|
|
2263
|
+
// Cline's scope root IS the rules directory — no `rules/` suffix.
|
|
2264
|
+
cline: "Documents/Cline/Rules"
|
|
2265
|
+
};
|
|
2266
|
+
function globalRuleLayerPath(toolId, home = process.env["HOME"] ?? os4.homedir()) {
|
|
2267
|
+
const rel = GLOBAL_RULE_DIRS[toolId];
|
|
2268
|
+
return rel === void 0 ? null : path13.join(home, rel);
|
|
2269
|
+
}
|
|
2270
|
+
|
|
2271
|
+
// src/scripts/_lib/rule_law_section.ts
|
|
2272
|
+
var IRON_LAW_RE = /\biron\s+laws?\b/i;
|
|
2273
|
+
var HEADING_RE = /^(#{1,6})\s+(.+?)\s*$/;
|
|
2274
|
+
var FENCE_RE = /^\s*```/;
|
|
2275
|
+
function splitFrontmatter(text) {
|
|
2276
|
+
if (text.startsWith("---\n")) {
|
|
2277
|
+
const end = text.indexOf("\n---\n", 4);
|
|
2278
|
+
if (end !== -1) {
|
|
2279
|
+
return [text.slice(0, end + 5), text.slice(end + 5)];
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
return ["", text];
|
|
2283
|
+
}
|
|
2284
|
+
function ruleBody(text) {
|
|
2285
|
+
const [, body] = splitFrontmatter(text);
|
|
2286
|
+
return body.replace(/<!--[\s\S]*?-->/g, "").trim();
|
|
2287
|
+
}
|
|
2288
|
+
function lawSections(body) {
|
|
2289
|
+
const lines = body.split("\n");
|
|
2290
|
+
let inFence = false;
|
|
2291
|
+
const headings = [];
|
|
2292
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
2293
|
+
const raw = lines[i];
|
|
2294
|
+
if (FENCE_RE.test(raw)) {
|
|
2295
|
+
inFence = !inFence;
|
|
2296
|
+
continue;
|
|
2297
|
+
}
|
|
2298
|
+
if (inFence) continue;
|
|
2299
|
+
const m = HEADING_RE.exec(raw);
|
|
2300
|
+
if (m) headings.push({ i, depth: m[1].length, title: m[2].trim() });
|
|
2301
|
+
}
|
|
2302
|
+
const out = [];
|
|
2303
|
+
for (let k = 0; k < headings.length; k += 1) {
|
|
2304
|
+
const h = headings[k];
|
|
2305
|
+
if (!IRON_LAW_RE.test(h.title)) continue;
|
|
2306
|
+
let end = lines.length;
|
|
2307
|
+
for (let j = k + 1; j < headings.length; j += 1) {
|
|
2308
|
+
const n = headings[j];
|
|
2309
|
+
if (n.depth <= h.depth) {
|
|
2310
|
+
end = n.i;
|
|
2311
|
+
break;
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
out.push({
|
|
2315
|
+
title: h.title,
|
|
2316
|
+
depth: h.depth,
|
|
2317
|
+
line: h.i + 1,
|
|
2318
|
+
text: lines.slice(h.i, end).join("\n").trim()
|
|
2319
|
+
});
|
|
2320
|
+
}
|
|
2321
|
+
return out;
|
|
2322
|
+
}
|
|
2323
|
+
function lawText(body) {
|
|
2324
|
+
const sections = lawSections(body);
|
|
2325
|
+
if (sections.length === 0) return null;
|
|
2326
|
+
return sections.map((s) => s.text).join("\n\n");
|
|
2327
|
+
}
|
|
2328
|
+
|
|
2329
|
+
// src/scripts/_lib/installed_layer.ts
|
|
2330
|
+
var TOP_FILES = 20;
|
|
2331
|
+
var LIMIT_WARN_FRACTION = 0.8;
|
|
2332
|
+
function isUnconditional(text) {
|
|
2333
|
+
return !/^paths:/m.test(text);
|
|
2334
|
+
}
|
|
2335
|
+
function readLayer(host, scope, dir, recorded) {
|
|
2336
|
+
const empty = {
|
|
2337
|
+
files: 0,
|
|
2338
|
+
unconditional: 0,
|
|
2339
|
+
chars: 0,
|
|
2340
|
+
package_owned: 0,
|
|
2341
|
+
foreign: 0,
|
|
2342
|
+
package_owned_chars: 0,
|
|
2343
|
+
foreign_chars: 0,
|
|
2344
|
+
top: []
|
|
2345
|
+
};
|
|
2346
|
+
let names;
|
|
2347
|
+
try {
|
|
2348
|
+
names = fs14.readdirSync(dir);
|
|
2349
|
+
} catch {
|
|
2350
|
+
return { host, scope, dir, present: false, ...empty };
|
|
2351
|
+
}
|
|
2352
|
+
const readings = [];
|
|
2353
|
+
for (const name of names.sort()) {
|
|
2354
|
+
if (!name.endsWith(".md")) continue;
|
|
2355
|
+
const abs = path14.join(dir, name);
|
|
2356
|
+
let text;
|
|
2357
|
+
try {
|
|
2358
|
+
const st = fs14.statSync(abs);
|
|
2359
|
+
if (!st.isFile()) continue;
|
|
2360
|
+
text = fs14.readFileSync(abs, "utf-8");
|
|
2361
|
+
} catch {
|
|
2362
|
+
continue;
|
|
2363
|
+
}
|
|
2364
|
+
const owned = recorded.has(abs);
|
|
2365
|
+
readings.push({
|
|
2366
|
+
file: name,
|
|
2367
|
+
// THE STRIP IS THE PROJECTOR'S OWN. `ruleBody` is what
|
|
2368
|
+
// `project_thin_rules` and the delivery carrier both call, so "what
|
|
2369
|
+
// a host loads" and "what a delivery carries" cannot drift into two
|
|
2370
|
+
// spellings of the same measurement.
|
|
2371
|
+
chars: ruleBody(text).length,
|
|
2372
|
+
unconditional: isUnconditional(text),
|
|
2373
|
+
package_owned: owned
|
|
2374
|
+
});
|
|
2375
|
+
}
|
|
2376
|
+
const top = [...readings].sort((a, b) => b.chars - a.chars || a.file.localeCompare(b.file)).slice(0, TOP_FILES);
|
|
2377
|
+
return {
|
|
2378
|
+
host,
|
|
2379
|
+
scope,
|
|
2380
|
+
dir,
|
|
2381
|
+
present: true,
|
|
2382
|
+
files: readings.length,
|
|
2383
|
+
unconditional: readings.filter((r) => r.unconditional).length,
|
|
2384
|
+
chars: readings.reduce((n, r) => n + r.chars, 0),
|
|
2385
|
+
package_owned: readings.filter((r) => r.package_owned).length,
|
|
2386
|
+
foreign: readings.filter((r) => !r.package_owned).length,
|
|
2387
|
+
package_owned_chars: readings.reduce((n, r) => n + (r.package_owned ? r.chars : 0), 0),
|
|
2388
|
+
foreign_chars: readings.reduce((n, r) => n + (r.package_owned ? 0 : r.chars), 0),
|
|
2389
|
+
top
|
|
2390
|
+
};
|
|
2391
|
+
}
|
|
2392
|
+
function defaultHostLimitsPath() {
|
|
2393
|
+
return path14.join(
|
|
2394
|
+
path14.dirname(fileURLToPath2(import.meta.url)),
|
|
2395
|
+
"..",
|
|
2396
|
+
"..",
|
|
2397
|
+
"config",
|
|
2398
|
+
"host-instruction-limits.json"
|
|
2399
|
+
);
|
|
2400
|
+
}
|
|
2401
|
+
function loadHostInstructionLimits(file = defaultHostLimitsPath()) {
|
|
2402
|
+
const out = /* @__PURE__ */ new Map();
|
|
2403
|
+
let raw;
|
|
2404
|
+
try {
|
|
2405
|
+
raw = JSON.parse(fs14.readFileSync(file, "utf-8"));
|
|
2406
|
+
} catch {
|
|
2407
|
+
return out;
|
|
2408
|
+
}
|
|
2409
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return out;
|
|
2410
|
+
for (const [host, v] of Object.entries(raw)) {
|
|
2411
|
+
if (host.startsWith("_")) continue;
|
|
2412
|
+
if (typeof v !== "object" || v === null || Array.isArray(v)) continue;
|
|
2413
|
+
const e = v;
|
|
2414
|
+
const n = e.limit;
|
|
2415
|
+
const limit = typeof n === "number" && Number.isFinite(n) && n > 0 ? n : null;
|
|
2416
|
+
const k = e.kind;
|
|
2417
|
+
const kind = limit === null ? "unpublished" : k === "vendor-published" || k === "reported" ? k : "reported";
|
|
2418
|
+
out.set(host, { limit, kind });
|
|
2419
|
+
}
|
|
2420
|
+
return out;
|
|
2421
|
+
}
|
|
2422
|
+
function buildHostLimitRows(layers, limits) {
|
|
2423
|
+
const byHost = /* @__PURE__ */ new Map();
|
|
2424
|
+
for (const l of layers) {
|
|
2425
|
+
if (!l.present) continue;
|
|
2426
|
+
const acc = byHost.get(l.host) ?? { chars: 0, owned: 0, foreign: 0 };
|
|
2427
|
+
acc.chars += l.chars;
|
|
2428
|
+
acc.owned += l.package_owned_chars;
|
|
2429
|
+
acc.foreign += l.foreign_chars;
|
|
2430
|
+
byHost.set(l.host, acc);
|
|
2431
|
+
}
|
|
2432
|
+
for (const l of layers) if (!byHost.has(l.host)) byHost.set(l.host, { chars: 0, owned: 0, foreign: 0 });
|
|
2433
|
+
for (const [host, e] of limits) if (e.limit !== null && !byHost.has(host)) {
|
|
2434
|
+
byHost.set(host, { chars: 0, owned: 0, foreign: 0 });
|
|
2435
|
+
}
|
|
2436
|
+
const rows = [];
|
|
2437
|
+
for (const host of [...byHost.keys()].sort()) {
|
|
2438
|
+
const a = byHost.get(host);
|
|
2439
|
+
const e = limits.get(host) ?? { limit: null, kind: "unpublished" };
|
|
2440
|
+
const fraction = e.limit === null ? null : a.chars / e.limit;
|
|
2441
|
+
rows.push({
|
|
2442
|
+
host,
|
|
2443
|
+
limit: e.limit,
|
|
2444
|
+
kind: e.kind,
|
|
2445
|
+
chars: a.chars,
|
|
2446
|
+
package_owned_chars: a.owned,
|
|
2447
|
+
foreign_chars: a.foreign,
|
|
2448
|
+
fraction,
|
|
2449
|
+
warn: fraction !== null && fraction >= LIMIT_WARN_FRACTION
|
|
2450
|
+
});
|
|
2451
|
+
}
|
|
2452
|
+
return rows;
|
|
2453
|
+
}
|
|
2454
|
+
function renderHostLimitRows(rows) {
|
|
2455
|
+
const out = [
|
|
2456
|
+
"host instruction budgets \u2014 package-owned + foreign against the published limit"
|
|
2457
|
+
];
|
|
2458
|
+
for (const r of rows) {
|
|
2459
|
+
const split = `${String(r.package_owned_chars)} package-owned + ${String(r.foreign_chars)} foreign = ${String(r.chars)} chars`;
|
|
2460
|
+
if (r.limit === null) {
|
|
2461
|
+
out.push(` ${r.host} \u2014 ${split}; no published limit recorded \u2014 not measured`);
|
|
2462
|
+
continue;
|
|
2463
|
+
}
|
|
2464
|
+
const pct = (r.fraction * 100).toFixed(1);
|
|
2465
|
+
out.push(
|
|
2466
|
+
` ${r.host} \u2014 ${split}; ${pct}% of ${String(r.limit)} (${r.kind})` + (r.warn ? ` \u2014 WARNING: at or past ${String(Math.round(LIMIT_WARN_FRACTION * 100))}% of the published limit` : "")
|
|
2467
|
+
);
|
|
2468
|
+
}
|
|
2469
|
+
return out;
|
|
2470
|
+
}
|
|
2471
|
+
|
|
2472
|
+
// src/scripts/_lib/thin_rules.ts
|
|
2473
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
2474
|
+
import * as fs16 from "node:fs";
|
|
2475
|
+
import * as path16 from "node:path";
|
|
2476
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
2477
|
+
|
|
2478
|
+
// src/scripts/_lib/rule_consequence_class.ts
|
|
2479
|
+
import * as fs15 from "node:fs";
|
|
2480
|
+
import * as path15 from "node:path";
|
|
2481
|
+
var CLASS_CONFIG_REL = "src/config/rule-consequence-class.json";
|
|
2482
|
+
function readConsequenceClass(repoRoot) {
|
|
2483
|
+
const raw = JSON.parse(fs15.readFileSync(path15.join(repoRoot, CLASS_CONFIG_REL), "utf-8"));
|
|
2484
|
+
return {
|
|
2485
|
+
criterion_ref: raw.criterion_ref ?? "",
|
|
2486
|
+
members: raw.members ?? {},
|
|
2487
|
+
no_stub: raw.no_stub ?? {},
|
|
2488
|
+
excluded: raw.excluded ?? {}
|
|
2489
|
+
};
|
|
2490
|
+
}
|
|
2491
|
+
function stubLawIds(cfg) {
|
|
2492
|
+
return new Set(Object.keys(cfg.members).filter((id) => cfg.no_stub[id] === void 0));
|
|
2493
|
+
}
|
|
2494
|
+
|
|
2495
|
+
// src/scripts/_lib/rule_injection.ts
|
|
2496
|
+
var PATH_TRIGGER_KINDS = ["path_prefix", "file_pattern"];
|
|
2497
|
+
function tierEntries(router, tier) {
|
|
2498
|
+
const raw = router[tier];
|
|
2499
|
+
if (!Array.isArray(raw)) return [];
|
|
2500
|
+
return raw.map((r) => ({
|
|
2501
|
+
id: String(r["id"] ?? ""),
|
|
2502
|
+
triggers: Array.isArray(r["triggers"]) ? r["triggers"] : []
|
|
2503
|
+
}));
|
|
2504
|
+
}
|
|
2505
|
+
function allTierRules(router) {
|
|
2506
|
+
const out = [];
|
|
2507
|
+
for (const tier of ["tier_1", "tier_2"]) {
|
|
2508
|
+
for (const e of tierEntries(router, tier)) out.push({ ...e, tier });
|
|
2509
|
+
}
|
|
2510
|
+
return out;
|
|
2511
|
+
}
|
|
2512
|
+
function pathOnlyRuleIds(router) {
|
|
2513
|
+
const ids = /* @__PURE__ */ new Set();
|
|
2514
|
+
for (const r of allTierRules(router)) {
|
|
2515
|
+
if (r.triggers.length === 0) continue;
|
|
2516
|
+
const allPath = r.triggers.every(
|
|
2517
|
+
(t) => PATH_TRIGGER_KINDS.some((k) => k in t)
|
|
2518
|
+
);
|
|
2519
|
+
if (allPath) ids.add(r.id);
|
|
2520
|
+
}
|
|
2521
|
+
return ids;
|
|
2522
|
+
}
|
|
2523
|
+
function triggerlessRuleIds(router) {
|
|
2524
|
+
return allTierRules(router).filter((r) => r.triggers.length === 0).map((r) => r.id);
|
|
2525
|
+
}
|
|
2526
|
+
|
|
2527
|
+
// src/scripts/_lib/thin_rules.ts
|
|
2528
|
+
var _HERE = fileURLToPath3(import.meta.url);
|
|
2529
|
+
var REPO_ROOT = path16.resolve(path16.dirname(_HERE), "..", "..", "..");
|
|
2530
|
+
var RULES_SOURCE = path16.join(REPO_ROOT, "dist/agent-src", "rules");
|
|
2531
|
+
var ROUTER = path16.join(REPO_ROOT, "dist", "router.json");
|
|
2532
|
+
function _globSortedMd(dir) {
|
|
2533
|
+
let names;
|
|
2534
|
+
try {
|
|
2535
|
+
names = fs16.readdirSync(dir);
|
|
2536
|
+
} catch {
|
|
2537
|
+
return [];
|
|
2538
|
+
}
|
|
2539
|
+
const out = names.filter((n) => n.endsWith(".md")).map((n) => path16.join(dir, n));
|
|
2540
|
+
out.sort();
|
|
2541
|
+
return out;
|
|
2542
|
+
}
|
|
2543
|
+
function kernel_ids(routerPath = ROUTER) {
|
|
2544
|
+
const data = JSON.parse(fs16.readFileSync(routerPath, "utf-8"));
|
|
2545
|
+
const kernel = data.kernel;
|
|
2546
|
+
if (Array.isArray(kernel)) {
|
|
2547
|
+
return new Set(kernel.map((x) => String(x)));
|
|
2548
|
+
}
|
|
2549
|
+
return /* @__PURE__ */ new Set();
|
|
2550
|
+
}
|
|
2551
|
+
function _router(routerPath = ROUTER) {
|
|
2552
|
+
return JSON.parse(fs16.readFileSync(routerPath, "utf-8"));
|
|
2553
|
+
}
|
|
2554
|
+
function path_only_ids(routerPath = ROUTER) {
|
|
2555
|
+
return pathOnlyRuleIds(_router(routerPath));
|
|
2556
|
+
}
|
|
2557
|
+
function no_trigger_ids(routerPath = ROUTER) {
|
|
2558
|
+
return new Set(triggerlessRuleIds(_router(routerPath)));
|
|
2559
|
+
}
|
|
2560
|
+
function rule_workspaces_map(routerPath = ROUTER) {
|
|
2561
|
+
const data = JSON.parse(fs16.readFileSync(routerPath, "utf-8"));
|
|
2562
|
+
const map = /* @__PURE__ */ new Map();
|
|
2563
|
+
for (const tier of ["tier_1", "tier_2"]) {
|
|
2564
|
+
const entries = data[tier];
|
|
2565
|
+
if (!Array.isArray(entries)) continue;
|
|
2566
|
+
for (const e of entries) {
|
|
2567
|
+
const obj = e;
|
|
2568
|
+
const ws = Array.isArray(obj.workspaces) ? obj.workspaces.map((w) => String(w)) : [];
|
|
2569
|
+
map.set(String(obj.id), ws);
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
return map;
|
|
2573
|
+
}
|
|
2574
|
+
function id_in_scope(rule_id, scope, kernel, wsMap, fallback_ws = []) {
|
|
2575
|
+
if (scope === null || kernel.has(rule_id)) {
|
|
2576
|
+
return true;
|
|
2577
|
+
}
|
|
2578
|
+
const ws = wsMap.get(rule_id) ?? fallback_ws;
|
|
2579
|
+
if (ws.length === 0) {
|
|
2580
|
+
return true;
|
|
2581
|
+
}
|
|
2582
|
+
return ws.some((w) => scope.includes(w));
|
|
2583
|
+
}
|
|
2584
|
+
function fm_workspaces(text) {
|
|
2585
|
+
const [fm] = split_frontmatter(text);
|
|
2586
|
+
const flow = /^workspaces:[ \t]*\[([^\]]*)\]/m.exec(fm);
|
|
2587
|
+
if (flow) {
|
|
2588
|
+
return flow[1].split(",").map((s) => s.trim().replace(/^["']|["']$/g, "")).filter((s) => s.length > 0);
|
|
2589
|
+
}
|
|
2590
|
+
const m = /^workspaces:[ \t]*\n((?:[ \t]+-[ \t]+.*(?:\n|$))+)/m.exec(fm);
|
|
2591
|
+
if (!m) {
|
|
2592
|
+
return [];
|
|
2593
|
+
}
|
|
2594
|
+
return [...m[1].matchAll(/-[ \t]+(\S+)/g)].map((x) => x[1]);
|
|
2595
|
+
}
|
|
2596
|
+
function split_frontmatter(text) {
|
|
2597
|
+
if (text.startsWith("---\n")) {
|
|
2598
|
+
const end = text.indexOf("\n---\n", 4);
|
|
2599
|
+
if (end !== -1) {
|
|
2600
|
+
return [text.slice(0, end + 5), text.slice(end + 5)];
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
return ["", text];
|
|
2604
|
+
}
|
|
2605
|
+
function _description(fm) {
|
|
2606
|
+
const m = /^description:\s*"?(.+?)"?\s*$/m.exec(fm);
|
|
2607
|
+
return m ? m[1].trim() : "";
|
|
2608
|
+
}
|
|
2609
|
+
var _TRIGGER_HINT_LIMIT = 6;
|
|
2610
|
+
function _trigger_hint(fm) {
|
|
2611
|
+
const hits = [];
|
|
2612
|
+
const re = /^\s*-\s*(?:keyword|phrase):\s*"?(.+?)"?\s*$/gm;
|
|
2613
|
+
let m;
|
|
2614
|
+
while ((m = re.exec(fm)) !== null) {
|
|
2615
|
+
hits.push(m[1].trim());
|
|
2616
|
+
if (hits.length >= _TRIGGER_HINT_LIMIT) {
|
|
2617
|
+
break;
|
|
2618
|
+
}
|
|
2619
|
+
}
|
|
2620
|
+
return hits.join(", ");
|
|
2621
|
+
}
|
|
2622
|
+
function _title(s) {
|
|
2623
|
+
return s.replace(/[A-Za-z]+/g, (w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase());
|
|
2624
|
+
}
|
|
2625
|
+
var THIN_ENTRY_MARKER = "> Routed rule \u2014 load the body on trigger-match.";
|
|
2626
|
+
var BODY_LINK_PREFIX = "../../dist/agent-src/rules/";
|
|
2627
|
+
function absoluteBodyLinkPrefix(packageRoot) {
|
|
2628
|
+
return `${path16.join(path16.resolve(packageRoot), "dist", "agent-src", "rules")}${path16.sep}`;
|
|
2629
|
+
}
|
|
2630
|
+
function thin_entry(rule_id, text, bodyLinkPrefix = BODY_LINK_PREFIX) {
|
|
2631
|
+
const [fm] = split_frontmatter(text);
|
|
2632
|
+
const desc = _description(fm);
|
|
2633
|
+
const hint = _trigger_hint(fm);
|
|
2634
|
+
const title = _title(rule_id.replace(/-/g, " "));
|
|
2635
|
+
const fires = hint ? ` Fires on: ${hint}.` : "";
|
|
2636
|
+
return `## ${title}
|
|
2637
|
+
${THIN_ENTRY_MARKER}${fires} ${desc} Body: [\`${rule_id}\`](${bodyLinkPrefix}${rule_id}.md)
|
|
2638
|
+
`;
|
|
2639
|
+
}
|
|
2640
|
+
var STUB_LAW_OPEN = "<!-- law: byte-copied from the rule, sha256 ";
|
|
2641
|
+
var STUB_LAW_CLOSE = "<!-- /law -->";
|
|
2642
|
+
function lawDigest(law) {
|
|
2643
|
+
return createHash7("sha256").update(law, "utf-8").digest("hex").slice(0, 16);
|
|
2644
|
+
}
|
|
2645
|
+
var StubLawError = class extends Error {
|
|
2646
|
+
ruleId;
|
|
2647
|
+
constructor(ruleId, message) {
|
|
2648
|
+
super(message);
|
|
2649
|
+
this.name = "StubLawError";
|
|
2650
|
+
this.ruleId = ruleId;
|
|
2651
|
+
}
|
|
2652
|
+
};
|
|
2653
|
+
var STUB_LAW_MAX_CHARS = 2e3;
|
|
2654
|
+
function thin_entry_with_law(rule_id, text, bodyLinkPrefix = BODY_LINK_PREFIX) {
|
|
2655
|
+
const law = lawText(ruleBody(text));
|
|
2656
|
+
if (law === null) {
|
|
2657
|
+
throw new StubLawError(
|
|
2658
|
+
rule_id,
|
|
2659
|
+
`${rule_id} is a high-consequence class member with no law section \u2014 write one, or record it under \`no_stub\` in src/config/rule-consequence-class.json with the reason`
|
|
2660
|
+
);
|
|
2661
|
+
}
|
|
2662
|
+
if (law.length > STUB_LAW_MAX_CHARS) {
|
|
2663
|
+
throw new StubLawError(
|
|
2664
|
+
rule_id,
|
|
2665
|
+
`${rule_id} is a high-consequence class member whose law section is ${law.length} chars, over the ${STUB_LAW_MAX_CHARS} ceiling \u2014 a stub never ships a shortened copy, so either the law moves under the ceiling or the rule is recorded under \`no_stub\` in src/config/rule-consequence-class.json with the reason`
|
|
2666
|
+
);
|
|
2667
|
+
}
|
|
2668
|
+
return thin_entry(rule_id, text, bodyLinkPrefix) + `
|
|
2669
|
+
${STUB_LAW_OPEN}${lawDigest(law)} -->
|
|
2670
|
+
${law}
|
|
2671
|
+
${STUB_LAW_CLOSE}
|
|
2672
|
+
`;
|
|
2673
|
+
}
|
|
2674
|
+
function build_thin(rules_dir = RULES_SOURCE, scope = null, announce = null, consequenceClass = null, roots = null) {
|
|
2675
|
+
const routerPath = roots?.routerPath ?? (roots?.packageRoot === void 0 ? ROUTER : path16.join(roots.packageRoot, "dist", "router.json"));
|
|
2676
|
+
const classRoot = roots?.packageRoot ?? REPO_ROOT;
|
|
2677
|
+
const bodyLinkPrefix = roots?.bodyLinkPrefix ?? BODY_LINK_PREFIX;
|
|
2678
|
+
const kernel = kernel_ids(routerPath);
|
|
2679
|
+
const noTrigger = no_trigger_ids(routerPath);
|
|
2680
|
+
const pathOnly = path_only_ids(routerPath);
|
|
2681
|
+
const cls = consequenceClass ?? readConsequenceClass(classRoot);
|
|
2682
|
+
const lawInStub = stubLawIds(cls);
|
|
2683
|
+
const wsMap = scope !== null ? rule_workspaces_map(routerPath) : /* @__PURE__ */ new Map();
|
|
2684
|
+
const out = /* @__PURE__ */ new Map();
|
|
2685
|
+
for (const p of _globSortedMd(rules_dir)) {
|
|
2686
|
+
const text = fs16.readFileSync(p, "utf-8");
|
|
2687
|
+
const stem = path16.basename(p).replace(/\.md$/, "");
|
|
2688
|
+
if (!id_in_scope(stem, scope, kernel, wsMap, fm_workspaces(text))) {
|
|
2689
|
+
continue;
|
|
2690
|
+
}
|
|
2691
|
+
const noStub = cls.no_stub[stem] !== void 0;
|
|
2692
|
+
const full = kernel.has(stem) || noTrigger.has(stem) || pathOnly.has(stem) || noStub;
|
|
2693
|
+
if (announce !== null && noTrigger.has(stem) && !kernel.has(stem)) {
|
|
2694
|
+
announce(`D3: trigger-less auto rule ${path16.basename(p)} \u2014 kept full-bodied, never thinned`);
|
|
2695
|
+
}
|
|
2696
|
+
if (announce !== null && pathOnly.has(stem) && !kernel.has(stem) && !noTrigger.has(stem)) {
|
|
2697
|
+
announce(
|
|
2698
|
+
`E2: path-only auto rule ${path16.basename(p)} \u2014 kept full-bodied; its only triggers are path-shaped and the delivery concern is not bound on pre_tool_use`
|
|
2699
|
+
);
|
|
2700
|
+
}
|
|
2701
|
+
if (full) {
|
|
2702
|
+
out.set(path16.basename(p), text);
|
|
2703
|
+
continue;
|
|
2704
|
+
}
|
|
2705
|
+
if (lawInStub.has(stem)) {
|
|
2706
|
+
if (announce !== null) {
|
|
2707
|
+
announce(
|
|
2708
|
+
`LAW: high-consequence rule ${path16.basename(p)} \u2014 stub carries its own law section, byte-copied`
|
|
2709
|
+
);
|
|
2710
|
+
}
|
|
2711
|
+
out.set(path16.basename(p), thin_entry_with_law(stem, text, bodyLinkPrefix));
|
|
2712
|
+
continue;
|
|
2713
|
+
}
|
|
2714
|
+
out.set(path16.basename(p), thin_entry(stem, text, bodyLinkPrefix));
|
|
2715
|
+
}
|
|
2716
|
+
return out;
|
|
2717
|
+
}
|
|
2718
|
+
|
|
2719
|
+
// src/install/installThinLayer.ts
|
|
2720
|
+
function thinInstalledRuleLayer(opts) {
|
|
2721
|
+
const packageRoot = path17.resolve(opts.packageRoot);
|
|
2722
|
+
const bodySourceDir = path17.join(packageRoot, "dist", "agent-src", "rules");
|
|
2723
|
+
const bodyLinkPrefix = absoluteBodyLinkPrefix(packageRoot);
|
|
2724
|
+
const preserved = opts.preserved ?? /* @__PURE__ */ new Set();
|
|
2725
|
+
const stubs = build_thin(bodySourceDir, null, null, null, { packageRoot, bodyLinkPrefix });
|
|
2726
|
+
let thinned = 0;
|
|
2727
|
+
let rewritten = 0;
|
|
2728
|
+
let kept = 0;
|
|
2729
|
+
let charsBefore = 0;
|
|
2730
|
+
let charsAfter = 0;
|
|
2731
|
+
const preservedHits = [];
|
|
2732
|
+
const absent = [];
|
|
2733
|
+
const failed = [];
|
|
2734
|
+
for (const [name, stubText] of stubs) {
|
|
2735
|
+
const target = path17.join(opts.rulesDir, name);
|
|
2736
|
+
let installed;
|
|
2737
|
+
try {
|
|
2738
|
+
installed = fs17.readFileSync(target, "utf-8");
|
|
2739
|
+
} catch (e) {
|
|
2740
|
+
if (e.code === "ENOENT") absent.push(name);
|
|
2741
|
+
else failed.push({ rule: name, reason: String(e) });
|
|
2742
|
+
continue;
|
|
2743
|
+
}
|
|
2744
|
+
let sourceText;
|
|
2745
|
+
try {
|
|
2746
|
+
sourceText = fs17.readFileSync(path17.join(bodySourceDir, name), "utf-8");
|
|
2747
|
+
} catch {
|
|
2748
|
+
sourceText = null;
|
|
2749
|
+
}
|
|
2750
|
+
if (stubText === sourceText) {
|
|
2751
|
+
kept += 1;
|
|
2752
|
+
charsBefore += installed.length;
|
|
2753
|
+
charsAfter += installed.length;
|
|
2754
|
+
continue;
|
|
2755
|
+
}
|
|
2756
|
+
if (preserved.has(path17.resolve(target))) {
|
|
2757
|
+
preservedHits.push(name);
|
|
2758
|
+
charsBefore += installed.length;
|
|
2759
|
+
charsAfter += installed.length;
|
|
2760
|
+
continue;
|
|
2761
|
+
}
|
|
2762
|
+
const [frontmatter] = split_frontmatter(installed);
|
|
2763
|
+
charsBefore += installed.length;
|
|
2764
|
+
if (frontmatter === "" && /^\uFEFF?[\s]*---/.test(installed)) {
|
|
2765
|
+
failed.push({
|
|
2766
|
+
rule: name,
|
|
2767
|
+
reason: "opens a frontmatter block that never closes \u2014 left untouched so its ownership keys survive"
|
|
2768
|
+
});
|
|
2769
|
+
charsAfter += installed.length;
|
|
2770
|
+
continue;
|
|
2771
|
+
}
|
|
2772
|
+
const next = `${frontmatter}${stubText}`;
|
|
2773
|
+
try {
|
|
2774
|
+
if (next !== installed) {
|
|
2775
|
+
fs17.writeFileSync(target, next, "utf-8");
|
|
2776
|
+
rewritten += 1;
|
|
2777
|
+
}
|
|
2778
|
+
thinned += 1;
|
|
2779
|
+
charsAfter += next.length;
|
|
2780
|
+
} catch (e) {
|
|
2781
|
+
failed.push({ rule: name, reason: String(e) });
|
|
2782
|
+
charsAfter += installed.length;
|
|
2783
|
+
}
|
|
2784
|
+
}
|
|
2785
|
+
if (stubs.size === 0) {
|
|
2786
|
+
failed.push({
|
|
2787
|
+
rule: bodySourceDir,
|
|
2788
|
+
reason: "no rule bodies found to build stubs from \u2014 the layer was left full-bodied"
|
|
2789
|
+
});
|
|
2790
|
+
}
|
|
2791
|
+
return {
|
|
2792
|
+
thinned,
|
|
2793
|
+
rewritten,
|
|
2794
|
+
kept,
|
|
2795
|
+
preserved: preservedHits,
|
|
2796
|
+
absent,
|
|
2797
|
+
failed,
|
|
2798
|
+
bodyLinkPrefix,
|
|
2799
|
+
charsBefore,
|
|
2800
|
+
charsAfter
|
|
2801
|
+
};
|
|
2802
|
+
}
|
|
2803
|
+
function describeThinInstalledLayer(res) {
|
|
2804
|
+
const out = [];
|
|
2805
|
+
out.push(
|
|
2806
|
+
res.rewritten === 0 && res.thinned > 0 ? ` claude-code: ${String(res.thinned)} rule(s) already thinned, ${String(res.kept)} kept full-bodied; ${String(res.charsAfter)} chars \u2014 nothing to rewrite` : ` claude-code: thinned ${String(res.rewritten)} rule(s) to stubs, ${String(res.kept)} kept full-bodied; ${String(res.charsBefore)} -> ${String(res.charsAfter)} chars`
|
|
2807
|
+
);
|
|
2808
|
+
if (res.preserved.length > 0) {
|
|
2809
|
+
out.push(
|
|
2810
|
+
` claude-code: ${String(res.preserved.length)} rule(s) left full \u2014 you edited them and they are preserved, never overwritten (${res.preserved.join(", ")})`
|
|
2811
|
+
);
|
|
2812
|
+
}
|
|
2813
|
+
for (const f of res.failed) {
|
|
2814
|
+
out.push(` claude-code: ${f.rule}: could not write stub \u2014 ${f.reason}`);
|
|
2815
|
+
}
|
|
2816
|
+
return out;
|
|
2817
|
+
}
|
|
2818
|
+
function installReceiptBudgetLines(packageRoot, home = os5.homedir()) {
|
|
2819
|
+
try {
|
|
2820
|
+
const recorded = (() => {
|
|
2821
|
+
try {
|
|
2822
|
+
return readRecordedHashes(manifest_path(packageRoot), packageRoot);
|
|
2823
|
+
} catch {
|
|
2824
|
+
return NO_RECORDED_HASHES;
|
|
2825
|
+
}
|
|
2826
|
+
})();
|
|
2827
|
+
const layers = [];
|
|
2828
|
+
for (const host of Object.keys(GLOBAL_RULE_DIRS).sort()) {
|
|
2829
|
+
const dir = globalRuleLayerPath(host, home);
|
|
2830
|
+
if (dir === null) continue;
|
|
2831
|
+
layers.push(readLayer(host, "global", dir, recorded));
|
|
2832
|
+
}
|
|
2833
|
+
const rows = buildHostLimitRows(layers, loadHostInstructionLimits());
|
|
2834
|
+
return rows.length === 0 ? [] : renderHostLimitRows(rows).map((l) => ` ${l}`);
|
|
2835
|
+
} catch {
|
|
2836
|
+
return [];
|
|
2837
|
+
}
|
|
2838
|
+
}
|
|
2839
|
+
|
|
2840
|
+
// src/install/globalRuleScope.ts
|
|
2841
|
+
function isPlainObject2(v) {
|
|
2842
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
2843
|
+
}
|
|
2844
|
+
function resolveGlobalRuleScope(inputs) {
|
|
2845
|
+
const { packageRoot, warn: warn2 } = inputs;
|
|
2846
|
+
const settings_path = inputs.settingsPath;
|
|
2847
|
+
if (settings_path === null) {
|
|
2848
|
+
try {
|
|
2849
|
+
return ruleScopeFromSettings(inputs.loadDefaults(), packageRoot);
|
|
2850
|
+
} catch {
|
|
2851
|
+
return LEGACY_ALL;
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
2854
|
+
let text;
|
|
2855
|
+
try {
|
|
2856
|
+
text = inputs.readText(settings_path);
|
|
2857
|
+
} catch (e) {
|
|
2858
|
+
warn2(
|
|
2859
|
+
`could not read ${settings_path} (${String(e)}) \u2014 rule scoping falls back to legacy-all, so ALL rules including maintainer-only ones will be installed. Fix the file to restore scoping.`
|
|
2860
|
+
);
|
|
2861
|
+
return LEGACY_ALL;
|
|
2862
|
+
}
|
|
2863
|
+
const parsed = inputs.parseYaml(text);
|
|
2864
|
+
if (!isPlainObject2(parsed)) {
|
|
2865
|
+
warn2(
|
|
2866
|
+
`${settings_path} is not a YAML mapping \u2014 rule scoping falls back to legacy-all, so ALL rules including maintainer-only ones will be installed. Fix the file to restore scoping.`
|
|
2867
|
+
);
|
|
2868
|
+
return LEGACY_ALL;
|
|
2869
|
+
}
|
|
2870
|
+
try {
|
|
2871
|
+
return ruleScopeFromSettings(parsed, packageRoot);
|
|
2872
|
+
} catch (e) {
|
|
2873
|
+
warn2(
|
|
2874
|
+
`could not derive rule scope from ${settings_path} (${String(e)}) \u2014 falling back to legacy-all; ALL rules will be installed.`
|
|
2875
|
+
);
|
|
2876
|
+
return LEGACY_ALL;
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
|
|
2880
|
+
// src/scripts/_lib/lean_projection_mode.ts
|
|
2881
|
+
import * as path18 from "node:path";
|
|
2882
|
+
var DEFAULT_LEAN_PROJECTION_MODE = "eager-all";
|
|
2883
|
+
function normalizeLeanProjectionMode(raw) {
|
|
2884
|
+
const v = typeof raw === "string" ? raw.trim().toLowerCase() : "";
|
|
2885
|
+
if (v === "thin") return "thin";
|
|
2886
|
+
if (v === "delivery") return "delivery";
|
|
2887
|
+
return DEFAULT_LEAN_PROJECTION_MODE;
|
|
2888
|
+
}
|
|
2889
|
+
function writesThinFiles(mode) {
|
|
2890
|
+
return mode === "thin" || mode === "delivery";
|
|
2891
|
+
}
|
|
2892
|
+
var THINNABLE_HOSTS = ["claude-code", "cursor", "cline"];
|
|
2893
|
+
var DEFAULT_LEAN_PROJECTION_HOSTS = ["claude-code"];
|
|
2894
|
+
function resolveLeanProjectionHosts(raw) {
|
|
2895
|
+
const known = new Set(THINNABLE_HOSTS);
|
|
2896
|
+
if (!Array.isArray(raw) || raw.length === 0) {
|
|
2897
|
+
return { hosts: [...DEFAULT_LEAN_PROJECTION_HOSTS], dropped: [], usedDefault: true };
|
|
2898
|
+
}
|
|
2899
|
+
const hosts = [];
|
|
2900
|
+
const dropped = [];
|
|
2901
|
+
for (const entry of raw) {
|
|
2902
|
+
const id = typeof entry === "string" ? entry.trim().toLowerCase() : "";
|
|
2903
|
+
if (id === "") {
|
|
2904
|
+
dropped.push({ id: String(entry), reason: "unknown" });
|
|
2905
|
+
continue;
|
|
2906
|
+
}
|
|
2907
|
+
if (!known.has(id)) {
|
|
2908
|
+
dropped.push({ id, reason: KNOWN_NON_THINNABLE_HOSTS.has(id) ? "not-thinnable" : "unknown" });
|
|
2909
|
+
continue;
|
|
2910
|
+
}
|
|
2911
|
+
if (!hosts.includes(id)) hosts.push(id);
|
|
2912
|
+
}
|
|
2913
|
+
hosts.sort();
|
|
2914
|
+
return { hosts, dropped, usedDefault: false };
|
|
2915
|
+
}
|
|
2916
|
+
var KNOWN_NON_THINNABLE_HOSTS = /* @__PURE__ */ new Set([
|
|
2917
|
+
"claude-desktop",
|
|
2918
|
+
"augment",
|
|
2919
|
+
"copilot",
|
|
2920
|
+
"windsurf",
|
|
2921
|
+
"gemini",
|
|
2922
|
+
"codex",
|
|
2923
|
+
"cowork"
|
|
2924
|
+
]);
|
|
2925
|
+
function thinsHost(mode, hosts, hostId) {
|
|
2926
|
+
return writesThinFiles(mode) && hosts.includes(hostId);
|
|
2927
|
+
}
|
|
2928
|
+
function resolveLeanProjection(opts = {}) {
|
|
2929
|
+
const file = opts.settingsPath ?? path18.join(opts.projectRoot ?? process.cwd(), ".agent-settings.yml");
|
|
2930
|
+
const tpl = opts.packageRoot == null ? null : path18.join(opts.packageRoot, "src", "config", "agent-settings.template.yml");
|
|
2931
|
+
let lean;
|
|
2932
|
+
try {
|
|
2933
|
+
lean = load_agent_settings(
|
|
2934
|
+
tpl === null ? { project_path: file } : { project_path: file, template_path: tpl }
|
|
2935
|
+
)["lean_projection"];
|
|
2936
|
+
} catch {
|
|
2937
|
+
}
|
|
2938
|
+
const obj = typeof lean === "object" && lean !== null && !Array.isArray(lean) ? lean : {};
|
|
2939
|
+
const o = obj;
|
|
2940
|
+
return {
|
|
2941
|
+
mode: normalizeLeanProjectionMode(o["mode"] ?? ""),
|
|
2942
|
+
hosts: resolveLeanProjectionHosts(o["hosts"]),
|
|
2943
|
+
// LAZY, and the hot path is the reason. Provenance needs a SECOND,
|
|
2944
|
+
// template-isolated cascade, and only the installer reads it — the
|
|
2945
|
+
// delivery concern on `user_prompt_submit` destructures `{ mode, hosts }`
|
|
2946
|
+
// and discards this field, so computing it eagerly doubled the per-prompt
|
|
2947
|
+
// settings read for an answer nobody asked for. A getter keeps the
|
|
2948
|
+
// field's shape (`readonly modeExplicit: boolean`) and charges only the
|
|
2949
|
+
// caller that touches it.
|
|
2950
|
+
get modeExplicit() {
|
|
2951
|
+
return rawExplicitLeanProjectionMode(opts) !== "";
|
|
2952
|
+
}
|
|
2953
|
+
};
|
|
2954
|
+
}
|
|
2955
|
+
var NO_TEMPLATE_LAYER = path18.join(path18.sep, "dev", "null", "agent-config-absent-template.yml");
|
|
2956
|
+
function rawExplicitLeanProjectionMode(opts = {}) {
|
|
2957
|
+
const file = opts.settingsPath ?? path18.join(opts.projectRoot ?? process.cwd(), ".agent-settings.yml");
|
|
2958
|
+
let lean;
|
|
2959
|
+
try {
|
|
2960
|
+
lean = load_agent_settings({ project_path: file, template_path: NO_TEMPLATE_LAYER })["lean_projection"];
|
|
2961
|
+
} catch {
|
|
2962
|
+
return "";
|
|
2963
|
+
}
|
|
2964
|
+
if (typeof lean !== "object" || lean === null || Array.isArray(lean)) return "";
|
|
2965
|
+
const m = lean["mode"];
|
|
2966
|
+
return typeof m === "string" ? m.trim() : "";
|
|
2967
|
+
}
|
|
2968
|
+
function installerThinsHost(hostId, opts = {}) {
|
|
2969
|
+
const { mode, hosts, modeExplicit } = resolveLeanProjection({
|
|
2970
|
+
...opts,
|
|
2971
|
+
settingsPath: opts.settingsPath ?? NO_PROJECT_LAYER
|
|
2972
|
+
});
|
|
2973
|
+
return modeExplicit && thinsHost(mode, hosts.hosts, hostId);
|
|
2974
|
+
}
|
|
2975
|
+
var NO_PROJECT_LAYER = path18.join(
|
|
2976
|
+
path18.sep,
|
|
2977
|
+
"dev",
|
|
2978
|
+
"null",
|
|
2979
|
+
"agent-config-absent-project-settings.yml"
|
|
2980
|
+
);
|
|
2981
|
+
|
|
2038
2982
|
// src/shared/settingsSurface.ts
|
|
2039
2983
|
function unwrapRef(root) {
|
|
2040
2984
|
if (root.$ref !== void 0 && root.definitions !== void 0) {
|
|
@@ -3390,8 +4334,8 @@ var zodToJsonSchema = (schema, options) => {
|
|
|
3390
4334
|
};
|
|
3391
4335
|
|
|
3392
4336
|
// src/scripts/_lib/module_detection.ts
|
|
3393
|
-
import * as
|
|
3394
|
-
import * as
|
|
4337
|
+
import * as fs18 from "node:fs";
|
|
4338
|
+
import * as path19 from "node:path";
|
|
3395
4339
|
var _SKIP_DIRS = /* @__PURE__ */ new Set([".module-template", ".example"]);
|
|
3396
4340
|
var _RULES = [
|
|
3397
4341
|
["app/Modules", "laravel-hmvc", "App\\Modules\\{ModuleName}"],
|
|
@@ -3405,14 +4349,14 @@ var _RULES = [
|
|
|
3405
4349
|
];
|
|
3406
4350
|
function _isDir(p) {
|
|
3407
4351
|
try {
|
|
3408
|
-
return
|
|
4352
|
+
return fs18.statSync(p).isDirectory();
|
|
3409
4353
|
} catch {
|
|
3410
4354
|
return false;
|
|
3411
4355
|
}
|
|
3412
4356
|
}
|
|
3413
4357
|
function _isFile(p) {
|
|
3414
4358
|
try {
|
|
3415
|
-
return
|
|
4359
|
+
return fs18.statSync(p).isFile();
|
|
3416
4360
|
} catch {
|
|
3417
4361
|
return false;
|
|
3418
4362
|
}
|
|
@@ -3426,13 +4370,13 @@ function _isUpperChar(ch) {
|
|
|
3426
4370
|
function _list_module_subdirs(root) {
|
|
3427
4371
|
let entries;
|
|
3428
4372
|
try {
|
|
3429
|
-
entries =
|
|
4373
|
+
entries = fs18.readdirSync(root).sort();
|
|
3430
4374
|
} catch {
|
|
3431
4375
|
return [];
|
|
3432
4376
|
}
|
|
3433
4377
|
const out = [];
|
|
3434
4378
|
for (const name of entries) {
|
|
3435
|
-
if (!_isDir(
|
|
4379
|
+
if (!_isDir(path19.join(root, name))) {
|
|
3436
4380
|
continue;
|
|
3437
4381
|
}
|
|
3438
4382
|
if (name.startsWith(".")) {
|
|
@@ -3454,11 +4398,11 @@ function _score_confidence(stack, root, subdirs) {
|
|
|
3454
4398
|
return capitalized.length > 0 ? "high" : "medium";
|
|
3455
4399
|
}
|
|
3456
4400
|
if (stack === "node-monorepo") {
|
|
3457
|
-
const withPkgJson = subdirs.filter((name) => _isFile(
|
|
4401
|
+
const withPkgJson = subdirs.filter((name) => _isFile(path19.join(root, name, "package.json")));
|
|
3458
4402
|
return withPkgJson.length > 0 ? "high" : "medium";
|
|
3459
4403
|
}
|
|
3460
4404
|
if (stack === "python-src") {
|
|
3461
|
-
const withInit = subdirs.filter((name) => _isFile(
|
|
4405
|
+
const withInit = subdirs.filter((name) => _isFile(path19.join(root, name, "__init__.py")));
|
|
3462
4406
|
return withInit.length > 0 ? "high" : "medium";
|
|
3463
4407
|
}
|
|
3464
4408
|
if (stack === "go-internal") {
|
|
@@ -3470,7 +4414,7 @@ function detect_module_roots(project_root) {
|
|
|
3470
4414
|
const high = [];
|
|
3471
4415
|
const medium = [];
|
|
3472
4416
|
for (const [rel_path, stack, namespace_template] of _RULES) {
|
|
3473
|
-
const abs_path =
|
|
4417
|
+
const abs_path = path19.join(project_root, rel_path);
|
|
3474
4418
|
if (!_isDir(abs_path)) {
|
|
3475
4419
|
continue;
|
|
3476
4420
|
}
|
|
@@ -3492,7 +4436,7 @@ function detect_module_roots(project_root) {
|
|
|
3492
4436
|
}
|
|
3493
4437
|
|
|
3494
4438
|
// src/scripts/_lib/model_tier.ts
|
|
3495
|
-
import
|
|
4439
|
+
import fs19 from "node:fs";
|
|
3496
4440
|
var TIER_TO_CLAUDE_MODEL = {
|
|
3497
4441
|
frontier: "fable",
|
|
3498
4442
|
high: "opus",
|
|
@@ -3501,8 +4445,8 @@ var TIER_TO_CLAUDE_MODEL = {
|
|
|
3501
4445
|
};
|
|
3502
4446
|
var MODEL_TIER_RE = /^model_tier:\s*"?([a-z]+)"?\s*$/m;
|
|
3503
4447
|
function read_model_tier(skill_md) {
|
|
3504
|
-
if (!
|
|
3505
|
-
const text =
|
|
4448
|
+
if (!fs19.existsSync(skill_md)) return null;
|
|
4449
|
+
const text = fs19.readFileSync(skill_md).toString("utf-8");
|
|
3506
4450
|
if (!text.startsWith("---\n")) return null;
|
|
3507
4451
|
const end = text.indexOf("\n---\n", 4);
|
|
3508
4452
|
if (end === -1) return null;
|
|
@@ -3518,15 +4462,15 @@ function render_native_model_md(text, tier) {
|
|
|
3518
4462
|
}
|
|
3519
4463
|
|
|
3520
4464
|
// src/install/paths.ts
|
|
3521
|
-
import { homedir as
|
|
3522
|
-
import { join as
|
|
4465
|
+
import { homedir as homedir7, tmpdir } from "node:os";
|
|
4466
|
+
import { join as join20 } from "node:path";
|
|
3523
4467
|
var INSTALL_ROOT_SUBPATH = ".event4u/agent-config";
|
|
3524
4468
|
var INSTALL_LOG_FILENAME = "install-log.jsonl";
|
|
3525
4469
|
function resolveHome(home) {
|
|
3526
4470
|
if (home && home.length > 0) {
|
|
3527
4471
|
return home;
|
|
3528
4472
|
}
|
|
3529
|
-
const fromOs =
|
|
4473
|
+
const fromOs = homedir7();
|
|
3530
4474
|
if (!fromOs) {
|
|
3531
4475
|
throw new Error(
|
|
3532
4476
|
"Cannot resolve home directory \u2014 both $HOME (POSIX) and $USERPROFILE (Windows) are unset."
|
|
@@ -3535,14 +4479,14 @@ function resolveHome(home) {
|
|
|
3535
4479
|
return fromOs;
|
|
3536
4480
|
}
|
|
3537
4481
|
function getInstallRoot(home) {
|
|
3538
|
-
return
|
|
4482
|
+
return join20(resolveHome(home), INSTALL_ROOT_SUBPATH);
|
|
3539
4483
|
}
|
|
3540
4484
|
function getLogPath(home) {
|
|
3541
|
-
return
|
|
4485
|
+
return join20(getInstallRoot(home), INSTALL_LOG_FILENAME);
|
|
3542
4486
|
}
|
|
3543
4487
|
|
|
3544
4488
|
// src/scripts/install.ts
|
|
3545
|
-
var
|
|
4489
|
+
var _HERE2 = fileURLToPath4(import.meta.url);
|
|
3546
4490
|
var SystemExitError = class extends Error {
|
|
3547
4491
|
constructor(code) {
|
|
3548
4492
|
super(`system-exit-${code}`);
|
|
@@ -3558,43 +4502,43 @@ var ArgparseExit = class extends Error {
|
|
|
3558
4502
|
code;
|
|
3559
4503
|
};
|
|
3560
4504
|
function expanduser3(p) {
|
|
3561
|
-
if (p === "~") return
|
|
4505
|
+
if (p === "~") return os6.homedir();
|
|
3562
4506
|
if (p.startsWith("~/") || p.startsWith("~\\")) {
|
|
3563
|
-
return
|
|
4507
|
+
return path20.join(os6.homedir(), p.slice(2));
|
|
3564
4508
|
}
|
|
3565
4509
|
return p;
|
|
3566
4510
|
}
|
|
3567
4511
|
function isFile(p) {
|
|
3568
4512
|
try {
|
|
3569
|
-
return
|
|
4513
|
+
return fs20.statSync(p).isFile();
|
|
3570
4514
|
} catch {
|
|
3571
4515
|
return false;
|
|
3572
4516
|
}
|
|
3573
4517
|
}
|
|
3574
4518
|
function isDir(p) {
|
|
3575
4519
|
try {
|
|
3576
|
-
return
|
|
4520
|
+
return fs20.statSync(p).isDirectory();
|
|
3577
4521
|
} catch {
|
|
3578
4522
|
return false;
|
|
3579
4523
|
}
|
|
3580
4524
|
}
|
|
3581
4525
|
function isSymlink(p) {
|
|
3582
4526
|
try {
|
|
3583
|
-
return
|
|
4527
|
+
return fs20.lstatSync(p).isSymbolicLink();
|
|
3584
4528
|
} catch {
|
|
3585
4529
|
return false;
|
|
3586
4530
|
}
|
|
3587
4531
|
}
|
|
3588
4532
|
function readText(p) {
|
|
3589
|
-
return
|
|
4533
|
+
return fs20.readFileSync(p, "utf-8");
|
|
3590
4534
|
}
|
|
3591
4535
|
function writeText(p, content) {
|
|
3592
|
-
|
|
4536
|
+
fs20.writeFileSync(p, content, "utf-8");
|
|
3593
4537
|
}
|
|
3594
4538
|
function sortedGlobStems(directory, suffix) {
|
|
3595
4539
|
let entries;
|
|
3596
4540
|
try {
|
|
3597
|
-
entries =
|
|
4541
|
+
entries = fs20.readdirSync(directory);
|
|
3598
4542
|
} catch {
|
|
3599
4543
|
return [];
|
|
3600
4544
|
}
|
|
@@ -3614,34 +4558,34 @@ function sortedGlobStems(directory, suffix) {
|
|
|
3614
4558
|
function countZips(directory) {
|
|
3615
4559
|
if (!isDir(directory)) return 0;
|
|
3616
4560
|
let n = 0;
|
|
3617
|
-
for (const name of
|
|
4561
|
+
for (const name of fs20.readdirSync(directory)) {
|
|
3618
4562
|
if (name.endsWith(".zip")) n += 1;
|
|
3619
4563
|
}
|
|
3620
4564
|
return n;
|
|
3621
4565
|
}
|
|
3622
4566
|
function atomicWrite0644(target, body, prefix) {
|
|
3623
|
-
const dir =
|
|
3624
|
-
const tmpName =
|
|
4567
|
+
const dir = path20.dirname(target);
|
|
4568
|
+
const tmpName = path20.join(
|
|
3625
4569
|
dir,
|
|
3626
4570
|
`${prefix}${process2.pid}.${crypto5.randomBytes(6).toString("hex")}.yml.tmp`
|
|
3627
4571
|
);
|
|
3628
4572
|
let fd = null;
|
|
3629
4573
|
try {
|
|
3630
|
-
fd =
|
|
3631
|
-
|
|
3632
|
-
|
|
4574
|
+
fd = fs20.openSync(tmpName, "wx", 420);
|
|
4575
|
+
fs20.writeFileSync(fd, body, "utf-8");
|
|
4576
|
+
fs20.closeSync(fd);
|
|
3633
4577
|
fd = null;
|
|
3634
|
-
|
|
3635
|
-
|
|
4578
|
+
fs20.chmodSync(tmpName, 420);
|
|
4579
|
+
fs20.renameSync(tmpName, target);
|
|
3636
4580
|
} catch (err) {
|
|
3637
4581
|
if (fd !== null) {
|
|
3638
4582
|
try {
|
|
3639
|
-
|
|
4583
|
+
fs20.closeSync(fd);
|
|
3640
4584
|
} catch {
|
|
3641
4585
|
}
|
|
3642
4586
|
}
|
|
3643
4587
|
try {
|
|
3644
|
-
|
|
4588
|
+
fs20.unlinkSync(tmpName);
|
|
3645
4589
|
} catch {
|
|
3646
4590
|
}
|
|
3647
4591
|
throw err;
|
|
@@ -3653,14 +4597,14 @@ function utcStamp(now) {
|
|
|
3653
4597
|
return `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())}T${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}:${pad(d.getUTCSeconds())}Z`;
|
|
3654
4598
|
}
|
|
3655
4599
|
function yamlSafeLoad(text) {
|
|
3656
|
-
let
|
|
4600
|
+
let YAML3;
|
|
3657
4601
|
try {
|
|
3658
|
-
|
|
4602
|
+
YAML3 = require_dist();
|
|
3659
4603
|
} catch {
|
|
3660
4604
|
return null;
|
|
3661
4605
|
}
|
|
3662
4606
|
try {
|
|
3663
|
-
const data =
|
|
4607
|
+
const data = YAML3.parse(text, { version: "1.1" });
|
|
3664
4608
|
return data;
|
|
3665
4609
|
} catch {
|
|
3666
4610
|
return void 0;
|
|
@@ -3676,12 +4620,12 @@ var LEGACY_SETTINGS_FILE = ".agent-settings";
|
|
|
3676
4620
|
var LEGACY_BACKUP_FILE = ".agent-settings.backup.key-value";
|
|
3677
4621
|
var SETTINGS_SUBDIR = ["agents", "settings"];
|
|
3678
4622
|
function _canonical_settings_target(project_root) {
|
|
3679
|
-
return
|
|
4623
|
+
return path20.join(project_root, ...SETTINGS_SUBDIR, SETTINGS_FILE);
|
|
3680
4624
|
}
|
|
3681
4625
|
function _resolve_settings_read(project_root) {
|
|
3682
4626
|
const canonical = _canonical_settings_target(project_root);
|
|
3683
4627
|
if (pathExists(canonical)) return canonical;
|
|
3684
|
-
const legacy =
|
|
4628
|
+
const legacy = path20.join(project_root, SETTINGS_FILE);
|
|
3685
4629
|
if (pathExists(legacy)) return legacy;
|
|
3686
4630
|
return canonical;
|
|
3687
4631
|
}
|
|
@@ -3747,9 +4691,9 @@ function fail(msg) {
|
|
|
3747
4691
|
throw new SystemExitError(1);
|
|
3748
4692
|
}
|
|
3749
4693
|
function detect_package_root(project_root) {
|
|
3750
|
-
const npm_path =
|
|
4694
|
+
const npm_path = path20.join(project_root, "node_modules", "@event4u", "agent-config");
|
|
3751
4695
|
if (isDir(npm_path)) return resolvePath(npm_path);
|
|
3752
|
-
if (pathExists(
|
|
4696
|
+
if (pathExists(path20.join(project_root, "src", "config", "profiles", "minimal.ini"))) {
|
|
3753
4697
|
return project_root;
|
|
3754
4698
|
}
|
|
3755
4699
|
fail(
|
|
@@ -3757,12 +4701,12 @@ function detect_package_root(project_root) {
|
|
|
3757
4701
|
);
|
|
3758
4702
|
}
|
|
3759
4703
|
function detect_package_type(package_root) {
|
|
3760
|
-
if (package_root.split(
|
|
4704
|
+
if (package_root.split(path20.sep).includes("node_modules")) return "npm";
|
|
3761
4705
|
return "local";
|
|
3762
4706
|
}
|
|
3763
4707
|
function detect_package_type_for_project(project_root, package_root) {
|
|
3764
4708
|
const npm_path = resolvePath(
|
|
3765
|
-
|
|
4709
|
+
path20.join(project_root, "node_modules", "@event4u", "agent-config")
|
|
3766
4710
|
);
|
|
3767
4711
|
const package_resolved = resolvePath(package_root);
|
|
3768
4712
|
if (package_resolved === npm_path) return "npm";
|
|
@@ -3786,7 +4730,7 @@ function ensure_directory(p) {
|
|
|
3786
4730
|
mkdirp(p);
|
|
3787
4731
|
}
|
|
3788
4732
|
function write_file(p, content) {
|
|
3789
|
-
ensure_directory(
|
|
4733
|
+
ensure_directory(path20.dirname(p));
|
|
3790
4734
|
writeText(p, content);
|
|
3791
4735
|
}
|
|
3792
4736
|
function read_json_file(p) {
|
|
@@ -3807,50 +4751,6 @@ function write_json_file(p, data) {
|
|
|
3807
4751
|
const content = jsonDumpsIndent(data, 4) + "\n";
|
|
3808
4752
|
write_file(p, content);
|
|
3809
4753
|
}
|
|
3810
|
-
function _isPlainObject(v) {
|
|
3811
|
-
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
3812
|
-
}
|
|
3813
|
-
function deepcopy(v) {
|
|
3814
|
-
if (v === null || typeof v !== "object") return v;
|
|
3815
|
-
if (Array.isArray(v)) return v.map((x) => deepcopy(x));
|
|
3816
|
-
const out = {};
|
|
3817
|
-
for (const k of Object.keys(v)) {
|
|
3818
|
-
out[k] = deepcopy(v[k]);
|
|
3819
|
-
}
|
|
3820
|
-
return out;
|
|
3821
|
-
}
|
|
3822
|
-
function deep_merge(base, overlay) {
|
|
3823
|
-
const result = deepcopy(base);
|
|
3824
|
-
for (const key of Object.keys(overlay)) {
|
|
3825
|
-
const value = overlay[key];
|
|
3826
|
-
if (Object.prototype.hasOwnProperty.call(result, key) && _isPlainObject(result[key]) && _isPlainObject(value)) {
|
|
3827
|
-
result[key] = deep_merge(
|
|
3828
|
-
result[key],
|
|
3829
|
-
value
|
|
3830
|
-
);
|
|
3831
|
-
} else {
|
|
3832
|
-
result[key] = deepcopy(value);
|
|
3833
|
-
}
|
|
3834
|
-
}
|
|
3835
|
-
return result;
|
|
3836
|
-
}
|
|
3837
|
-
function jsonEqual(a, b) {
|
|
3838
|
-
if (a === b) return true;
|
|
3839
|
-
if (typeof a !== typeof b) return false;
|
|
3840
|
-
if (Array.isArray(a) || Array.isArray(b)) {
|
|
3841
|
-
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
|
|
3842
|
-
return a.every((v, i) => jsonEqual(v, b[i]));
|
|
3843
|
-
}
|
|
3844
|
-
if (_isPlainObject(a) && _isPlainObject(b)) {
|
|
3845
|
-
const ka = Object.keys(a);
|
|
3846
|
-
const kb = Object.keys(b);
|
|
3847
|
-
if (ka.length !== kb.length) return false;
|
|
3848
|
-
return ka.every(
|
|
3849
|
-
(k) => Object.prototype.hasOwnProperty.call(b, k) && jsonEqual(a[k], b[k])
|
|
3850
|
-
);
|
|
3851
|
-
}
|
|
3852
|
-
return false;
|
|
3853
|
-
}
|
|
3854
4754
|
function merge_json_file(p, new_data, _force, label) {
|
|
3855
4755
|
const new_entries = build_merge_entries(label, new_data);
|
|
3856
4756
|
if (!pathExists(p)) {
|
|
@@ -3859,7 +4759,7 @@ function merge_json_file(p, new_data, _force, label) {
|
|
|
3859
4759
|
return new_entries;
|
|
3860
4760
|
}
|
|
3861
4761
|
const existing = read_json_file(p);
|
|
3862
|
-
const merged =
|
|
4762
|
+
const merged = mergeHostConfig(existing, new_data, HOOK_SIGNATURES[label] ?? "", deepMerge);
|
|
3863
4763
|
if (jsonEqual(merged, existing)) {
|
|
3864
4764
|
skip(`${label} already configured`);
|
|
3865
4765
|
return new_entries;
|
|
@@ -3957,7 +4857,7 @@ function _append_unknown_legacy(rendered, legacy_values, unknown_keys) {
|
|
|
3957
4857
|
return rendered + "\n" + suffix;
|
|
3958
4858
|
}
|
|
3959
4859
|
function _migrate_legacy_if_present(project_root, template_body) {
|
|
3960
|
-
const legacy_target =
|
|
4860
|
+
const legacy_target = path20.join(project_root, LEGACY_SETTINGS_FILE);
|
|
3961
4861
|
if (!isFile(legacy_target)) return null;
|
|
3962
4862
|
const legacy_text = readText(legacy_target);
|
|
3963
4863
|
const [values, unknown] = _parse_legacy_settings(legacy_text);
|
|
@@ -3972,9 +4872,9 @@ function _migrate_legacy_if_present(project_root, template_body) {
|
|
|
3972
4872
|
}
|
|
3973
4873
|
}
|
|
3974
4874
|
rendered = _append_unknown_legacy(rendered, values, unknown);
|
|
3975
|
-
const backup_target =
|
|
4875
|
+
const backup_target = path20.join(project_root, LEGACY_BACKUP_FILE);
|
|
3976
4876
|
writeText(backup_target, legacy_text);
|
|
3977
|
-
|
|
4877
|
+
fs20.unlinkSync(legacy_target);
|
|
3978
4878
|
info(`Migrated legacy ${LEGACY_SETTINGS_FILE} \u2192 ${SETTINGS_FILE}`);
|
|
3979
4879
|
info(`Backup saved to ${LEGACY_BACKUP_FILE}`);
|
|
3980
4880
|
if (unknown.length > 0) {
|
|
@@ -4009,7 +4909,7 @@ function _render_template(template, profile_values) {
|
|
|
4009
4909
|
return body;
|
|
4010
4910
|
}
|
|
4011
4911
|
function _load_valid_user_types(package_root) {
|
|
4012
|
-
const directory =
|
|
4912
|
+
const directory = path20.join(package_root, USER_TYPES_DIR);
|
|
4013
4913
|
if (!isDir(directory)) return [];
|
|
4014
4914
|
return sortedGlobStems(directory, ".yml");
|
|
4015
4915
|
}
|
|
@@ -4066,8 +4966,8 @@ function splitlinesKeepends(text) {
|
|
|
4066
4966
|
}
|
|
4067
4967
|
function ensure_agent_settings(project_root, package_root, profile, force, user_type = "", packs = null) {
|
|
4068
4968
|
const target = _canonical_settings_target(project_root);
|
|
4069
|
-
const profile_source =
|
|
4070
|
-
const template_source =
|
|
4969
|
+
const profile_source = path20.join(package_root, "src", "config", "profiles", `${profile}.ini`);
|
|
4970
|
+
const template_source = path20.join(package_root, "src", "config", "agent-settings.template.yml");
|
|
4071
4971
|
if (!pathExists(profile_source)) fail(`Missing profile preset: ${profile_source}`);
|
|
4072
4972
|
if (!pathExists(template_source)) fail(`Missing settings template: ${template_source}`);
|
|
4073
4973
|
const template = readText(template_source);
|
|
@@ -4081,21 +4981,21 @@ function ensure_agent_settings(project_root, package_root, profile, force, user_
|
|
|
4081
4981
|
if (profile_values["rule_loading_tier"] !== profile) {
|
|
4082
4982
|
const got = "rule_loading_tier" in profile_values ? `'${profile_values["rule_loading_tier"]}'` : "None";
|
|
4083
4983
|
fail(
|
|
4084
|
-
`Profile preset ${
|
|
4984
|
+
`Profile preset ${path20.basename(profile_source)} has rule_loading_tier=${got} but --profile=${profile}`
|
|
4085
4985
|
);
|
|
4086
4986
|
}
|
|
4087
4987
|
profile_values["user_type"] = _validate_user_type(package_root, user_type);
|
|
4088
4988
|
let template_body = _render_template(template, profile_values);
|
|
4089
4989
|
template_body = _inject_packs(template_body, packs ?? []);
|
|
4090
|
-
const legacy_root =
|
|
4990
|
+
const legacy_root = path20.join(project_root, SETTINGS_FILE);
|
|
4091
4991
|
if (isFile(legacy_root) && !pathExists(target)) {
|
|
4092
|
-
mkdirp(
|
|
4992
|
+
mkdirp(path20.dirname(target));
|
|
4093
4993
|
writeText(target, readText(legacy_root));
|
|
4094
|
-
|
|
4994
|
+
fs20.unlinkSync(legacy_root);
|
|
4095
4995
|
success(`Migrated ${SETTINGS_FILE} \u2192 agents/settings/${SETTINGS_FILE} (ADR-038)`);
|
|
4096
4996
|
return;
|
|
4097
4997
|
}
|
|
4098
|
-
const legacy_target =
|
|
4998
|
+
const legacy_target = path20.join(project_root, LEGACY_SETTINGS_FILE);
|
|
4099
4999
|
if (isFile(legacy_target) && pathExists(target)) {
|
|
4100
5000
|
warn(
|
|
4101
5001
|
`Both ${SETTINGS_FILE} and legacy ${LEGACY_SETTINGS_FILE} exist. Skipping migration to avoid overwriting ${SETTINGS_FILE}. Delete one of them manually and re-run.`
|
|
@@ -4112,7 +5012,7 @@ function ensure_agent_settings(project_root, package_root, profile, force, user_
|
|
|
4112
5012
|
skip(`${SETTINGS_FILE} already exists`);
|
|
4113
5013
|
return;
|
|
4114
5014
|
}
|
|
4115
|
-
mkdirp(
|
|
5015
|
+
mkdirp(path20.dirname(target));
|
|
4116
5016
|
write_file(target, template_body);
|
|
4117
5017
|
const user_type_value = profile_values["user_type"] ?? "";
|
|
4118
5018
|
const suffix = user_type_value ? `, user_type=${user_type_value}` : "";
|
|
@@ -4125,7 +5025,7 @@ function ensure_vscode_bridge(project_root, package_type, force) {
|
|
|
4125
5025
|
const plugin_path = plugin_paths[package_type] ?? "./plugin/agent-config";
|
|
4126
5026
|
const bridge = { "chat.pluginLocations": { [plugin_path]: true } };
|
|
4127
5027
|
return merge_json_file(
|
|
4128
|
-
|
|
5028
|
+
path20.join(project_root, ".vscode", "settings.json"),
|
|
4129
5029
|
bridge,
|
|
4130
5030
|
force,
|
|
4131
5031
|
".vscode/settings.json"
|
|
@@ -4134,14 +5034,14 @@ function ensure_vscode_bridge(project_root, package_type, force) {
|
|
|
4134
5034
|
function ensure_augment_bridge(project_root, force) {
|
|
4135
5035
|
const bridge = { enabledPlugins: { "agent-config@event4u": true } };
|
|
4136
5036
|
return merge_json_file(
|
|
4137
|
-
|
|
5037
|
+
path20.join(project_root, ".augment", "settings.json"),
|
|
4138
5038
|
bridge,
|
|
4139
5039
|
force,
|
|
4140
5040
|
".augment/settings.json"
|
|
4141
5041
|
);
|
|
4142
5042
|
}
|
|
4143
|
-
var AUGMENT_USER_DIR =
|
|
4144
|
-
var AUGMENT_USER_HOOKS_DIR =
|
|
5043
|
+
var AUGMENT_USER_DIR = path20.join(os6.homedir(), ".augment");
|
|
5044
|
+
var AUGMENT_USER_HOOKS_DIR = path20.join(AUGMENT_USER_DIR, "hooks");
|
|
4145
5045
|
var AUGMENT_DISPATCHER_TRAMPOLINE = "augment-dispatcher.sh";
|
|
4146
5046
|
var AUGMENT_LEGACY_TRAMPOLINES = [
|
|
4147
5047
|
"augment-chat-history.sh",
|
|
@@ -4150,29 +5050,29 @@ var AUGMENT_LEGACY_TRAMPOLINES = [
|
|
|
4150
5050
|
"augment-context-hygiene.sh"
|
|
4151
5051
|
];
|
|
4152
5052
|
function _deploy_augment_trampoline(package_root, name, force) {
|
|
4153
|
-
const src =
|
|
5053
|
+
const src = path20.join(package_root, "scripts", "hooks", name);
|
|
4154
5054
|
if (!pathExists(src)) {
|
|
4155
5055
|
skip(`augment trampoline missing in package: ${src}`);
|
|
4156
5056
|
return null;
|
|
4157
5057
|
}
|
|
4158
5058
|
mkdirp(AUGMENT_USER_HOOKS_DIR);
|
|
4159
|
-
const dst =
|
|
5059
|
+
const dst = path20.join(AUGMENT_USER_HOOKS_DIR, name);
|
|
4160
5060
|
const src_text = readText(src);
|
|
4161
5061
|
if (pathExists(dst) && readText(dst) === src_text && !force) {
|
|
4162
5062
|
skip(`~/.augment/hooks/${name} already up to date`);
|
|
4163
5063
|
} else {
|
|
4164
5064
|
writeText(dst, src_text);
|
|
4165
|
-
|
|
5065
|
+
fs20.chmodSync(dst, 493);
|
|
4166
5066
|
success(`~/.augment/hooks/${name} installed`);
|
|
4167
5067
|
}
|
|
4168
5068
|
return dst;
|
|
4169
5069
|
}
|
|
4170
5070
|
function _remove_legacy_augment_trampolines() {
|
|
4171
5071
|
for (const name of AUGMENT_LEGACY_TRAMPOLINES) {
|
|
4172
|
-
const legacy =
|
|
5072
|
+
const legacy = path20.join(AUGMENT_USER_HOOKS_DIR, name);
|
|
4173
5073
|
try {
|
|
4174
5074
|
if (isFile(legacy)) {
|
|
4175
|
-
|
|
5075
|
+
fs20.unlinkSync(legacy);
|
|
4176
5076
|
skip(`removed legacy ~/.augment/hooks/${name}`);
|
|
4177
5077
|
}
|
|
4178
5078
|
} catch (err) {
|
|
@@ -4192,7 +5092,7 @@ function ensure_augment_user_hooks(package_root, force) {
|
|
|
4192
5092
|
}
|
|
4193
5093
|
const settings_patch = { hooks: per_event };
|
|
4194
5094
|
return merge_json_file(
|
|
4195
|
-
|
|
5095
|
+
path20.join(AUGMENT_USER_DIR, "settings.json"),
|
|
4196
5096
|
settings_patch,
|
|
4197
5097
|
force,
|
|
4198
5098
|
"~/.augment/settings.json"
|
|
@@ -4207,7 +5107,7 @@ function _heal_legacy_claude_plugin_ids(p) {
|
|
|
4207
5107
|
if (!pathExists(p)) return [];
|
|
4208
5108
|
const data = read_json_file(p);
|
|
4209
5109
|
const enabled = data["enabledPlugins"];
|
|
4210
|
-
if (!
|
|
5110
|
+
if (!isPlainObject(enabled)) return [];
|
|
4211
5111
|
const removed = CLAUDE_LEGACY_PLUGIN_IDS.filter((pid) => pid in enabled);
|
|
4212
5112
|
if (removed.length === 0) return [];
|
|
4213
5113
|
for (const pid of removed) {
|
|
@@ -4217,12 +5117,10 @@ function _heal_legacy_claude_plugin_ids(p) {
|
|
|
4217
5117
|
return removed;
|
|
4218
5118
|
}
|
|
4219
5119
|
function ensure_claude_bridge(project_root, force) {
|
|
4220
|
-
const target =
|
|
5120
|
+
const target = path20.join(project_root, ".claude", "settings.json");
|
|
4221
5121
|
const healed = _heal_legacy_claude_plugin_ids(target);
|
|
4222
|
-
for (const pid of healed) {
|
|
4223
|
-
|
|
4224
|
-
}
|
|
4225
|
-
const bridge = { enabledPlugins: { [CLAUDE_PLUGIN_ID]: true } };
|
|
5122
|
+
for (const pid of healed) success(`.claude/settings.json: removed stale plugin id \`${pid}\``);
|
|
5123
|
+
const bridge = withHostEnv({ enabledPlugins: { [CLAUDE_PLUGIN_ID]: true } }, project_root, success);
|
|
4226
5124
|
return merge_json_file(target, bridge, force || healed.length > 0, ".claude/settings.json");
|
|
4227
5125
|
}
|
|
4228
5126
|
var ensure_mcp_bridge = makeEnsureMcpBridge(merge_json_file);
|
|
@@ -4237,29 +5135,29 @@ function ensure_cursor_bridge(project_root, force) {
|
|
|
4237
5135
|
}
|
|
4238
5136
|
const bridge = { version: 1, hooks };
|
|
4239
5137
|
return merge_json_file(
|
|
4240
|
-
|
|
5138
|
+
path20.join(project_root, ".cursor", "hooks.json"),
|
|
4241
5139
|
bridge,
|
|
4242
5140
|
force,
|
|
4243
5141
|
".cursor/hooks.json"
|
|
4244
5142
|
);
|
|
4245
5143
|
}
|
|
4246
|
-
var CURSOR_USER_DIR =
|
|
4247
|
-
var CURSOR_USER_HOOKS_DIR =
|
|
5144
|
+
var CURSOR_USER_DIR = path20.join(os6.homedir(), ".cursor");
|
|
5145
|
+
var CURSOR_USER_HOOKS_DIR = path20.join(CURSOR_USER_DIR, "hooks");
|
|
4248
5146
|
var CURSOR_DISPATCHER_TRAMPOLINE = "cursor-dispatcher.sh";
|
|
4249
5147
|
function ensure_cursor_user_hooks(package_root, force) {
|
|
4250
|
-
const src =
|
|
5148
|
+
const src = path20.join(package_root, "scripts", "hooks", CURSOR_DISPATCHER_TRAMPOLINE);
|
|
4251
5149
|
if (!pathExists(src)) {
|
|
4252
5150
|
skip(`cursor trampoline missing in package: ${src}`);
|
|
4253
5151
|
return [];
|
|
4254
5152
|
}
|
|
4255
5153
|
mkdirp(CURSOR_USER_HOOKS_DIR);
|
|
4256
|
-
const dst =
|
|
5154
|
+
const dst = path20.join(CURSOR_USER_HOOKS_DIR, CURSOR_DISPATCHER_TRAMPOLINE);
|
|
4257
5155
|
const src_text = readText(src);
|
|
4258
5156
|
if (pathExists(dst) && readText(dst) === src_text && !force) {
|
|
4259
5157
|
skip(`~/.cursor/hooks/${CURSOR_DISPATCHER_TRAMPOLINE} already up to date`);
|
|
4260
5158
|
} else {
|
|
4261
5159
|
writeText(dst, src_text);
|
|
4262
|
-
|
|
5160
|
+
fs20.chmodSync(dst, 493);
|
|
4263
5161
|
success(`~/.cursor/hooks/${CURSOR_DISPATCHER_TRAMPOLINE} installed`);
|
|
4264
5162
|
}
|
|
4265
5163
|
const hooks = {};
|
|
@@ -4268,7 +5166,7 @@ function ensure_cursor_user_hooks(package_root, force) {
|
|
|
4268
5166
|
}
|
|
4269
5167
|
const settings_patch = { version: 1, hooks };
|
|
4270
5168
|
return merge_json_file(
|
|
4271
|
-
|
|
5169
|
+
path20.join(CURSOR_USER_DIR, "hooks.json"),
|
|
4272
5170
|
settings_patch,
|
|
4273
5171
|
force,
|
|
4274
5172
|
"~/.cursor/hooks.json"
|
|
@@ -4303,12 +5201,12 @@ exit 0
|
|
|
4303
5201
|
`;
|
|
4304
5202
|
}
|
|
4305
5203
|
function ensure_cline_bridge(project_root, force) {
|
|
4306
|
-
const hooks_dir =
|
|
5204
|
+
const hooks_dir = path20.join(project_root, ".clinerules", "hooks");
|
|
4307
5205
|
mkdirp(hooks_dir);
|
|
4308
5206
|
const workspace_quoted = shlexQuote(resolvePath(project_root));
|
|
4309
5207
|
let written = 0;
|
|
4310
5208
|
for (const { slot, native } of hostBindings("cline")) {
|
|
4311
|
-
const target =
|
|
5209
|
+
const target = path20.join(hooks_dir, native);
|
|
4312
5210
|
const body = clineProjectHookBody(native, slot, workspace_quoted);
|
|
4313
5211
|
if (pathExists(target) && readText(target) === body && !force) {
|
|
4314
5212
|
continue;
|
|
@@ -4318,7 +5216,7 @@ function ensure_cline_bridge(project_root, force) {
|
|
|
4318
5216
|
continue;
|
|
4319
5217
|
}
|
|
4320
5218
|
writeText(target, body);
|
|
4321
|
-
|
|
5219
|
+
fs20.chmodSync(target, 493);
|
|
4322
5220
|
written += 1;
|
|
4323
5221
|
}
|
|
4324
5222
|
if (written) {
|
|
@@ -4327,27 +5225,27 @@ function ensure_cline_bridge(project_root, force) {
|
|
|
4327
5225
|
skip(".clinerules/hooks/ already up to date");
|
|
4328
5226
|
}
|
|
4329
5227
|
}
|
|
4330
|
-
var CLINE_USER_DIR =
|
|
5228
|
+
var CLINE_USER_DIR = path20.join(os6.homedir(), "Documents", "Cline", "Hooks");
|
|
4331
5229
|
var CLINE_DISPATCHER_TRAMPOLINE = "cline-dispatcher.sh";
|
|
4332
5230
|
function ensure_cline_user_hooks(package_root, force) {
|
|
4333
|
-
const src =
|
|
5231
|
+
const src = path20.join(package_root, "scripts", "hooks", CLINE_DISPATCHER_TRAMPOLINE);
|
|
4334
5232
|
if (!pathExists(src)) {
|
|
4335
5233
|
skip(`cline trampoline missing in package: ${src}`);
|
|
4336
5234
|
return;
|
|
4337
5235
|
}
|
|
4338
5236
|
mkdirp(CLINE_USER_DIR);
|
|
4339
|
-
const trampoline =
|
|
5237
|
+
const trampoline = path20.join(CLINE_USER_DIR, CLINE_DISPATCHER_TRAMPOLINE);
|
|
4340
5238
|
const src_text = readText(src);
|
|
4341
5239
|
if (pathExists(trampoline) && readText(trampoline) === src_text && !force) {
|
|
4342
5240
|
skip(`~/Documents/Cline/Hooks/${CLINE_DISPATCHER_TRAMPOLINE} already up to date`);
|
|
4343
5241
|
} else {
|
|
4344
5242
|
writeText(trampoline, src_text);
|
|
4345
|
-
|
|
5243
|
+
fs20.chmodSync(trampoline, 493);
|
|
4346
5244
|
success(`~/Documents/Cline/Hooks/${CLINE_DISPATCHER_TRAMPOLINE} installed`);
|
|
4347
5245
|
}
|
|
4348
5246
|
const trampoline_quoted = shlexQuote(trampoline);
|
|
4349
5247
|
for (const { slot, native } of hostBindings("cline")) {
|
|
4350
|
-
const wrapper =
|
|
5248
|
+
const wrapper = path20.join(CLINE_USER_DIR, native);
|
|
4351
5249
|
const body = `#!/usr/bin/env bash
|
|
4352
5250
|
# Generated by event4u/agent-config \u2014 DO NOT EDIT.
|
|
4353
5251
|
# User-scope Cline hook for ${native} \u2192 agent-config ${slot}.
|
|
@@ -4357,7 +5255,7 @@ exec ${trampoline_quoted} ${slot} ${native}
|
|
|
4357
5255
|
continue;
|
|
4358
5256
|
}
|
|
4359
5257
|
writeText(wrapper, body);
|
|
4360
|
-
|
|
5258
|
+
fs20.chmodSync(wrapper, 493);
|
|
4361
5259
|
}
|
|
4362
5260
|
}
|
|
4363
5261
|
function _windsurf_dispatch_command(ac_event, native) {
|
|
@@ -4373,29 +5271,29 @@ function ensure_windsurf_bridge(project_root, force) {
|
|
|
4373
5271
|
}
|
|
4374
5272
|
const bridge = { hooks };
|
|
4375
5273
|
return merge_json_file(
|
|
4376
|
-
|
|
5274
|
+
path20.join(project_root, ".windsurf", "hooks.json"),
|
|
4377
5275
|
bridge,
|
|
4378
5276
|
force,
|
|
4379
5277
|
".windsurf/hooks.json"
|
|
4380
5278
|
);
|
|
4381
5279
|
}
|
|
4382
|
-
var WINDSURF_USER_DIR =
|
|
4383
|
-
var WINDSURF_USER_HOOKS_DIR =
|
|
5280
|
+
var WINDSURF_USER_DIR = path20.join(os6.homedir(), ".codeium", "windsurf");
|
|
5281
|
+
var WINDSURF_USER_HOOKS_DIR = path20.join(WINDSURF_USER_DIR, "hooks");
|
|
4384
5282
|
var WINDSURF_DISPATCHER_TRAMPOLINE = "windsurf-dispatcher.sh";
|
|
4385
5283
|
function ensure_windsurf_user_hooks(package_root, force) {
|
|
4386
|
-
const src =
|
|
5284
|
+
const src = path20.join(package_root, "scripts", "hooks", WINDSURF_DISPATCHER_TRAMPOLINE);
|
|
4387
5285
|
if (!pathExists(src)) {
|
|
4388
5286
|
skip(`windsurf trampoline missing in package: ${src}`);
|
|
4389
5287
|
return [];
|
|
4390
5288
|
}
|
|
4391
5289
|
mkdirp(WINDSURF_USER_HOOKS_DIR);
|
|
4392
|
-
const dst =
|
|
5290
|
+
const dst = path20.join(WINDSURF_USER_HOOKS_DIR, WINDSURF_DISPATCHER_TRAMPOLINE);
|
|
4393
5291
|
const src_text = readText(src);
|
|
4394
5292
|
if (pathExists(dst) && readText(dst) === src_text && !force) {
|
|
4395
5293
|
skip(`~/.codeium/windsurf/hooks/${WINDSURF_DISPATCHER_TRAMPOLINE} already up to date`);
|
|
4396
5294
|
} else {
|
|
4397
5295
|
writeText(dst, src_text);
|
|
4398
|
-
|
|
5296
|
+
fs20.chmodSync(dst, 493);
|
|
4399
5297
|
success(`~/.codeium/windsurf/hooks/${WINDSURF_DISPATCHER_TRAMPOLINE} installed`);
|
|
4400
5298
|
}
|
|
4401
5299
|
const hooks = {};
|
|
@@ -4407,7 +5305,7 @@ function ensure_windsurf_user_hooks(package_root, force) {
|
|
|
4407
5305
|
}
|
|
4408
5306
|
const settings_patch = { hooks };
|
|
4409
5307
|
return merge_json_file(
|
|
4410
|
-
|
|
5308
|
+
path20.join(WINDSURF_USER_DIR, "hooks.json"),
|
|
4411
5309
|
settings_patch,
|
|
4412
5310
|
force,
|
|
4413
5311
|
"~/.codeium/windsurf/hooks.json"
|
|
@@ -4429,43 +5327,43 @@ function _gemini_hooks_dict(command_factory) {
|
|
|
4429
5327
|
function ensure_gemini_bridge(project_root, force) {
|
|
4430
5328
|
const bridge = { hooks: _gemini_hooks_dict(_gemini_dispatch_command) };
|
|
4431
5329
|
return merge_json_file(
|
|
4432
|
-
|
|
5330
|
+
path20.join(project_root, ".gemini", "settings.json"),
|
|
4433
5331
|
bridge,
|
|
4434
5332
|
force,
|
|
4435
5333
|
".gemini/settings.json"
|
|
4436
5334
|
);
|
|
4437
5335
|
}
|
|
4438
|
-
var GEMINI_USER_DIR =
|
|
4439
|
-
var GEMINI_USER_HOOKS_DIR =
|
|
5336
|
+
var GEMINI_USER_DIR = path20.join(os6.homedir(), ".gemini");
|
|
5337
|
+
var GEMINI_USER_HOOKS_DIR = path20.join(GEMINI_USER_DIR, "hooks");
|
|
4440
5338
|
var GEMINI_DISPATCHER_TRAMPOLINE = "gemini-dispatcher.sh";
|
|
4441
5339
|
function ensure_gemini_user_hooks(package_root, force) {
|
|
4442
|
-
const src =
|
|
5340
|
+
const src = path20.join(package_root, "scripts", "hooks", GEMINI_DISPATCHER_TRAMPOLINE);
|
|
4443
5341
|
if (!pathExists(src)) {
|
|
4444
5342
|
skip(`gemini trampoline missing in package: ${src}`);
|
|
4445
5343
|
return [];
|
|
4446
5344
|
}
|
|
4447
5345
|
mkdirp(GEMINI_USER_HOOKS_DIR);
|
|
4448
|
-
const dst =
|
|
5346
|
+
const dst = path20.join(GEMINI_USER_HOOKS_DIR, GEMINI_DISPATCHER_TRAMPOLINE);
|
|
4449
5347
|
const src_text = readText(src);
|
|
4450
5348
|
if (pathExists(dst) && readText(dst) === src_text && !force) {
|
|
4451
5349
|
skip(`~/.gemini/hooks/${GEMINI_DISPATCHER_TRAMPOLINE} already up to date`);
|
|
4452
5350
|
} else {
|
|
4453
5351
|
writeText(dst, src_text);
|
|
4454
|
-
|
|
5352
|
+
fs20.chmodSync(dst, 493);
|
|
4455
5353
|
success(`~/.gemini/hooks/${GEMINI_DISPATCHER_TRAMPOLINE} installed`);
|
|
4456
5354
|
}
|
|
4457
5355
|
const settings_patch = {
|
|
4458
5356
|
hooks: _gemini_hooks_dict((ac_event, native) => `${dst} ${ac_event} ${native}`)
|
|
4459
5357
|
};
|
|
4460
5358
|
return merge_json_file(
|
|
4461
|
-
|
|
5359
|
+
path20.join(GEMINI_USER_DIR, "settings.json"),
|
|
4462
5360
|
settings_patch,
|
|
4463
5361
|
force,
|
|
4464
5362
|
"~/.gemini/settings.json"
|
|
4465
5363
|
);
|
|
4466
5364
|
}
|
|
4467
5365
|
function ensure_copilot_bridge(project_root, force) {
|
|
4468
|
-
const target =
|
|
5366
|
+
const target = path20.join(project_root, ".github", "plugin", "marketplace.json");
|
|
4469
5367
|
const bridge = {
|
|
4470
5368
|
marketplace: {
|
|
4471
5369
|
name: "event4u-agent-marketplace",
|
|
@@ -4508,7 +5406,7 @@ See \`docs/setup/per-ide/roocode.md\` for the full activation guide.
|
|
|
4508
5406
|
Run \`./agent-config --help\` for available commands.
|
|
4509
5407
|
`;
|
|
4510
5408
|
function ensure_roocode_bridge(project_root, force) {
|
|
4511
|
-
const target =
|
|
5409
|
+
const target = path20.join(project_root, ".roo", "rules", "agent-config.md");
|
|
4512
5410
|
if (pathExists(target) && !force) {
|
|
4513
5411
|
skip(".roo/rules/agent-config.md already exists");
|
|
4514
5412
|
return;
|
|
@@ -4530,7 +5428,7 @@ To wire Claude Desktop to this project's rules, run:
|
|
|
4530
5428
|
Canonical rule and skill source: \`.augment/\` (see \`AGENTS.md\`).
|
|
4531
5429
|
`;
|
|
4532
5430
|
function ensure_claude_desktop_bridge(project_root, force) {
|
|
4533
|
-
const target =
|
|
5431
|
+
const target = path20.join(project_root, ".claude-desktop", "agent-config.md");
|
|
4534
5432
|
if (pathExists(target) && !force) {
|
|
4535
5433
|
skip(".claude-desktop/agent-config.md already exists");
|
|
4536
5434
|
return;
|
|
@@ -4555,7 +5453,7 @@ Or pass \`--read .aider/agent-config.md\` on the command line.
|
|
|
4555
5453
|
Canonical rule and skill source: \`.augment/\` (see \`AGENTS.md\`).
|
|
4556
5454
|
`;
|
|
4557
5455
|
function ensure_aider_bridge(project_root, force) {
|
|
4558
|
-
const target =
|
|
5456
|
+
const target = path20.join(project_root, ".aider", "agent-config.md");
|
|
4559
5457
|
if (pathExists(target) && !force) {
|
|
4560
5458
|
skip(".aider/agent-config.md already exists");
|
|
4561
5459
|
return;
|
|
@@ -4574,7 +5472,7 @@ developers where the rules and skills live.
|
|
|
4574
5472
|
Canonical rule and skill source: \`.augment/\` (see project \`AGENTS.md\`).
|
|
4575
5473
|
`;
|
|
4576
5474
|
function ensure_codex_bridge(project_root, force) {
|
|
4577
|
-
const target =
|
|
5475
|
+
const target = path20.join(project_root, ".codex", "agent-config.md");
|
|
4578
5476
|
if (pathExists(target) && !force) {
|
|
4579
5477
|
skip(".codex/agent-config.md already exists");
|
|
4580
5478
|
return;
|
|
@@ -4592,7 +5490,7 @@ rules per session. The canonical rule and skill source lives under
|
|
|
4592
5490
|
orientation).
|
|
4593
5491
|
`;
|
|
4594
5492
|
function ensure_continue_bridge(project_root, force) {
|
|
4595
|
-
const target =
|
|
5493
|
+
const target = path20.join(project_root, ".continue", "rules", "agent-config.md");
|
|
4596
5494
|
if (pathExists(target) && !force) {
|
|
4597
5495
|
skip(".continue/rules/agent-config.md already exists");
|
|
4598
5496
|
return;
|
|
@@ -4623,7 +5521,7 @@ orientation).
|
|
|
4623
5521
|
See \`docs/setup/per-ide/kilocode.md\` for the full activation guide.
|
|
4624
5522
|
`;
|
|
4625
5523
|
function ensure_kilocode_bridge(project_root, force) {
|
|
4626
|
-
const target =
|
|
5524
|
+
const target = path20.join(project_root, ".kilocode", "rules", "agent-config.md");
|
|
4627
5525
|
if (pathExists(target) && !force) {
|
|
4628
5526
|
skip(".kilocode/rules/agent-config.md already exists");
|
|
4629
5527
|
return;
|
|
@@ -4650,7 +5548,7 @@ canonical source (or symlink it):
|
|
|
4650
5548
|
Canonical rule and skill source: \`.augment/\` (see \`AGENTS.md\`).
|
|
4651
5549
|
`;
|
|
4652
5550
|
function ensure_zed_bridge(project_root, force) {
|
|
4653
|
-
const target =
|
|
5551
|
+
const target = path20.join(project_root, ".zed", "agent-config.md");
|
|
4654
5552
|
if (pathExists(target) && !force) {
|
|
4655
5553
|
skip(".zed/agent-config.md already exists");
|
|
4656
5554
|
return;
|
|
@@ -4671,7 +5569,7 @@ rules into your JetBrains profile.
|
|
|
4671
5569
|
Canonical rule and skill source: \`.augment/\` (see \`AGENTS.md\`).
|
|
4672
5570
|
`;
|
|
4673
5571
|
function ensure_jetbrains_bridge(project_root, force) {
|
|
4674
|
-
const target =
|
|
5572
|
+
const target = path20.join(project_root, ".jetbrains", "agent-config.md");
|
|
4675
5573
|
if (pathExists(target) && !force) {
|
|
4676
5574
|
skip(".jetbrains/agent-config.md already exists");
|
|
4677
5575
|
return;
|
|
@@ -4702,7 +5600,7 @@ session. The canonical rule and skill source lives under \`.augment/\`
|
|
|
4702
5600
|
See \`docs/setup/per-ide/kiro.md\` for the full activation guide.
|
|
4703
5601
|
`;
|
|
4704
5602
|
function ensure_kiro_bridge(project_root, force) {
|
|
4705
|
-
const target =
|
|
5603
|
+
const target = path20.join(project_root, ".kiro", "steering", "agent-config.md");
|
|
4706
5604
|
if (pathExists(target) && !force) {
|
|
4707
5605
|
skip(".kiro/steering/agent-config.md already exists");
|
|
4708
5606
|
return;
|
|
@@ -4739,35 +5637,35 @@ var SMOKE_BRIDGE_PATHS = {
|
|
|
4739
5637
|
};
|
|
4740
5638
|
function dirHasEntries(p) {
|
|
4741
5639
|
try {
|
|
4742
|
-
return
|
|
5640
|
+
return fs20.readdirSync(p).length > 0;
|
|
4743
5641
|
} catch {
|
|
4744
5642
|
return false;
|
|
4745
5643
|
}
|
|
4746
5644
|
}
|
|
4747
5645
|
function _resolve_tsx_invocation(scriptPath, scriptArgs) {
|
|
4748
5646
|
const binName = process2.platform === "win32" ? "tsx.cmd" : "tsx";
|
|
4749
|
-
let dir =
|
|
5647
|
+
let dir = path20.dirname(scriptPath);
|
|
4750
5648
|
for (; ; ) {
|
|
4751
|
-
const candidate =
|
|
5649
|
+
const candidate = path20.join(dir, "node_modules", ".bin", binName);
|
|
4752
5650
|
if (isFile(candidate)) {
|
|
4753
5651
|
return { command: candidate, args: [scriptPath, ...scriptArgs] };
|
|
4754
5652
|
}
|
|
4755
|
-
const parent =
|
|
5653
|
+
const parent = path20.dirname(dir);
|
|
4756
5654
|
if (parent === dir) break;
|
|
4757
5655
|
dir = parent;
|
|
4758
5656
|
}
|
|
4759
5657
|
return { command: "npx", args: ["tsx", scriptPath, ...scriptArgs] };
|
|
4760
5658
|
}
|
|
4761
5659
|
function _smoke_test_hooks(project_root, package_root) {
|
|
4762
|
-
const dispatcher =
|
|
4763
|
-
const manifest =
|
|
5660
|
+
const dispatcher = path20.join(package_root, "scripts", "hooks", "dispatch_hook.ts");
|
|
5661
|
+
const manifest = path20.join(package_root, "scripts", "hook_manifest.yaml");
|
|
4764
5662
|
if (!isFile(dispatcher) || !isFile(manifest)) return 0;
|
|
4765
5663
|
const failed = [];
|
|
4766
5664
|
const skipped = [];
|
|
4767
5665
|
const passed = [];
|
|
4768
5666
|
for (const [platform, native] of smokeProbeEvents()) {
|
|
4769
5667
|
const rel_bridge = SMOKE_BRIDGE_PATHS[platform] ?? "";
|
|
4770
|
-
const bridge_path = rel_bridge ?
|
|
5668
|
+
const bridge_path = rel_bridge ? path20.join(project_root, rel_bridge) : null;
|
|
4771
5669
|
const bridge_present = Boolean(
|
|
4772
5670
|
bridge_path && (isFile(bridge_path) || isDir(bridge_path) && dirHasEntries(bridge_path))
|
|
4773
5671
|
);
|
|
@@ -4816,7 +5714,7 @@ function _smoke_test_hooks(project_root, package_root) {
|
|
|
4816
5714
|
failed.push(`${platform}: dispatcher did not emit JSON plan`);
|
|
4817
5715
|
continue;
|
|
4818
5716
|
}
|
|
4819
|
-
const concerns =
|
|
5717
|
+
const concerns = isPlainObject(plan) ? plan["concerns"] : void 0;
|
|
4820
5718
|
if (!Array.isArray(concerns)) {
|
|
4821
5719
|
failed.push(`${platform}: plan.concerns missing or not a list`);
|
|
4822
5720
|
continue;
|
|
@@ -4898,47 +5796,6 @@ var PROJECT_BRIDGE_MARKERS = {
|
|
|
4898
5796
|
jetbrains: ".jetbrains/agent-config.md",
|
|
4899
5797
|
kiro: ".kiro/steering/agent-config.md"
|
|
4900
5798
|
};
|
|
4901
|
-
var _CLAUDE_SKILL_BUNDLE = [
|
|
4902
|
-
["dist/agent-src/rules", "rules"],
|
|
4903
|
-
["dist/agent-src/skills", "skills"],
|
|
4904
|
-
["dist/agent-src/commands", "commands"],
|
|
4905
|
-
["dist/agent-src/personas", "personas"]
|
|
4906
|
-
];
|
|
4907
|
-
var GLOBAL_DEPLOY_SOURCES = {
|
|
4908
|
-
"claude-code": _CLAUDE_SKILL_BUNDLE,
|
|
4909
|
-
augment: [
|
|
4910
|
-
["dist/agent-src/rules", "rules"],
|
|
4911
|
-
["dist/agent-src/skills", "skills"],
|
|
4912
|
-
["dist/agent-src/commands", "commands"],
|
|
4913
|
-
["dist/agent-src/contexts", "contexts"],
|
|
4914
|
-
["dist/agent-src/personas", "personas"],
|
|
4915
|
-
["dist/agent-src/templates", "templates"]
|
|
4916
|
-
],
|
|
4917
|
-
cursor: [
|
|
4918
|
-
["dist/agent-src/rules", "rules"],
|
|
4919
|
-
["dist/agent-src/commands", "commands"],
|
|
4920
|
-
["dist/agent-src/personas", "personas"]
|
|
4921
|
-
],
|
|
4922
|
-
windsurf: [["dist/agent-src/rules", "rules"]],
|
|
4923
|
-
cline: [["dist/agent-src/rules", ""]],
|
|
4924
|
-
"gemini-cli": _CLAUDE_SKILL_BUNDLE,
|
|
4925
|
-
codex: _CLAUDE_SKILL_BUNDLE,
|
|
4926
|
-
continue: _CLAUDE_SKILL_BUNDLE,
|
|
4927
|
-
roocode: _CLAUDE_SKILL_BUNDLE,
|
|
4928
|
-
kilocode: _CLAUDE_SKILL_BUNDLE,
|
|
4929
|
-
qoder: _CLAUDE_SKILL_BUNDLE,
|
|
4930
|
-
opencode: _CLAUDE_SKILL_BUNDLE,
|
|
4931
|
-
trae: _CLAUDE_SKILL_BUNDLE,
|
|
4932
|
-
antigravity: _CLAUDE_SKILL_BUNDLE,
|
|
4933
|
-
codebuddy: _CLAUDE_SKILL_BUNDLE,
|
|
4934
|
-
droid: _CLAUDE_SKILL_BUNDLE,
|
|
4935
|
-
warp: _CLAUDE_SKILL_BUNDLE,
|
|
4936
|
-
kiro: [
|
|
4937
|
-
["dist/agent-src/rules", "rules"],
|
|
4938
|
-
["dist/agent-src/skills", "steering"],
|
|
4939
|
-
["dist/agent-src/personas", "personas"]
|
|
4940
|
-
]
|
|
4941
|
-
};
|
|
4942
5799
|
function claudeDesktopMarkerBody(lockfile, anchor, bundles_dir, bundle_count) {
|
|
4943
5800
|
return `# agent-config \u2014 Claude Desktop marker
|
|
4944
5801
|
|
|
@@ -4967,9 +5824,9 @@ To remove this marker, delete this file.
|
|
|
4967
5824
|
`;
|
|
4968
5825
|
}
|
|
4969
5826
|
var _CLAUDE_DESKTOP_BUNDLES_SUBPATH = "claude-desktop/bundles";
|
|
4970
|
-
var GLOBAL_ROOT =
|
|
4971
|
-
var GLOBAL_USER_SETTINGS_PATH =
|
|
4972
|
-
var GLOBAL_AGENT_SETTINGS_PATH =
|
|
5827
|
+
var GLOBAL_ROOT = path20.join(os6.homedir(), ".event4u", "agent-config");
|
|
5828
|
+
var GLOBAL_USER_SETTINGS_PATH = path20.join(GLOBAL_ROOT, ".agent-user.yml");
|
|
5829
|
+
var GLOBAL_AGENT_SETTINGS_PATH = path20.join(GLOBAL_ROOT, ".agent-settings.yml");
|
|
4973
5830
|
function _bridge_marker(tool_id, scope) {
|
|
4974
5831
|
if (scope === "global") return USER_SCOPE_PATHS[tool_id] ?? "";
|
|
4975
5832
|
return PROJECT_BRIDGE_MARKERS[tool_id] ?? "";
|
|
@@ -5015,10 +5872,10 @@ function _load_yaml_doc(p) {
|
|
|
5015
5872
|
return {};
|
|
5016
5873
|
}
|
|
5017
5874
|
const data = yamlSafeLoad(text);
|
|
5018
|
-
return
|
|
5875
|
+
return isPlainObject(data) ? data : {};
|
|
5019
5876
|
}
|
|
5020
5877
|
function _load_default_settings(package_root) {
|
|
5021
|
-
const template_source =
|
|
5878
|
+
const template_source = path20.join(package_root, "src", "config", "agent-settings.template.yml");
|
|
5022
5879
|
if (!pathExists(template_source)) return {};
|
|
5023
5880
|
let text;
|
|
5024
5881
|
try {
|
|
@@ -5028,15 +5885,15 @@ function _load_default_settings(package_root) {
|
|
|
5028
5885
|
}
|
|
5029
5886
|
const rendered = text.split(RULE_LOADING_TIER_PLACEHOLDER).join(DEFAULT_PROFILE).split(USER_TYPE_PLACEHOLDER).join("");
|
|
5030
5887
|
const data = yamlSafeLoad(rendered);
|
|
5031
|
-
return
|
|
5888
|
+
return isPlainObject(data) ? data : {};
|
|
5032
5889
|
}
|
|
5033
5890
|
var RULE_LAYER_CHOICES = ["global", "project", "both-acknowledged"];
|
|
5034
5891
|
function _suppress_rule_layer(project_root, suppress_dir) {
|
|
5035
|
-
const target =
|
|
5892
|
+
const target = path20.join(project_root, ".claude", "settings.local.json");
|
|
5036
5893
|
const existing = pathExists(target) ? read_json_file(target) : {};
|
|
5037
5894
|
let real_dir = suppress_dir;
|
|
5038
5895
|
try {
|
|
5039
|
-
real_dir =
|
|
5896
|
+
real_dir = fs20.realpathSync(suppress_dir);
|
|
5040
5897
|
} catch {
|
|
5041
5898
|
real_dir = suppress_dir;
|
|
5042
5899
|
}
|
|
@@ -5047,8 +5904,7 @@ function _suppress_rule_layer(project_root, suppress_dir) {
|
|
|
5047
5904
|
success(`.claude/settings.local.json: claudeMdExcludes += ${entry}`);
|
|
5048
5905
|
}
|
|
5049
5906
|
function _gate_rule_layer_overlap(project_root, layer, dry_run) {
|
|
5050
|
-
const global_dir =
|
|
5051
|
-
const project_dir = path12.join(project_root, ".claude", "rules");
|
|
5907
|
+
const [global_dir, project_dir] = hostRuleLayerDirs(project_root);
|
|
5052
5908
|
const g = readRuleLayer(global_dir);
|
|
5053
5909
|
const p = readRuleLayer(project_dir);
|
|
5054
5910
|
if (g === null || p === null) return true;
|
|
@@ -5136,9 +5992,9 @@ function detect_scope(cwd) {
|
|
|
5136
5992
|
if (pathExists(_resolve_settings_read(cwd))) {
|
|
5137
5993
|
return ["project", `existing ${SETTINGS_FILE}`];
|
|
5138
5994
|
}
|
|
5139
|
-
const has_manifest = SCOPE_DETECT_MANIFESTS.find((m) => pathExists(
|
|
5140
|
-
const has_ai_dir = SCOPE_DETECT_AI_DIRS.find((d) => isDir(
|
|
5141
|
-
const has_ai_file = SCOPE_DETECT_AI_FILES.find((f) => pathExists(
|
|
5995
|
+
const has_manifest = SCOPE_DETECT_MANIFESTS.find((m) => pathExists(path20.join(cwd, m))) ?? null;
|
|
5996
|
+
const has_ai_dir = SCOPE_DETECT_AI_DIRS.find((d) => isDir(path20.join(cwd, d))) ?? null;
|
|
5997
|
+
const has_ai_file = SCOPE_DETECT_AI_FILES.find((f) => pathExists(path20.join(cwd, f))) ?? null;
|
|
5142
5998
|
if (has_manifest && (has_ai_dir || has_ai_file)) {
|
|
5143
5999
|
const marker = has_ai_dir || has_ai_file;
|
|
5144
6000
|
return ["prompt", `manifest (${has_manifest}) + AI-tool config (${marker})`];
|
|
@@ -5159,7 +6015,7 @@ function readLineSyncRaw(promptText) {
|
|
|
5159
6015
|
for (; ; ) {
|
|
5160
6016
|
let n;
|
|
5161
6017
|
try {
|
|
5162
|
-
n =
|
|
6018
|
+
n = fs20.readSync(0, buf, 0, 1, null);
|
|
5163
6019
|
} catch (err) {
|
|
5164
6020
|
const code = err.code;
|
|
5165
6021
|
if (code === "EAGAIN") {
|
|
@@ -5242,26 +6098,26 @@ function _update_installed_tools_manifest(project_root, tools, scope, force, fil
|
|
|
5242
6098
|
}
|
|
5243
6099
|
write_manifest(target, version, entries);
|
|
5244
6100
|
if (!state.QUIET) {
|
|
5245
|
-
const rel = isRelativeTo(target, project_root) ?
|
|
6101
|
+
const rel = isRelativeTo(target, project_root) ? path20.relative(project_root, target) : target;
|
|
5246
6102
|
info(`Manifest updated: ${rel}`);
|
|
5247
6103
|
}
|
|
5248
6104
|
return 0;
|
|
5249
6105
|
}
|
|
5250
6106
|
function isRelativeTo(child, parent) {
|
|
5251
|
-
const rel =
|
|
5252
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
6107
|
+
const rel = path20.relative(parent, child);
|
|
6108
|
+
return rel === "" || !rel.startsWith("..") && !path20.isAbsolute(rel);
|
|
5253
6109
|
}
|
|
5254
6110
|
function _resolve_package_root_for_global() {
|
|
5255
|
-
const here = resolvePath(
|
|
5256
|
-
const candidate =
|
|
5257
|
-
if (!pathExists(
|
|
6111
|
+
const here = resolvePath(_HERE2);
|
|
6112
|
+
const candidate = path20.dirname(path20.dirname(path20.dirname(here)));
|
|
6113
|
+
if (!pathExists(path20.join(candidate, "src", "config", "profiles", "minimal.ini"))) {
|
|
5258
6114
|
fail(
|
|
5259
6115
|
`Could not locate agent-config package root from ${here}. Expected src/config/profiles/minimal.ini at the parent directory.`
|
|
5260
6116
|
);
|
|
5261
6117
|
}
|
|
5262
6118
|
return candidate;
|
|
5263
6119
|
}
|
|
5264
|
-
var CONSUMER_BRIDGE_MARKER_RELPATH =
|
|
6120
|
+
var CONSUMER_BRIDGE_MARKER_RELPATH = path20.join("agents", ".event4u-bridge.yml");
|
|
5265
6121
|
var MIGRATE_LEGACY_YAML_FILES = [".agent-settings.yml", ".agent-user.yml"];
|
|
5266
6122
|
var MIGRATE_LEGACY_TOOL_DIRS = [".augment", ".claude", ".cursor"];
|
|
5267
6123
|
var AGENT_CONFIG_PACKAGE_NAME = "@event4u/agent-config";
|
|
@@ -5269,7 +6125,7 @@ function _is_agent_config_source_repo(project_root) {
|
|
|
5269
6125
|
if (process2.env["AGENT_CONFIG_CONSUMER_MODE"] === "1") {
|
|
5270
6126
|
return [false, "consumer-mode-override"];
|
|
5271
6127
|
}
|
|
5272
|
-
const pkg_json =
|
|
6128
|
+
const pkg_json = path20.join(project_root, "package.json");
|
|
5273
6129
|
if (isFile(pkg_json)) {
|
|
5274
6130
|
let data = {};
|
|
5275
6131
|
try {
|
|
@@ -5277,17 +6133,17 @@ function _is_agent_config_source_repo(project_root) {
|
|
|
5277
6133
|
} catch {
|
|
5278
6134
|
data = {};
|
|
5279
6135
|
}
|
|
5280
|
-
if (
|
|
6136
|
+
if (isPlainObject(data) && data["name"] === AGENT_CONFIG_PACKAGE_NAME) {
|
|
5281
6137
|
return [true, "package.json:name"];
|
|
5282
6138
|
}
|
|
5283
6139
|
}
|
|
5284
|
-
if (isDir(
|
|
6140
|
+
if (isDir(path20.join(project_root, ".agent-src.uncondensed"))) {
|
|
5285
6141
|
return [true, ".agent-src.uncondensed/"];
|
|
5286
6142
|
}
|
|
5287
|
-
const packages_dir =
|
|
6143
|
+
const packages_dir = path20.join(project_root, "packages");
|
|
5288
6144
|
if (isDir(packages_dir)) {
|
|
5289
|
-
for (const child of
|
|
5290
|
-
if (isDir(
|
|
6145
|
+
for (const child of fs20.readdirSync(packages_dir)) {
|
|
6146
|
+
if (isDir(path20.join(packages_dir, child, ".agent-src.uncondensed"))) {
|
|
5291
6147
|
return [true, `packages/${child}/.agent-src.uncondensed/`];
|
|
5292
6148
|
}
|
|
5293
6149
|
}
|
|
@@ -5305,17 +6161,17 @@ function _detect_legacy_for_migration(project_root) {
|
|
|
5305
6161
|
}
|
|
5306
6162
|
return [];
|
|
5307
6163
|
}
|
|
5308
|
-
if (isFile(
|
|
6164
|
+
if (isFile(path20.join(project_root, INSTALL_MODE_MARKER_REL))) return [];
|
|
5309
6165
|
const found = [];
|
|
5310
6166
|
for (const name of MIGRATE_LEGACY_YAML_FILES) {
|
|
5311
|
-
if (isFile(
|
|
6167
|
+
if (isFile(path20.join(project_root, name))) {
|
|
5312
6168
|
found.push(name);
|
|
5313
|
-
} else if (isFile(
|
|
6169
|
+
} else if (isFile(path20.join(project_root, "settings", name))) {
|
|
5314
6170
|
found.push(`settings/${name}`);
|
|
5315
6171
|
}
|
|
5316
6172
|
}
|
|
5317
6173
|
for (const name of MIGRATE_LEGACY_TOOL_DIRS) {
|
|
5318
|
-
const p =
|
|
6174
|
+
const p = path20.join(project_root, name);
|
|
5319
6175
|
if (isDir(p) && !isSymlink(p)) {
|
|
5320
6176
|
found.push(`${name}/`);
|
|
5321
6177
|
}
|
|
@@ -5327,7 +6183,7 @@ function _prompt_migrate_to_global(project_root, artefacts) {
|
|
|
5327
6183
|
process2.stdout.write("\n");
|
|
5328
6184
|
warn("Legacy project-local artefacts detected \u2014 pre-ADR-020 layout:");
|
|
5329
6185
|
for (const rel of artefacts) {
|
|
5330
|
-
info(` ${
|
|
6186
|
+
info(` ${path20.join(project_root, rel)}`);
|
|
5331
6187
|
}
|
|
5332
6188
|
info("The unified `agent-config migrate` sweeps these in one pass.");
|
|
5333
6189
|
info("The wizard recreates fresh config afterwards.");
|
|
@@ -5356,22 +6212,22 @@ function _run_migrate_to_global(project_root) {
|
|
|
5356
6212
|
}
|
|
5357
6213
|
}
|
|
5358
6214
|
function _format_global_root_for_marker(global_root) {
|
|
5359
|
-
const home = resolvePath(
|
|
6215
|
+
const home = resolvePath(os6.homedir());
|
|
5360
6216
|
const resolved = resolvePath(global_root);
|
|
5361
|
-
const rel =
|
|
5362
|
-
if (rel === "" || rel.startsWith("..") ||
|
|
6217
|
+
const rel = path20.relative(home, resolved);
|
|
6218
|
+
if (rel === "" || rel.startsWith("..") || path20.isAbsolute(rel)) {
|
|
5363
6219
|
return global_root;
|
|
5364
6220
|
}
|
|
5365
|
-
return `~/${rel.split(
|
|
6221
|
+
return `~/${rel.split(path20.sep).join("/")}`;
|
|
5366
6222
|
}
|
|
5367
6223
|
function _remove_legacy_consumer_bridge_marker(project_root, env = null) {
|
|
5368
6224
|
const env_map = env ?? process2.env;
|
|
5369
6225
|
if (env_map["AGENT_CONFIG_DEV_MODE"] === "1") return null;
|
|
5370
|
-
if (isDir(
|
|
5371
|
-
const target =
|
|
6226
|
+
if (isDir(path20.join(project_root, ".agent-src.uncondensed"))) return null;
|
|
6227
|
+
const target = path20.join(project_root, CONSUMER_BRIDGE_MARKER_RELPATH);
|
|
5372
6228
|
if (!isFile(target)) return null;
|
|
5373
6229
|
try {
|
|
5374
|
-
|
|
6230
|
+
fs20.rmSync(target);
|
|
5375
6231
|
} catch {
|
|
5376
6232
|
return null;
|
|
5377
6233
|
}
|
|
@@ -5385,7 +6241,7 @@ var PROJECT_ANCHOR_TOOLS = {
|
|
|
5385
6241
|
function _write_per_tool_project_anchors(project_root, tools, env = null, now = null) {
|
|
5386
6242
|
const env_map = env ?? process2.env;
|
|
5387
6243
|
if (env_map["AGENT_CONFIG_DEV_MODE"] === "1") return [];
|
|
5388
|
-
if (isDir(
|
|
6244
|
+
if (isDir(path20.join(project_root, ".agent-src.uncondensed"))) return [];
|
|
5389
6245
|
const global_root_str = _format_global_root_for_marker(
|
|
5390
6246
|
event4u_root(env_map)
|
|
5391
6247
|
);
|
|
@@ -5394,8 +6250,8 @@ function _write_per_tool_project_anchors(project_root, tools, env = null, now =
|
|
|
5394
6250
|
for (const tool_id of Object.keys(PROJECT_ANCHOR_TOOLS).sort()) {
|
|
5395
6251
|
const rel_path = PROJECT_ANCHOR_TOOLS[tool_id];
|
|
5396
6252
|
if (!tools.has(tool_id)) continue;
|
|
5397
|
-
const target =
|
|
5398
|
-
mkdirp(
|
|
6253
|
+
const target = path20.join(project_root, rel_path);
|
|
6254
|
+
mkdirp(path20.dirname(target));
|
|
5399
6255
|
const body = `# event4u/agent-config \u2014 per-tool project anchor (auto-written).
|
|
5400
6256
|
# Spec: docs/contracts/consumer-bridge.md \xA7 Per-tool anchor strategy.
|
|
5401
6257
|
# Tool: ${tool_id}. Resolves the global install directly \u2014 no
|
|
@@ -5413,7 +6269,7 @@ installed_at: ${stamp}
|
|
|
5413
6269
|
}
|
|
5414
6270
|
var PACKAGE_TAG_ID = "event4u/agent-config";
|
|
5415
6271
|
function _inject_package_tag(target, source, package_root) {
|
|
5416
|
-
if (
|
|
6272
|
+
if (path20.extname(target) !== ".md") return;
|
|
5417
6273
|
let text;
|
|
5418
6274
|
try {
|
|
5419
6275
|
text = readText(target);
|
|
@@ -5441,8 +6297,8 @@ function _inject_package_tag(target, source, package_root) {
|
|
|
5441
6297
|
resolved_src = source;
|
|
5442
6298
|
}
|
|
5443
6299
|
if (package_root !== null) {
|
|
5444
|
-
const rel =
|
|
5445
|
-
if (rel !== "" && !rel.startsWith("..") && !
|
|
6300
|
+
const rel = path20.relative(resolvePath(package_root), resolved_src);
|
|
6301
|
+
if (rel !== "" && !rel.startsWith("..") && !path20.isAbsolute(rel)) {
|
|
5446
6302
|
source_value = rel;
|
|
5447
6303
|
} else {
|
|
5448
6304
|
source_value = resolved_src;
|
|
@@ -5477,7 +6333,7 @@ function _escapes_package_root(resolved, package_root) {
|
|
|
5477
6333
|
if (package_root === null) return false;
|
|
5478
6334
|
let root;
|
|
5479
6335
|
try {
|
|
5480
|
-
root =
|
|
6336
|
+
root = fs20.realpathSync(package_root);
|
|
5481
6337
|
} catch {
|
|
5482
6338
|
return false;
|
|
5483
6339
|
}
|
|
@@ -5503,7 +6359,7 @@ function _copy_dir_dereferencing_symlinks(src, dest, force, package_root = null,
|
|
|
5503
6359
|
if (file_filter !== null && !file_filter(src)) return [0, 0, written_paths];
|
|
5504
6360
|
let resolved_src = src;
|
|
5505
6361
|
try {
|
|
5506
|
-
resolved_src =
|
|
6362
|
+
resolved_src = fs20.realpathSync(src);
|
|
5507
6363
|
} catch {
|
|
5508
6364
|
resolved_src = src;
|
|
5509
6365
|
}
|
|
@@ -5511,14 +6367,14 @@ function _copy_dir_dereferencing_symlinks(src, dest, force, package_root = null,
|
|
|
5511
6367
|
warn(`refused: ${src} dereferences outside the package root \u2014 not copied`);
|
|
5512
6368
|
return [0, 0, written_paths];
|
|
5513
6369
|
}
|
|
5514
|
-
mkdirp(
|
|
6370
|
+
mkdirp(path20.dirname(dest));
|
|
5515
6371
|
const decision = tracker.resolve(dest, force);
|
|
5516
6372
|
if (decision === "preserve") {
|
|
5517
6373
|
tracker.preserve(dest, resolved_src, package_root);
|
|
5518
6374
|
_log_tx_entry("skip", dest);
|
|
5519
6375
|
return [0, 1, written_paths];
|
|
5520
6376
|
}
|
|
5521
|
-
|
|
6377
|
+
fs20.copyFileSync(src, dest);
|
|
5522
6378
|
_inject_package_tag(dest, src, package_root);
|
|
5523
6379
|
_log_tx_entry("write", dest);
|
|
5524
6380
|
written_paths.push(dest);
|
|
@@ -5527,11 +6383,11 @@ function _copy_dir_dereferencing_symlinks(src, dest, force, package_root = null,
|
|
|
5527
6383
|
mkdirp(dest);
|
|
5528
6384
|
const walk = (node) => {
|
|
5529
6385
|
const acc = [];
|
|
5530
|
-
const names =
|
|
6386
|
+
const names = fs20.readdirSync(node).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
5531
6387
|
for (const name of names) {
|
|
5532
|
-
const entry =
|
|
6388
|
+
const entry = path20.join(node, name);
|
|
5533
6389
|
acc.push(entry);
|
|
5534
|
-
const lst =
|
|
6390
|
+
const lst = fs20.lstatSync(entry);
|
|
5535
6391
|
if (lst.isDirectory() && !lst.isSymbolicLink()) {
|
|
5536
6392
|
acc.push(...walk(entry));
|
|
5537
6393
|
}
|
|
@@ -5539,9 +6395,9 @@ function _copy_dir_dereferencing_symlinks(src, dest, force, package_root = null,
|
|
|
5539
6395
|
return acc;
|
|
5540
6396
|
};
|
|
5541
6397
|
for (const entry of walk(src)) {
|
|
5542
|
-
const rel =
|
|
5543
|
-
const target =
|
|
5544
|
-
const lst =
|
|
6398
|
+
const rel = path20.relative(src, entry);
|
|
6399
|
+
const target = path20.join(dest, rel);
|
|
6400
|
+
const lst = fs20.lstatSync(entry);
|
|
5545
6401
|
if (lst.isDirectory() && !lst.isSymbolicLink()) {
|
|
5546
6402
|
mkdirp(target);
|
|
5547
6403
|
continue;
|
|
@@ -5549,8 +6405,8 @@ function _copy_dir_dereferencing_symlinks(src, dest, force, package_root = null,
|
|
|
5549
6405
|
let resolvedIsDir = false;
|
|
5550
6406
|
let resolved = entry;
|
|
5551
6407
|
try {
|
|
5552
|
-
resolved =
|
|
5553
|
-
resolvedIsDir =
|
|
6408
|
+
resolved = fs20.realpathSync(entry);
|
|
6409
|
+
resolvedIsDir = fs20.statSync(entry).isDirectory();
|
|
5554
6410
|
} catch {
|
|
5555
6411
|
resolvedIsDir = false;
|
|
5556
6412
|
}
|
|
@@ -5582,8 +6438,8 @@ function _copy_dir_dereferencing_symlinks(src, dest, force, package_root = null,
|
|
|
5582
6438
|
_log_tx_entry("skip", target);
|
|
5583
6439
|
continue;
|
|
5584
6440
|
}
|
|
5585
|
-
mkdirp(
|
|
5586
|
-
|
|
6441
|
+
mkdirp(path20.dirname(target));
|
|
6442
|
+
fs20.copyFileSync(resolved, target);
|
|
5587
6443
|
_inject_package_tag(target, resolved, package_root);
|
|
5588
6444
|
_log_tx_entry("write", target);
|
|
5589
6445
|
written += 1;
|
|
@@ -5596,7 +6452,7 @@ function _claude_desktop_bundles_dir() {
|
|
|
5596
6452
|
}
|
|
5597
6453
|
function _write_claude_desktop_marker(force, lockfile_path2, bundles_dir, bundle_count) {
|
|
5598
6454
|
const anchor = expanduser3(USER_SCOPE_PATHS["claude-desktop"]);
|
|
5599
|
-
const target =
|
|
6455
|
+
const target = path20.join(anchor, "agent-config.md");
|
|
5600
6456
|
mkdirp(anchor);
|
|
5601
6457
|
const body = claudeDesktopMarkerBody(lockfile_path2, anchor, bundles_dir, bundle_count);
|
|
5602
6458
|
if (tracker.resolve(target, force) === "preserve") {
|
|
@@ -5621,27 +6477,15 @@ function _deploy_claude_desktop(force, package_root, lockfile_path2) {
|
|
|
5621
6477
|
return [bundle_count, 0, "deployed", [bundles_dir, ...marker_paths]];
|
|
5622
6478
|
}
|
|
5623
6479
|
var _CLAUDE_FLAT_WRAPPER_EXTRA = /* @__PURE__ */ new Set(["commit"]);
|
|
5624
|
-
function _apply_claude_flat_command_wrappers(anchor, package_root, current_files) {
|
|
6480
|
+
function _apply_claude_flat_command_wrappers(anchor, package_root, current_files, recorded_files = /* @__PURE__ */ new Set()) {
|
|
5625
6481
|
const wrapped = [];
|
|
5626
6482
|
const collisions = [];
|
|
5627
|
-
const
|
|
5628
|
-
const
|
|
5629
|
-
let flat_entries = [];
|
|
5630
|
-
try {
|
|
5631
|
-
flat_entries = fs14.readdirSync(commands_dir).filter((f) => f.endsWith(".md"));
|
|
5632
|
-
} catch {
|
|
5633
|
-
}
|
|
5634
|
-
for (const fname of flat_entries.sort()) {
|
|
5635
|
-
const slug = fname.slice(0, -".md".length);
|
|
5636
|
-
if (!is_claude_builtin_name(slug)) continue;
|
|
5637
|
-
fs14.rmSync(path12.join(commands_dir, fname), { force: true });
|
|
5638
|
-
current_files.delete(`commands/${fname}`);
|
|
5639
|
-
reserved.push(slug);
|
|
5640
|
-
}
|
|
6483
|
+
const commands_dir = path20.join(anchor, "commands");
|
|
6484
|
+
const { reserved, foreign } = sweepReservedNames(commands_dir, current_files, is_claude_builtin_name, recorded_files);
|
|
5641
6485
|
const eligible = new Set(_CLAUDE_FLAT_WRAPPER_EXTRA);
|
|
5642
6486
|
try {
|
|
5643
6487
|
const manifest = JSON.parse(
|
|
5644
|
-
|
|
6488
|
+
fs20.readFileSync(path20.join(package_root, "dist", "discovery", "discovery-manifest.json"), "utf8")
|
|
5645
6489
|
);
|
|
5646
6490
|
for (const a of manifest.artefacts ?? []) {
|
|
5647
6491
|
if (a.category !== "command" || typeof a.slug !== "string") continue;
|
|
@@ -5652,27 +6496,27 @@ function _apply_claude_flat_command_wrappers(anchor, package_root, current_files
|
|
|
5652
6496
|
}
|
|
5653
6497
|
for (const slug of [...eligible].sort()) {
|
|
5654
6498
|
const flat_rel = `commands/${slug}.md`;
|
|
5655
|
-
const flat_abs =
|
|
5656
|
-
if (!
|
|
5657
|
-
const skill_dir =
|
|
5658
|
-
if (
|
|
6499
|
+
const flat_abs = path20.join(anchor, "commands", `${slug}.md`);
|
|
6500
|
+
if (!fs20.existsSync(flat_abs)) continue;
|
|
6501
|
+
const skill_dir = path20.join(anchor, "skills", slug);
|
|
6502
|
+
if (fs20.existsSync(skill_dir)) {
|
|
5659
6503
|
collisions.push(slug);
|
|
5660
6504
|
continue;
|
|
5661
6505
|
}
|
|
5662
|
-
let body =
|
|
6506
|
+
let body = fs20.readFileSync(flat_abs, "utf8");
|
|
5663
6507
|
if (body.startsWith("---\n") && !/^name:/m.test(body.split("\n---")[0] ?? "")) {
|
|
5664
6508
|
body = body.replace("---\n", `---
|
|
5665
6509
|
name: ${slug}
|
|
5666
6510
|
`);
|
|
5667
6511
|
}
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
6512
|
+
fs20.mkdirSync(skill_dir, { recursive: true });
|
|
6513
|
+
fs20.writeFileSync(path20.join(skill_dir, "SKILL.md"), body, "utf8");
|
|
6514
|
+
fs20.rmSync(flat_abs, { force: true });
|
|
5671
6515
|
current_files.delete(flat_rel);
|
|
5672
6516
|
current_files.add(`skills/${slug}/SKILL.md`);
|
|
5673
6517
|
wrapped.push(slug);
|
|
5674
6518
|
}
|
|
5675
|
-
return { wrapped, collisions, reserved };
|
|
6519
|
+
return { wrapped, collisions, reserved, foreign };
|
|
5676
6520
|
}
|
|
5677
6521
|
function _deploy_global_content(tools, force, package_root, lockfile_path2) {
|
|
5678
6522
|
const results = {};
|
|
@@ -5699,8 +6543,8 @@ function _deploy_global_content(tools, force, package_root, lockfile_path2) {
|
|
|
5699
6543
|
const written_paths = [];
|
|
5700
6544
|
let current_files = /* @__PURE__ */ new Set();
|
|
5701
6545
|
for (const [src_rel, dest_sub] of plan) {
|
|
5702
|
-
const src =
|
|
5703
|
-
const dest = dest_sub ?
|
|
6546
|
+
const src = path20.join(package_root, src_rel);
|
|
6547
|
+
const dest = dest_sub ? path20.join(anchor, dest_sub) : anchor;
|
|
5704
6548
|
const rule_filter = _rule_filter_for_source(src_rel, rule_scope);
|
|
5705
6549
|
const [w, s, paths] = _copy_dir_dereferencing_symlinks(
|
|
5706
6550
|
src,
|
|
@@ -5722,15 +6566,31 @@ function _deploy_global_content(tools, force, package_root, lockfile_path2) {
|
|
|
5722
6566
|
);
|
|
5723
6567
|
}
|
|
5724
6568
|
if (tool_id === "claude-code") {
|
|
5725
|
-
const res = _apply_claude_flat_command_wrappers(anchor, package_root, current_files);
|
|
6569
|
+
const res = _apply_claude_flat_command_wrappers(anchor, package_root, current_files, recorded_rel_files(tool_id, anchor));
|
|
6570
|
+
const preserved_now = new Set(
|
|
6571
|
+
tracker.conflictState.preserved.map((p) => path20.resolve(p))
|
|
6572
|
+
);
|
|
5726
6573
|
rewriteAndReport(
|
|
5727
|
-
|
|
6574
|
+
path20.join(anchor, "rules"),
|
|
5728
6575
|
state.QUIET,
|
|
5729
6576
|
info,
|
|
5730
6577
|
warn,
|
|
5731
6578
|
res,
|
|
5732
|
-
|
|
6579
|
+
preserved_now
|
|
5733
6580
|
);
|
|
6581
|
+
if (installerThinsHost(tool_id, { packageRoot: package_root })) {
|
|
6582
|
+
try {
|
|
6583
|
+
const thin = thinInstalledRuleLayer({
|
|
6584
|
+
rulesDir: path20.join(anchor, "rules"),
|
|
6585
|
+
packageRoot: package_root,
|
|
6586
|
+
preserved: preserved_now
|
|
6587
|
+
});
|
|
6588
|
+
if (!state.QUIET) for (const l of describeThinInstalledLayer(thin)) info(l);
|
|
6589
|
+
} catch (e) {
|
|
6590
|
+
warn(`claude-code: thinned rule layer not written \u2014 ${String(e)}`);
|
|
6591
|
+
}
|
|
6592
|
+
}
|
|
6593
|
+
if (!state.QUIET) for (const l of installReceiptBudgetLines(package_root)) info(l);
|
|
5734
6594
|
}
|
|
5735
6595
|
const missing_targets = _verify_deploy_targets(anchor, plan);
|
|
5736
6596
|
if (missing_targets.length > 0) {
|
|
@@ -5772,10 +6632,10 @@ function _deploy_global_content(tools, force, package_root, lockfile_path2) {
|
|
|
5772
6632
|
results[tool_id] = [written_total, skipped_total, "deployed", written_paths];
|
|
5773
6633
|
if (tool_id === "claude-code") {
|
|
5774
6634
|
try {
|
|
5775
|
-
const manifest =
|
|
6635
|
+
const manifest = path20.join(package_root, "src", "scripts", "hook_manifest.yaml");
|
|
5776
6636
|
const matrix = build_claude_hook_matrix(manifest);
|
|
5777
6637
|
const res = ensure_managed_hooks(
|
|
5778
|
-
|
|
6638
|
+
path20.join(anchor, "settings.json"),
|
|
5779
6639
|
matrix
|
|
5780
6640
|
);
|
|
5781
6641
|
if (!state.QUIET) {
|
|
@@ -5812,7 +6672,7 @@ function _preview_global_reap(tools, package_root) {
|
|
|
5812
6672
|
const anchor = expanduser3(anchor_raw);
|
|
5813
6673
|
let current_files = /* @__PURE__ */ new Set();
|
|
5814
6674
|
for (const [src_rel, dest_sub] of plan) {
|
|
5815
|
-
const src =
|
|
6675
|
+
const src = path20.join(package_root, src_rel);
|
|
5816
6676
|
current_files = setUnion(
|
|
5817
6677
|
current_files,
|
|
5818
6678
|
expected_deploy_files(
|
|
@@ -5846,14 +6706,14 @@ function _preview_global_reap(tools, package_root) {
|
|
|
5846
6706
|
function _verify_deploy_targets(anchor, plan) {
|
|
5847
6707
|
const missing = [];
|
|
5848
6708
|
for (const [, dest_sub] of plan) {
|
|
5849
|
-
const target = dest_sub ?
|
|
6709
|
+
const target = dest_sub ? path20.join(anchor, dest_sub) : anchor;
|
|
5850
6710
|
const label = dest_sub || ".";
|
|
5851
6711
|
if (!isDir(target)) {
|
|
5852
6712
|
missing.push(label);
|
|
5853
6713
|
continue;
|
|
5854
6714
|
}
|
|
5855
6715
|
try {
|
|
5856
|
-
const entries =
|
|
6716
|
+
const entries = fs20.readdirSync(target);
|
|
5857
6717
|
if (entries.length === 0) missing.push(label);
|
|
5858
6718
|
} catch {
|
|
5859
6719
|
missing.push(label);
|
|
@@ -5871,54 +6731,30 @@ function _resolve_global_settings_doc() {
|
|
|
5871
6731
|
}
|
|
5872
6732
|
function _resolve_global_settings_path() {
|
|
5873
6733
|
const root = event4u_root();
|
|
5874
|
-
const canonical =
|
|
6734
|
+
const canonical = path20.join(root, "settings", SETTINGS_FILE);
|
|
5875
6735
|
if (pathExists(canonical)) return canonical;
|
|
5876
|
-
const legacy =
|
|
6736
|
+
const legacy = path20.join(root, SETTINGS_FILE);
|
|
5877
6737
|
if (pathExists(legacy)) return legacy;
|
|
5878
6738
|
return null;
|
|
5879
6739
|
}
|
|
5880
6740
|
function _resolve_scoped_projection(package_root) {
|
|
5881
6741
|
const doc = _resolve_global_settings_doc() ?? _load_default_settings(package_root);
|
|
5882
|
-
const projection =
|
|
6742
|
+
const projection = isPlainObject(doc["projection"]) ? doc["projection"] : {};
|
|
5883
6743
|
const mode = projectionModeOf(projection["mode"]);
|
|
5884
|
-
const runtime =
|
|
6744
|
+
const runtime = isPlainObject(doc["runtime"]) ? doc["runtime"] : {};
|
|
5885
6745
|
const active_packs_raw = runtime["active_packs"];
|
|
5886
6746
|
const active_packs = Array.isArray(active_packs_raw) ? active_packs_raw.filter((v) => typeof v === "string") : [];
|
|
5887
6747
|
return { mode, active_packs };
|
|
5888
6748
|
}
|
|
5889
6749
|
function _resolve_global_rule_scope(package_root) {
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
}
|
|
5898
|
-
let text;
|
|
5899
|
-
try {
|
|
5900
|
-
text = readText(settings_path);
|
|
5901
|
-
} catch (e) {
|
|
5902
|
-
warn(
|
|
5903
|
-
`could not read ${settings_path} (${String(e)}) \u2014 rule scoping falls back to legacy-all, so ALL rules including maintainer-only ones will be installed. Fix the file to restore scoping.`
|
|
5904
|
-
);
|
|
5905
|
-
return LEGACY_ALL;
|
|
5906
|
-
}
|
|
5907
|
-
const parsed = yamlSafeLoad(text);
|
|
5908
|
-
if (!_isPlainObject(parsed)) {
|
|
5909
|
-
warn(
|
|
5910
|
-
`${settings_path} is not a YAML mapping \u2014 rule scoping falls back to legacy-all, so ALL rules including maintainer-only ones will be installed. Fix the file to restore scoping.`
|
|
5911
|
-
);
|
|
5912
|
-
return LEGACY_ALL;
|
|
5913
|
-
}
|
|
5914
|
-
try {
|
|
5915
|
-
return ruleScopeFromSettings(parsed, package_root);
|
|
5916
|
-
} catch (e) {
|
|
5917
|
-
warn(
|
|
5918
|
-
`could not derive rule scope from ${settings_path} (${String(e)}) \u2014 falling back to legacy-all; ALL rules will be installed.`
|
|
5919
|
-
);
|
|
5920
|
-
return LEGACY_ALL;
|
|
5921
|
-
}
|
|
6750
|
+
return resolveGlobalRuleScope({
|
|
6751
|
+
settingsPath: _resolve_global_settings_path(),
|
|
6752
|
+
packageRoot: package_root,
|
|
6753
|
+
readText,
|
|
6754
|
+
parseYaml: yamlSafeLoad,
|
|
6755
|
+
loadDefaults: () => _load_default_settings(package_root),
|
|
6756
|
+
warn
|
|
6757
|
+
});
|
|
5922
6758
|
}
|
|
5923
6759
|
function _rule_filter_for_source(src_rel, scope) {
|
|
5924
6760
|
if (src_rel !== RULE_SOURCE_REL) return null;
|
|
@@ -5984,7 +6820,7 @@ function install_global(tools, force, project_root = null, core_only = false) {
|
|
|
5984
6820
|
info(` schema_version=1, agent_config_version=${installed_version}`);
|
|
5985
6821
|
info(` tools=${merged_tools.join(",")}`);
|
|
5986
6822
|
}
|
|
5987
|
-
if (project_root !== null && pathExists(_resolve_settings_read(project_root)) && !isDir(
|
|
6823
|
+
if (project_root !== null && pathExists(_resolve_settings_read(project_root)) && !isDir(path20.join(project_root, ".agent-src.uncondensed"))) {
|
|
5988
6824
|
const drift = collect_drift(project_root);
|
|
5989
6825
|
if (!state.QUIET) {
|
|
5990
6826
|
process2.stdout.write("\n");
|
|
@@ -6098,19 +6934,19 @@ function install_global(tools, force, project_root = null, core_only = false) {
|
|
|
6098
6934
|
}
|
|
6099
6935
|
}
|
|
6100
6936
|
}
|
|
6101
|
-
if (project_root !== null && pathExists(_resolve_settings_read(project_root)) && !isDir(
|
|
6937
|
+
if (project_root !== null && pathExists(_resolve_settings_read(project_root)) && !isDir(path20.join(project_root, ".agent-src.uncondensed"))) {
|
|
6102
6938
|
const files_by_tool = filesByToolFromDeploy(deploy_results);
|
|
6103
6939
|
const rc = _update_installed_tools_manifest(project_root, tools, "global", force, files_by_tool);
|
|
6104
6940
|
if (rc !== 0) return rc;
|
|
6105
6941
|
const removed_marker = _remove_legacy_consumer_bridge_marker(project_root);
|
|
6106
6942
|
if (removed_marker !== null && !state.QUIET) {
|
|
6107
|
-
const rel = isRelativeTo(removed_marker, project_root) ?
|
|
6943
|
+
const rel = isRelativeTo(removed_marker, project_root) ? path20.relative(project_root, removed_marker) : removed_marker;
|
|
6108
6944
|
info(`Removed legacy bridge marker: ${rel}`);
|
|
6109
6945
|
}
|
|
6110
6946
|
const anchor_paths = _write_per_tool_project_anchors(project_root, tools);
|
|
6111
6947
|
if (anchor_paths.length > 0 && !state.QUIET) {
|
|
6112
6948
|
for (const p of anchor_paths) {
|
|
6113
|
-
const rel = isRelativeTo(p, project_root) ?
|
|
6949
|
+
const rel = isRelativeTo(p, project_root) ? path20.relative(project_root, p) : p;
|
|
6114
6950
|
info(`Project anchor written: ${rel}`);
|
|
6115
6951
|
}
|
|
6116
6952
|
}
|
|
@@ -6146,8 +6982,8 @@ function install_global(tools, force, project_root = null, core_only = false) {
|
|
|
6146
6982
|
}
|
|
6147
6983
|
function _catalogue_truncation_warnings(deploy_results, project_root) {
|
|
6148
6984
|
const log_candidates = [
|
|
6149
|
-
|
|
6150
|
-
...project_root ? [
|
|
6985
|
+
path20.join(event4u_root(), "state", "skill-catalogue.jsonl"),
|
|
6986
|
+
...project_root ? [path20.join(project_root, OBSERVATION_LOG)] : []
|
|
6151
6987
|
];
|
|
6152
6988
|
const records = log_candidates.flatMap((p) => readObservationLog(p));
|
|
6153
6989
|
if (records.length === 0) return [];
|
|
@@ -6170,13 +7006,13 @@ function _catalogue_truncation_warnings(deploy_results, project_root) {
|
|
|
6170
7006
|
function _scoped_migration_notice(deploy_results, project_root, package_root, probe) {
|
|
6171
7007
|
if (!isInteractiveSession(probe)) return [];
|
|
6172
7008
|
const log_candidates = [
|
|
6173
|
-
|
|
6174
|
-
...project_root ? [
|
|
7009
|
+
path20.join(event4u_root(), "state", "skill-catalogue.jsonl"),
|
|
7010
|
+
...project_root ? [path20.join(project_root, OBSERVATION_LOG)] : []
|
|
6175
7011
|
];
|
|
6176
7012
|
const limits = knownHostLimits(log_candidates.flatMap((p) => readObservationLog(p)));
|
|
6177
7013
|
if (limits.size === 0) return [];
|
|
6178
7014
|
const resolved = _resolve_scoped_projection(package_root);
|
|
6179
|
-
const settings_path = _resolve_global_settings_path() ??
|
|
7015
|
+
const settings_path = _resolve_global_settings_path() ?? path20.join(event4u_root(), "settings", SETTINGS_FILE);
|
|
6180
7016
|
for (const tool_id of Object.keys(deploy_results).sort()) {
|
|
6181
7017
|
const [, , status] = deploy_results[tool_id];
|
|
6182
7018
|
if (status !== "deployed") continue;
|
|
@@ -6195,8 +7031,8 @@ function _scoped_migration_notice(deploy_results, project_root, package_root, pr
|
|
|
6195
7031
|
}
|
|
6196
7032
|
return [];
|
|
6197
7033
|
}
|
|
6198
|
-
var SETTINGS_SURFACE_REL =
|
|
6199
|
-
var SETTINGS_DELTA_REL =
|
|
7034
|
+
var SETTINGS_SURFACE_REL = path20.join("state", "settings-surface.json");
|
|
7035
|
+
var SETTINGS_DELTA_REL = path20.join("state", "settings-delta.json");
|
|
6200
7036
|
function _current_settings_surface(version) {
|
|
6201
7037
|
const jsonSchema = zodToJsonSchema(settingsSchema, {
|
|
6202
7038
|
name: "AgentSettings",
|
|
@@ -6207,20 +7043,20 @@ function _current_settings_surface(version) {
|
|
|
6207
7043
|
}
|
|
6208
7044
|
function _write_settings_surface_snapshot(installed_version) {
|
|
6209
7045
|
const root = event4u_root();
|
|
6210
|
-
const surface_path =
|
|
6211
|
-
const delta_path =
|
|
7046
|
+
const surface_path = path20.join(root, SETTINGS_SURFACE_REL);
|
|
7047
|
+
const delta_path = path20.join(root, SETTINGS_DELTA_REL);
|
|
6212
7048
|
const next = _current_settings_surface(installed_version);
|
|
6213
7049
|
let previous = null;
|
|
6214
7050
|
try {
|
|
6215
|
-
const parsed = JSON.parse(
|
|
7051
|
+
const parsed = JSON.parse(fs20.readFileSync(surface_path, "utf8"));
|
|
6216
7052
|
if (parsed !== null && typeof parsed === "object" && parsed.entries !== void 0) previous = parsed;
|
|
6217
7053
|
} catch {
|
|
6218
7054
|
}
|
|
6219
7055
|
if (previous !== null && previous.version !== next.version) {
|
|
6220
7056
|
const delta = computeSurfaceDelta(previous, next);
|
|
6221
7057
|
if (delta.changes.length > 0) {
|
|
6222
|
-
|
|
6223
|
-
|
|
7058
|
+
fs20.mkdirSync(path20.dirname(delta_path), { recursive: true, mode: 448 });
|
|
7059
|
+
fs20.writeFileSync(delta_path, `${JSON.stringify(delta, null, 2)}
|
|
6224
7060
|
`, { mode: 384 });
|
|
6225
7061
|
if (!state.QUIET) {
|
|
6226
7062
|
const counts = {};
|
|
@@ -6232,8 +7068,8 @@ function _write_settings_surface_snapshot(installed_version) {
|
|
|
6232
7068
|
}
|
|
6233
7069
|
}
|
|
6234
7070
|
}
|
|
6235
|
-
|
|
6236
|
-
|
|
7071
|
+
fs20.mkdirSync(path20.dirname(surface_path), { recursive: true, mode: 448 });
|
|
7072
|
+
fs20.writeFileSync(surface_path, `${JSON.stringify(next, null, 2)}
|
|
6237
7073
|
`, { mode: 384 });
|
|
6238
7074
|
}
|
|
6239
7075
|
function arrayStrEqual(a, b) {
|
|
@@ -6449,17 +7285,17 @@ function _is_tool_enabled(tools, tool_id) {
|
|
|
6449
7285
|
return tools.has(tool_id);
|
|
6450
7286
|
}
|
|
6451
7287
|
function _minimal_templates_root() {
|
|
6452
|
-
const start = resolvePath(
|
|
7288
|
+
const start = resolvePath(_HERE2);
|
|
6453
7289
|
const chain = [start];
|
|
6454
7290
|
let cur = start;
|
|
6455
7291
|
for (; ; ) {
|
|
6456
|
-
const parent =
|
|
7292
|
+
const parent = path20.dirname(cur);
|
|
6457
7293
|
if (parent === cur) break;
|
|
6458
7294
|
chain.push(parent);
|
|
6459
7295
|
cur = parent;
|
|
6460
7296
|
}
|
|
6461
7297
|
for (const ancestor of chain) {
|
|
6462
|
-
const candidate =
|
|
7298
|
+
const candidate = path20.join(ancestor, "src", "templates", "minimal");
|
|
6463
7299
|
if (isDir(candidate)) return candidate;
|
|
6464
7300
|
}
|
|
6465
7301
|
fail("Could not locate src/templates/minimal/ \u2014 package install is corrupt.");
|
|
@@ -6467,9 +7303,9 @@ function _minimal_templates_root() {
|
|
|
6467
7303
|
var INSTALL_MODE_MARKER_REL = "agents/.agent-state/install-mode.txt";
|
|
6468
7304
|
function _write_install_mode_marker(project_root, mode) {
|
|
6469
7305
|
if (mode !== "minimal" && mode !== "full") return;
|
|
6470
|
-
const marker =
|
|
7306
|
+
const marker = path20.join(project_root, INSTALL_MODE_MARKER_REL);
|
|
6471
7307
|
try {
|
|
6472
|
-
mkdirp(
|
|
7308
|
+
mkdirp(path20.dirname(marker));
|
|
6473
7309
|
writeText(marker, `${mode}
|
|
6474
7310
|
`);
|
|
6475
7311
|
} catch {
|
|
@@ -6478,7 +7314,7 @@ function _write_install_mode_marker(project_root, mode) {
|
|
|
6478
7314
|
function install_minimal(target_root_in, force, user_type = "") {
|
|
6479
7315
|
let target_root = resolvePath(target_root_in);
|
|
6480
7316
|
mkdirp(target_root);
|
|
6481
|
-
const parent =
|
|
7317
|
+
const parent = path20.dirname(target_root);
|
|
6482
7318
|
if (parent !== target_root) {
|
|
6483
7319
|
const existing = find_project_root_with_anchor(parent);
|
|
6484
7320
|
if (existing !== null && existing[0] !== target_root) {
|
|
@@ -6489,21 +7325,21 @@ function install_minimal(target_root_in, force, user_type = "") {
|
|
|
6489
7325
|
}
|
|
6490
7326
|
}
|
|
6491
7327
|
const templates = _minimal_templates_root();
|
|
6492
|
-
const settings_src =
|
|
6493
|
-
const overrides_gitkeep_src =
|
|
6494
|
-
const overrides_readme_src =
|
|
7328
|
+
const settings_src = path20.join(templates, SETTINGS_FILE);
|
|
7329
|
+
const overrides_gitkeep_src = path20.join(templates, "overrides-gitkeep");
|
|
7330
|
+
const overrides_readme_src = path20.join(templates, "agents-overrides-readme.md");
|
|
6495
7331
|
if (!isFile(settings_src)) fail(`Bundled minimal settings template missing under ${templates}`);
|
|
6496
7332
|
if (!isFile(overrides_gitkeep_src) || !isFile(overrides_readme_src)) {
|
|
6497
7333
|
fail(`Bundled overrides scaffold templates missing under ${templates}`);
|
|
6498
7334
|
}
|
|
6499
7335
|
info(`Minimal init \u2192 ${target_root}`);
|
|
6500
|
-
const overrides_root =
|
|
7336
|
+
const overrides_root = path20.join(target_root, "agents", "overrides");
|
|
6501
7337
|
mkdirp(overrides_root);
|
|
6502
7338
|
const gitkeep_body = readText(overrides_gitkeep_src);
|
|
6503
7339
|
for (const sub of ["rules", "skills", "commands"]) {
|
|
6504
|
-
const sub_dir =
|
|
7340
|
+
const sub_dir = path20.join(overrides_root, sub);
|
|
6505
7341
|
mkdirp(sub_dir);
|
|
6506
|
-
const gitkeep_dst =
|
|
7342
|
+
const gitkeep_dst = path20.join(sub_dir, ".gitkeep");
|
|
6507
7343
|
if (pathExists(gitkeep_dst) && !force) {
|
|
6508
7344
|
skip(`agents/overrides/${sub}/.gitkeep already exists (use --force to overwrite)`);
|
|
6509
7345
|
} else {
|
|
@@ -6511,7 +7347,7 @@ function install_minimal(target_root_in, force, user_type = "") {
|
|
|
6511
7347
|
success(`Wrote agents/overrides/${sub}/.gitkeep`);
|
|
6512
7348
|
}
|
|
6513
7349
|
}
|
|
6514
|
-
const readme_dst =
|
|
7350
|
+
const readme_dst = path20.join(overrides_root, "README.md");
|
|
6515
7351
|
if (pathExists(readme_dst) && !force) {
|
|
6516
7352
|
skip("agents/overrides/README.md already exists (use --force to overwrite)");
|
|
6517
7353
|
} else {
|
|
@@ -6529,14 +7365,14 @@ function install_minimal(target_root_in, force, user_type = "") {
|
|
|
6529
7365
|
personal:
|
|
6530
7366
|
user_type: ${user_type}
|
|
6531
7367
|
`;
|
|
6532
|
-
mkdirp(
|
|
7368
|
+
mkdirp(path20.dirname(settings_dst));
|
|
6533
7369
|
writeText(settings_dst, body);
|
|
6534
7370
|
success(`Wrote ${SETTINGS_FILE} (user_type=${user_type})`);
|
|
6535
7371
|
}
|
|
6536
7372
|
}
|
|
6537
7373
|
const removed_marker = _remove_legacy_consumer_bridge_marker(target_root);
|
|
6538
7374
|
if (removed_marker !== null) {
|
|
6539
|
-
const rel = isRelativeTo(removed_marker, target_root) ?
|
|
7375
|
+
const rel = isRelativeTo(removed_marker, target_root) ? path20.relative(target_root, removed_marker) : removed_marker;
|
|
6540
7376
|
success(`Removed legacy bridge marker: ${rel}`);
|
|
6541
7377
|
}
|
|
6542
7378
|
_write_install_mode_marker(target_root, "minimal");
|
|
@@ -6610,7 +7446,7 @@ function run_interactive_init(project_root, force) {
|
|
|
6610
7446
|
);
|
|
6611
7447
|
return 0;
|
|
6612
7448
|
}
|
|
6613
|
-
const target =
|
|
7449
|
+
const target = path20.join(project_root, _LOCAL_CONFIG_FILE);
|
|
6614
7450
|
if (pathExists(target) && !force) {
|
|
6615
7451
|
warn(
|
|
6616
7452
|
`${_LOCAL_CONFIG_FILE} already exists; re-run with --force to overwrite. Skipping interactive init.`
|
|
@@ -6637,7 +7473,7 @@ function run_interactive_init(project_root, force) {
|
|
|
6637
7473
|
warn(`Could not write ${target}: ${String(exc)}`);
|
|
6638
7474
|
return 1;
|
|
6639
7475
|
}
|
|
6640
|
-
success(`Wrote ${
|
|
7476
|
+
success(`Wrote ${path20.relative(project_root, target)} (${user_type} / ${stack} / ${verbosity})`);
|
|
6641
7477
|
return 0;
|
|
6642
7478
|
}
|
|
6643
7479
|
var _WIZARD_READY_RE = /^WIZARD_READY (http:\/\/(?:127\.0\.0\.1|localhost):\d+\/\S*)\r?$/;
|
|
@@ -6655,12 +7491,12 @@ function _wizard_should_launch(opts) {
|
|
|
6655
7491
|
return [true, ""];
|
|
6656
7492
|
}
|
|
6657
7493
|
function _wizard_cli_dist(_project_root) {
|
|
6658
|
-
const package_root =
|
|
6659
|
-
const cli =
|
|
7494
|
+
const package_root = path20.dirname(path20.dirname(path20.dirname(resolvePath(_HERE2))));
|
|
7495
|
+
const cli = path20.join(package_root, "dist", "cli", "agent-config.js");
|
|
6660
7496
|
return pathExists(cli) ? cli : null;
|
|
6661
7497
|
}
|
|
6662
7498
|
function _server_info_path() {
|
|
6663
|
-
return
|
|
7499
|
+
return path20.join(os6.homedir(), ".event4u", "agent-config", "local-server.json");
|
|
6664
7500
|
}
|
|
6665
7501
|
function _pid_is_agent_config(pid) {
|
|
6666
7502
|
let res;
|
|
@@ -6677,7 +7513,7 @@ function _pid_is_agent_config(pid) {
|
|
|
6677
7513
|
}
|
|
6678
7514
|
function unlinkMissingOk(p) {
|
|
6679
7515
|
try {
|
|
6680
|
-
|
|
7516
|
+
fs20.unlinkSync(p);
|
|
6681
7517
|
} catch {
|
|
6682
7518
|
}
|
|
6683
7519
|
}
|
|
@@ -6755,14 +7591,14 @@ function _wizard_spawn(project_root, pass_project_root = true) {
|
|
|
6755
7591
|
}
|
|
6756
7592
|
function _wizard_run_sync(cmd, env, cli) {
|
|
6757
7593
|
const total = _WIZARD_TIMEOUTS.reduce((a, b) => a + b, 0);
|
|
6758
|
-
const log_path =
|
|
6759
|
-
|
|
7594
|
+
const log_path = path20.join(
|
|
7595
|
+
os6.tmpdir(),
|
|
6760
7596
|
`agent-config-wizard-${process2.pid}-${Date.now()}.log`
|
|
6761
7597
|
);
|
|
6762
7598
|
let child;
|
|
6763
7599
|
let log_fd = null;
|
|
6764
7600
|
try {
|
|
6765
|
-
log_fd =
|
|
7601
|
+
log_fd = fs20.openSync(log_path, "w");
|
|
6766
7602
|
child = spawn(cmd[0], cmd.slice(1), {
|
|
6767
7603
|
env,
|
|
6768
7604
|
detached: true,
|
|
@@ -6780,7 +7616,7 @@ function _wizard_run_sync(cmd, env, cli) {
|
|
|
6780
7616
|
} finally {
|
|
6781
7617
|
if (log_fd !== null) {
|
|
6782
7618
|
try {
|
|
6783
|
-
|
|
7619
|
+
fs20.closeSync(log_fd);
|
|
6784
7620
|
} catch {
|
|
6785
7621
|
}
|
|
6786
7622
|
}
|
|
@@ -6957,7 +7793,7 @@ function main2(argv) {
|
|
|
6957
7793
|
} catch (exc) {
|
|
6958
7794
|
fail(`--apply-payload JSON parse error: ${String(exc)}`);
|
|
6959
7795
|
}
|
|
6960
|
-
if (!
|
|
7796
|
+
if (!isPlainObject(payload)) fail("--apply-payload root must be a JSON object");
|
|
6961
7797
|
const pl = payload;
|
|
6962
7798
|
const schema_version = pl["schema_version"];
|
|
6963
7799
|
if (schema_version !== "wizard-v2" && schema_version !== "installer-v1") {
|
|
@@ -6976,13 +7812,13 @@ function main2(argv) {
|
|
|
6976
7812
|
opts.scope = "global";
|
|
6977
7813
|
}
|
|
6978
7814
|
const settings = pl["settings"];
|
|
6979
|
-
if (
|
|
7815
|
+
if (isPlainObject(settings)) {
|
|
6980
7816
|
const rule_loading_tier = settings["rule_loading_tier"] || settings["cost_profile"];
|
|
6981
7817
|
if (typeof rule_loading_tier === "string" && rule_loading_tier) {
|
|
6982
7818
|
opts.profile = rule_loading_tier;
|
|
6983
7819
|
}
|
|
6984
7820
|
const personal = settings["personal"];
|
|
6985
|
-
if (
|
|
7821
|
+
if (isPlainObject(personal)) {
|
|
6986
7822
|
const user_type = personal["user_type"];
|
|
6987
7823
|
if (typeof user_type === "string" && user_type) {
|
|
6988
7824
|
opts.user_type = user_type;
|
|
@@ -7030,8 +7866,8 @@ function main2(argv) {
|
|
|
7030
7866
|
const target_root = resolvePath(
|
|
7031
7867
|
opts.custom_path || opts.project || process2.env["PROJECT_ROOT"] || process2.cwd()
|
|
7032
7868
|
);
|
|
7033
|
-
const minimal_package_root =
|
|
7034
|
-
|
|
7869
|
+
const minimal_package_root = path20.dirname(
|
|
7870
|
+
path20.dirname(path20.dirname(_minimal_templates_root()))
|
|
7035
7871
|
);
|
|
7036
7872
|
const validated_user_type = _validate_user_type(minimal_package_root, opts.user_type);
|
|
7037
7873
|
return install_minimal(target_root, opts.force, validated_user_type);
|
|
@@ -7067,7 +7903,7 @@ function main2(argv) {
|
|
|
7067
7903
|
return rc2;
|
|
7068
7904
|
}
|
|
7069
7905
|
const project_root = custom_path || resolvePath(opts.project || process2.env["PROJECT_ROOT"] || process2.cwd());
|
|
7070
|
-
const is_first_run = !pathExists(
|
|
7906
|
+
const is_first_run = !pathExists(path20.join(project_root, SETTINGS_FILE));
|
|
7071
7907
|
tracker.begin(project_root);
|
|
7072
7908
|
let rc = _main_project_install(opts, project_root, parsed_tools, is_first_run);
|
|
7073
7909
|
if (rc === 0 && opts.interactive) {
|
|
@@ -7112,8 +7948,8 @@ function _read_consumer_auto_switch(project_root) {
|
|
|
7112
7948
|
} catch {
|
|
7113
7949
|
return "suggest";
|
|
7114
7950
|
}
|
|
7115
|
-
const model =
|
|
7116
|
-
const value =
|
|
7951
|
+
const model = isPlainObject(data) ? data["model"] : null;
|
|
7952
|
+
const value = isPlainObject(model) ? model["auto_switch"] : null;
|
|
7117
7953
|
if (typeof value === "string" && ["auto", "suggest", "off"].includes(value.trim().toLowerCase())) {
|
|
7118
7954
|
return value.trim().toLowerCase();
|
|
7119
7955
|
}
|
|
@@ -7126,23 +7962,23 @@ function _team_setup_hint_line(project_root) {
|
|
|
7126
7962
|
} catch {
|
|
7127
7963
|
data = {};
|
|
7128
7964
|
}
|
|
7129
|
-
const ai_team =
|
|
7130
|
-
const flag =
|
|
7965
|
+
const ai_team = isPlainObject(data) ? data["ai_team"] : null;
|
|
7966
|
+
const flag = isPlainObject(ai_team) ? ai_team["suppress_setup_hint"] : null;
|
|
7131
7967
|
const suppressed = flag === true || typeof flag === "string" && ["true", "yes", "on", "1"].includes(flag.trim().toLowerCase());
|
|
7132
7968
|
if (suppressed) return null;
|
|
7133
7969
|
return " \u2022 Claude Code team mode (optional cross-model review via the official codex plugin): run `agent-config doctor --check team` for setup status.";
|
|
7134
7970
|
}
|
|
7135
7971
|
function finalize_claude_model_tiers(project_root) {
|
|
7136
|
-
const claude_skills =
|
|
7137
|
-
const augment_skills =
|
|
7972
|
+
const claude_skills = path20.join(project_root, ".claude", "skills");
|
|
7973
|
+
const augment_skills = path20.join(project_root, ".augment", "skills");
|
|
7138
7974
|
if (!isDir(claude_skills) || !isDir(augment_skills)) return 0;
|
|
7139
7975
|
if (_read_consumer_auto_switch(project_root) !== "auto") return 0;
|
|
7140
7976
|
let rendered = 0;
|
|
7141
|
-
const entries =
|
|
7977
|
+
const entries = fs20.readdirSync(claude_skills).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
7142
7978
|
for (const name of entries) {
|
|
7143
|
-
const entry =
|
|
7144
|
-
const src_dir =
|
|
7145
|
-
const src_md =
|
|
7979
|
+
const entry = path20.join(claude_skills, name);
|
|
7980
|
+
const src_dir = path20.join(augment_skills, name);
|
|
7981
|
+
const src_md = path20.join(src_dir, "SKILL.md");
|
|
7146
7982
|
let tier;
|
|
7147
7983
|
try {
|
|
7148
7984
|
tier = read_model_tier(src_md);
|
|
@@ -7151,22 +7987,22 @@ function finalize_claude_model_tiers(project_root) {
|
|
|
7151
7987
|
}
|
|
7152
7988
|
if (tier === null || !(tier in TIER_TO_CLAUDE_MODEL) || !isDir(src_dir)) continue;
|
|
7153
7989
|
if (isSymlink(entry) || isFile(entry)) {
|
|
7154
|
-
|
|
7990
|
+
fs20.unlinkSync(entry);
|
|
7155
7991
|
} else if (isDir(entry)) {
|
|
7156
|
-
|
|
7992
|
+
fs20.rmSync(entry, { recursive: true, force: true });
|
|
7157
7993
|
}
|
|
7158
7994
|
mkdirp(entry);
|
|
7159
|
-
const srcFiles =
|
|
7995
|
+
const srcFiles = fs20.readdirSync(src_dir).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
7160
7996
|
for (const fname of srcFiles) {
|
|
7161
7997
|
if (fname === "SKILL.md") {
|
|
7162
7998
|
writeText(
|
|
7163
|
-
|
|
7999
|
+
path20.join(entry, "SKILL.md"),
|
|
7164
8000
|
render_native_model_md(readText(src_md), tier)
|
|
7165
8001
|
);
|
|
7166
8002
|
} else {
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
8003
|
+
fs20.symlinkSync(
|
|
8004
|
+
path20.join("../../../.augment/skills", name, fname),
|
|
8005
|
+
path20.join(entry, fname)
|
|
7170
8006
|
);
|
|
7171
8007
|
}
|
|
7172
8008
|
}
|
|
@@ -7184,7 +8020,7 @@ function _main_project_install(opts, project_root, parsed_tools, is_first_run) {
|
|
|
7184
8020
|
let package_type;
|
|
7185
8021
|
if (opts.package) {
|
|
7186
8022
|
package_root = resolvePath(opts.package);
|
|
7187
|
-
if (!pathExists(
|
|
8023
|
+
if (!pathExists(path20.join(package_root, "src", "config", "profiles", "minimal.ini"))) {
|
|
7188
8024
|
fail(`Invalid --package path (missing src/config/profiles/minimal.ini): ${package_root}`);
|
|
7189
8025
|
}
|
|
7190
8026
|
package_type = detect_package_type_for_project(project_root, package_root);
|
|
@@ -7322,19 +8158,21 @@ function _main_project_install(opts, project_root, parsed_tools, is_first_run) {
|
|
|
7322
8158
|
if (will_launch) {
|
|
7323
8159
|
return _wizard_spawn(project_root);
|
|
7324
8160
|
}
|
|
8161
|
+
const ign = write_managed_block(project_root, opts.dry_run);
|
|
8162
|
+
if (ign > 0) success(`.gitignore: ${opts.dry_run ? "would add " : "+"}${ign} managed entries`);
|
|
7325
8163
|
return 0;
|
|
7326
8164
|
}
|
|
7327
8165
|
function _resolvedArgv1() {
|
|
7328
8166
|
if (process2.argv[1] === void 0) return void 0;
|
|
7329
8167
|
try {
|
|
7330
|
-
return
|
|
8168
|
+
return fs20.realpathSync(path20.resolve(process2.argv[1]));
|
|
7331
8169
|
} catch {
|
|
7332
|
-
return
|
|
8170
|
+
return path20.resolve(process2.argv[1]);
|
|
7333
8171
|
}
|
|
7334
8172
|
}
|
|
7335
8173
|
var _argv1 = _resolvedArgv1();
|
|
7336
8174
|
var _isCliEntry = _argv1 !== void 0 && import.meta.url === pathToFileURL(_argv1).href;
|
|
7337
|
-
if (_isCliEntry || _argv1 ===
|
|
8175
|
+
if (_isCliEntry || _argv1 === _HERE2) {
|
|
7338
8176
|
try {
|
|
7339
8177
|
process2.exitCode = main2(process2.argv.slice(2));
|
|
7340
8178
|
} catch (e) {
|