@aaac/contracts 0.1.15 → 0.1.16
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/dist/cli/index.js +560 -32
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -13,8 +13,11 @@ import {
|
|
|
13
13
|
loadHookBindings,
|
|
14
14
|
loadInitConfig,
|
|
15
15
|
materializeHooks,
|
|
16
|
+
mergeCursorHooks,
|
|
16
17
|
parseComponentFile,
|
|
18
|
+
parseCursorHooksFile,
|
|
17
19
|
readGovernanceLock,
|
|
20
|
+
serializeCursorHooksFile,
|
|
18
21
|
unmaterializeHooks,
|
|
19
22
|
validateComponent,
|
|
20
23
|
writeGeneratedFiles
|
|
@@ -22,7 +25,7 @@ import {
|
|
|
22
25
|
|
|
23
26
|
// src/cli/index.ts
|
|
24
27
|
import { readFileSync } from "fs";
|
|
25
|
-
import { dirname as
|
|
28
|
+
import { dirname as dirname3, resolve as resolve2 } from "path";
|
|
26
29
|
import { fileURLToPath } from "url";
|
|
27
30
|
|
|
28
31
|
// ../../node_modules/commander/lib/error.js
|
|
@@ -3649,6 +3652,72 @@ var commandDefinitions = {
|
|
|
3649
3652
|
}
|
|
3650
3653
|
}
|
|
3651
3654
|
]
|
|
3655
|
+
},
|
|
3656
|
+
"init": {
|
|
3657
|
+
"effects": {},
|
|
3658
|
+
"options": [
|
|
3659
|
+
{
|
|
3660
|
+
"name": "project-yaml",
|
|
3661
|
+
"schema": {
|
|
3662
|
+
"type": "string"
|
|
3663
|
+
}
|
|
3664
|
+
},
|
|
3665
|
+
{
|
|
3666
|
+
"name": "binary-path",
|
|
3667
|
+
"schema": {
|
|
3668
|
+
"type": "string"
|
|
3669
|
+
}
|
|
3670
|
+
}
|
|
3671
|
+
]
|
|
3672
|
+
},
|
|
3673
|
+
"update": {
|
|
3674
|
+
"effects": {},
|
|
3675
|
+
"options": [
|
|
3676
|
+
{
|
|
3677
|
+
"name": "project-yaml",
|
|
3678
|
+
"schema": {
|
|
3679
|
+
"type": "string"
|
|
3680
|
+
}
|
|
3681
|
+
}
|
|
3682
|
+
]
|
|
3683
|
+
},
|
|
3684
|
+
"uninstall": {
|
|
3685
|
+
"effects": {}
|
|
3686
|
+
},
|
|
3687
|
+
"install": {
|
|
3688
|
+
"effects": {},
|
|
3689
|
+
"options": [
|
|
3690
|
+
{
|
|
3691
|
+
"name": "global",
|
|
3692
|
+
"schema": {
|
|
3693
|
+
"type": "boolean"
|
|
3694
|
+
}
|
|
3695
|
+
},
|
|
3696
|
+
{
|
|
3697
|
+
"name": "dry-run",
|
|
3698
|
+
"schema": {
|
|
3699
|
+
"type": "boolean"
|
|
3700
|
+
}
|
|
3701
|
+
},
|
|
3702
|
+
{
|
|
3703
|
+
"name": "skip-cursor",
|
|
3704
|
+
"schema": {
|
|
3705
|
+
"type": "boolean"
|
|
3706
|
+
}
|
|
3707
|
+
},
|
|
3708
|
+
{
|
|
3709
|
+
"name": "skip-claude",
|
|
3710
|
+
"schema": {
|
|
3711
|
+
"type": "boolean"
|
|
3712
|
+
}
|
|
3713
|
+
},
|
|
3714
|
+
{
|
|
3715
|
+
"name": "skip-git",
|
|
3716
|
+
"schema": {
|
|
3717
|
+
"type": "boolean"
|
|
3718
|
+
}
|
|
3719
|
+
}
|
|
3720
|
+
]
|
|
3652
3721
|
}
|
|
3653
3722
|
};
|
|
3654
3723
|
function deriveCommandPolicy(command_id, optionValues) {
|
|
@@ -3675,8 +3744,230 @@ function deriveCommandPolicy(command_id, optionValues) {
|
|
|
3675
3744
|
}
|
|
3676
3745
|
|
|
3677
3746
|
// src/generated/contract.ts
|
|
3678
|
-
var CONTRACT_YAML =
|
|
3679
|
-
|
|
3747
|
+
var CONTRACT_YAML = `# yaml-language-server: $schema=./node_modules/cli-contracts/schemas/cli-contract.schema.json
|
|
3748
|
+
cli_contracts: 0.1.0
|
|
3749
|
+
|
|
3750
|
+
info:
|
|
3751
|
+
title: AaaC CLI
|
|
3752
|
+
version: 0.1.0
|
|
3753
|
+
description: Agent as a Component \u2014 Contract compiler and code generator
|
|
3754
|
+
|
|
3755
|
+
command_sets:
|
|
3756
|
+
aaac:
|
|
3757
|
+
summary: AaaC CLI \u2014 compile Component Contracts and generate adapters
|
|
3758
|
+
executable: aaac
|
|
3759
|
+
global_options:
|
|
3760
|
+
- name: verbose
|
|
3761
|
+
aliases: [v]
|
|
3762
|
+
schema: { type: boolean }
|
|
3763
|
+
description: Enable verbose output
|
|
3764
|
+
- name: quiet
|
|
3765
|
+
aliases: [q]
|
|
3766
|
+
schema: { type: boolean }
|
|
3767
|
+
description: Suppress non-essential output
|
|
3768
|
+
- name: resume
|
|
3769
|
+
schema: { type: string }
|
|
3770
|
+
description: Resume from a previous memory_ref ID
|
|
3771
|
+
commands:
|
|
3772
|
+
compile:
|
|
3773
|
+
summary: Compile a Component Contract YAML to Component IR
|
|
3774
|
+
arguments:
|
|
3775
|
+
- name: file
|
|
3776
|
+
required: true
|
|
3777
|
+
schema: { type: string }
|
|
3778
|
+
description: Path to the Component Contract YAML file
|
|
3779
|
+
options:
|
|
3780
|
+
- name: output
|
|
3781
|
+
aliases: [o]
|
|
3782
|
+
schema: { type: string }
|
|
3783
|
+
description: Output path for the compiled IR (JSON)
|
|
3784
|
+
exits:
|
|
3785
|
+
'0':
|
|
3786
|
+
description: Compilation succeeded
|
|
3787
|
+
stdout:
|
|
3788
|
+
format: json
|
|
3789
|
+
schema:
|
|
3790
|
+
type: object
|
|
3791
|
+
description: Component IR
|
|
3792
|
+
'1':
|
|
3793
|
+
description: Compilation failed (validation errors)
|
|
3794
|
+
stderr:
|
|
3795
|
+
format: text
|
|
3796
|
+
|
|
3797
|
+
generate:
|
|
3798
|
+
summary: Generate adapters from a Component Contract
|
|
3799
|
+
arguments:
|
|
3800
|
+
- name: file
|
|
3801
|
+
required: true
|
|
3802
|
+
schema: { type: string }
|
|
3803
|
+
description: Path to the Component Contract YAML file
|
|
3804
|
+
options:
|
|
3805
|
+
- name: output-dir
|
|
3806
|
+
aliases: [o]
|
|
3807
|
+
schema: { type: string }
|
|
3808
|
+
description: Output directory for generated files
|
|
3809
|
+
- name: targets
|
|
3810
|
+
aliases: [t]
|
|
3811
|
+
schema:
|
|
3812
|
+
type: array
|
|
3813
|
+
items:
|
|
3814
|
+
type: string
|
|
3815
|
+
enum: [library, cli, runtime, claude, openai]
|
|
3816
|
+
description: Generation targets (defaults to projections in contract)
|
|
3817
|
+
- name: dry-run
|
|
3818
|
+
schema: { type: boolean }
|
|
3819
|
+
description: Show what would be generated without writing files
|
|
3820
|
+
effects:
|
|
3821
|
+
filesystem: read_write
|
|
3822
|
+
exits:
|
|
3823
|
+
'0':
|
|
3824
|
+
description: Generation succeeded
|
|
3825
|
+
stdout:
|
|
3826
|
+
format: text
|
|
3827
|
+
'1':
|
|
3828
|
+
description: Generation failed
|
|
3829
|
+
stderr:
|
|
3830
|
+
format: text
|
|
3831
|
+
|
|
3832
|
+
validate:
|
|
3833
|
+
summary: Validate a Component Contract YAML
|
|
3834
|
+
arguments:
|
|
3835
|
+
- name: file
|
|
3836
|
+
required: true
|
|
3837
|
+
schema: { type: string }
|
|
3838
|
+
description: Path to the Component Contract YAML file
|
|
3839
|
+
options:
|
|
3840
|
+
- name: strict
|
|
3841
|
+
schema: { type: boolean }
|
|
3842
|
+
description: Enable strict validation (check implementation refs)
|
|
3843
|
+
exits:
|
|
3844
|
+
'0':
|
|
3845
|
+
description: Validation passed
|
|
3846
|
+
stdout:
|
|
3847
|
+
format: text
|
|
3848
|
+
'1':
|
|
3849
|
+
description: Validation failed
|
|
3850
|
+
stderr:
|
|
3851
|
+
format: text
|
|
3852
|
+
|
|
3853
|
+
introspect:
|
|
3854
|
+
summary: Dump Component IR information
|
|
3855
|
+
arguments:
|
|
3856
|
+
- name: file
|
|
3857
|
+
required: true
|
|
3858
|
+
schema: { type: string }
|
|
3859
|
+
description: Path to the Component Contract YAML file
|
|
3860
|
+
options:
|
|
3861
|
+
- name: format
|
|
3862
|
+
aliases: [f]
|
|
3863
|
+
schema:
|
|
3864
|
+
type: string
|
|
3865
|
+
enum: [json, yaml]
|
|
3866
|
+
description: Output format (default yaml)
|
|
3867
|
+
exits:
|
|
3868
|
+
'0':
|
|
3869
|
+
description: Success
|
|
3870
|
+
stdout:
|
|
3871
|
+
format: json
|
|
3872
|
+
schema:
|
|
3873
|
+
type: object
|
|
3874
|
+
description: Component IR dump
|
|
3875
|
+
|
|
3876
|
+
init:
|
|
3877
|
+
summary: Initialize a project \u2014 copy CLI binary, scaffold project.yaml, materialize git hooks
|
|
3878
|
+
arguments:
|
|
3879
|
+
- name: projectRoot
|
|
3880
|
+
required: false
|
|
3881
|
+
schema: { type: string }
|
|
3882
|
+
description: "Project root directory (default: current directory)"
|
|
3883
|
+
options:
|
|
3884
|
+
- name: project-yaml
|
|
3885
|
+
schema: { type: string }
|
|
3886
|
+
description: Path to project.yaml relative to projectRoot (default project.yaml)
|
|
3887
|
+
- name: binary-path
|
|
3888
|
+
schema: { type: string }
|
|
3889
|
+
description: "Path to the CLI binary to copy (default: process.argv[1]); for programmatic/test use"
|
|
3890
|
+
effects:
|
|
3891
|
+
filesystem: read_write
|
|
3892
|
+
exits:
|
|
3893
|
+
'0':
|
|
3894
|
+
description: Initialization succeeded
|
|
3895
|
+
stdout:
|
|
3896
|
+
format: text
|
|
3897
|
+
'1':
|
|
3898
|
+
description: Initialization failed
|
|
3899
|
+
stderr:
|
|
3900
|
+
format: text
|
|
3901
|
+
|
|
3902
|
+
update:
|
|
3903
|
+
summary: Re-read project.yaml and re-materialize git hooks
|
|
3904
|
+
arguments:
|
|
3905
|
+
- name: projectRoot
|
|
3906
|
+
required: false
|
|
3907
|
+
schema: { type: string }
|
|
3908
|
+
description: "Project root directory (default: current directory)"
|
|
3909
|
+
options:
|
|
3910
|
+
- name: project-yaml
|
|
3911
|
+
schema: { type: string }
|
|
3912
|
+
description: Path to project.yaml relative to projectRoot (default project.yaml)
|
|
3913
|
+
effects:
|
|
3914
|
+
filesystem: read_write
|
|
3915
|
+
exits:
|
|
3916
|
+
'0':
|
|
3917
|
+
description: Update succeeded
|
|
3918
|
+
stdout:
|
|
3919
|
+
format: text
|
|
3920
|
+
'1':
|
|
3921
|
+
description: Update failed
|
|
3922
|
+
stderr:
|
|
3923
|
+
format: text
|
|
3924
|
+
|
|
3925
|
+
uninstall:
|
|
3926
|
+
summary: Remove all managed hook blocks recorded in governance-manifest.lock
|
|
3927
|
+
arguments:
|
|
3928
|
+
- name: projectRoot
|
|
3929
|
+
required: false
|
|
3930
|
+
schema: { type: string }
|
|
3931
|
+
description: "Project root directory (default: current directory)"
|
|
3932
|
+
effects:
|
|
3933
|
+
filesystem: read_write
|
|
3934
|
+
exits:
|
|
3935
|
+
'0':
|
|
3936
|
+
description: Uninstall succeeded
|
|
3937
|
+
stdout:
|
|
3938
|
+
format: text
|
|
3939
|
+
|
|
3940
|
+
install:
|
|
3941
|
+
summary: Install user-global observability hooks (Cursor + Claude + Git) in one command \u2014 idempotent, non-destructive
|
|
3942
|
+
options:
|
|
3943
|
+
- name: global
|
|
3944
|
+
schema: { type: boolean }
|
|
3945
|
+
description: Install at user scope (~/.cursor, ~/.claude, git --global). Currently the only supported scope.
|
|
3946
|
+
- name: dry-run
|
|
3947
|
+
schema: { type: boolean }
|
|
3948
|
+
description: Preview the changes without writing any files or git config
|
|
3949
|
+
- name: skip-cursor
|
|
3950
|
+
schema: { type: boolean }
|
|
3951
|
+
description: Do not configure the Cursor user hooks
|
|
3952
|
+
- name: skip-claude
|
|
3953
|
+
schema: { type: boolean }
|
|
3954
|
+
description: Do not configure the Claude Code user hooks
|
|
3955
|
+
- name: skip-git
|
|
3956
|
+
schema: { type: boolean }
|
|
3957
|
+
description: Do not configure the global git hooks / core.hooksPath
|
|
3958
|
+
effects:
|
|
3959
|
+
filesystem: read_write
|
|
3960
|
+
exits:
|
|
3961
|
+
'0':
|
|
3962
|
+
description: Install succeeded (or previewed with --dry-run)
|
|
3963
|
+
stdout:
|
|
3964
|
+
format: text
|
|
3965
|
+
'1':
|
|
3966
|
+
description: Install failed
|
|
3967
|
+
stderr:
|
|
3968
|
+
format: text
|
|
3969
|
+
`;
|
|
3970
|
+
var CONTRACT_JSON_STR = '{\n "cli_contracts": "0.1.0",\n "info": {\n "title": "AaaC CLI",\n "version": "0.1.0",\n "description": "Agent as a Component \u2014 Contract compiler and code generator"\n },\n "command_sets": {\n "aaac": {\n "summary": "AaaC CLI \u2014 compile Component Contracts and generate adapters",\n "executable": "aaac",\n "global_options": [\n {\n "name": "verbose",\n "aliases": [\n "v"\n ],\n "schema": {\n "type": "boolean"\n },\n "description": "Enable verbose output"\n },\n {\n "name": "quiet",\n "aliases": [\n "q"\n ],\n "schema": {\n "type": "boolean"\n },\n "description": "Suppress non-essential output"\n },\n {\n "name": "resume",\n "schema": {\n "type": "string"\n },\n "description": "Resume from a previous memory_ref ID"\n }\n ],\n "commands": {\n "compile": {\n "summary": "Compile a Component Contract YAML to Component IR",\n "arguments": [\n {\n "name": "file",\n "required": true,\n "schema": {\n "type": "string"\n },\n "description": "Path to the Component Contract YAML file"\n }\n ],\n "options": [\n {\n "name": "output",\n "aliases": [\n "o"\n ],\n "schema": {\n "type": "string"\n },\n "description": "Output path for the compiled IR (JSON)"\n }\n ],\n "exits": {\n "0": {\n "description": "Compilation succeeded",\n "stdout": {\n "format": "json",\n "schema": {\n "type": "object",\n "description": "Component IR"\n }\n }\n },\n "1": {\n "description": "Compilation failed (validation errors)",\n "stderr": {\n "format": "text"\n }\n }\n }\n },\n "generate": {\n "summary": "Generate adapters from a Component Contract",\n "arguments": [\n {\n "name": "file",\n "required": true,\n "schema": {\n "type": "string"\n },\n "description": "Path to the Component Contract YAML file"\n }\n ],\n "options": [\n {\n "name": "output-dir",\n "aliases": [\n "o"\n ],\n "schema": {\n "type": "string"\n },\n "description": "Output directory for generated files"\n },\n {\n "name": "targets",\n "aliases": [\n "t"\n ],\n "schema": {\n "type": "array",\n "items": {\n "type": "string",\n "enum": [\n "library",\n "cli",\n "runtime",\n "claude",\n "openai"\n ]\n }\n },\n "description": "Generation targets (defaults to projections in contract)"\n },\n {\n "name": "dry-run",\n "schema": {\n "type": "boolean"\n },\n "description": "Show what would be generated without writing files"\n }\n ],\n "effects": {\n "filesystem": "read_write"\n },\n "exits": {\n "0": {\n "description": "Generation succeeded",\n "stdout": {\n "format": "text"\n }\n },\n "1": {\n "description": "Generation failed",\n "stderr": {\n "format": "text"\n }\n }\n }\n },\n "validate": {\n "summary": "Validate a Component Contract YAML",\n "arguments": [\n {\n "name": "file",\n "required": true,\n "schema": {\n "type": "string"\n },\n "description": "Path to the Component Contract YAML file"\n }\n ],\n "options": [\n {\n "name": "strict",\n "schema": {\n "type": "boolean"\n },\n "description": "Enable strict validation (check implementation refs)"\n }\n ],\n "exits": {\n "0": {\n "description": "Validation passed",\n "stdout": {\n "format": "text"\n }\n },\n "1": {\n "description": "Validation failed",\n "stderr": {\n "format": "text"\n }\n }\n }\n },\n "introspect": {\n "summary": "Dump Component IR information",\n "arguments": [\n {\n "name": "file",\n "required": true,\n "schema": {\n "type": "string"\n },\n "description": "Path to the Component Contract YAML file"\n }\n ],\n "options": [\n {\n "name": "format",\n "aliases": [\n "f"\n ],\n "schema": {\n "type": "string",\n "enum": [\n "json",\n "yaml"\n ]\n },\n "description": "Output format (default yaml)"\n }\n ],\n "exits": {\n "0": {\n "description": "Success",\n "stdout": {\n "format": "json",\n "schema": {\n "type": "object",\n "description": "Component IR dump"\n }\n }\n }\n }\n },\n "init": {\n "summary": "Initialize a project \u2014 copy CLI binary, scaffold project.yaml, materialize git hooks",\n "arguments": [\n {\n "name": "projectRoot",\n "required": false,\n "schema": {\n "type": "string"\n },\n "description": "Project root directory (default: current directory)"\n }\n ],\n "options": [\n {\n "name": "project-yaml",\n "schema": {\n "type": "string"\n },\n "description": "Path to project.yaml relative to projectRoot (default project.yaml)"\n },\n {\n "name": "binary-path",\n "schema": {\n "type": "string"\n },\n "description": "Path to the CLI binary to copy (default: process.argv[1]); for programmatic/test use"\n }\n ],\n "effects": {\n "filesystem": "read_write"\n },\n "exits": {\n "0": {\n "description": "Initialization succeeded",\n "stdout": {\n "format": "text"\n }\n },\n "1": {\n "description": "Initialization failed",\n "stderr": {\n "format": "text"\n }\n }\n }\n },\n "update": {\n "summary": "Re-read project.yaml and re-materialize git hooks",\n "arguments": [\n {\n "name": "projectRoot",\n "required": false,\n "schema": {\n "type": "string"\n },\n "description": "Project root directory (default: current directory)"\n }\n ],\n "options": [\n {\n "name": "project-yaml",\n "schema": {\n "type": "string"\n },\n "description": "Path to project.yaml relative to projectRoot (default project.yaml)"\n }\n ],\n "effects": {\n "filesystem": "read_write"\n },\n "exits": {\n "0": {\n "description": "Update succeeded",\n "stdout": {\n "format": "text"\n }\n },\n "1": {\n "description": "Update failed",\n "stderr": {\n "format": "text"\n }\n }\n }\n },\n "uninstall": {\n "summary": "Remove all managed hook blocks recorded in governance-manifest.lock",\n "arguments": [\n {\n "name": "projectRoot",\n "required": false,\n "schema": {\n "type": "string"\n },\n "description": "Project root directory (default: current directory)"\n }\n ],\n "effects": {\n "filesystem": "read_write"\n },\n "exits": {\n "0": {\n "description": "Uninstall succeeded",\n "stdout": {\n "format": "text"\n }\n }\n }\n },\n "install": {\n "summary": "Install user-global observability hooks (Cursor + Claude + Git) in one command \u2014 idempotent, non-destructive",\n "options": [\n {\n "name": "global",\n "schema": {\n "type": "boolean"\n },\n "description": "Install at user scope (~/.cursor, ~/.claude, git --global). Currently the only supported scope."\n },\n {\n "name": "dry-run",\n "schema": {\n "type": "boolean"\n },\n "description": "Preview the changes without writing any files or git config"\n },\n {\n "name": "skip-cursor",\n "schema": {\n "type": "boolean"\n },\n "description": "Do not configure the Cursor user hooks"\n },\n {\n "name": "skip-claude",\n "schema": {\n "type": "boolean"\n },\n "description": "Do not configure the Claude Code user hooks"\n },\n {\n "name": "skip-git",\n "schema": {\n "type": "boolean"\n },\n "description": "Do not configure the global git hooks / core.hooksPath"\n }\n ],\n "effects": {\n "filesystem": "read_write"\n },\n "exits": {\n "0": {\n "description": "Install succeeded (or previewed with --dry-run)",\n "stdout": {\n "format": "text"\n }\n },\n "1": {\n "description": "Install failed",\n "stderr": {\n "format": "text"\n }\n }\n }\n }\n }\n }\n }\n}';
|
|
3680
3971
|
|
|
3681
3972
|
// src/generated/program.ts
|
|
3682
3973
|
function createProgram(handlers2, version) {
|
|
@@ -3722,17 +4013,41 @@ function createProgram(handlers2, version) {
|
|
|
3722
4013
|
}
|
|
3723
4014
|
await handlers2.introspect(file, opts, globalOpts);
|
|
3724
4015
|
});
|
|
3725
|
-
program3.command("init").description("Initialize a project
|
|
4016
|
+
program3.command("init").description("Initialize a project \u2014 copy CLI binary, scaffold project.yaml, materialize git hooks").argument("[projectRoot]", "Project root directory (default: current directory)").option("--project-yaml <value>", "Path to project.yaml relative to projectRoot (default project.yaml)").option("--binary-path <value>", "Path to the CLI binary to copy (default: process.argv[1]); for programmatic/test use").action(async (projectRoot, opts, cmd) => {
|
|
3726
4017
|
const globalOpts = cmd.optsWithGlobals();
|
|
4018
|
+
if (globalOpts.introspect) {
|
|
4019
|
+
const policy = deriveCommandPolicy("init", opts);
|
|
4020
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
4021
|
+
return;
|
|
4022
|
+
}
|
|
3727
4023
|
await handlers2.init(projectRoot, opts, globalOpts);
|
|
3728
4024
|
});
|
|
3729
|
-
program3.command("update").description("Re-read project.yaml and re-materialize git hooks").argument("[projectRoot]", "Project root directory (default: current directory)").option("--project-yaml <value>", "Path to project.yaml relative to projectRoot (default
|
|
4025
|
+
program3.command("update").description("Re-read project.yaml and re-materialize git hooks").argument("[projectRoot]", "Project root directory (default: current directory)").option("--project-yaml <value>", "Path to project.yaml relative to projectRoot (default project.yaml)").action(async (projectRoot, opts, cmd) => {
|
|
3730
4026
|
const globalOpts = cmd.optsWithGlobals();
|
|
4027
|
+
if (globalOpts.introspect) {
|
|
4028
|
+
const policy = deriveCommandPolicy("update", opts);
|
|
4029
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
4030
|
+
return;
|
|
4031
|
+
}
|
|
3731
4032
|
await handlers2.update(projectRoot, opts, globalOpts);
|
|
3732
4033
|
});
|
|
3733
4034
|
program3.command("uninstall").description("Remove all managed hook blocks recorded in governance-manifest.lock").argument("[projectRoot]", "Project root directory (default: current directory)").action(async (projectRoot, opts, cmd) => {
|
|
3734
4035
|
const globalOpts = cmd.optsWithGlobals();
|
|
3735
|
-
|
|
4036
|
+
if (globalOpts.introspect) {
|
|
4037
|
+
const policy = deriveCommandPolicy("uninstall", opts);
|
|
4038
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
4039
|
+
return;
|
|
4040
|
+
}
|
|
4041
|
+
await handlers2.uninstall(projectRoot, {}, globalOpts);
|
|
4042
|
+
});
|
|
4043
|
+
program3.command("install").description("Install user-global observability hooks (Cursor + Claude + Git) in one command \u2014 idempotent, non-destructive").option("--global", "Install at user scope (~/.cursor, ~/.claude, git --global). Currently the only supported scope.").option("--dry-run", "Preview the changes without writing any files or git config").option("--skip-cursor", "Do not configure the Cursor user hooks").option("--skip-claude", "Do not configure the Claude Code user hooks").option("--skip-git", "Do not configure the global git hooks / core.hooksPath").action(async (opts, cmd) => {
|
|
4044
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
4045
|
+
if (globalOpts.introspect) {
|
|
4046
|
+
const policy = deriveCommandPolicy("install", opts);
|
|
4047
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
4048
|
+
return;
|
|
4049
|
+
}
|
|
4050
|
+
await handlers2.install(opts, globalOpts);
|
|
3736
4051
|
});
|
|
3737
4052
|
program3.command("extract").description("Extract contract specification for this CLI tool.").argument("[commands...]", "Command IDs to extract. Use dot notation.").option("-a, --all", "Extract all commands.", false).option("--include-meta", "Include extraction metadata.", true).option("-F, --format <format>", "Output format (yaml or json).", "yaml").action(async (commands, opts, cmd) => {
|
|
3738
4053
|
if (commands.length === 0 && !opts.all) {
|
|
@@ -3751,7 +4066,7 @@ function createProgram(handlers2, version) {
|
|
|
3751
4066
|
type: "cli-contracts/extract",
|
|
3752
4067
|
extractedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3753
4068
|
specVersion: doc.cli_contracts ?? "0.1.0",
|
|
3754
|
-
commands: ["aaac.compile", "aaac.generate", "aaac.validate", "aaac.introspect", "aaac.init", "aaac.update", "aaac.uninstall"]
|
|
4069
|
+
commands: ["aaac.compile", "aaac.generate", "aaac.validate", "aaac.introspect", "aaac.init", "aaac.update", "aaac.uninstall", "aaac.install"]
|
|
3755
4070
|
};
|
|
3756
4071
|
}
|
|
3757
4072
|
Object.assign(out, doc);
|
|
@@ -3768,7 +4083,7 @@ function createProgram(handlers2, version) {
|
|
|
3768
4083
|
yamlLines.push("extractedAt: " + (/* @__PURE__ */ new Date()).toISOString());
|
|
3769
4084
|
yamlLines.push("spec_version: " + (doc.cli_contracts ?? "0.1.0"));
|
|
3770
4085
|
yamlLines.push("commands:");
|
|
3771
|
-
for (const id of ["aaac.compile", "aaac.generate", "aaac.validate", "aaac.introspect", "aaac.init", "aaac.update", "aaac.uninstall"]) {
|
|
4086
|
+
for (const id of ["aaac.compile", "aaac.generate", "aaac.validate", "aaac.introspect", "aaac.init", "aaac.update", "aaac.uninstall", "aaac.install"]) {
|
|
3772
4087
|
yamlLines.push(" - " + id);
|
|
3773
4088
|
}
|
|
3774
4089
|
}
|
|
@@ -3808,9 +4123,189 @@ function createProgram(handlers2, version) {
|
|
|
3808
4123
|
}
|
|
3809
4124
|
|
|
3810
4125
|
// src/cli/handlers.ts
|
|
4126
|
+
import { existsSync as existsSync2 } from "fs";
|
|
4127
|
+
import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
|
|
4128
|
+
import { homedir } from "os";
|
|
4129
|
+
import { dirname as dirname2, join as join2, resolve } from "path";
|
|
4130
|
+
|
|
4131
|
+
// src/cli/global-install.ts
|
|
4132
|
+
import { execFileSync } from "child_process";
|
|
3811
4133
|
import { existsSync } from "fs";
|
|
3812
|
-
import { mkdir, writeFile } from "fs/promises";
|
|
3813
|
-
import { dirname, join
|
|
4134
|
+
import { chmod, mkdir, readFile, writeFile } from "fs/promises";
|
|
4135
|
+
import { dirname, join } from "path";
|
|
4136
|
+
var GLOBAL_RECORDER_CMD = "aaac-observ-global-record";
|
|
4137
|
+
var GLOBAL_CURSOR_HOOK_EVENTS = [
|
|
4138
|
+
"sessionStart",
|
|
4139
|
+
"sessionEnd",
|
|
4140
|
+
"subagentStart",
|
|
4141
|
+
"subagentStop",
|
|
4142
|
+
"preToolUse",
|
|
4143
|
+
"postToolUse",
|
|
4144
|
+
"afterFileEdit",
|
|
4145
|
+
"afterShellExecution"
|
|
4146
|
+
];
|
|
4147
|
+
function buildGlobalCursorEntries(recorder = GLOBAL_RECORDER_CMD) {
|
|
4148
|
+
return GLOBAL_CURSOR_HOOK_EVENTS.map((event) => ({
|
|
4149
|
+
event,
|
|
4150
|
+
command: `${recorder} ${event} --source cursor-hook`
|
|
4151
|
+
}));
|
|
4152
|
+
}
|
|
4153
|
+
function cursorHooksPath(home) {
|
|
4154
|
+
return join(home, ".cursor", "hooks.json");
|
|
4155
|
+
}
|
|
4156
|
+
var GLOBAL_CLAUDE_HOOK_EVENTS = [
|
|
4157
|
+
"SessionStart",
|
|
4158
|
+
"PreToolUse",
|
|
4159
|
+
"PostToolUse",
|
|
4160
|
+
"Stop",
|
|
4161
|
+
"SubagentStop"
|
|
4162
|
+
];
|
|
4163
|
+
function buildClaudeHookCommand(event, recorder = GLOBAL_RECORDER_CMD) {
|
|
4164
|
+
return `${recorder} ${event} --source claude-hook`;
|
|
4165
|
+
}
|
|
4166
|
+
function claudeSettingsPath(home) {
|
|
4167
|
+
return join(home, ".claude", "settings.json");
|
|
4168
|
+
}
|
|
4169
|
+
function parseClaudeSettings(raw) {
|
|
4170
|
+
if (!raw || !raw.trim()) return {};
|
|
4171
|
+
try {
|
|
4172
|
+
const parsed = JSON.parse(raw);
|
|
4173
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
4174
|
+
} catch {
|
|
4175
|
+
return {};
|
|
4176
|
+
}
|
|
4177
|
+
}
|
|
4178
|
+
function serializeClaudeSettings(settings) {
|
|
4179
|
+
return JSON.stringify(settings, null, 2) + "\n";
|
|
4180
|
+
}
|
|
4181
|
+
function mergeClaudeSettings(existing, recorder = GLOBAL_RECORDER_CMD) {
|
|
4182
|
+
const settings = { ...existing };
|
|
4183
|
+
const hooks = {};
|
|
4184
|
+
for (const [event, groups] of Object.entries(existing.hooks ?? {})) {
|
|
4185
|
+
hooks[event] = groups.map((g) => ({ ...g, hooks: g.hooks.map((h) => ({ ...h })) }));
|
|
4186
|
+
}
|
|
4187
|
+
for (const event of GLOBAL_CLAUDE_HOOK_EVENTS) {
|
|
4188
|
+
const command = buildClaudeHookCommand(event, recorder);
|
|
4189
|
+
const groups = hooks[event] ?? [];
|
|
4190
|
+
const already = groups.some((g) => g.hooks.some((h) => h.command === command));
|
|
4191
|
+
if (!already) {
|
|
4192
|
+
groups.push({ hooks: [{ type: "command", command }] });
|
|
4193
|
+
}
|
|
4194
|
+
hooks[event] = groups;
|
|
4195
|
+
}
|
|
4196
|
+
settings.hooks = hooks;
|
|
4197
|
+
return settings;
|
|
4198
|
+
}
|
|
4199
|
+
var GLOBAL_GIT_HOOK_NAMES = [
|
|
4200
|
+
"pre-commit",
|
|
4201
|
+
"commit-msg",
|
|
4202
|
+
"post-commit",
|
|
4203
|
+
"pre-push"
|
|
4204
|
+
];
|
|
4205
|
+
function globalGitHooksDir(home) {
|
|
4206
|
+
return join(home, ".aaac", "git-hooks");
|
|
4207
|
+
}
|
|
4208
|
+
function buildGlobalGitHookScript(recorder = GLOBAL_RECORDER_CMD) {
|
|
4209
|
+
return [
|
|
4210
|
+
"#!/bin/sh",
|
|
4211
|
+
"# >>> aaac-observ:global-git-hook (do not edit) >>>",
|
|
4212
|
+
"# Records promotion events from ANY repo, then chains to the repo-local hook.",
|
|
4213
|
+
'hook_name="$(basename "$0")"',
|
|
4214
|
+
`${recorder} "$hook_name" --source git-hook >/dev/null 2>&1 || true`,
|
|
4215
|
+
'repo_root="$(git rev-parse --show-toplevel 2>/dev/null)"',
|
|
4216
|
+
'if [ -n "$repo_root" ] && [ -x "$repo_root/.git/hooks/$hook_name" ]; then',
|
|
4217
|
+
' exec "$repo_root/.git/hooks/$hook_name" "$@"',
|
|
4218
|
+
"fi",
|
|
4219
|
+
"exit 0",
|
|
4220
|
+
"# <<< aaac-observ:global-git-hook <<<",
|
|
4221
|
+
""
|
|
4222
|
+
].join("\n");
|
|
4223
|
+
}
|
|
4224
|
+
var defaultGitConfigIO = {
|
|
4225
|
+
get(key) {
|
|
4226
|
+
try {
|
|
4227
|
+
const out = execFileSync("git", ["config", "--global", "--get", key], {
|
|
4228
|
+
encoding: "utf8",
|
|
4229
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
4230
|
+
});
|
|
4231
|
+
const trimmed = out.trim();
|
|
4232
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
4233
|
+
} catch {
|
|
4234
|
+
return void 0;
|
|
4235
|
+
}
|
|
4236
|
+
},
|
|
4237
|
+
set(key, value) {
|
|
4238
|
+
execFileSync("git", ["config", "--global", key, value], { stdio: "ignore" });
|
|
4239
|
+
}
|
|
4240
|
+
};
|
|
4241
|
+
async function readIfExists(path2) {
|
|
4242
|
+
if (!existsSync(path2)) return void 0;
|
|
4243
|
+
return readFile(path2, "utf8");
|
|
4244
|
+
}
|
|
4245
|
+
async function materializeFile(target, path2, existing, next, dryRun, mode) {
|
|
4246
|
+
let action;
|
|
4247
|
+
if (existing === void 0) action = "create";
|
|
4248
|
+
else if (existing === next) action = "unchanged";
|
|
4249
|
+
else action = "update";
|
|
4250
|
+
if (!dryRun && action !== "unchanged") {
|
|
4251
|
+
await mkdir(dirname(path2), { recursive: true });
|
|
4252
|
+
await writeFile(path2, next, "utf8");
|
|
4253
|
+
if (mode !== void 0) await chmod(path2, mode);
|
|
4254
|
+
}
|
|
4255
|
+
return { target, path: path2, action };
|
|
4256
|
+
}
|
|
4257
|
+
async function installGlobalHooks(opts) {
|
|
4258
|
+
const {
|
|
4259
|
+
home,
|
|
4260
|
+
recorder = GLOBAL_RECORDER_CMD,
|
|
4261
|
+
dryRun = false,
|
|
4262
|
+
cursor = true,
|
|
4263
|
+
claude = true,
|
|
4264
|
+
git = true,
|
|
4265
|
+
gitConfig = defaultGitConfigIO
|
|
4266
|
+
} = opts;
|
|
4267
|
+
const actions = [];
|
|
4268
|
+
if (cursor) {
|
|
4269
|
+
const path2 = cursorHooksPath(home);
|
|
4270
|
+
const existingRaw = await readIfExists(path2);
|
|
4271
|
+
const merged = mergeCursorHooks(parseCursorHooksFile(existingRaw), buildGlobalCursorEntries(recorder));
|
|
4272
|
+
const next = serializeCursorHooksFile(merged);
|
|
4273
|
+
actions.push(await materializeFile("cursor", path2, existingRaw, next, dryRun));
|
|
4274
|
+
}
|
|
4275
|
+
if (claude) {
|
|
4276
|
+
const path2 = claudeSettingsPath(home);
|
|
4277
|
+
const existingRaw = await readIfExists(path2);
|
|
4278
|
+
const merged = mergeClaudeSettings(parseClaudeSettings(existingRaw), recorder);
|
|
4279
|
+
const next = serializeClaudeSettings(merged);
|
|
4280
|
+
actions.push(await materializeFile("claude", path2, existingRaw, next, dryRun));
|
|
4281
|
+
}
|
|
4282
|
+
if (git) {
|
|
4283
|
+
const hooksDir = globalGitHooksDir(home);
|
|
4284
|
+
const script = buildGlobalGitHookScript(recorder);
|
|
4285
|
+
for (const name of GLOBAL_GIT_HOOK_NAMES) {
|
|
4286
|
+
const path2 = join(hooksDir, name);
|
|
4287
|
+
const existingRaw = await readIfExists(path2);
|
|
4288
|
+
actions.push(await materializeFile("git", path2, existingRaw, script, dryRun, 493));
|
|
4289
|
+
}
|
|
4290
|
+
const current = gitConfig.get("core.hooksPath");
|
|
4291
|
+
if (current === hooksDir) {
|
|
4292
|
+
actions.push({ target: "git", path: "core.hooksPath", action: "unchanged" });
|
|
4293
|
+
} else if (current && current.length > 0) {
|
|
4294
|
+
actions.push({
|
|
4295
|
+
target: "git",
|
|
4296
|
+
path: "core.hooksPath",
|
|
4297
|
+
action: "skip",
|
|
4298
|
+
note: `core.hooksPath already set to ${current}; leave it and source ${hooksDir} from your hooks, or unset to let aaac manage it`
|
|
4299
|
+
});
|
|
4300
|
+
} else {
|
|
4301
|
+
if (!dryRun) gitConfig.set("core.hooksPath", hooksDir);
|
|
4302
|
+
actions.push({ target: "git", path: "core.hooksPath", action: "create" });
|
|
4303
|
+
}
|
|
4304
|
+
}
|
|
4305
|
+
return actions;
|
|
4306
|
+
}
|
|
4307
|
+
|
|
4308
|
+
// src/cli/handlers.ts
|
|
3814
4309
|
import { stringify as stringifyYaml } from "yaml";
|
|
3815
4310
|
function formatError(err, file) {
|
|
3816
4311
|
if (err instanceof ComponentParseError) {
|
|
@@ -3842,7 +4337,7 @@ function resolveComponentPath(file) {
|
|
|
3842
4337
|
return resolve(file);
|
|
3843
4338
|
}
|
|
3844
4339
|
function defaultOutputDir(componentPath) {
|
|
3845
|
-
return
|
|
4340
|
+
return join2(dirname2(componentPath), "generated");
|
|
3846
4341
|
}
|
|
3847
4342
|
function buildIntrospectionDump(ir) {
|
|
3848
4343
|
const operations = {};
|
|
@@ -3877,7 +4372,7 @@ var handleCompile = async (file, options, parentOpts) => {
|
|
|
3877
4372
|
const ir = await compileComponentFile(componentPath);
|
|
3878
4373
|
const json = JSON.stringify(ir, null, 2);
|
|
3879
4374
|
if (options.output) {
|
|
3880
|
-
await
|
|
4375
|
+
await writeFile2(resolve(options.output), `${json}
|
|
3881
4376
|
`, "utf-8");
|
|
3882
4377
|
if (!parentOpts.quiet) {
|
|
3883
4378
|
process.stdout.write(`Wrote IR to ${resolve(options.output)}
|
|
@@ -3895,7 +4390,7 @@ async function resolveEmbeddedDslData(ir, componentPath) {
|
|
|
3895
4390
|
if (!ir.embeddedDslDir || !ir.implementation) {
|
|
3896
4391
|
return void 0;
|
|
3897
4392
|
}
|
|
3898
|
-
const implPath = resolve(
|
|
4393
|
+
const implPath = resolve(dirname2(componentPath), ir.implementation);
|
|
3899
4394
|
const { resolve: resolveDsl } = await import("agent-contracts");
|
|
3900
4395
|
const dslResult = await resolveDsl(implPath);
|
|
3901
4396
|
return dslResult.data;
|
|
@@ -3939,10 +4434,10 @@ var handleGenerate = async (file, options, parentOpts) => {
|
|
|
3939
4434
|
}
|
|
3940
4435
|
}
|
|
3941
4436
|
for (const generated of embedded) {
|
|
3942
|
-
const embeddedDir = resolve(
|
|
4437
|
+
const embeddedDir = resolve(dirname2(componentPath), generated.targetDir);
|
|
3943
4438
|
const action = generated.overwrite ? "write" : "create";
|
|
3944
4439
|
process.stdout.write(
|
|
3945
|
-
` ${action}: ${
|
|
4440
|
+
` ${action}: ${join2(embeddedDir, generated.path)} (embedded DSL)
|
|
3946
4441
|
`
|
|
3947
4442
|
);
|
|
3948
4443
|
}
|
|
@@ -3951,10 +4446,10 @@ var handleGenerate = async (file, options, parentOpts) => {
|
|
|
3951
4446
|
}
|
|
3952
4447
|
const result = await writeGeneratedFiles(main, outputDir);
|
|
3953
4448
|
for (const generated of embedded) {
|
|
3954
|
-
const embeddedDir = resolve(
|
|
3955
|
-
await
|
|
3956
|
-
await
|
|
3957
|
-
result.written.push(
|
|
4449
|
+
const embeddedDir = resolve(dirname2(componentPath), generated.targetDir);
|
|
4450
|
+
await mkdir2(embeddedDir, { recursive: true });
|
|
4451
|
+
await writeFile2(join2(embeddedDir, generated.path), generated.content, "utf-8");
|
|
4452
|
+
result.written.push(join2(generated.targetDir, generated.path));
|
|
3958
4453
|
}
|
|
3959
4454
|
if (!parentOpts.quiet) {
|
|
3960
4455
|
if (result.written.length > 0) {
|
|
@@ -3984,7 +4479,7 @@ var handleGenerate = async (file, options, parentOpts) => {
|
|
|
3984
4479
|
};
|
|
3985
4480
|
var handleValidate = async (file, options, parentOpts) => {
|
|
3986
4481
|
const componentPath = resolveComponentPath(file);
|
|
3987
|
-
const basePath =
|
|
4482
|
+
const basePath = dirname2(componentPath);
|
|
3988
4483
|
try {
|
|
3989
4484
|
const dsl = await parseComponentFile(componentPath);
|
|
3990
4485
|
const ir = compileComponent(dsl, { basePath });
|
|
@@ -4020,22 +4515,22 @@ var DEFAULT_PROJECT_YAML = "project.yaml";
|
|
|
4020
4515
|
var handleInit = async (projectRoot, options, parentOpts) => {
|
|
4021
4516
|
const root = resolve(projectRoot ?? ".");
|
|
4022
4517
|
const quiet = Boolean(parentOpts.quiet);
|
|
4023
|
-
const projectYamlPath =
|
|
4518
|
+
const projectYamlPath = join2(root, options.projectYaml ?? DEFAULT_PROJECT_YAML);
|
|
4024
4519
|
const srcBinary = resolve(options.binaryPath ?? process.argv[1]);
|
|
4025
4520
|
const binaryResult = await copyCLIBinary(srcBinary, root);
|
|
4026
4521
|
if (!quiet && binaryResult.action !== "unchanged") {
|
|
4027
4522
|
process.stdout.write(` ${binaryResult.action}: ${binaryResult.path}
|
|
4028
4523
|
`);
|
|
4029
4524
|
}
|
|
4030
|
-
if (!
|
|
4031
|
-
await
|
|
4525
|
+
if (!existsSync2(projectYamlPath)) {
|
|
4526
|
+
await writeFile2(projectYamlPath, SCAFFOLD_PROJECT_YAML, "utf8");
|
|
4032
4527
|
if (!quiet) {
|
|
4033
4528
|
process.stdout.write(` created: ${DEFAULT_PROJECT_YAML}
|
|
4034
4529
|
`);
|
|
4035
4530
|
}
|
|
4036
4531
|
}
|
|
4037
|
-
const gitDir =
|
|
4038
|
-
if (!
|
|
4532
|
+
const gitDir = join2(root, ".git");
|
|
4533
|
+
if (!existsSync2(gitDir)) {
|
|
4039
4534
|
process.stderr.write(
|
|
4040
4535
|
`Warning: .git/ not found in ${root}; skipping hook materialization
|
|
4041
4536
|
`
|
|
@@ -4093,14 +4588,14 @@ var handleInit = async (projectRoot, options, parentOpts) => {
|
|
|
4093
4588
|
var handleUpdate = async (projectRoot, options, parentOpts) => {
|
|
4094
4589
|
const root = resolve(projectRoot ?? ".");
|
|
4095
4590
|
const quiet = Boolean(parentOpts.quiet);
|
|
4096
|
-
const projectYamlPath =
|
|
4097
|
-
if (!
|
|
4591
|
+
const projectYamlPath = join2(root, options.projectYaml ?? DEFAULT_PROJECT_YAML);
|
|
4592
|
+
if (!existsSync2(projectYamlPath)) {
|
|
4098
4593
|
fail(
|
|
4099
4594
|
`Error: ${DEFAULT_PROJECT_YAML} not found at ${root}. Run 'aaac init' first.`
|
|
4100
4595
|
);
|
|
4101
4596
|
}
|
|
4102
|
-
const gitDir =
|
|
4103
|
-
if (!
|
|
4597
|
+
const gitDir = join2(root, ".git");
|
|
4598
|
+
if (!existsSync2(gitDir)) {
|
|
4104
4599
|
process.stderr.write(
|
|
4105
4600
|
`Warning: .git/ not found in ${root}; skipping hook materialization
|
|
4106
4601
|
`
|
|
@@ -4146,7 +4641,7 @@ var handleUninstall = async (projectRoot, _options, parentOpts) => {
|
|
|
4146
4641
|
if (!lock || lock.entries.length === 0) {
|
|
4147
4642
|
if (!quiet) {
|
|
4148
4643
|
process.stdout.write(
|
|
4149
|
-
`Nothing to uninstall (no governance lock found at ${
|
|
4644
|
+
`Nothing to uninstall (no governance lock found at ${join2(root, GOVERNANCE_LOCK_PATH)})
|
|
4150
4645
|
`
|
|
4151
4646
|
);
|
|
4152
4647
|
}
|
|
@@ -4158,6 +4653,38 @@ var handleUninstall = async (projectRoot, _options, parentOpts) => {
|
|
|
4158
4653
|
`);
|
|
4159
4654
|
}
|
|
4160
4655
|
};
|
|
4656
|
+
var handleInstall = async (options, parentOpts) => {
|
|
4657
|
+
const quiet = Boolean(parentOpts.quiet);
|
|
4658
|
+
const dryRun = Boolean(options.dryRun);
|
|
4659
|
+
const home = homedir();
|
|
4660
|
+
if (!home) {
|
|
4661
|
+
fail("Error: could not resolve home directory ($HOME)");
|
|
4662
|
+
}
|
|
4663
|
+
let actions;
|
|
4664
|
+
try {
|
|
4665
|
+
actions = await installGlobalHooks({
|
|
4666
|
+
home,
|
|
4667
|
+
dryRun,
|
|
4668
|
+
cursor: !options.skipCursor,
|
|
4669
|
+
claude: !options.skipClaude,
|
|
4670
|
+
git: !options.skipGit
|
|
4671
|
+
});
|
|
4672
|
+
} catch (err) {
|
|
4673
|
+
fail(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
4674
|
+
}
|
|
4675
|
+
if (!quiet) {
|
|
4676
|
+
const prefix = dryRun ? "[dry-run] " : "";
|
|
4677
|
+
for (const a of actions) {
|
|
4678
|
+
const note = a.note ? ` \u2014 ${a.note}` : "";
|
|
4679
|
+
process.stdout.write(` ${prefix}${a.action}: [${a.target}] ${a.path}${note}
|
|
4680
|
+
`);
|
|
4681
|
+
}
|
|
4682
|
+
process.stdout.write(
|
|
4683
|
+
`${dryRun ? "Previewed" : "Installed"} user-global observability hooks (Cursor + Claude + Git)
|
|
4684
|
+
`
|
|
4685
|
+
);
|
|
4686
|
+
}
|
|
4687
|
+
};
|
|
4161
4688
|
var handlers = {
|
|
4162
4689
|
compile: handleCompile,
|
|
4163
4690
|
generate: handleGenerate,
|
|
@@ -4165,11 +4692,12 @@ var handlers = {
|
|
|
4165
4692
|
introspect: handleIntrospect,
|
|
4166
4693
|
init: handleInit,
|
|
4167
4694
|
update: handleUpdate,
|
|
4168
|
-
uninstall: handleUninstall
|
|
4695
|
+
uninstall: handleUninstall,
|
|
4696
|
+
install: handleInstall
|
|
4169
4697
|
};
|
|
4170
4698
|
|
|
4171
4699
|
// src/cli/index.ts
|
|
4172
|
-
var __dirname =
|
|
4700
|
+
var __dirname = dirname3(fileURLToPath(import.meta.url));
|
|
4173
4701
|
var pkg = JSON.parse(
|
|
4174
4702
|
readFileSync(resolve2(__dirname, "../../package.json"), "utf8")
|
|
4175
4703
|
);
|