wicked-crew 0.5.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 (167) hide show
  1. package/dist/api/audit.d.ts +70 -0
  2. package/dist/api/audit.d.ts.map +1 -0
  3. package/dist/api/audit.js +131 -0
  4. package/dist/api/audit.js.map +1 -0
  5. package/dist/api/auth.d.ts +192 -0
  6. package/dist/api/auth.d.ts.map +1 -0
  7. package/dist/api/auth.js +515 -0
  8. package/dist/api/auth.js.map +1 -0
  9. package/dist/api/gate-cache.d.ts +8 -0
  10. package/dist/api/gate-cache.d.ts.map +1 -1
  11. package/dist/api/gate-cache.js +10 -0
  12. package/dist/api/gate-cache.js.map +1 -1
  13. package/dist/api/guidance-index.d.ts +39 -0
  14. package/dist/api/guidance-index.d.ts.map +1 -0
  15. package/dist/api/guidance-index.js +67 -0
  16. package/dist/api/guidance-index.js.map +1 -0
  17. package/dist/api/open-path.d.ts +34 -0
  18. package/dist/api/open-path.d.ts.map +1 -0
  19. package/dist/api/open-path.js +101 -0
  20. package/dist/api/open-path.js.map +1 -0
  21. package/dist/api/retry-index.d.ts +30 -0
  22. package/dist/api/retry-index.d.ts.map +1 -0
  23. package/dist/api/retry-index.js +45 -0
  24. package/dist/api/retry-index.js.map +1 -0
  25. package/dist/api/routes.d.ts +164 -1
  26. package/dist/api/routes.d.ts.map +1 -1
  27. package/dist/api/routes.js +769 -21
  28. package/dist/api/routes.js.map +1 -1
  29. package/dist/api/run-files.d.ts +63 -0
  30. package/dist/api/run-files.d.ts.map +1 -0
  31. package/dist/api/run-files.js +271 -0
  32. package/dist/api/run-files.js.map +1 -0
  33. package/dist/api/seat-health.d.ts +55 -0
  34. package/dist/api/seat-health.d.ts.map +1 -0
  35. package/dist/api/seat-health.js +273 -0
  36. package/dist/api/seat-health.js.map +1 -0
  37. package/dist/api/seat-signin.d.ts +27 -0
  38. package/dist/api/seat-signin.d.ts.map +1 -0
  39. package/dist/api/seat-signin.js +143 -0
  40. package/dist/api/seat-signin.js.map +1 -0
  41. package/dist/api/server.d.ts +190 -3
  42. package/dist/api/server.d.ts.map +1 -1
  43. package/dist/api/server.js +365 -11
  44. package/dist/api/server.js.map +1 -1
  45. package/dist/api/stall-watchdog.d.ts +62 -0
  46. package/dist/api/stall-watchdog.d.ts.map +1 -0
  47. package/dist/api/stall-watchdog.js +138 -0
  48. package/dist/api/stall-watchdog.js.map +1 -0
  49. package/dist/cli/index.js +171 -12
  50. package/dist/cli/index.js.map +1 -1
  51. package/dist/cli/mcp.d.ts +14 -0
  52. package/dist/cli/mcp.d.ts.map +1 -0
  53. package/dist/cli/mcp.js +119 -0
  54. package/dist/cli/mcp.js.map +1 -0
  55. package/dist/core/adapter.d.ts +87 -10
  56. package/dist/core/adapter.d.ts.map +1 -1
  57. package/dist/core/adapter.js +347 -28
  58. package/dist/core/adapter.js.map +1 -1
  59. package/dist/core/bridge-reaper.d.ts +134 -0
  60. package/dist/core/bridge-reaper.d.ts.map +1 -0
  61. package/dist/core/bridge-reaper.js +286 -0
  62. package/dist/core/bridge-reaper.js.map +1 -0
  63. package/dist/core/deliver.d.ts +118 -0
  64. package/dist/core/deliver.d.ts.map +1 -0
  65. package/dist/core/deliver.js +241 -0
  66. package/dist/core/deliver.js.map +1 -0
  67. package/dist/core/deliverable-floor.d.ts +103 -0
  68. package/dist/core/deliverable-floor.d.ts.map +1 -0
  69. package/dist/core/deliverable-floor.js +173 -0
  70. package/dist/core/deliverable-floor.js.map +1 -0
  71. package/dist/core/exec.d.ts +2 -0
  72. package/dist/core/exec.d.ts.map +1 -1
  73. package/dist/core/exec.js.map +1 -1
  74. package/dist/core/types.d.ts +92 -352
  75. package/dist/core/types.d.ts.map +1 -1
  76. package/dist/core/types.js +14 -4
  77. package/dist/core/types.js.map +1 -1
  78. package/dist/interactive/bridge-pool.d.ts +99 -0
  79. package/dist/interactive/bridge-pool.d.ts.map +1 -0
  80. package/dist/interactive/bridge-pool.js +244 -0
  81. package/dist/interactive/bridge-pool.js.map +1 -0
  82. package/dist/interactive/bridge-root.d.ts +36 -0
  83. package/dist/interactive/bridge-root.d.ts.map +1 -0
  84. package/dist/interactive/bridge-root.js +48 -0
  85. package/dist/interactive/bridge-root.js.map +1 -0
  86. package/dist/interactive/chat-events.d.ts +207 -0
  87. package/dist/interactive/chat-events.d.ts.map +1 -0
  88. package/dist/interactive/chat-events.js +769 -0
  89. package/dist/interactive/chat-events.js.map +1 -0
  90. package/dist/interactive/demo-events.d.ts +283 -0
  91. package/dist/interactive/demo-events.d.ts.map +1 -0
  92. package/dist/interactive/demo-events.js +889 -0
  93. package/dist/interactive/demo-events.js.map +1 -0
  94. package/dist/interactive/draft-events.d.ts +224 -0
  95. package/dist/interactive/draft-events.d.ts.map +1 -0
  96. package/dist/interactive/draft-events.js +793 -0
  97. package/dist/interactive/draft-events.js.map +1 -0
  98. package/dist/interactive/edit-events.d.ts +194 -0
  99. package/dist/interactive/edit-events.d.ts.map +1 -0
  100. package/dist/interactive/edit-events.js +601 -0
  101. package/dist/interactive/edit-events.js.map +1 -0
  102. package/dist/interactive/ledger.d.ts +39 -0
  103. package/dist/interactive/ledger.d.ts.map +1 -0
  104. package/dist/interactive/ledger.js +93 -0
  105. package/dist/interactive/ledger.js.map +1 -0
  106. package/dist/interactive/proxy-routes.d.ts +39 -0
  107. package/dist/interactive/proxy-routes.d.ts.map +1 -0
  108. package/dist/interactive/proxy-routes.js +189 -0
  109. package/dist/interactive/proxy-routes.js.map +1 -0
  110. package/dist/interactive/repo-snapshot.d.ts +100 -0
  111. package/dist/interactive/repo-snapshot.d.ts.map +1 -0
  112. package/dist/interactive/repo-snapshot.js +289 -0
  113. package/dist/interactive/repo-snapshot.js.map +1 -0
  114. package/dist/interactive/ws-relay.d.ts +85 -0
  115. package/dist/interactive/ws-relay.d.ts.map +1 -0
  116. package/dist/interactive/ws-relay.js +191 -0
  117. package/dist/interactive/ws-relay.js.map +1 -0
  118. package/dist/projects/activity.d.ts +29 -0
  119. package/dist/projects/activity.d.ts.map +1 -0
  120. package/dist/projects/activity.js +172 -0
  121. package/dist/projects/activity.js.map +1 -0
  122. package/dist/projects/charter.d.ts +28 -0
  123. package/dist/projects/charter.d.ts.map +1 -0
  124. package/dist/projects/charter.js +53 -0
  125. package/dist/projects/charter.js.map +1 -0
  126. package/dist/projects/events.d.ts +55 -0
  127. package/dist/projects/events.d.ts.map +1 -0
  128. package/dist/projects/events.js +141 -0
  129. package/dist/projects/events.js.map +1 -0
  130. package/dist/projects/graph-paths.d.ts +92 -0
  131. package/dist/projects/graph-paths.d.ts.map +1 -0
  132. package/dist/projects/graph-paths.js +130 -0
  133. package/dist/projects/graph-paths.js.map +1 -0
  134. package/dist/projects/graph.d.ts +179 -0
  135. package/dist/projects/graph.d.ts.map +1 -0
  136. package/dist/projects/graph.js +775 -0
  137. package/dist/projects/graph.js.map +1 -0
  138. package/dist/projects/membership-index.d.ts +25 -0
  139. package/dist/projects/membership-index.d.ts.map +1 -0
  140. package/dist/projects/membership-index.js +46 -0
  141. package/dist/projects/membership-index.js.map +1 -0
  142. package/dist/projects/routes.d.ts +97 -0
  143. package/dist/projects/routes.d.ts.map +1 -0
  144. package/dist/projects/routes.js +510 -0
  145. package/dist/projects/routes.js.map +1 -0
  146. package/dist/projects/settings.d.ts +32 -0
  147. package/dist/projects/settings.d.ts.map +1 -0
  148. package/dist/projects/settings.js +64 -0
  149. package/dist/projects/settings.js.map +1 -0
  150. package/dist/qe/acceptance.d.ts +137 -0
  151. package/dist/qe/acceptance.d.ts.map +1 -0
  152. package/dist/qe/acceptance.js +249 -0
  153. package/dist/qe/acceptance.js.map +1 -0
  154. package/dist/qe/gate-events.d.ts +111 -0
  155. package/dist/qe/gate-events.d.ts.map +1 -0
  156. package/dist/qe/gate-events.js +168 -0
  157. package/dist/qe/gate-events.js.map +1 -0
  158. package/dist/qe/ledger.d.ts +100 -0
  159. package/dist/qe/ledger.d.ts.map +1 -0
  160. package/dist/qe/ledger.js +154 -0
  161. package/dist/qe/ledger.js.map +1 -0
  162. package/dist/studio/assets/index-8p8uwCxG.js +530 -0
  163. package/dist/studio/assets/index-D6S9zUtO.css +32 -0
  164. package/dist/studio/index.html +5 -3
  165. package/package.json +10 -4
  166. package/dist/studio/assets/index-DaaUU8Ep.css +0 -32
  167. package/dist/studio/assets/index-Fu5DRC00.js +0 -423
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/projects/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAQ1C,MAAM,UAAU,mBAAmB,CAAC,MAAyB,OAAO,CAAC,GAAG;IACtE,OAAO,GAAG,CAAC,8BAA8B,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,cAAc,EAAE,uBAAuB,CAAC,CAAC;AACzG,CAAC;AAED,MAAM,OAAO,oBAAoB;IACd,IAAI,CAAS;IACb,IAAI,GAAoC,EAAE,CAAC;IAE5D,YAAY,OAAe,mBAAmB,EAAE;QAC9C,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAmD,CAAC;YACxG,KAAK,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,IAAI,EAAE,CAAC,EAAE,CAAC;gBAC/D,yFAAyF;gBACzF,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;oBAAE,SAAS;gBACtD,MAAM,IAAI,GAAG,GAAG,CAAC,eAAe,CAAC;gBACjC,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACpE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;gBACtE,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,yFAAyF;YACzF,uDAAuD;QACzD,CAAC;IACH,CAAC;IAED,uEAAuE;IACvE,GAAG,CAAC,SAAiB;QACnB,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;IACpC,CAAC;IAED,8FAA8F;IAC9F,GAAG,CAAC,SAAiB,EAAE,KAAsB;QAC3C,MAAM,IAAI,GAAoB,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC;QACnE,IAAI,IAAI,CAAC,eAAe,KAAK,IAAI,IAAI,IAAI,CAAC,eAAe,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,eAAe,CAAC;QACrG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,OAAO;QACb,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,IAAI,QAAQ,OAAO,CAAC,GAAG,EAAE,CAAC;QAC9C,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAC7E,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;CACF"}
@@ -0,0 +1,137 @@
1
+ /**
2
+ * The acceptance gate: deny-dominates resolution of a workflow's acceptance
3
+ * requirement from the QE evidence ledger (Phase 6a made crew the
4
+ * control-plane owner of the gate; Phase 6c retired wicked-testing, so the
5
+ * QE pipeline is garden's qe skills writing through wicked-ledger).
6
+ *
7
+ * A workflow DECLARES an acceptance requirement through its phases: any phase
8
+ * carrying `verified_evidence: true` requires its "done" to be re-derived from
9
+ * evidence rather than asserted (the same field the engine's evidence floor
10
+ * keys on). When a governed run's workflow declares one, crew resolves it from
11
+ * the ledger's newest verdict — deny-dominates throughout:
12
+ *
13
+ * PASS → satisfied
14
+ * FAIL → denied (the reviewer's reason is surfaced)
15
+ * CONDITIONAL → denied — garden's VERDICT_TO_STATUS maps it to
16
+ * run status `partial` ("approve with listed
17
+ * fixes", a deliberate ship-with-conditions
18
+ * outcome, distinct from PASS and FAIL). Under
19
+ * deny-dominates a conditional approval does not
20
+ * satisfy the gate on its own: the conditions
21
+ * are unmet work, and the hold stands until a
22
+ * clean PASS is recorded or a human approves at
23
+ * the crew gate with the conditions in view.
24
+ * PARTIAL → denied (some criteria met — not all)
25
+ * INCONCLUSIVE / N-A / SKIP → denied (evidence missing or not evaluated —
26
+ * map to `inconclusive`, the `?? 'inconclusive'`
27
+ * fallback of garden's convention)
28
+ * missing ledger / verdict → denied (no evidence is never a pass)
29
+ * unreadable ledger → denied, naming the read failure
30
+ *
31
+ * The verdict enum and the status mapping follow garden's qe `accept` action
32
+ * (VERDICT_TO_STATUS) and wicked-ledger's `RunStatus` — this module maps 1:1
33
+ * and never collapses distinct non-PASS outcomes into one another; only the
34
+ * GATE decision collapses (everything not PASS denies), and each denial keeps
35
+ * its own reason.
36
+ */
37
+ import type { Verdict } from 'wicked-ledger';
38
+ import type { RepoEntry, SessionView, WorkflowDef } from '../core/types.js';
39
+ import type { QeAcceptanceState, QeManifestSummary } from './ledger.js';
40
+ import type { QeGateCache, QeGateEventEntry } from './gate-events.js';
41
+ /**
42
+ * Verdict → run-status, 1:1 with garden's qe `accept` action (VERDICT_TO_STATUS)
43
+ * extended over the full ledger enum: N-A and SKIP take the convention's
44
+ * `?? 'inconclusive'` fallback ("couldn't evaluate"), exactly as the accept
45
+ * action computes `runStatus`. CONDITIONAL → `partial` is deliberate — a
46
+ * ship-with-conditions outcome, not a clean pass and not a failure.
47
+ */
48
+ export declare const VERDICT_TO_STATUS: Record<Verdict, string>;
49
+ /** Ids of a workflow's phases that declare the acceptance requirement (`verified_evidence: true`). */
50
+ export declare function acceptancePhaseIds(workflow: WorkflowDef | null): string[];
51
+ /**
52
+ * Resolve the workflow DEFINITION a run was launched with.
53
+ *
54
+ * The engine stores `workflow_id` as an instance id (`wf-<session-uuid>`), and
55
+ * `sessionsDetail()` patches it back to the definition name by matching phase
56
+ * sequences — against BUILT-INS only, so a run of a user-registered workflow
57
+ * still carries the instance id here. The acceptance requirement lives on the
58
+ * DEFINITION, so this falls back to the same phase-sequence match over the
59
+ * full registry (built-ins + user workflows). Free-text runs are excluded by
60
+ * construction: their planned units are `u1`, `u2`, … — not phase ids — and
61
+ * they declare nothing.
62
+ */
63
+ export declare function resolveRunWorkflow(run: SessionView, workflows: WorkflowDef[]): WorkflowDef | null;
64
+ /** The gate's resolution of one run's acceptance requirement. */
65
+ export interface AcceptanceGateResolution {
66
+ /** Whether the run's workflow declares an acceptance requirement at all. */
67
+ required: boolean;
68
+ /** Deny-dominates decision. `true` only for a clean PASS (or when nothing is required). */
69
+ satisfied: boolean;
70
+ /** The governing ledger verdict, when one was read. */
71
+ verdict: Verdict | null;
72
+ /** That verdict mapped through {@link VERDICT_TO_STATUS} (null when no verdict). */
73
+ runStatus: string | null;
74
+ /** Why the gate decided what it decided — always populated, never empty. */
75
+ reason: string;
76
+ }
77
+ /**
78
+ * Resolve the acceptance requirement for one run — pure, deny-dominates.
79
+ *
80
+ * `state === null` means the run has no repo context at all (a repo-less run
81
+ * has nowhere a ledger could live), which is its own denial reason: evidence
82
+ * that cannot be LOCATED is indistinguishable from evidence that does not
83
+ * exist, and neither satisfies a gate.
84
+ */
85
+ export declare function resolveAcceptanceGate(required: boolean, state: QeAcceptanceState | null): AcceptanceGateResolution;
86
+ /** The body `GET /runs/:id/acceptance` serves. */
87
+ export interface AcceptanceView {
88
+ runId: string;
89
+ repo: {
90
+ id: string;
91
+ name: string;
92
+ rootPath: string;
93
+ } | null;
94
+ requirement: {
95
+ declared: boolean;
96
+ phases: string[];
97
+ };
98
+ acceptance: {
99
+ ledgerDir: string;
100
+ ledgerRoot: string;
101
+ found: boolean;
102
+ qeRun: {
103
+ id: string;
104
+ status: string;
105
+ startedAt: string;
106
+ finishedAt: string | null;
107
+ projectId: string;
108
+ scenarioId: string;
109
+ } | null;
110
+ verdict: {
111
+ id: string;
112
+ verdict: string;
113
+ reviewer: string;
114
+ reason: string | null;
115
+ createdAt: string;
116
+ qeRunId: string;
117
+ } | null;
118
+ manifest: QeManifestSummary | null;
119
+ error?: string;
120
+ } | null;
121
+ gate: AcceptanceGateResolution;
122
+ /** The latest matching `wicked.qe.*` bus event, when the bus seam is armed and one was seen. */
123
+ busEvent: QeGateEventEntry | null;
124
+ }
125
+ /**
126
+ * Assemble the acceptance view for one crew run: read the ledger (lazy read —
127
+ * the fallback that needs no bus), resolve the gate, and attach the freshest
128
+ * matching bus event when the opt-in subscription has seen one.
129
+ */
130
+ export declare function buildAcceptanceView(opts: {
131
+ runId: string;
132
+ repo: RepoEntry | null;
133
+ workflow: WorkflowDef | null;
134
+ gateEvents: QeGateCache;
135
+ qeRunId?: string;
136
+ }): Promise<AcceptanceView>;
137
+ //# sourceMappingURL=acceptance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acceptance.d.ts","sourceRoot":"","sources":["../../src/qe/acceptance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,249 @@
1
+ /**
2
+ * The acceptance gate: deny-dominates resolution of a workflow's acceptance
3
+ * requirement from the QE evidence ledger (Phase 6a made crew the
4
+ * control-plane owner of the gate; Phase 6c retired wicked-testing, so the
5
+ * QE pipeline is garden's qe skills writing through wicked-ledger).
6
+ *
7
+ * A workflow DECLARES an acceptance requirement through its phases: any phase
8
+ * carrying `verified_evidence: true` requires its "done" to be re-derived from
9
+ * evidence rather than asserted (the same field the engine's evidence floor
10
+ * keys on). When a governed run's workflow declares one, crew resolves it from
11
+ * the ledger's newest verdict — deny-dominates throughout:
12
+ *
13
+ * PASS → satisfied
14
+ * FAIL → denied (the reviewer's reason is surfaced)
15
+ * CONDITIONAL → denied — garden's VERDICT_TO_STATUS maps it to
16
+ * run status `partial` ("approve with listed
17
+ * fixes", a deliberate ship-with-conditions
18
+ * outcome, distinct from PASS and FAIL). Under
19
+ * deny-dominates a conditional approval does not
20
+ * satisfy the gate on its own: the conditions
21
+ * are unmet work, and the hold stands until a
22
+ * clean PASS is recorded or a human approves at
23
+ * the crew gate with the conditions in view.
24
+ * PARTIAL → denied (some criteria met — not all)
25
+ * INCONCLUSIVE / N-A / SKIP → denied (evidence missing or not evaluated —
26
+ * map to `inconclusive`, the `?? 'inconclusive'`
27
+ * fallback of garden's convention)
28
+ * missing ledger / verdict → denied (no evidence is never a pass)
29
+ * unreadable ledger → denied, naming the read failure
30
+ *
31
+ * The verdict enum and the status mapping follow garden's qe `accept` action
32
+ * (VERDICT_TO_STATUS) and wicked-ledger's `RunStatus` — this module maps 1:1
33
+ * and never collapses distinct non-PASS outcomes into one another; only the
34
+ * GATE decision collapses (everything not PASS denies), and each denial keeps
35
+ * its own reason.
36
+ */
37
+ import { VERDICT_VALUES } from 'wicked-ledger';
38
+ import { basename } from 'node:path';
39
+ import { readAcceptanceState, summarizeManifest } from './ledger.js';
40
+ /**
41
+ * Verdict → run-status, 1:1 with garden's qe `accept` action (VERDICT_TO_STATUS)
42
+ * extended over the full ledger enum: N-A and SKIP take the convention's
43
+ * `?? 'inconclusive'` fallback ("couldn't evaluate"), exactly as the accept
44
+ * action computes `runStatus`. CONDITIONAL → `partial` is deliberate — a
45
+ * ship-with-conditions outcome, not a clean pass and not a failure.
46
+ */
47
+ export const VERDICT_TO_STATUS = {
48
+ PASS: 'passed',
49
+ FAIL: 'failed',
50
+ PARTIAL: 'partial',
51
+ CONDITIONAL: 'partial',
52
+ INCONCLUSIVE: 'inconclusive',
53
+ 'N-A': 'inconclusive',
54
+ SKIP: 'inconclusive',
55
+ };
56
+ /** Ids of a workflow's phases that declare the acceptance requirement (`verified_evidence: true`). */
57
+ export function acceptancePhaseIds(workflow) {
58
+ if (workflow === null)
59
+ return [];
60
+ return workflow.phases.filter((p) => p.verified_evidence === true).map((p) => p.id);
61
+ }
62
+ /**
63
+ * Resolve the workflow DEFINITION a run was launched with.
64
+ *
65
+ * The engine stores `workflow_id` as an instance id (`wf-<session-uuid>`), and
66
+ * `sessionsDetail()` patches it back to the definition name by matching phase
67
+ * sequences — against BUILT-INS only, so a run of a user-registered workflow
68
+ * still carries the instance id here. The acceptance requirement lives on the
69
+ * DEFINITION, so this falls back to the same phase-sequence match over the
70
+ * full registry (built-ins + user workflows). Free-text runs are excluded by
71
+ * construction: their planned units are `u1`, `u2`, … — not phase ids — and
72
+ * they declare nothing.
73
+ */
74
+ export function resolveRunWorkflow(run, workflows) {
75
+ const direct = workflows.find((w) => w.id === run.session.workflow_id);
76
+ if (direct !== undefined)
77
+ return direct;
78
+ if (!run.session.workflow_id.startsWith('wf-'))
79
+ return null;
80
+ const phases = [...run.units]
81
+ .sort((a, b) => a.ord - b.ord)
82
+ .map((u) => {
83
+ const colonIdx = u.id.indexOf(':');
84
+ return colonIdx >= 0 ? u.id.slice(colonIdx + 1) : '';
85
+ });
86
+ if (phases.length === 0 || phases.some((p) => p === '' || /^u\d+$/.test(p)))
87
+ return null;
88
+ return (workflows.find((w) => w.phases.length === phases.length && w.phases.every((p, i) => p.id === phases[i])) ?? null);
89
+ }
90
+ /** Narrow an arbitrary string from the store to the ledger's verdict enum. */
91
+ function asVerdict(value) {
92
+ return VERDICT_VALUES.includes(value) ? value : null;
93
+ }
94
+ /**
95
+ * Resolve the acceptance requirement for one run — pure, deny-dominates.
96
+ *
97
+ * `state === null` means the run has no repo context at all (a repo-less run
98
+ * has nowhere a ledger could live), which is its own denial reason: evidence
99
+ * that cannot be LOCATED is indistinguishable from evidence that does not
100
+ * exist, and neither satisfies a gate.
101
+ */
102
+ export function resolveAcceptanceGate(required, state) {
103
+ const verdictValue = state?.verdict?.verdict ?? null;
104
+ const verdict = verdictValue !== null ? asVerdict(verdictValue) : null;
105
+ const runStatus = verdict !== null ? (VERDICT_TO_STATUS[verdict] ?? 'inconclusive') : null;
106
+ const base = { required, verdict, runStatus };
107
+ if (!required) {
108
+ // Vacuous, and labeled as such: nothing was required, so nothing is held.
109
+ // NOT a statement that evidence exists — the acceptance body says what was found.
110
+ return {
111
+ ...base,
112
+ satisfied: true,
113
+ reason: 'workflow declares no acceptance requirement (no verified_evidence phase)',
114
+ };
115
+ }
116
+ if (state === null) {
117
+ return {
118
+ ...base,
119
+ satisfied: false,
120
+ reason: 'run has no repo context — acceptance evidence cannot be located (missing ⇒ deny)',
121
+ };
122
+ }
123
+ if (!state.found) {
124
+ return {
125
+ ...base,
126
+ satisfied: false,
127
+ reason: `no QE ledger at ${state.root} — no acceptance evidence recorded (missing ⇒ deny)`,
128
+ };
129
+ }
130
+ if (state.error !== undefined) {
131
+ // Unreadable is NOT "absent": the remedy is fixing the store, not running QE again.
132
+ return {
133
+ ...base,
134
+ satisfied: false,
135
+ reason: `QE ledger at ${state.root} could not be read: ${state.error} (unreadable ⇒ deny)`,
136
+ };
137
+ }
138
+ if (state.verdict === null) {
139
+ return {
140
+ ...base,
141
+ satisfied: false,
142
+ reason: `QE ledger at ${state.root} records no verdict (missing ⇒ deny)`,
143
+ };
144
+ }
145
+ if (verdict === null) {
146
+ // A verdict row outside the enum should be impossible (the store enforces
147
+ // the enum pre-write and via CHECK constraint) — but an impossible row is
148
+ // still not a PASS, and saying which row broke beats crashing the route.
149
+ return {
150
+ ...base,
151
+ satisfied: false,
152
+ reason: `verdict ${state.verdict.id} carries an out-of-enum value '${verdictValue}' (unrecognized ⇒ deny)`,
153
+ };
154
+ }
155
+ const cite = `verdict ${state.verdict.id} by ${state.verdict.reviewer}`;
156
+ switch (verdict) {
157
+ case 'PASS':
158
+ return { ...base, satisfied: true, reason: `PASS — ${cite}` };
159
+ case 'FAIL':
160
+ return {
161
+ ...base,
162
+ satisfied: false,
163
+ reason: `FAIL — ${cite}${state.verdict.reason ? `: ${state.verdict.reason}` : ''}`,
164
+ };
165
+ case 'CONDITIONAL':
166
+ return {
167
+ ...base,
168
+ satisfied: false,
169
+ reason: `CONDITIONAL (run status 'partial') — approve-with-listed-fixes does not satisfy the gate on its own; ` +
170
+ `hold until a clean PASS or a human approves with the conditions in view. ${cite}` +
171
+ `${state.verdict.reason ? `: ${state.verdict.reason}` : ''}`,
172
+ };
173
+ case 'PARTIAL':
174
+ return {
175
+ ...base,
176
+ satisfied: false,
177
+ reason: `PARTIAL — some criteria met, not all; not a pass. ${cite}`,
178
+ };
179
+ default:
180
+ // INCONCLUSIVE / N-A / SKIP — could not be (or was not) evaluated.
181
+ return {
182
+ ...base,
183
+ satisfied: false,
184
+ reason: `${verdict} — evidence was not conclusively evaluated; not a pass. ${cite}`,
185
+ };
186
+ }
187
+ }
188
+ /**
189
+ * Assemble the acceptance view for one crew run: read the ledger (lazy read —
190
+ * the fallback that needs no bus), resolve the gate, and attach the freshest
191
+ * matching bus event when the opt-in subscription has seen one.
192
+ */
193
+ export async function buildAcceptanceView(opts) {
194
+ const phases = acceptancePhaseIds(opts.workflow);
195
+ const required = phases.length > 0;
196
+ const state = opts.repo !== null
197
+ ? await readAcceptanceState(opts.repo.root_path, opts.qeRunId !== undefined ? { qeRunId: opts.qeRunId } : undefined)
198
+ : null;
199
+ const gate = resolveAcceptanceGate(required, state);
200
+ // Freshness signal only — the ledger stays the system of record for the
201
+ // gate. Keyed by the QE run id when the ledger named one, else by context
202
+ // (the gate emitter's `context` is the QE project id).
203
+ const busEvent = (state?.verdict !== null && state?.verdict !== undefined
204
+ ? opts.gateEvents.forRun(state.verdict.run_id)
205
+ : undefined) ??
206
+ (state?.run != null ? opts.gateEvents.forContext(state.run.project_id) : undefined) ??
207
+ null;
208
+ return {
209
+ runId: opts.runId,
210
+ repo: opts.repo !== null
211
+ ? { id: opts.repo.id, name: opts.repo.name, rootPath: opts.repo.root_path }
212
+ : null,
213
+ requirement: { declared: required, phases },
214
+ acceptance: state !== null
215
+ ? {
216
+ // The dirname actually resolved (dual-read may have picked the
217
+ // legacy `.wicked-testing` root) — not the configured default.
218
+ ledgerDir: basename(state.root),
219
+ ledgerRoot: state.root,
220
+ found: state.found,
221
+ qeRun: state.run !== null
222
+ ? {
223
+ id: state.run.id,
224
+ status: state.run.status,
225
+ startedAt: state.run.started_at,
226
+ finishedAt: state.run.finished_at ?? null,
227
+ projectId: state.run.project_id,
228
+ scenarioId: state.run.scenario_id,
229
+ }
230
+ : null,
231
+ verdict: state.verdict !== null
232
+ ? {
233
+ id: state.verdict.id,
234
+ verdict: state.verdict.verdict,
235
+ reviewer: state.verdict.reviewer,
236
+ reason: state.verdict.reason ?? null,
237
+ createdAt: state.verdict.created_at,
238
+ qeRunId: state.verdict.run_id,
239
+ }
240
+ : null,
241
+ manifest: state.manifest !== null ? summarizeManifest(state.manifest) : null,
242
+ ...(state.error !== undefined ? { error: state.error } : {}),
243
+ }
244
+ : null,
245
+ gate,
246
+ busEvent,
247
+ };
248
+ }
249
+ //# sourceMappingURL=acceptance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acceptance.js","sourceRoot":"","sources":["../../src/qe/acceptance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Opt-in consumption of the QE gate's wicked-bus events.
3
+ *
4
+ * The QE pipeline announces gate results on the bus — the wire contract the
5
+ * retired wicked-testing package's `lib/gate.mjs` established and garden's qe
6
+ * skills now emit (Phase 6c kept these event names and payload fields STABLE
7
+ * by decision — only the emitters' `domain` stamp rebranded to `qe`):
8
+ *
9
+ * wicked.qe.gate.passed | wicked.qe.gate.failed | wicked.qe.gate.conditional
10
+ * payload (8 canonical fields): run_id, context, gate_verdict, exit_code,
11
+ * verdict_summary, mode, completed_at, scenario_count
12
+ * idempotency key: `qe:gate.result:{context}:{sha256(run_id)[0:16]}:0`
13
+ * wicked.qe.deploy.completed
14
+ * payload: run_id, project_id (emitted alongside a PASS)
15
+ *
16
+ * Consumption is OPT-IN behind crew's existing bus seam (like `--bus-db` /
17
+ * `WICKED_BUS_EXEC`): when armed, a durable wicked-bus subscriber folds each
18
+ * event into this in-memory cache so acceptance reads see gate results the
19
+ * moment they happen; when the bus is absent, nothing here runs and the
20
+ * acceptance route's lazy ledger read is the (always-correct) fallback. The
21
+ * cache is a freshness signal — the ledger stays the system of record for the
22
+ * gate decision, so a lost or replayed event can never flip a verdict.
23
+ */
24
+ /** The gate-result event types (the old gate.mjs wire contract, verbatim). */
25
+ export declare const QE_GATE_EVENT_TYPES: readonly ["wicked.qe.gate.passed", "wicked.qe.gate.failed", "wicked.qe.gate.conditional"];
26
+ /** The cross-product deploy signal emitted alongside a PASS. */
27
+ export declare const QE_DEPLOY_EVENT_TYPE = "wicked.qe.deploy.completed";
28
+ /**
29
+ * One durable-subscription filter covering both families above
30
+ * (`prefix.**` = one or more remaining segments in wicked-bus filter grammar).
31
+ */
32
+ export declare const QE_BUS_FILTER = "wicked.qe.**";
33
+ /** Subscriber identity on the bus (registration + cursor resume key). */
34
+ export declare const QE_BUS_PLUGIN = "wicked-crew";
35
+ /** A folded gate/deploy event, as the acceptance route serves it. */
36
+ export interface QeGateEventEntry {
37
+ eventType: string;
38
+ /** The QE run the result is about (`run_id`). */
39
+ runId: string;
40
+ /** The emitter's context — the QE project id (`context` / `project_id`). */
41
+ context: string | null;
42
+ /** PASS | FAIL | CONDITIONAL | SYSTEM_ERROR (gate events; null on deploy). */
43
+ gateVerdict: string | null;
44
+ exitCode: number | null;
45
+ verdictSummary: string | null;
46
+ mode: string | null;
47
+ completedAt: string | null;
48
+ scenarioCount: number | null;
49
+ /** When THIS daemon observed the event (bus delivery time), ISO-8601. */
50
+ observedAt: string;
51
+ }
52
+ /**
53
+ * Latest-gate-result cache, keyed by QE run id and by context.
54
+ *
55
+ * At-least-once delivery means the same logical event may arrive more than
56
+ * once; folding is idempotent by construction (same event ⇒ same entry). No
57
+ * eviction: entries are one small record per QE run/context and the daemon is
58
+ * local-first — a restart simply starts empty and the ledger read covers it.
59
+ */
60
+ export declare class QeGateCache {
61
+ private readonly byRun;
62
+ private readonly byContext;
63
+ private latestEntry;
64
+ /**
65
+ * Fold one bus event. Returns `true` when the event was a recognized
66
+ * `wicked.qe.*` gate/deploy frame and was cached; unknown types are ignored
67
+ * (the durable filter is a prefix, so future qe events pass through here).
68
+ */
69
+ ingest(eventType: string, payload: unknown, observedAt?: string): boolean;
70
+ /** The latest cached result for a QE run id. */
71
+ forRun(runId: string): QeGateEventEntry | undefined;
72
+ /** The latest cached result for a context (QE project id). */
73
+ forContext(context: string): QeGateEventEntry | undefined;
74
+ /** The most recently observed event, whatever it was keyed by. */
75
+ latest(): QeGateEventEntry | undefined;
76
+ /** Number of distinct QE runs with a cached result (diagnostics / tests). */
77
+ size(): number;
78
+ }
79
+ /** Options for {@link startQeGateSubscriber}. */
80
+ export interface QeGateSubscriberOptions {
81
+ /**
82
+ * Bus SQLite db path. Omit to let wicked-bus resolve its own default
83
+ * (`~/.something-wicked/wicked-bus/bus.db`) — which is where the QE
84
+ * pipeline's CLI emits unless redirected, so the default is usually right.
85
+ */
86
+ dbPath?: string;
87
+ /** Poll cadence, ms (default 5000; tests use a short interval). */
88
+ pollIntervalMs?: number;
89
+ /** Diagnostics sink (default: console.error). */
90
+ log?: (message: string) => void;
91
+ }
92
+ /** Handle for a running subscription. */
93
+ export interface QeGateSubscription {
94
+ stop(): Promise<void> | void;
95
+ }
96
+ /**
97
+ * Start the durable `wicked.qe.**` subscriber and fold events into `cache`.
98
+ *
99
+ * Graceful degradation, matching how other wicked consumers subscribe
100
+ * (wicked-brain's memory subscriber): wicked-bus is dynamically imported, and
101
+ * a missing package / unopenable db returns `null` instead of throwing — the
102
+ * caller opted in, so the degradation is LOGGED, but a daemon must still boot
103
+ * on a machine whose bus is broken (acceptance falls back to lazy ledger
104
+ * reads, which never needed the bus).
105
+ *
106
+ * `cursor_init: 'latest'`: the cache is a live freshness signal, not history —
107
+ * replaying an old bus backlog into it would let a stale event masquerade as
108
+ * fresh. History belongs to the ledger.
109
+ */
110
+ export declare function startQeGateSubscriber(cache: QeGateCache, opts?: QeGateSubscriberOptions): Promise<QeGateSubscription | null>;
111
+ //# sourceMappingURL=gate-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-events.d.ts","sourceRoot":"","sources":["../../src/qe/gate-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,8EAA8E;AAC9E,eAAO,MAAM,mBAAmB,2FAItB,CAAC;AAEX,gEAAgE;AAChE,eAAO,MAAM,oBAAoB,+BAA+B,CAAC;AAEjE;;;GAGG;AACH,eAAO,MAAM,aAAa,iBAAiB,CAAC;AAE5C,yEAAyE;AACzE,eAAO,MAAM,aAAa,gBAAgB,CAAC;AAE3C,qEAAqE;AACrE,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,4EAA4E;IAC5E,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,8EAA8E;IAC9E,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAC;CACpB;AAUD;;;;;;;GAOG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuC;IAC7D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAuC;IACjE,OAAO,CAAC,WAAW,CAA+B;IAElD;;;;OAIG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,SAA2B,GAAG,OAAO;IAoC3F,gDAAgD;IAChD,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAInD,8DAA8D;IAC9D,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAIzD,kEAAkE;IAClE,MAAM,IAAI,gBAAgB,GAAG,SAAS;IAItC,6EAA6E;IAC7E,IAAI,IAAI,MAAM;CAGf;AAED,iDAAiD;AACjD,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iDAAiD;IACjD,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAED,yCAAyC;AACzC,MAAM,WAAW,kBAAkB;IACjC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC9B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,WAAW,EAClB,IAAI,GAAE,uBAA4B,GACjC,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAiDpC"}