@event4u/agent-config 16.2.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 +89 -237
- 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 +4 -4
- 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/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/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/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/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-system-capture/references/import-procedure.md +1 -1
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +2 -2
- 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/monorepo-workspace/SKILL.md +1 -1
- 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 +2 -2
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +48 -6
- package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
- 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-IGD6ERX6.js → chunk-JQVYKIZA.js} +10 -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-7RQP4UDH.js → chunk-KR6EM23A.js} +235 -1455
- package/dist/cli-delegate/{chunk-LTYVIY76.js → chunk-LIYTLH6O.js} +1 -1
- package/dist/cli-delegate/{chunk-YJ72UIAK.js → chunk-NQ7WT43P.js} +1186 -244
- 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-7XGBX6ZH.js → chunk-RQNNW7IF.js} +1314 -560
- package/dist/cli-delegate/{chunk-4XFP2Y3E.js → chunk-S4UMZNES.js} +1 -1
- package/dist/cli-delegate/{chunk-6KM6ORRY.js → chunk-S4YWNRKO.js} +24 -8
- package/dist/cli-delegate/{chunk-FP36SWJD.js → chunk-TRI6DQZ6.js} +2781 -340
- 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 +1167 -234
- 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 +127 -75
- 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 +5357 -6656
- package/dist/hooks/dispatch.sha256 +1 -1
- 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 +2080 -1024
- 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 +31965 -27154
- 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 +6 -0
- package/dist/shared/skillRanking.js +74 -13
- package/docs/contracts/settings-classes.md +7 -5
- package/package.json +1 -1
- 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/apply.ts +48 -6
- package/src/agent-src/templates/scripts/work_engine/stack/runner.ts +774 -109
- package/src/config/agent-settings.template.yml +62 -22
- package/src/config/continuity-surface.json +7 -0
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +96 -3
- package/src/config/gate-violation-baselines.json +17 -9
- package/src/config/hook-bundle-budget.json +25 -0
- package/src/config/hook-token-budget.json +6 -1
- package/src/config/host-instruction-limits.json +33 -0
- package/src/config/routing-coverage-seed.json +24 -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 +23 -71
- package/src/scripts/_cli/cmd_doctor_neighbours.ts +293 -0
- package/src/scripts/_dispatch.bash +16 -2
- package/src/scripts/_lib/agent_settings.ts +11 -0
- package/src/scripts/_lib/claude_settings_hooks.ts +10 -8
- 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/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_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/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/prompt_shape.ts +46 -0
- package/src/scripts/_lib/release_migration_gate.ts +19 -3
- package/src/scripts/_lib/reserved_name_sweep.ts +73 -0
- 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/skill_origin.ts +254 -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 +77 -2
- 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/audit_skill_overlap.ts +261 -0
- package/src/scripts/before_complete_hook.ts +243 -12
- package/src/scripts/bench_touched_file_quality.ts +238 -0
- package/src/scripts/check_enforcement_matrix.ts +377 -20
- package/src/scripts/check_estate_count.ts +130 -153
- package/src/scripts/check_finding_dispositions.ts +116 -4
- package/src/scripts/check_hook_bundle_composition.ts +370 -0
- package/src/scripts/check_kernel_edit_ratified.ts +49 -11
- package/src/scripts/check_memory.ts +7 -1
- package/src/scripts/check_release_highlights.ts +10 -0
- package/src/scripts/check_release_pr_shape.ts +38 -15
- package/src/scripts/check_standing_rule_delivery.ts +33 -13
- package/src/scripts/check_verify_expectation_delta.ts +521 -0
- 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 +33 -1
- package/src/scripts/condense.ts +14 -27
- package/src/scripts/estate_exemption_shape.ts +202 -0
- package/src/scripts/generate_host_cost_table.ts +1 -1
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +150 -9
- package/src/scripts/hooks/block_config_weakening.ts +67 -2
- package/src/scripts/hooks/block_plumbing_writes.ts +29 -1
- package/src/scripts/hooks/code_graph_context_hook.ts +252 -23
- package/src/scripts/hooks/concern_failure_policy.ts +280 -0
- package/src/scripts/hooks/dispatch_hook.ts +52 -52
- package/src/scripts/hooks/exit_codes.ts +2 -1
- package/src/scripts/hooks/host_lowering.json +1 -1
- package/src/scripts/hooks/host_lowering.ts +19 -1
- package/src/scripts/hooks/one_question_per_ask_hook.ts +41 -25
- package/src/scripts/hooks/payload_stub.ts +10 -1
- package/src/scripts/hooks/rule_inject_hook.ts +757 -63
- package/src/scripts/hooks/table_fingerprint.ts +21 -0
- package/src/scripts/hooks/telemetry_usage_hook.ts +64 -8
- package/src/scripts/hooks/turn_end_gate_hook.ts +84 -0
- package/src/scripts/hooks_status.ts +112 -0
- package/src/scripts/injection_scan_hook.ts +7 -0
- package/src/scripts/install.ts +72 -185
- 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_hook_manifest.ts +53 -0
- package/src/scripts/lint_major_migration_sections.ts +156 -26
- package/src/scripts/lint_pack_boundaries.ts +63 -5
- package/src/scripts/lint_rule_law_section.ts +517 -0
- 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/measure_routing_signal.ts +54 -16
- package/src/scripts/measure_skill_ranker_baseline.ts +216 -8
- package/src/scripts/memory_learn_hook.ts +91 -6
- package/src/scripts/model_rule_injection.ts +52 -5
- package/src/scripts/project_thin_rules.ts +34 -327
- package/src/scripts/report_evidence_temperature.ts +657 -0
- package/src/scripts/report_installed_rule_links.ts +157 -0
- package/src/scripts/report_label_agreement.ts +233 -0
- package/src/scripts/report_obligation_mechanism.ts +230 -0
- package/src/scripts/report_single_token_triggers.ts +277 -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/rule_activation_census.ts +5 -2
- package/src/scripts/rule_trigger_eval.ts +9 -9
- package/src/scripts/schemas/review-findings.schema.json +3 -2
- package/src/scripts/schemas/rule.schema.json +5 -0
- package/src/scripts/self_review_gate.ts +62 -7
- package/src/scripts/skill_tools/score_skill_relevance.ts +290 -25
- 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 -5
- package/src/server/schemas/settings.ts +10 -0
- package/src/shared/skillRanking.ts +117 -11
- package/dist/cli-delegate/chunk-JNMVLWLR.js +0 -4457
- package/dist/cli-delegate/chunk-YDPILCOL.js +0 -152
|
@@ -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,16 +338,44 @@ 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";
|
|
291
346
|
|
|
292
|
-
// src/scripts/_lib/
|
|
293
|
-
var YAML = __toESM(require_dist(), 1);
|
|
347
|
+
// src/scripts/_lib/reserved_name_sweep.ts
|
|
294
348
|
import * as fs from "node:fs";
|
|
295
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";
|
|
296
379
|
var WRITABLE_HOST_ENV = [
|
|
297
380
|
{ variable: "BASH_MAX_OUTPUT_LENGTH", settingsKey: "bash_max_output_length" },
|
|
298
381
|
{ variable: "MAX_MCP_OUTPUT_TOKENS", settingsKey: "max_mcp_output_tokens" }
|
|
@@ -303,10 +386,10 @@ var SETTINGS_CANDIDATES = [
|
|
|
303
386
|
];
|
|
304
387
|
function readSettingsDoc(projectRoot) {
|
|
305
388
|
for (const parts of SETTINGS_CANDIDATES) {
|
|
306
|
-
const p =
|
|
389
|
+
const p = path2.join(projectRoot, ...parts);
|
|
307
390
|
let text;
|
|
308
391
|
try {
|
|
309
|
-
text =
|
|
392
|
+
text = fs2.readFileSync(p, "utf-8");
|
|
310
393
|
} catch {
|
|
311
394
|
continue;
|
|
312
395
|
}
|
|
@@ -547,8 +630,8 @@ function is_claude_builtin_name(slug) {
|
|
|
547
630
|
}
|
|
548
631
|
|
|
549
632
|
// src/scripts/_lib/mcp_bridge.ts
|
|
550
|
-
import * as
|
|
551
|
-
import * as
|
|
633
|
+
import * as fs3 from "node:fs";
|
|
634
|
+
import * as path3 from "node:path";
|
|
552
635
|
var MCP_SERVER_KEY = "agent-config";
|
|
553
636
|
var MCP_PACKAGE_NAME = "@event4u/agent-config";
|
|
554
637
|
function mcpBridgeEntry(packageRoot) {
|
|
@@ -565,7 +648,7 @@ function mcpBridgeEntry(packageRoot) {
|
|
|
565
648
|
}
|
|
566
649
|
function readPackageVersion(packageRoot) {
|
|
567
650
|
try {
|
|
568
|
-
const raw =
|
|
651
|
+
const raw = fs3.readFileSync(path3.join(packageRoot, "package.json"), "utf-8");
|
|
569
652
|
const v = JSON.parse(raw).version;
|
|
570
653
|
return typeof v === "string" && v.trim() !== "" ? v : null;
|
|
571
654
|
} catch {
|
|
@@ -574,7 +657,7 @@ function readPackageVersion(packageRoot) {
|
|
|
574
657
|
}
|
|
575
658
|
function makeEnsureMcpBridge(mergeJsonFile) {
|
|
576
659
|
return (projectRoot, force, packageRoot = projectRoot) => mergeJsonFile(
|
|
577
|
-
|
|
660
|
+
path3.join(projectRoot, ".mcp.json"),
|
|
578
661
|
mcpBridgeEntry(packageRoot),
|
|
579
662
|
force,
|
|
580
663
|
".mcp.json"
|
|
@@ -600,7 +683,7 @@ function makeEnsureMcpRegistrations(mergeJsonFile) {
|
|
|
600
683
|
const merged = {};
|
|
601
684
|
for (const t of targets) {
|
|
602
685
|
merged[t.toolId] = mergeJsonFile(
|
|
603
|
-
|
|
686
|
+
path3.join(projectRoot, ...t.relPath.split("/")),
|
|
604
687
|
mcpBridgeEntry(packageRoot),
|
|
605
688
|
force,
|
|
606
689
|
t.relPath
|
|
@@ -631,10 +714,10 @@ function projectionModeOf(raw) {
|
|
|
631
714
|
return raw === "scoped" ? "scoped" : raw === "tiered" ? "tiered" : "legacy-all";
|
|
632
715
|
}
|
|
633
716
|
function resolveTierB(packageRoot) {
|
|
634
|
-
const p =
|
|
635
|
-
if (!
|
|
717
|
+
const p = path3.join(packageRoot, "agents", "runtime", "state", "skill-tiers.json");
|
|
718
|
+
if (!fs3.existsSync(p)) return null;
|
|
636
719
|
try {
|
|
637
|
-
const parsed = JSON.parse(
|
|
720
|
+
const parsed = JSON.parse(fs3.readFileSync(p, "utf-8"));
|
|
638
721
|
if (!Array.isArray(parsed.tier_b)) return null;
|
|
639
722
|
return new Set(parsed.tier_b.filter((n) => typeof n === "string"));
|
|
640
723
|
} catch {
|
|
@@ -642,7 +725,7 @@ function resolveTierB(packageRoot) {
|
|
|
642
725
|
}
|
|
643
726
|
}
|
|
644
727
|
function tierBPrunePredicate(tierB) {
|
|
645
|
-
return (mdPath) => tierB.has(
|
|
728
|
+
return (mdPath) => tierB.has(path3.basename(path3.dirname(mdPath)));
|
|
646
729
|
}
|
|
647
730
|
function tierBAdvisory(packageRoot) {
|
|
648
731
|
const tierB = resolveTierB(packageRoot);
|
|
@@ -671,35 +754,35 @@ function applyTieredPrune(deployResults, packageRoot, pruneBy) {
|
|
|
671
754
|
|
|
672
755
|
// src/install/conflictTracker.ts
|
|
673
756
|
import * as crypto2 from "node:crypto";
|
|
674
|
-
import * as
|
|
675
|
-
import * as
|
|
757
|
+
import * as fs5 from "node:fs";
|
|
758
|
+
import * as path5 from "node:path";
|
|
676
759
|
|
|
677
760
|
// src/install/fsPrimitives.ts
|
|
678
761
|
import * as crypto from "node:crypto";
|
|
679
|
-
import * as
|
|
680
|
-
import * as
|
|
762
|
+
import * as fs4 from "node:fs";
|
|
763
|
+
import * as path4 from "node:path";
|
|
681
764
|
function resolvePath(p) {
|
|
682
765
|
try {
|
|
683
|
-
return
|
|
766
|
+
return fs4.realpathSync(path4.resolve(p));
|
|
684
767
|
} catch {
|
|
685
|
-
return
|
|
768
|
+
return path4.resolve(p);
|
|
686
769
|
}
|
|
687
770
|
}
|
|
688
771
|
function pathExists(p) {
|
|
689
772
|
try {
|
|
690
|
-
|
|
773
|
+
fs4.statSync(p);
|
|
691
774
|
return true;
|
|
692
775
|
} catch {
|
|
693
776
|
return false;
|
|
694
777
|
}
|
|
695
778
|
}
|
|
696
779
|
function mkdirp(p) {
|
|
697
|
-
|
|
780
|
+
fs4.mkdirSync(p, { recursive: true });
|
|
698
781
|
}
|
|
699
782
|
function sha256OfFile(p) {
|
|
700
783
|
let data;
|
|
701
784
|
try {
|
|
702
|
-
data =
|
|
785
|
+
data = fs4.readFileSync(p);
|
|
703
786
|
} catch {
|
|
704
787
|
return null;
|
|
705
788
|
}
|
|
@@ -740,20 +823,20 @@ function createConflictTracker(host) {
|
|
|
740
823
|
function recordedHashFor(target) {
|
|
741
824
|
if (conflictState.root === null) return void 0;
|
|
742
825
|
conflictState.recorded ??= recordedHashesForRoot(conflictState.root);
|
|
743
|
-
const plain =
|
|
826
|
+
const plain = path5.resolve(target);
|
|
744
827
|
if (conflictState.recorded.has(plain)) return conflictState.recorded.get(plain);
|
|
745
828
|
const real = resolvePath(target);
|
|
746
829
|
return real === plain ? void 0 : conflictState.recorded.get(real);
|
|
747
830
|
}
|
|
748
831
|
function stageInto(target, sidecar, produce) {
|
|
749
|
-
mkdirp(
|
|
750
|
-
const tmp =
|
|
751
|
-
|
|
752
|
-
`.${
|
|
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)}`
|
|
753
836
|
);
|
|
754
837
|
const discard = () => {
|
|
755
838
|
try {
|
|
756
|
-
|
|
839
|
+
fs5.unlinkSync(tmp);
|
|
757
840
|
} catch {
|
|
758
841
|
}
|
|
759
842
|
};
|
|
@@ -780,7 +863,7 @@ function createConflictTracker(host) {
|
|
|
780
863
|
}
|
|
781
864
|
}
|
|
782
865
|
try {
|
|
783
|
-
|
|
866
|
+
fs5.renameSync(tmp, sidecar);
|
|
784
867
|
} catch (exc) {
|
|
785
868
|
discard();
|
|
786
869
|
host.fail(
|
|
@@ -829,7 +912,7 @@ function createConflictTracker(host) {
|
|
|
829
912
|
preserve(target, source, packageRoot) {
|
|
830
913
|
const sidecar = sidecarPathFor(target);
|
|
831
914
|
stageInto(target, sidecar, (tmp) => {
|
|
832
|
-
|
|
915
|
+
fs5.copyFileSync(source, tmp);
|
|
833
916
|
host.tagDeployed(tmp, source, packageRoot);
|
|
834
917
|
});
|
|
835
918
|
record(target, sidecar);
|
|
@@ -845,7 +928,7 @@ function createConflictTracker(host) {
|
|
|
845
928
|
*/
|
|
846
929
|
preserveContent(target, content) {
|
|
847
930
|
const sidecar = sidecarPathFor(target);
|
|
848
|
-
stageInto(target, sidecar, (tmp) =>
|
|
931
|
+
stageInto(target, sidecar, (tmp) => fs5.writeFileSync(tmp, content, "utf-8"));
|
|
849
932
|
record(target, sidecar);
|
|
850
933
|
},
|
|
851
934
|
/**
|
|
@@ -867,7 +950,7 @@ function createConflictTracker(host) {
|
|
|
867
950
|
var YAML2 = __toESM(require_dist(), 1);
|
|
868
951
|
import { existsSync as existsSync2, readFileSync as readFileSync4 } from "node:fs";
|
|
869
952
|
import { homedir } from "node:os";
|
|
870
|
-
import { isAbsolute, join as
|
|
953
|
+
import { isAbsolute, join as join5, resolve as resolve3 } from "node:path";
|
|
871
954
|
function fileEntry(p, kind, hashContent) {
|
|
872
955
|
return { path: p, kind, sha256: hashContent ? sha256OfFile(p) : null };
|
|
873
956
|
}
|
|
@@ -890,7 +973,7 @@ function filesByToolFromBridges(tools, projectRoot, scope, bridgeMarker) {
|
|
|
890
973
|
for (const toolId of [...tools].sort()) {
|
|
891
974
|
const marker = bridgeMarker(toolId, scope);
|
|
892
975
|
if (!marker) continue;
|
|
893
|
-
const markerPath = isAbsolute(marker) ? marker :
|
|
976
|
+
const markerPath = isAbsolute(marker) ? marker : join5(projectRoot, marker);
|
|
894
977
|
out[toolId] = [fileEntry(markerPath, "bridge", false)];
|
|
895
978
|
}
|
|
896
979
|
return out;
|
|
@@ -898,7 +981,7 @@ function filesByToolFromBridges(tools, projectRoot, scope, bridgeMarker) {
|
|
|
898
981
|
function expanduser(p) {
|
|
899
982
|
if (p === "~") return homedir();
|
|
900
983
|
if (p.startsWith("~/") || process.platform === "win32" && p.startsWith("~\\")) {
|
|
901
|
-
return
|
|
984
|
+
return join5(homedir(), p.slice(2));
|
|
902
985
|
}
|
|
903
986
|
return p;
|
|
904
987
|
}
|
|
@@ -990,8 +1073,9 @@ function preservedIndex(preservedTargets, staged) {
|
|
|
990
1073
|
}
|
|
991
1074
|
|
|
992
1075
|
// src/scripts/_lib/rule_layer_overlap.ts
|
|
993
|
-
import * as
|
|
994
|
-
import * as
|
|
1076
|
+
import * as fs6 from "node:fs";
|
|
1077
|
+
import * as os from "node:os";
|
|
1078
|
+
import * as path6 from "node:path";
|
|
995
1079
|
var INSTALLER_PROVENANCE_KEYS = ["package", "source_path"];
|
|
996
1080
|
function stripProvenance(text) {
|
|
997
1081
|
const lines = text.split("\n");
|
|
@@ -1042,17 +1126,23 @@ function compareLayers(global_layer, project_layer) {
|
|
|
1042
1126
|
redundant_chars
|
|
1043
1127
|
};
|
|
1044
1128
|
}
|
|
1129
|
+
function hostRuleLayerDirs(projectRoot) {
|
|
1130
|
+
return [
|
|
1131
|
+
path6.join(os.homedir(), ".claude", "rules"),
|
|
1132
|
+
path6.join(projectRoot, ".claude", "rules")
|
|
1133
|
+
];
|
|
1134
|
+
}
|
|
1045
1135
|
function readRuleLayer(dir) {
|
|
1046
1136
|
let names;
|
|
1047
1137
|
try {
|
|
1048
|
-
names =
|
|
1138
|
+
names = fs6.readdirSync(dir);
|
|
1049
1139
|
} catch {
|
|
1050
1140
|
return null;
|
|
1051
1141
|
}
|
|
1052
1142
|
const files = /* @__PURE__ */ new Map();
|
|
1053
1143
|
for (const name of names.filter((n) => n.endsWith(".md")).sort()) {
|
|
1054
1144
|
try {
|
|
1055
|
-
files.set(name,
|
|
1145
|
+
files.set(name, fs6.readFileSync(path6.join(dir, name), "utf-8"));
|
|
1056
1146
|
} catch {
|
|
1057
1147
|
continue;
|
|
1058
1148
|
}
|
|
@@ -1060,7 +1150,7 @@ function readRuleLayer(dir) {
|
|
|
1060
1150
|
return { dir, files };
|
|
1061
1151
|
}
|
|
1062
1152
|
function claudeMdExcludesGlob(dir) {
|
|
1063
|
-
return `${
|
|
1153
|
+
return `${path6.resolve(dir).replace(/\/+$/, "")}/**`;
|
|
1064
1154
|
}
|
|
1065
1155
|
function mergeClaudeMdExcludes(existing, entry) {
|
|
1066
1156
|
if (!Array.isArray(existing)) return [entry];
|
|
@@ -1091,25 +1181,25 @@ function decideLayerAction(report, choice, global_dir, project_dir) {
|
|
|
1091
1181
|
// src/scripts/_lib/install_drift.ts
|
|
1092
1182
|
var import_yaml = __toESM(require_dist(), 1);
|
|
1093
1183
|
import * as crypto3 from "node:crypto";
|
|
1094
|
-
import * as
|
|
1095
|
-
import * as
|
|
1096
|
-
import * as
|
|
1184
|
+
import * as fs7 from "node:fs";
|
|
1185
|
+
import * as os2 from "node:os";
|
|
1186
|
+
import * as path7 from "node:path";
|
|
1097
1187
|
function expanduser2(p) {
|
|
1098
1188
|
if (p === "~") {
|
|
1099
|
-
return
|
|
1189
|
+
return os2.homedir();
|
|
1100
1190
|
}
|
|
1101
1191
|
if (p.startsWith("~/") || process.platform === "win32" && p.startsWith("~\\")) {
|
|
1102
|
-
return
|
|
1192
|
+
return path7.join(os2.homedir(), p.slice(2));
|
|
1103
1193
|
}
|
|
1104
1194
|
return p;
|
|
1105
1195
|
}
|
|
1106
1196
|
function resolve_entry_path(project_root, raw) {
|
|
1107
1197
|
const p = expanduser2(raw);
|
|
1108
|
-
return
|
|
1198
|
+
return path7.isAbsolute(p) ? p : path7.join(project_root, p);
|
|
1109
1199
|
}
|
|
1110
1200
|
function sha256_of_file(p) {
|
|
1111
1201
|
try {
|
|
1112
|
-
return crypto3.createHash("sha256").update(
|
|
1202
|
+
return crypto3.createHash("sha256").update(fs7.readFileSync(p)).digest("hex");
|
|
1113
1203
|
} catch {
|
|
1114
1204
|
return null;
|
|
1115
1205
|
}
|
|
@@ -1118,7 +1208,7 @@ function collect_drift(project_root, env) {
|
|
|
1118
1208
|
const target = manifest_path(project_root, env);
|
|
1119
1209
|
let text;
|
|
1120
1210
|
try {
|
|
1121
|
-
text =
|
|
1211
|
+
text = fs7.readFileSync(target, "utf-8");
|
|
1122
1212
|
} catch {
|
|
1123
1213
|
return null;
|
|
1124
1214
|
}
|
|
@@ -1163,7 +1253,7 @@ function collect_drift(project_root, env) {
|
|
|
1163
1253
|
continue;
|
|
1164
1254
|
}
|
|
1165
1255
|
const resolved = resolve_entry_path(project_root, raw_path);
|
|
1166
|
-
if (!
|
|
1256
|
+
if (!fs7.existsSync(resolved)) {
|
|
1167
1257
|
out.push({
|
|
1168
1258
|
tool_id,
|
|
1169
1259
|
path: resolved,
|
|
@@ -1216,15 +1306,15 @@ function format_drift_report(entries) {
|
|
|
1216
1306
|
}
|
|
1217
1307
|
|
|
1218
1308
|
// src/scripts/_lib/skill_catalogue.ts
|
|
1219
|
-
import * as
|
|
1220
|
-
import * as
|
|
1309
|
+
import * as fs8 from "node:fs";
|
|
1310
|
+
import * as path8 from "node:path";
|
|
1221
1311
|
var PROJECT_CATALOGUE_ROOTS = ["src/skills", ".claude/skills"];
|
|
1222
1312
|
var HOST_CATALOGUE_ROOT = ".claude/skills";
|
|
1223
1313
|
var DEFAULT_CATALOGUE_ROOTS = [
|
|
1224
1314
|
...PROJECT_CATALOGUE_ROOTS,
|
|
1225
1315
|
`~/${HOST_CATALOGUE_ROOT}`
|
|
1226
1316
|
];
|
|
1227
|
-
var OBSERVATION_LOG =
|
|
1317
|
+
var OBSERVATION_LOG = path8.join(
|
|
1228
1318
|
"agents",
|
|
1229
1319
|
"evidence",
|
|
1230
1320
|
"metrics",
|
|
@@ -1268,9 +1358,9 @@ function descriptionOf(frontmatter) {
|
|
|
1268
1358
|
return "";
|
|
1269
1359
|
}
|
|
1270
1360
|
function readProjectedCatalogue(root) {
|
|
1271
|
-
const names =
|
|
1361
|
+
const names = fs8.readdirSync(root).filter((n) => fs8.existsSync(path8.join(root, n, "SKILL.md"))).sort();
|
|
1272
1362
|
return names.map((name, index) => {
|
|
1273
|
-
const content =
|
|
1363
|
+
const content = fs8.readFileSync(path8.join(root, name, "SKILL.md"), "utf-8");
|
|
1274
1364
|
const frontmatter = frontmatterOf(content);
|
|
1275
1365
|
const description = descriptionOf(frontmatter);
|
|
1276
1366
|
return {
|
|
@@ -1287,12 +1377,12 @@ function truncationModeOf(record) {
|
|
|
1287
1377
|
return record.truncation_mode ?? "per-entry";
|
|
1288
1378
|
}
|
|
1289
1379
|
function markdownFilesUnder(root) {
|
|
1290
|
-
if (!
|
|
1380
|
+
if (!fs8.existsSync(root)) return [];
|
|
1291
1381
|
const out = [];
|
|
1292
1382
|
const walk = (dir) => {
|
|
1293
|
-
for (const entry of
|
|
1294
|
-
const full =
|
|
1295
|
-
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);
|
|
1296
1386
|
else if (entry.name.endsWith(".md")) out.push(full);
|
|
1297
1387
|
}
|
|
1298
1388
|
};
|
|
@@ -1300,9 +1390,9 @@ function markdownFilesUnder(root) {
|
|
|
1300
1390
|
return out;
|
|
1301
1391
|
}
|
|
1302
1392
|
function measureCatalogueVolume(host, root) {
|
|
1303
|
-
const skillsRoot =
|
|
1304
|
-
const skills =
|
|
1305
|
-
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;
|
|
1306
1396
|
return {
|
|
1307
1397
|
host,
|
|
1308
1398
|
root,
|
|
@@ -1380,9 +1470,9 @@ function migrationPromptLines(host, eligibility, settingsPath) {
|
|
|
1380
1470
|
];
|
|
1381
1471
|
}
|
|
1382
1472
|
function readObservationLog(logPath) {
|
|
1383
|
-
if (!
|
|
1473
|
+
if (!fs8.existsSync(logPath)) return [];
|
|
1384
1474
|
const out = [];
|
|
1385
|
-
for (const line of
|
|
1475
|
+
for (const line of fs8.readFileSync(logPath, "utf-8").split("\n")) {
|
|
1386
1476
|
const trimmed = line.trim();
|
|
1387
1477
|
if (trimmed.length === 0) continue;
|
|
1388
1478
|
try {
|
|
@@ -1423,8 +1513,8 @@ function isInteractiveSession(probe) {
|
|
|
1423
1513
|
|
|
1424
1514
|
// src/scripts/_lib/claude_desktop_bundler.ts
|
|
1425
1515
|
import * as crypto4 from "node:crypto";
|
|
1426
|
-
import * as
|
|
1427
|
-
import * as
|
|
1516
|
+
import * as fs9 from "node:fs";
|
|
1517
|
+
import * as path9 from "node:path";
|
|
1428
1518
|
|
|
1429
1519
|
// src/scripts/_lib/zip_min.ts
|
|
1430
1520
|
import * as zlib from "node:zlib";
|
|
@@ -1531,7 +1621,7 @@ function _is_excluded(rel_parts) {
|
|
|
1531
1621
|
}
|
|
1532
1622
|
function _is_dir(p) {
|
|
1533
1623
|
try {
|
|
1534
|
-
return
|
|
1624
|
+
return fs9.statSync(p).isDirectory();
|
|
1535
1625
|
} catch {
|
|
1536
1626
|
return false;
|
|
1537
1627
|
}
|
|
@@ -1543,12 +1633,12 @@ function _compare_rel_parts(a, b) {
|
|
|
1543
1633
|
}
|
|
1544
1634
|
function _walk_skill_files(skill_dir) {
|
|
1545
1635
|
const out = [];
|
|
1546
|
-
const resolved =
|
|
1636
|
+
const resolved = fs9.realpathSync(skill_dir);
|
|
1547
1637
|
const walk = (root, relRoot) => {
|
|
1548
1638
|
const dirNames = [];
|
|
1549
1639
|
const fileNames = [];
|
|
1550
|
-
for (const dirent of
|
|
1551
|
-
const full =
|
|
1640
|
+
for (const dirent of fs9.readdirSync(root, { withFileTypes: true })) {
|
|
1641
|
+
const full = path9.join(root, dirent.name);
|
|
1552
1642
|
const isDir2 = dirent.isDirectory() || dirent.isSymbolicLink() && _is_dir(full);
|
|
1553
1643
|
if (isDir2) {
|
|
1554
1644
|
dirNames.push(dirent.name);
|
|
@@ -1561,13 +1651,13 @@ function _walk_skill_files(skill_dir) {
|
|
|
1561
1651
|
if (_is_excluded(rel_parts)) {
|
|
1562
1652
|
continue;
|
|
1563
1653
|
}
|
|
1564
|
-
out.push([
|
|
1654
|
+
out.push([path9.join(root, fname), rel_parts]);
|
|
1565
1655
|
}
|
|
1566
1656
|
for (const dname of dirNames) {
|
|
1567
1657
|
if (_is_excluded([dname])) {
|
|
1568
1658
|
continue;
|
|
1569
1659
|
}
|
|
1570
|
-
walk(
|
|
1660
|
+
walk(path9.join(root, dname), [...relRoot, dname]);
|
|
1571
1661
|
}
|
|
1572
1662
|
};
|
|
1573
1663
|
walk(resolved, []);
|
|
@@ -1580,53 +1670,53 @@ function _manifest_digest(files) {
|
|
|
1580
1670
|
const rel = rel_parts.join("/");
|
|
1581
1671
|
h.update(Buffer.from(rel, "utf-8"));
|
|
1582
1672
|
h.update(Buffer.from([0]));
|
|
1583
|
-
h.update(crypto4.createHash("sha256").update(
|
|
1673
|
+
h.update(crypto4.createHash("sha256").update(fs9.readFileSync(abs_path)).digest());
|
|
1584
1674
|
h.update(Buffer.from([0]));
|
|
1585
1675
|
}
|
|
1586
1676
|
return h.digest("hex");
|
|
1587
1677
|
}
|
|
1588
1678
|
function _atomic_write_zip(zip_path, files) {
|
|
1589
|
-
|
|
1590
|
-
const stem =
|
|
1591
|
-
const tmp_path =
|
|
1592
|
-
|
|
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),
|
|
1593
1683
|
`.${stem}.${crypto4.randomBytes(6).toString("hex")}.zip.tmp`
|
|
1594
1684
|
);
|
|
1595
1685
|
try {
|
|
1596
1686
|
const entries = files.map(([abs_path, rel_parts]) => ({
|
|
1597
1687
|
name: rel_parts.join("/"),
|
|
1598
|
-
data:
|
|
1688
|
+
data: fs9.readFileSync(abs_path)
|
|
1599
1689
|
}));
|
|
1600
|
-
|
|
1601
|
-
|
|
1690
|
+
fs9.writeFileSync(tmp_path, zip_write_sync(entries));
|
|
1691
|
+
fs9.renameSync(tmp_path, zip_path);
|
|
1602
1692
|
} finally {
|
|
1603
|
-
if (
|
|
1604
|
-
|
|
1693
|
+
if (fs9.existsSync(tmp_path)) {
|
|
1694
|
+
fs9.unlinkSync(tmp_path);
|
|
1605
1695
|
}
|
|
1606
1696
|
}
|
|
1607
1697
|
}
|
|
1608
1698
|
function _write_if_changed(dest_dir, slug, files, force, written) {
|
|
1609
1699
|
const digest = _manifest_digest(files);
|
|
1610
|
-
const zip_path =
|
|
1611
|
-
const digest_path =
|
|
1612
|
-
const recorded =
|
|
1613
|
-
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)) {
|
|
1614
1704
|
return;
|
|
1615
1705
|
}
|
|
1616
1706
|
_atomic_write_zip(zip_path, files);
|
|
1617
|
-
|
|
1707
|
+
fs9.writeFileSync(digest_path, digest + "\n", "utf-8");
|
|
1618
1708
|
written.push(zip_path);
|
|
1619
1709
|
}
|
|
1620
1710
|
function build_skill_bundles(package_root, dest_dir, force = false, curation = null) {
|
|
1621
|
-
const skills_root =
|
|
1711
|
+
const skills_root = path9.join(package_root, "dist/agent-src", "skills");
|
|
1622
1712
|
if (!_is_dir(skills_root)) {
|
|
1623
1713
|
return [];
|
|
1624
1714
|
}
|
|
1625
|
-
|
|
1715
|
+
fs9.mkdirSync(dest_dir, { recursive: true });
|
|
1626
1716
|
const written = [];
|
|
1627
|
-
for (const name of
|
|
1628
|
-
const entry =
|
|
1629
|
-
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();
|
|
1630
1720
|
if (!(_is_dir(entry) || isSymlink2)) {
|
|
1631
1721
|
continue;
|
|
1632
1722
|
}
|
|
@@ -1634,8 +1724,8 @@ function build_skill_bundles(package_root, dest_dir, force = false, curation = n
|
|
|
1634
1724
|
if (curation !== null && !curation.includes(skill_name)) {
|
|
1635
1725
|
continue;
|
|
1636
1726
|
}
|
|
1637
|
-
const skill_md =
|
|
1638
|
-
if (!
|
|
1727
|
+
const skill_md = path9.join(entry, "SKILL.md");
|
|
1728
|
+
if (!fs9.existsSync(skill_md)) {
|
|
1639
1729
|
continue;
|
|
1640
1730
|
}
|
|
1641
1731
|
const files = _walk_skill_files(entry);
|
|
@@ -1647,15 +1737,15 @@ function build_skill_bundles(package_root, dest_dir, force = false, curation = n
|
|
|
1647
1737
|
return written;
|
|
1648
1738
|
}
|
|
1649
1739
|
function _command_slug(source_file, commands_root) {
|
|
1650
|
-
const rel =
|
|
1651
|
-
const noExt = rel.slice(0, rel.length -
|
|
1652
|
-
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("-");
|
|
1653
1743
|
}
|
|
1654
1744
|
function _iter_command_files(commands_root) {
|
|
1655
1745
|
const found = [];
|
|
1656
1746
|
const walk = (dir) => {
|
|
1657
|
-
for (const dirent of
|
|
1658
|
-
const full =
|
|
1747
|
+
for (const dirent of fs9.readdirSync(dir, { withFileTypes: true })) {
|
|
1748
|
+
const full = path9.join(dir, dirent.name);
|
|
1659
1749
|
if (dirent.isDirectory() || dirent.isSymbolicLink() && _is_dir(full)) {
|
|
1660
1750
|
walk(full);
|
|
1661
1751
|
} else if (dirent.name.endsWith(".md")) {
|
|
@@ -1665,21 +1755,21 @@ function _iter_command_files(commands_root) {
|
|
|
1665
1755
|
};
|
|
1666
1756
|
walk(commands_root);
|
|
1667
1757
|
found.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
1668
|
-
return found.filter((source_file) =>
|
|
1758
|
+
return found.filter((source_file) => path9.basename(source_file) !== "AGENTS.md");
|
|
1669
1759
|
}
|
|
1670
1760
|
function build_command_bundles(package_root, dest_dir, force = false, curation = null) {
|
|
1671
|
-
const commands_root =
|
|
1761
|
+
const commands_root = path9.join(package_root, "dist/agent-src", "commands");
|
|
1672
1762
|
if (!_is_dir(commands_root)) {
|
|
1673
1763
|
return [];
|
|
1674
1764
|
}
|
|
1675
|
-
const skills_root =
|
|
1765
|
+
const skills_root = path9.join(package_root, "dist/agent-src", "skills");
|
|
1676
1766
|
let skill_names = /* @__PURE__ */ new Set();
|
|
1677
1767
|
if (_is_dir(skills_root)) {
|
|
1678
1768
|
skill_names = new Set(
|
|
1679
|
-
|
|
1769
|
+
fs9.readdirSync(skills_root).filter((name) => _is_dir(path9.join(skills_root, name)))
|
|
1680
1770
|
);
|
|
1681
1771
|
}
|
|
1682
|
-
|
|
1772
|
+
fs9.mkdirSync(dest_dir, { recursive: true });
|
|
1683
1773
|
const written = [];
|
|
1684
1774
|
for (const source_file of _iter_command_files(commands_root)) {
|
|
1685
1775
|
const slug = _command_slug(source_file, commands_root);
|
|
@@ -1689,7 +1779,7 @@ function build_command_bundles(package_root, dest_dir, force = false, curation =
|
|
|
1689
1779
|
if (curation !== null && !curation.includes(slug)) {
|
|
1690
1780
|
continue;
|
|
1691
1781
|
}
|
|
1692
|
-
const files = [[
|
|
1782
|
+
const files = [[fs9.realpathSync(source_file), ["SKILL.md"]]];
|
|
1693
1783
|
_write_if_changed(dest_dir, slug, files, force, written);
|
|
1694
1784
|
}
|
|
1695
1785
|
return written;
|
|
@@ -1697,8 +1787,8 @@ function build_command_bundles(package_root, dest_dir, force = false, curation =
|
|
|
1697
1787
|
|
|
1698
1788
|
// src/scripts/hooks/host_lowering.ts
|
|
1699
1789
|
var import_yaml2 = __toESM(require_dist(), 1);
|
|
1700
|
-
import * as
|
|
1701
|
-
import * as
|
|
1790
|
+
import * as fs10 from "node:fs";
|
|
1791
|
+
import * as path10 from "node:path";
|
|
1702
1792
|
import { fileURLToPath } from "node:url";
|
|
1703
1793
|
|
|
1704
1794
|
// src/scripts/hooks/table_fingerprint.ts
|
|
@@ -1710,12 +1800,12 @@ function tableFingerprint(text) {
|
|
|
1710
1800
|
|
|
1711
1801
|
// src/scripts/hooks/host_lowering.ts
|
|
1712
1802
|
var _IN_BUNDLE = true;
|
|
1713
|
-
var _REPO_ROOT =
|
|
1714
|
-
|
|
1803
|
+
var _REPO_ROOT = path10.resolve(
|
|
1804
|
+
path10.dirname(fileURLToPath(import.meta.url)),
|
|
1715
1805
|
..._IN_BUNDLE ? ["..", ".."] : ["..", "..", ".."]
|
|
1716
1806
|
);
|
|
1717
|
-
var HOST_LOWERING_PATH =
|
|
1718
|
-
var HOST_LOWERING_JSON_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");
|
|
1719
1809
|
var DEFAULT_SURFACE = "any";
|
|
1720
1810
|
function _asString(v) {
|
|
1721
1811
|
if (v === null || v === void 0) return null;
|
|
@@ -1787,10 +1877,10 @@ function _structure(raw) {
|
|
|
1787
1877
|
var _cache = null;
|
|
1788
1878
|
function loadHostLowering() {
|
|
1789
1879
|
if (_cache !== null) return _cache;
|
|
1790
|
-
const text =
|
|
1880
|
+
const text = fs10.readFileSync(HOST_LOWERING_PATH, "utf-8");
|
|
1791
1881
|
let compiled;
|
|
1792
1882
|
try {
|
|
1793
|
-
compiled =
|
|
1883
|
+
compiled = fs10.readFileSync(HOST_LOWERING_JSON_PATH, "utf-8");
|
|
1794
1884
|
} catch {
|
|
1795
1885
|
compiled = null;
|
|
1796
1886
|
}
|
|
@@ -1802,7 +1892,24 @@ function resolveTable(yamlText, compiledText) {
|
|
|
1802
1892
|
try {
|
|
1803
1893
|
const raw = JSON.parse(compiledText);
|
|
1804
1894
|
const table = raw["table"];
|
|
1805
|
-
if (raw["fingerprint"] === tableFingerprint(yamlText) && typeof table === "object" && table !== null
|
|
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))) {
|
|
1806
1913
|
return _structure(table);
|
|
1807
1914
|
}
|
|
1808
1915
|
} catch {
|
|
@@ -1826,26 +1933,26 @@ function hostBindings(host, table = loadHostLowering()) {
|
|
|
1826
1933
|
}
|
|
1827
1934
|
|
|
1828
1935
|
// src/install/partitionEligibility.ts
|
|
1829
|
-
import * as
|
|
1830
|
-
import * as
|
|
1936
|
+
import * as fs12 from "node:fs";
|
|
1937
|
+
import * as os3 from "node:os";
|
|
1831
1938
|
|
|
1832
1939
|
// src/install/hostLayerFingerprint.ts
|
|
1833
1940
|
import { createHash as createHash6 } from "node:crypto";
|
|
1834
|
-
import * as
|
|
1835
|
-
import * as
|
|
1941
|
+
import * as fs11 from "node:fs";
|
|
1942
|
+
import * as path11 from "node:path";
|
|
1836
1943
|
var FINGERPRINT_SCHEMA = 1;
|
|
1837
1944
|
function collectFiles(dir) {
|
|
1838
1945
|
const out = [];
|
|
1839
1946
|
const walk = (d) => {
|
|
1840
1947
|
let entries;
|
|
1841
1948
|
try {
|
|
1842
|
-
entries =
|
|
1949
|
+
entries = fs11.readdirSync(d, { withFileTypes: true });
|
|
1843
1950
|
} catch {
|
|
1844
1951
|
return;
|
|
1845
1952
|
}
|
|
1846
1953
|
const sorted = [...entries].sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
1847
1954
|
for (const e of sorted) {
|
|
1848
|
-
const p =
|
|
1955
|
+
const p = path11.join(d, e.name);
|
|
1849
1956
|
if (e.isDirectory()) {
|
|
1850
1957
|
walk(p);
|
|
1851
1958
|
} else if (e.isFile()) {
|
|
@@ -1862,10 +1969,10 @@ function fingerprintLayers(layers) {
|
|
|
1862
1969
|
for (const layer of layers) {
|
|
1863
1970
|
h.update(`layer:${layer.label}\0`);
|
|
1864
1971
|
for (const file of collectFiles(layer.root)) {
|
|
1865
|
-
h.update(
|
|
1972
|
+
h.update(path11.relative(layer.root, file));
|
|
1866
1973
|
h.update("\0");
|
|
1867
1974
|
try {
|
|
1868
|
-
h.update(
|
|
1975
|
+
h.update(fs11.readFileSync(file));
|
|
1869
1976
|
} catch {
|
|
1870
1977
|
h.update("\0unreadable\0");
|
|
1871
1978
|
}
|
|
@@ -1875,11 +1982,11 @@ function fingerprintLayers(layers) {
|
|
|
1875
1982
|
return h.digest("hex");
|
|
1876
1983
|
}
|
|
1877
1984
|
function hostLayerInputs(userHome) {
|
|
1878
|
-
const claude =
|
|
1985
|
+
const claude = path11.join(userHome, ".claude");
|
|
1879
1986
|
return [
|
|
1880
|
-
{ label: "rules", root:
|
|
1881
|
-
{ label: "skills", root:
|
|
1882
|
-
{ 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") }
|
|
1883
1990
|
];
|
|
1884
1991
|
}
|
|
1885
1992
|
|
|
@@ -1888,7 +1995,7 @@ var MAINTAINER_WORKSPACE = "agent-config-maintainer";
|
|
|
1888
1995
|
function isExclusivelyPackageOnly(source_path) {
|
|
1889
1996
|
let meta;
|
|
1890
1997
|
try {
|
|
1891
|
-
[meta] = parseFrontmatter(
|
|
1998
|
+
[meta] = parseFrontmatter(fs12.readFileSync(source_path, "utf-8"));
|
|
1892
1999
|
} catch {
|
|
1893
2000
|
return false;
|
|
1894
2001
|
}
|
|
@@ -1903,7 +2010,7 @@ function stampHostLayerFingerprint(installedVersion, tools, lockfilePath, skip2,
|
|
|
1903
2010
|
return null;
|
|
1904
2011
|
}
|
|
1905
2012
|
try {
|
|
1906
|
-
const fingerprint = fingerprintLayers(hostLayerInputs(
|
|
2013
|
+
const fingerprint = fingerprintLayers(hostLayerInputs(os3.homedir()));
|
|
1907
2014
|
write_lockfile(installedVersion, [...tools], {
|
|
1908
2015
|
path: lockfilePath,
|
|
1909
2016
|
host_layer_fingerprint: fingerprint
|
|
@@ -1919,8 +2026,8 @@ function stampHostLayerFingerprint(installedVersion, tools, lockfilePath, skip2,
|
|
|
1919
2026
|
}
|
|
1920
2027
|
|
|
1921
2028
|
// src/install/claudeRuleRewrite.ts
|
|
1922
|
-
import * as
|
|
1923
|
-
import * as
|
|
2029
|
+
import * as fs13 from "node:fs";
|
|
2030
|
+
import * as path12 from "node:path";
|
|
1924
2031
|
|
|
1925
2032
|
// src/install/claudePathsPlan.ts
|
|
1926
2033
|
function derive_trigger_globs(meta) {
|
|
@@ -1960,14 +2067,22 @@ function _expanded_pattern_count(pattern) {
|
|
|
1960
2067
|
return n;
|
|
1961
2068
|
}
|
|
1962
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"]);
|
|
1963
2072
|
function _has_non_path_trigger(meta) {
|
|
1964
2073
|
const triggers = meta["triggers"];
|
|
1965
2074
|
if (!Array.isArray(triggers)) return false;
|
|
1966
2075
|
for (const t of triggers) {
|
|
1967
2076
|
if (t === null || typeof t !== "object" || Array.isArray(t)) continue;
|
|
1968
2077
|
const obj = t;
|
|
1969
|
-
|
|
1970
|
-
|
|
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
|
+
}
|
|
1971
2086
|
}
|
|
1972
2087
|
return false;
|
|
1973
2088
|
}
|
|
@@ -2035,6 +2150,11 @@ function rewriteAndReport(rulesDir, quiet, info2, warn2, wrappers, preserved = /
|
|
|
2035
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`
|
|
2036
2151
|
);
|
|
2037
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
|
+
}
|
|
2038
2158
|
}
|
|
2039
2159
|
if (result.rewritten > 0 && !quiet) {
|
|
2040
2160
|
info2(
|
|
@@ -2076,23 +2196,23 @@ function rewriteClaudeRules(rulesDir, preserved = /* @__PURE__ */ new Set()) {
|
|
|
2076
2196
|
const result = { rewritten: 0, scoped: [], dropped: [], failed: [] };
|
|
2077
2197
|
let entries;
|
|
2078
2198
|
try {
|
|
2079
|
-
entries =
|
|
2199
|
+
entries = fs13.readdirSync(rulesDir);
|
|
2080
2200
|
} catch {
|
|
2081
2201
|
return result;
|
|
2082
2202
|
}
|
|
2083
2203
|
for (const name of entries.filter((n) => n.endsWith(".md")).sort()) {
|
|
2084
|
-
const full =
|
|
2085
|
-
if (preserved.has(
|
|
2204
|
+
const full = path12.join(rulesDir, name);
|
|
2205
|
+
if (preserved.has(path12.resolve(full))) continue;
|
|
2086
2206
|
let stat;
|
|
2087
2207
|
try {
|
|
2088
|
-
stat =
|
|
2208
|
+
stat = fs13.lstatSync(full);
|
|
2089
2209
|
} catch {
|
|
2090
2210
|
continue;
|
|
2091
2211
|
}
|
|
2092
2212
|
if (!stat.isFile() || stat.isSymbolicLink()) continue;
|
|
2093
2213
|
let text;
|
|
2094
2214
|
try {
|
|
2095
|
-
text =
|
|
2215
|
+
text = fs13.readFileSync(full, "utf-8");
|
|
2096
2216
|
} catch {
|
|
2097
2217
|
continue;
|
|
2098
2218
|
}
|
|
@@ -2102,7 +2222,7 @@ function rewriteClaudeRules(rulesDir, preserved = /* @__PURE__ */ new Set()) {
|
|
|
2102
2222
|
const withOwnership = _withPreservedKeys(rendered.text, text);
|
|
2103
2223
|
if (withOwnership !== text) {
|
|
2104
2224
|
try {
|
|
2105
|
-
|
|
2225
|
+
fs13.writeFileSync(full, withOwnership, "utf-8");
|
|
2106
2226
|
} catch (e) {
|
|
2107
2227
|
result.failed.push({
|
|
2108
2228
|
rule: name.slice(0, -3),
|
|
@@ -2121,6 +2241,744 @@ function rewriteClaudeRules(rulesDir, preserved = /* @__PURE__ */ new Set()) {
|
|
|
2121
2241
|
return result;
|
|
2122
2242
|
}
|
|
2123
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
|
+
|
|
2124
2982
|
// src/shared/settingsSurface.ts
|
|
2125
2983
|
function unwrapRef(root) {
|
|
2126
2984
|
if (root.$ref !== void 0 && root.definitions !== void 0) {
|
|
@@ -3476,8 +4334,8 @@ var zodToJsonSchema = (schema, options) => {
|
|
|
3476
4334
|
};
|
|
3477
4335
|
|
|
3478
4336
|
// src/scripts/_lib/module_detection.ts
|
|
3479
|
-
import * as
|
|
3480
|
-
import * as
|
|
4337
|
+
import * as fs18 from "node:fs";
|
|
4338
|
+
import * as path19 from "node:path";
|
|
3481
4339
|
var _SKIP_DIRS = /* @__PURE__ */ new Set([".module-template", ".example"]);
|
|
3482
4340
|
var _RULES = [
|
|
3483
4341
|
["app/Modules", "laravel-hmvc", "App\\Modules\\{ModuleName}"],
|
|
@@ -3491,14 +4349,14 @@ var _RULES = [
|
|
|
3491
4349
|
];
|
|
3492
4350
|
function _isDir(p) {
|
|
3493
4351
|
try {
|
|
3494
|
-
return
|
|
4352
|
+
return fs18.statSync(p).isDirectory();
|
|
3495
4353
|
} catch {
|
|
3496
4354
|
return false;
|
|
3497
4355
|
}
|
|
3498
4356
|
}
|
|
3499
4357
|
function _isFile(p) {
|
|
3500
4358
|
try {
|
|
3501
|
-
return
|
|
4359
|
+
return fs18.statSync(p).isFile();
|
|
3502
4360
|
} catch {
|
|
3503
4361
|
return false;
|
|
3504
4362
|
}
|
|
@@ -3512,13 +4370,13 @@ function _isUpperChar(ch) {
|
|
|
3512
4370
|
function _list_module_subdirs(root) {
|
|
3513
4371
|
let entries;
|
|
3514
4372
|
try {
|
|
3515
|
-
entries =
|
|
4373
|
+
entries = fs18.readdirSync(root).sort();
|
|
3516
4374
|
} catch {
|
|
3517
4375
|
return [];
|
|
3518
4376
|
}
|
|
3519
4377
|
const out = [];
|
|
3520
4378
|
for (const name of entries) {
|
|
3521
|
-
if (!_isDir(
|
|
4379
|
+
if (!_isDir(path19.join(root, name))) {
|
|
3522
4380
|
continue;
|
|
3523
4381
|
}
|
|
3524
4382
|
if (name.startsWith(".")) {
|
|
@@ -3540,11 +4398,11 @@ function _score_confidence(stack, root, subdirs) {
|
|
|
3540
4398
|
return capitalized.length > 0 ? "high" : "medium";
|
|
3541
4399
|
}
|
|
3542
4400
|
if (stack === "node-monorepo") {
|
|
3543
|
-
const withPkgJson = subdirs.filter((name) => _isFile(
|
|
4401
|
+
const withPkgJson = subdirs.filter((name) => _isFile(path19.join(root, name, "package.json")));
|
|
3544
4402
|
return withPkgJson.length > 0 ? "high" : "medium";
|
|
3545
4403
|
}
|
|
3546
4404
|
if (stack === "python-src") {
|
|
3547
|
-
const withInit = subdirs.filter((name) => _isFile(
|
|
4405
|
+
const withInit = subdirs.filter((name) => _isFile(path19.join(root, name, "__init__.py")));
|
|
3548
4406
|
return withInit.length > 0 ? "high" : "medium";
|
|
3549
4407
|
}
|
|
3550
4408
|
if (stack === "go-internal") {
|
|
@@ -3556,7 +4414,7 @@ function detect_module_roots(project_root) {
|
|
|
3556
4414
|
const high = [];
|
|
3557
4415
|
const medium = [];
|
|
3558
4416
|
for (const [rel_path, stack, namespace_template] of _RULES) {
|
|
3559
|
-
const abs_path =
|
|
4417
|
+
const abs_path = path19.join(project_root, rel_path);
|
|
3560
4418
|
if (!_isDir(abs_path)) {
|
|
3561
4419
|
continue;
|
|
3562
4420
|
}
|
|
@@ -3578,7 +4436,7 @@ function detect_module_roots(project_root) {
|
|
|
3578
4436
|
}
|
|
3579
4437
|
|
|
3580
4438
|
// src/scripts/_lib/model_tier.ts
|
|
3581
|
-
import
|
|
4439
|
+
import fs19 from "node:fs";
|
|
3582
4440
|
var TIER_TO_CLAUDE_MODEL = {
|
|
3583
4441
|
frontier: "fable",
|
|
3584
4442
|
high: "opus",
|
|
@@ -3587,8 +4445,8 @@ var TIER_TO_CLAUDE_MODEL = {
|
|
|
3587
4445
|
};
|
|
3588
4446
|
var MODEL_TIER_RE = /^model_tier:\s*"?([a-z]+)"?\s*$/m;
|
|
3589
4447
|
function read_model_tier(skill_md) {
|
|
3590
|
-
if (!
|
|
3591
|
-
const text =
|
|
4448
|
+
if (!fs19.existsSync(skill_md)) return null;
|
|
4449
|
+
const text = fs19.readFileSync(skill_md).toString("utf-8");
|
|
3592
4450
|
if (!text.startsWith("---\n")) return null;
|
|
3593
4451
|
const end = text.indexOf("\n---\n", 4);
|
|
3594
4452
|
if (end === -1) return null;
|
|
@@ -3604,15 +4462,15 @@ function render_native_model_md(text, tier) {
|
|
|
3604
4462
|
}
|
|
3605
4463
|
|
|
3606
4464
|
// src/install/paths.ts
|
|
3607
|
-
import { homedir as
|
|
3608
|
-
import { join as
|
|
4465
|
+
import { homedir as homedir7, tmpdir } from "node:os";
|
|
4466
|
+
import { join as join20 } from "node:path";
|
|
3609
4467
|
var INSTALL_ROOT_SUBPATH = ".event4u/agent-config";
|
|
3610
4468
|
var INSTALL_LOG_FILENAME = "install-log.jsonl";
|
|
3611
4469
|
function resolveHome(home) {
|
|
3612
4470
|
if (home && home.length > 0) {
|
|
3613
4471
|
return home;
|
|
3614
4472
|
}
|
|
3615
|
-
const fromOs =
|
|
4473
|
+
const fromOs = homedir7();
|
|
3616
4474
|
if (!fromOs) {
|
|
3617
4475
|
throw new Error(
|
|
3618
4476
|
"Cannot resolve home directory \u2014 both $HOME (POSIX) and $USERPROFILE (Windows) are unset."
|
|
@@ -3621,14 +4479,14 @@ function resolveHome(home) {
|
|
|
3621
4479
|
return fromOs;
|
|
3622
4480
|
}
|
|
3623
4481
|
function getInstallRoot(home) {
|
|
3624
|
-
return
|
|
4482
|
+
return join20(resolveHome(home), INSTALL_ROOT_SUBPATH);
|
|
3625
4483
|
}
|
|
3626
4484
|
function getLogPath(home) {
|
|
3627
|
-
return
|
|
4485
|
+
return join20(getInstallRoot(home), INSTALL_LOG_FILENAME);
|
|
3628
4486
|
}
|
|
3629
4487
|
|
|
3630
4488
|
// src/scripts/install.ts
|
|
3631
|
-
var
|
|
4489
|
+
var _HERE2 = fileURLToPath4(import.meta.url);
|
|
3632
4490
|
var SystemExitError = class extends Error {
|
|
3633
4491
|
constructor(code) {
|
|
3634
4492
|
super(`system-exit-${code}`);
|
|
@@ -3644,43 +4502,43 @@ var ArgparseExit = class extends Error {
|
|
|
3644
4502
|
code;
|
|
3645
4503
|
};
|
|
3646
4504
|
function expanduser3(p) {
|
|
3647
|
-
if (p === "~") return
|
|
4505
|
+
if (p === "~") return os6.homedir();
|
|
3648
4506
|
if (p.startsWith("~/") || p.startsWith("~\\")) {
|
|
3649
|
-
return
|
|
4507
|
+
return path20.join(os6.homedir(), p.slice(2));
|
|
3650
4508
|
}
|
|
3651
4509
|
return p;
|
|
3652
4510
|
}
|
|
3653
4511
|
function isFile(p) {
|
|
3654
4512
|
try {
|
|
3655
|
-
return
|
|
4513
|
+
return fs20.statSync(p).isFile();
|
|
3656
4514
|
} catch {
|
|
3657
4515
|
return false;
|
|
3658
4516
|
}
|
|
3659
4517
|
}
|
|
3660
4518
|
function isDir(p) {
|
|
3661
4519
|
try {
|
|
3662
|
-
return
|
|
4520
|
+
return fs20.statSync(p).isDirectory();
|
|
3663
4521
|
} catch {
|
|
3664
4522
|
return false;
|
|
3665
4523
|
}
|
|
3666
4524
|
}
|
|
3667
4525
|
function isSymlink(p) {
|
|
3668
4526
|
try {
|
|
3669
|
-
return
|
|
4527
|
+
return fs20.lstatSync(p).isSymbolicLink();
|
|
3670
4528
|
} catch {
|
|
3671
4529
|
return false;
|
|
3672
4530
|
}
|
|
3673
4531
|
}
|
|
3674
4532
|
function readText(p) {
|
|
3675
|
-
return
|
|
4533
|
+
return fs20.readFileSync(p, "utf-8");
|
|
3676
4534
|
}
|
|
3677
4535
|
function writeText(p, content) {
|
|
3678
|
-
|
|
4536
|
+
fs20.writeFileSync(p, content, "utf-8");
|
|
3679
4537
|
}
|
|
3680
4538
|
function sortedGlobStems(directory, suffix) {
|
|
3681
4539
|
let entries;
|
|
3682
4540
|
try {
|
|
3683
|
-
entries =
|
|
4541
|
+
entries = fs20.readdirSync(directory);
|
|
3684
4542
|
} catch {
|
|
3685
4543
|
return [];
|
|
3686
4544
|
}
|
|
@@ -3700,34 +4558,34 @@ function sortedGlobStems(directory, suffix) {
|
|
|
3700
4558
|
function countZips(directory) {
|
|
3701
4559
|
if (!isDir(directory)) return 0;
|
|
3702
4560
|
let n = 0;
|
|
3703
|
-
for (const name of
|
|
4561
|
+
for (const name of fs20.readdirSync(directory)) {
|
|
3704
4562
|
if (name.endsWith(".zip")) n += 1;
|
|
3705
4563
|
}
|
|
3706
4564
|
return n;
|
|
3707
4565
|
}
|
|
3708
4566
|
function atomicWrite0644(target, body, prefix) {
|
|
3709
|
-
const dir =
|
|
3710
|
-
const tmpName =
|
|
4567
|
+
const dir = path20.dirname(target);
|
|
4568
|
+
const tmpName = path20.join(
|
|
3711
4569
|
dir,
|
|
3712
4570
|
`${prefix}${process2.pid}.${crypto5.randomBytes(6).toString("hex")}.yml.tmp`
|
|
3713
4571
|
);
|
|
3714
4572
|
let fd = null;
|
|
3715
4573
|
try {
|
|
3716
|
-
fd =
|
|
3717
|
-
|
|
3718
|
-
|
|
4574
|
+
fd = fs20.openSync(tmpName, "wx", 420);
|
|
4575
|
+
fs20.writeFileSync(fd, body, "utf-8");
|
|
4576
|
+
fs20.closeSync(fd);
|
|
3719
4577
|
fd = null;
|
|
3720
|
-
|
|
3721
|
-
|
|
4578
|
+
fs20.chmodSync(tmpName, 420);
|
|
4579
|
+
fs20.renameSync(tmpName, target);
|
|
3722
4580
|
} catch (err) {
|
|
3723
4581
|
if (fd !== null) {
|
|
3724
4582
|
try {
|
|
3725
|
-
|
|
4583
|
+
fs20.closeSync(fd);
|
|
3726
4584
|
} catch {
|
|
3727
4585
|
}
|
|
3728
4586
|
}
|
|
3729
4587
|
try {
|
|
3730
|
-
|
|
4588
|
+
fs20.unlinkSync(tmpName);
|
|
3731
4589
|
} catch {
|
|
3732
4590
|
}
|
|
3733
4591
|
throw err;
|
|
@@ -3762,12 +4620,12 @@ var LEGACY_SETTINGS_FILE = ".agent-settings";
|
|
|
3762
4620
|
var LEGACY_BACKUP_FILE = ".agent-settings.backup.key-value";
|
|
3763
4621
|
var SETTINGS_SUBDIR = ["agents", "settings"];
|
|
3764
4622
|
function _canonical_settings_target(project_root) {
|
|
3765
|
-
return
|
|
4623
|
+
return path20.join(project_root, ...SETTINGS_SUBDIR, SETTINGS_FILE);
|
|
3766
4624
|
}
|
|
3767
4625
|
function _resolve_settings_read(project_root) {
|
|
3768
4626
|
const canonical = _canonical_settings_target(project_root);
|
|
3769
4627
|
if (pathExists(canonical)) return canonical;
|
|
3770
|
-
const legacy =
|
|
4628
|
+
const legacy = path20.join(project_root, SETTINGS_FILE);
|
|
3771
4629
|
if (pathExists(legacy)) return legacy;
|
|
3772
4630
|
return canonical;
|
|
3773
4631
|
}
|
|
@@ -3833,9 +4691,9 @@ function fail(msg) {
|
|
|
3833
4691
|
throw new SystemExitError(1);
|
|
3834
4692
|
}
|
|
3835
4693
|
function detect_package_root(project_root) {
|
|
3836
|
-
const npm_path =
|
|
4694
|
+
const npm_path = path20.join(project_root, "node_modules", "@event4u", "agent-config");
|
|
3837
4695
|
if (isDir(npm_path)) return resolvePath(npm_path);
|
|
3838
|
-
if (pathExists(
|
|
4696
|
+
if (pathExists(path20.join(project_root, "src", "config", "profiles", "minimal.ini"))) {
|
|
3839
4697
|
return project_root;
|
|
3840
4698
|
}
|
|
3841
4699
|
fail(
|
|
@@ -3843,12 +4701,12 @@ function detect_package_root(project_root) {
|
|
|
3843
4701
|
);
|
|
3844
4702
|
}
|
|
3845
4703
|
function detect_package_type(package_root) {
|
|
3846
|
-
if (package_root.split(
|
|
4704
|
+
if (package_root.split(path20.sep).includes("node_modules")) return "npm";
|
|
3847
4705
|
return "local";
|
|
3848
4706
|
}
|
|
3849
4707
|
function detect_package_type_for_project(project_root, package_root) {
|
|
3850
4708
|
const npm_path = resolvePath(
|
|
3851
|
-
|
|
4709
|
+
path20.join(project_root, "node_modules", "@event4u", "agent-config")
|
|
3852
4710
|
);
|
|
3853
4711
|
const package_resolved = resolvePath(package_root);
|
|
3854
4712
|
if (package_resolved === npm_path) return "npm";
|
|
@@ -3872,7 +4730,7 @@ function ensure_directory(p) {
|
|
|
3872
4730
|
mkdirp(p);
|
|
3873
4731
|
}
|
|
3874
4732
|
function write_file(p, content) {
|
|
3875
|
-
ensure_directory(
|
|
4733
|
+
ensure_directory(path20.dirname(p));
|
|
3876
4734
|
writeText(p, content);
|
|
3877
4735
|
}
|
|
3878
4736
|
function read_json_file(p) {
|
|
@@ -3893,50 +4751,6 @@ function write_json_file(p, data) {
|
|
|
3893
4751
|
const content = jsonDumpsIndent(data, 4) + "\n";
|
|
3894
4752
|
write_file(p, content);
|
|
3895
4753
|
}
|
|
3896
|
-
function _isPlainObject(v) {
|
|
3897
|
-
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
3898
|
-
}
|
|
3899
|
-
function deepcopy(v) {
|
|
3900
|
-
if (v === null || typeof v !== "object") return v;
|
|
3901
|
-
if (Array.isArray(v)) return v.map((x) => deepcopy(x));
|
|
3902
|
-
const out = {};
|
|
3903
|
-
for (const k of Object.keys(v)) {
|
|
3904
|
-
out[k] = deepcopy(v[k]);
|
|
3905
|
-
}
|
|
3906
|
-
return out;
|
|
3907
|
-
}
|
|
3908
|
-
function deep_merge(base, overlay) {
|
|
3909
|
-
const result = deepcopy(base);
|
|
3910
|
-
for (const key of Object.keys(overlay)) {
|
|
3911
|
-
const value = overlay[key];
|
|
3912
|
-
if (Object.prototype.hasOwnProperty.call(result, key) && _isPlainObject(result[key]) && _isPlainObject(value)) {
|
|
3913
|
-
result[key] = deep_merge(
|
|
3914
|
-
result[key],
|
|
3915
|
-
value
|
|
3916
|
-
);
|
|
3917
|
-
} else {
|
|
3918
|
-
result[key] = deepcopy(value);
|
|
3919
|
-
}
|
|
3920
|
-
}
|
|
3921
|
-
return result;
|
|
3922
|
-
}
|
|
3923
|
-
function jsonEqual(a, b) {
|
|
3924
|
-
if (a === b) return true;
|
|
3925
|
-
if (typeof a !== typeof b) return false;
|
|
3926
|
-
if (Array.isArray(a) || Array.isArray(b)) {
|
|
3927
|
-
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;
|
|
3928
|
-
return a.every((v, i) => jsonEqual(v, b[i]));
|
|
3929
|
-
}
|
|
3930
|
-
if (_isPlainObject(a) && _isPlainObject(b)) {
|
|
3931
|
-
const ka = Object.keys(a);
|
|
3932
|
-
const kb = Object.keys(b);
|
|
3933
|
-
if (ka.length !== kb.length) return false;
|
|
3934
|
-
return ka.every(
|
|
3935
|
-
(k) => Object.prototype.hasOwnProperty.call(b, k) && jsonEqual(a[k], b[k])
|
|
3936
|
-
);
|
|
3937
|
-
}
|
|
3938
|
-
return false;
|
|
3939
|
-
}
|
|
3940
4754
|
function merge_json_file(p, new_data, _force, label) {
|
|
3941
4755
|
const new_entries = build_merge_entries(label, new_data);
|
|
3942
4756
|
if (!pathExists(p)) {
|
|
@@ -3945,7 +4759,7 @@ function merge_json_file(p, new_data, _force, label) {
|
|
|
3945
4759
|
return new_entries;
|
|
3946
4760
|
}
|
|
3947
4761
|
const existing = read_json_file(p);
|
|
3948
|
-
const merged =
|
|
4762
|
+
const merged = mergeHostConfig(existing, new_data, HOOK_SIGNATURES[label] ?? "", deepMerge);
|
|
3949
4763
|
if (jsonEqual(merged, existing)) {
|
|
3950
4764
|
skip(`${label} already configured`);
|
|
3951
4765
|
return new_entries;
|
|
@@ -4043,7 +4857,7 @@ function _append_unknown_legacy(rendered, legacy_values, unknown_keys) {
|
|
|
4043
4857
|
return rendered + "\n" + suffix;
|
|
4044
4858
|
}
|
|
4045
4859
|
function _migrate_legacy_if_present(project_root, template_body) {
|
|
4046
|
-
const legacy_target =
|
|
4860
|
+
const legacy_target = path20.join(project_root, LEGACY_SETTINGS_FILE);
|
|
4047
4861
|
if (!isFile(legacy_target)) return null;
|
|
4048
4862
|
const legacy_text = readText(legacy_target);
|
|
4049
4863
|
const [values, unknown] = _parse_legacy_settings(legacy_text);
|
|
@@ -4058,9 +4872,9 @@ function _migrate_legacy_if_present(project_root, template_body) {
|
|
|
4058
4872
|
}
|
|
4059
4873
|
}
|
|
4060
4874
|
rendered = _append_unknown_legacy(rendered, values, unknown);
|
|
4061
|
-
const backup_target =
|
|
4875
|
+
const backup_target = path20.join(project_root, LEGACY_BACKUP_FILE);
|
|
4062
4876
|
writeText(backup_target, legacy_text);
|
|
4063
|
-
|
|
4877
|
+
fs20.unlinkSync(legacy_target);
|
|
4064
4878
|
info(`Migrated legacy ${LEGACY_SETTINGS_FILE} \u2192 ${SETTINGS_FILE}`);
|
|
4065
4879
|
info(`Backup saved to ${LEGACY_BACKUP_FILE}`);
|
|
4066
4880
|
if (unknown.length > 0) {
|
|
@@ -4095,7 +4909,7 @@ function _render_template(template, profile_values) {
|
|
|
4095
4909
|
return body;
|
|
4096
4910
|
}
|
|
4097
4911
|
function _load_valid_user_types(package_root) {
|
|
4098
|
-
const directory =
|
|
4912
|
+
const directory = path20.join(package_root, USER_TYPES_DIR);
|
|
4099
4913
|
if (!isDir(directory)) return [];
|
|
4100
4914
|
return sortedGlobStems(directory, ".yml");
|
|
4101
4915
|
}
|
|
@@ -4152,8 +4966,8 @@ function splitlinesKeepends(text) {
|
|
|
4152
4966
|
}
|
|
4153
4967
|
function ensure_agent_settings(project_root, package_root, profile, force, user_type = "", packs = null) {
|
|
4154
4968
|
const target = _canonical_settings_target(project_root);
|
|
4155
|
-
const profile_source =
|
|
4156
|
-
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");
|
|
4157
4971
|
if (!pathExists(profile_source)) fail(`Missing profile preset: ${profile_source}`);
|
|
4158
4972
|
if (!pathExists(template_source)) fail(`Missing settings template: ${template_source}`);
|
|
4159
4973
|
const template = readText(template_source);
|
|
@@ -4167,21 +4981,21 @@ function ensure_agent_settings(project_root, package_root, profile, force, user_
|
|
|
4167
4981
|
if (profile_values["rule_loading_tier"] !== profile) {
|
|
4168
4982
|
const got = "rule_loading_tier" in profile_values ? `'${profile_values["rule_loading_tier"]}'` : "None";
|
|
4169
4983
|
fail(
|
|
4170
|
-
`Profile preset ${
|
|
4984
|
+
`Profile preset ${path20.basename(profile_source)} has rule_loading_tier=${got} but --profile=${profile}`
|
|
4171
4985
|
);
|
|
4172
4986
|
}
|
|
4173
4987
|
profile_values["user_type"] = _validate_user_type(package_root, user_type);
|
|
4174
4988
|
let template_body = _render_template(template, profile_values);
|
|
4175
4989
|
template_body = _inject_packs(template_body, packs ?? []);
|
|
4176
|
-
const legacy_root =
|
|
4990
|
+
const legacy_root = path20.join(project_root, SETTINGS_FILE);
|
|
4177
4991
|
if (isFile(legacy_root) && !pathExists(target)) {
|
|
4178
|
-
mkdirp(
|
|
4992
|
+
mkdirp(path20.dirname(target));
|
|
4179
4993
|
writeText(target, readText(legacy_root));
|
|
4180
|
-
|
|
4994
|
+
fs20.unlinkSync(legacy_root);
|
|
4181
4995
|
success(`Migrated ${SETTINGS_FILE} \u2192 agents/settings/${SETTINGS_FILE} (ADR-038)`);
|
|
4182
4996
|
return;
|
|
4183
4997
|
}
|
|
4184
|
-
const legacy_target =
|
|
4998
|
+
const legacy_target = path20.join(project_root, LEGACY_SETTINGS_FILE);
|
|
4185
4999
|
if (isFile(legacy_target) && pathExists(target)) {
|
|
4186
5000
|
warn(
|
|
4187
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.`
|
|
@@ -4198,7 +5012,7 @@ function ensure_agent_settings(project_root, package_root, profile, force, user_
|
|
|
4198
5012
|
skip(`${SETTINGS_FILE} already exists`);
|
|
4199
5013
|
return;
|
|
4200
5014
|
}
|
|
4201
|
-
mkdirp(
|
|
5015
|
+
mkdirp(path20.dirname(target));
|
|
4202
5016
|
write_file(target, template_body);
|
|
4203
5017
|
const user_type_value = profile_values["user_type"] ?? "";
|
|
4204
5018
|
const suffix = user_type_value ? `, user_type=${user_type_value}` : "";
|
|
@@ -4211,7 +5025,7 @@ function ensure_vscode_bridge(project_root, package_type, force) {
|
|
|
4211
5025
|
const plugin_path = plugin_paths[package_type] ?? "./plugin/agent-config";
|
|
4212
5026
|
const bridge = { "chat.pluginLocations": { [plugin_path]: true } };
|
|
4213
5027
|
return merge_json_file(
|
|
4214
|
-
|
|
5028
|
+
path20.join(project_root, ".vscode", "settings.json"),
|
|
4215
5029
|
bridge,
|
|
4216
5030
|
force,
|
|
4217
5031
|
".vscode/settings.json"
|
|
@@ -4220,14 +5034,14 @@ function ensure_vscode_bridge(project_root, package_type, force) {
|
|
|
4220
5034
|
function ensure_augment_bridge(project_root, force) {
|
|
4221
5035
|
const bridge = { enabledPlugins: { "agent-config@event4u": true } };
|
|
4222
5036
|
return merge_json_file(
|
|
4223
|
-
|
|
5037
|
+
path20.join(project_root, ".augment", "settings.json"),
|
|
4224
5038
|
bridge,
|
|
4225
5039
|
force,
|
|
4226
5040
|
".augment/settings.json"
|
|
4227
5041
|
);
|
|
4228
5042
|
}
|
|
4229
|
-
var AUGMENT_USER_DIR =
|
|
4230
|
-
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");
|
|
4231
5045
|
var AUGMENT_DISPATCHER_TRAMPOLINE = "augment-dispatcher.sh";
|
|
4232
5046
|
var AUGMENT_LEGACY_TRAMPOLINES = [
|
|
4233
5047
|
"augment-chat-history.sh",
|
|
@@ -4236,29 +5050,29 @@ var AUGMENT_LEGACY_TRAMPOLINES = [
|
|
|
4236
5050
|
"augment-context-hygiene.sh"
|
|
4237
5051
|
];
|
|
4238
5052
|
function _deploy_augment_trampoline(package_root, name, force) {
|
|
4239
|
-
const src =
|
|
5053
|
+
const src = path20.join(package_root, "scripts", "hooks", name);
|
|
4240
5054
|
if (!pathExists(src)) {
|
|
4241
5055
|
skip(`augment trampoline missing in package: ${src}`);
|
|
4242
5056
|
return null;
|
|
4243
5057
|
}
|
|
4244
5058
|
mkdirp(AUGMENT_USER_HOOKS_DIR);
|
|
4245
|
-
const dst =
|
|
5059
|
+
const dst = path20.join(AUGMENT_USER_HOOKS_DIR, name);
|
|
4246
5060
|
const src_text = readText(src);
|
|
4247
5061
|
if (pathExists(dst) && readText(dst) === src_text && !force) {
|
|
4248
5062
|
skip(`~/.augment/hooks/${name} already up to date`);
|
|
4249
5063
|
} else {
|
|
4250
5064
|
writeText(dst, src_text);
|
|
4251
|
-
|
|
5065
|
+
fs20.chmodSync(dst, 493);
|
|
4252
5066
|
success(`~/.augment/hooks/${name} installed`);
|
|
4253
5067
|
}
|
|
4254
5068
|
return dst;
|
|
4255
5069
|
}
|
|
4256
5070
|
function _remove_legacy_augment_trampolines() {
|
|
4257
5071
|
for (const name of AUGMENT_LEGACY_TRAMPOLINES) {
|
|
4258
|
-
const legacy =
|
|
5072
|
+
const legacy = path20.join(AUGMENT_USER_HOOKS_DIR, name);
|
|
4259
5073
|
try {
|
|
4260
5074
|
if (isFile(legacy)) {
|
|
4261
|
-
|
|
5075
|
+
fs20.unlinkSync(legacy);
|
|
4262
5076
|
skip(`removed legacy ~/.augment/hooks/${name}`);
|
|
4263
5077
|
}
|
|
4264
5078
|
} catch (err) {
|
|
@@ -4278,7 +5092,7 @@ function ensure_augment_user_hooks(package_root, force) {
|
|
|
4278
5092
|
}
|
|
4279
5093
|
const settings_patch = { hooks: per_event };
|
|
4280
5094
|
return merge_json_file(
|
|
4281
|
-
|
|
5095
|
+
path20.join(AUGMENT_USER_DIR, "settings.json"),
|
|
4282
5096
|
settings_patch,
|
|
4283
5097
|
force,
|
|
4284
5098
|
"~/.augment/settings.json"
|
|
@@ -4293,7 +5107,7 @@ function _heal_legacy_claude_plugin_ids(p) {
|
|
|
4293
5107
|
if (!pathExists(p)) return [];
|
|
4294
5108
|
const data = read_json_file(p);
|
|
4295
5109
|
const enabled = data["enabledPlugins"];
|
|
4296
|
-
if (!
|
|
5110
|
+
if (!isPlainObject(enabled)) return [];
|
|
4297
5111
|
const removed = CLAUDE_LEGACY_PLUGIN_IDS.filter((pid) => pid in enabled);
|
|
4298
5112
|
if (removed.length === 0) return [];
|
|
4299
5113
|
for (const pid of removed) {
|
|
@@ -4303,7 +5117,7 @@ function _heal_legacy_claude_plugin_ids(p) {
|
|
|
4303
5117
|
return removed;
|
|
4304
5118
|
}
|
|
4305
5119
|
function ensure_claude_bridge(project_root, force) {
|
|
4306
|
-
const target =
|
|
5120
|
+
const target = path20.join(project_root, ".claude", "settings.json");
|
|
4307
5121
|
const healed = _heal_legacy_claude_plugin_ids(target);
|
|
4308
5122
|
for (const pid of healed) success(`.claude/settings.json: removed stale plugin id \`${pid}\``);
|
|
4309
5123
|
const bridge = withHostEnv({ enabledPlugins: { [CLAUDE_PLUGIN_ID]: true } }, project_root, success);
|
|
@@ -4321,29 +5135,29 @@ function ensure_cursor_bridge(project_root, force) {
|
|
|
4321
5135
|
}
|
|
4322
5136
|
const bridge = { version: 1, hooks };
|
|
4323
5137
|
return merge_json_file(
|
|
4324
|
-
|
|
5138
|
+
path20.join(project_root, ".cursor", "hooks.json"),
|
|
4325
5139
|
bridge,
|
|
4326
5140
|
force,
|
|
4327
5141
|
".cursor/hooks.json"
|
|
4328
5142
|
);
|
|
4329
5143
|
}
|
|
4330
|
-
var CURSOR_USER_DIR =
|
|
4331
|
-
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");
|
|
4332
5146
|
var CURSOR_DISPATCHER_TRAMPOLINE = "cursor-dispatcher.sh";
|
|
4333
5147
|
function ensure_cursor_user_hooks(package_root, force) {
|
|
4334
|
-
const src =
|
|
5148
|
+
const src = path20.join(package_root, "scripts", "hooks", CURSOR_DISPATCHER_TRAMPOLINE);
|
|
4335
5149
|
if (!pathExists(src)) {
|
|
4336
5150
|
skip(`cursor trampoline missing in package: ${src}`);
|
|
4337
5151
|
return [];
|
|
4338
5152
|
}
|
|
4339
5153
|
mkdirp(CURSOR_USER_HOOKS_DIR);
|
|
4340
|
-
const dst =
|
|
5154
|
+
const dst = path20.join(CURSOR_USER_HOOKS_DIR, CURSOR_DISPATCHER_TRAMPOLINE);
|
|
4341
5155
|
const src_text = readText(src);
|
|
4342
5156
|
if (pathExists(dst) && readText(dst) === src_text && !force) {
|
|
4343
5157
|
skip(`~/.cursor/hooks/${CURSOR_DISPATCHER_TRAMPOLINE} already up to date`);
|
|
4344
5158
|
} else {
|
|
4345
5159
|
writeText(dst, src_text);
|
|
4346
|
-
|
|
5160
|
+
fs20.chmodSync(dst, 493);
|
|
4347
5161
|
success(`~/.cursor/hooks/${CURSOR_DISPATCHER_TRAMPOLINE} installed`);
|
|
4348
5162
|
}
|
|
4349
5163
|
const hooks = {};
|
|
@@ -4352,7 +5166,7 @@ function ensure_cursor_user_hooks(package_root, force) {
|
|
|
4352
5166
|
}
|
|
4353
5167
|
const settings_patch = { version: 1, hooks };
|
|
4354
5168
|
return merge_json_file(
|
|
4355
|
-
|
|
5169
|
+
path20.join(CURSOR_USER_DIR, "hooks.json"),
|
|
4356
5170
|
settings_patch,
|
|
4357
5171
|
force,
|
|
4358
5172
|
"~/.cursor/hooks.json"
|
|
@@ -4387,12 +5201,12 @@ exit 0
|
|
|
4387
5201
|
`;
|
|
4388
5202
|
}
|
|
4389
5203
|
function ensure_cline_bridge(project_root, force) {
|
|
4390
|
-
const hooks_dir =
|
|
5204
|
+
const hooks_dir = path20.join(project_root, ".clinerules", "hooks");
|
|
4391
5205
|
mkdirp(hooks_dir);
|
|
4392
5206
|
const workspace_quoted = shlexQuote(resolvePath(project_root));
|
|
4393
5207
|
let written = 0;
|
|
4394
5208
|
for (const { slot, native } of hostBindings("cline")) {
|
|
4395
|
-
const target =
|
|
5209
|
+
const target = path20.join(hooks_dir, native);
|
|
4396
5210
|
const body = clineProjectHookBody(native, slot, workspace_quoted);
|
|
4397
5211
|
if (pathExists(target) && readText(target) === body && !force) {
|
|
4398
5212
|
continue;
|
|
@@ -4402,7 +5216,7 @@ function ensure_cline_bridge(project_root, force) {
|
|
|
4402
5216
|
continue;
|
|
4403
5217
|
}
|
|
4404
5218
|
writeText(target, body);
|
|
4405
|
-
|
|
5219
|
+
fs20.chmodSync(target, 493);
|
|
4406
5220
|
written += 1;
|
|
4407
5221
|
}
|
|
4408
5222
|
if (written) {
|
|
@@ -4411,27 +5225,27 @@ function ensure_cline_bridge(project_root, force) {
|
|
|
4411
5225
|
skip(".clinerules/hooks/ already up to date");
|
|
4412
5226
|
}
|
|
4413
5227
|
}
|
|
4414
|
-
var CLINE_USER_DIR =
|
|
5228
|
+
var CLINE_USER_DIR = path20.join(os6.homedir(), "Documents", "Cline", "Hooks");
|
|
4415
5229
|
var CLINE_DISPATCHER_TRAMPOLINE = "cline-dispatcher.sh";
|
|
4416
5230
|
function ensure_cline_user_hooks(package_root, force) {
|
|
4417
|
-
const src =
|
|
5231
|
+
const src = path20.join(package_root, "scripts", "hooks", CLINE_DISPATCHER_TRAMPOLINE);
|
|
4418
5232
|
if (!pathExists(src)) {
|
|
4419
5233
|
skip(`cline trampoline missing in package: ${src}`);
|
|
4420
5234
|
return;
|
|
4421
5235
|
}
|
|
4422
5236
|
mkdirp(CLINE_USER_DIR);
|
|
4423
|
-
const trampoline =
|
|
5237
|
+
const trampoline = path20.join(CLINE_USER_DIR, CLINE_DISPATCHER_TRAMPOLINE);
|
|
4424
5238
|
const src_text = readText(src);
|
|
4425
5239
|
if (pathExists(trampoline) && readText(trampoline) === src_text && !force) {
|
|
4426
5240
|
skip(`~/Documents/Cline/Hooks/${CLINE_DISPATCHER_TRAMPOLINE} already up to date`);
|
|
4427
5241
|
} else {
|
|
4428
5242
|
writeText(trampoline, src_text);
|
|
4429
|
-
|
|
5243
|
+
fs20.chmodSync(trampoline, 493);
|
|
4430
5244
|
success(`~/Documents/Cline/Hooks/${CLINE_DISPATCHER_TRAMPOLINE} installed`);
|
|
4431
5245
|
}
|
|
4432
5246
|
const trampoline_quoted = shlexQuote(trampoline);
|
|
4433
5247
|
for (const { slot, native } of hostBindings("cline")) {
|
|
4434
|
-
const wrapper =
|
|
5248
|
+
const wrapper = path20.join(CLINE_USER_DIR, native);
|
|
4435
5249
|
const body = `#!/usr/bin/env bash
|
|
4436
5250
|
# Generated by event4u/agent-config \u2014 DO NOT EDIT.
|
|
4437
5251
|
# User-scope Cline hook for ${native} \u2192 agent-config ${slot}.
|
|
@@ -4441,7 +5255,7 @@ exec ${trampoline_quoted} ${slot} ${native}
|
|
|
4441
5255
|
continue;
|
|
4442
5256
|
}
|
|
4443
5257
|
writeText(wrapper, body);
|
|
4444
|
-
|
|
5258
|
+
fs20.chmodSync(wrapper, 493);
|
|
4445
5259
|
}
|
|
4446
5260
|
}
|
|
4447
5261
|
function _windsurf_dispatch_command(ac_event, native) {
|
|
@@ -4457,29 +5271,29 @@ function ensure_windsurf_bridge(project_root, force) {
|
|
|
4457
5271
|
}
|
|
4458
5272
|
const bridge = { hooks };
|
|
4459
5273
|
return merge_json_file(
|
|
4460
|
-
|
|
5274
|
+
path20.join(project_root, ".windsurf", "hooks.json"),
|
|
4461
5275
|
bridge,
|
|
4462
5276
|
force,
|
|
4463
5277
|
".windsurf/hooks.json"
|
|
4464
5278
|
);
|
|
4465
5279
|
}
|
|
4466
|
-
var WINDSURF_USER_DIR =
|
|
4467
|
-
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");
|
|
4468
5282
|
var WINDSURF_DISPATCHER_TRAMPOLINE = "windsurf-dispatcher.sh";
|
|
4469
5283
|
function ensure_windsurf_user_hooks(package_root, force) {
|
|
4470
|
-
const src =
|
|
5284
|
+
const src = path20.join(package_root, "scripts", "hooks", WINDSURF_DISPATCHER_TRAMPOLINE);
|
|
4471
5285
|
if (!pathExists(src)) {
|
|
4472
5286
|
skip(`windsurf trampoline missing in package: ${src}`);
|
|
4473
5287
|
return [];
|
|
4474
5288
|
}
|
|
4475
5289
|
mkdirp(WINDSURF_USER_HOOKS_DIR);
|
|
4476
|
-
const dst =
|
|
5290
|
+
const dst = path20.join(WINDSURF_USER_HOOKS_DIR, WINDSURF_DISPATCHER_TRAMPOLINE);
|
|
4477
5291
|
const src_text = readText(src);
|
|
4478
5292
|
if (pathExists(dst) && readText(dst) === src_text && !force) {
|
|
4479
5293
|
skip(`~/.codeium/windsurf/hooks/${WINDSURF_DISPATCHER_TRAMPOLINE} already up to date`);
|
|
4480
5294
|
} else {
|
|
4481
5295
|
writeText(dst, src_text);
|
|
4482
|
-
|
|
5296
|
+
fs20.chmodSync(dst, 493);
|
|
4483
5297
|
success(`~/.codeium/windsurf/hooks/${WINDSURF_DISPATCHER_TRAMPOLINE} installed`);
|
|
4484
5298
|
}
|
|
4485
5299
|
const hooks = {};
|
|
@@ -4491,7 +5305,7 @@ function ensure_windsurf_user_hooks(package_root, force) {
|
|
|
4491
5305
|
}
|
|
4492
5306
|
const settings_patch = { hooks };
|
|
4493
5307
|
return merge_json_file(
|
|
4494
|
-
|
|
5308
|
+
path20.join(WINDSURF_USER_DIR, "hooks.json"),
|
|
4495
5309
|
settings_patch,
|
|
4496
5310
|
force,
|
|
4497
5311
|
"~/.codeium/windsurf/hooks.json"
|
|
@@ -4513,43 +5327,43 @@ function _gemini_hooks_dict(command_factory) {
|
|
|
4513
5327
|
function ensure_gemini_bridge(project_root, force) {
|
|
4514
5328
|
const bridge = { hooks: _gemini_hooks_dict(_gemini_dispatch_command) };
|
|
4515
5329
|
return merge_json_file(
|
|
4516
|
-
|
|
5330
|
+
path20.join(project_root, ".gemini", "settings.json"),
|
|
4517
5331
|
bridge,
|
|
4518
5332
|
force,
|
|
4519
5333
|
".gemini/settings.json"
|
|
4520
5334
|
);
|
|
4521
5335
|
}
|
|
4522
|
-
var GEMINI_USER_DIR =
|
|
4523
|
-
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");
|
|
4524
5338
|
var GEMINI_DISPATCHER_TRAMPOLINE = "gemini-dispatcher.sh";
|
|
4525
5339
|
function ensure_gemini_user_hooks(package_root, force) {
|
|
4526
|
-
const src =
|
|
5340
|
+
const src = path20.join(package_root, "scripts", "hooks", GEMINI_DISPATCHER_TRAMPOLINE);
|
|
4527
5341
|
if (!pathExists(src)) {
|
|
4528
5342
|
skip(`gemini trampoline missing in package: ${src}`);
|
|
4529
5343
|
return [];
|
|
4530
5344
|
}
|
|
4531
5345
|
mkdirp(GEMINI_USER_HOOKS_DIR);
|
|
4532
|
-
const dst =
|
|
5346
|
+
const dst = path20.join(GEMINI_USER_HOOKS_DIR, GEMINI_DISPATCHER_TRAMPOLINE);
|
|
4533
5347
|
const src_text = readText(src);
|
|
4534
5348
|
if (pathExists(dst) && readText(dst) === src_text && !force) {
|
|
4535
5349
|
skip(`~/.gemini/hooks/${GEMINI_DISPATCHER_TRAMPOLINE} already up to date`);
|
|
4536
5350
|
} else {
|
|
4537
5351
|
writeText(dst, src_text);
|
|
4538
|
-
|
|
5352
|
+
fs20.chmodSync(dst, 493);
|
|
4539
5353
|
success(`~/.gemini/hooks/${GEMINI_DISPATCHER_TRAMPOLINE} installed`);
|
|
4540
5354
|
}
|
|
4541
5355
|
const settings_patch = {
|
|
4542
5356
|
hooks: _gemini_hooks_dict((ac_event, native) => `${dst} ${ac_event} ${native}`)
|
|
4543
5357
|
};
|
|
4544
5358
|
return merge_json_file(
|
|
4545
|
-
|
|
5359
|
+
path20.join(GEMINI_USER_DIR, "settings.json"),
|
|
4546
5360
|
settings_patch,
|
|
4547
5361
|
force,
|
|
4548
5362
|
"~/.gemini/settings.json"
|
|
4549
5363
|
);
|
|
4550
5364
|
}
|
|
4551
5365
|
function ensure_copilot_bridge(project_root, force) {
|
|
4552
|
-
const target =
|
|
5366
|
+
const target = path20.join(project_root, ".github", "plugin", "marketplace.json");
|
|
4553
5367
|
const bridge = {
|
|
4554
5368
|
marketplace: {
|
|
4555
5369
|
name: "event4u-agent-marketplace",
|
|
@@ -4592,7 +5406,7 @@ See \`docs/setup/per-ide/roocode.md\` for the full activation guide.
|
|
|
4592
5406
|
Run \`./agent-config --help\` for available commands.
|
|
4593
5407
|
`;
|
|
4594
5408
|
function ensure_roocode_bridge(project_root, force) {
|
|
4595
|
-
const target =
|
|
5409
|
+
const target = path20.join(project_root, ".roo", "rules", "agent-config.md");
|
|
4596
5410
|
if (pathExists(target) && !force) {
|
|
4597
5411
|
skip(".roo/rules/agent-config.md already exists");
|
|
4598
5412
|
return;
|
|
@@ -4614,7 +5428,7 @@ To wire Claude Desktop to this project's rules, run:
|
|
|
4614
5428
|
Canonical rule and skill source: \`.augment/\` (see \`AGENTS.md\`).
|
|
4615
5429
|
`;
|
|
4616
5430
|
function ensure_claude_desktop_bridge(project_root, force) {
|
|
4617
|
-
const target =
|
|
5431
|
+
const target = path20.join(project_root, ".claude-desktop", "agent-config.md");
|
|
4618
5432
|
if (pathExists(target) && !force) {
|
|
4619
5433
|
skip(".claude-desktop/agent-config.md already exists");
|
|
4620
5434
|
return;
|
|
@@ -4639,7 +5453,7 @@ Or pass \`--read .aider/agent-config.md\` on the command line.
|
|
|
4639
5453
|
Canonical rule and skill source: \`.augment/\` (see \`AGENTS.md\`).
|
|
4640
5454
|
`;
|
|
4641
5455
|
function ensure_aider_bridge(project_root, force) {
|
|
4642
|
-
const target =
|
|
5456
|
+
const target = path20.join(project_root, ".aider", "agent-config.md");
|
|
4643
5457
|
if (pathExists(target) && !force) {
|
|
4644
5458
|
skip(".aider/agent-config.md already exists");
|
|
4645
5459
|
return;
|
|
@@ -4658,7 +5472,7 @@ developers where the rules and skills live.
|
|
|
4658
5472
|
Canonical rule and skill source: \`.augment/\` (see project \`AGENTS.md\`).
|
|
4659
5473
|
`;
|
|
4660
5474
|
function ensure_codex_bridge(project_root, force) {
|
|
4661
|
-
const target =
|
|
5475
|
+
const target = path20.join(project_root, ".codex", "agent-config.md");
|
|
4662
5476
|
if (pathExists(target) && !force) {
|
|
4663
5477
|
skip(".codex/agent-config.md already exists");
|
|
4664
5478
|
return;
|
|
@@ -4676,7 +5490,7 @@ rules per session. The canonical rule and skill source lives under
|
|
|
4676
5490
|
orientation).
|
|
4677
5491
|
`;
|
|
4678
5492
|
function ensure_continue_bridge(project_root, force) {
|
|
4679
|
-
const target =
|
|
5493
|
+
const target = path20.join(project_root, ".continue", "rules", "agent-config.md");
|
|
4680
5494
|
if (pathExists(target) && !force) {
|
|
4681
5495
|
skip(".continue/rules/agent-config.md already exists");
|
|
4682
5496
|
return;
|
|
@@ -4707,7 +5521,7 @@ orientation).
|
|
|
4707
5521
|
See \`docs/setup/per-ide/kilocode.md\` for the full activation guide.
|
|
4708
5522
|
`;
|
|
4709
5523
|
function ensure_kilocode_bridge(project_root, force) {
|
|
4710
|
-
const target =
|
|
5524
|
+
const target = path20.join(project_root, ".kilocode", "rules", "agent-config.md");
|
|
4711
5525
|
if (pathExists(target) && !force) {
|
|
4712
5526
|
skip(".kilocode/rules/agent-config.md already exists");
|
|
4713
5527
|
return;
|
|
@@ -4734,7 +5548,7 @@ canonical source (or symlink it):
|
|
|
4734
5548
|
Canonical rule and skill source: \`.augment/\` (see \`AGENTS.md\`).
|
|
4735
5549
|
`;
|
|
4736
5550
|
function ensure_zed_bridge(project_root, force) {
|
|
4737
|
-
const target =
|
|
5551
|
+
const target = path20.join(project_root, ".zed", "agent-config.md");
|
|
4738
5552
|
if (pathExists(target) && !force) {
|
|
4739
5553
|
skip(".zed/agent-config.md already exists");
|
|
4740
5554
|
return;
|
|
@@ -4755,7 +5569,7 @@ rules into your JetBrains profile.
|
|
|
4755
5569
|
Canonical rule and skill source: \`.augment/\` (see \`AGENTS.md\`).
|
|
4756
5570
|
`;
|
|
4757
5571
|
function ensure_jetbrains_bridge(project_root, force) {
|
|
4758
|
-
const target =
|
|
5572
|
+
const target = path20.join(project_root, ".jetbrains", "agent-config.md");
|
|
4759
5573
|
if (pathExists(target) && !force) {
|
|
4760
5574
|
skip(".jetbrains/agent-config.md already exists");
|
|
4761
5575
|
return;
|
|
@@ -4786,7 +5600,7 @@ session. The canonical rule and skill source lives under \`.augment/\`
|
|
|
4786
5600
|
See \`docs/setup/per-ide/kiro.md\` for the full activation guide.
|
|
4787
5601
|
`;
|
|
4788
5602
|
function ensure_kiro_bridge(project_root, force) {
|
|
4789
|
-
const target =
|
|
5603
|
+
const target = path20.join(project_root, ".kiro", "steering", "agent-config.md");
|
|
4790
5604
|
if (pathExists(target) && !force) {
|
|
4791
5605
|
skip(".kiro/steering/agent-config.md already exists");
|
|
4792
5606
|
return;
|
|
@@ -4823,35 +5637,35 @@ var SMOKE_BRIDGE_PATHS = {
|
|
|
4823
5637
|
};
|
|
4824
5638
|
function dirHasEntries(p) {
|
|
4825
5639
|
try {
|
|
4826
|
-
return
|
|
5640
|
+
return fs20.readdirSync(p).length > 0;
|
|
4827
5641
|
} catch {
|
|
4828
5642
|
return false;
|
|
4829
5643
|
}
|
|
4830
5644
|
}
|
|
4831
5645
|
function _resolve_tsx_invocation(scriptPath, scriptArgs) {
|
|
4832
5646
|
const binName = process2.platform === "win32" ? "tsx.cmd" : "tsx";
|
|
4833
|
-
let dir =
|
|
5647
|
+
let dir = path20.dirname(scriptPath);
|
|
4834
5648
|
for (; ; ) {
|
|
4835
|
-
const candidate =
|
|
5649
|
+
const candidate = path20.join(dir, "node_modules", ".bin", binName);
|
|
4836
5650
|
if (isFile(candidate)) {
|
|
4837
5651
|
return { command: candidate, args: [scriptPath, ...scriptArgs] };
|
|
4838
5652
|
}
|
|
4839
|
-
const parent =
|
|
5653
|
+
const parent = path20.dirname(dir);
|
|
4840
5654
|
if (parent === dir) break;
|
|
4841
5655
|
dir = parent;
|
|
4842
5656
|
}
|
|
4843
5657
|
return { command: "npx", args: ["tsx", scriptPath, ...scriptArgs] };
|
|
4844
5658
|
}
|
|
4845
5659
|
function _smoke_test_hooks(project_root, package_root) {
|
|
4846
|
-
const dispatcher =
|
|
4847
|
-
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");
|
|
4848
5662
|
if (!isFile(dispatcher) || !isFile(manifest)) return 0;
|
|
4849
5663
|
const failed = [];
|
|
4850
5664
|
const skipped = [];
|
|
4851
5665
|
const passed = [];
|
|
4852
5666
|
for (const [platform, native] of smokeProbeEvents()) {
|
|
4853
5667
|
const rel_bridge = SMOKE_BRIDGE_PATHS[platform] ?? "";
|
|
4854
|
-
const bridge_path = rel_bridge ?
|
|
5668
|
+
const bridge_path = rel_bridge ? path20.join(project_root, rel_bridge) : null;
|
|
4855
5669
|
const bridge_present = Boolean(
|
|
4856
5670
|
bridge_path && (isFile(bridge_path) || isDir(bridge_path) && dirHasEntries(bridge_path))
|
|
4857
5671
|
);
|
|
@@ -4900,7 +5714,7 @@ function _smoke_test_hooks(project_root, package_root) {
|
|
|
4900
5714
|
failed.push(`${platform}: dispatcher did not emit JSON plan`);
|
|
4901
5715
|
continue;
|
|
4902
5716
|
}
|
|
4903
|
-
const concerns =
|
|
5717
|
+
const concerns = isPlainObject(plan) ? plan["concerns"] : void 0;
|
|
4904
5718
|
if (!Array.isArray(concerns)) {
|
|
4905
5719
|
failed.push(`${platform}: plan.concerns missing or not a list`);
|
|
4906
5720
|
continue;
|
|
@@ -4982,47 +5796,6 @@ var PROJECT_BRIDGE_MARKERS = {
|
|
|
4982
5796
|
jetbrains: ".jetbrains/agent-config.md",
|
|
4983
5797
|
kiro: ".kiro/steering/agent-config.md"
|
|
4984
5798
|
};
|
|
4985
|
-
var _CLAUDE_SKILL_BUNDLE = [
|
|
4986
|
-
["dist/agent-src/rules", "rules"],
|
|
4987
|
-
["dist/agent-src/skills", "skills"],
|
|
4988
|
-
["dist/agent-src/commands", "commands"],
|
|
4989
|
-
["dist/agent-src/personas", "personas"]
|
|
4990
|
-
];
|
|
4991
|
-
var GLOBAL_DEPLOY_SOURCES = {
|
|
4992
|
-
"claude-code": _CLAUDE_SKILL_BUNDLE,
|
|
4993
|
-
augment: [
|
|
4994
|
-
["dist/agent-src/rules", "rules"],
|
|
4995
|
-
["dist/agent-src/skills", "skills"],
|
|
4996
|
-
["dist/agent-src/commands", "commands"],
|
|
4997
|
-
["dist/agent-src/contexts", "contexts"],
|
|
4998
|
-
["dist/agent-src/personas", "personas"],
|
|
4999
|
-
["dist/agent-src/templates", "templates"]
|
|
5000
|
-
],
|
|
5001
|
-
cursor: [
|
|
5002
|
-
["dist/agent-src/rules", "rules"],
|
|
5003
|
-
["dist/agent-src/commands", "commands"],
|
|
5004
|
-
["dist/agent-src/personas", "personas"]
|
|
5005
|
-
],
|
|
5006
|
-
windsurf: [["dist/agent-src/rules", "rules"]],
|
|
5007
|
-
cline: [["dist/agent-src/rules", ""]],
|
|
5008
|
-
"gemini-cli": _CLAUDE_SKILL_BUNDLE,
|
|
5009
|
-
codex: _CLAUDE_SKILL_BUNDLE,
|
|
5010
|
-
continue: _CLAUDE_SKILL_BUNDLE,
|
|
5011
|
-
roocode: _CLAUDE_SKILL_BUNDLE,
|
|
5012
|
-
kilocode: _CLAUDE_SKILL_BUNDLE,
|
|
5013
|
-
qoder: _CLAUDE_SKILL_BUNDLE,
|
|
5014
|
-
opencode: _CLAUDE_SKILL_BUNDLE,
|
|
5015
|
-
trae: _CLAUDE_SKILL_BUNDLE,
|
|
5016
|
-
antigravity: _CLAUDE_SKILL_BUNDLE,
|
|
5017
|
-
codebuddy: _CLAUDE_SKILL_BUNDLE,
|
|
5018
|
-
droid: _CLAUDE_SKILL_BUNDLE,
|
|
5019
|
-
warp: _CLAUDE_SKILL_BUNDLE,
|
|
5020
|
-
kiro: [
|
|
5021
|
-
["dist/agent-src/rules", "rules"],
|
|
5022
|
-
["dist/agent-src/skills", "steering"],
|
|
5023
|
-
["dist/agent-src/personas", "personas"]
|
|
5024
|
-
]
|
|
5025
|
-
};
|
|
5026
5799
|
function claudeDesktopMarkerBody(lockfile, anchor, bundles_dir, bundle_count) {
|
|
5027
5800
|
return `# agent-config \u2014 Claude Desktop marker
|
|
5028
5801
|
|
|
@@ -5051,9 +5824,9 @@ To remove this marker, delete this file.
|
|
|
5051
5824
|
`;
|
|
5052
5825
|
}
|
|
5053
5826
|
var _CLAUDE_DESKTOP_BUNDLES_SUBPATH = "claude-desktop/bundles";
|
|
5054
|
-
var GLOBAL_ROOT =
|
|
5055
|
-
var GLOBAL_USER_SETTINGS_PATH =
|
|
5056
|
-
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");
|
|
5057
5830
|
function _bridge_marker(tool_id, scope) {
|
|
5058
5831
|
if (scope === "global") return USER_SCOPE_PATHS[tool_id] ?? "";
|
|
5059
5832
|
return PROJECT_BRIDGE_MARKERS[tool_id] ?? "";
|
|
@@ -5099,10 +5872,10 @@ function _load_yaml_doc(p) {
|
|
|
5099
5872
|
return {};
|
|
5100
5873
|
}
|
|
5101
5874
|
const data = yamlSafeLoad(text);
|
|
5102
|
-
return
|
|
5875
|
+
return isPlainObject(data) ? data : {};
|
|
5103
5876
|
}
|
|
5104
5877
|
function _load_default_settings(package_root) {
|
|
5105
|
-
const template_source =
|
|
5878
|
+
const template_source = path20.join(package_root, "src", "config", "agent-settings.template.yml");
|
|
5106
5879
|
if (!pathExists(template_source)) return {};
|
|
5107
5880
|
let text;
|
|
5108
5881
|
try {
|
|
@@ -5112,15 +5885,15 @@ function _load_default_settings(package_root) {
|
|
|
5112
5885
|
}
|
|
5113
5886
|
const rendered = text.split(RULE_LOADING_TIER_PLACEHOLDER).join(DEFAULT_PROFILE).split(USER_TYPE_PLACEHOLDER).join("");
|
|
5114
5887
|
const data = yamlSafeLoad(rendered);
|
|
5115
|
-
return
|
|
5888
|
+
return isPlainObject(data) ? data : {};
|
|
5116
5889
|
}
|
|
5117
5890
|
var RULE_LAYER_CHOICES = ["global", "project", "both-acknowledged"];
|
|
5118
5891
|
function _suppress_rule_layer(project_root, suppress_dir) {
|
|
5119
|
-
const target =
|
|
5892
|
+
const target = path20.join(project_root, ".claude", "settings.local.json");
|
|
5120
5893
|
const existing = pathExists(target) ? read_json_file(target) : {};
|
|
5121
5894
|
let real_dir = suppress_dir;
|
|
5122
5895
|
try {
|
|
5123
|
-
real_dir =
|
|
5896
|
+
real_dir = fs20.realpathSync(suppress_dir);
|
|
5124
5897
|
} catch {
|
|
5125
5898
|
real_dir = suppress_dir;
|
|
5126
5899
|
}
|
|
@@ -5131,8 +5904,7 @@ function _suppress_rule_layer(project_root, suppress_dir) {
|
|
|
5131
5904
|
success(`.claude/settings.local.json: claudeMdExcludes += ${entry}`);
|
|
5132
5905
|
}
|
|
5133
5906
|
function _gate_rule_layer_overlap(project_root, layer, dry_run) {
|
|
5134
|
-
const global_dir =
|
|
5135
|
-
const project_dir = path13.join(project_root, ".claude", "rules");
|
|
5907
|
+
const [global_dir, project_dir] = hostRuleLayerDirs(project_root);
|
|
5136
5908
|
const g = readRuleLayer(global_dir);
|
|
5137
5909
|
const p = readRuleLayer(project_dir);
|
|
5138
5910
|
if (g === null || p === null) return true;
|
|
@@ -5220,9 +5992,9 @@ function detect_scope(cwd) {
|
|
|
5220
5992
|
if (pathExists(_resolve_settings_read(cwd))) {
|
|
5221
5993
|
return ["project", `existing ${SETTINGS_FILE}`];
|
|
5222
5994
|
}
|
|
5223
|
-
const has_manifest = SCOPE_DETECT_MANIFESTS.find((m) => pathExists(
|
|
5224
|
-
const has_ai_dir = SCOPE_DETECT_AI_DIRS.find((d) => isDir(
|
|
5225
|
-
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;
|
|
5226
5998
|
if (has_manifest && (has_ai_dir || has_ai_file)) {
|
|
5227
5999
|
const marker = has_ai_dir || has_ai_file;
|
|
5228
6000
|
return ["prompt", `manifest (${has_manifest}) + AI-tool config (${marker})`];
|
|
@@ -5243,7 +6015,7 @@ function readLineSyncRaw(promptText) {
|
|
|
5243
6015
|
for (; ; ) {
|
|
5244
6016
|
let n;
|
|
5245
6017
|
try {
|
|
5246
|
-
n =
|
|
6018
|
+
n = fs20.readSync(0, buf, 0, 1, null);
|
|
5247
6019
|
} catch (err) {
|
|
5248
6020
|
const code = err.code;
|
|
5249
6021
|
if (code === "EAGAIN") {
|
|
@@ -5326,26 +6098,26 @@ function _update_installed_tools_manifest(project_root, tools, scope, force, fil
|
|
|
5326
6098
|
}
|
|
5327
6099
|
write_manifest(target, version, entries);
|
|
5328
6100
|
if (!state.QUIET) {
|
|
5329
|
-
const rel = isRelativeTo(target, project_root) ?
|
|
6101
|
+
const rel = isRelativeTo(target, project_root) ? path20.relative(project_root, target) : target;
|
|
5330
6102
|
info(`Manifest updated: ${rel}`);
|
|
5331
6103
|
}
|
|
5332
6104
|
return 0;
|
|
5333
6105
|
}
|
|
5334
6106
|
function isRelativeTo(child, parent) {
|
|
5335
|
-
const rel =
|
|
5336
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
6107
|
+
const rel = path20.relative(parent, child);
|
|
6108
|
+
return rel === "" || !rel.startsWith("..") && !path20.isAbsolute(rel);
|
|
5337
6109
|
}
|
|
5338
6110
|
function _resolve_package_root_for_global() {
|
|
5339
|
-
const here = resolvePath(
|
|
5340
|
-
const candidate =
|
|
5341
|
-
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"))) {
|
|
5342
6114
|
fail(
|
|
5343
6115
|
`Could not locate agent-config package root from ${here}. Expected src/config/profiles/minimal.ini at the parent directory.`
|
|
5344
6116
|
);
|
|
5345
6117
|
}
|
|
5346
6118
|
return candidate;
|
|
5347
6119
|
}
|
|
5348
|
-
var CONSUMER_BRIDGE_MARKER_RELPATH =
|
|
6120
|
+
var CONSUMER_BRIDGE_MARKER_RELPATH = path20.join("agents", ".event4u-bridge.yml");
|
|
5349
6121
|
var MIGRATE_LEGACY_YAML_FILES = [".agent-settings.yml", ".agent-user.yml"];
|
|
5350
6122
|
var MIGRATE_LEGACY_TOOL_DIRS = [".augment", ".claude", ".cursor"];
|
|
5351
6123
|
var AGENT_CONFIG_PACKAGE_NAME = "@event4u/agent-config";
|
|
@@ -5353,7 +6125,7 @@ function _is_agent_config_source_repo(project_root) {
|
|
|
5353
6125
|
if (process2.env["AGENT_CONFIG_CONSUMER_MODE"] === "1") {
|
|
5354
6126
|
return [false, "consumer-mode-override"];
|
|
5355
6127
|
}
|
|
5356
|
-
const pkg_json =
|
|
6128
|
+
const pkg_json = path20.join(project_root, "package.json");
|
|
5357
6129
|
if (isFile(pkg_json)) {
|
|
5358
6130
|
let data = {};
|
|
5359
6131
|
try {
|
|
@@ -5361,17 +6133,17 @@ function _is_agent_config_source_repo(project_root) {
|
|
|
5361
6133
|
} catch {
|
|
5362
6134
|
data = {};
|
|
5363
6135
|
}
|
|
5364
|
-
if (
|
|
6136
|
+
if (isPlainObject(data) && data["name"] === AGENT_CONFIG_PACKAGE_NAME) {
|
|
5365
6137
|
return [true, "package.json:name"];
|
|
5366
6138
|
}
|
|
5367
6139
|
}
|
|
5368
|
-
if (isDir(
|
|
6140
|
+
if (isDir(path20.join(project_root, ".agent-src.uncondensed"))) {
|
|
5369
6141
|
return [true, ".agent-src.uncondensed/"];
|
|
5370
6142
|
}
|
|
5371
|
-
const packages_dir =
|
|
6143
|
+
const packages_dir = path20.join(project_root, "packages");
|
|
5372
6144
|
if (isDir(packages_dir)) {
|
|
5373
|
-
for (const child of
|
|
5374
|
-
if (isDir(
|
|
6145
|
+
for (const child of fs20.readdirSync(packages_dir)) {
|
|
6146
|
+
if (isDir(path20.join(packages_dir, child, ".agent-src.uncondensed"))) {
|
|
5375
6147
|
return [true, `packages/${child}/.agent-src.uncondensed/`];
|
|
5376
6148
|
}
|
|
5377
6149
|
}
|
|
@@ -5389,17 +6161,17 @@ function _detect_legacy_for_migration(project_root) {
|
|
|
5389
6161
|
}
|
|
5390
6162
|
return [];
|
|
5391
6163
|
}
|
|
5392
|
-
if (isFile(
|
|
6164
|
+
if (isFile(path20.join(project_root, INSTALL_MODE_MARKER_REL))) return [];
|
|
5393
6165
|
const found = [];
|
|
5394
6166
|
for (const name of MIGRATE_LEGACY_YAML_FILES) {
|
|
5395
|
-
if (isFile(
|
|
6167
|
+
if (isFile(path20.join(project_root, name))) {
|
|
5396
6168
|
found.push(name);
|
|
5397
|
-
} else if (isFile(
|
|
6169
|
+
} else if (isFile(path20.join(project_root, "settings", name))) {
|
|
5398
6170
|
found.push(`settings/${name}`);
|
|
5399
6171
|
}
|
|
5400
6172
|
}
|
|
5401
6173
|
for (const name of MIGRATE_LEGACY_TOOL_DIRS) {
|
|
5402
|
-
const p =
|
|
6174
|
+
const p = path20.join(project_root, name);
|
|
5403
6175
|
if (isDir(p) && !isSymlink(p)) {
|
|
5404
6176
|
found.push(`${name}/`);
|
|
5405
6177
|
}
|
|
@@ -5411,7 +6183,7 @@ function _prompt_migrate_to_global(project_root, artefacts) {
|
|
|
5411
6183
|
process2.stdout.write("\n");
|
|
5412
6184
|
warn("Legacy project-local artefacts detected \u2014 pre-ADR-020 layout:");
|
|
5413
6185
|
for (const rel of artefacts) {
|
|
5414
|
-
info(` ${
|
|
6186
|
+
info(` ${path20.join(project_root, rel)}`);
|
|
5415
6187
|
}
|
|
5416
6188
|
info("The unified `agent-config migrate` sweeps these in one pass.");
|
|
5417
6189
|
info("The wizard recreates fresh config afterwards.");
|
|
@@ -5440,22 +6212,22 @@ function _run_migrate_to_global(project_root) {
|
|
|
5440
6212
|
}
|
|
5441
6213
|
}
|
|
5442
6214
|
function _format_global_root_for_marker(global_root) {
|
|
5443
|
-
const home = resolvePath(
|
|
6215
|
+
const home = resolvePath(os6.homedir());
|
|
5444
6216
|
const resolved = resolvePath(global_root);
|
|
5445
|
-
const rel =
|
|
5446
|
-
if (rel === "" || rel.startsWith("..") ||
|
|
6217
|
+
const rel = path20.relative(home, resolved);
|
|
6218
|
+
if (rel === "" || rel.startsWith("..") || path20.isAbsolute(rel)) {
|
|
5447
6219
|
return global_root;
|
|
5448
6220
|
}
|
|
5449
|
-
return `~/${rel.split(
|
|
6221
|
+
return `~/${rel.split(path20.sep).join("/")}`;
|
|
5450
6222
|
}
|
|
5451
6223
|
function _remove_legacy_consumer_bridge_marker(project_root, env = null) {
|
|
5452
6224
|
const env_map = env ?? process2.env;
|
|
5453
6225
|
if (env_map["AGENT_CONFIG_DEV_MODE"] === "1") return null;
|
|
5454
|
-
if (isDir(
|
|
5455
|
-
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);
|
|
5456
6228
|
if (!isFile(target)) return null;
|
|
5457
6229
|
try {
|
|
5458
|
-
|
|
6230
|
+
fs20.rmSync(target);
|
|
5459
6231
|
} catch {
|
|
5460
6232
|
return null;
|
|
5461
6233
|
}
|
|
@@ -5469,7 +6241,7 @@ var PROJECT_ANCHOR_TOOLS = {
|
|
|
5469
6241
|
function _write_per_tool_project_anchors(project_root, tools, env = null, now = null) {
|
|
5470
6242
|
const env_map = env ?? process2.env;
|
|
5471
6243
|
if (env_map["AGENT_CONFIG_DEV_MODE"] === "1") return [];
|
|
5472
|
-
if (isDir(
|
|
6244
|
+
if (isDir(path20.join(project_root, ".agent-src.uncondensed"))) return [];
|
|
5473
6245
|
const global_root_str = _format_global_root_for_marker(
|
|
5474
6246
|
event4u_root(env_map)
|
|
5475
6247
|
);
|
|
@@ -5478,8 +6250,8 @@ function _write_per_tool_project_anchors(project_root, tools, env = null, now =
|
|
|
5478
6250
|
for (const tool_id of Object.keys(PROJECT_ANCHOR_TOOLS).sort()) {
|
|
5479
6251
|
const rel_path = PROJECT_ANCHOR_TOOLS[tool_id];
|
|
5480
6252
|
if (!tools.has(tool_id)) continue;
|
|
5481
|
-
const target =
|
|
5482
|
-
mkdirp(
|
|
6253
|
+
const target = path20.join(project_root, rel_path);
|
|
6254
|
+
mkdirp(path20.dirname(target));
|
|
5483
6255
|
const body = `# event4u/agent-config \u2014 per-tool project anchor (auto-written).
|
|
5484
6256
|
# Spec: docs/contracts/consumer-bridge.md \xA7 Per-tool anchor strategy.
|
|
5485
6257
|
# Tool: ${tool_id}. Resolves the global install directly \u2014 no
|
|
@@ -5497,7 +6269,7 @@ installed_at: ${stamp}
|
|
|
5497
6269
|
}
|
|
5498
6270
|
var PACKAGE_TAG_ID = "event4u/agent-config";
|
|
5499
6271
|
function _inject_package_tag(target, source, package_root) {
|
|
5500
|
-
if (
|
|
6272
|
+
if (path20.extname(target) !== ".md") return;
|
|
5501
6273
|
let text;
|
|
5502
6274
|
try {
|
|
5503
6275
|
text = readText(target);
|
|
@@ -5525,8 +6297,8 @@ function _inject_package_tag(target, source, package_root) {
|
|
|
5525
6297
|
resolved_src = source;
|
|
5526
6298
|
}
|
|
5527
6299
|
if (package_root !== null) {
|
|
5528
|
-
const rel =
|
|
5529
|
-
if (rel !== "" && !rel.startsWith("..") && !
|
|
6300
|
+
const rel = path20.relative(resolvePath(package_root), resolved_src);
|
|
6301
|
+
if (rel !== "" && !rel.startsWith("..") && !path20.isAbsolute(rel)) {
|
|
5530
6302
|
source_value = rel;
|
|
5531
6303
|
} else {
|
|
5532
6304
|
source_value = resolved_src;
|
|
@@ -5561,7 +6333,7 @@ function _escapes_package_root(resolved, package_root) {
|
|
|
5561
6333
|
if (package_root === null) return false;
|
|
5562
6334
|
let root;
|
|
5563
6335
|
try {
|
|
5564
|
-
root =
|
|
6336
|
+
root = fs20.realpathSync(package_root);
|
|
5565
6337
|
} catch {
|
|
5566
6338
|
return false;
|
|
5567
6339
|
}
|
|
@@ -5587,7 +6359,7 @@ function _copy_dir_dereferencing_symlinks(src, dest, force, package_root = null,
|
|
|
5587
6359
|
if (file_filter !== null && !file_filter(src)) return [0, 0, written_paths];
|
|
5588
6360
|
let resolved_src = src;
|
|
5589
6361
|
try {
|
|
5590
|
-
resolved_src =
|
|
6362
|
+
resolved_src = fs20.realpathSync(src);
|
|
5591
6363
|
} catch {
|
|
5592
6364
|
resolved_src = src;
|
|
5593
6365
|
}
|
|
@@ -5595,14 +6367,14 @@ function _copy_dir_dereferencing_symlinks(src, dest, force, package_root = null,
|
|
|
5595
6367
|
warn(`refused: ${src} dereferences outside the package root \u2014 not copied`);
|
|
5596
6368
|
return [0, 0, written_paths];
|
|
5597
6369
|
}
|
|
5598
|
-
mkdirp(
|
|
6370
|
+
mkdirp(path20.dirname(dest));
|
|
5599
6371
|
const decision = tracker.resolve(dest, force);
|
|
5600
6372
|
if (decision === "preserve") {
|
|
5601
6373
|
tracker.preserve(dest, resolved_src, package_root);
|
|
5602
6374
|
_log_tx_entry("skip", dest);
|
|
5603
6375
|
return [0, 1, written_paths];
|
|
5604
6376
|
}
|
|
5605
|
-
|
|
6377
|
+
fs20.copyFileSync(src, dest);
|
|
5606
6378
|
_inject_package_tag(dest, src, package_root);
|
|
5607
6379
|
_log_tx_entry("write", dest);
|
|
5608
6380
|
written_paths.push(dest);
|
|
@@ -5611,11 +6383,11 @@ function _copy_dir_dereferencing_symlinks(src, dest, force, package_root = null,
|
|
|
5611
6383
|
mkdirp(dest);
|
|
5612
6384
|
const walk = (node) => {
|
|
5613
6385
|
const acc = [];
|
|
5614
|
-
const names =
|
|
6386
|
+
const names = fs20.readdirSync(node).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
5615
6387
|
for (const name of names) {
|
|
5616
|
-
const entry =
|
|
6388
|
+
const entry = path20.join(node, name);
|
|
5617
6389
|
acc.push(entry);
|
|
5618
|
-
const lst =
|
|
6390
|
+
const lst = fs20.lstatSync(entry);
|
|
5619
6391
|
if (lst.isDirectory() && !lst.isSymbolicLink()) {
|
|
5620
6392
|
acc.push(...walk(entry));
|
|
5621
6393
|
}
|
|
@@ -5623,9 +6395,9 @@ function _copy_dir_dereferencing_symlinks(src, dest, force, package_root = null,
|
|
|
5623
6395
|
return acc;
|
|
5624
6396
|
};
|
|
5625
6397
|
for (const entry of walk(src)) {
|
|
5626
|
-
const rel =
|
|
5627
|
-
const target =
|
|
5628
|
-
const lst =
|
|
6398
|
+
const rel = path20.relative(src, entry);
|
|
6399
|
+
const target = path20.join(dest, rel);
|
|
6400
|
+
const lst = fs20.lstatSync(entry);
|
|
5629
6401
|
if (lst.isDirectory() && !lst.isSymbolicLink()) {
|
|
5630
6402
|
mkdirp(target);
|
|
5631
6403
|
continue;
|
|
@@ -5633,8 +6405,8 @@ function _copy_dir_dereferencing_symlinks(src, dest, force, package_root = null,
|
|
|
5633
6405
|
let resolvedIsDir = false;
|
|
5634
6406
|
let resolved = entry;
|
|
5635
6407
|
try {
|
|
5636
|
-
resolved =
|
|
5637
|
-
resolvedIsDir =
|
|
6408
|
+
resolved = fs20.realpathSync(entry);
|
|
6409
|
+
resolvedIsDir = fs20.statSync(entry).isDirectory();
|
|
5638
6410
|
} catch {
|
|
5639
6411
|
resolvedIsDir = false;
|
|
5640
6412
|
}
|
|
@@ -5666,8 +6438,8 @@ function _copy_dir_dereferencing_symlinks(src, dest, force, package_root = null,
|
|
|
5666
6438
|
_log_tx_entry("skip", target);
|
|
5667
6439
|
continue;
|
|
5668
6440
|
}
|
|
5669
|
-
mkdirp(
|
|
5670
|
-
|
|
6441
|
+
mkdirp(path20.dirname(target));
|
|
6442
|
+
fs20.copyFileSync(resolved, target);
|
|
5671
6443
|
_inject_package_tag(target, resolved, package_root);
|
|
5672
6444
|
_log_tx_entry("write", target);
|
|
5673
6445
|
written += 1;
|
|
@@ -5680,7 +6452,7 @@ function _claude_desktop_bundles_dir() {
|
|
|
5680
6452
|
}
|
|
5681
6453
|
function _write_claude_desktop_marker(force, lockfile_path2, bundles_dir, bundle_count) {
|
|
5682
6454
|
const anchor = expanduser3(USER_SCOPE_PATHS["claude-desktop"]);
|
|
5683
|
-
const target =
|
|
6455
|
+
const target = path20.join(anchor, "agent-config.md");
|
|
5684
6456
|
mkdirp(anchor);
|
|
5685
6457
|
const body = claudeDesktopMarkerBody(lockfile_path2, anchor, bundles_dir, bundle_count);
|
|
5686
6458
|
if (tracker.resolve(target, force) === "preserve") {
|
|
@@ -5705,27 +6477,15 @@ function _deploy_claude_desktop(force, package_root, lockfile_path2) {
|
|
|
5705
6477
|
return [bundle_count, 0, "deployed", [bundles_dir, ...marker_paths]];
|
|
5706
6478
|
}
|
|
5707
6479
|
var _CLAUDE_FLAT_WRAPPER_EXTRA = /* @__PURE__ */ new Set(["commit"]);
|
|
5708
|
-
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()) {
|
|
5709
6481
|
const wrapped = [];
|
|
5710
6482
|
const collisions = [];
|
|
5711
|
-
const
|
|
5712
|
-
const
|
|
5713
|
-
let flat_entries = [];
|
|
5714
|
-
try {
|
|
5715
|
-
flat_entries = fs15.readdirSync(commands_dir).filter((f) => f.endsWith(".md"));
|
|
5716
|
-
} catch {
|
|
5717
|
-
}
|
|
5718
|
-
for (const fname of flat_entries.sort()) {
|
|
5719
|
-
const slug = fname.slice(0, -".md".length);
|
|
5720
|
-
if (!is_claude_builtin_name(slug)) continue;
|
|
5721
|
-
fs15.rmSync(path13.join(commands_dir, fname), { force: true });
|
|
5722
|
-
current_files.delete(`commands/${fname}`);
|
|
5723
|
-
reserved.push(slug);
|
|
5724
|
-
}
|
|
6483
|
+
const commands_dir = path20.join(anchor, "commands");
|
|
6484
|
+
const { reserved, foreign } = sweepReservedNames(commands_dir, current_files, is_claude_builtin_name, recorded_files);
|
|
5725
6485
|
const eligible = new Set(_CLAUDE_FLAT_WRAPPER_EXTRA);
|
|
5726
6486
|
try {
|
|
5727
6487
|
const manifest = JSON.parse(
|
|
5728
|
-
|
|
6488
|
+
fs20.readFileSync(path20.join(package_root, "dist", "discovery", "discovery-manifest.json"), "utf8")
|
|
5729
6489
|
);
|
|
5730
6490
|
for (const a of manifest.artefacts ?? []) {
|
|
5731
6491
|
if (a.category !== "command" || typeof a.slug !== "string") continue;
|
|
@@ -5736,27 +6496,27 @@ function _apply_claude_flat_command_wrappers(anchor, package_root, current_files
|
|
|
5736
6496
|
}
|
|
5737
6497
|
for (const slug of [...eligible].sort()) {
|
|
5738
6498
|
const flat_rel = `commands/${slug}.md`;
|
|
5739
|
-
const flat_abs =
|
|
5740
|
-
if (!
|
|
5741
|
-
const skill_dir =
|
|
5742
|
-
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)) {
|
|
5743
6503
|
collisions.push(slug);
|
|
5744
6504
|
continue;
|
|
5745
6505
|
}
|
|
5746
|
-
let body =
|
|
6506
|
+
let body = fs20.readFileSync(flat_abs, "utf8");
|
|
5747
6507
|
if (body.startsWith("---\n") && !/^name:/m.test(body.split("\n---")[0] ?? "")) {
|
|
5748
6508
|
body = body.replace("---\n", `---
|
|
5749
6509
|
name: ${slug}
|
|
5750
6510
|
`);
|
|
5751
6511
|
}
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
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 });
|
|
5755
6515
|
current_files.delete(flat_rel);
|
|
5756
6516
|
current_files.add(`skills/${slug}/SKILL.md`);
|
|
5757
6517
|
wrapped.push(slug);
|
|
5758
6518
|
}
|
|
5759
|
-
return { wrapped, collisions, reserved };
|
|
6519
|
+
return { wrapped, collisions, reserved, foreign };
|
|
5760
6520
|
}
|
|
5761
6521
|
function _deploy_global_content(tools, force, package_root, lockfile_path2) {
|
|
5762
6522
|
const results = {};
|
|
@@ -5783,8 +6543,8 @@ function _deploy_global_content(tools, force, package_root, lockfile_path2) {
|
|
|
5783
6543
|
const written_paths = [];
|
|
5784
6544
|
let current_files = /* @__PURE__ */ new Set();
|
|
5785
6545
|
for (const [src_rel, dest_sub] of plan) {
|
|
5786
|
-
const src =
|
|
5787
|
-
const dest = dest_sub ?
|
|
6546
|
+
const src = path20.join(package_root, src_rel);
|
|
6547
|
+
const dest = dest_sub ? path20.join(anchor, dest_sub) : anchor;
|
|
5788
6548
|
const rule_filter = _rule_filter_for_source(src_rel, rule_scope);
|
|
5789
6549
|
const [w, s, paths] = _copy_dir_dereferencing_symlinks(
|
|
5790
6550
|
src,
|
|
@@ -5806,15 +6566,31 @@ function _deploy_global_content(tools, force, package_root, lockfile_path2) {
|
|
|
5806
6566
|
);
|
|
5807
6567
|
}
|
|
5808
6568
|
if (tool_id === "claude-code") {
|
|
5809
|
-
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
|
+
);
|
|
5810
6573
|
rewriteAndReport(
|
|
5811
|
-
|
|
6574
|
+
path20.join(anchor, "rules"),
|
|
5812
6575
|
state.QUIET,
|
|
5813
6576
|
info,
|
|
5814
6577
|
warn,
|
|
5815
6578
|
res,
|
|
5816
|
-
|
|
6579
|
+
preserved_now
|
|
5817
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);
|
|
5818
6594
|
}
|
|
5819
6595
|
const missing_targets = _verify_deploy_targets(anchor, plan);
|
|
5820
6596
|
if (missing_targets.length > 0) {
|
|
@@ -5856,10 +6632,10 @@ function _deploy_global_content(tools, force, package_root, lockfile_path2) {
|
|
|
5856
6632
|
results[tool_id] = [written_total, skipped_total, "deployed", written_paths];
|
|
5857
6633
|
if (tool_id === "claude-code") {
|
|
5858
6634
|
try {
|
|
5859
|
-
const manifest =
|
|
6635
|
+
const manifest = path20.join(package_root, "src", "scripts", "hook_manifest.yaml");
|
|
5860
6636
|
const matrix = build_claude_hook_matrix(manifest);
|
|
5861
6637
|
const res = ensure_managed_hooks(
|
|
5862
|
-
|
|
6638
|
+
path20.join(anchor, "settings.json"),
|
|
5863
6639
|
matrix
|
|
5864
6640
|
);
|
|
5865
6641
|
if (!state.QUIET) {
|
|
@@ -5896,7 +6672,7 @@ function _preview_global_reap(tools, package_root) {
|
|
|
5896
6672
|
const anchor = expanduser3(anchor_raw);
|
|
5897
6673
|
let current_files = /* @__PURE__ */ new Set();
|
|
5898
6674
|
for (const [src_rel, dest_sub] of plan) {
|
|
5899
|
-
const src =
|
|
6675
|
+
const src = path20.join(package_root, src_rel);
|
|
5900
6676
|
current_files = setUnion(
|
|
5901
6677
|
current_files,
|
|
5902
6678
|
expected_deploy_files(
|
|
@@ -5930,14 +6706,14 @@ function _preview_global_reap(tools, package_root) {
|
|
|
5930
6706
|
function _verify_deploy_targets(anchor, plan) {
|
|
5931
6707
|
const missing = [];
|
|
5932
6708
|
for (const [, dest_sub] of plan) {
|
|
5933
|
-
const target = dest_sub ?
|
|
6709
|
+
const target = dest_sub ? path20.join(anchor, dest_sub) : anchor;
|
|
5934
6710
|
const label = dest_sub || ".";
|
|
5935
6711
|
if (!isDir(target)) {
|
|
5936
6712
|
missing.push(label);
|
|
5937
6713
|
continue;
|
|
5938
6714
|
}
|
|
5939
6715
|
try {
|
|
5940
|
-
const entries =
|
|
6716
|
+
const entries = fs20.readdirSync(target);
|
|
5941
6717
|
if (entries.length === 0) missing.push(label);
|
|
5942
6718
|
} catch {
|
|
5943
6719
|
missing.push(label);
|
|
@@ -5955,54 +6731,30 @@ function _resolve_global_settings_doc() {
|
|
|
5955
6731
|
}
|
|
5956
6732
|
function _resolve_global_settings_path() {
|
|
5957
6733
|
const root = event4u_root();
|
|
5958
|
-
const canonical =
|
|
6734
|
+
const canonical = path20.join(root, "settings", SETTINGS_FILE);
|
|
5959
6735
|
if (pathExists(canonical)) return canonical;
|
|
5960
|
-
const legacy =
|
|
6736
|
+
const legacy = path20.join(root, SETTINGS_FILE);
|
|
5961
6737
|
if (pathExists(legacy)) return legacy;
|
|
5962
6738
|
return null;
|
|
5963
6739
|
}
|
|
5964
6740
|
function _resolve_scoped_projection(package_root) {
|
|
5965
6741
|
const doc = _resolve_global_settings_doc() ?? _load_default_settings(package_root);
|
|
5966
|
-
const projection =
|
|
6742
|
+
const projection = isPlainObject(doc["projection"]) ? doc["projection"] : {};
|
|
5967
6743
|
const mode = projectionModeOf(projection["mode"]);
|
|
5968
|
-
const runtime =
|
|
6744
|
+
const runtime = isPlainObject(doc["runtime"]) ? doc["runtime"] : {};
|
|
5969
6745
|
const active_packs_raw = runtime["active_packs"];
|
|
5970
6746
|
const active_packs = Array.isArray(active_packs_raw) ? active_packs_raw.filter((v) => typeof v === "string") : [];
|
|
5971
6747
|
return { mode, active_packs };
|
|
5972
6748
|
}
|
|
5973
6749
|
function _resolve_global_rule_scope(package_root) {
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
}
|
|
5982
|
-
let text;
|
|
5983
|
-
try {
|
|
5984
|
-
text = readText(settings_path);
|
|
5985
|
-
} catch (e) {
|
|
5986
|
-
warn(
|
|
5987
|
-
`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.`
|
|
5988
|
-
);
|
|
5989
|
-
return LEGACY_ALL;
|
|
5990
|
-
}
|
|
5991
|
-
const parsed = yamlSafeLoad(text);
|
|
5992
|
-
if (!_isPlainObject(parsed)) {
|
|
5993
|
-
warn(
|
|
5994
|
-
`${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.`
|
|
5995
|
-
);
|
|
5996
|
-
return LEGACY_ALL;
|
|
5997
|
-
}
|
|
5998
|
-
try {
|
|
5999
|
-
return ruleScopeFromSettings(parsed, package_root);
|
|
6000
|
-
} catch (e) {
|
|
6001
|
-
warn(
|
|
6002
|
-
`could not derive rule scope from ${settings_path} (${String(e)}) \u2014 falling back to legacy-all; ALL rules will be installed.`
|
|
6003
|
-
);
|
|
6004
|
-
return LEGACY_ALL;
|
|
6005
|
-
}
|
|
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
|
+
});
|
|
6006
6758
|
}
|
|
6007
6759
|
function _rule_filter_for_source(src_rel, scope) {
|
|
6008
6760
|
if (src_rel !== RULE_SOURCE_REL) return null;
|
|
@@ -6068,7 +6820,7 @@ function install_global(tools, force, project_root = null, core_only = false) {
|
|
|
6068
6820
|
info(` schema_version=1, agent_config_version=${installed_version}`);
|
|
6069
6821
|
info(` tools=${merged_tools.join(",")}`);
|
|
6070
6822
|
}
|
|
6071
|
-
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"))) {
|
|
6072
6824
|
const drift = collect_drift(project_root);
|
|
6073
6825
|
if (!state.QUIET) {
|
|
6074
6826
|
process2.stdout.write("\n");
|
|
@@ -6182,19 +6934,19 @@ function install_global(tools, force, project_root = null, core_only = false) {
|
|
|
6182
6934
|
}
|
|
6183
6935
|
}
|
|
6184
6936
|
}
|
|
6185
|
-
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"))) {
|
|
6186
6938
|
const files_by_tool = filesByToolFromDeploy(deploy_results);
|
|
6187
6939
|
const rc = _update_installed_tools_manifest(project_root, tools, "global", force, files_by_tool);
|
|
6188
6940
|
if (rc !== 0) return rc;
|
|
6189
6941
|
const removed_marker = _remove_legacy_consumer_bridge_marker(project_root);
|
|
6190
6942
|
if (removed_marker !== null && !state.QUIET) {
|
|
6191
|
-
const rel = isRelativeTo(removed_marker, project_root) ?
|
|
6943
|
+
const rel = isRelativeTo(removed_marker, project_root) ? path20.relative(project_root, removed_marker) : removed_marker;
|
|
6192
6944
|
info(`Removed legacy bridge marker: ${rel}`);
|
|
6193
6945
|
}
|
|
6194
6946
|
const anchor_paths = _write_per_tool_project_anchors(project_root, tools);
|
|
6195
6947
|
if (anchor_paths.length > 0 && !state.QUIET) {
|
|
6196
6948
|
for (const p of anchor_paths) {
|
|
6197
|
-
const rel = isRelativeTo(p, project_root) ?
|
|
6949
|
+
const rel = isRelativeTo(p, project_root) ? path20.relative(project_root, p) : p;
|
|
6198
6950
|
info(`Project anchor written: ${rel}`);
|
|
6199
6951
|
}
|
|
6200
6952
|
}
|
|
@@ -6230,8 +6982,8 @@ function install_global(tools, force, project_root = null, core_only = false) {
|
|
|
6230
6982
|
}
|
|
6231
6983
|
function _catalogue_truncation_warnings(deploy_results, project_root) {
|
|
6232
6984
|
const log_candidates = [
|
|
6233
|
-
|
|
6234
|
-
...project_root ? [
|
|
6985
|
+
path20.join(event4u_root(), "state", "skill-catalogue.jsonl"),
|
|
6986
|
+
...project_root ? [path20.join(project_root, OBSERVATION_LOG)] : []
|
|
6235
6987
|
];
|
|
6236
6988
|
const records = log_candidates.flatMap((p) => readObservationLog(p));
|
|
6237
6989
|
if (records.length === 0) return [];
|
|
@@ -6254,13 +7006,13 @@ function _catalogue_truncation_warnings(deploy_results, project_root) {
|
|
|
6254
7006
|
function _scoped_migration_notice(deploy_results, project_root, package_root, probe) {
|
|
6255
7007
|
if (!isInteractiveSession(probe)) return [];
|
|
6256
7008
|
const log_candidates = [
|
|
6257
|
-
|
|
6258
|
-
...project_root ? [
|
|
7009
|
+
path20.join(event4u_root(), "state", "skill-catalogue.jsonl"),
|
|
7010
|
+
...project_root ? [path20.join(project_root, OBSERVATION_LOG)] : []
|
|
6259
7011
|
];
|
|
6260
7012
|
const limits = knownHostLimits(log_candidates.flatMap((p) => readObservationLog(p)));
|
|
6261
7013
|
if (limits.size === 0) return [];
|
|
6262
7014
|
const resolved = _resolve_scoped_projection(package_root);
|
|
6263
|
-
const settings_path = _resolve_global_settings_path() ??
|
|
7015
|
+
const settings_path = _resolve_global_settings_path() ?? path20.join(event4u_root(), "settings", SETTINGS_FILE);
|
|
6264
7016
|
for (const tool_id of Object.keys(deploy_results).sort()) {
|
|
6265
7017
|
const [, , status] = deploy_results[tool_id];
|
|
6266
7018
|
if (status !== "deployed") continue;
|
|
@@ -6279,8 +7031,8 @@ function _scoped_migration_notice(deploy_results, project_root, package_root, pr
|
|
|
6279
7031
|
}
|
|
6280
7032
|
return [];
|
|
6281
7033
|
}
|
|
6282
|
-
var SETTINGS_SURFACE_REL =
|
|
6283
|
-
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");
|
|
6284
7036
|
function _current_settings_surface(version) {
|
|
6285
7037
|
const jsonSchema = zodToJsonSchema(settingsSchema, {
|
|
6286
7038
|
name: "AgentSettings",
|
|
@@ -6291,20 +7043,20 @@ function _current_settings_surface(version) {
|
|
|
6291
7043
|
}
|
|
6292
7044
|
function _write_settings_surface_snapshot(installed_version) {
|
|
6293
7045
|
const root = event4u_root();
|
|
6294
|
-
const surface_path =
|
|
6295
|
-
const delta_path =
|
|
7046
|
+
const surface_path = path20.join(root, SETTINGS_SURFACE_REL);
|
|
7047
|
+
const delta_path = path20.join(root, SETTINGS_DELTA_REL);
|
|
6296
7048
|
const next = _current_settings_surface(installed_version);
|
|
6297
7049
|
let previous = null;
|
|
6298
7050
|
try {
|
|
6299
|
-
const parsed = JSON.parse(
|
|
7051
|
+
const parsed = JSON.parse(fs20.readFileSync(surface_path, "utf8"));
|
|
6300
7052
|
if (parsed !== null && typeof parsed === "object" && parsed.entries !== void 0) previous = parsed;
|
|
6301
7053
|
} catch {
|
|
6302
7054
|
}
|
|
6303
7055
|
if (previous !== null && previous.version !== next.version) {
|
|
6304
7056
|
const delta = computeSurfaceDelta(previous, next);
|
|
6305
7057
|
if (delta.changes.length > 0) {
|
|
6306
|
-
|
|
6307
|
-
|
|
7058
|
+
fs20.mkdirSync(path20.dirname(delta_path), { recursive: true, mode: 448 });
|
|
7059
|
+
fs20.writeFileSync(delta_path, `${JSON.stringify(delta, null, 2)}
|
|
6308
7060
|
`, { mode: 384 });
|
|
6309
7061
|
if (!state.QUIET) {
|
|
6310
7062
|
const counts = {};
|
|
@@ -6316,8 +7068,8 @@ function _write_settings_surface_snapshot(installed_version) {
|
|
|
6316
7068
|
}
|
|
6317
7069
|
}
|
|
6318
7070
|
}
|
|
6319
|
-
|
|
6320
|
-
|
|
7071
|
+
fs20.mkdirSync(path20.dirname(surface_path), { recursive: true, mode: 448 });
|
|
7072
|
+
fs20.writeFileSync(surface_path, `${JSON.stringify(next, null, 2)}
|
|
6321
7073
|
`, { mode: 384 });
|
|
6322
7074
|
}
|
|
6323
7075
|
function arrayStrEqual(a, b) {
|
|
@@ -6533,17 +7285,17 @@ function _is_tool_enabled(tools, tool_id) {
|
|
|
6533
7285
|
return tools.has(tool_id);
|
|
6534
7286
|
}
|
|
6535
7287
|
function _minimal_templates_root() {
|
|
6536
|
-
const start = resolvePath(
|
|
7288
|
+
const start = resolvePath(_HERE2);
|
|
6537
7289
|
const chain = [start];
|
|
6538
7290
|
let cur = start;
|
|
6539
7291
|
for (; ; ) {
|
|
6540
|
-
const parent =
|
|
7292
|
+
const parent = path20.dirname(cur);
|
|
6541
7293
|
if (parent === cur) break;
|
|
6542
7294
|
chain.push(parent);
|
|
6543
7295
|
cur = parent;
|
|
6544
7296
|
}
|
|
6545
7297
|
for (const ancestor of chain) {
|
|
6546
|
-
const candidate =
|
|
7298
|
+
const candidate = path20.join(ancestor, "src", "templates", "minimal");
|
|
6547
7299
|
if (isDir(candidate)) return candidate;
|
|
6548
7300
|
}
|
|
6549
7301
|
fail("Could not locate src/templates/minimal/ \u2014 package install is corrupt.");
|
|
@@ -6551,9 +7303,9 @@ function _minimal_templates_root() {
|
|
|
6551
7303
|
var INSTALL_MODE_MARKER_REL = "agents/.agent-state/install-mode.txt";
|
|
6552
7304
|
function _write_install_mode_marker(project_root, mode) {
|
|
6553
7305
|
if (mode !== "minimal" && mode !== "full") return;
|
|
6554
|
-
const marker =
|
|
7306
|
+
const marker = path20.join(project_root, INSTALL_MODE_MARKER_REL);
|
|
6555
7307
|
try {
|
|
6556
|
-
mkdirp(
|
|
7308
|
+
mkdirp(path20.dirname(marker));
|
|
6557
7309
|
writeText(marker, `${mode}
|
|
6558
7310
|
`);
|
|
6559
7311
|
} catch {
|
|
@@ -6562,7 +7314,7 @@ function _write_install_mode_marker(project_root, mode) {
|
|
|
6562
7314
|
function install_minimal(target_root_in, force, user_type = "") {
|
|
6563
7315
|
let target_root = resolvePath(target_root_in);
|
|
6564
7316
|
mkdirp(target_root);
|
|
6565
|
-
const parent =
|
|
7317
|
+
const parent = path20.dirname(target_root);
|
|
6566
7318
|
if (parent !== target_root) {
|
|
6567
7319
|
const existing = find_project_root_with_anchor(parent);
|
|
6568
7320
|
if (existing !== null && existing[0] !== target_root) {
|
|
@@ -6573,21 +7325,21 @@ function install_minimal(target_root_in, force, user_type = "") {
|
|
|
6573
7325
|
}
|
|
6574
7326
|
}
|
|
6575
7327
|
const templates = _minimal_templates_root();
|
|
6576
|
-
const settings_src =
|
|
6577
|
-
const overrides_gitkeep_src =
|
|
6578
|
-
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");
|
|
6579
7331
|
if (!isFile(settings_src)) fail(`Bundled minimal settings template missing under ${templates}`);
|
|
6580
7332
|
if (!isFile(overrides_gitkeep_src) || !isFile(overrides_readme_src)) {
|
|
6581
7333
|
fail(`Bundled overrides scaffold templates missing under ${templates}`);
|
|
6582
7334
|
}
|
|
6583
7335
|
info(`Minimal init \u2192 ${target_root}`);
|
|
6584
|
-
const overrides_root =
|
|
7336
|
+
const overrides_root = path20.join(target_root, "agents", "overrides");
|
|
6585
7337
|
mkdirp(overrides_root);
|
|
6586
7338
|
const gitkeep_body = readText(overrides_gitkeep_src);
|
|
6587
7339
|
for (const sub of ["rules", "skills", "commands"]) {
|
|
6588
|
-
const sub_dir =
|
|
7340
|
+
const sub_dir = path20.join(overrides_root, sub);
|
|
6589
7341
|
mkdirp(sub_dir);
|
|
6590
|
-
const gitkeep_dst =
|
|
7342
|
+
const gitkeep_dst = path20.join(sub_dir, ".gitkeep");
|
|
6591
7343
|
if (pathExists(gitkeep_dst) && !force) {
|
|
6592
7344
|
skip(`agents/overrides/${sub}/.gitkeep already exists (use --force to overwrite)`);
|
|
6593
7345
|
} else {
|
|
@@ -6595,7 +7347,7 @@ function install_minimal(target_root_in, force, user_type = "") {
|
|
|
6595
7347
|
success(`Wrote agents/overrides/${sub}/.gitkeep`);
|
|
6596
7348
|
}
|
|
6597
7349
|
}
|
|
6598
|
-
const readme_dst =
|
|
7350
|
+
const readme_dst = path20.join(overrides_root, "README.md");
|
|
6599
7351
|
if (pathExists(readme_dst) && !force) {
|
|
6600
7352
|
skip("agents/overrides/README.md already exists (use --force to overwrite)");
|
|
6601
7353
|
} else {
|
|
@@ -6613,14 +7365,14 @@ function install_minimal(target_root_in, force, user_type = "") {
|
|
|
6613
7365
|
personal:
|
|
6614
7366
|
user_type: ${user_type}
|
|
6615
7367
|
`;
|
|
6616
|
-
mkdirp(
|
|
7368
|
+
mkdirp(path20.dirname(settings_dst));
|
|
6617
7369
|
writeText(settings_dst, body);
|
|
6618
7370
|
success(`Wrote ${SETTINGS_FILE} (user_type=${user_type})`);
|
|
6619
7371
|
}
|
|
6620
7372
|
}
|
|
6621
7373
|
const removed_marker = _remove_legacy_consumer_bridge_marker(target_root);
|
|
6622
7374
|
if (removed_marker !== null) {
|
|
6623
|
-
const rel = isRelativeTo(removed_marker, target_root) ?
|
|
7375
|
+
const rel = isRelativeTo(removed_marker, target_root) ? path20.relative(target_root, removed_marker) : removed_marker;
|
|
6624
7376
|
success(`Removed legacy bridge marker: ${rel}`);
|
|
6625
7377
|
}
|
|
6626
7378
|
_write_install_mode_marker(target_root, "minimal");
|
|
@@ -6694,7 +7446,7 @@ function run_interactive_init(project_root, force) {
|
|
|
6694
7446
|
);
|
|
6695
7447
|
return 0;
|
|
6696
7448
|
}
|
|
6697
|
-
const target =
|
|
7449
|
+
const target = path20.join(project_root, _LOCAL_CONFIG_FILE);
|
|
6698
7450
|
if (pathExists(target) && !force) {
|
|
6699
7451
|
warn(
|
|
6700
7452
|
`${_LOCAL_CONFIG_FILE} already exists; re-run with --force to overwrite. Skipping interactive init.`
|
|
@@ -6721,7 +7473,7 @@ function run_interactive_init(project_root, force) {
|
|
|
6721
7473
|
warn(`Could not write ${target}: ${String(exc)}`);
|
|
6722
7474
|
return 1;
|
|
6723
7475
|
}
|
|
6724
|
-
success(`Wrote ${
|
|
7476
|
+
success(`Wrote ${path20.relative(project_root, target)} (${user_type} / ${stack} / ${verbosity})`);
|
|
6725
7477
|
return 0;
|
|
6726
7478
|
}
|
|
6727
7479
|
var _WIZARD_READY_RE = /^WIZARD_READY (http:\/\/(?:127\.0\.0\.1|localhost):\d+\/\S*)\r?$/;
|
|
@@ -6739,12 +7491,12 @@ function _wizard_should_launch(opts) {
|
|
|
6739
7491
|
return [true, ""];
|
|
6740
7492
|
}
|
|
6741
7493
|
function _wizard_cli_dist(_project_root) {
|
|
6742
|
-
const package_root =
|
|
6743
|
-
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");
|
|
6744
7496
|
return pathExists(cli) ? cli : null;
|
|
6745
7497
|
}
|
|
6746
7498
|
function _server_info_path() {
|
|
6747
|
-
return
|
|
7499
|
+
return path20.join(os6.homedir(), ".event4u", "agent-config", "local-server.json");
|
|
6748
7500
|
}
|
|
6749
7501
|
function _pid_is_agent_config(pid) {
|
|
6750
7502
|
let res;
|
|
@@ -6761,7 +7513,7 @@ function _pid_is_agent_config(pid) {
|
|
|
6761
7513
|
}
|
|
6762
7514
|
function unlinkMissingOk(p) {
|
|
6763
7515
|
try {
|
|
6764
|
-
|
|
7516
|
+
fs20.unlinkSync(p);
|
|
6765
7517
|
} catch {
|
|
6766
7518
|
}
|
|
6767
7519
|
}
|
|
@@ -6839,14 +7591,14 @@ function _wizard_spawn(project_root, pass_project_root = true) {
|
|
|
6839
7591
|
}
|
|
6840
7592
|
function _wizard_run_sync(cmd, env, cli) {
|
|
6841
7593
|
const total = _WIZARD_TIMEOUTS.reduce((a, b) => a + b, 0);
|
|
6842
|
-
const log_path =
|
|
6843
|
-
|
|
7594
|
+
const log_path = path20.join(
|
|
7595
|
+
os6.tmpdir(),
|
|
6844
7596
|
`agent-config-wizard-${process2.pid}-${Date.now()}.log`
|
|
6845
7597
|
);
|
|
6846
7598
|
let child;
|
|
6847
7599
|
let log_fd = null;
|
|
6848
7600
|
try {
|
|
6849
|
-
log_fd =
|
|
7601
|
+
log_fd = fs20.openSync(log_path, "w");
|
|
6850
7602
|
child = spawn(cmd[0], cmd.slice(1), {
|
|
6851
7603
|
env,
|
|
6852
7604
|
detached: true,
|
|
@@ -6864,7 +7616,7 @@ function _wizard_run_sync(cmd, env, cli) {
|
|
|
6864
7616
|
} finally {
|
|
6865
7617
|
if (log_fd !== null) {
|
|
6866
7618
|
try {
|
|
6867
|
-
|
|
7619
|
+
fs20.closeSync(log_fd);
|
|
6868
7620
|
} catch {
|
|
6869
7621
|
}
|
|
6870
7622
|
}
|
|
@@ -7041,7 +7793,7 @@ function main2(argv) {
|
|
|
7041
7793
|
} catch (exc) {
|
|
7042
7794
|
fail(`--apply-payload JSON parse error: ${String(exc)}`);
|
|
7043
7795
|
}
|
|
7044
|
-
if (!
|
|
7796
|
+
if (!isPlainObject(payload)) fail("--apply-payload root must be a JSON object");
|
|
7045
7797
|
const pl = payload;
|
|
7046
7798
|
const schema_version = pl["schema_version"];
|
|
7047
7799
|
if (schema_version !== "wizard-v2" && schema_version !== "installer-v1") {
|
|
@@ -7060,13 +7812,13 @@ function main2(argv) {
|
|
|
7060
7812
|
opts.scope = "global";
|
|
7061
7813
|
}
|
|
7062
7814
|
const settings = pl["settings"];
|
|
7063
|
-
if (
|
|
7815
|
+
if (isPlainObject(settings)) {
|
|
7064
7816
|
const rule_loading_tier = settings["rule_loading_tier"] || settings["cost_profile"];
|
|
7065
7817
|
if (typeof rule_loading_tier === "string" && rule_loading_tier) {
|
|
7066
7818
|
opts.profile = rule_loading_tier;
|
|
7067
7819
|
}
|
|
7068
7820
|
const personal = settings["personal"];
|
|
7069
|
-
if (
|
|
7821
|
+
if (isPlainObject(personal)) {
|
|
7070
7822
|
const user_type = personal["user_type"];
|
|
7071
7823
|
if (typeof user_type === "string" && user_type) {
|
|
7072
7824
|
opts.user_type = user_type;
|
|
@@ -7114,8 +7866,8 @@ function main2(argv) {
|
|
|
7114
7866
|
const target_root = resolvePath(
|
|
7115
7867
|
opts.custom_path || opts.project || process2.env["PROJECT_ROOT"] || process2.cwd()
|
|
7116
7868
|
);
|
|
7117
|
-
const minimal_package_root =
|
|
7118
|
-
|
|
7869
|
+
const minimal_package_root = path20.dirname(
|
|
7870
|
+
path20.dirname(path20.dirname(_minimal_templates_root()))
|
|
7119
7871
|
);
|
|
7120
7872
|
const validated_user_type = _validate_user_type(minimal_package_root, opts.user_type);
|
|
7121
7873
|
return install_minimal(target_root, opts.force, validated_user_type);
|
|
@@ -7151,7 +7903,7 @@ function main2(argv) {
|
|
|
7151
7903
|
return rc2;
|
|
7152
7904
|
}
|
|
7153
7905
|
const project_root = custom_path || resolvePath(opts.project || process2.env["PROJECT_ROOT"] || process2.cwd());
|
|
7154
|
-
const is_first_run = !pathExists(
|
|
7906
|
+
const is_first_run = !pathExists(path20.join(project_root, SETTINGS_FILE));
|
|
7155
7907
|
tracker.begin(project_root);
|
|
7156
7908
|
let rc = _main_project_install(opts, project_root, parsed_tools, is_first_run);
|
|
7157
7909
|
if (rc === 0 && opts.interactive) {
|
|
@@ -7196,8 +7948,8 @@ function _read_consumer_auto_switch(project_root) {
|
|
|
7196
7948
|
} catch {
|
|
7197
7949
|
return "suggest";
|
|
7198
7950
|
}
|
|
7199
|
-
const model =
|
|
7200
|
-
const value =
|
|
7951
|
+
const model = isPlainObject(data) ? data["model"] : null;
|
|
7952
|
+
const value = isPlainObject(model) ? model["auto_switch"] : null;
|
|
7201
7953
|
if (typeof value === "string" && ["auto", "suggest", "off"].includes(value.trim().toLowerCase())) {
|
|
7202
7954
|
return value.trim().toLowerCase();
|
|
7203
7955
|
}
|
|
@@ -7210,23 +7962,23 @@ function _team_setup_hint_line(project_root) {
|
|
|
7210
7962
|
} catch {
|
|
7211
7963
|
data = {};
|
|
7212
7964
|
}
|
|
7213
|
-
const ai_team =
|
|
7214
|
-
const flag =
|
|
7965
|
+
const ai_team = isPlainObject(data) ? data["ai_team"] : null;
|
|
7966
|
+
const flag = isPlainObject(ai_team) ? ai_team["suppress_setup_hint"] : null;
|
|
7215
7967
|
const suppressed = flag === true || typeof flag === "string" && ["true", "yes", "on", "1"].includes(flag.trim().toLowerCase());
|
|
7216
7968
|
if (suppressed) return null;
|
|
7217
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.";
|
|
7218
7970
|
}
|
|
7219
7971
|
function finalize_claude_model_tiers(project_root) {
|
|
7220
|
-
const claude_skills =
|
|
7221
|
-
const augment_skills =
|
|
7972
|
+
const claude_skills = path20.join(project_root, ".claude", "skills");
|
|
7973
|
+
const augment_skills = path20.join(project_root, ".augment", "skills");
|
|
7222
7974
|
if (!isDir(claude_skills) || !isDir(augment_skills)) return 0;
|
|
7223
7975
|
if (_read_consumer_auto_switch(project_root) !== "auto") return 0;
|
|
7224
7976
|
let rendered = 0;
|
|
7225
|
-
const entries =
|
|
7977
|
+
const entries = fs20.readdirSync(claude_skills).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
7226
7978
|
for (const name of entries) {
|
|
7227
|
-
const entry =
|
|
7228
|
-
const src_dir =
|
|
7229
|
-
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");
|
|
7230
7982
|
let tier;
|
|
7231
7983
|
try {
|
|
7232
7984
|
tier = read_model_tier(src_md);
|
|
@@ -7235,22 +7987,22 @@ function finalize_claude_model_tiers(project_root) {
|
|
|
7235
7987
|
}
|
|
7236
7988
|
if (tier === null || !(tier in TIER_TO_CLAUDE_MODEL) || !isDir(src_dir)) continue;
|
|
7237
7989
|
if (isSymlink(entry) || isFile(entry)) {
|
|
7238
|
-
|
|
7990
|
+
fs20.unlinkSync(entry);
|
|
7239
7991
|
} else if (isDir(entry)) {
|
|
7240
|
-
|
|
7992
|
+
fs20.rmSync(entry, { recursive: true, force: true });
|
|
7241
7993
|
}
|
|
7242
7994
|
mkdirp(entry);
|
|
7243
|
-
const srcFiles =
|
|
7995
|
+
const srcFiles = fs20.readdirSync(src_dir).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
7244
7996
|
for (const fname of srcFiles) {
|
|
7245
7997
|
if (fname === "SKILL.md") {
|
|
7246
7998
|
writeText(
|
|
7247
|
-
|
|
7999
|
+
path20.join(entry, "SKILL.md"),
|
|
7248
8000
|
render_native_model_md(readText(src_md), tier)
|
|
7249
8001
|
);
|
|
7250
8002
|
} else {
|
|
7251
|
-
|
|
7252
|
-
|
|
7253
|
-
|
|
8003
|
+
fs20.symlinkSync(
|
|
8004
|
+
path20.join("../../../.augment/skills", name, fname),
|
|
8005
|
+
path20.join(entry, fname)
|
|
7254
8006
|
);
|
|
7255
8007
|
}
|
|
7256
8008
|
}
|
|
@@ -7268,7 +8020,7 @@ function _main_project_install(opts, project_root, parsed_tools, is_first_run) {
|
|
|
7268
8020
|
let package_type;
|
|
7269
8021
|
if (opts.package) {
|
|
7270
8022
|
package_root = resolvePath(opts.package);
|
|
7271
|
-
if (!pathExists(
|
|
8023
|
+
if (!pathExists(path20.join(package_root, "src", "config", "profiles", "minimal.ini"))) {
|
|
7272
8024
|
fail(`Invalid --package path (missing src/config/profiles/minimal.ini): ${package_root}`);
|
|
7273
8025
|
}
|
|
7274
8026
|
package_type = detect_package_type_for_project(project_root, package_root);
|
|
@@ -7406,19 +8158,21 @@ function _main_project_install(opts, project_root, parsed_tools, is_first_run) {
|
|
|
7406
8158
|
if (will_launch) {
|
|
7407
8159
|
return _wizard_spawn(project_root);
|
|
7408
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`);
|
|
7409
8163
|
return 0;
|
|
7410
8164
|
}
|
|
7411
8165
|
function _resolvedArgv1() {
|
|
7412
8166
|
if (process2.argv[1] === void 0) return void 0;
|
|
7413
8167
|
try {
|
|
7414
|
-
return
|
|
8168
|
+
return fs20.realpathSync(path20.resolve(process2.argv[1]));
|
|
7415
8169
|
} catch {
|
|
7416
|
-
return
|
|
8170
|
+
return path20.resolve(process2.argv[1]);
|
|
7417
8171
|
}
|
|
7418
8172
|
}
|
|
7419
8173
|
var _argv1 = _resolvedArgv1();
|
|
7420
8174
|
var _isCliEntry = _argv1 !== void 0 && import.meta.url === pathToFileURL(_argv1).href;
|
|
7421
|
-
if (_isCliEntry || _argv1 ===
|
|
8175
|
+
if (_isCliEntry || _argv1 === _HERE2) {
|
|
7422
8176
|
try {
|
|
7423
8177
|
process2.exitCode = main2(process2.argv.slice(2));
|
|
7424
8178
|
} catch (e) {
|