mova-claude-import 0.1.1 → 0.1.2

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.
Files changed (188) hide show
  1. package/README.md +68 -4
  2. package/control_surface_exclusions_v0.json +8 -0
  3. package/dist/anthropic_profile_v0.d.ts +1 -1
  4. package/dist/anthropic_profile_v0.js +1 -0
  5. package/dist/cli.js +206 -23
  6. package/dist/control_apply_v0.d.ts +5 -1
  7. package/dist/control_apply_v0.js +125 -8
  8. package/dist/control_check_v0.d.ts +1 -0
  9. package/dist/control_check_v0.js +194 -23
  10. package/dist/control_prefill_v0.js +128 -9
  11. package/dist/control_surface_coverage_v0.d.ts +22 -0
  12. package/dist/control_surface_coverage_v0.js +128 -0
  13. package/dist/control_v0.d.ts +149 -0
  14. package/dist/control_v0.js +360 -0
  15. package/dist/control_v0_schema.d.ts +6 -0
  16. package/dist/control_v0_schema.js +19 -0
  17. package/dist/init_v0.d.ts +6 -1
  18. package/dist/init_v0.js +41 -1
  19. package/dist/observability_writer_v0.d.ts +1 -0
  20. package/dist/observability_writer_v0.js +157 -0
  21. package/dist/observe_v0.d.ts +8 -0
  22. package/dist/observe_v0.js +57 -0
  23. package/dist/presets_v0.d.ts +11 -0
  24. package/dist/presets_v0.js +49 -0
  25. package/dist/redaction.js +5 -1
  26. package/dist/run_import.js +111 -26
  27. package/docs/CLAUDE_CONTROL_SURFACE_MAP_v0.md +78 -0
  28. package/docs/OPERATOR_GUIDE_v0.md +11 -0
  29. package/fixtures/pos/basic/mova/control_v0.json +93 -0
  30. package/fixtures/pos/claude_code_demo_full/.claude/agents/code-reviewer.md +13 -0
  31. package/fixtures/pos/claude_code_demo_full/.claude/agents/github-workflow.md +10 -0
  32. package/fixtures/pos/claude_code_demo_full/.claude/commands/code-quality.md +8 -0
  33. package/fixtures/pos/claude_code_demo_full/.claude/commands/docs-sync.md +8 -0
  34. package/fixtures/pos/claude_code_demo_full/.claude/commands/onboard.md +8 -0
  35. package/fixtures/pos/claude_code_demo_full/.claude/commands/pr-review.md +10 -0
  36. package/fixtures/pos/claude_code_demo_full/.claude/commands/pr-summary.md +8 -0
  37. package/fixtures/pos/claude_code_demo_full/.claude/commands/ticket.md +10 -0
  38. package/fixtures/pos/claude_code_demo_full/.claude/hooks/skill-eval.js +13 -0
  39. package/fixtures/pos/claude_code_demo_full/.claude/hooks/skill-eval.sh +15 -0
  40. package/fixtures/pos/claude_code_demo_full/.claude/hooks/skill-rules.json +21 -0
  41. package/fixtures/pos/claude_code_demo_full/.claude/hooks/skill-rules.schema.json +24 -0
  42. package/fixtures/pos/claude_code_demo_full/.claude/rules/code-style.md +5 -0
  43. package/fixtures/pos/claude_code_demo_full/.claude/rules/security.md +5 -0
  44. package/fixtures/pos/claude_code_demo_full/.claude/settings.json +102 -0
  45. package/fixtures/pos/claude_code_demo_full/.claude/settings.md +6 -0
  46. package/fixtures/pos/claude_code_demo_full/.claude/skills/core-components/SKILL.md +9 -0
  47. package/fixtures/pos/claude_code_demo_full/.claude/skills/formik-patterns/SKILL.md +9 -0
  48. package/fixtures/pos/claude_code_demo_full/.claude/skills/graphql-schema/SKILL.md +10 -0
  49. package/fixtures/pos/claude_code_demo_full/.claude/skills/react-ui-patterns/SKILL.md +10 -0
  50. package/fixtures/pos/claude_code_demo_full/.claude/skills/systematic-debugging/SKILL.md +9 -0
  51. package/fixtures/pos/claude_code_demo_full/.claude/skills/testing-patterns/SKILL.md +10 -0
  52. package/fixtures/pos/claude_code_demo_full/.github/workflows/pr-claude-code-review.yml +14 -0
  53. package/fixtures/pos/claude_code_demo_full/.github/workflows/scheduled-claude-code-dependency-audit.yml +14 -0
  54. package/fixtures/pos/claude_code_demo_full/.github/workflows/scheduled-claude-code-docs-sync.yml +14 -0
  55. package/fixtures/pos/claude_code_demo_full/.github/workflows/scheduled-claude-code-quality.yml +14 -0
  56. package/fixtures/pos/claude_code_demo_full/.mcp.json +44 -0
  57. package/fixtures/pos/claude_code_demo_full/CLAUDE.md +28 -0
  58. package/fixtures/pos/control_basic_project/mova/control_v0.json +93 -0
  59. package/fixtures/pos/observability_basic/CLAUDE.md +3 -0
  60. package/{.tmp_test_zip/out1 → fixtures/pos/preset_safe_observable_v0}/.mcp.json +3 -3
  61. package/fixtures/pos/preset_safe_observable_v0/CLAUDE.md +3 -0
  62. package/package.json +2 -1
  63. package/presets/safe_observable_v0/assets/.claude/agents/code-reviewer.md +9 -0
  64. package/presets/safe_observable_v0/assets/.claude/commands/finish.md +9 -0
  65. package/presets/safe_observable_v0/assets/.claude/commands/start.md +9 -0
  66. package/presets/safe_observable_v0/assets/.claude/hooks/skill-eval.js +15 -0
  67. package/presets/safe_observable_v0/assets/.claude/hooks/skill-eval.sh +17 -0
  68. package/presets/safe_observable_v0/assets/.claude/hooks/skill-rules.json +26 -0
  69. package/presets/safe_observable_v0/assets/.claude/rules/code-style.md +6 -0
  70. package/presets/safe_observable_v0/assets/.claude/rules/security.md +6 -0
  71. package/presets/safe_observable_v0/assets/.claude/skills/git-workflow/SKILL.md +9 -0
  72. package/presets/safe_observable_v0/assets/.claude/skills/security-basics/SKILL.md +9 -0
  73. package/presets/safe_observable_v0/assets/.claude/skills/systematic-debugging/SKILL.md +9 -0
  74. package/presets/safe_observable_v0/assets/.claude/skills/testing-patterns/SKILL.md +9 -0
  75. package/presets/safe_observable_v0/control_v0.json +214 -0
  76. package/schemas/mova.control_v0.schema.json +252 -0
  77. package/src/anthropic_profile_v0.ts +1 -0
  78. package/src/cli.ts +194 -23
  79. package/src/control_apply_v0.ts +131 -8
  80. package/src/control_check_v0.ts +203 -23
  81. package/src/control_prefill_v0.ts +136 -8
  82. package/src/control_surface_coverage_v0.ts +164 -0
  83. package/src/control_v0.ts +808 -0
  84. package/src/control_v0_schema.ts +26 -0
  85. package/src/init_v0.ts +48 -1
  86. package/src/observability_writer_v0.ts +157 -0
  87. package/src/observe_v0.ts +64 -0
  88. package/src/presets_v0.ts +55 -0
  89. package/src/redaction.ts +6 -1
  90. package/src/run_import.ts +132 -26
  91. package/test/control_demo_full_roundtrip.test.js +92 -0
  92. package/test/control_surface_coverage_v0.test.js +36 -0
  93. package/test/control_v0_schema_validation.test.js +69 -0
  94. package/test/init_v0.test.js +9 -0
  95. package/test/observability_writer_v0.test.js +59 -0
  96. package/test/preset_safe_observable_v0.test.js +55 -0
  97. package/test/profile_v0_output.test.js +1 -0
  98. package/test/scaffold_v0_output.test.js +1 -0
  99. package/tools/control_surface_coverage_v0.mjs +27 -0
  100. package/tools/smoke_v0.mjs +33 -0
  101. package/.tmp_test_control_apply/proj/.claude/agents/example_agent.md +0 -3
  102. package/.tmp_test_control_apply/proj/.claude/commands/example_command.md +0 -3
  103. package/.tmp_test_control_apply/proj/.claude/hooks/example_hook.sh +0 -2
  104. package/.tmp_test_control_apply/proj/.claude/output-styles/example_style.md +0 -3
  105. package/.tmp_test_control_apply/proj/.claude/settings.json +0 -30
  106. package/.tmp_test_control_apply/proj/.claude/settings.local.example.json +0 -3
  107. package/.tmp_test_control_apply/proj/.mcp.json +0 -3
  108. package/.tmp_test_control_apply/proj/CLAUDE.md +0 -13
  109. package/.tmp_test_control_apply/proj/MOVA.md +0 -3
  110. package/.tmp_test_control_check/proj/.mcp.json +0 -1
  111. package/.tmp_test_control_check/proj/CLAUDE.md +0 -1
  112. package/.tmp_test_control_prefill/out1/claude_control_profile_v0.json +0 -114
  113. package/.tmp_test_control_prefill/out1/prefill_report_v0.json +0 -13
  114. package/.tmp_test_control_prefill/out2/claude_control_profile_v0.json +0 -114
  115. package/.tmp_test_control_prefill/out2/prefill_report_v0.json +0 -13
  116. package/.tmp_test_overlay/proj/.claude/skills/a.md +0 -1
  117. package/.tmp_test_overlay/proj/.mcp.json +0 -1
  118. package/.tmp_test_overlay/proj/CLAUDE.md +0 -1
  119. package/.tmp_test_profile/proj/.claude/skills/a.md +0 -1
  120. package/.tmp_test_profile/proj/.mcp.json +0 -1
  121. package/.tmp_test_profile/proj/CLAUDE.md +0 -1
  122. package/.tmp_test_scaffold_apply/proj/.claude/agents/example_agent.md +0 -3
  123. package/.tmp_test_scaffold_apply/proj/.claude/commands/example_command.md +0 -3
  124. package/.tmp_test_scaffold_apply/proj/.claude/hooks/example_hook.sh +0 -2
  125. package/.tmp_test_scaffold_apply/proj/.claude/output-styles/example_style.md +0 -3
  126. package/.tmp_test_scaffold_apply/proj/.claude/settings.json +0 -30
  127. package/.tmp_test_scaffold_apply/proj/.claude/settings.local.example.json +0 -3
  128. package/.tmp_test_scaffold_apply/proj/.mcp.json +0 -3
  129. package/.tmp_test_scaffold_apply/proj/CLAUDE.md +0 -13
  130. package/.tmp_test_scaffold_apply/proj/MOVA.md +0 -3
  131. package/.tmp_test_strict/mova/claude_import/v0/VERSION.json +0 -10
  132. package/.tmp_test_strict/mova/claude_import/v0/episode_import_run.json +0 -20
  133. package/.tmp_test_strict/mova/claude_import/v0/import_manifest.json +0 -20
  134. package/.tmp_test_strict/mova/claude_import/v0/input_policy_report_v0.json +0 -32
  135. package/.tmp_test_zip/out1/.claude/agents/example_agent.md +0 -3
  136. package/.tmp_test_zip/out1/.claude/commands/example_command.md +0 -3
  137. package/.tmp_test_zip/out1/.claude/commands/mova_context.md +0 -4
  138. package/.tmp_test_zip/out1/.claude/commands/mova_lint.md +0 -4
  139. package/.tmp_test_zip/out1/.claude/commands/mova_proof.md +0 -6
  140. package/.tmp_test_zip/out1/.claude/hooks/example_hook.sh +0 -2
  141. package/.tmp_test_zip/out1/.claude/output-styles/example_style.md +0 -3
  142. package/.tmp_test_zip/out1/.claude/settings.json +0 -30
  143. package/.tmp_test_zip/out1/.claude/settings.local.example.json +0 -3
  144. package/.tmp_test_zip/out1/.claude/skills/a/SKILL.md +0 -1
  145. package/.tmp_test_zip/out1/.claude/skills/mova-control-v0/SKILL.md +0 -11
  146. package/.tmp_test_zip/out1/.claude/skills/mova-layer-v0/SKILL.md +0 -8
  147. package/.tmp_test_zip/out1/CLAUDE.md +0 -4
  148. package/.tmp_test_zip/out1/MOVA.md +0 -10
  149. package/.tmp_test_zip/out1/export.zip +0 -0
  150. package/.tmp_test_zip/out1/mova/claude_import/v0/VERSION.json +0 -10
  151. package/.tmp_test_zip/out1/mova/claude_import/v0/contracts/instruction_profile_v0.json +0 -8
  152. package/.tmp_test_zip/out1/mova/claude_import/v0/contracts/mcp_servers_v0.json +0 -4
  153. package/.tmp_test_zip/out1/mova/claude_import/v0/contracts/skills_catalog_v0.json +0 -11
  154. package/.tmp_test_zip/out1/mova/claude_import/v0/episode_import_run.json +0 -80
  155. package/.tmp_test_zip/out1/mova/claude_import/v0/export_manifest_v0.json +0 -32
  156. package/.tmp_test_zip/out1/mova/claude_import/v0/import_manifest.json +0 -33
  157. package/.tmp_test_zip/out1/mova/claude_import/v0/input_policy_report_v0.json +0 -38
  158. package/.tmp_test_zip/out1/mova/claude_import/v0/lint_report_v0.json +0 -6
  159. package/.tmp_test_zip/out1/mova/claude_import/v0/redaction_report.json +0 -4
  160. package/.tmp_test_zip/out2/.claude/agents/example_agent.md +0 -3
  161. package/.tmp_test_zip/out2/.claude/commands/example_command.md +0 -3
  162. package/.tmp_test_zip/out2/.claude/commands/mova_context.md +0 -4
  163. package/.tmp_test_zip/out2/.claude/commands/mova_lint.md +0 -4
  164. package/.tmp_test_zip/out2/.claude/commands/mova_proof.md +0 -6
  165. package/.tmp_test_zip/out2/.claude/hooks/example_hook.sh +0 -2
  166. package/.tmp_test_zip/out2/.claude/output-styles/example_style.md +0 -3
  167. package/.tmp_test_zip/out2/.claude/settings.json +0 -30
  168. package/.tmp_test_zip/out2/.claude/settings.local.example.json +0 -3
  169. package/.tmp_test_zip/out2/.claude/skills/a/SKILL.md +0 -1
  170. package/.tmp_test_zip/out2/.claude/skills/mova-control-v0/SKILL.md +0 -11
  171. package/.tmp_test_zip/out2/.claude/skills/mova-layer-v0/SKILL.md +0 -8
  172. package/.tmp_test_zip/out2/.mcp.json +0 -3
  173. package/.tmp_test_zip/out2/CLAUDE.md +0 -4
  174. package/.tmp_test_zip/out2/MOVA.md +0 -10
  175. package/.tmp_test_zip/out2/export.zip +0 -0
  176. package/.tmp_test_zip/out2/mova/claude_import/v0/VERSION.json +0 -10
  177. package/.tmp_test_zip/out2/mova/claude_import/v0/contracts/instruction_profile_v0.json +0 -8
  178. package/.tmp_test_zip/out2/mova/claude_import/v0/contracts/mcp_servers_v0.json +0 -4
  179. package/.tmp_test_zip/out2/mova/claude_import/v0/contracts/skills_catalog_v0.json +0 -11
  180. package/.tmp_test_zip/out2/mova/claude_import/v0/episode_import_run.json +0 -80
  181. package/.tmp_test_zip/out2/mova/claude_import/v0/export_manifest_v0.json +0 -32
  182. package/.tmp_test_zip/out2/mova/claude_import/v0/import_manifest.json +0 -33
  183. package/.tmp_test_zip/out2/mova/claude_import/v0/input_policy_report_v0.json +0 -38
  184. package/.tmp_test_zip/out2/mova/claude_import/v0/lint_report_v0.json +0 -6
  185. package/.tmp_test_zip/out2/mova/claude_import/v0/redaction_report.json +0 -4
  186. package/.tmp_test_zip/proj/.claude/skills/a.md +0 -1
  187. package/.tmp_test_zip/proj/.mcp.json +0 -1
  188. package/.tmp_test_zip/proj/CLAUDE.md +0 -1
@@ -0,0 +1,149 @@
1
+ export declare const CONTROL_V0_SCHEMA_ID = "https://mova.dev/schemas/mova.control_v0.schema.json";
2
+ export type AssetMode = "copy_through" | "managed";
3
+ export type AssetItem = {
4
+ path: string;
5
+ mode: AssetMode;
6
+ source_path?: string;
7
+ };
8
+ export type ControlV0 = {
9
+ $schema?: string;
10
+ version: "control_v0";
11
+ claude_md: {
12
+ inject_control_entry: boolean;
13
+ marker: string;
14
+ priority_sources: string[];
15
+ };
16
+ claude_memory: {
17
+ enable: boolean;
18
+ sources: string[];
19
+ };
20
+ overlay: {
21
+ enable: boolean;
22
+ };
23
+ settings: {
24
+ include_co_authored_by: boolean;
25
+ env: Record<string, string>;
26
+ };
27
+ mcp: {
28
+ servers: any;
29
+ enable_all_project_mcp_servers: boolean;
30
+ enabled_mcpjson_servers: string[];
31
+ env_substitutions: {
32
+ format: string;
33
+ default_format: string;
34
+ };
35
+ };
36
+ policy: {
37
+ mode: string;
38
+ hooks: {
39
+ enable: boolean;
40
+ on_invalid_hook: string;
41
+ definitions: any[];
42
+ events: Record<string, any>;
43
+ };
44
+ permissions: {
45
+ allow: any[];
46
+ deny: any[];
47
+ on_conflict: string;
48
+ on_unknown: string;
49
+ };
50
+ plugins: {
51
+ enable: boolean;
52
+ allowed_plugin_ids: any[];
53
+ denied_plugin_ids: any[];
54
+ on_unknown: string;
55
+ enabled_plugins: Record<string, boolean>;
56
+ };
57
+ };
58
+ lsp: {
59
+ enabled_plugins: string[];
60
+ config_path: string;
61
+ managed: boolean;
62
+ };
63
+ skill_eval: {
64
+ enable: boolean;
65
+ hooks: {
66
+ shell: string;
67
+ node: string;
68
+ };
69
+ rules_path: string;
70
+ scoring: {
71
+ threshold: number;
72
+ };
73
+ };
74
+ observability: {
75
+ enable: boolean;
76
+ mode: string;
77
+ writer: {
78
+ type: "node";
79
+ script_path: string;
80
+ };
81
+ output_dir: string;
82
+ stdout_tail_bytes: number;
83
+ stderr_tail_bytes: number;
84
+ max_event_bytes: number;
85
+ tail_lines: number;
86
+ include_tools: string[];
87
+ include_events: string[];
88
+ };
89
+ assets: {
90
+ skills: AssetItem[];
91
+ agents: AssetItem[];
92
+ commands: AssetItem[];
93
+ rules: AssetItem[];
94
+ hooks: AssetItem[];
95
+ workflows: AssetItem[];
96
+ docs: AssetItem[];
97
+ dotfiles: AssetItem[];
98
+ schemas: AssetItem[];
99
+ };
100
+ };
101
+ export declare function defaultControlV0(): ControlV0;
102
+ export declare function normalizeControlV0(input: any): {
103
+ control: ControlV0;
104
+ defaults: string[];
105
+ };
106
+ export declare function controlFromSettingsV0(settings: any | undefined, mcp: any | undefined): {
107
+ control: ControlV0;
108
+ defaults: string[];
109
+ };
110
+ export declare function controlToSettingsV0(control: ControlV0): {
111
+ includeCoAuthoredBy: boolean;
112
+ env: Record<string, string>;
113
+ mcp: {
114
+ enableAllProjectMcpServers: boolean;
115
+ enabledMcpjsonServers: string[];
116
+ };
117
+ permissions: {
118
+ allow: any[];
119
+ deny: any[];
120
+ behavior: {
121
+ on_conflict: string;
122
+ on_unknown: string;
123
+ };
124
+ };
125
+ plugins: {
126
+ enable: boolean;
127
+ allowed_plugin_ids: any[];
128
+ denied_plugin_ids: any[];
129
+ behavior: {
130
+ on_unknown: string;
131
+ };
132
+ enabledPlugins: Record<string, boolean>;
133
+ };
134
+ lsp: {
135
+ enabledPlugins: string[];
136
+ };
137
+ hooks: Record<string, any>;
138
+ claude_md: {
139
+ inject_control_entry: boolean;
140
+ marker: string;
141
+ };
142
+ };
143
+ export declare function controlToMcpJson(control: ControlV0): {
144
+ servers: any[];
145
+ mcpServers?: undefined;
146
+ } | {
147
+ mcpServers: Record<string, any>;
148
+ servers?: undefined;
149
+ };
@@ -0,0 +1,360 @@
1
+ import { MOVA_CONTROL_ENTRY_MARKER } from "./mova_overlay_v0.js";
2
+ export const CONTROL_V0_SCHEMA_ID = "https://mova.dev/schemas/mova.control_v0.schema.json";
3
+ function isObject(value) {
4
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
5
+ }
6
+ export function defaultControlV0() {
7
+ return {
8
+ $schema: CONTROL_V0_SCHEMA_ID,
9
+ version: "control_v0",
10
+ claude_md: {
11
+ inject_control_entry: true,
12
+ marker: MOVA_CONTROL_ENTRY_MARKER,
13
+ priority_sources: ["CLAUDE.md", ".claude/CLAUDE.md", "~/.claude/CLAUDE.md"],
14
+ },
15
+ claude_memory: {
16
+ enable: true,
17
+ sources: ["CLAUDE.md"],
18
+ },
19
+ overlay: {
20
+ enable: true,
21
+ },
22
+ settings: {
23
+ include_co_authored_by: true,
24
+ env: {},
25
+ },
26
+ mcp: {
27
+ servers: {},
28
+ enable_all_project_mcp_servers: false,
29
+ enabled_mcpjson_servers: [],
30
+ env_substitutions: {
31
+ format: "${VAR}",
32
+ default_format: "${VAR:-default}",
33
+ },
34
+ },
35
+ policy: {
36
+ mode: "report_only",
37
+ hooks: {
38
+ enable: true,
39
+ on_invalid_hook: "report_only",
40
+ definitions: [],
41
+ events: {},
42
+ },
43
+ permissions: {
44
+ allow: [],
45
+ deny: [],
46
+ on_conflict: "deny_wins",
47
+ on_unknown: "report_only",
48
+ },
49
+ plugins: {
50
+ enable: true,
51
+ allowed_plugin_ids: [],
52
+ denied_plugin_ids: [],
53
+ on_unknown: "report_only",
54
+ enabled_plugins: {},
55
+ },
56
+ },
57
+ lsp: {
58
+ enabled_plugins: [],
59
+ config_path: ".claude/lsp.json",
60
+ managed: false,
61
+ },
62
+ skill_eval: {
63
+ enable: false,
64
+ hooks: {
65
+ shell: ".claude/hooks/skill-eval.sh",
66
+ node: ".claude/hooks/skill-eval.js",
67
+ },
68
+ rules_path: ".claude/hooks/skill-rules.json",
69
+ scoring: {
70
+ threshold: 0.6,
71
+ },
72
+ },
73
+ observability: {
74
+ enable: true,
75
+ mode: "report_only",
76
+ writer: {
77
+ type: "node",
78
+ script_path: ".claude/hooks/mova-observe.js",
79
+ },
80
+ output_dir: ".mova/episodes",
81
+ stdout_tail_bytes: 4000,
82
+ stderr_tail_bytes: 4000,
83
+ max_event_bytes: 20000,
84
+ tail_lines: 50,
85
+ include_tools: ["Bash", "Read", "Edit", "MultiEdit", "Write"],
86
+ include_events: ["PostToolUse", "UserPromptSubmit", "Stop"],
87
+ },
88
+ assets: {
89
+ skills: [],
90
+ agents: [],
91
+ commands: [],
92
+ rules: [],
93
+ hooks: [],
94
+ workflows: [],
95
+ docs: [],
96
+ dotfiles: [],
97
+ schemas: [],
98
+ },
99
+ };
100
+ }
101
+ function coerceBoolean(value, fallback, defaults, path) {
102
+ if (typeof value === "boolean")
103
+ return value;
104
+ defaults.push(path);
105
+ return fallback;
106
+ }
107
+ function coerceString(value, fallback, defaults, path) {
108
+ if (typeof value === "string")
109
+ return value;
110
+ defaults.push(path);
111
+ return fallback;
112
+ }
113
+ function coerceNumber(value, fallback, defaults, path) {
114
+ if (typeof value === "number" && Number.isFinite(value))
115
+ return value;
116
+ defaults.push(path);
117
+ return fallback;
118
+ }
119
+ function coerceArray(value, fallback, defaults, path) {
120
+ if (Array.isArray(value))
121
+ return value;
122
+ defaults.push(path);
123
+ return fallback;
124
+ }
125
+ function coerceRecord(value, fallback, defaults, path) {
126
+ if (isObject(value))
127
+ return value;
128
+ defaults.push(path);
129
+ return fallback;
130
+ }
131
+ function coerceServers(value, fallback, defaults, path) {
132
+ if (Array.isArray(value))
133
+ return value;
134
+ if (isObject(value))
135
+ return value;
136
+ defaults.push(path);
137
+ return fallback;
138
+ }
139
+ function normalizeAssets(value, fallback, defaults, path) {
140
+ if (!Array.isArray(value)) {
141
+ defaults.push(path);
142
+ return fallback;
143
+ }
144
+ const normalized = [];
145
+ for (const item of value) {
146
+ if (!isObject(item) || typeof item.path !== "string")
147
+ continue;
148
+ const mode = item.mode === "managed" ? "managed" : "copy_through";
149
+ const entry = { path: item.path, mode };
150
+ if (typeof item.source_path === "string")
151
+ entry.source_path = item.source_path;
152
+ normalized.push(entry);
153
+ }
154
+ return normalized.sort((a, b) => a.path.localeCompare(b.path));
155
+ }
156
+ export function normalizeControlV0(input) {
157
+ const defaults = [];
158
+ const base = defaultControlV0();
159
+ const src = isObject(input) ? input : {};
160
+ base.$schema = CONTROL_V0_SCHEMA_ID;
161
+ base.version = "control_v0";
162
+ base.claude_md.inject_control_entry = coerceBoolean(src?.claude_md?.inject_control_entry, base.claude_md.inject_control_entry, defaults, "claude_md.inject_control_entry");
163
+ base.claude_md.marker = coerceString(src?.claude_md?.marker, base.claude_md.marker, defaults, "claude_md.marker");
164
+ base.claude_md.priority_sources = coerceArray(src?.claude_md?.priority_sources, base.claude_md.priority_sources, defaults, "claude_md.priority_sources");
165
+ base.claude_memory.enable = coerceBoolean(src?.claude_memory?.enable, base.claude_memory.enable, defaults, "claude_memory.enable");
166
+ base.claude_memory.sources = coerceArray(src?.claude_memory?.sources, base.claude_memory.sources, defaults, "claude_memory.sources");
167
+ base.overlay.enable = coerceBoolean(src?.overlay?.enable, base.overlay.enable, defaults, "overlay.enable");
168
+ base.settings.include_co_authored_by = coerceBoolean(src?.settings?.include_co_authored_by, base.settings.include_co_authored_by, defaults, "settings.include_co_authored_by");
169
+ base.settings.env = coerceRecord(src?.settings?.env, base.settings.env, defaults, "settings.env");
170
+ base.mcp.servers = coerceServers(src?.mcp?.servers, base.mcp.servers, defaults, "mcp.servers");
171
+ base.mcp.enable_all_project_mcp_servers = coerceBoolean(src?.mcp?.enable_all_project_mcp_servers, base.mcp.enable_all_project_mcp_servers, defaults, "mcp.enable_all_project_mcp_servers");
172
+ base.mcp.enabled_mcpjson_servers = coerceArray(src?.mcp?.enabled_mcpjson_servers, base.mcp.enabled_mcpjson_servers, defaults, "mcp.enabled_mcpjson_servers");
173
+ base.mcp.env_substitutions = coerceRecord(src?.mcp?.env_substitutions, base.mcp.env_substitutions, defaults, "mcp.env_substitutions");
174
+ base.mcp.env_substitutions.format = coerceString(base.mcp.env_substitutions.format, "${VAR}", defaults, "mcp.env_substitutions.format");
175
+ base.mcp.env_substitutions.default_format = coerceString(base.mcp.env_substitutions.default_format, "${VAR:-default}", defaults, "mcp.env_substitutions.default_format");
176
+ base.policy.mode = coerceString(src?.policy?.mode, base.policy.mode, defaults, "policy.mode");
177
+ base.policy.hooks.enable = coerceBoolean(src?.policy?.hooks?.enable, base.policy.hooks.enable, defaults, "policy.hooks.enable");
178
+ base.policy.hooks.on_invalid_hook = coerceString(src?.policy?.hooks?.on_invalid_hook, base.policy.hooks.on_invalid_hook, defaults, "policy.hooks.on_invalid_hook");
179
+ base.policy.hooks.definitions = coerceArray(src?.policy?.hooks?.definitions, base.policy.hooks.definitions, defaults, "policy.hooks.definitions");
180
+ base.policy.hooks.events = coerceRecord(src?.policy?.hooks?.events, base.policy.hooks.events, defaults, "policy.hooks.events");
181
+ base.policy.permissions.allow = coerceArray(src?.policy?.permissions?.allow, base.policy.permissions.allow, defaults, "policy.permissions.allow");
182
+ base.policy.permissions.deny = coerceArray(src?.policy?.permissions?.deny, base.policy.permissions.deny, defaults, "policy.permissions.deny");
183
+ base.policy.permissions.on_conflict = coerceString(src?.policy?.permissions?.on_conflict, base.policy.permissions.on_conflict, defaults, "policy.permissions.on_conflict");
184
+ base.policy.permissions.on_unknown = coerceString(src?.policy?.permissions?.on_unknown, base.policy.permissions.on_unknown, defaults, "policy.permissions.on_unknown");
185
+ base.policy.plugins.enable = coerceBoolean(src?.policy?.plugins?.enable, base.policy.plugins.enable, defaults, "policy.plugins.enable");
186
+ base.policy.plugins.allowed_plugin_ids = coerceArray(src?.policy?.plugins?.allowed_plugin_ids, base.policy.plugins.allowed_plugin_ids, defaults, "policy.plugins.allowed_plugin_ids");
187
+ base.policy.plugins.denied_plugin_ids = coerceArray(src?.policy?.plugins?.denied_plugin_ids, base.policy.plugins.denied_plugin_ids, defaults, "policy.plugins.denied_plugin_ids");
188
+ base.policy.plugins.on_unknown = coerceString(src?.policy?.plugins?.on_unknown, base.policy.plugins.on_unknown, defaults, "policy.plugins.on_unknown");
189
+ base.policy.plugins.enabled_plugins = coerceRecord(src?.policy?.plugins?.enabled_plugins, base.policy.plugins.enabled_plugins, defaults, "policy.plugins.enabled_plugins");
190
+ base.lsp.enabled_plugins = coerceArray(src?.lsp?.enabled_plugins, base.lsp.enabled_plugins, defaults, "lsp.enabled_plugins");
191
+ base.lsp.config_path = coerceString(src?.lsp?.config_path, base.lsp.config_path, defaults, "lsp.config_path");
192
+ base.lsp.managed = coerceBoolean(src?.lsp?.managed, base.lsp.managed, defaults, "lsp.managed");
193
+ base.skill_eval.enable = coerceBoolean(src?.skill_eval?.enable, base.skill_eval.enable, defaults, "skill_eval.enable");
194
+ base.skill_eval.hooks = coerceRecord(src?.skill_eval?.hooks, base.skill_eval.hooks, defaults, "skill_eval.hooks");
195
+ base.skill_eval.hooks.shell = coerceString(base.skill_eval.hooks.shell, defaultControlV0().skill_eval.hooks.shell, defaults, "skill_eval.hooks.shell");
196
+ base.skill_eval.hooks.node = coerceString(base.skill_eval.hooks.node, defaultControlV0().skill_eval.hooks.node, defaults, "skill_eval.hooks.node");
197
+ base.skill_eval.rules_path = coerceString(src?.skill_eval?.rules_path, base.skill_eval.rules_path, defaults, "skill_eval.rules_path");
198
+ base.skill_eval.scoring = coerceRecord(src?.skill_eval?.scoring, base.skill_eval.scoring, defaults, "skill_eval.scoring");
199
+ base.skill_eval.scoring.threshold = coerceNumber(base.skill_eval.scoring.threshold, defaultControlV0().skill_eval.scoring.threshold, defaults, "skill_eval.scoring.threshold");
200
+ base.observability.enable = coerceBoolean(src?.observability?.enable, base.observability.enable, defaults, "observability.enable");
201
+ base.observability.mode = coerceString(src?.observability?.mode, base.observability.mode, defaults, "observability.mode");
202
+ base.observability.writer = coerceRecord(src?.observability?.writer, base.observability.writer, defaults, "observability.writer");
203
+ base.observability.writer.type = "node";
204
+ base.observability.writer.script_path = coerceString(base.observability.writer.script_path, defaultControlV0().observability.writer.script_path, defaults, "observability.writer.script_path");
205
+ base.observability.output_dir = coerceString(src?.observability?.output_dir, base.observability.output_dir, defaults, "observability.output_dir");
206
+ base.observability.stdout_tail_bytes = coerceNumber(src?.observability?.stdout_tail_bytes, base.observability.stdout_tail_bytes, defaults, "observability.stdout_tail_bytes");
207
+ base.observability.stderr_tail_bytes = coerceNumber(src?.observability?.stderr_tail_bytes, base.observability.stderr_tail_bytes, defaults, "observability.stderr_tail_bytes");
208
+ base.observability.max_event_bytes = coerceNumber(src?.observability?.max_event_bytes, base.observability.max_event_bytes, defaults, "observability.max_event_bytes");
209
+ base.observability.tail_lines = coerceNumber(src?.observability?.tail_lines, base.observability.tail_lines, defaults, "observability.tail_lines");
210
+ base.observability.include_tools = coerceArray(src?.observability?.include_tools, base.observability.include_tools, defaults, "observability.include_tools");
211
+ base.observability.include_events = coerceArray(src?.observability?.include_events, base.observability.include_events, defaults, "observability.include_events");
212
+ base.assets.skills = normalizeAssets(src?.assets?.skills, base.assets.skills, defaults, "assets.skills");
213
+ base.assets.agents = normalizeAssets(src?.assets?.agents, base.assets.agents, defaults, "assets.agents");
214
+ base.assets.commands = normalizeAssets(src?.assets?.commands, base.assets.commands, defaults, "assets.commands");
215
+ base.assets.rules = normalizeAssets(src?.assets?.rules, base.assets.rules, defaults, "assets.rules");
216
+ base.assets.hooks = normalizeAssets(src?.assets?.hooks, base.assets.hooks, defaults, "assets.hooks");
217
+ base.assets.workflows = normalizeAssets(src?.assets?.workflows, base.assets.workflows, defaults, "assets.workflows");
218
+ base.assets.docs = normalizeAssets(src?.assets?.docs, base.assets.docs, defaults, "assets.docs");
219
+ base.assets.dotfiles = normalizeAssets(src?.assets?.dotfiles, base.assets.dotfiles, defaults, "assets.dotfiles");
220
+ base.assets.schemas = normalizeAssets(src?.assets?.schemas, base.assets.schemas, defaults, "assets.schemas");
221
+ return { control: base, defaults };
222
+ }
223
+ export function controlFromSettingsV0(settings, mcp) {
224
+ const defaults = [];
225
+ const base = defaultControlV0();
226
+ if (!settings) {
227
+ defaults.push("settings", "policy", "claude_md");
228
+ }
229
+ else {
230
+ base.settings.include_co_authored_by = coerceBoolean(settings?.includeCoAuthoredBy, base.settings.include_co_authored_by, defaults, "settings.include_co_authored_by");
231
+ base.settings.env = coerceRecord(settings?.env, base.settings.env, defaults, "settings.env");
232
+ base.policy.hooks.enable = coerceBoolean(settings?.hooks?.enable ?? true, base.policy.hooks.enable, defaults, "policy.hooks.enable");
233
+ base.policy.hooks.on_invalid_hook = coerceString(settings?.hooks?.behavior?.on_invalid_hook, base.policy.hooks.on_invalid_hook, defaults, "policy.hooks.on_invalid_hook");
234
+ base.policy.hooks.definitions = coerceArray(settings?.hooks?.definitions, base.policy.hooks.definitions, defaults, "policy.hooks.definitions");
235
+ const events = {};
236
+ if (isObject(settings?.hooks)) {
237
+ for (const [key, value] of Object.entries(settings.hooks)) {
238
+ if (key === "enable" || key === "behavior" || key === "definitions")
239
+ continue;
240
+ events[key] = value;
241
+ }
242
+ }
243
+ base.policy.hooks.events = events;
244
+ base.policy.permissions.allow = coerceArray(settings?.permissions?.allow, base.policy.permissions.allow, defaults, "policy.permissions.allow");
245
+ base.policy.permissions.deny = coerceArray(settings?.permissions?.deny, base.policy.permissions.deny, defaults, "policy.permissions.deny");
246
+ base.policy.permissions.on_conflict = coerceString(settings?.permissions?.behavior?.on_conflict, base.policy.permissions.on_conflict, defaults, "policy.permissions.on_conflict");
247
+ base.policy.permissions.on_unknown = coerceString(settings?.permissions?.behavior?.on_unknown, base.policy.permissions.on_unknown, defaults, "policy.permissions.on_unknown");
248
+ base.policy.plugins.enable = coerceBoolean(settings?.plugins?.enable, base.policy.plugins.enable, defaults, "policy.plugins.enable");
249
+ base.policy.plugins.allowed_plugin_ids = coerceArray(settings?.plugins?.allowed_plugin_ids, base.policy.plugins.allowed_plugin_ids, defaults, "policy.plugins.allowed_plugin_ids");
250
+ base.policy.plugins.denied_plugin_ids = coerceArray(settings?.plugins?.denied_plugin_ids, base.policy.plugins.denied_plugin_ids, defaults, "policy.plugins.denied_plugin_ids");
251
+ base.policy.plugins.on_unknown = coerceString(settings?.plugins?.behavior?.on_unknown, base.policy.plugins.on_unknown, defaults, "policy.plugins.on_unknown");
252
+ base.policy.plugins.enabled_plugins = coerceRecord(settings?.plugins?.enabledPlugins, base.policy.plugins.enabled_plugins, defaults, "policy.plugins.enabled_plugins");
253
+ base.claude_md.inject_control_entry = coerceBoolean(settings?.claude_md?.inject_control_entry, base.claude_md.inject_control_entry, defaults, "claude_md.inject_control_entry");
254
+ base.claude_md.marker = coerceString(settings?.claude_md?.marker, base.claude_md.marker, defaults, "claude_md.marker");
255
+ base.mcp.enable_all_project_mcp_servers = coerceBoolean(settings?.mcp?.enableAllProjectMcpServers, base.mcp.enable_all_project_mcp_servers, defaults, "mcp.enable_all_project_mcp_servers");
256
+ base.mcp.enabled_mcpjson_servers = coerceArray(settings?.mcp?.enabledMcpjsonServers, base.mcp.enabled_mcpjson_servers, defaults, "mcp.enabled_mcpjson_servers");
257
+ base.lsp.enabled_plugins = coerceArray(settings?.lsp?.enabledPlugins, base.lsp.enabled_plugins, defaults, "lsp.enabled_plugins");
258
+ }
259
+ if (!mcp) {
260
+ defaults.push("mcp.servers");
261
+ }
262
+ else if (isObject(mcp) && isObject(mcp.mcpServers)) {
263
+ base.mcp.servers = mcp.mcpServers;
264
+ }
265
+ else {
266
+ base.mcp.servers = coerceServers(mcp?.servers, base.mcp.servers, defaults, "mcp.servers");
267
+ }
268
+ return { control: base, defaults };
269
+ }
270
+ export function controlToSettingsV0(control) {
271
+ const hooks = {
272
+ enable: control.policy.hooks.enable,
273
+ definitions: control.policy.hooks.definitions,
274
+ behavior: {
275
+ on_invalid_hook: control.policy.hooks.on_invalid_hook,
276
+ },
277
+ };
278
+ for (const [event, value] of Object.entries(control.policy.hooks.events)) {
279
+ hooks[event] = value;
280
+ }
281
+ if (control.observability.enable && Array.isArray(control.observability.include_events)) {
282
+ const scriptRel = control.observability.writer.script_path.replace(/^[\\/]+/, "");
283
+ const baseCommand = `node \"$CLAUDE_PROJECT_DIR/${scriptRel}\"`;
284
+ const commonArgs = [
285
+ `--stdout-tail-bytes ${control.observability.stdout_tail_bytes}`,
286
+ `--stderr-tail-bytes ${control.observability.stderr_tail_bytes}`,
287
+ `--max-event-bytes ${control.observability.max_event_bytes}`,
288
+ `--tail-lines ${control.observability.tail_lines}`,
289
+ `--output-dir ${control.observability.output_dir}`,
290
+ ].join(" ");
291
+ const postMatcher = control.observability.include_tools.length
292
+ ? control.observability.include_tools.join("|")
293
+ : undefined;
294
+ const ensureEventHook = (event, matcher) => {
295
+ const entry = {
296
+ hooks: [
297
+ {
298
+ type: "command",
299
+ command: `${baseCommand} --event ${event} ${commonArgs}`.trim(),
300
+ timeout: 5,
301
+ },
302
+ ],
303
+ };
304
+ if (matcher)
305
+ entry.matcher = matcher;
306
+ hooks[event] = Array.isArray(hooks[event]) ? [...hooks[event], entry] : [entry];
307
+ };
308
+ if (control.observability.include_events.includes("PostToolUse")) {
309
+ ensureEventHook("PostToolUse", postMatcher);
310
+ }
311
+ if (control.observability.include_events.includes("UserPromptSubmit")) {
312
+ ensureEventHook("UserPromptSubmit");
313
+ }
314
+ if (control.observability.include_events.includes("Stop")) {
315
+ ensureEventHook("Stop");
316
+ }
317
+ }
318
+ return {
319
+ includeCoAuthoredBy: control.settings.include_co_authored_by,
320
+ env: control.settings.env,
321
+ mcp: {
322
+ enableAllProjectMcpServers: control.mcp.enable_all_project_mcp_servers,
323
+ enabledMcpjsonServers: control.mcp.enabled_mcpjson_servers,
324
+ },
325
+ permissions: {
326
+ allow: control.policy.permissions.allow,
327
+ deny: control.policy.permissions.deny,
328
+ behavior: {
329
+ on_conflict: control.policy.permissions.on_conflict,
330
+ on_unknown: control.policy.permissions.on_unknown,
331
+ },
332
+ },
333
+ plugins: {
334
+ enable: control.policy.plugins.enable,
335
+ allowed_plugin_ids: control.policy.plugins.allowed_plugin_ids,
336
+ denied_plugin_ids: control.policy.plugins.denied_plugin_ids,
337
+ behavior: {
338
+ on_unknown: control.policy.plugins.on_unknown,
339
+ },
340
+ enabledPlugins: control.policy.plugins.enabled_plugins,
341
+ },
342
+ lsp: {
343
+ enabledPlugins: control.lsp.enabled_plugins,
344
+ },
345
+ hooks,
346
+ claude_md: {
347
+ inject_control_entry: control.claude_md.inject_control_entry,
348
+ marker: control.claude_md.marker,
349
+ },
350
+ };
351
+ }
352
+ export function controlToMcpJson(control) {
353
+ if (Array.isArray(control.mcp.servers)) {
354
+ return { servers: control.mcp.servers };
355
+ }
356
+ if (isObject(control.mcp.servers)) {
357
+ return { mcpServers: control.mcp.servers };
358
+ }
359
+ return { servers: [] };
360
+ }
@@ -0,0 +1,6 @@
1
+ type ValidationResult = {
2
+ ok: boolean;
3
+ errors: any[] | null | undefined;
4
+ };
5
+ export declare function validateControlV0Schema(control: any): Promise<ValidationResult>;
6
+ export {};
@@ -0,0 +1,19 @@
1
+ import fs from "node:fs/promises";
2
+ import { fileURLToPath } from "node:url";
3
+ import Ajv from "ajv";
4
+ import addFormats from "ajv-formats";
5
+ import { CONTROL_V0_SCHEMA_ID } from "./control_v0.js";
6
+ async function loadControlSchema() {
7
+ const schemaPath = fileURLToPath(new URL("../schemas/mova.control_v0.schema.json", import.meta.url));
8
+ const raw = await fs.readFile(schemaPath, "utf8");
9
+ return JSON.parse(raw);
10
+ }
11
+ export async function validateControlV0Schema(control) {
12
+ const schema = await loadControlSchema();
13
+ const ajv = new Ajv({ allErrors: true, strict: true, validateSchema: false });
14
+ addFormats(ajv);
15
+ ajv.addSchema(schema, CONTROL_V0_SCHEMA_ID);
16
+ const validate = ajv.compile(schema);
17
+ const ok = Boolean(validate(control));
18
+ return { ok, errors: validate.errors };
19
+ }
package/dist/init_v0.d.ts CHANGED
@@ -1,7 +1,12 @@
1
+ import { type ControlV0 } from "./control_v0.js";
1
2
  type InitResult = {
2
3
  createdFiles: string[];
3
4
  zipRelPath?: string;
4
5
  zipSha256?: string;
5
6
  };
6
- export declare function initProfileV0(outRoot: string, emitZip: boolean): Promise<InitResult>;
7
+ type InitOptions = {
8
+ controlOverride?: ControlV0;
9
+ assetsRoot?: string;
10
+ };
11
+ export declare function initProfileV0(outRoot: string, emitZip: boolean, options?: InitOptions): Promise<InitResult>;
7
12
  export {};
package/dist/init_v0.js CHANGED
@@ -4,6 +4,7 @@ import { getAnthropicProfileV0Files } from "./anthropic_profile_v0.js";
4
4
  import { stableStringify } from "./stable_json.js";
5
5
  import { createExportZipV0 } from "./export_zip_v0.js";
6
6
  import { writeCleanClaudeProfileScaffoldV0 } from "./claude_profile_scaffold_v0.js";
7
+ import { defaultControlV0 } from "./control_v0.js";
7
8
  async function writeTextFile(absPath, content) {
8
9
  await fs.mkdir(path.dirname(absPath), { recursive: true });
9
10
  await fs.writeFile(absPath, content, "utf8");
@@ -12,7 +13,38 @@ async function writeJsonFile(absPath, obj) {
12
13
  await fs.mkdir(path.dirname(absPath), { recursive: true });
13
14
  await fs.writeFile(absPath, stableStringify(obj) + "\n", "utf8");
14
15
  }
15
- export async function initProfileV0(outRoot, emitZip) {
16
+ async function copyPresetAssets(control, assetsRoot, outRoot) {
17
+ const created = [];
18
+ const assets = [
19
+ ...control.assets.skills,
20
+ ...control.assets.agents,
21
+ ...control.assets.commands,
22
+ ...control.assets.rules,
23
+ ...control.assets.hooks,
24
+ ...control.assets.workflows,
25
+ ...control.assets.docs,
26
+ ...control.assets.dotfiles,
27
+ ...control.assets.schemas,
28
+ ];
29
+ for (const asset of assets) {
30
+ const sourceRel = asset.source_path ?? asset.path;
31
+ const source = path.isAbsolute(sourceRel) ? sourceRel : path.join(assetsRoot, sourceRel);
32
+ const target = path.join(outRoot, asset.path);
33
+ try {
34
+ await fs.stat(source);
35
+ }
36
+ catch {
37
+ continue;
38
+ }
39
+ await fs.mkdir(path.dirname(target), { recursive: true });
40
+ if (source !== target) {
41
+ await fs.copyFile(source, target);
42
+ }
43
+ created.push(asset.path.replace(/\\/g, "/"));
44
+ }
45
+ return created.sort();
46
+ }
47
+ export async function initProfileV0(outRoot, emitZip, options) {
16
48
  const createdFiles = [];
17
49
  await writeCleanClaudeProfileScaffoldV0(outRoot);
18
50
  const profileFiles = getAnthropicProfileV0Files();
@@ -22,6 +54,14 @@ export async function initProfileV0(outRoot, emitZip) {
22
54
  await writeTextFile(path.join(outRoot, rel), content);
23
55
  createdFiles.push(rel);
24
56
  }
57
+ const controlRel = path.join("mova", "control_v0.json").replace(/\\/g, "/");
58
+ const control = options?.controlOverride ?? defaultControlV0();
59
+ await writeJsonFile(path.join(outRoot, controlRel), control);
60
+ createdFiles.push(controlRel);
61
+ if (options?.assetsRoot) {
62
+ const assetFiles = await copyPresetAssets(control, options.assetsRoot, outRoot);
63
+ createdFiles.push(...assetFiles);
64
+ }
25
65
  const movaBase = path.join(outRoot, "mova", "claude_import", "v0");
26
66
  const initManifestRel = path.join("mova", "claude_import", "v0", "init_manifest_v0.json").replace(/\\/g, "/");
27
67
  let zipRelPath;
@@ -0,0 +1 @@
1
+ export declare function getMovaObserveScriptV0(): string;