@generacy-ai/cockpit 0.6.0 → 0.7.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.
Files changed (58) hide show
  1. package/README.md +148 -0
  2. package/dist/gates/clarification-hash.d.ts +33 -0
  3. package/dist/gates/clarification-hash.d.ts.map +1 -0
  4. package/dist/gates/clarification-hash.js +27 -0
  5. package/dist/gates/clarification-hash.js.map +1 -0
  6. package/dist/gates/fixtures.d.ts +15 -0
  7. package/dist/gates/fixtures.d.ts.map +1 -0
  8. package/dist/gates/fixtures.js +227 -0
  9. package/dist/gates/fixtures.js.map +1 -0
  10. package/dist/gates/gate-id.d.ts +11 -0
  11. package/dist/gates/gate-id.d.ts.map +1 -0
  12. package/dist/gates/gate-id.js +11 -0
  13. package/dist/gates/gate-id.js.map +1 -0
  14. package/dist/gates/generation.d.ts +39 -0
  15. package/dist/gates/generation.d.ts.map +1 -0
  16. package/dist/gates/generation.js +31 -0
  17. package/dist/gates/generation.js.map +1 -0
  18. package/dist/gates/index.d.ts +10 -0
  19. package/dist/gates/index.d.ts.map +1 -0
  20. package/dist/gates/index.js +19 -0
  21. package/dist/gates/index.js.map +1 -0
  22. package/dist/gates/schema.d.ts +192 -0
  23. package/dist/gates/schema.d.ts.map +1 -0
  24. package/dist/gates/schema.js +136 -0
  25. package/dist/gates/schema.js.map +1 -0
  26. package/dist/gates/schemas.d.ts +28 -0
  27. package/dist/gates/schemas.d.ts.map +1 -0
  28. package/dist/gates/schemas.js +21 -0
  29. package/dist/gates/schemas.js.map +1 -0
  30. package/dist/gates/types.d.ts +15 -0
  31. package/dist/gates/types.d.ts.map +1 -0
  32. package/dist/gates/types.js +19 -0
  33. package/dist/gates/types.js.map +1 -0
  34. package/dist/gates/wire-fixtures.d.ts +84 -0
  35. package/dist/gates/wire-fixtures.d.ts.map +1 -0
  36. package/dist/gates/wire-fixtures.js +107 -0
  37. package/dist/gates/wire-fixtures.js.map +1 -0
  38. package/dist/gh/wrapper.d.ts +22 -0
  39. package/dist/gh/wrapper.d.ts.map +1 -1
  40. package/dist/gh/wrapper.js +47 -6
  41. package/dist/gh/wrapper.js.map +1 -1
  42. package/dist/index.d.ts +2 -1
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +22 -0
  45. package/dist/index.js.map +1 -1
  46. package/dist/resolver/parse-epic-body.d.ts +9 -3
  47. package/dist/resolver/parse-epic-body.d.ts.map +1 -1
  48. package/dist/resolver/parse-epic-body.js +59 -5
  49. package/dist/resolver/parse-epic-body.js.map +1 -1
  50. package/dist/resolver/resolve.d.ts.map +1 -1
  51. package/dist/resolver/resolve.js +3 -1
  52. package/dist/resolver/resolve.js.map +1 -1
  53. package/dist/resolver/types.d.ts +19 -0
  54. package/dist/resolver/types.d.ts.map +1 -1
  55. package/dist/state/precedence.d.ts.map +1 -1
  56. package/dist/state/precedence.js +16 -0
  57. package/dist/state/precedence.js.map +1 -1
  58. package/package.json +2 -2
@@ -0,0 +1,192 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Canonical cockpit gate wire schemas — the cluster (generacy) side of the
4
+ * frozen contract in tetrad-development/docs/cockpit-remote-gates-plan.md
5
+ * § "Wire contracts" and generacy-cloud/specs/843-part-cockpit-remote-gates/
6
+ * contracts/gates-wire.md (Shapes 1/2/3).
7
+ *
8
+ * The cloud is the authoritative RECEIVER; these schemas MUST stay
9
+ * field-for-field compatible with generacy-cloud:
10
+ * - services/api/src/services/relay/message-handler.ts
11
+ * gateOpenPayloadSchema / gateOutcomePayloadSchema
12
+ * - packages/db/src/collections/cockpit-gates.ts
13
+ * cockpitGateTypeEnum / cockpitGateOptionSchema / cockpitGateAnswerSchema
14
+ *
15
+ * Wire values are JSON, so all timestamps are ISO-8601 strings here; the cloud
16
+ * ingests them with `z.coerce.date()`.
17
+ */
18
+ export declare const GateTypeSchema: z.ZodEnum<["clarification", "artifact-review", "implementation-review", "manual-validation", "escalation", "phase-queue", "filing", "scope-drained"]>;
19
+ export type GateType = z.infer<typeof GateTypeSchema>;
20
+ export declare const GateOptionSchema: z.ZodObject<{
21
+ id: z.ZodString;
22
+ label: z.ZodString;
23
+ description: z.ZodOptional<z.ZodString>;
24
+ recommended: z.ZodOptional<z.ZodBoolean>;
25
+ }, "strip", z.ZodTypeAny, {
26
+ id: string;
27
+ label: string;
28
+ description?: string | undefined;
29
+ recommended?: boolean | undefined;
30
+ }, {
31
+ id: string;
32
+ label: string;
33
+ description?: string | undefined;
34
+ recommended?: boolean | undefined;
35
+ }>;
36
+ export type GateOption = z.infer<typeof GateOptionSchema>;
37
+ export declare const GateOpenSchema: z.ZodObject<{
38
+ type: z.ZodLiteral<"gate-open">;
39
+ gateId: z.ZodString;
40
+ gateKey: z.ZodString;
41
+ gateType: z.ZodEnum<["clarification", "artifact-review", "implementation-review", "manual-validation", "escalation", "phase-queue", "filing", "scope-drained"]>;
42
+ epicRef: z.ZodString;
43
+ issueRef: z.ZodString;
44
+ issueTitle: z.ZodString;
45
+ issueUrl: z.ZodString;
46
+ branch: z.ZodOptional<z.ZodString>;
47
+ prNumber: z.ZodOptional<z.ZodNumber>;
48
+ title: z.ZodString;
49
+ body: z.ZodString;
50
+ options: z.ZodArray<z.ZodObject<{
51
+ id: z.ZodString;
52
+ label: z.ZodString;
53
+ description: z.ZodOptional<z.ZodString>;
54
+ recommended: z.ZodOptional<z.ZodBoolean>;
55
+ }, "strip", z.ZodTypeAny, {
56
+ id: string;
57
+ label: string;
58
+ description?: string | undefined;
59
+ recommended?: boolean | undefined;
60
+ }, {
61
+ id: string;
62
+ label: string;
63
+ description?: string | undefined;
64
+ recommended?: boolean | undefined;
65
+ }>, "many">;
66
+ allowFreeText: z.ZodBoolean;
67
+ sessionId: z.ZodString;
68
+ askedAt: z.ZodString;
69
+ frameId: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodEffects<z.ZodLiteral<"">, undefined, "">, z.ZodEffects<z.ZodNull, undefined, null>]>>;
70
+ }, "strip", z.ZodTypeAny, {
71
+ options: {
72
+ id: string;
73
+ label: string;
74
+ description?: string | undefined;
75
+ recommended?: boolean | undefined;
76
+ }[];
77
+ type: "gate-open";
78
+ title: string;
79
+ body: string;
80
+ gateId: string;
81
+ gateKey: string;
82
+ gateType: "clarification" | "artifact-review" | "implementation-review" | "manual-validation" | "escalation" | "phase-queue" | "filing" | "scope-drained";
83
+ epicRef: string;
84
+ issueRef: string;
85
+ issueTitle: string;
86
+ issueUrl: string;
87
+ allowFreeText: boolean;
88
+ sessionId: string;
89
+ askedAt: string;
90
+ prNumber?: number | undefined;
91
+ branch?: string | undefined;
92
+ frameId?: string | undefined;
93
+ }, {
94
+ options: {
95
+ id: string;
96
+ label: string;
97
+ description?: string | undefined;
98
+ recommended?: boolean | undefined;
99
+ }[];
100
+ type: "gate-open";
101
+ title: string;
102
+ body: string;
103
+ gateId: string;
104
+ gateKey: string;
105
+ gateType: "clarification" | "artifact-review" | "implementation-review" | "manual-validation" | "escalation" | "phase-queue" | "filing" | "scope-drained";
106
+ epicRef: string;
107
+ issueRef: string;
108
+ issueTitle: string;
109
+ issueUrl: string;
110
+ allowFreeText: boolean;
111
+ sessionId: string;
112
+ askedAt: string;
113
+ prNumber?: number | undefined;
114
+ branch?: string | undefined;
115
+ frameId?: string | null | undefined;
116
+ }>;
117
+ export type GateOpen = z.infer<typeof GateOpenSchema>;
118
+ export declare const GateOutcomeSchema: z.ZodObject<{
119
+ type: z.ZodLiteral<"gate-outcome">;
120
+ gateId: z.ZodString;
121
+ outcome: z.ZodEnum<["applied", "superseded", "failed"]>;
122
+ detail: z.ZodOptional<z.ZodString>;
123
+ at: z.ZodString;
124
+ frameId: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodEffects<z.ZodLiteral<"">, undefined, "">, z.ZodEffects<z.ZodNull, undefined, null>]>>;
125
+ }, "strip", z.ZodTypeAny, {
126
+ type: "gate-outcome";
127
+ at: string;
128
+ outcome: "applied" | "superseded" | "failed";
129
+ gateId: string;
130
+ frameId?: string | undefined;
131
+ detail?: string | undefined;
132
+ }, {
133
+ type: "gate-outcome";
134
+ at: string;
135
+ outcome: "applied" | "superseded" | "failed";
136
+ gateId: string;
137
+ frameId?: string | null | undefined;
138
+ detail?: string | undefined;
139
+ }>;
140
+ export type GateOutcome = z.infer<typeof GateOutcomeSchema>;
141
+ export declare const GateAnswerSchema: z.ZodObject<{
142
+ type: z.ZodLiteral<"gate-answer">;
143
+ gateId: z.ZodString;
144
+ gateKey: z.ZodString;
145
+ optionId: z.ZodNullable<z.ZodString>;
146
+ freeText: z.ZodNullable<z.ZodString>;
147
+ actor: z.ZodObject<{
148
+ userId: z.ZodString;
149
+ email: z.ZodNullable<z.ZodString>;
150
+ displayName: z.ZodNullable<z.ZodString>;
151
+ }, "strip", z.ZodTypeAny, {
152
+ userId: string;
153
+ email: string | null;
154
+ displayName: string | null;
155
+ }, {
156
+ userId: string;
157
+ email: string | null;
158
+ displayName: string | null;
159
+ }>;
160
+ answeredAt: z.ZodString;
161
+ deliveryId: z.ZodString;
162
+ }, "strip", z.ZodTypeAny, {
163
+ type: "gate-answer";
164
+ gateId: string;
165
+ gateKey: string;
166
+ optionId: string | null;
167
+ freeText: string | null;
168
+ actor: {
169
+ userId: string;
170
+ email: string | null;
171
+ displayName: string | null;
172
+ };
173
+ answeredAt: string;
174
+ deliveryId: string;
175
+ }, {
176
+ type: "gate-answer";
177
+ gateId: string;
178
+ gateKey: string;
179
+ optionId: string | null;
180
+ freeText: string | null;
181
+ actor: {
182
+ userId: string;
183
+ email: string | null;
184
+ displayName: string | null;
185
+ };
186
+ answeredAt: string;
187
+ deliveryId: string;
188
+ }>;
189
+ export type GateAnswer = z.infer<typeof GateAnswerSchema>;
190
+ export declare function deriveGateKey(issueRef: string, gateType: GateType, generation: string | number, runId?: string): string;
191
+ export declare function deriveGateId(gateKey: string): string;
192
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/gates/schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;GAeG;AAKH,eAAO,MAAM,cAAc,uJASzB,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAKtD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;EAK3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAQ1D,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BzB,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAMtD,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;EAc5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAQ5D,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAa3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAa1D,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,MAAM,GAAG,MAAM,EAC3B,KAAK,CAAC,EAAE,MAAM,GACb,MAAM,CAGR;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpD"}
@@ -0,0 +1,136 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { z } from 'zod';
3
+ /**
4
+ * Canonical cockpit gate wire schemas — the cluster (generacy) side of the
5
+ * frozen contract in tetrad-development/docs/cockpit-remote-gates-plan.md
6
+ * § "Wire contracts" and generacy-cloud/specs/843-part-cockpit-remote-gates/
7
+ * contracts/gates-wire.md (Shapes 1/2/3).
8
+ *
9
+ * The cloud is the authoritative RECEIVER; these schemas MUST stay
10
+ * field-for-field compatible with generacy-cloud:
11
+ * - services/api/src/services/relay/message-handler.ts
12
+ * gateOpenPayloadSchema / gateOutcomePayloadSchema
13
+ * - packages/db/src/collections/cockpit-gates.ts
14
+ * cockpitGateTypeEnum / cockpitGateOptionSchema / cockpitGateAnswerSchema
15
+ *
16
+ * Wire values are JSON, so all timestamps are ISO-8601 strings here; the cloud
17
+ * ingests them with `z.coerce.date()`.
18
+ */
19
+ // ---------------------------------------------------------------------------
20
+ // Gate type enum — mirrors cloud `cockpitGateTypeEnum` exactly (8 values, order preserved).
21
+ // ---------------------------------------------------------------------------
22
+ export const GateTypeSchema = z.enum([
23
+ 'clarification',
24
+ 'artifact-review',
25
+ 'implementation-review',
26
+ 'manual-validation',
27
+ 'escalation',
28
+ 'phase-queue',
29
+ 'filing',
30
+ 'scope-drained',
31
+ ]);
32
+ // ---------------------------------------------------------------------------
33
+ // Option — mirrors cloud `cockpitGateOptionSchema`.
34
+ // ---------------------------------------------------------------------------
35
+ export const GateOptionSchema = z.object({
36
+ id: z.string(),
37
+ label: z.string(),
38
+ description: z.string().optional(),
39
+ recommended: z.boolean().optional(),
40
+ });
41
+ // ---------------------------------------------------------------------------
42
+ // Shape 1 — gate-open (cluster → cloud, up-path).
43
+ // Mirrors cloud `gateOpenPayloadSchema` (message-handler.ts).
44
+ // Flat, type-literal 'gate-open'. gateId/gateKey are DERIVED by the MCP tool
45
+ // (cockpit_gate_open) — the plugin/LLM never hand-builds a sha256.
46
+ // ---------------------------------------------------------------------------
47
+ export const GateOpenSchema = z.object({
48
+ type: z.literal('gate-open'),
49
+ gateId: z.string().length(24),
50
+ gateKey: z.string().min(1),
51
+ gateType: GateTypeSchema,
52
+ epicRef: z.string().min(1),
53
+ issueRef: z.string().min(1),
54
+ issueTitle: z.string(),
55
+ issueUrl: z.string().url(),
56
+ branch: z.string().optional(),
57
+ prNumber: z.number().int().positive().optional(),
58
+ title: z.string(),
59
+ body: z.string(),
60
+ options: z.array(GateOptionSchema).min(0).max(20),
61
+ allowFreeText: z.boolean(),
62
+ sessionId: z.string().min(1),
63
+ askedAt: z.string().datetime(),
64
+ // #1066 — preserved for cloud per-frame reply correlation. Cloud reads at
65
+ // services/api/src/services/relay/message-handler.ts:804 (raw `data.frameId`,
66
+ // upstream of the frozen payload schema). Three encodings of "no correlation"
67
+ // are normalized to absent: omitted, `""`, and `null`. `null` matches the
68
+ // cloud's own vocabulary (see `packages/cluster-relay/src/messages.ts:154`
69
+ // + `:387` — reply `frameId: string | null`), so a caller doing
70
+ // `?? null` round-trips without a 400.
71
+ frameId: z
72
+ .union([
73
+ z.string().min(1),
74
+ z.literal('').transform(() => undefined),
75
+ z.null().transform(() => undefined),
76
+ ])
77
+ .optional(),
78
+ });
79
+ // ---------------------------------------------------------------------------
80
+ // Shape 2 — gate-outcome (cluster → cloud, up-path). THE ACK.
81
+ // Replaces the invented GateAckSchema. Mirrors cloud `gateOutcomePayloadSchema`.
82
+ // ---------------------------------------------------------------------------
83
+ export const GateOutcomeSchema = z.object({
84
+ type: z.literal('gate-outcome'),
85
+ gateId: z.string().length(24),
86
+ outcome: z.enum(['applied', 'superseded', 'failed']),
87
+ detail: z.string().optional(),
88
+ at: z.string().datetime(),
89
+ // Same shape and rationale as GateOpenSchema.frameId — #1066.
90
+ frameId: z
91
+ .union([
92
+ z.string().min(1),
93
+ z.literal('').transform(() => undefined),
94
+ z.null().transform(() => undefined),
95
+ ])
96
+ .optional(),
97
+ });
98
+ // ---------------------------------------------------------------------------
99
+ // Shape 3 — gate-answer (cloud → cluster, down-path).
100
+ // Consumed by the orchestrator `POST /cockpit/answers` route + doorbell parser.
101
+ // Mirrors cloud stored `cockpitGateAnswerSchema` (nullable optionId/freeText and
102
+ // nullable actor.email/displayName) plus the wire-only type/gateId/gateKey.
103
+ // ---------------------------------------------------------------------------
104
+ export const GateAnswerSchema = z.object({
105
+ type: z.literal('gate-answer'),
106
+ gateId: z.string().length(24),
107
+ gateKey: z.string().min(1),
108
+ optionId: z.string().nullable(), // null on pure free-text
109
+ freeText: z.string().nullable(),
110
+ actor: z.object({
111
+ userId: z.string(),
112
+ email: z.string().email().nullable(),
113
+ displayName: z.string().nullable(),
114
+ }),
115
+ answeredAt: z.string().datetime(),
116
+ deliveryId: z.string(), // unique per delivery attempt; cluster dedups on this
117
+ });
118
+ // ---------------------------------------------------------------------------
119
+ // Gate identity derivation.
120
+ // gateKey = "<owner>/<repo>#<issue>:<gateType>:<generation>[:<runId>]"
121
+ // = `${issueRef}:${gateType}:${generation}[:${runId}]`
122
+ // gateId = sha256(gateKey) hex, first 24 chars.
123
+ // `generation` is gateType-specific (batch id, head SHA, phase number, drain
124
+ // counter, …); coerced to string so numeric discriminators (phase 2) are stable.
125
+ // `runId` (#1053) is the optional per-run discriminator that guarantees a
126
+ // fresh gateId across independent runs of the same natural gate. When absent
127
+ // the output is byte-for-byte compatible with the pre-#1053 shape.
128
+ // ---------------------------------------------------------------------------
129
+ export function deriveGateKey(issueRef, gateType, generation, runId) {
130
+ const base = `${issueRef}:${gateType}:${String(generation)}`;
131
+ return runId === undefined ? base : `${base}:${runId}`;
132
+ }
133
+ export function deriveGateId(gateKey) {
134
+ return createHash('sha256').update(gateKey, 'utf8').digest('hex').slice(0, 24);
135
+ }
136
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/gates/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Object form of an issue reference. This is a cluster-local convenience shape
4
+ * used by the gate-generation helpers (`deriveScopeDrainedGeneration`) and by
5
+ * MCP callers before they format it to the flat `owner/repo#N` wire string.
6
+ *
7
+ * The WIRE shapes in `./schema.ts` carry `issueRef` / `epicRef` as plain
8
+ * strings (Shapes 1/3, mirroring the cloud); this object shape never crosses
9
+ * the wire. Format it with {@link issueRefToString} before calling
10
+ * `deriveGateKey`.
11
+ */
12
+ export declare const IssueRefSchema: z.ZodObject<{
13
+ owner: z.ZodString;
14
+ repo: z.ZodString;
15
+ number: z.ZodNumber;
16
+ }, "strip", z.ZodTypeAny, {
17
+ number: number;
18
+ owner: string;
19
+ repo: string;
20
+ }, {
21
+ number: number;
22
+ owner: string;
23
+ repo: string;
24
+ }>;
25
+ export type IssueRef = z.infer<typeof IssueRefSchema>;
26
+ /** Format an object {@link IssueRef} to the canonical `owner/repo#N` wire ref. */
27
+ export declare function issueRefToString(ref: IssueRef): string;
28
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/gates/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;EAIzB,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,kFAAkF;AAClF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,CAEtD"}
@@ -0,0 +1,21 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Object form of an issue reference. This is a cluster-local convenience shape
4
+ * used by the gate-generation helpers (`deriveScopeDrainedGeneration`) and by
5
+ * MCP callers before they format it to the flat `owner/repo#N` wire string.
6
+ *
7
+ * The WIRE shapes in `./schema.ts` carry `issueRef` / `epicRef` as plain
8
+ * strings (Shapes 1/3, mirroring the cloud); this object shape never crosses
9
+ * the wire. Format it with {@link issueRefToString} before calling
10
+ * `deriveGateKey`.
11
+ */
12
+ export const IssueRefSchema = z.object({
13
+ owner: z.string().min(1).regex(/^[a-zA-Z0-9-_.]+$/),
14
+ repo: z.string().min(1).regex(/^[a-zA-Z0-9-_.]+$/),
15
+ number: z.number().int().positive(),
16
+ });
17
+ /** Format an object {@link IssueRef} to the canonical `owner/repo#N` wire ref. */
18
+ export function issueRefToString(ref) {
19
+ return `${ref.owner}/${ref.repo}#${ref.number}`;
20
+ }
21
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/gates/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC;IACnD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC;IAClD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;CACpC,CAAC,CAAC;AAGH,kFAAkF;AAClF,MAAM,UAAU,gBAAgB,CAAC,GAAa;IAC5C,OAAO,GAAG,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;AAClD,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Artifact-review kinds — a cluster-local enumeration used only by the
4
+ * `deriveArtifactReviewGeneration` helper (generation.ts) to build the
5
+ * `<kind>:<headSha>` discriminator. It is NOT a wire type: the gate-open
6
+ * record carries `gateType: 'artifact-review'`, and the kind is folded into
7
+ * `gateKey`'s generation slot.
8
+ *
9
+ * The wire enum (`GateTypeSchema`), the gate option/answer/outcome shapes and
10
+ * the gateKey/gateId derivation all live in `./schema.ts` — the single source.
11
+ */
12
+ export declare const ARTIFACT_REVIEW_KINDS: readonly ["spec-review", "plan-review", "tasks-review", "clarification-review"];
13
+ export declare const ArtifactReviewKindSchema: z.ZodEnum<["spec-review", "plan-review", "tasks-review", "clarification-review"]>;
14
+ export type ArtifactReviewKind = z.infer<typeof ArtifactReviewKindSchema>;
15
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/gates/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,iFAKxB,CAAC;AAEX,eAAO,MAAM,wBAAwB,mFAAgC,CAAC;AACtE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Artifact-review kinds — a cluster-local enumeration used only by the
4
+ * `deriveArtifactReviewGeneration` helper (generation.ts) to build the
5
+ * `<kind>:<headSha>` discriminator. It is NOT a wire type: the gate-open
6
+ * record carries `gateType: 'artifact-review'`, and the kind is folded into
7
+ * `gateKey`'s generation slot.
8
+ *
9
+ * The wire enum (`GateTypeSchema`), the gate option/answer/outcome shapes and
10
+ * the gateKey/gateId derivation all live in `./schema.ts` — the single source.
11
+ */
12
+ export const ARTIFACT_REVIEW_KINDS = [
13
+ 'spec-review',
14
+ 'plan-review',
15
+ 'tasks-review',
16
+ 'clarification-review',
17
+ ];
18
+ export const ArtifactReviewKindSchema = z.enum(ARTIFACT_REVIEW_KINDS);
19
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/gates/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,aAAa;IACb,aAAa;IACb,cAAc;IACd,sBAAsB;CACd,CAAC;AAEX,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Wire-envelope fixture builders for the cluster-side transport contracts
3
+ * (#1024). These build the exact JSON frames that cross the cluster-side wire,
4
+ * all validated against the canonical schemas in `./schema.ts`:
5
+ *
6
+ * - `gateOpenFixture()` → body of `POST /cockpit/gates` (`GateOpenSchema`, Shape 1)
7
+ * - `gateOutcomeFixture()` → body of `POST /cockpit/gates/:id/ack` (`GateOutcomeSchema`, Shape 2 — THE ACK)
8
+ * - `answerLineFixture()` → body of `POST /cockpit/answers` AND the NDJSON
9
+ * line the doorbell tails (`GateAnswerSchema`, Shape 3)
10
+ *
11
+ * The #1024 integration harness single-sources every wire body through these
12
+ * builders (FR-009 / SC-004) so a drift in the transport shape fails the
13
+ * harness in one place rather than silently passing an inline literal.
14
+ *
15
+ * NB: the frozen frames are FLAT with a `type` discriminator ('gate-open' |
16
+ * 'gate-outcome' | 'gate-answer'); there is no `kind`, no `scope` wrapper and no
17
+ * top-level `generation` (generation is folded into `gateKey`). gateId/gateKey
18
+ * are DERIVED, so the default frame carries a real 24-hex gateId.
19
+ */
20
+ import { type GateAnswer, type GateOpen, type GateOutcome } from './schema.js';
21
+ /** Epic/issue scope the harness binds the doorbell to. The wire carries the ref
22
+ * as the flat `owner/repo#N` string ({@link DEFAULT_WIRE_EPIC_REF}); this object
23
+ * form is a convenience for callers that need the parts. */
24
+ export interface WireScope {
25
+ owner: string;
26
+ repo: string;
27
+ number: number;
28
+ }
29
+ export declare const DEFAULT_WIRE_SCOPE: WireScope;
30
+ /** `owner/repo#number` for the default scope — the epic ref the harness binds
31
+ * the doorbell to. Kept in lockstep with {@link DEFAULT_WIRE_SCOPE}. */
32
+ export declare const DEFAULT_WIRE_EPIC_REF: string;
33
+ export interface GateOpenFixtureOverrides {
34
+ gateId?: string;
35
+ gateKey?: string;
36
+ gateType?: GateOpen['gateType'];
37
+ epicRef?: string;
38
+ issueRef?: string;
39
+ issueTitle?: string;
40
+ issueUrl?: string;
41
+ title?: string;
42
+ body?: string;
43
+ options?: GateOpen['options'];
44
+ allowFreeText?: boolean;
45
+ sessionId?: string;
46
+ askedAt?: string;
47
+ frameId?: string;
48
+ }
49
+ /**
50
+ * Build a `POST /cockpit/gates` body (Shape 1). Validated against
51
+ * `GateOpenSchema` before return so a builder that drifts from the transport
52
+ * contract throws at the call site.
53
+ */
54
+ export declare function gateOpenFixture(overrides?: GateOpenFixtureOverrides): GateOpen;
55
+ export interface GateOutcomeFixtureOverrides {
56
+ gateId?: string;
57
+ outcome?: GateOutcome['outcome'];
58
+ detail?: string;
59
+ at?: string;
60
+ frameId?: string;
61
+ }
62
+ /**
63
+ * Build a `POST /cockpit/gates/:id/ack` body (Shape 2, the gate-outcome ACK).
64
+ * The route injects the path `:id` as `gateId`; the fixture carries a matching
65
+ * `gateId` so a direct POST with `body.gateId === :id` passes any equality guard.
66
+ */
67
+ export declare function gateOutcomeFixture(overrides?: GateOutcomeFixtureOverrides): GateOutcome;
68
+ export interface AnswerLineFixtureOverrides {
69
+ deliveryId?: string;
70
+ gateId?: string;
71
+ gateKey?: string;
72
+ optionId?: string | null;
73
+ freeText?: string | null;
74
+ actor?: GateAnswer['actor'];
75
+ answeredAt?: string;
76
+ }
77
+ /**
78
+ * Build a gate-answer line (Shape 3, down-path). This is the single wire shape
79
+ * that flows peer/cloud → `POST /cockpit/answers` → answers file → doorbell
80
+ * tail (FR-005) — the seam the #1024 harness exists to pin. Validated against
81
+ * `GateAnswerSchema`.
82
+ */
83
+ export declare function answerLineFixture(overrides?: AnswerLineFixtureOverrides): GateAnswer;
84
+ //# sourceMappingURL=wire-fixtures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire-fixtures.d.ts","sourceRoot":"","sources":["../../src/gates/wire-fixtures.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAML,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,WAAW,EACjB,MAAM,aAAa,CAAC;AAGrB;;6DAE6D;AAC7D,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,kBAAkB,EAAE,SAIhC,CAAC;AAEF;yEACyE;AACzE,eAAO,MAAM,qBAAqB,QAAmD,CAAC;AAiBtF,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC9B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,SAAS,GAAE,wBAA6B,GAAG,QAAQ,CAwBlF;AAED,MAAM,WAAW,2BAA2B;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,GAAE,2BAAgC,GAAG,WAAW,CAU3F;AAED,MAAM,WAAW,0BAA0B;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,GAAE,0BAA+B,GAAG,UAAU,CAYxF"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Wire-envelope fixture builders for the cluster-side transport contracts
3
+ * (#1024). These build the exact JSON frames that cross the cluster-side wire,
4
+ * all validated against the canonical schemas in `./schema.ts`:
5
+ *
6
+ * - `gateOpenFixture()` → body of `POST /cockpit/gates` (`GateOpenSchema`, Shape 1)
7
+ * - `gateOutcomeFixture()` → body of `POST /cockpit/gates/:id/ack` (`GateOutcomeSchema`, Shape 2 — THE ACK)
8
+ * - `answerLineFixture()` → body of `POST /cockpit/answers` AND the NDJSON
9
+ * line the doorbell tails (`GateAnswerSchema`, Shape 3)
10
+ *
11
+ * The #1024 integration harness single-sources every wire body through these
12
+ * builders (FR-009 / SC-004) so a drift in the transport shape fails the
13
+ * harness in one place rather than silently passing an inline literal.
14
+ *
15
+ * NB: the frozen frames are FLAT with a `type` discriminator ('gate-open' |
16
+ * 'gate-outcome' | 'gate-answer'); there is no `kind`, no `scope` wrapper and no
17
+ * top-level `generation` (generation is folded into `gateKey`). gateId/gateKey
18
+ * are DERIVED, so the default frame carries a real 24-hex gateId.
19
+ */
20
+ import { GateAnswerSchema, GateOpenSchema, GateOutcomeSchema, deriveGateId, deriveGateKey, } from './schema.js';
21
+ import { issueRefToString } from './schemas.js';
22
+ export const DEFAULT_WIRE_SCOPE = {
23
+ owner: 'generacy-ai',
24
+ repo: 'generacy',
25
+ number: 1024,
26
+ };
27
+ /** `owner/repo#number` for the default scope — the epic ref the harness binds
28
+ * the doorbell to. Kept in lockstep with {@link DEFAULT_WIRE_SCOPE}. */
29
+ export const DEFAULT_WIRE_EPIC_REF = issueRefToString(DEFAULT_WIRE_SCOPE);
30
+ const DEFAULT_GATE_TYPE = 'phase-queue';
31
+ const DEFAULT_GENERATION = '2';
32
+ const DEFAULT_GATE_KEY = deriveGateKey(DEFAULT_WIRE_EPIC_REF, DEFAULT_GATE_TYPE, DEFAULT_GENERATION);
33
+ const DEFAULT_GATE_ID = deriveGateId(DEFAULT_GATE_KEY);
34
+ const DEFAULT_SESSION_ID = 'sess-1024-default';
35
+ const DEFAULT_ASKED_AT = '2026-07-21T12:00:00.000Z';
36
+ const DEFAULT_ANSWERED_AT = '2026-07-21T12:05:00.000Z';
37
+ const DEFAULT_OUTCOME_AT = '2026-07-21T12:05:01.000Z';
38
+ const DEFAULT_ACTOR = {
39
+ userId: 'user-1024',
40
+ email: 'operator@example.com',
41
+ displayName: 'Operator One',
42
+ };
43
+ /**
44
+ * Build a `POST /cockpit/gates` body (Shape 1). Validated against
45
+ * `GateOpenSchema` before return so a builder that drifts from the transport
46
+ * contract throws at the call site.
47
+ */
48
+ export function gateOpenFixture(overrides = {}) {
49
+ const body = {
50
+ type: 'gate-open',
51
+ gateId: overrides.gateId ?? DEFAULT_GATE_ID,
52
+ gateKey: overrides.gateKey ?? DEFAULT_GATE_KEY,
53
+ gateType: overrides.gateType ?? DEFAULT_GATE_TYPE,
54
+ epicRef: overrides.epicRef ?? DEFAULT_WIRE_EPIC_REF,
55
+ issueRef: overrides.issueRef ?? DEFAULT_WIRE_EPIC_REF,
56
+ issueTitle: overrides.issueTitle ?? 'Phase 2: cockpit remote gates',
57
+ issueUrl: overrides.issueUrl ??
58
+ `https://github.com/${DEFAULT_WIRE_SCOPE.owner}/${DEFAULT_WIRE_SCOPE.repo}/issues/${DEFAULT_WIRE_SCOPE.number}`,
59
+ title: overrides.title ?? 'Queue phase 2?',
60
+ body: overrides.body ?? 'Proceed with the next phase?',
61
+ options: overrides.options ?? [
62
+ { id: 'proceed', label: 'Proceed', recommended: true },
63
+ { id: 'hold', label: 'Hold' },
64
+ ],
65
+ allowFreeText: overrides.allowFreeText ?? true,
66
+ sessionId: overrides.sessionId ?? DEFAULT_SESSION_ID,
67
+ askedAt: overrides.askedAt ?? DEFAULT_ASKED_AT,
68
+ ...(overrides.frameId !== undefined ? { frameId: overrides.frameId } : {}),
69
+ };
70
+ return GateOpenSchema.parse(body);
71
+ }
72
+ /**
73
+ * Build a `POST /cockpit/gates/:id/ack` body (Shape 2, the gate-outcome ACK).
74
+ * The route injects the path `:id` as `gateId`; the fixture carries a matching
75
+ * `gateId` so a direct POST with `body.gateId === :id` passes any equality guard.
76
+ */
77
+ export function gateOutcomeFixture(overrides = {}) {
78
+ const body = {
79
+ type: 'gate-outcome',
80
+ gateId: overrides.gateId ?? DEFAULT_GATE_ID,
81
+ outcome: overrides.outcome ?? 'applied',
82
+ ...(overrides.detail !== undefined ? { detail: overrides.detail } : {}),
83
+ at: overrides.at ?? DEFAULT_OUTCOME_AT,
84
+ ...(overrides.frameId !== undefined ? { frameId: overrides.frameId } : {}),
85
+ };
86
+ return GateOutcomeSchema.parse(body);
87
+ }
88
+ /**
89
+ * Build a gate-answer line (Shape 3, down-path). This is the single wire shape
90
+ * that flows peer/cloud → `POST /cockpit/answers` → answers file → doorbell
91
+ * tail (FR-005) — the seam the #1024 harness exists to pin. Validated against
92
+ * `GateAnswerSchema`.
93
+ */
94
+ export function answerLineFixture(overrides = {}) {
95
+ const body = {
96
+ type: 'gate-answer',
97
+ gateId: overrides.gateId ?? DEFAULT_GATE_ID,
98
+ gateKey: overrides.gateKey ?? DEFAULT_GATE_KEY,
99
+ optionId: overrides.optionId !== undefined ? overrides.optionId : 'proceed',
100
+ freeText: overrides.freeText !== undefined ? overrides.freeText : null,
101
+ actor: overrides.actor ?? { ...DEFAULT_ACTOR },
102
+ answeredAt: overrides.answeredAt ?? DEFAULT_ANSWERED_AT,
103
+ deliveryId: overrides.deliveryId ?? 'dlv_1024_default',
104
+ };
105
+ return GateAnswerSchema.parse(body);
106
+ }
107
+ //# sourceMappingURL=wire-fixtures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire-fixtures.js","sourceRoot":"","sources":["../../src/gates/wire-fixtures.ts"],"names":[],"mappings":"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"}