wicked-crew 0.7.28 → 0.7.30

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 (146) hide show
  1. package/README.md +12 -1
  2. package/dist/api/chat-scope.d.ts +210 -0
  3. package/dist/api/chat-scope.d.ts.map +1 -0
  4. package/dist/api/chat-scope.js +728 -0
  5. package/dist/api/chat-scope.js.map +1 -0
  6. package/dist/api/diagnostics.d.ts +30 -2
  7. package/dist/api/diagnostics.d.ts.map +1 -1
  8. package/dist/api/diagnostics.js +73 -5
  9. package/dist/api/diagnostics.js.map +1 -1
  10. package/dist/api/governance-health.d.ts +171 -0
  11. package/dist/api/governance-health.d.ts.map +1 -0
  12. package/dist/api/governance-health.js +379 -0
  13. package/dist/api/governance-health.js.map +1 -0
  14. package/dist/api/open-path.d.ts.map +1 -1
  15. package/dist/api/open-path.js +2 -1
  16. package/dist/api/open-path.js.map +1 -1
  17. package/dist/api/post-hoc-deliver.d.ts +9 -5
  18. package/dist/api/post-hoc-deliver.d.ts.map +1 -1
  19. package/dist/api/post-hoc-deliver.js +21 -7
  20. package/dist/api/post-hoc-deliver.js.map +1 -1
  21. package/dist/api/routes.d.ts +70 -12
  22. package/dist/api/routes.d.ts.map +1 -1
  23. package/dist/api/routes.js +375 -60
  24. package/dist/api/routes.js.map +1 -1
  25. package/dist/api/seat-health.d.ts +38 -0
  26. package/dist/api/seat-health.d.ts.map +1 -1
  27. package/dist/api/seat-health.js +88 -5
  28. package/dist/api/seat-health.js.map +1 -1
  29. package/dist/api/seat-signin.d.ts.map +1 -1
  30. package/dist/api/seat-signin.js +49 -23
  31. package/dist/api/seat-signin.js.map +1 -1
  32. package/dist/api/seat-standing.d.ts +101 -0
  33. package/dist/api/seat-standing.d.ts.map +1 -0
  34. package/dist/api/seat-standing.js +138 -0
  35. package/dist/api/seat-standing.js.map +1 -0
  36. package/dist/api/server.d.ts.map +1 -1
  37. package/dist/api/server.js +37 -0
  38. package/dist/api/server.js.map +1 -1
  39. package/dist/campaigns/routes.d.ts +4 -4
  40. package/dist/cli/governance.d.ts +131 -0
  41. package/dist/cli/governance.d.ts.map +1 -0
  42. package/dist/cli/governance.js +354 -0
  43. package/dist/cli/governance.js.map +1 -0
  44. package/dist/cli/index.js +102 -3
  45. package/dist/cli/index.js.map +1 -1
  46. package/dist/core/adapter.d.ts +99 -1
  47. package/dist/core/adapter.d.ts.map +1 -1
  48. package/dist/core/adapter.js +149 -8
  49. package/dist/core/adapter.js.map +1 -1
  50. package/dist/core/bridge-path.d.ts +21 -0
  51. package/dist/core/bridge-path.d.ts.map +1 -1
  52. package/dist/core/bridge-path.js +37 -0
  53. package/dist/core/bridge-path.js.map +1 -1
  54. package/dist/core/bridge-reaper.d.ts.map +1 -1
  55. package/dist/core/bridge-reaper.js +11 -4
  56. package/dist/core/bridge-reaper.js.map +1 -1
  57. package/dist/core/deliver-text.d.ts +184 -0
  58. package/dist/core/deliver-text.d.ts.map +1 -0
  59. package/dist/core/deliver-text.js +434 -0
  60. package/dist/core/deliver-text.js.map +1 -0
  61. package/dist/core/deliver-triage.d.ts +90 -0
  62. package/dist/core/deliver-triage.d.ts.map +1 -0
  63. package/dist/core/deliver-triage.js +106 -0
  64. package/dist/core/deliver-triage.js.map +1 -0
  65. package/dist/core/deliver.d.ts +103 -9
  66. package/dist/core/deliver.d.ts.map +1 -1
  67. package/dist/core/deliver.js +244 -46
  68. package/dist/core/deliver.js.map +1 -1
  69. package/dist/core/estate-mcp-client.d.ts.map +1 -1
  70. package/dist/core/estate-mcp-client.js +7 -2
  71. package/dist/core/estate-mcp-client.js.map +1 -1
  72. package/dist/core/exec.d.ts.map +1 -1
  73. package/dist/core/exec.js +11 -1
  74. package/dist/core/exec.js.map +1 -1
  75. package/dist/core/governance-store.d.ts +219 -0
  76. package/dist/core/governance-store.d.ts.map +1 -0
  77. package/dist/core/governance-store.js +290 -0
  78. package/dist/core/governance-store.js.map +1 -0
  79. package/dist/core/repoPaths.d.ts +36 -5
  80. package/dist/core/repoPaths.d.ts.map +1 -1
  81. package/dist/core/repoPaths.js +46 -4
  82. package/dist/core/repoPaths.js.map +1 -1
  83. package/dist/interactive/bridge-pool.d.ts +29 -24
  84. package/dist/interactive/bridge-pool.d.ts.map +1 -1
  85. package/dist/interactive/bridge-pool.js +74 -7
  86. package/dist/interactive/bridge-pool.js.map +1 -1
  87. package/dist/interactive/chat-events.d.ts.map +1 -1
  88. package/dist/interactive/chat-events.js +5 -2
  89. package/dist/interactive/chat-events.js.map +1 -1
  90. package/dist/interactive/council-outcome.d.ts +28 -0
  91. package/dist/interactive/council-outcome.d.ts.map +1 -0
  92. package/dist/interactive/council-outcome.js +57 -0
  93. package/dist/interactive/council-outcome.js.map +1 -0
  94. package/dist/interactive/demo-events.d.ts.map +1 -1
  95. package/dist/interactive/demo-events.js +5 -2
  96. package/dist/interactive/demo-events.js.map +1 -1
  97. package/dist/interactive/doc-delete-routes.d.ts.map +1 -1
  98. package/dist/interactive/doc-delete-routes.js +3 -2
  99. package/dist/interactive/doc-delete-routes.js.map +1 -1
  100. package/dist/interactive/draft-events.d.ts.map +1 -1
  101. package/dist/interactive/draft-events.js +5 -2
  102. package/dist/interactive/draft-events.js.map +1 -1
  103. package/dist/interactive/edit-events.d.ts.map +1 -1
  104. package/dist/interactive/edit-events.js +5 -2
  105. package/dist/interactive/edit-events.js.map +1 -1
  106. package/dist/projects/auto-refresh.d.ts +54 -0
  107. package/dist/projects/auto-refresh.d.ts.map +1 -0
  108. package/dist/projects/auto-refresh.js +76 -0
  109. package/dist/projects/auto-refresh.js.map +1 -0
  110. package/dist/projects/graph-paths.d.ts +4 -2
  111. package/dist/projects/graph-paths.d.ts.map +1 -1
  112. package/dist/projects/graph-paths.js +4 -2
  113. package/dist/projects/graph-paths.js.map +1 -1
  114. package/dist/projects/graph.d.ts +20 -6
  115. package/dist/projects/graph.d.ts.map +1 -1
  116. package/dist/projects/graph.js +40 -13
  117. package/dist/projects/graph.js.map +1 -1
  118. package/dist/projects/routes.d.ts.map +1 -1
  119. package/dist/projects/routes.js +30 -11
  120. package/dist/projects/routes.js.map +1 -1
  121. package/dist/projects/state-home.d.ts +6 -0
  122. package/dist/projects/state-home.d.ts.map +1 -1
  123. package/dist/projects/state-home.js +9 -1
  124. package/dist/projects/state-home.js.map +1 -1
  125. package/dist/skills/guards.d.ts +17 -6
  126. package/dist/skills/guards.d.ts.map +1 -1
  127. package/dist/skills/guards.js +42 -15
  128. package/dist/skills/guards.js.map +1 -1
  129. package/dist/skills/plugin-source.d.ts.map +1 -1
  130. package/dist/skills/plugin-source.js +3 -0
  131. package/dist/skills/plugin-source.js.map +1 -1
  132. package/dist/skills/refs.d.ts +181 -17
  133. package/dist/skills/refs.d.ts.map +1 -1
  134. package/dist/skills/refs.js +345 -26
  135. package/dist/skills/refs.js.map +1 -1
  136. package/dist/skills/store.d.ts +22 -1
  137. package/dist/skills/store.d.ts.map +1 -1
  138. package/dist/skills/store.js +161 -23
  139. package/dist/skills/store.js.map +1 -1
  140. package/dist/studio/assets/index-CWUS9Ump.js +542 -0
  141. package/dist/studio/assets/{index-CK1uJWs2.css → index-_ydd-jKd.css} +1 -1
  142. package/dist/studio/index.html +2 -2
  143. package/dist/studio/testid-inventory.json +567 -6
  144. package/endpoint-manifest.json +67 -14
  145. package/package.json +4 -4
  146. package/dist/studio/assets/index-CdmCMh2f.js +0 -539
@@ -0,0 +1,184 @@
1
+ /**
2
+ * The deliver phase's PR + commit TEXT (crew#524, acceptance finding F-3R2-014).
3
+ *
4
+ * `gh pr create --fill` opened wicked-studio#249 with a title cut MID-WORD out of the intent's first
5
+ * 72 characters (`…scenario CLN-2) aga`) and an EMPTY body: no `Fixes #214`, no run link, no record
6
+ * of what ran or what passed — and the commit carried the same truncated headline. A reviewer got
7
+ * nothing to review against. This module composes the text from the RUN instead. ONE composer, two
8
+ * moments it can be asked:
9
+ *
10
+ * - at DELIVERY, from the persisted run view (`GET /runs/:id/deliver-text`, text/plain): every
11
+ * phase the run went through with its seat and gate outcome, the repo checks the verify phase
12
+ * ran with their exit codes, the evaluator's verdict, and a link to the run;
13
+ * - at LAUNCH, from the workflow definition — the fallback the deliver script carries in case the
14
+ * daemon cannot answer when the PR opens (an auth-required daemon, no `curl`, a daemon that went
15
+ * away): the intent, the issue links, the run id and the phase list ARE known then; the runtime
16
+ * sections say plainly that they were not available rather than pretending.
17
+ *
18
+ * The title is the intent's first line, cut at a WORD boundary within {@link DELIVER_TITLE_MAX}
19
+ * characters (never mid-word), or `wicked-crew run <id>` when the intent is blank. `Fixes #N` is
20
+ * emitted when the intent names an issue with a closing verb (`fix issue #214`, `closes #7`); every
21
+ * other `#N` / `repo#N` / `owner/repo#N` mention rides as `Refs:`.
22
+ *
23
+ * FRAMING, shared by both carriers (the daemon's text/plain answer and the script's embedded
24
+ * fallback) so the script parses exactly one shape: line 1 = title, line 2 = blank, then the body.
25
+ * The framed text is also, verbatim, the message of the commit the deliver phase MAKES when the
26
+ * run left uncommitted work (`git commit -F`: git takes the first paragraph as the subject). A run
27
+ * that committed incrementally keeps its own commits untouched — the PR title is composed from the
28
+ * run either way; only the deliver phase's own commit is guaranteed to match it.
29
+ */
30
+ import type { GateSpec, PhaseDef, SessionView } from './types.js';
31
+ /** The PR title / commit subject cap — git's conventional subject width. */
32
+ export declare const DELIVER_TITLE_MAX = 72;
33
+ /** One phase of the run, with as much as is known about it at composition time. */
34
+ export interface DeliverPhaseFact {
35
+ id: string;
36
+ stage: string;
37
+ role: string;
38
+ gate: string;
39
+ /** The seat that did the work — `null` when unknown (launch time) or when the phase is tooling. */
40
+ seat: string | null;
41
+ /** The recorded gate outcome / unit status, or `—` at launch time. */
42
+ outcome: string;
43
+ }
44
+ /** One repo check the verify phase ran (`typecheck` / `lint` / `test`), as the engine recorded it. */
45
+ export interface DeliverCheckFact {
46
+ name: string;
47
+ command: string;
48
+ exitCode: number | null;
49
+ durationMs: number | null;
50
+ timedOut: boolean;
51
+ spawnError: string | null;
52
+ }
53
+ /** An evaluator-role phase's recorded verdict. */
54
+ export interface DeliverVerdictFact {
55
+ phase: string;
56
+ seat: string | null;
57
+ verdict: string;
58
+ reason: string | null;
59
+ }
60
+ /** Everything the composer needs. Built by {@link factsFromRun} or {@link factsFromWorkflow}. */
61
+ export interface DeliverTextFacts {
62
+ runId: string;
63
+ intent: string;
64
+ workflowId: string | null;
65
+ repoRef: string | null;
66
+ /** The studio bookmark for the run (`<daemon origin>/runs/<id>`), when the origin is known. */
67
+ runUrl: string | null;
68
+ /** `run`: from the persisted run view; `workflow`: from the definition at launch (no runtime facts). */
69
+ source: 'run' | 'workflow';
70
+ phases: DeliverPhaseFact[];
71
+ /** Recorded repo checks; `null` when the run recorded none. Ignored when `source` is `workflow`. */
72
+ checks: DeliverCheckFact[] | null;
73
+ verdicts: DeliverVerdictFact[];
74
+ }
75
+ export interface DeliverText {
76
+ /** ≤ {@link DELIVER_TITLE_MAX} characters, one line, never cut mid-word. */
77
+ title: string;
78
+ /** Markdown; never empty. */
79
+ body: string;
80
+ }
81
+ export interface IssueRefs {
82
+ /** `#N` (or `repo#N`) mentions the intent pairs with a closing verb — emitted as `Fixes …`. */
83
+ fixes: string[];
84
+ /** Every other issue mention — emitted as `Refs: …`. */
85
+ refs: string[];
86
+ }
87
+ /**
88
+ * The PR title / commit subject: the intent's first line, whole when it fits, otherwise cut at the
89
+ * last word boundary that leaves room for a single `…` — so the result is ≤ 72 characters and never
90
+ * ends mid-word (the F-3R2-014 headline `…scenario CLN-2) aga`). Dangling punctuation before the
91
+ * ellipsis is dropped. A blank intent names the run instead — through the SAME bounded cut, so a
92
+ * long caller-supplied session id (the CLI passes `--session` through) is never cut mid-id either
93
+ * (Copilot on #525): the body names the run id in full.
94
+ */
95
+ export declare function deliverTitle(intent: string, runId: string): string;
96
+ /**
97
+ * The issues the intent names, split into the ones it says it fixes and the rest.
98
+ *
99
+ * GitHub links and closes on `#N` (this repo) and `owner/repo#N` only. An OWNER-LESS `repo#N`
100
+ * does neither — so when its repo segment names the delivery repo (`repoRef`, the registered
101
+ * repo id the PR lands in) it is emitted as plain `#N` (review W3-K2: `fixes wicked-studio#214`
102
+ * on a wicked-studio delivery must close #214). Any other owner-less `repo#N` rides verbatim as
103
+ * information; `owner/repo#N` is left exactly as written.
104
+ */
105
+ export declare function issueRefs(intent: string, repoRef?: string | null): IssueRefs;
106
+ /**
107
+ * How much of the intent the deliver SCRIPT carries in its embedded fallback text. The script is
108
+ * one `bash -lc` argument, and `LaunchSchema.problem` has no length cap, so an unbounded intent
109
+ * could exceed a platform's single-argument limit (Linux: 128 KiB) and fail the phase with E2BIG
110
+ * before it runs (Copilot on #525). The run-derived text the daemon answers is NOT bounded — it
111
+ * travels over HTTP, never through argv.
112
+ */
113
+ export declare const EMBEDDED_INTENT_CAP = 8000;
114
+ /** `intent` bounded for embedding in the script: whole when it fits, else cut and said so. */
115
+ export declare function boundIntentForEmbedding(intent: string): string;
116
+ /**
117
+ * The launch-time FALLBACK text the deliver script embeds (crew#524; wave-3 isolation review): the
118
+ * intent rides BOUNDED ({@link boundIntentForEmbedding} — the script is one argv entry) but the
119
+ * issue references are derived from the FULL intent FIRST, so a `fixes #214` that sits past the
120
+ * {@link EMBEDDED_INTENT_CAP} still reaches the body as `Fixes #214` — the line GitHub acts on —
121
+ * when no daemon answers `GET /runs/:id/deliver-text`. The title is the intent's first line either
122
+ * way. The cut copy carries the "longer than the script embeds" note, so the omission is disclosed
123
+ * and the reference is not.
124
+ */
125
+ export declare function composeEmbeddedDeliverText(f: DeliverTextFacts): DeliverText;
126
+ /**
127
+ * The PR title + body (and, through {@link framedDeliverText}, the commit message) for a run.
128
+ * Never empty: every section either carries the recorded facts or says why it does not.
129
+ *
130
+ * `links` defaults to the issue references of `f.intent`; the embedded-fallback path passes the
131
+ * references of the FULL intent while `f.intent` is the bounded copy ({@link composeEmbeddedDeliverText}).
132
+ */
133
+ export declare function composeDeliverText(f: DeliverTextFacts, links?: IssueRefs): DeliverText;
134
+ /** The one shape both carriers speak: title, blank line, body, trailing newline. */
135
+ export declare function framedDeliverText(text: DeliverText): string;
136
+ /**
137
+ * The inverse of {@link framedDeliverText}, or `null` when the text is not framed that way — a
138
+ * non-empty title line, a blank line 2, and a body with something in it (the same three conditions
139
+ * the deliver script's `_framed` check applies before it accepts a daemon answer).
140
+ */
141
+ export declare function parseFramedDeliverText(framed: string): DeliverText | null;
142
+ /** A `GateSpec` (or the engine's loose string form) as a short label. */
143
+ export declare function gateLabel(gate: GateSpec | string | undefined): string;
144
+ /**
145
+ * A composed per-run workflow id (`<base>-deliver-<run id>`, `<base>-verified-<run id>`; see
146
+ * `composeDeliverWorkflow` / `composeDeliverableFloor`) reads as its base. The composed id is
147
+ * capped at 128 characters, so for a long caller-supplied run id the marker's tail is CUT — the
148
+ * tail is therefore matched as a prefix of the sanitised run id, not whole.
149
+ */
150
+ export declare function baseWorkflowId(workflowId: string, runId: string): string;
151
+ /**
152
+ * The facts from a persisted run view — what the daemon answers on `GET /runs/:id/deliver-text`.
153
+ * The deliver phase itself (running while it asks) is listed as `this PR`.
154
+ *
155
+ * `resolved.workflowId` is the DEFINITION the route resolved for the run (`resolveRunWorkflow`
156
+ * over the full registry): the engine stores an instance id (`wf-<uuid>`) that `sessionsDetail()`
157
+ * patches back to a name for BUILT-INS only, so a user-registered workflow would otherwise read as
158
+ * `workflow wf-…` here. Absent, the view's id is used (with the per-run composition suffix cut).
159
+ */
160
+ export declare function factsFromRun(view: SessionView, runUrl: string | null, resolved?: {
161
+ workflowId?: string | null;
162
+ }): DeliverTextFacts;
163
+ /** What is known at LAUNCH, from the workflow definition — the script's embedded fallback. */
164
+ export declare function factsFromWorkflow(input: {
165
+ runId: string;
166
+ intent: string | undefined;
167
+ workflowId: string | null;
168
+ repoRef: string | null;
169
+ phases: PhaseDef[];
170
+ runUrl: string | null;
171
+ }): DeliverTextFacts;
172
+ /**
173
+ * `s` as ONE URL path segment, RFC 3986 strict: everything but unreserved characters is
174
+ * percent-encoded — `encodeURIComponent` alone leaves `!'()*` alone, and `'` in particular must not
175
+ * reach a single-quoted shell literal (the deliver script bakes this in; Copilot on #525).
176
+ */
177
+ export declare function urlPathSegment(s: string): string;
178
+ /**
179
+ * The studio bookmark for a run under a daemon origin (`http://127.0.0.1:7701/runs/<id>`), or
180
+ * null. LOOPBACK ORIGINS ONLY (review W3-K4): a daemon bound to a LAN host or IP would otherwise
181
+ * put that host into a public PR body; the run id itself is always named in the text.
182
+ */
183
+ export declare function runUrlFor(origin: string | null | undefined, runId: string): string | null;
184
+ //# sourceMappingURL=deliver-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deliver-text.d.ts","sourceRoot":"","sources":["../../src/core/deliver-text.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,434 @@
1
+ /**
2
+ * The deliver phase's PR + commit TEXT (crew#524, acceptance finding F-3R2-014).
3
+ *
4
+ * `gh pr create --fill` opened wicked-studio#249 with a title cut MID-WORD out of the intent's first
5
+ * 72 characters (`…scenario CLN-2) aga`) and an EMPTY body: no `Fixes #214`, no run link, no record
6
+ * of what ran or what passed — and the commit carried the same truncated headline. A reviewer got
7
+ * nothing to review against. This module composes the text from the RUN instead. ONE composer, two
8
+ * moments it can be asked:
9
+ *
10
+ * - at DELIVERY, from the persisted run view (`GET /runs/:id/deliver-text`, text/plain): every
11
+ * phase the run went through with its seat and gate outcome, the repo checks the verify phase
12
+ * ran with their exit codes, the evaluator's verdict, and a link to the run;
13
+ * - at LAUNCH, from the workflow definition — the fallback the deliver script carries in case the
14
+ * daemon cannot answer when the PR opens (an auth-required daemon, no `curl`, a daemon that went
15
+ * away): the intent, the issue links, the run id and the phase list ARE known then; the runtime
16
+ * sections say plainly that they were not available rather than pretending.
17
+ *
18
+ * The title is the intent's first line, cut at a WORD boundary within {@link DELIVER_TITLE_MAX}
19
+ * characters (never mid-word), or `wicked-crew run <id>` when the intent is blank. `Fixes #N` is
20
+ * emitted when the intent names an issue with a closing verb (`fix issue #214`, `closes #7`); every
21
+ * other `#N` / `repo#N` / `owner/repo#N` mention rides as `Refs:`.
22
+ *
23
+ * FRAMING, shared by both carriers (the daemon's text/plain answer and the script's embedded
24
+ * fallback) so the script parses exactly one shape: line 1 = title, line 2 = blank, then the body.
25
+ * The framed text is also, verbatim, the message of the commit the deliver phase MAKES when the
26
+ * run left uncommitted work (`git commit -F`: git takes the first paragraph as the subject). A run
27
+ * that committed incrementally keeps its own commits untouched — the PR title is composed from the
28
+ * run either way; only the deliver phase's own commit is guaranteed to match it.
29
+ */
30
+ /** The PR title / commit subject cap — git's conventional subject width. */
31
+ export const DELIVER_TITLE_MAX = 72;
32
+ // ── the title ──────────────────────────────────────────────────────────────────────────────────
33
+ /** Control characters other than newline/tab — never part of a title, a table cell or a commit. */
34
+ const CONTROL_CHARS = /[\u0000-\u0008\u000b-\u001f\u007f]/g;
35
+ /** EVERY control character, newline and tab included — for values that must stay on one line. */
36
+ const ALL_CONTROL_CHARS = /[\u0000-\u001f\u007f]/g;
37
+ /** `s` as one line: control characters (newlines included) become spaces, runs collapse, ends trim. */
38
+ function oneLine(s) {
39
+ return s.replace(ALL_CONTROL_CHARS, ' ').replace(/\s+/g, ' ').trim();
40
+ }
41
+ /** One line of intent reduced to plain words: markdown markers and links stripped, spaces collapsed. */
42
+ function plainLine(raw) {
43
+ return raw
44
+ .replace(CONTROL_CHARS, ' ')
45
+ .replace(/^\s*(?:#{1,6}\s+|[-*+]\s+|>\s+|\d+\.\s+)/, '') // heading / list / quote markers
46
+ .replace(/\[([^\]]+)\]\([^)]*\)/g, '$1') // [text](url) → text
47
+ .replace(/\*\*|__|`/g, '') // strong / code markers
48
+ // Paired single-marker emphasis (`*fix*`, `_fix_`), guarded by word boundaries so an identifier
49
+ // like `snake_case_name` or a bare `a * b` is left alone.
50
+ .replace(/(^|[^\w*])\*([^*\s][^*]*?)\*(?![\w*])/g, '$1$2')
51
+ .replace(/(^|[^\w_])_([^_\s][^_]*?)_(?![\w_])/g, '$1$2')
52
+ .replace(/\s+/g, ' ')
53
+ .trim();
54
+ }
55
+ /** The intent's first non-blank line as plain words, or `''`. */
56
+ function firstLine(intent) {
57
+ for (const raw of intent.split(/\r?\n/)) {
58
+ const line = plainLine(raw);
59
+ if (line !== '')
60
+ return line;
61
+ }
62
+ return '';
63
+ }
64
+ /**
65
+ * The PR title / commit subject: the intent's first line, whole when it fits, otherwise cut at the
66
+ * last word boundary that leaves room for a single `…` — so the result is ≤ 72 characters and never
67
+ * ends mid-word (the F-3R2-014 headline `…scenario CLN-2) aga`). Dangling punctuation before the
68
+ * ellipsis is dropped. A blank intent names the run instead — through the SAME bounded cut, so a
69
+ * long caller-supplied session id (the CLI passes `--session` through) is never cut mid-id either
70
+ * (Copilot on #525): the body names the run id in full.
71
+ */
72
+ export function deliverTitle(intent, runId) {
73
+ const line = firstLine(intent);
74
+ // The run id is caller-supplied too (`LaunchSchema` only requires it non-empty): a newline in it
75
+ // must not turn the title into two lines and break the framing (Copilot on #525).
76
+ return boundedTitle(line === '' ? oneLine(`wicked-crew run ${oneLine(runId)}`) : line);
77
+ }
78
+ /** `line` whole when it fits, else cut at a word boundary with a single `…` — ≤ 72 characters. */
79
+ function boundedTitle(line) {
80
+ if (line.length <= DELIVER_TITLE_MAX)
81
+ return line;
82
+ const room = DELIVER_TITLE_MAX - 1; // one character is the ellipsis
83
+ const head = line.slice(0, room + 1); // one past the room: a space HERE means the room ends a word
84
+ const cut = head.lastIndexOf(' ');
85
+ // A single 72+ character token has no boundary to cut at; then — and only then — it is cut hard.
86
+ const kept = (cut > 0 ? head.slice(0, cut) : head.slice(0, room)).replace(/[\s,;:(\-–—]+$/u, '');
87
+ return `${kept}…`;
88
+ }
89
+ // ── issue references ───────────────────────────────────────────────────────────────────────────
90
+ /** `fix issue #214`, `fixes #7`, `closes wicked-studio#3`, `resolved: #9` — a closing verb + a ref. */
91
+ const CLOSING_REF = /\b(?:fix(?:es|ed)?|close[sd]?|resolve[sd]?)\b(?:\s+(?:issue|bug|for))?\s*:?\s*((?:[\w.-]+\/)?[\w.-]+)?#(\d+)\b/gi;
92
+ /** Any `#N`, `repo#N` or `owner/repo#N` not glued to a word/path (so `a/b#1` is one ref, `#1a` none). */
93
+ const ANY_REF = /(?<![\w/#])((?:[\w.-]+\/)?[\w.-]+)?#(\d+)\b/g;
94
+ /**
95
+ * The issues the intent names, split into the ones it says it fixes and the rest.
96
+ *
97
+ * GitHub links and closes on `#N` (this repo) and `owner/repo#N` only. An OWNER-LESS `repo#N`
98
+ * does neither — so when its repo segment names the delivery repo (`repoRef`, the registered
99
+ * repo id the PR lands in) it is emitted as plain `#N` (review W3-K2: `fixes wicked-studio#214`
100
+ * on a wicked-studio delivery must close #214). Any other owner-less `repo#N` rides verbatim as
101
+ * information; `owner/repo#N` is left exactly as written.
102
+ */
103
+ export function issueRefs(intent, repoRef) {
104
+ const normalize = (prefix, n) => {
105
+ if (prefix === undefined || prefix === '')
106
+ return `#${n}`;
107
+ if (!prefix.includes('/') && repoRef !== undefined && repoRef !== null && prefix === repoRef)
108
+ return `#${n}`;
109
+ return `${prefix}#${n}`;
110
+ };
111
+ const fixes = [];
112
+ const refs = [];
113
+ for (const m of intent.matchAll(CLOSING_REF)) {
114
+ const ref = normalize(m[1], m[2]);
115
+ if (!fixes.includes(ref))
116
+ fixes.push(ref);
117
+ }
118
+ for (const m of intent.matchAll(ANY_REF)) {
119
+ const ref = normalize(m[1], m[2]);
120
+ if (!fixes.includes(ref) && !refs.includes(ref))
121
+ refs.push(ref);
122
+ }
123
+ return { fixes, refs };
124
+ }
125
+ /**
126
+ * How much of the intent the deliver SCRIPT carries in its embedded fallback text. The script is
127
+ * one `bash -lc` argument, and `LaunchSchema.problem` has no length cap, so an unbounded intent
128
+ * could exceed a platform's single-argument limit (Linux: 128 KiB) and fail the phase with E2BIG
129
+ * before it runs (Copilot on #525). The run-derived text the daemon answers is NOT bounded — it
130
+ * travels over HTTP, never through argv.
131
+ */
132
+ export const EMBEDDED_INTENT_CAP = 8_000;
133
+ const EMBEDDED_INTENT_NOTE = '_(the intent is longer than the deliver script embeds — the full text is on the run record)_';
134
+ /** `intent` bounded for embedding in the script: whole when it fits, else cut and said so. */
135
+ export function boundIntentForEmbedding(intent) {
136
+ if (intent.length <= EMBEDDED_INTENT_CAP)
137
+ return intent;
138
+ return `${intent.slice(0, EMBEDDED_INTENT_CAP).trimEnd()}\n\n${EMBEDDED_INTENT_NOTE}`;
139
+ }
140
+ /**
141
+ * The launch-time FALLBACK text the deliver script embeds (crew#524; wave-3 isolation review): the
142
+ * intent rides BOUNDED ({@link boundIntentForEmbedding} — the script is one argv entry) but the
143
+ * issue references are derived from the FULL intent FIRST, so a `fixes #214` that sits past the
144
+ * {@link EMBEDDED_INTENT_CAP} still reaches the body as `Fixes #214` — the line GitHub acts on —
145
+ * when no daemon answers `GET /runs/:id/deliver-text`. The title is the intent's first line either
146
+ * way. The cut copy carries the "longer than the script embeds" note, so the omission is disclosed
147
+ * and the reference is not.
148
+ */
149
+ export function composeEmbeddedDeliverText(f) {
150
+ return composeDeliverText({ ...f, intent: boundIntentForEmbedding(f.intent) }, issueRefs(f.intent, f.repoRef));
151
+ }
152
+ // ── the body ───────────────────────────────────────────────────────────────────────────────────
153
+ /** A markdown table cell: control characters out, pipes escaped, bounded. */
154
+ function cell(value, max = 200) {
155
+ if (value === null || value === undefined || value === '')
156
+ return '—';
157
+ const s = String(value).replace(CONTROL_CHARS, ' ').replace(/\s+/g, ' ').trim().replace(/\|/g, '\\|');
158
+ return s.length <= max ? s : `${s.slice(0, max - 1)}…`;
159
+ }
160
+ function code(value) {
161
+ if (value === null || value === undefined || value === '')
162
+ return '—';
163
+ // One line (a code span cannot span lines); backticks inside a code span would end it early, so
164
+ // they are dropped; pipes are escaped for the table cells this lands in.
165
+ const one = oneLine(value).replace(/`/g, '').replace(/\|/g, '\\|');
166
+ return one === '' ? '—' : `\`${one}\``;
167
+ }
168
+ function duration(ms) {
169
+ if (ms === null || !Number.isFinite(ms))
170
+ return '—';
171
+ return ms < 1000 ? `${Math.round(ms)}ms` : `${(ms / 1000).toFixed(1)}s`;
172
+ }
173
+ function exitLabel(c) {
174
+ if (c.exitCode !== null)
175
+ return String(c.exitCode);
176
+ if (c.timedOut)
177
+ return 'timed out';
178
+ if (c.spawnError !== null && c.spawnError !== '')
179
+ return `spawn error: ${c.spawnError}`;
180
+ return '—';
181
+ }
182
+ /** The product site — never a repo owner handle (crew bakes no account name into a script). */
183
+ const FOOTER_LINK = '[wicked-crew](https://wc.wickedagile.com)';
184
+ /**
185
+ * The PR title + body (and, through {@link framedDeliverText}, the commit message) for a run.
186
+ * Never empty: every section either carries the recorded facts or says why it does not.
187
+ *
188
+ * `links` defaults to the issue references of `f.intent`; the embedded-fallback path passes the
189
+ * references of the FULL intent while `f.intent` is the bounded copy ({@link composeEmbeddedDeliverText}).
190
+ */
191
+ export function composeDeliverText(f, links = issueRefs(f.intent, f.repoRef)) {
192
+ const title = deliverTitle(f.intent, f.runId);
193
+ const { fixes, refs } = links;
194
+ const intent = f.intent.replace(/\r\n?/g, '\n').replace(CONTROL_CHARS, ' ').trim();
195
+ const out = [];
196
+ out.push('## Intent', '', intent === '' ? '_(the run recorded no intent)_' : intent, '');
197
+ if (fixes.length > 0 || refs.length > 0) {
198
+ for (const x of fixes)
199
+ out.push(`Fixes ${x}`);
200
+ if (refs.length > 0)
201
+ out.push(`Refs: ${refs.join(', ')}`);
202
+ out.push('');
203
+ }
204
+ out.push('## Run', '');
205
+ // The label is the same one-line code span as the unlinked form — a caller-supplied id cannot
206
+ // break the line or the Markdown (the URL half is `urlPathSegment`-encoded by `runUrlFor`).
207
+ out.push(f.runUrl !== null ? `- Run: [${code(f.runId)}](${f.runUrl})` : `- Run: ${code(f.runId)}`);
208
+ const where = [
209
+ f.workflowId !== null && f.workflowId !== '' ? `workflow ${code(f.workflowId)}` : null,
210
+ f.repoRef !== null && f.repoRef !== '' ? `repo ${code(f.repoRef)}` : null,
211
+ ].filter((s) => s !== null);
212
+ if (where.length > 0)
213
+ out.push(`- ${where.join(' · ')}`);
214
+ out.push('');
215
+ out.push('## Phases', '');
216
+ if (f.source === 'workflow') {
217
+ out.push('_From the workflow definition at launch — the daemon could not be asked for the run record ' +
218
+ 'when this PR opened, so seats and gate outcomes are not shown. Every phase before `deliver` ' +
219
+ 'had passed its gate for the deliver phase to run._', '');
220
+ }
221
+ if (f.phases.length === 0) {
222
+ out.push('_(no phases recorded)_');
223
+ }
224
+ else {
225
+ out.push('| phase | stage | role | seat | gate | outcome |', '|---|---|---|---|---|---|');
226
+ for (const p of f.phases) {
227
+ out.push(`| ${code(p.id)} | ${cell(p.stage)} | ${cell(p.role)} | ${cell(p.seat)} | ${cell(p.gate)} | ${cell(p.outcome)} |`);
228
+ }
229
+ }
230
+ out.push('');
231
+ out.push('## Repo checks', '');
232
+ if (f.source === 'workflow') {
233
+ out.push('_Not available at composition time — the run record has them._');
234
+ }
235
+ else if (f.checks === null || f.checks.length === 0) {
236
+ out.push('_The run recorded no repo checks (no `typecheck` / `lint` / `test` script was found, or the ' +
237
+ 'workflow has no verify phase)._');
238
+ }
239
+ else {
240
+ out.push('| check | command | exit | duration |', '|---|---|---|---|');
241
+ for (const c of f.checks) {
242
+ out.push(`| ${cell(c.name)} | ${code(c.command)} | ${cell(exitLabel(c))} | ${duration(c.durationMs)} |`);
243
+ }
244
+ }
245
+ out.push('');
246
+ out.push('## Evaluator verdict', '');
247
+ if (f.source === 'workflow') {
248
+ out.push('_Not available at composition time — the run record has it._');
249
+ }
250
+ else if (f.verdicts.length === 0) {
251
+ out.push('_This workflow has no evaluator phase._');
252
+ }
253
+ else {
254
+ for (const v of f.verdicts) {
255
+ const reason = v.reason !== null && v.reason.trim() !== '' ? ` — ${cell(v.reason, 400)}` : '';
256
+ out.push(`- ${code(v.phase)} (${cell(v.seat ?? 'seat unknown')}): **${cell(v.verdict)}**${reason}`);
257
+ }
258
+ }
259
+ out.push('');
260
+ out.push('---', '', `Delivered by ${FOOTER_LINK} run ${code(f.runId)}. Merge stays human: the phase opens the PR, never merges it.`);
261
+ return { title, body: out.join('\n') };
262
+ }
263
+ /** The one shape both carriers speak: title, blank line, body, trailing newline. */
264
+ export function framedDeliverText(text) {
265
+ return `${text.title}\n\n${text.body}\n`;
266
+ }
267
+ /**
268
+ * The inverse of {@link framedDeliverText}, or `null` when the text is not framed that way — a
269
+ * non-empty title line, a blank line 2, and a body with something in it (the same three conditions
270
+ * the deliver script's `_framed` check applies before it accepts a daemon answer).
271
+ */
272
+ export function parseFramedDeliverText(framed) {
273
+ const lines = framed.split('\n');
274
+ if (lines.length < 3 || lines[0].trim() === '' || lines[1] !== '')
275
+ return null;
276
+ const body = lines.slice(2).join('\n').replace(/\n$/, '');
277
+ if (body.trim() === '')
278
+ return null;
279
+ return { title: lines[0], body };
280
+ }
281
+ // ── facts ──────────────────────────────────────────────────────────────────────────────────────
282
+ /** A `GateSpec` (or the engine's loose string form) as a short label. */
283
+ export function gateLabel(gate) {
284
+ if (gate === undefined || gate === null)
285
+ return '—';
286
+ if (typeof gate === 'string')
287
+ return gate;
288
+ if ('human_confirm_if' in gate)
289
+ return `human if ${gate.human_confirm_if.replace(/_/g, ' ')}`;
290
+ if ('human_confirm' in gate)
291
+ return gate.human_confirm.unconditional ? 'human' : 'human (conditional)';
292
+ return '—';
293
+ }
294
+ /** `<run id>:<phase>` → `<phase>`; anything else is returned whole. */
295
+ function phaseIdOf(unit) {
296
+ const prefix = `${unit.session_id}:`;
297
+ return unit.id.startsWith(prefix) ? unit.id.slice(prefix.length) : unit.id;
298
+ }
299
+ function seatOf(unit) {
300
+ if (unit.routing?.method === 'tool')
301
+ return 'tool';
302
+ if (unit.assigned_cli !== null && unit.assigned_cli !== '')
303
+ return unit.assigned_cli;
304
+ const r = unit.routing;
305
+ if (r !== null && r !== undefined && 'winner' in r)
306
+ return r.winner;
307
+ return null;
308
+ }
309
+ function checksOf(unit) {
310
+ const rc = unit.repo_checks;
311
+ if (rc === null || rc === undefined || !Array.isArray(rc.checks))
312
+ return [];
313
+ return rc.checks.map((c) => ({
314
+ name: c.name ?? '—',
315
+ command: Array.isArray(c.argv) ? c.argv.join(' ') : '—',
316
+ exitCode: typeof c.exit_code === 'number' ? c.exit_code : null,
317
+ durationMs: typeof c.duration_ms === 'number' ? c.duration_ms : null,
318
+ timedOut: c.timed_out === true,
319
+ spawnError: typeof c.spawn_error === 'string' ? c.spawn_error : null,
320
+ }));
321
+ }
322
+ /**
323
+ * A composed per-run workflow id (`<base>-deliver-<run id>`, `<base>-verified-<run id>`; see
324
+ * `composeDeliverWorkflow` / `composeDeliverableFloor`) reads as its base. The composed id is
325
+ * capped at 128 characters, so for a long caller-supplied run id the marker's tail is CUT — the
326
+ * tail is therefore matched as a prefix of the sanitised run id, not whole.
327
+ */
328
+ export function baseWorkflowId(workflowId, runId) {
329
+ const safeRunId = runId.replace(/[^a-zA-Z0-9._-]/g, '_');
330
+ let id = workflowId;
331
+ for (const marker of ['-deliver-', '-verified-']) {
332
+ const at = id.indexOf(marker);
333
+ if (at > 0 && safeRunId.startsWith(id.slice(at + marker.length)))
334
+ id = id.slice(0, at);
335
+ }
336
+ return id;
337
+ }
338
+ /**
339
+ * The facts from a persisted run view — what the daemon answers on `GET /runs/:id/deliver-text`.
340
+ * The deliver phase itself (running while it asks) is listed as `this PR`.
341
+ *
342
+ * `resolved.workflowId` is the DEFINITION the route resolved for the run (`resolveRunWorkflow`
343
+ * over the full registry): the engine stores an instance id (`wf-<uuid>`) that `sessionsDetail()`
344
+ * patches back to a name for BUILT-INS only, so a user-registered workflow would otherwise read as
345
+ * `workflow wf-…` here. Absent, the view's id is used (with the per-run composition suffix cut).
346
+ */
347
+ export function factsFromRun(view, runUrl, resolved = {}) {
348
+ const s = view.session;
349
+ const units = [...view.units].sort((a, b) => a.ord - b.ord);
350
+ const checks = units.flatMap(checksOf);
351
+ return {
352
+ runId: s.id,
353
+ intent: s.problem ?? '',
354
+ workflowId: resolved.workflowId ?? baseWorkflowId(s.workflow_id, s.id),
355
+ repoRef: s.repo_ref,
356
+ runUrl,
357
+ source: 'run',
358
+ phases: units.map((u) => {
359
+ const id = phaseIdOf(u);
360
+ const running = u.status === 'pending' || u.status === 'distributed'; // not yet done: it is asking
361
+ return {
362
+ id,
363
+ stage: u.stage,
364
+ role: u.role ?? 'neutral',
365
+ gate: gateLabel(u.gate),
366
+ seat: seatOf(u),
367
+ outcome: id === 'deliver' && running ? 'this PR' : (u.phase_status ?? u.status),
368
+ };
369
+ }),
370
+ checks: checks.length > 0 ? checks : null,
371
+ verdicts: units
372
+ .filter((u) => u.role === 'evaluator')
373
+ .map((u) => ({
374
+ phase: phaseIdOf(u),
375
+ seat: seatOf(u),
376
+ verdict: u.phase_status ?? u.status,
377
+ reason: u.denial_reason,
378
+ })),
379
+ };
380
+ }
381
+ /** What is known at LAUNCH, from the workflow definition — the script's embedded fallback. */
382
+ export function factsFromWorkflow(input) {
383
+ return {
384
+ runId: input.runId,
385
+ intent: input.intent ?? '',
386
+ workflowId: input.workflowId,
387
+ repoRef: input.repoRef,
388
+ runUrl: input.runUrl,
389
+ source: 'workflow',
390
+ phases: input.phases.map((p) => ({
391
+ id: p.id,
392
+ stage: p.kind,
393
+ role: p.role,
394
+ gate: gateLabel(p.gate),
395
+ seat: p.executor?.type === 'tool' ? 'tool' : null,
396
+ outcome: '—',
397
+ })),
398
+ checks: null,
399
+ verdicts: [],
400
+ };
401
+ }
402
+ /**
403
+ * `s` as ONE URL path segment, RFC 3986 strict: everything but unreserved characters is
404
+ * percent-encoded — `encodeURIComponent` alone leaves `!'()*` alone, and `'` in particular must not
405
+ * reach a single-quoted shell literal (the deliver script bakes this in; Copilot on #525).
406
+ */
407
+ export function urlPathSegment(s) {
408
+ return encodeURIComponent(s).replace(/[!'()*]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
409
+ }
410
+ /** Is `host` (as `URL.hostname` spells it) the local machine — `127.0.0.0/8`, `::1`, `localhost`? */
411
+ function isLoopbackHost(host) {
412
+ const h = host.replace(/^\[|\]$/g, '').toLowerCase();
413
+ return h === 'localhost' || h === '::1' || /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(h);
414
+ }
415
+ /**
416
+ * The studio bookmark for a run under a daemon origin (`http://127.0.0.1:7701/runs/<id>`), or
417
+ * null. LOOPBACK ORIGINS ONLY (review W3-K4): a daemon bound to a LAN host or IP would otherwise
418
+ * put that host into a public PR body; the run id itself is always named in the text.
419
+ */
420
+ export function runUrlFor(origin, runId) {
421
+ if (origin === null || origin === undefined || origin === '')
422
+ return null;
423
+ let host;
424
+ try {
425
+ host = new URL(origin).hostname;
426
+ }
427
+ catch {
428
+ return null;
429
+ }
430
+ if (!isLoopbackHost(host))
431
+ return null;
432
+ return `${origin.replace(/\/+$/, '')}/runs/${urlPathSegment(runId)}`;
433
+ }
434
+ //# sourceMappingURL=deliver-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deliver-text.js","sourceRoot":"","sources":["../../src/core/deliver-text.ts"],"names":[],"mappings":"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"}