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.
- package/dist/api/audit.d.ts +70 -0
- package/dist/api/audit.d.ts.map +1 -0
- package/dist/api/audit.js +131 -0
- package/dist/api/audit.js.map +1 -0
- package/dist/api/auth.d.ts +192 -0
- package/dist/api/auth.d.ts.map +1 -0
- package/dist/api/auth.js +515 -0
- package/dist/api/auth.js.map +1 -0
- package/dist/api/gate-cache.d.ts +8 -0
- package/dist/api/gate-cache.d.ts.map +1 -1
- package/dist/api/gate-cache.js +10 -0
- package/dist/api/gate-cache.js.map +1 -1
- package/dist/api/guidance-index.d.ts +39 -0
- package/dist/api/guidance-index.d.ts.map +1 -0
- package/dist/api/guidance-index.js +67 -0
- package/dist/api/guidance-index.js.map +1 -0
- package/dist/api/open-path.d.ts +34 -0
- package/dist/api/open-path.d.ts.map +1 -0
- package/dist/api/open-path.js +101 -0
- package/dist/api/open-path.js.map +1 -0
- package/dist/api/retry-index.d.ts +30 -0
- package/dist/api/retry-index.d.ts.map +1 -0
- package/dist/api/retry-index.js +45 -0
- package/dist/api/retry-index.js.map +1 -0
- package/dist/api/routes.d.ts +164 -1
- package/dist/api/routes.d.ts.map +1 -1
- package/dist/api/routes.js +769 -21
- package/dist/api/routes.js.map +1 -1
- package/dist/api/run-files.d.ts +63 -0
- package/dist/api/run-files.d.ts.map +1 -0
- package/dist/api/run-files.js +271 -0
- package/dist/api/run-files.js.map +1 -0
- package/dist/api/seat-health.d.ts +55 -0
- package/dist/api/seat-health.d.ts.map +1 -0
- package/dist/api/seat-health.js +273 -0
- package/dist/api/seat-health.js.map +1 -0
- package/dist/api/seat-signin.d.ts +27 -0
- package/dist/api/seat-signin.d.ts.map +1 -0
- package/dist/api/seat-signin.js +143 -0
- package/dist/api/seat-signin.js.map +1 -0
- package/dist/api/server.d.ts +190 -3
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +365 -11
- package/dist/api/server.js.map +1 -1
- package/dist/api/stall-watchdog.d.ts +62 -0
- package/dist/api/stall-watchdog.d.ts.map +1 -0
- package/dist/api/stall-watchdog.js +138 -0
- package/dist/api/stall-watchdog.js.map +1 -0
- package/dist/cli/index.js +171 -12
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp.d.ts +14 -0
- package/dist/cli/mcp.d.ts.map +1 -0
- package/dist/cli/mcp.js +119 -0
- package/dist/cli/mcp.js.map +1 -0
- package/dist/core/adapter.d.ts +87 -10
- package/dist/core/adapter.d.ts.map +1 -1
- package/dist/core/adapter.js +347 -28
- package/dist/core/adapter.js.map +1 -1
- package/dist/core/bridge-reaper.d.ts +134 -0
- package/dist/core/bridge-reaper.d.ts.map +1 -0
- package/dist/core/bridge-reaper.js +286 -0
- package/dist/core/bridge-reaper.js.map +1 -0
- package/dist/core/deliver.d.ts +118 -0
- package/dist/core/deliver.d.ts.map +1 -0
- package/dist/core/deliver.js +241 -0
- package/dist/core/deliver.js.map +1 -0
- package/dist/core/deliverable-floor.d.ts +103 -0
- package/dist/core/deliverable-floor.d.ts.map +1 -0
- package/dist/core/deliverable-floor.js +173 -0
- package/dist/core/deliverable-floor.js.map +1 -0
- package/dist/core/exec.d.ts +2 -0
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js.map +1 -1
- package/dist/core/types.d.ts +92 -352
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +14 -4
- package/dist/core/types.js.map +1 -1
- package/dist/interactive/bridge-pool.d.ts +99 -0
- package/dist/interactive/bridge-pool.d.ts.map +1 -0
- package/dist/interactive/bridge-pool.js +244 -0
- package/dist/interactive/bridge-pool.js.map +1 -0
- package/dist/interactive/bridge-root.d.ts +36 -0
- package/dist/interactive/bridge-root.d.ts.map +1 -0
- package/dist/interactive/bridge-root.js +48 -0
- package/dist/interactive/bridge-root.js.map +1 -0
- package/dist/interactive/chat-events.d.ts +207 -0
- package/dist/interactive/chat-events.d.ts.map +1 -0
- package/dist/interactive/chat-events.js +769 -0
- package/dist/interactive/chat-events.js.map +1 -0
- package/dist/interactive/demo-events.d.ts +283 -0
- package/dist/interactive/demo-events.d.ts.map +1 -0
- package/dist/interactive/demo-events.js +889 -0
- package/dist/interactive/demo-events.js.map +1 -0
- package/dist/interactive/draft-events.d.ts +224 -0
- package/dist/interactive/draft-events.d.ts.map +1 -0
- package/dist/interactive/draft-events.js +793 -0
- package/dist/interactive/draft-events.js.map +1 -0
- package/dist/interactive/edit-events.d.ts +194 -0
- package/dist/interactive/edit-events.d.ts.map +1 -0
- package/dist/interactive/edit-events.js +601 -0
- package/dist/interactive/edit-events.js.map +1 -0
- package/dist/interactive/ledger.d.ts +39 -0
- package/dist/interactive/ledger.d.ts.map +1 -0
- package/dist/interactive/ledger.js +93 -0
- package/dist/interactive/ledger.js.map +1 -0
- package/dist/interactive/proxy-routes.d.ts +39 -0
- package/dist/interactive/proxy-routes.d.ts.map +1 -0
- package/dist/interactive/proxy-routes.js +189 -0
- package/dist/interactive/proxy-routes.js.map +1 -0
- package/dist/interactive/repo-snapshot.d.ts +100 -0
- package/dist/interactive/repo-snapshot.d.ts.map +1 -0
- package/dist/interactive/repo-snapshot.js +289 -0
- package/dist/interactive/repo-snapshot.js.map +1 -0
- package/dist/interactive/ws-relay.d.ts +85 -0
- package/dist/interactive/ws-relay.d.ts.map +1 -0
- package/dist/interactive/ws-relay.js +191 -0
- package/dist/interactive/ws-relay.js.map +1 -0
- package/dist/projects/activity.d.ts +29 -0
- package/dist/projects/activity.d.ts.map +1 -0
- package/dist/projects/activity.js +172 -0
- package/dist/projects/activity.js.map +1 -0
- package/dist/projects/charter.d.ts +28 -0
- package/dist/projects/charter.d.ts.map +1 -0
- package/dist/projects/charter.js +53 -0
- package/dist/projects/charter.js.map +1 -0
- package/dist/projects/events.d.ts +55 -0
- package/dist/projects/events.d.ts.map +1 -0
- package/dist/projects/events.js +141 -0
- package/dist/projects/events.js.map +1 -0
- package/dist/projects/graph-paths.d.ts +92 -0
- package/dist/projects/graph-paths.d.ts.map +1 -0
- package/dist/projects/graph-paths.js +130 -0
- package/dist/projects/graph-paths.js.map +1 -0
- package/dist/projects/graph.d.ts +179 -0
- package/dist/projects/graph.d.ts.map +1 -0
- package/dist/projects/graph.js +775 -0
- package/dist/projects/graph.js.map +1 -0
- package/dist/projects/membership-index.d.ts +25 -0
- package/dist/projects/membership-index.d.ts.map +1 -0
- package/dist/projects/membership-index.js +46 -0
- package/dist/projects/membership-index.js.map +1 -0
- package/dist/projects/routes.d.ts +97 -0
- package/dist/projects/routes.d.ts.map +1 -0
- package/dist/projects/routes.js +510 -0
- package/dist/projects/routes.js.map +1 -0
- package/dist/projects/settings.d.ts +32 -0
- package/dist/projects/settings.d.ts.map +1 -0
- package/dist/projects/settings.js +64 -0
- package/dist/projects/settings.js.map +1 -0
- package/dist/qe/acceptance.d.ts +137 -0
- package/dist/qe/acceptance.d.ts.map +1 -0
- package/dist/qe/acceptance.js +249 -0
- package/dist/qe/acceptance.js.map +1 -0
- package/dist/qe/gate-events.d.ts +111 -0
- package/dist/qe/gate-events.d.ts.map +1 -0
- package/dist/qe/gate-events.js +168 -0
- package/dist/qe/gate-events.js.map +1 -0
- package/dist/qe/ledger.d.ts +100 -0
- package/dist/qe/ledger.d.ts.map +1 -0
- package/dist/qe/ledger.js +154 -0
- package/dist/qe/ledger.js.map +1 -0
- package/dist/studio/assets/index-8p8uwCxG.js +530 -0
- package/dist/studio/assets/index-D6S9zUtO.css +32 -0
- package/dist/studio/index.html +5 -3
- package/package.json +10 -4
- package/dist/studio/assets/index-DaaUU8Ep.css +0 -32
- package/dist/studio/assets/index-Fu5DRC00.js +0 -423
|
@@ -0,0 +1,601 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opt-in governed answering of wicked-interactive's STRUCTURAL edits (task #86, Phase 7c
|
|
3
|
+
* final leg — the draft leg's sibling, see draft-events.ts).
|
|
4
|
+
*
|
|
5
|
+
* wicked-interactive's service is model-free: a feedback batch's deterministic items
|
|
6
|
+
* (content/style/remove) are applied instantly by the service and NEVER reach this seam —
|
|
7
|
+
* only `structural-change` items climb. The service lands the deterministic partial as
|
|
8
|
+
* `_v{N}.html`, then emits `wicked.interactive.feedback.processed` with `awaiting_structural > 0`
|
|
9
|
+
* and the structural items INLINE (selector + instruction + the element's CURRENT fragment),
|
|
10
|
+
* expecting *something with intelligence* to answer with `wicked.interactive.edit.completed`
|
|
11
|
+
* carrying the edited fragments. Today that answerer is an ad-hoc `assist` agent session
|
|
12
|
+
* (assist skill Step 3); this module makes a crew-governed run the answerer instead.
|
|
13
|
+
*
|
|
14
|
+
* Same shape as the draft leg, with the structural deltas:
|
|
15
|
+
*
|
|
16
|
+
* - VERSIONED TARGETING: the dedupe unit is the HANDOFF — `<doc>:v<version>` — not the doc
|
|
17
|
+
* (one doc produces many structural handoffs over its life). The durable ledger keys on the
|
|
18
|
+
* handoff, and the closing emit's idempotency key carries doc+version.
|
|
19
|
+
* - INV-2 AT SCALE: unlike a first draft (no pre-existing anchors), an edited fragment MUST
|
|
20
|
+
* retain every pre-existing `data-wid` BYTE-EXACT — the service silently rejects violations
|
|
21
|
+
* (regenerate.js Inv2Error → the user's edit dies with no version landed). So this seam runs
|
|
22
|
+
* a deterministic PRE-EMIT SELF-CHECK mirroring the assist skill's Step 2/Step 3c discipline:
|
|
23
|
+
* parse the handed-off fragment's data-wids, verify the worker's fragment retains all of
|
|
24
|
+
* them, and fail HONEST (error status, no emit) on any violation — a loud crew-side rejection
|
|
25
|
+
* instead of a silent service-side one.
|
|
26
|
+
* - HANDOFF BY FILE: fragments can be arbitrarily large and the PTY seat runner's prompt is
|
|
27
|
+
* single-line, so the seam writes the items to a handoff JSON on disk and names its path in
|
|
28
|
+
* the problem; the worker writes each edited fragment to a per-item output file (never JSON
|
|
29
|
+
* with hand-escaped HTML — the exact failure the assist skill's Step 3c warns about).
|
|
30
|
+
* - PROJECT ATTRIBUTION (the 7b surface): a project-bound doc's events carry `project_id`
|
|
31
|
+
* (interactive's DES-PROJECT-001 enrichment); the governed run is launched with
|
|
32
|
+
* `LaunchOptions.projectId` so the edit shows up in the project's activity feed.
|
|
33
|
+
*/
|
|
34
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
35
|
+
import { join } from 'node:path';
|
|
36
|
+
import { homedir } from 'node:os';
|
|
37
|
+
import { randomUUID } from 'node:crypto';
|
|
38
|
+
import { DOC_NAME, INTERACTIVE_DOMAIN, INTERACTIVE_PRODUCER, STATUS_POSTED, oneLine, } from './draft-events.js';
|
|
39
|
+
import { InteractiveHandoffLedger } from './ledger.js';
|
|
40
|
+
import { readDocHead } from './chat-events.js';
|
|
41
|
+
import { resolveInteractiveRoot } from './bridge-root.js';
|
|
42
|
+
// ── Vocabulary constants (interactive's, verbatim — src/service/events.js is the truth) ──────
|
|
43
|
+
export const FEEDBACK_PROCESSED = 'wicked.interactive.feedback.processed';
|
|
44
|
+
export const EDIT_COMPLETED = 'wicked.interactive.edit.completed';
|
|
45
|
+
/** Exact-type filter with a domain guard — no wildcard, one event type is the whole trigger. */
|
|
46
|
+
export const INTERACTIVE_EDIT_BUS_FILTER = `${FEEDBACK_PROCESSED}@${INTERACTIVE_DOMAIN}`;
|
|
47
|
+
/** Dedicated durable-cursor identity — NOT the draft seam's, so the two interactive seams
|
|
48
|
+
* advance independent cursors and stopping one never strands the other. */
|
|
49
|
+
export const INTERACTIVE_EDIT_BUS_PLUGIN = 'wicked-crew-interactive-edit';
|
|
50
|
+
// ── The workflow (workflows-as-data) ─────────────────────────────────────────────────────────
|
|
51
|
+
export const INTERACTIVE_EDIT_WORKFLOW = 'interactive-edit';
|
|
52
|
+
/**
|
|
53
|
+
* The governed workflow that fulfils a structural handoff. ONE agent phase — `edit` (build,
|
|
54
|
+
* creator role): the target fragments are already extracted and the instructions already
|
|
55
|
+
* written, so unlike the draft leg there is nothing left to plan; a recon phase would only
|
|
56
|
+
* burn a council turn re-reading a handoff the edit phase reads anyway.
|
|
57
|
+
*
|
|
58
|
+
* The phase `instructions` adapt the fragment-edit contract from interactive's assist skill
|
|
59
|
+
* (Step 2 + Step 3): rewrite each handed-off fragment per its instruction, preserve every
|
|
60
|
+
* pre-existing `data-wid` byte-for-byte, never mint new anchors, keep the markup well-formed,
|
|
61
|
+
* and never fabricate facts. SINGLE-LINE by contract (PTY seat runner, wicked-core FINDING-011).
|
|
62
|
+
*
|
|
63
|
+
* The gate is `auto` with `validator_pin: null` — no human gate, no deterministic floor —
|
|
64
|
+
* because this seam runs its own deterministic pre-emit self-check (INV-2) and interactive's
|
|
65
|
+
* apply path re-checks the same invariant; a wrong-but-anchor-safe edit is the user's to judge
|
|
66
|
+
* on the canvas, exactly as with the assist session it replaces.
|
|
67
|
+
*/
|
|
68
|
+
export const INTERACTIVE_EDIT_WORKFLOW_DEF = {
|
|
69
|
+
id: INTERACTIVE_EDIT_WORKFLOW,
|
|
70
|
+
is_system: true,
|
|
71
|
+
phases: [
|
|
72
|
+
{
|
|
73
|
+
id: 'edit',
|
|
74
|
+
kind: 'build',
|
|
75
|
+
instructions: 'Read the handoff JSON file named in the task; for EACH entry of its items array: rewrite that item\'s "fragment" (the current outerHTML of one document element) to fulfil the item\'s "instruction", and SAVE the complete edited fragment — the element\'s full outerHTML only, no document wrapper, no markdown fences — to the item\'s exact absolute "output_path" (create parent directories if needed, overwrite if present). NON-NEGOTIABLE (INV-2): every data-wid attribute in the input fragment MUST survive in your edited fragment byte-for-byte — never remove, rename, or re-value a data-wid, and keep the root element\'s own data-wid on the root; elements you ADD must carry no data-wid at all (the wicked-interactive service instruments its own anchors). Keep the markup well-formed (balanced tags), change only what the instruction asks, and never fabricate facts or figures. Write every output file before you finish and end your reply with the absolute paths you wrote.',
|
|
76
|
+
gate_type: 'execution',
|
|
77
|
+
gate: 'auto',
|
|
78
|
+
executes_code: false,
|
|
79
|
+
verified_evidence: false,
|
|
80
|
+
required_deliverables: [],
|
|
81
|
+
depends_on: [],
|
|
82
|
+
role: 'creator',
|
|
83
|
+
skill_ref: null,
|
|
84
|
+
allowed_skills: [],
|
|
85
|
+
validator_pin: null,
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Parse a bus frame into a {@link StructuralHandoff}, or `null` when it is not an actionable
|
|
91
|
+
* structural handoff: wrong type, malformed payload, slug-invalid document_id, non-integer
|
|
92
|
+
* version, or NO usable structural items. Deterministic-only batches (`awaiting_structural: 0`)
|
|
93
|
+
* return `null` by construction — those edits already landed inside the service (edit-routing
|
|
94
|
+
* rung 1) and must never climb to a crew. Items whose `fragment` is missing/null (the service
|
|
95
|
+
* could not extract the element) are dropped: there is no current markup to edit.
|
|
96
|
+
*/
|
|
97
|
+
export function parseStructuralFeedback(eventType, payload) {
|
|
98
|
+
if (eventType !== FEEDBACK_PROCESSED)
|
|
99
|
+
return null;
|
|
100
|
+
if (typeof payload !== 'object' || payload === null)
|
|
101
|
+
return null;
|
|
102
|
+
const p = payload;
|
|
103
|
+
// The declared handoff size is the explicit gate: a frame carrying structural_items while
|
|
104
|
+
// announcing `awaiting_structural: 0` (or omitting it) is producer drift, not a handoff —
|
|
105
|
+
// never launch a governed run off an inconsistent frame.
|
|
106
|
+
const awaiting = p['awaiting_structural'];
|
|
107
|
+
if (typeof awaiting !== 'number' || !Number.isInteger(awaiting) || awaiting <= 0)
|
|
108
|
+
return null;
|
|
109
|
+
const documentId = typeof p['document_id'] === 'string' ? p['document_id'] : '';
|
|
110
|
+
if (!DOC_NAME.test(documentId))
|
|
111
|
+
return null;
|
|
112
|
+
const version = p['version'];
|
|
113
|
+
if (typeof version !== 'number' || !Number.isInteger(version) || version < 0)
|
|
114
|
+
return null;
|
|
115
|
+
const rawItems = Array.isArray(p['structural_items']) ? p['structural_items'] : [];
|
|
116
|
+
const items = [];
|
|
117
|
+
for (const raw of rawItems) {
|
|
118
|
+
if (typeof raw !== 'object' || raw === null)
|
|
119
|
+
continue;
|
|
120
|
+
const r = raw;
|
|
121
|
+
const selector = typeof r['selector'] === 'string' ? r['selector'] : '';
|
|
122
|
+
const fragment = typeof r['fragment'] === 'string' ? r['fragment'] : '';
|
|
123
|
+
if (selector.length === 0 || fragment.length === 0)
|
|
124
|
+
continue;
|
|
125
|
+
items.push({
|
|
126
|
+
selector,
|
|
127
|
+
instruction: typeof r['instruction'] === 'string' ? r['instruction'] : '',
|
|
128
|
+
fragment,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
if (items.length === 0)
|
|
132
|
+
return null;
|
|
133
|
+
const projectId = typeof p['project_id'] === 'string' && p['project_id'].length > 0 ? p['project_id'] : undefined;
|
|
134
|
+
return { documentId, version, items, ...(projectId !== undefined ? { projectId } : {}) };
|
|
135
|
+
}
|
|
136
|
+
/** The one dedupe unit of this seam: a handoff is doc+version, NOT doc-lifetime. */
|
|
137
|
+
export function handoffKey(documentId, version) {
|
|
138
|
+
return `${documentId}:v${version}`;
|
|
139
|
+
}
|
|
140
|
+
/** Deterministic bus idempotency key for the one edit this seam may land per handoff. */
|
|
141
|
+
export function editIdempotencyKey(documentId, version) {
|
|
142
|
+
return `crew:interactive.edit:${documentId}:v${version}`;
|
|
143
|
+
}
|
|
144
|
+
/** Per-item output paths are INDEX-named (`fragment-1.html`, …), never selector-named — a
|
|
145
|
+
* selector is bus-supplied data and must not name a filesystem path. */
|
|
146
|
+
export function handoffFileItems(handoff, outDir) {
|
|
147
|
+
return handoff.items.map((item, i) => ({
|
|
148
|
+
...item,
|
|
149
|
+
output_path: join(outDir, `fragment-${i + 1}.html`),
|
|
150
|
+
}));
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* The run's problem statement. Single-line (PTY contract); the bulky fragments ride in the
|
|
154
|
+
* handoff FILE, so only identity, the capped instruction gist, and the file path ride here.
|
|
155
|
+
*/
|
|
156
|
+
export function editProblem(handoff, handoffPath) {
|
|
157
|
+
const gist = oneLine(handoff.items.map((i) => i.instruction).filter((s) => s.length > 0).join('; '), 600);
|
|
158
|
+
return (`Fulfil ${handoff.items.length} structural edit(s) on the wicked-interactive document ` +
|
|
159
|
+
`"${handoff.documentId}" (editing version ${handoff.version}). Read the handoff file at ` +
|
|
160
|
+
`${handoffPath} — a JSON file whose items array carries, per edit: the user's instruction, ` +
|
|
161
|
+
`the element's current HTML fragment, and the exact absolute output_path where the edited ` +
|
|
162
|
+
`fragment must be saved. The user asked: ${gist.length > 0 ? gist : '(no instruction text)'}`);
|
|
163
|
+
}
|
|
164
|
+
// ── The pre-emit INV-2 self-check (deterministic; mirrors assist skill Step 3c) ──────────────
|
|
165
|
+
/** Every `data-wid` value in a fragment, in document order (duplicates preserved). */
|
|
166
|
+
export function fragmentWids(fragment) {
|
|
167
|
+
return [...fragment.matchAll(/data-wid="([^"]*)"/g)].map((m) => m[1]);
|
|
168
|
+
}
|
|
169
|
+
/** The data-wids of `before` missing from `after`, byte-exact. Non-empty = INV-2 violation.
|
|
170
|
+
* Deliberately conservative: a wid that survives with different quoting/escaping counts as
|
|
171
|
+
* dropped — the service compares exact attribute values, and fail-closed here beats a silent
|
|
172
|
+
* Inv2Error rejection there. */
|
|
173
|
+
export function droppedWids(before, after) {
|
|
174
|
+
const kept = new Set(fragmentWids(after));
|
|
175
|
+
return [...new Set(fragmentWids(before))].filter((w) => !kept.has(w));
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Read the worker's per-item output files and verify each against the handed-off fragment:
|
|
179
|
+
* the file must exist non-empty, and every pre-existing `data-wid` must survive byte-exact.
|
|
180
|
+
* ANY violation fails the whole handoff (all-or-nothing): a partial apply would land a version
|
|
181
|
+
* the user believes complete, and the violating item would die silently service-side.
|
|
182
|
+
*/
|
|
183
|
+
export function collectEditResults(items) {
|
|
184
|
+
const results = [];
|
|
185
|
+
const violations = [];
|
|
186
|
+
for (const item of items) {
|
|
187
|
+
let fragment = '';
|
|
188
|
+
try {
|
|
189
|
+
fragment = readFileSync(item.output_path, 'utf8').trim();
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
/* missing file → the empty-fragment violation below */
|
|
193
|
+
}
|
|
194
|
+
if (fragment.length === 0) {
|
|
195
|
+
violations.push({ selector: item.selector, reason: `no edited fragment at ${item.output_path}` });
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
const dropped = droppedWids(item.fragment, fragment);
|
|
199
|
+
if (dropped.length > 0) {
|
|
200
|
+
violations.push({
|
|
201
|
+
selector: item.selector,
|
|
202
|
+
reason: `INV-2 violation — data-wid(s) dropped: ${dropped.join(', ')}`,
|
|
203
|
+
});
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
results.push({ selector: item.selector, fragment });
|
|
207
|
+
}
|
|
208
|
+
return { results, violations };
|
|
209
|
+
}
|
|
210
|
+
function defaultStateDir() {
|
|
211
|
+
return join(homedir(), '.wicked-crew');
|
|
212
|
+
}
|
|
213
|
+
/** The production council roster, resolved lazily through the adapter's own class so this module
|
|
214
|
+
* never imports the native addon at runtime (unit tests pass `clisJson` and a fake adapter). */
|
|
215
|
+
function rosterOf(adapter) {
|
|
216
|
+
return adapter.constructor.roster();
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Arm the seam: register the `interactive-edit` workflow, open a durable
|
|
220
|
+
* `wicked.interactive.feedback.processed` subscription, and answer each handoff carrying
|
|
221
|
+
* structural items with a governed run that ends in `wicked.interactive.edit.completed`.
|
|
222
|
+
*
|
|
223
|
+
* Graceful degradation mirrors the draft seam: a missing wicked-bus package or an unopenable
|
|
224
|
+
* db LOGS and returns `null` — the daemon must still boot on a machine whose bus is broken;
|
|
225
|
+
* interactive's assist loop remains the (always-available) fallback answerer.
|
|
226
|
+
*/
|
|
227
|
+
export async function startInteractiveEditSubscriber(adapter, opts = {}) {
|
|
228
|
+
const log = opts.log ?? ((m) => console.error(m));
|
|
229
|
+
let bus;
|
|
230
|
+
try {
|
|
231
|
+
bus = await import('wicked-bus');
|
|
232
|
+
}
|
|
233
|
+
catch (err) {
|
|
234
|
+
log(`[interactive-edit] wicked-bus is not importable — governed structural edits disabled: ${err instanceof Error ? err.message : String(err)}`);
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
let db;
|
|
238
|
+
let config;
|
|
239
|
+
try {
|
|
240
|
+
config = bus.loadConfig(opts.dbPath !== undefined ? { db_path: opts.dbPath } : {});
|
|
241
|
+
db = bus.openDb(opts.dbPath !== undefined ? { db_path: opts.dbPath } : {});
|
|
242
|
+
}
|
|
243
|
+
catch (err) {
|
|
244
|
+
log(`[interactive-edit] could not open the bus db${opts.dbPath !== undefined ? ` at ${opts.dbPath}` : ''} — governed structural edits disabled: ${err instanceof Error ? err.message : String(err)}`);
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
// The workflow rides the normal registration path — core validates the def BEFORE it is
|
|
248
|
+
// persisted/hot-registered (FINDING-002 ordering), so a drifted def fails the arm loudly
|
|
249
|
+
// instead of failing the first launch obscurely.
|
|
250
|
+
try {
|
|
251
|
+
await adapter.registerWorkflow(INTERACTIVE_EDIT_WORKFLOW_DEF);
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
log(`[interactive-edit] could not register the '${INTERACTIVE_EDIT_WORKFLOW}' workflow — ` +
|
|
255
|
+
`governed structural edits disabled: ${err instanceof Error ? err.message : String(err)}`);
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
const ledger = new InteractiveHandoffLedger(opts.ledgerPath ?? join(defaultStateDir(), 'interactive-edit-ledger.json'));
|
|
259
|
+
const editDir = opts.editDir ?? join(defaultStateDir(), 'interactive-edits');
|
|
260
|
+
const heartbeatMs = opts.heartbeatMs ?? 15_000;
|
|
261
|
+
// The run executes ONE MORE unit than the def declares: the crew#311 deliverable floor,
|
|
262
|
+
// appended per-run by `launchRun` from `requireDeliverables`. Narration keys off this so the
|
|
263
|
+
// "landing the new version" line fires when the FILES are verified, not when the worker
|
|
264
|
+
// merely stopped talking.
|
|
265
|
+
const agentPhaseCount = INTERACTIVE_EDIT_WORKFLOW_DEF.phases.length;
|
|
266
|
+
const inFlight = new Map(); // runId → live state
|
|
267
|
+
/** Emit onto interactive's vocabulary as the `wi-crew` producer. Never throws into the
|
|
268
|
+
* caller: narration/announce failures are logged — a lost status line must not kill the
|
|
269
|
+
* subscription, and a duplicate edit emit (WB-002) is the idempotency key WORKING. */
|
|
270
|
+
function emitInteractive(type, payload, idempotencyKey) {
|
|
271
|
+
try {
|
|
272
|
+
bus.emit(db, config, {
|
|
273
|
+
event_type: type,
|
|
274
|
+
domain: INTERACTIVE_DOMAIN,
|
|
275
|
+
subdomain: type === EDIT_COMPLETED ? 'feedback' : 'status',
|
|
276
|
+
payload: { ts: new Date().toISOString(), ...payload },
|
|
277
|
+
producer_id: INTERACTIVE_PRODUCER,
|
|
278
|
+
...(idempotencyKey !== undefined ? { idempotency_key: idempotencyKey } : {}),
|
|
279
|
+
});
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
catch (err) {
|
|
283
|
+
const code = err.error;
|
|
284
|
+
if (code === 'WB-002') {
|
|
285
|
+
// Duplicate idempotency key — the emit already happened (redelivery race). Success.
|
|
286
|
+
return true;
|
|
287
|
+
}
|
|
288
|
+
log(`[interactive-edit] emit ${type} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
function narrate(flight, message) {
|
|
293
|
+
flight.narration = message;
|
|
294
|
+
emitInteractive(STATUS_POSTED, {
|
|
295
|
+
document_id: flight.documentId,
|
|
296
|
+
version: flight.version,
|
|
297
|
+
state: 'working',
|
|
298
|
+
message,
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
function endFlight(runId) {
|
|
302
|
+
const flight = inFlight.get(runId);
|
|
303
|
+
if (flight) {
|
|
304
|
+
clearInterval(flight.heartbeat);
|
|
305
|
+
inFlight.delete(runId);
|
|
306
|
+
}
|
|
307
|
+
return flight;
|
|
308
|
+
}
|
|
309
|
+
/** Terminal-event fold: turn the governed run's own events into interactive narration, and
|
|
310
|
+
* close the loop with `edit.completed` when the run lands AND the self-check passes. */
|
|
311
|
+
const offCoreEvents = adapter.onEvent((event) => {
|
|
312
|
+
const runId = typeof event.session === 'string' ? event.session : undefined;
|
|
313
|
+
if (runId === undefined)
|
|
314
|
+
return;
|
|
315
|
+
const flight = inFlight.get(runId);
|
|
316
|
+
if (flight === undefined)
|
|
317
|
+
return;
|
|
318
|
+
// Narration ladder — same rationale as the draft fold: the heartbeat repeats the LATEST
|
|
319
|
+
// line and the transcript dedups repeats, so advancing the line = visible progress.
|
|
320
|
+
const blocks = flight.items.length === 1 ? 'the targeted block' : `${flight.items.length} targeted blocks`;
|
|
321
|
+
// The crew#311 deliverable floor is a DETERMINISTIC tool phase — no seat, no council. Core
|
|
322
|
+
// still emits the seat-selection events for it (its `cli` is the node interpreter's absolute
|
|
323
|
+
// path), so narrating them verbatim put "Council picked /opt/homebrew/.../node to rework…"
|
|
324
|
+
// in the reader's thread. Drop those two lines for the floor ord.
|
|
325
|
+
const isFloorOrd = (e) => typeof e.ord === 'number' && e.ord > agentPhaseCount;
|
|
326
|
+
if (event.type === 'councilConvened') {
|
|
327
|
+
if (isFloorOrd(event))
|
|
328
|
+
return;
|
|
329
|
+
const seats = Array.isArray(event.clis) ? event.clis.length : 0;
|
|
330
|
+
// "0-seat council" reads like a bug — generic phrasing whenever clis is missing or empty
|
|
331
|
+
// (Copilot, #269).
|
|
332
|
+
const council = seats > 0 ? `a ${seats}-seat council` : 'a council';
|
|
333
|
+
narrate(flight, `Convening ${council} to pick who reworks ${blocks}…`);
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
if (event.type === 'unitDistributed') {
|
|
337
|
+
if (isFloorOrd(event))
|
|
338
|
+
return;
|
|
339
|
+
const who = typeof event.cli === 'string' ? event.cli : 'a worker';
|
|
340
|
+
const pct = typeof event.agreement_pct === 'number' ? ` (${event.agreement_pct}% agreement)` : '';
|
|
341
|
+
narrate(flight, `Council picked ${who} to rework ${blocks}${pct}…`);
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
if (event.type === 'unitDispatched') {
|
|
345
|
+
if (isFloorOrd(event)) {
|
|
346
|
+
narrate(flight, 'Checking the edited fragment files were actually written…');
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
narrate(flight, `Crew is reworking ${blocks}…`);
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
if (event.type === 'toolInvoked') {
|
|
353
|
+
const tools = Array.isArray(event.tools) ? [...new Set(event.tools)].join(', ') : '';
|
|
354
|
+
if (tools)
|
|
355
|
+
narrate(flight, `Worker is using ${tools} on ${blocks}…`);
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
if (event.type === 'unitOutputCaptured') {
|
|
359
|
+
narrate(flight, `Rework finished — the governance gate is reviewing it…`);
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
if (event.type === 'gateDecided' && event.allow === true) {
|
|
363
|
+
const ord = typeof event.ord === 'number' ? event.ord : 0;
|
|
364
|
+
// ord > the def's own phase count = the crew#311 deliverable floor, appended per-run.
|
|
365
|
+
narrate(flight, ord > agentPhaseCount
|
|
366
|
+
? 'Edited fragments verified on disk — landing the new version now…'
|
|
367
|
+
: 'Gate approved the edit — checking the fragment files landed…');
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
if (event.type === 'acpFallback') {
|
|
371
|
+
const who = typeof event.cliKey === 'string' ? event.cliKey : 'the worker';
|
|
372
|
+
narrate(flight, `${who}'s live session dropped — continuing in single-shot mode…`);
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
if (event.type === 'sessionCompleted') {
|
|
376
|
+
endFlight(runId);
|
|
377
|
+
finalize(flight, runId);
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
if (event.type === 'stepFailed') {
|
|
381
|
+
// Remember the engine's own reason (crew#311) so the terminal status can name it.
|
|
382
|
+
const detail = typeof event.detail === 'string' ? event.detail.trim() : '';
|
|
383
|
+
if (detail.length > 0)
|
|
384
|
+
flight.failureDetail = detail;
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
if (event.type === 'sessionFailed' || event.type === 'runCancelled') {
|
|
388
|
+
endFlight(runId);
|
|
389
|
+
ledger.recordFailure(flight.key);
|
|
390
|
+
const why = flight.failureDetail !== undefined ? ` Reason: ${oneLine(flight.failureDetail, 600)}` : '';
|
|
391
|
+
emitInteractive(STATUS_POSTED, {
|
|
392
|
+
document_id: flight.documentId,
|
|
393
|
+
version: flight.version,
|
|
394
|
+
state: 'error',
|
|
395
|
+
message: `The crew run answering this edit ${event.type === 'runCancelled' ? 'was cancelled' : 'failed'} ` +
|
|
396
|
+
`(run ${runId}).${why} Inspect it via the crew API (GET /api/v1/runs/${runId}); the assist loop can still take over.`,
|
|
397
|
+
});
|
|
398
|
+
log(`[interactive-edit] run ${runId} for handoff ${flight.key} ended: ${event.type}`);
|
|
399
|
+
}
|
|
400
|
+
});
|
|
401
|
+
function finalize(flight, runId) {
|
|
402
|
+
const { documentId, version, key, items } = flight;
|
|
403
|
+
// The deterministic pre-emit self-check (INV-2 at scale): a violating fragment would be
|
|
404
|
+
// rejected SILENTLY by the service (regenerate.js Inv2Error) — the user's edit would just
|
|
405
|
+
// die. Fail honest here instead: error status, failure row, no emit.
|
|
406
|
+
const { results, violations } = collectEditResults(items);
|
|
407
|
+
if (violations.length > 0) {
|
|
408
|
+
ledger.recordFailure(key);
|
|
409
|
+
const detail = violations.map((v) => `${v.selector}: ${v.reason}`).join('; ');
|
|
410
|
+
emitInteractive(STATUS_POSTED, {
|
|
411
|
+
document_id: documentId,
|
|
412
|
+
version,
|
|
413
|
+
state: 'error',
|
|
414
|
+
message: `The crew's edit failed its pre-emit self-check and was NOT applied — ${detail} ` +
|
|
415
|
+
`(run ${runId}). The document is unchanged; resubmit the edit or let the assist loop take over.`,
|
|
416
|
+
});
|
|
417
|
+
log(`[interactive-edit] run ${runId} rejected by self-check for ${key}: ${detail}`);
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
// Announce with the handoff's version (the parent the service forks from) and the
|
|
421
|
+
// deterministic doc+version key — a re-announce is a WB-002 no-op.
|
|
422
|
+
const emitted = emitInteractive(EDIT_COMPLETED, { document_id: documentId, version, results }, editIdempotencyKey(documentId, version));
|
|
423
|
+
if (!emitted) {
|
|
424
|
+
// The bus refused the announce (non-WB-002): the edit exists on disk but never reached
|
|
425
|
+
// the service. Fail HONEST — leaving the ledger row launched-but-never-closed would
|
|
426
|
+
// silently eat every replay of this handoff (the launch gate is `ledger.has`).
|
|
427
|
+
ledger.recordFailure(key);
|
|
428
|
+
emitInteractive(STATUS_POSTED, {
|
|
429
|
+
document_id: documentId,
|
|
430
|
+
version,
|
|
431
|
+
state: 'error',
|
|
432
|
+
message: `Crew finished the edit but could not announce it on the bus (run ${runId}); ` +
|
|
433
|
+
`the document is unchanged. Inspect the crew daemon log, then resubmit the edit.`,
|
|
434
|
+
});
|
|
435
|
+
log(`[interactive-edit] edit.completed emit FAILED for ${key} (run ${runId}) — recorded as failure`);
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
ledger.recordEmitted(key);
|
|
439
|
+
emitInteractive(STATUS_POSTED, {
|
|
440
|
+
document_id: documentId,
|
|
441
|
+
version,
|
|
442
|
+
state: 'complete',
|
|
443
|
+
message: 'Edit is in — landing the new version on the canvas now.',
|
|
444
|
+
});
|
|
445
|
+
log(`[interactive-edit] edit.completed emitted for ${key} (run ${runId}, ${results.length} fragment(s))`);
|
|
446
|
+
}
|
|
447
|
+
async function handleFeedbackProcessed(event) {
|
|
448
|
+
const handoff = parseStructuralFeedback(event.event_type, event.payload);
|
|
449
|
+
if (handoff === null)
|
|
450
|
+
return;
|
|
451
|
+
// THE KIND GATE (CREW-UX-9): the frame carries no `kind`, so the doc's own manifest is
|
|
452
|
+
// the truth. A demo doc's step feedback means "re-author demo.spec.mjs and re-record"
|
|
453
|
+
// (assist SKILL.md Step 8c) — the demo seam's business; answering it here would land a
|
|
454
|
+
// storyboard-text edit the next re-record overwrites, while the user's actual ask (change
|
|
455
|
+
// the demo) dies. Fail-open on an unreadable manifest: that is this seam's pre-CREW-UX-9
|
|
456
|
+
// behavior, and the demo seam requires a READABLE demo manifest — one answerer either way.
|
|
457
|
+
const docsRoot = (opts.resolveDocsRoot ?? (() => resolveInteractiveRoot(null)))(handoff.projectId);
|
|
458
|
+
const head = readDocHead(docsRoot, handoff.documentId);
|
|
459
|
+
if (head !== null && head.kind === 'demo') {
|
|
460
|
+
// …but ONLY when the demo seam is actually there to take it. Skipping into a seam that
|
|
461
|
+
// never armed is a silent drop: no run, no status, a canvas that waits forever. Say so.
|
|
462
|
+
if (!(opts.demoSeamArmed ?? (() => false))()) {
|
|
463
|
+
emitInteractive(STATUS_POSTED, {
|
|
464
|
+
document_id: handoff.documentId,
|
|
465
|
+
version: handoff.version,
|
|
466
|
+
state: 'error',
|
|
467
|
+
message: `This is a demo document: changing it means re-authoring its demo spec and ` +
|
|
468
|
+
`re-recording, which the crew's demo seam does — and that seam is not running on ` +
|
|
469
|
+
`this daemon. Nothing was changed. Start crew with the interactive demo events ` +
|
|
470
|
+
`enabled (drop --no-interactive-demo-events / WICKED_INTERACTIVE_DEMO_EVENTS), then ` +
|
|
471
|
+
`resubmit this feedback.`,
|
|
472
|
+
});
|
|
473
|
+
// DELIBERATELY no ledger row: this handoff was NOT answered, it was declined. An
|
|
474
|
+
// operator who arms the demo seam and replays the frame must get a real re-author run,
|
|
475
|
+
// and the launch gate is `ledger.has` — a row here would eat that replay forever.
|
|
476
|
+
log(`[interactive-edit] doc ${handoff.documentId} is a demo but the demo seam is NOT armed ` +
|
|
477
|
+
`— handoff v${handoff.version} answered with an honest error status, not silently dropped`);
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
log(`[interactive-edit] doc ${handoff.documentId} is a demo — its step feedback re-authors ` +
|
|
481
|
+
`the spec (demo seam), not the storyboard; handoff v${handoff.version} skipped here`);
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
const key = handoffKey(handoff.documentId, handoff.version);
|
|
485
|
+
// Replay-dedup: the ledger is the durable gate (redelivery after crash/restart), the
|
|
486
|
+
// in-flight scan the live one (redelivery inside a single process lifetime). Keyed by
|
|
487
|
+
// HANDOFF — a later feedback batch on the same doc is a new key and launches normally.
|
|
488
|
+
if (ledger.has(key)) {
|
|
489
|
+
log(`[interactive-edit] handoff ${key} already answered (run ${ledger.get(key)?.runId}) — replay ignored`);
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
for (const f of inFlight.values()) {
|
|
493
|
+
if (f.key === key)
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
const outDir = join(editDir, key.replace(':', '-'));
|
|
497
|
+
mkdirSync(outDir, { recursive: true });
|
|
498
|
+
const items = handoffFileItems(handoff, outDir);
|
|
499
|
+
const handoffPath = join(editDir, `${key.replace(':', '-')}-handoff.json`);
|
|
500
|
+
writeFileSync(handoffPath, JSON.stringify({ document_id: handoff.documentId, version: handoff.version, items }, null, 2), 'utf8');
|
|
501
|
+
const runId = randomUUID();
|
|
502
|
+
emitInteractive(STATUS_POSTED, {
|
|
503
|
+
document_id: handoff.documentId,
|
|
504
|
+
version: handoff.version,
|
|
505
|
+
state: 'processing',
|
|
506
|
+
message: `A governed crew picked up your edit — reworking ${items.length === 1 ? 'the block' : `${items.length} blocks`}…`,
|
|
507
|
+
});
|
|
508
|
+
try {
|
|
509
|
+
const input = {
|
|
510
|
+
problem: editProblem(handoff, handoffPath),
|
|
511
|
+
sessionId: runId,
|
|
512
|
+
clisJson: opts.clisJson ?? JSON.stringify(rosterOf(adapter)),
|
|
513
|
+
workflow: INTERACTIVE_EDIT_WORKFLOW,
|
|
514
|
+
// The 7b surface: a project-bound doc's governed edits are FILED — the run lands in
|
|
515
|
+
// the project's activity feed instead of floating unattributed.
|
|
516
|
+
...(handoff.projectId !== undefined ? { projectId: handoff.projectId } : {}),
|
|
517
|
+
// The task names the handoff JSON + per-block output files under `editDir`, which sits
|
|
518
|
+
// OUTSIDE the unit's sandbox — the wrapped-CLI boundary would deny both the reads and
|
|
519
|
+
// the deliverable writes (crew#263, same shape as the draft path). One declared root
|
|
520
|
+
// covers both: write roots are readable (wicked-core#259).
|
|
521
|
+
extraWriteRoots: [editDir],
|
|
522
|
+
// THE DELIVERABLE FLOOR (crew#311): EVERY handed-off fragment file is a deliverable, so
|
|
523
|
+
// a run that rewrote three blocks and wrote one file fails too — the floor is per-path,
|
|
524
|
+
// not "did anything land". Without it the engine's substance floor passes a worker
|
|
525
|
+
// whose Writes were denied as long as it narrated ~200 characters first.
|
|
526
|
+
requireDeliverables: items.map((i) => i.output_path),
|
|
527
|
+
};
|
|
528
|
+
await adapter.launchRun(input);
|
|
529
|
+
}
|
|
530
|
+
catch (err) {
|
|
531
|
+
// The 'processing' status is already on the thread — close it out honestly so the
|
|
532
|
+
// canvas never sits in an in-between state on a launch that went nowhere.
|
|
533
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
534
|
+
emitInteractive(STATUS_POSTED, {
|
|
535
|
+
document_id: handoff.documentId,
|
|
536
|
+
version: handoff.version,
|
|
537
|
+
state: 'error',
|
|
538
|
+
message: `Crew could not start a run for this edit: ${reason}. The assist loop can still take over.`,
|
|
539
|
+
});
|
|
540
|
+
// DELIBERATELY no ledger write: only an answered handoff earns a row, so an operator can
|
|
541
|
+
// replay the dead-lettered feedback.processed after fixing the daemon and get a real
|
|
542
|
+
// retry. Re-throw so the bus (maxRetries 0) dead-letters the frame — visible, replayable,
|
|
543
|
+
// and incapable of hot-looping.
|
|
544
|
+
throw err;
|
|
545
|
+
}
|
|
546
|
+
// Record AFTER the launch resolved: a failed launch leaves no ledger row, so a replayed
|
|
547
|
+
// delivery retries. The crash window between launch and this write is the reason the
|
|
548
|
+
// edit emit ALSO carries a deterministic idempotency key.
|
|
549
|
+
ledger.recordLaunch(key, runId);
|
|
550
|
+
if (handoff.projectId !== undefined)
|
|
551
|
+
opts.onRunFiled?.(runId, handoff.projectId);
|
|
552
|
+
const flight = {
|
|
553
|
+
key,
|
|
554
|
+
documentId: handoff.documentId,
|
|
555
|
+
version: handoff.version,
|
|
556
|
+
items,
|
|
557
|
+
narration: 'Crew run launched — working on your edit…',
|
|
558
|
+
heartbeat: setInterval(() => {
|
|
559
|
+
// Repeat the last real narration so the ~20s status.requested window is always fed,
|
|
560
|
+
// even mid-phase when the engine is quiet.
|
|
561
|
+
emitInteractive(STATUS_POSTED, {
|
|
562
|
+
document_id: flight.documentId,
|
|
563
|
+
version: flight.version,
|
|
564
|
+
state: 'working',
|
|
565
|
+
message: flight.narration,
|
|
566
|
+
});
|
|
567
|
+
}, heartbeatMs),
|
|
568
|
+
// Do not keep the daemon alive for narration alone.
|
|
569
|
+
};
|
|
570
|
+
flight.heartbeat.unref?.();
|
|
571
|
+
inFlight.set(runId, flight);
|
|
572
|
+
log(`[interactive-edit] handoff ${key} → governed run ${runId} (${items.length} item(s), handoff ${handoffPath})`);
|
|
573
|
+
}
|
|
574
|
+
const sub = bus.subscribe({
|
|
575
|
+
db,
|
|
576
|
+
plugin: INTERACTIVE_EDIT_BUS_PLUGIN,
|
|
577
|
+
filter: INTERACTIVE_EDIT_BUS_FILTER,
|
|
578
|
+
// Live triggers only: replaying a bus backlog would answer handoffs whose edits the assist
|
|
579
|
+
// loop long since produced. History reconciliation belongs to the state plane, not here.
|
|
580
|
+
cursor_init: 'latest',
|
|
581
|
+
pollIntervalMs: opts.pollIntervalMs ?? 2000,
|
|
582
|
+
// Our own ledger + idempotency key are the dedupe; a bus-level retry of a failed launch
|
|
583
|
+
// would double-launch precisely because the ledger row is only written on success.
|
|
584
|
+
maxRetries: 0,
|
|
585
|
+
handler: (event) => handleFeedbackProcessed(event),
|
|
586
|
+
onError: (err, event) => {
|
|
587
|
+
log(`[interactive-edit] handler error on event ${String(event?.event_id ?? '?')}: ${err.message}`);
|
|
588
|
+
},
|
|
589
|
+
});
|
|
590
|
+
return {
|
|
591
|
+
ledger,
|
|
592
|
+
inFlightDocs: () => [...new Set([...inFlight.values()].map((f) => f.documentId))],
|
|
593
|
+
stop: async () => {
|
|
594
|
+
offCoreEvents();
|
|
595
|
+
for (const runId of [...inFlight.keys()])
|
|
596
|
+
endFlight(runId);
|
|
597
|
+
await sub.stop();
|
|
598
|
+
},
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
//# sourceMappingURL=edit-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit-events.js","sourceRoot":"","sources":["../../src/interactive/edit-events.ts"],"names":[],"mappings":"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"}
|