@ikenga/contract 0.12.0 → 0.13.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.
@@ -0,0 +1,389 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * The eight stateful domains plus the one stateless generic skill.
4
+ * `skill-core` is the ONLY legal `depends_on` target (one-way edge, G-04/E-14).
5
+ */
6
+ export declare const DomainEnum: z.ZodEnum<["tasks", "mail", "outbound", "sales", "finance", "content", "research", "strategy", "skill-core"]>;
7
+ export type Domain = z.infer<typeof DomainEnum>;
8
+ /**
9
+ * How an action presents itself to the operator.
10
+ * - confirm : preview the planned effect, single yes/no, then run.
11
+ * - silent : run with no prompt (still subject to capability scopes).
12
+ * - form : collect `inputs_schema` from the operator before running.
13
+ * - streaming : run with live token/log streaming surfaced in the dock.
14
+ * - approve : run-THEN-pause on a produced draft; operator approves/edits
15
+ * /rejects the artifact before any external side effect commits
16
+ * (the draft-review gate, E-11).
17
+ */
18
+ export declare const UxModeEnum: z.ZodEnum<["confirm", "silent", "form", "streaming", "approve"]>;
19
+ export type UxMode = z.infer<typeof UxModeEnum>;
20
+ export declare const RunBinding: z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
21
+ kind: z.ZodLiteral<"chat_prompt">;
22
+ prompt: z.ZodString;
23
+ }, "strip", z.ZodTypeAny, {
24
+ kind: "chat_prompt";
25
+ prompt: string;
26
+ }, {
27
+ kind: "chat_prompt";
28
+ prompt: string;
29
+ }>, z.ZodObject<{
30
+ kind: z.ZodLiteral<"sidecar">;
31
+ sidecar_id: z.ZodString;
32
+ args: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
33
+ }, "strip", z.ZodTypeAny, {
34
+ kind: "sidecar";
35
+ sidecar_id: string;
36
+ args: string[];
37
+ }, {
38
+ kind: "sidecar";
39
+ sidecar_id: string;
40
+ args?: string[] | undefined;
41
+ }>, z.ZodObject<{
42
+ kind: z.ZodLiteral<"mcp_tool">;
43
+ server_id: z.ZodString;
44
+ tool: z.ZodString;
45
+ }, "strip", z.ZodTypeAny, {
46
+ kind: "mcp_tool";
47
+ server_id: string;
48
+ tool: string;
49
+ }, {
50
+ kind: "mcp_tool";
51
+ server_id: string;
52
+ tool: string;
53
+ }>]>;
54
+ export type RunBinding = z.infer<typeof RunBinding>;
55
+ export declare const Trigger: z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
56
+ kind: z.ZodLiteral<"manual">;
57
+ }, "strip", z.ZodTypeAny, {
58
+ kind: "manual";
59
+ }, {
60
+ kind: "manual";
61
+ }>, z.ZodObject<{
62
+ kind: z.ZodLiteral<"schedule">;
63
+ cron: z.ZodString;
64
+ label: z.ZodOptional<z.ZodString>;
65
+ }, "strip", z.ZodTypeAny, {
66
+ kind: "schedule";
67
+ cron: string;
68
+ label?: string | undefined;
69
+ }, {
70
+ kind: "schedule";
71
+ cron: string;
72
+ label?: string | undefined;
73
+ }>, z.ZodObject<{
74
+ kind: z.ZodLiteral<"webhook">;
75
+ path: z.ZodString;
76
+ }, "strip", z.ZodTypeAny, {
77
+ path: string;
78
+ kind: "webhook";
79
+ }, {
80
+ path: string;
81
+ kind: "webhook";
82
+ }>, z.ZodObject<{
83
+ kind: z.ZodLiteral<"event">;
84
+ event: z.ZodString;
85
+ }, "strip", z.ZodTypeAny, {
86
+ kind: "event";
87
+ event: string;
88
+ }, {
89
+ kind: "event";
90
+ event: string;
91
+ }>]>;
92
+ export type Trigger = z.infer<typeof Trigger>;
93
+ export declare const CapabilityEnum: z.ZodEnum<["sqlite", "mcp", "sidecar", "network", "fs", "secrets", "chat"]>;
94
+ export type Capability = z.infer<typeof CapabilityEnum>;
95
+ export declare const SetupModeEnum: z.ZodEnum<["ai_infer", "interview"]>;
96
+ export type SetupMode = z.infer<typeof SetupModeEnum>;
97
+ export declare const SetupSpec: z.ZodObject<{
98
+ mode: z.ZodEnum<["ai_infer", "interview"]>;
99
+ template_version: z.ZodNumber;
100
+ infer_sources: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
101
+ interview_questions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
102
+ }, "strip", z.ZodTypeAny, {
103
+ mode: "ai_infer" | "interview";
104
+ template_version: number;
105
+ infer_sources?: string[] | undefined;
106
+ interview_questions?: string[] | undefined;
107
+ }, {
108
+ mode: "ai_infer" | "interview";
109
+ template_version: number;
110
+ infer_sources?: string[] | undefined;
111
+ interview_questions?: string[] | undefined;
112
+ }>;
113
+ export type SetupSpec = z.infer<typeof SetupSpec>;
114
+ export declare const ActionFrontmatter: z.ZodEffects<z.ZodObject<{
115
+ /** Stable action id, unique within the skill. kebab-case. */
116
+ name: z.ZodString;
117
+ /** One-line human description shown in the command surface. */
118
+ description: z.ZodString;
119
+ /** Owning domain (G-TAXONOMY). */
120
+ domain: z.ZodEnum<["tasks", "mail", "outbound", "sales", "finance", "content", "research", "strategy", "skill-core"]>;
121
+ /** How the action presents to the operator (R5/E-11). */
122
+ ux_mode: z.ZodEnum<["confirm", "silent", "form", "streaming", "approve"]>;
123
+ /**
124
+ * JSON-Schema describing the action's inputs. Kept as an opaque object here
125
+ * (validated as JSON-Schema at the destination); `form`/`approve` modes
126
+ * render it, `chat_prompt` runs interpolate validated values from it.
127
+ */
128
+ inputs_schema: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
129
+ /** What the action actually does (G-01). */
130
+ run: z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
131
+ kind: z.ZodLiteral<"chat_prompt">;
132
+ prompt: z.ZodString;
133
+ }, "strip", z.ZodTypeAny, {
134
+ kind: "chat_prompt";
135
+ prompt: string;
136
+ }, {
137
+ kind: "chat_prompt";
138
+ prompt: string;
139
+ }>, z.ZodObject<{
140
+ kind: z.ZodLiteral<"sidecar">;
141
+ sidecar_id: z.ZodString;
142
+ args: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
143
+ }, "strip", z.ZodTypeAny, {
144
+ kind: "sidecar";
145
+ sidecar_id: string;
146
+ args: string[];
147
+ }, {
148
+ kind: "sidecar";
149
+ sidecar_id: string;
150
+ args?: string[] | undefined;
151
+ }>, z.ZodObject<{
152
+ kind: z.ZodLiteral<"mcp_tool">;
153
+ server_id: z.ZodString;
154
+ tool: z.ZodString;
155
+ }, "strip", z.ZodTypeAny, {
156
+ kind: "mcp_tool";
157
+ server_id: string;
158
+ tool: string;
159
+ }, {
160
+ kind: "mcp_tool";
161
+ server_id: string;
162
+ tool: string;
163
+ }>]>;
164
+ /** How the action can be invoked. Empty ⇒ manual-only. */
165
+ triggers: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<"kind", [z.ZodObject<{
166
+ kind: z.ZodLiteral<"manual">;
167
+ }, "strip", z.ZodTypeAny, {
168
+ kind: "manual";
169
+ }, {
170
+ kind: "manual";
171
+ }>, z.ZodObject<{
172
+ kind: z.ZodLiteral<"schedule">;
173
+ cron: z.ZodString;
174
+ label: z.ZodOptional<z.ZodString>;
175
+ }, "strip", z.ZodTypeAny, {
176
+ kind: "schedule";
177
+ cron: string;
178
+ label?: string | undefined;
179
+ }, {
180
+ kind: "schedule";
181
+ cron: string;
182
+ label?: string | undefined;
183
+ }>, z.ZodObject<{
184
+ kind: z.ZodLiteral<"webhook">;
185
+ path: z.ZodString;
186
+ }, "strip", z.ZodTypeAny, {
187
+ path: string;
188
+ kind: "webhook";
189
+ }, {
190
+ path: string;
191
+ kind: "webhook";
192
+ }>, z.ZodObject<{
193
+ kind: z.ZodLiteral<"event">;
194
+ event: z.ZodString;
195
+ }, "strip", z.ZodTypeAny, {
196
+ kind: "event";
197
+ event: string;
198
+ }, {
199
+ kind: "event";
200
+ event: string;
201
+ }>]>, "many">>;
202
+ /**
203
+ * One-way dependency edge. The ONLY legal target is 'skill-core'
204
+ * (G-04/E-14); any other entry is rejected by the lint in
205
+ * 06-skill-action-contract.md §"depends_on lint". Modeled as a literal
206
+ * array so the schema itself refuses non-skill-core targets.
207
+ */
208
+ depends_on: z.ZodDefault<z.ZodArray<z.ZodLiteral<"skill-core">, "many">>;
209
+ /** Coarse capability grants this action needs (G-08, R18/R19). */
210
+ requires_capabilities: z.ZodDefault<z.ZodArray<z.ZodEnum<["sqlite", "mcp", "sidecar", "network", "fs", "secrets", "chat"]>, "many">>;
211
+ /**
212
+ * Present ONLY on the well-known `setup` action. Omitted on every other
213
+ * action. Refined below.
214
+ */
215
+ setup: z.ZodOptional<z.ZodObject<{
216
+ mode: z.ZodEnum<["ai_infer", "interview"]>;
217
+ template_version: z.ZodNumber;
218
+ infer_sources: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
219
+ interview_questions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
220
+ }, "strip", z.ZodTypeAny, {
221
+ mode: "ai_infer" | "interview";
222
+ template_version: number;
223
+ infer_sources?: string[] | undefined;
224
+ interview_questions?: string[] | undefined;
225
+ }, {
226
+ mode: "ai_infer" | "interview";
227
+ template_version: number;
228
+ infer_sources?: string[] | undefined;
229
+ interview_questions?: string[] | undefined;
230
+ }>>;
231
+ }, "strict", z.ZodTypeAny, {
232
+ name: string;
233
+ description: string;
234
+ domain: "tasks" | "mail" | "outbound" | "sales" | "finance" | "content" | "research" | "strategy" | "skill-core";
235
+ ux_mode: "confirm" | "silent" | "form" | "streaming" | "approve";
236
+ run: {
237
+ kind: "chat_prompt";
238
+ prompt: string;
239
+ } | {
240
+ kind: "sidecar";
241
+ sidecar_id: string;
242
+ args: string[];
243
+ } | {
244
+ kind: "mcp_tool";
245
+ server_id: string;
246
+ tool: string;
247
+ };
248
+ triggers: ({
249
+ kind: "manual";
250
+ } | {
251
+ kind: "schedule";
252
+ cron: string;
253
+ label?: string | undefined;
254
+ } | {
255
+ path: string;
256
+ kind: "webhook";
257
+ } | {
258
+ kind: "event";
259
+ event: string;
260
+ })[];
261
+ depends_on: "skill-core"[];
262
+ requires_capabilities: ("sidecar" | "sqlite" | "mcp" | "network" | "fs" | "secrets" | "chat")[];
263
+ inputs_schema?: Record<string, unknown> | undefined;
264
+ setup?: {
265
+ mode: "ai_infer" | "interview";
266
+ template_version: number;
267
+ infer_sources?: string[] | undefined;
268
+ interview_questions?: string[] | undefined;
269
+ } | undefined;
270
+ }, {
271
+ name: string;
272
+ description: string;
273
+ domain: "tasks" | "mail" | "outbound" | "sales" | "finance" | "content" | "research" | "strategy" | "skill-core";
274
+ ux_mode: "confirm" | "silent" | "form" | "streaming" | "approve";
275
+ run: {
276
+ kind: "chat_prompt";
277
+ prompt: string;
278
+ } | {
279
+ kind: "sidecar";
280
+ sidecar_id: string;
281
+ args?: string[] | undefined;
282
+ } | {
283
+ kind: "mcp_tool";
284
+ server_id: string;
285
+ tool: string;
286
+ };
287
+ inputs_schema?: Record<string, unknown> | undefined;
288
+ triggers?: ({
289
+ kind: "manual";
290
+ } | {
291
+ kind: "schedule";
292
+ cron: string;
293
+ label?: string | undefined;
294
+ } | {
295
+ path: string;
296
+ kind: "webhook";
297
+ } | {
298
+ kind: "event";
299
+ event: string;
300
+ })[] | undefined;
301
+ depends_on?: "skill-core"[] | undefined;
302
+ requires_capabilities?: ("sidecar" | "sqlite" | "mcp" | "network" | "fs" | "secrets" | "chat")[] | undefined;
303
+ setup?: {
304
+ mode: "ai_infer" | "interview";
305
+ template_version: number;
306
+ infer_sources?: string[] | undefined;
307
+ interview_questions?: string[] | undefined;
308
+ } | undefined;
309
+ }>, {
310
+ name: string;
311
+ description: string;
312
+ domain: "tasks" | "mail" | "outbound" | "sales" | "finance" | "content" | "research" | "strategy" | "skill-core";
313
+ ux_mode: "confirm" | "silent" | "form" | "streaming" | "approve";
314
+ run: {
315
+ kind: "chat_prompt";
316
+ prompt: string;
317
+ } | {
318
+ kind: "sidecar";
319
+ sidecar_id: string;
320
+ args: string[];
321
+ } | {
322
+ kind: "mcp_tool";
323
+ server_id: string;
324
+ tool: string;
325
+ };
326
+ triggers: ({
327
+ kind: "manual";
328
+ } | {
329
+ kind: "schedule";
330
+ cron: string;
331
+ label?: string | undefined;
332
+ } | {
333
+ path: string;
334
+ kind: "webhook";
335
+ } | {
336
+ kind: "event";
337
+ event: string;
338
+ })[];
339
+ depends_on: "skill-core"[];
340
+ requires_capabilities: ("sidecar" | "sqlite" | "mcp" | "network" | "fs" | "secrets" | "chat")[];
341
+ inputs_schema?: Record<string, unknown> | undefined;
342
+ setup?: {
343
+ mode: "ai_infer" | "interview";
344
+ template_version: number;
345
+ infer_sources?: string[] | undefined;
346
+ interview_questions?: string[] | undefined;
347
+ } | undefined;
348
+ }, {
349
+ name: string;
350
+ description: string;
351
+ domain: "tasks" | "mail" | "outbound" | "sales" | "finance" | "content" | "research" | "strategy" | "skill-core";
352
+ ux_mode: "confirm" | "silent" | "form" | "streaming" | "approve";
353
+ run: {
354
+ kind: "chat_prompt";
355
+ prompt: string;
356
+ } | {
357
+ kind: "sidecar";
358
+ sidecar_id: string;
359
+ args?: string[] | undefined;
360
+ } | {
361
+ kind: "mcp_tool";
362
+ server_id: string;
363
+ tool: string;
364
+ };
365
+ inputs_schema?: Record<string, unknown> | undefined;
366
+ triggers?: ({
367
+ kind: "manual";
368
+ } | {
369
+ kind: "schedule";
370
+ cron: string;
371
+ label?: string | undefined;
372
+ } | {
373
+ path: string;
374
+ kind: "webhook";
375
+ } | {
376
+ kind: "event";
377
+ event: string;
378
+ })[] | undefined;
379
+ depends_on?: "skill-core"[] | undefined;
380
+ requires_capabilities?: ("sidecar" | "sqlite" | "mcp" | "network" | "fs" | "secrets" | "chat")[] | undefined;
381
+ setup?: {
382
+ mode: "ai_infer" | "interview";
383
+ template_version: number;
384
+ infer_sources?: string[] | undefined;
385
+ interview_questions?: string[] | undefined;
386
+ } | undefined;
387
+ }>;
388
+ export type ActionFrontmatter = z.infer<typeof ActionFrontmatter>;
389
+ //# sourceMappingURL=action-frontmatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-frontmatter.d.ts","sourceRoot":"","sources":["../src/action-frontmatter.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB;;;GAGG;AACH,eAAO,MAAM,UAAU,+GAUrB,CAAC;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAMhD;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,kEAMrB,CAAC;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AA4BhD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAIrB,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAiCpD,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAKlB,CAAC;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,OAAO,CAAC,CAAC;AAY9C,eAAO,MAAM,cAAc,6EAQzB,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAcxD,eAAO,MAAM,aAAa,sCAAoC,CAAC;AAC/D,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEtD,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;EAQpB,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AAMlD,eAAO,MAAM,iBAAiB;IAG1B,6DAA6D;;IAK7D,+DAA+D;;IAE/D,kCAAkC;;IAIlC,yDAAyD;;IAEzD;;;;OAIG;;IAIH,4CAA4C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAE5C,0DAA0D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAI1D;;;;;OAKG;;IAEH,kEAAkE;;IAIlE;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuBH,CAAC;AAEL,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
@@ -0,0 +1,215 @@
1
+ // Ikenga skill-action frontmatter schema — the source-of-truth shape for an
2
+ // Atelier skill *action*'s YAML frontmatter (the block between the leading
3
+ // `---` fences of an `actions/*.md` file).
4
+ //
5
+ // The Rust loader in `royalti-io/ikenga` at
6
+ // `src-tauri/src/pkg/skill_actions.rs` mirrors this schema. Field changes MUST
7
+ // be made in lockstep with that Rust struct — same convention as
8
+ // manifest.ts ↔ manifest.rs.
9
+ //
10
+ // Every field below is justified in plans/atelier/06-skill-action-contract.md.
11
+ import { z } from 'zod';
12
+ // ---------------------------------------------------------------------------
13
+ // Identity & taxonomy (G-TAXONOMY)
14
+ // ---------------------------------------------------------------------------
15
+ /**
16
+ * The eight stateful domains plus the one stateless generic skill.
17
+ * `skill-core` is the ONLY legal `depends_on` target (one-way edge, G-04/E-14).
18
+ */
19
+ export const DomainEnum = z.enum([
20
+ 'tasks',
21
+ 'mail',
22
+ 'outbound',
23
+ 'sales',
24
+ 'finance',
25
+ 'content',
26
+ 'research',
27
+ 'strategy',
28
+ 'skill-core',
29
+ ]);
30
+ // ---------------------------------------------------------------------------
31
+ // UX modes (R5, E-11) — exactly five
32
+ // ---------------------------------------------------------------------------
33
+ /**
34
+ * How an action presents itself to the operator.
35
+ * - confirm : preview the planned effect, single yes/no, then run.
36
+ * - silent : run with no prompt (still subject to capability scopes).
37
+ * - form : collect `inputs_schema` from the operator before running.
38
+ * - streaming : run with live token/log streaming surfaced in the dock.
39
+ * - approve : run-THEN-pause on a produced draft; operator approves/edits
40
+ * /rejects the artifact before any external side effect commits
41
+ * (the draft-review gate, E-11).
42
+ */
43
+ export const UxModeEnum = z.enum([
44
+ 'confirm',
45
+ 'silent',
46
+ 'form',
47
+ 'streaming',
48
+ 'approve',
49
+ ]);
50
+ // ---------------------------------------------------------------------------
51
+ // Run binding (R5, G-01) — how the action actually executes
52
+ // ---------------------------------------------------------------------------
53
+ /** chat_prompt: hand a templated prompt to the engine in the dock chat. */
54
+ const ChatPromptRun = z.object({
55
+ kind: z.literal('chat_prompt'),
56
+ // Prompt template; may interpolate validated `inputs` via {{var}}.
57
+ prompt: z.string().min(1),
58
+ });
59
+ /** sidecar: invoke a bundled CLI sidecar by its manifest-declared id. */
60
+ const SidecarRun = z.object({
61
+ kind: z.literal('sidecar'),
62
+ sidecar_id: z.string().min(1),
63
+ // Argv template; entries may interpolate validated `inputs`.
64
+ args: z.array(z.string()).default([]),
65
+ });
66
+ /** mcp_tool: call a tool on a pkg-declared MCP server. */
67
+ const McpToolRun = z.object({
68
+ kind: z.literal('mcp_tool'),
69
+ server_id: z.string().min(1),
70
+ tool: z.string().min(1),
71
+ });
72
+ export const RunBinding = z.discriminatedUnion('kind', [
73
+ ChatPromptRun,
74
+ SidecarRun,
75
+ McpToolRun,
76
+ ]);
77
+ // ---------------------------------------------------------------------------
78
+ // Triggers (R5) — absorbs the 41 legacy crons. An action may be reachable by
79
+ // more than one trigger; `manual` is the implicit default if none declared.
80
+ // ---------------------------------------------------------------------------
81
+ /** Operator-invoked from the command surface / dock. */
82
+ const ManualTrigger = z.object({
83
+ kind: z.literal('manual'),
84
+ });
85
+ /** Time-driven. `cron` is a standard 5-field crontab expression. */
86
+ const ScheduleTrigger = z.object({
87
+ kind: z.literal('schedule'),
88
+ cron: z.string().min(1),
89
+ // Optional human label surfaced in the schedule UI.
90
+ label: z.string().optional(),
91
+ });
92
+ /** Inbound HTTP trigger routed through the shell bridge. */
93
+ const WebhookTrigger = z.object({
94
+ kind: z.literal('webhook'),
95
+ // Stable path segment; the shell namespaces it under the pkg id.
96
+ path: z.string().min(1),
97
+ });
98
+ /** Reacts to an internal shell/domain event by name. */
99
+ const EventTrigger = z.object({
100
+ kind: z.literal('event'),
101
+ event: z.string().min(1),
102
+ });
103
+ export const Trigger = z.discriminatedUnion('kind', [
104
+ ManualTrigger,
105
+ ScheduleTrigger,
106
+ WebhookTrigger,
107
+ EventTrigger,
108
+ ]);
109
+ // ---------------------------------------------------------------------------
110
+ // Capabilities (G-08, R18/R19) — coarse permission grants an action requires.
111
+ // `sqlite` is the stateful-domain seam: state lives in the local ikenga.db,
112
+ // reached through the host dbQuery (SELECT-only) and dbExec (parameterized
113
+ // mutate) bridges. The *table scope* is NOT declared here — it is declared once
114
+ // at the pkg manifest as permissions["sqlite.tables"] and cross-checked at
115
+ // install time against the generated tables.json (the applied ikenga.db STRICT
116
+ // schema). The frontmatter only asserts "this action touches sqlite".
117
+ // ---------------------------------------------------------------------------
118
+ export const CapabilityEnum = z.enum([
119
+ 'sqlite', // host.dbQuery / host.dbExec against ikenga.db (R18/R19)
120
+ 'mcp', // call declared MCP tools
121
+ 'sidecar', // spawn declared sidecars
122
+ 'network', // outbound network
123
+ 'fs', // host filesystem (scoped by manifest)
124
+ 'secrets', // read Stronghold-vaulted secrets
125
+ 'chat', // drive the dock chat engine
126
+ ]);
127
+ // ---------------------------------------------------------------------------
128
+ // Setup lifecycle (D-02, setup-lifecycle decision) — `setup` is an optional,
129
+ // well-known action on EVERY skill. It localises the skill per project by
130
+ // writing ${CLAUDE_PROJECT_DIR}/.atelier/<skill>/manifest.json. It runs IN
131
+ // CHAT, never as a form screen. Two modes:
132
+ // - ai_infer : the agent drafts the instance config from the repo/site, the
133
+ // operator confirms/edits in chat.
134
+ // - interview: the agent asks the operator a scripted set of questions.
135
+ // `template_version` carries a migrate path so an upgraded skill can migrate an
136
+ // older instance file forward.
137
+ // ---------------------------------------------------------------------------
138
+ export const SetupModeEnum = z.enum(['ai_infer', 'interview']);
139
+ export const SetupSpec = z.object({
140
+ mode: SetupModeEnum,
141
+ // Bumped whenever the instance-file shape changes; drives the migrate path.
142
+ template_version: z.number().int().positive(),
143
+ // For ai_infer: where the agent should look to draft the instance config.
144
+ infer_sources: z.array(z.string()).optional(),
145
+ // For interview: ordered question ids the chat flow walks.
146
+ interview_questions: z.array(z.string()).optional(),
147
+ });
148
+ // ---------------------------------------------------------------------------
149
+ // ActionFrontmatter — the locked shape.
150
+ // ---------------------------------------------------------------------------
151
+ export const ActionFrontmatter = z
152
+ .object({
153
+ // --- identity ---
154
+ /** Stable action id, unique within the skill. kebab-case. */
155
+ name: z
156
+ .string()
157
+ .min(1)
158
+ .regex(/^[a-z][a-z0-9-]*$/, 'name must be kebab-case'),
159
+ /** One-line human description shown in the command surface. */
160
+ description: z.string().min(1),
161
+ /** Owning domain (G-TAXONOMY). */
162
+ domain: DomainEnum,
163
+ // --- presentation & io ---
164
+ /** How the action presents to the operator (R5/E-11). */
165
+ ux_mode: UxModeEnum,
166
+ /**
167
+ * JSON-Schema describing the action's inputs. Kept as an opaque object here
168
+ * (validated as JSON-Schema at the destination); `form`/`approve` modes
169
+ * render it, `chat_prompt` runs interpolate validated values from it.
170
+ */
171
+ inputs_schema: z.record(z.string(), z.unknown()).optional(),
172
+ // --- execution ---
173
+ /** What the action actually does (G-01). */
174
+ run: RunBinding,
175
+ /** How the action can be invoked. Empty ⇒ manual-only. */
176
+ triggers: z.array(Trigger).default([]),
177
+ // --- dependency & permissions ---
178
+ /**
179
+ * One-way dependency edge. The ONLY legal target is 'skill-core'
180
+ * (G-04/E-14); any other entry is rejected by the lint in
181
+ * 06-skill-action-contract.md §"depends_on lint". Modeled as a literal
182
+ * array so the schema itself refuses non-skill-core targets.
183
+ */
184
+ depends_on: z.array(z.literal('skill-core')).default([]),
185
+ /** Coarse capability grants this action needs (G-08, R18/R19). */
186
+ requires_capabilities: z.array(CapabilityEnum).default([]),
187
+ // --- lifecycle ---
188
+ /**
189
+ * Present ONLY on the well-known `setup` action. Omitted on every other
190
+ * action. Refined below.
191
+ */
192
+ setup: SetupSpec.optional(),
193
+ })
194
+ .strict()
195
+ .superRefine((fm, ctx) => {
196
+ // The `setup` block is allowed iff this IS the setup action.
197
+ if (fm.name === 'setup' && fm.setup === undefined) {
198
+ ctx.addIssue({
199
+ code: z.ZodIssueCode.custom,
200
+ path: ['setup'],
201
+ message: 'the "setup" action must declare a `setup` block',
202
+ });
203
+ }
204
+ if (fm.name !== 'setup' && fm.setup !== undefined) {
205
+ ctx.addIssue({
206
+ code: z.ZodIssueCode.custom,
207
+ path: ['setup'],
208
+ message: '`setup` block is only valid on the "setup" action',
209
+ });
210
+ }
211
+ // An action that runs SQL must declare the `sqlite` capability so the
212
+ // pkg-manifest sqlite.tables cross-check has something to bind to.
213
+ // (The reverse — declaring sqlite without using it — is allowed/harmless.)
214
+ });
215
+ //# sourceMappingURL=action-frontmatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-frontmatter.js","sourceRoot":"","sources":["../src/action-frontmatter.ts"],"names":[],"mappings":"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"}