wicked-crew 0.7.17 → 0.7.18

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.
@@ -247,6 +247,10 @@ export interface RuntimeDeps {
247
247
  * Injectable so route tests never shell out to git; defaults to {@link gitReprovisionWorktree}. */
248
248
  reprovisionWorktree?: WorktreeReprovisioner;
249
249
  openWithOs?: (target: string) => Promise<void>;
250
+ /** The estate-MCP proposal-queue client behind `/proposals*` (DES-MEM-FACETED-001 §5.0).
251
+ * Injectable so route tests never spawn `wicked-estate-mcp`; defaults to the real spawn-per-call
252
+ * client (NON-`--readonly`, `WICKED_MEMORY_DB` pinned to the operator global store). */
253
+ callEstateProposalTool?: (tool: string, args: Record<string, unknown>) => Promise<unknown>;
250
254
  /** Seat sign-in presence probe (seat sign-in) — injectable so route tests never read the
251
255
  * developer's real dotfiles. Defaults to the file/env heuristic in seat-signin.ts. */
252
256
  signedIn?: (seatKey: string, workerConfigRoot?: string) => boolean | null;
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/api/routes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/api/routes.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,7 @@ import { buildAcceptanceView, resolveRunWorkflow } from '../qe/acceptance.js';
14
14
  import { buildEvidenceBundle, coreUnitId, evidenceFilename } from './evidence.js';
15
15
  import { outputUnavailableReason, resolveUnit, unitKeysFor } from './unit-output.js';
16
16
  import { execCapped, ExecOutputTooLarge } from '../core/exec.js';
17
+ import { callEstateProposalTool, EstateMcpError } from '../core/estate-mcp-client.js';
17
18
  import { SeatHealthTracker } from './seat-health.js';
18
19
  import { applyWorkerConfigRoot, signedInHeuristic } from './seat-signin.js';
19
20
  import { allowedRootsFor, isInsideRoot, openWithSystemDefault } from './open-path.js';
@@ -282,6 +283,10 @@ runtime = {}) {
282
283
  });
283
284
  const deliverExec = runtime.deliverExec ?? runDeliverScript;
284
285
  const reprovisionWorktree = runtime.reprovisionWorktree ?? gitReprovisionWorktree;
286
+ // The estate proposal-queue client behind `/proposals*` (DES-MEM-FACETED-001 §5.0). The default
287
+ // is the real spawn-per-call `wicked-estate-mcp` client; route tests inject a stub so no process
288
+ // is ever spawned.
289
+ const proposalTool = runtime.callEstateProposalTool ?? callEstateProposalTool;
285
290
  /** Repo root for a repo ref, from the registry — shared by the reprovision path below. */
286
291
  const repoRootOf = async (repoRef) => (await adapter.listRepos()).find((r) => r.id === repoRef)?.root_path;
287
292
  // The run-DTO joins (DES-UX-001 §8.2/§8.3, DES-UX-002 §7.2): `project_id` from the membership
@@ -2636,6 +2641,81 @@ runtime = {}) {
2636
2641
  });
2637
2642
  return { settings };
2638
2643
  });
2644
+ // ── Memory proposal queue (DES-MEM-FACETED-001 §5.0) ─────────────────────────
2645
+ // The estate proposal queue over HTTP, so a studio operator can review the learnings workers
2646
+ // propose and approve/reject them. The queue tools live ONLY on the estate MCP (JSON-RPC over
2647
+ // stdio, estate #162), reached through `proposalTool` — a spawn-per-call `wicked-estate-mcp`
2648
+ // client, NON-`--readonly` (this is the OPERATOR surface: it lists AND mutates), with
2649
+ // WICKED_MEMORY_DB pinned to the operator global store. A queue/estate failure is an UPSTREAM
2650
+ // fault (502), kept distinct from a client mistake (400: a bad `state`/`id`, or estate's own
2651
+ // -32602 invalid-params) — the FINDING-031 posture that a malformed filter is refused, never
2652
+ // silently honored as a different request.
2653
+ const proposalUpstreamError = (reply, err) => {
2654
+ if (err instanceof EstateMcpError && err.code === -32602) {
2655
+ return reply.code(400).send({ error: err.message });
2656
+ }
2657
+ return reply.code(502).send({ error: message(err) });
2658
+ };
2659
+ // GET /proposals?kind_type=&state= → proposal.list → { proposals: Proposal[] }.
2660
+ app.get(`${V}/proposals`, { config: { manifest: { responseType: 'ListProposalsResponse', statusCodes: [200, 400, 502] } } }, async (req, reply) => {
2661
+ const q = req.query;
2662
+ const rawOf = (v) => Array.isArray(v) ? v[0] : v;
2663
+ const rawKind = rawOf(q.kind_type);
2664
+ const rawState = rawOf(q.state);
2665
+ // Fail-loud: a PRESENT-but-blank param (`?state=` / `?state=%20`) is a client error, NOT a
2666
+ // silent "no filter" — else a client accidentally issues a broader query than intended.
2667
+ if (rawKind !== undefined && rawKind.trim() === '') {
2668
+ return reply.code(400).send({ error: '`kind_type` must not be empty' });
2669
+ }
2670
+ if (rawState !== undefined && !['pending', 'approved', 'rejected'].includes(rawState.trim())) {
2671
+ return reply.code(400).send({ error: '`state` must be one of pending|approved|rejected' });
2672
+ }
2673
+ const kindType = rawKind?.trim() || undefined;
2674
+ const state = rawState?.trim() || undefined;
2675
+ const args = {};
2676
+ if (kindType !== undefined)
2677
+ args.kind_type = kindType;
2678
+ if (state !== undefined)
2679
+ args.state = state;
2680
+ try {
2681
+ return (await proposalTool('proposal.list', args));
2682
+ }
2683
+ catch (err) {
2684
+ return proposalUpstreamError(reply, err);
2685
+ }
2686
+ });
2687
+ // POST /proposals/:id/approve → proposal.approve →
2688
+ // { outcome:'promoted', active_id } — a MEMORY proposal, now an active memory (complete);
2689
+ // { outcome:'handed_off', payload } — a POLICY proposal, returned VERBATIM.
2690
+ app.post(`${V}/proposals/:id/approve`, { config: { manifest: { responseType: 'ApproveProposalResponse', statusCodes: [200, 400, 502] } } }, async (req, reply) => {
2691
+ const { id } = req.params;
2692
+ if (id.trim() === '') {
2693
+ return reply.code(400).send({ error: '`id` is required' });
2694
+ }
2695
+ try {
2696
+ // TODO: route handed_off policy payload to steering (crew steering-write, DES-MEM-FACETED-001
2697
+ // §5.2). Policy→steering routing is OUT OF SCOPE here: a `handed_off` outcome is passed
2698
+ // through as-is for a later steering-write to consume; memory proposals return `promoted` and
2699
+ // need nothing more.
2700
+ return (await proposalTool('proposal.approve', { id }));
2701
+ }
2702
+ catch (err) {
2703
+ return proposalUpstreamError(reply, err);
2704
+ }
2705
+ });
2706
+ // POST /proposals/:id/reject → proposal.reject → { ok: true }.
2707
+ app.post(`${V}/proposals/:id/reject`, { config: { manifest: { responseType: 'RejectProposalResponse', statusCodes: [200, 400, 502] } } }, async (req, reply) => {
2708
+ const { id } = req.params;
2709
+ if (id.trim() === '') {
2710
+ return reply.code(400).send({ error: '`id` is required' });
2711
+ }
2712
+ try {
2713
+ return (await proposalTool('proposal.reject', { id }));
2714
+ }
2715
+ catch (err) {
2716
+ return proposalUpstreamError(reply, err);
2717
+ }
2718
+ });
2639
2719
  // ── Projects (DES-PROJECT-001) — the 9-route experience-plane surface ────────
2640
2720
  registerProjectRoutes(app, adapter, { ...projects, settings: projectSettings }, security);
2641
2721
  // ── Campaigns (crew#342 + TH-9) — the engine's durable Run-DAG scheduler over REST ──────────