wicked-crew 0.7.0 → 0.7.2
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/README.md +103 -0
- package/dist/api/delivery-index.d.ts +61 -0
- package/dist/api/delivery-index.d.ts.map +1 -0
- package/dist/api/delivery-index.js +87 -0
- package/dist/api/delivery-index.js.map +1 -0
- package/dist/api/endpoint-manifest-live.d.ts +29 -0
- package/dist/api/endpoint-manifest-live.d.ts.map +1 -0
- package/dist/api/endpoint-manifest-live.js +72 -0
- package/dist/api/endpoint-manifest-live.js.map +1 -0
- package/dist/api/endpoint-manifest.d.ts +107 -0
- package/dist/api/endpoint-manifest.d.ts.map +1 -0
- package/dist/api/endpoint-manifest.js +108 -0
- package/dist/api/endpoint-manifest.js.map +1 -0
- package/dist/api/governance-wiki.d.ts +28 -0
- package/dist/api/governance-wiki.d.ts.map +1 -0
- package/dist/api/governance-wiki.js +97 -0
- package/dist/api/governance-wiki.js.map +1 -0
- package/dist/api/requirements.d.ts +7 -0
- package/dist/api/requirements.d.ts.map +1 -1
- package/dist/api/requirements.js +23 -2
- package/dist/api/requirements.js.map +1 -1
- package/dist/api/routes.d.ts +21 -16
- package/dist/api/routes.d.ts.map +1 -1
- package/dist/api/routes.js +129 -12
- package/dist/api/routes.js.map +1 -1
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +106 -5
- package/dist/api/server.js.map +1 -1
- package/dist/campaign/supervision.d.ts +296 -0
- package/dist/campaign/supervision.d.ts.map +1 -0
- package/dist/campaign/supervision.js +515 -0
- package/dist/campaign/supervision.js.map +1 -0
- package/dist/campaigns/plan.d.ts +64 -0
- package/dist/campaigns/plan.d.ts.map +1 -0
- package/dist/campaigns/plan.js +201 -0
- package/dist/campaigns/plan.js.map +1 -0
- package/dist/campaigns/routes.d.ts +28 -0
- package/dist/campaigns/routes.d.ts.map +1 -0
- package/dist/campaigns/routes.js +177 -0
- package/dist/campaigns/routes.js.map +1 -0
- package/dist/cli/index.js +13 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/core/adapter.d.ts +84 -1
- package/dist/core/adapter.d.ts.map +1 -1
- package/dist/core/adapter.js +204 -6
- package/dist/core/adapter.js.map +1 -1
- package/dist/core/deliverable-floor.d.ts +65 -13
- package/dist/core/deliverable-floor.d.ts.map +1 -1
- package/dist/core/deliverable-floor.js +96 -21
- package/dist/core/deliverable-floor.js.map +1 -1
- package/dist/interactive/bridge-pool.d.ts +24 -0
- package/dist/interactive/bridge-pool.d.ts.map +1 -1
- package/dist/interactive/bridge-pool.js +26 -2
- package/dist/interactive/bridge-pool.js.map +1 -1
- package/dist/interactive/edit-events.d.ts +3 -2
- package/dist/interactive/edit-events.d.ts.map +1 -1
- package/dist/interactive/edit-events.js +15 -7
- package/dist/interactive/edit-events.js.map +1 -1
- package/dist/projects/graph-paths.d.ts +32 -2
- package/dist/projects/graph-paths.d.ts.map +1 -1
- package/dist/projects/graph-paths.js +49 -4
- package/dist/projects/graph-paths.js.map +1 -1
- package/dist/projects/graph.d.ts +13 -1
- package/dist/projects/graph.d.ts.map +1 -1
- package/dist/projects/graph.js +73 -19
- package/dist/projects/graph.js.map +1 -1
- package/dist/projects/routes.d.ts +12 -2
- package/dist/projects/routes.d.ts.map +1 -1
- package/dist/projects/routes.js +18 -1
- package/dist/projects/routes.js.map +1 -1
- package/dist/qe/acceptance.d.ts +20 -1
- package/dist/qe/acceptance.d.ts.map +1 -1
- package/dist/qe/acceptance.js +32 -0
- package/dist/qe/acceptance.js.map +1 -1
- package/dist/qe/conformance.d.ts +158 -0
- package/dist/qe/conformance.d.ts.map +1 -0
- package/dist/qe/conformance.js +244 -0
- package/dist/qe/conformance.js.map +1 -0
- package/dist/qe/ledger.d.ts +3 -2
- package/dist/qe/ledger.d.ts.map +1 -1
- package/dist/qe/ledger.js +5 -4
- package/dist/qe/ledger.js.map +1 -1
- package/dist/studio/assets/index-C8rx24F1.js +530 -0
- package/dist/studio/assets/index-CwmIj-f2.css +32 -0
- package/dist/studio/index.html +2 -2
- package/dist/studio/testid-inventory.json +3924 -0
- package/endpoint-manifest.json +704 -0
- package/package.json +8 -5
- package/dist/studio/assets/index-8p8uwCxG.js +0 -530
- package/dist/studio/assets/index-D6S9zUtO.css +0 -32
package/dist/core/adapter.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CoreEvent, LaunchRunInput, RepoEntry, RepoOnboardRef, SessionView, RecordedEvent, GovernancePolicy, ConformanceRule, GovernanceClaim, CoverageReport, GraphKind, WorkflowDef, CrewSystemSettings, Project, ProjectMember, InteractionRequest } from './types.js';
|
|
1
|
+
import type { CoreEvent, LaunchRunInput, RepoEntry, RepoOnboardRef, SessionView, RecordedEvent, GovernancePolicy, ConformanceRule, GovernanceScoreboard, GovernanceClaim, CoverageReport, GraphKind, WorkflowDef, CrewSystemSettings, Project, ProjectMember, InteractionRequest, Campaign, CampaignDef } from './types.js';
|
|
2
2
|
/** Where the daemon persists system settings. Exported so tests write fixtures to the ONE
|
|
3
3
|
* spelling of this path (the tests/ tree is audited against spelling core paths itself). */
|
|
4
4
|
export declare function settingsFilePath(): string;
|
|
@@ -45,6 +45,27 @@ export declare class ProjectsUnsupportedError extends Error {
|
|
|
45
45
|
export declare class ElicitationUnsupportedError extends Error {
|
|
46
46
|
constructor(message: string);
|
|
47
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* The campaign surface (DES-CAMPAIGN-001 / TH-9) is not available in this deployment — the
|
|
50
|
+
* installed wicked-core-ts predates the campaign bindings. Typed for the same reason as
|
|
51
|
+
* `ChatUnsupportedError`: the routes answer 501 ("upgrade the engine") on this, never 400
|
|
52
|
+
* ("fix your request"). Gated on METHOD PRESENCE rather than a version floor because the
|
|
53
|
+
* bindings ship in the next core-ts release whose number is the release train's to pick —
|
|
54
|
+
* a presence check is true on whatever version actually carries them.
|
|
55
|
+
*/
|
|
56
|
+
export declare class CampaignsUnsupportedError extends Error {
|
|
57
|
+
constructor(what: string);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The wiki scoreboard (AW-23 / wiki-mgmt) is not available in this deployment — the installed
|
|
61
|
+
* wicked-core-ts predates the `governanceScoreboard` binding (ships in ≥ 0.7.4). Typed for the
|
|
62
|
+
* same reason as `ChatUnsupportedError`: the route answers 501 ("upgrade the engine") on this,
|
|
63
|
+
* never 400 ("fix your request"). Gated on METHOD PRESENCE, the campaigns doctrine — true on
|
|
64
|
+
* whatever release actually carries the binding.
|
|
65
|
+
*/
|
|
66
|
+
export declare class GovernanceScoreboardUnsupportedError extends Error {
|
|
67
|
+
constructor(what: string);
|
|
68
|
+
}
|
|
48
69
|
/** One live chat on the enumerate surface — see {@link CoreAdapter.chatList}. */
|
|
49
70
|
export interface ChatSummary {
|
|
50
71
|
chatId: string;
|
|
@@ -103,6 +124,18 @@ export declare class CoreAdapter {
|
|
|
103
124
|
readonly engineExec: boolean;
|
|
104
125
|
/** The bus db the exec seam runs over when armed (else `undefined`). */
|
|
105
126
|
readonly busDbPath: string | undefined;
|
|
127
|
+
/**
|
|
128
|
+
* `true` when this adapter drives the DETERMINISTIC OFFLINE engine (`Core.spawnStub`) rather
|
|
129
|
+
* than the production one — i.e. the `StubDispatcher` (every seat votes for the first roster
|
|
130
|
+
* option, no subprocess) plus the `StubStepRunner` (fixed text, no CLI).
|
|
131
|
+
*
|
|
132
|
+
* Exposed, not private, because a stub engine is not a quieter production engine — it is a
|
|
133
|
+
* FABRICATOR. Every phase resolves Ok in under a millisecond, so a run narrates its whole
|
|
134
|
+
* governed lifecycle, gate approvals included, with no work behind any of it. Anything that
|
|
135
|
+
* lets this daemon answer OTHER products' traffic has to be able to ask (see
|
|
136
|
+
* `api/server.ts`, crew#309).
|
|
137
|
+
*/
|
|
138
|
+
readonly stub: boolean;
|
|
106
139
|
constructor(opts: CoreAdapterOptions);
|
|
107
140
|
/** Register a CoreEvent listener. Returns an unsubscribe function. */
|
|
108
141
|
onEvent(listener: CoreEventListener): () => void;
|
|
@@ -118,6 +151,32 @@ export declare class CoreAdapter {
|
|
|
118
151
|
confirmGate(runId: string, approve: boolean, amend?: string): Promise<string>;
|
|
119
152
|
/** Cancel a run → the status token. */
|
|
120
153
|
cancelRun(runId: string): Promise<string>;
|
|
154
|
+
/** Whether the installed engine addon carries the campaign bindings. */
|
|
155
|
+
campaignsSupported(): boolean;
|
|
156
|
+
/** Guard: the campaign binding surface, or a typed 501-shaped refusal naming the action. */
|
|
157
|
+
private _campaigns;
|
|
158
|
+
/** Validate + launch a campaign DAG → the campaign id. `def` is the ENGINE wire shape
|
|
159
|
+
* (snake_case) — `campaigns/plan.ts` is the one producer of it in this daemon.
|
|
160
|
+
*
|
|
161
|
+
* `workflows` are the composed per-node Tool workflows the def's run_specs reference; they
|
|
162
|
+
* are armed FIRST (hot-register + overlay persist) so the engine can resolve them both now
|
|
163
|
+
* and after a restart — a campaign is durable, so its node workflows must be too. Unlike a
|
|
164
|
+
* deliver-composed def they are NOT purely ephemeral (`_armPerRunWorkflow`), and unlike a
|
|
165
|
+
* user workflow they never enter `userWorkflows` or the catalog (the hydration filter in
|
|
166
|
+
* `readOverlayWorkflows` skips the `campaign-` prefix). */
|
|
167
|
+
launchCampaign(def: CampaignDef, workflows?: WorkflowDef[]): Promise<string>;
|
|
168
|
+
/** Arm one composed campaign-node workflow: validate-then-persist (the FINDING-002 ordering —
|
|
169
|
+
* core's parser is the authority and runs BEFORE the overlay write), overlay file for
|
|
170
|
+
* restart durability, no `userWorkflows` entry. */
|
|
171
|
+
private _armCampaignWorkflow;
|
|
172
|
+
/** Resume a campaign from its persisted state → the campaign status token. */
|
|
173
|
+
resumeCampaign(id: string): Promise<string>;
|
|
174
|
+
/** Cancel a campaign (in-flight node Runs cancelled, the rest marked) → the status token. */
|
|
175
|
+
cancelCampaign(id: string): Promise<string>;
|
|
176
|
+
/** A campaign's full persisted state (DAG + node statuses + run ids), or `null` when unknown. */
|
|
177
|
+
campaignDetail(id: string): Promise<Campaign | null>;
|
|
178
|
+
/** Every campaign on the store. */
|
|
179
|
+
campaignList(): Promise<Campaign[]>;
|
|
121
180
|
/**
|
|
122
181
|
* Archive (or unarchive) a TERMINAL run (crew#265) — write-off, not delete. Resolves `true`
|
|
123
182
|
* when the session existed, `false` for an unknown id (→ 404); REJECTS when the run is
|
|
@@ -285,6 +344,30 @@ export declare class CoreAdapter {
|
|
|
285
344
|
retireConformanceRule(id: string): Promise<boolean>;
|
|
286
345
|
/** Recall conformance rules matching a facet query (read-only, does not block actor). */
|
|
287
346
|
recallRulesPreview(query: Record<string, string | string[] | undefined>): Promise<ConformanceRule[]>;
|
|
347
|
+
/** Whether the installed engine addon carries the AW-23 scoreboard binding (core-ts ≥ 0.7.4). */
|
|
348
|
+
wikiScoreboardSupported(): boolean;
|
|
349
|
+
/**
|
|
350
|
+
* The wiki population/connection scoreboard (AW-23 / arch-R23) — typed %, resolving %,
|
|
351
|
+
* enforcement evidence, and an in-band honesty marker for what cannot be measured. Read-only
|
|
352
|
+
* on the engine side (`open_store_ro`), so it never blocks the single-writer actor.
|
|
353
|
+
*
|
|
354
|
+
* `docsRoot` is the same docs root `rules ingest --dir` used; omitted, the typing half reports
|
|
355
|
+
* `available: false` with the reason — an honest in-band answer, not an error.
|
|
356
|
+
*
|
|
357
|
+
* Presence-gated (the campaigns doctrine): throws {@link GovernanceScoreboardUnsupportedError}
|
|
358
|
+
* on an addon that predates the binding, which the route maps to 501 ("upgrade the engine").
|
|
359
|
+
*/
|
|
360
|
+
governanceScoreboard(docsRoot?: string): Promise<GovernanceScoreboard>;
|
|
361
|
+
/**
|
|
362
|
+
* How many `RuleSet` rows (doctrine domain parents, AW-13) the store holds — or `null` when
|
|
363
|
+
* this engine build cannot count them (no `listRuleSets` binding yet).
|
|
364
|
+
*
|
|
365
|
+
* `null` rather than `0` on purpose (the `runEvents` doctrine): "no rulesets" is a real answer
|
|
366
|
+
* about an unseeded store, and "I cannot count" must never impersonate it — the wiki meta's
|
|
367
|
+
* empty state would otherwise report a seeded store as empty and point the operator at a
|
|
368
|
+
* runbook they already ran.
|
|
369
|
+
*/
|
|
370
|
+
countRuleSets(): Promise<number | null>;
|
|
288
371
|
private readonly userWorkflows;
|
|
289
372
|
/** Whether {@link hydrateFromOverlay} has run this process lifetime. */
|
|
290
373
|
private overlayHydrated;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/core/adapter.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,SAAS,EACT,cAAc,EACd,SAAS,EACT,cAAc,EACd,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,cAAc,EACd,SAAS,EACT,WAAW,EACX,kBAAkB,EAClB,OAAO,EACP,aAAa,EACb,kBAAkB,
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../src/core/adapter.ts"],"names":[],"mappings":"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"}
|
package/dist/core/adapter.js
CHANGED
|
@@ -8,6 +8,7 @@ import { randomUUID } from 'node:crypto';
|
|
|
8
8
|
import { DEFAULT_SETTINGS } from './types.js';
|
|
9
9
|
import { execCapped } from './exec.js';
|
|
10
10
|
import { composeDeliverWorkflow, DELIVER_PHASE_ID } from './deliver.js';
|
|
11
|
+
import { CAMPAIGN_WORKFLOW_PREFIX } from '../campaigns/plan.js';
|
|
11
12
|
import { composeDeliverableFloor } from './deliverable-floor.js';
|
|
12
13
|
/** Resolved path under the user's home directory. */
|
|
13
14
|
function wickedDir(...parts) {
|
|
@@ -50,6 +51,15 @@ function workflowOverlayDir() {
|
|
|
50
51
|
export function settingsFilePath() {
|
|
51
52
|
return join(homedir(), '.config', 'wicked-core', 'settings.json');
|
|
52
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Per-key ceiling on a `studio.*` settings value, as the UTF-8 byte length of its JSON form.
|
|
56
|
+
*
|
|
57
|
+
* The same 512KiB limit `PUT /settings` enforces (`STUDIO_SETTINGS_MAX_BYTES`, api/routes.ts) —
|
|
58
|
+
* restated rather than imported because routes.ts imports THIS module, so a shared constant here
|
|
59
|
+
* would close an import cycle. The two spellings must stay in step; the read-path test restates
|
|
60
|
+
* the number a third time so a change to either side breaks a test rather than a deployment.
|
|
61
|
+
*/
|
|
62
|
+
const STUDIO_SETTINGS_MAX_BYTES = 512 * 1024;
|
|
53
63
|
/** Read user-registered workflow overlays from `dir` (the same dir `registerWorkflow` writes to).
|
|
54
64
|
*
|
|
55
65
|
* Skips: files whose id matches a built-in (those are `_writeBuiltinOverlay` artifacts written FOR
|
|
@@ -73,6 +83,11 @@ export function readOverlayWorkflows(dir, builtinIds) {
|
|
|
73
83
|
const id = file.slice(0, -'.json'.length);
|
|
74
84
|
if (builtinIds.has(id))
|
|
75
85
|
continue; // a built-in overlay, not a user workflow
|
|
86
|
+
// A composed campaign-node workflow (TH-9): persisted here so the Rust actor reloads it at
|
|
87
|
+
// startup (a fresh-process resumeCampaign re-dispatches pending nodes by workflow id), but
|
|
88
|
+
// it is one node's private plumbing, not a user workflow — keep it out of the catalog.
|
|
89
|
+
if (id.startsWith(CAMPAIGN_WORKFLOW_PREFIX))
|
|
90
|
+
continue;
|
|
76
91
|
try {
|
|
77
92
|
const def = JSON.parse(readFileSync(join(dir, file), 'utf8'));
|
|
78
93
|
if (def && typeof def.id === 'string' && Array.isArray(def.phases))
|
|
@@ -384,6 +399,35 @@ export class ElicitationUnsupportedError extends Error {
|
|
|
384
399
|
this.name = 'ElicitationUnsupportedError';
|
|
385
400
|
}
|
|
386
401
|
}
|
|
402
|
+
/**
|
|
403
|
+
* The campaign surface (DES-CAMPAIGN-001 / TH-9) is not available in this deployment — the
|
|
404
|
+
* installed wicked-core-ts predates the campaign bindings. Typed for the same reason as
|
|
405
|
+
* `ChatUnsupportedError`: the routes answer 501 ("upgrade the engine") on this, never 400
|
|
406
|
+
* ("fix your request"). Gated on METHOD PRESENCE rather than a version floor because the
|
|
407
|
+
* bindings ship in the next core-ts release whose number is the release train's to pick —
|
|
408
|
+
* a presence check is true on whatever version actually carries them.
|
|
409
|
+
*/
|
|
410
|
+
export class CampaignsUnsupportedError extends Error {
|
|
411
|
+
constructor(what) {
|
|
412
|
+
super(`${what} is not supported by this wicked-core build (the installed wicked-core-ts has ` +
|
|
413
|
+
'no campaign bindings — upgrade it to a release carrying launchCampaign)');
|
|
414
|
+
this.name = 'CampaignsUnsupportedError';
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* The wiki scoreboard (AW-23 / wiki-mgmt) is not available in this deployment — the installed
|
|
419
|
+
* wicked-core-ts predates the `governanceScoreboard` binding (ships in ≥ 0.7.4). Typed for the
|
|
420
|
+
* same reason as `ChatUnsupportedError`: the route answers 501 ("upgrade the engine") on this,
|
|
421
|
+
* never 400 ("fix your request"). Gated on METHOD PRESENCE, the campaigns doctrine — true on
|
|
422
|
+
* whatever release actually carries the binding.
|
|
423
|
+
*/
|
|
424
|
+
export class GovernanceScoreboardUnsupportedError extends Error {
|
|
425
|
+
constructor(what) {
|
|
426
|
+
super(`${what} is not supported by this wicked-core build (the installed wicked-core-ts has ` +
|
|
427
|
+
'no governanceScoreboard binding — upgrade it to a release carrying it, >= 0.7.4)');
|
|
428
|
+
this.name = 'GovernanceScoreboardUnsupportedError';
|
|
429
|
+
}
|
|
430
|
+
}
|
|
387
431
|
/** The engine's own way of reporting a build that cannot do chat, raised at call time. */
|
|
388
432
|
const ENGINE_CHAT_UNSUPPORTED = /chat unsupported/i;
|
|
389
433
|
/**
|
|
@@ -476,6 +520,18 @@ export class CoreAdapter {
|
|
|
476
520
|
engineExec;
|
|
477
521
|
/** The bus db the exec seam runs over when armed (else `undefined`). */
|
|
478
522
|
busDbPath;
|
|
523
|
+
/**
|
|
524
|
+
* `true` when this adapter drives the DETERMINISTIC OFFLINE engine (`Core.spawnStub`) rather
|
|
525
|
+
* than the production one — i.e. the `StubDispatcher` (every seat votes for the first roster
|
|
526
|
+
* option, no subprocess) plus the `StubStepRunner` (fixed text, no CLI).
|
|
527
|
+
*
|
|
528
|
+
* Exposed, not private, because a stub engine is not a quieter production engine — it is a
|
|
529
|
+
* FABRICATOR. Every phase resolves Ok in under a millisecond, so a run narrates its whole
|
|
530
|
+
* governed lifecycle, gate approvals included, with no work behind any of it. Anything that
|
|
531
|
+
* lets this daemon answer OTHER products' traffic has to be able to ask (see
|
|
532
|
+
* `api/server.ts`, crew#309).
|
|
533
|
+
*/
|
|
534
|
+
stub;
|
|
479
535
|
constructor(opts) {
|
|
480
536
|
// Arm the EVENT-DRIVEN execution-mediation seam BEFORE spawning the Core: the Rust actor reads
|
|
481
537
|
// `WICKED_BUS_EXEC` + `WICKED_BUS_DB` from the process env at spawn time (wicked-core actor::run),
|
|
@@ -505,7 +561,8 @@ export class CoreAdapter {
|
|
|
505
561
|
if (wcExe)
|
|
506
562
|
process.env['WICKED_CORE_EXE'] = wcExe;
|
|
507
563
|
}
|
|
508
|
-
this.
|
|
564
|
+
this.stub = opts.stub === true;
|
|
565
|
+
this.core = this.stub ? Core.spawnStub(opts.dbPath) : Core.spawn(opts.dbPath);
|
|
509
566
|
// The ONE subscribe() for the process. Error-first callback (index.d.ts:56):
|
|
510
567
|
// one JSON string per CoreEvent, in emission order. A throw in a listener is
|
|
511
568
|
// isolated so one bad consumer can never stall the pump or the others.
|
|
@@ -623,11 +680,19 @@ export class CoreAdapter {
|
|
|
623
680
|
if (composed !== null && requireDeliverables.length > 0) {
|
|
624
681
|
// THE DELIVERABLE FLOOR (crew#311): "done" is re-derived from the artifact. The
|
|
625
682
|
// launcher declared what this run must produce, so a deterministic Tool phase appended
|
|
626
|
-
// here re-verifies that those files EXIST
|
|
627
|
-
// what was expected and what was found when they do not.
|
|
628
|
-
// phase below so the floor sits ahead of it: a run that
|
|
629
|
-
// rather than open a pull request over an empty branch.
|
|
630
|
-
|
|
683
|
+
// here re-verifies that those files EXIST, carry bytes, and were written by THIS RUN,
|
|
684
|
+
// and fails the run naming what was expected and what was found when they do not.
|
|
685
|
+
// Composed BEFORE the deliver phase below so the floor sits ahead of it: a run that
|
|
686
|
+
// produced nothing must fail rather than open a pull request over an empty branch.
|
|
687
|
+
//
|
|
688
|
+
// The timestamp is taken HERE, at composition — the last moment before `core.launchRun`
|
|
689
|
+
// below — and passed explicitly rather than left to the default, because the whole
|
|
690
|
+
// freshness claim rests on it: nothing this run produces can predate this line, so an
|
|
691
|
+
// artifact whose mtime does is a PRIOR run's leftover (crew#320). The interactive seams
|
|
692
|
+
// copy their deliverable to `outPath` and never remove it, and their run dirs are keyed
|
|
693
|
+
// by document id, so a re-run over the same key finds the previous file already there;
|
|
694
|
+
// without this the floor would pass on it and "done" would be asserted by a leftover.
|
|
695
|
+
composed = composeDeliverableFloor(composed, input.sessionId, requireDeliverables, Date.now());
|
|
631
696
|
}
|
|
632
697
|
if (composed !== null && input.deliver === 'pr') {
|
|
633
698
|
// First-class delivery (crew#293): compose a PER-RUN def — the selected workflow's
|
|
@@ -704,6 +769,77 @@ export class CoreAdapter {
|
|
|
704
769
|
cancelRun(runId) {
|
|
705
770
|
return this.core.cancelRun(runId);
|
|
706
771
|
}
|
|
772
|
+
// ── Campaigns (DES-CAMPAIGN-001 / crew#342 + TH-9) ─────────────────────────
|
|
773
|
+
// The engine is the campaign store — durable, single-writer, crash-resumable (its Campaign
|
|
774
|
+
// rows persist beside AgentSessions on the same estate substrate). Crew keeps NO shadow copy:
|
|
775
|
+
// every read below asks the engine, so a daemon restart or a second daemon over the same db
|
|
776
|
+
// sees the same campaigns. `launchCampaign` is gated on METHOD PRESENCE (not a version floor)
|
|
777
|
+
// because the bindings ship in whatever core-ts release the train cuts next.
|
|
778
|
+
/** Whether the installed engine addon carries the campaign bindings. */
|
|
779
|
+
campaignsSupported() {
|
|
780
|
+
return typeof this.core.launchCampaign === 'function';
|
|
781
|
+
}
|
|
782
|
+
/** Guard: the campaign binding surface, or a typed 501-shaped refusal naming the action. */
|
|
783
|
+
_campaigns(what) {
|
|
784
|
+
if (typeof this.core.launchCampaign !== 'function' ||
|
|
785
|
+
typeof this.core.resumeCampaign !== 'function' ||
|
|
786
|
+
typeof this.core.cancelCampaign !== 'function' ||
|
|
787
|
+
typeof this.core.campaignDetail !== 'function' ||
|
|
788
|
+
typeof this.core.campaignList !== 'function') {
|
|
789
|
+
throw new CampaignsUnsupportedError(what);
|
|
790
|
+
}
|
|
791
|
+
return this.core;
|
|
792
|
+
}
|
|
793
|
+
/** Validate + launch a campaign DAG → the campaign id. `def` is the ENGINE wire shape
|
|
794
|
+
* (snake_case) — `campaigns/plan.ts` is the one producer of it in this daemon.
|
|
795
|
+
*
|
|
796
|
+
* `workflows` are the composed per-node Tool workflows the def's run_specs reference; they
|
|
797
|
+
* are armed FIRST (hot-register + overlay persist) so the engine can resolve them both now
|
|
798
|
+
* and after a restart — a campaign is durable, so its node workflows must be too. Unlike a
|
|
799
|
+
* deliver-composed def they are NOT purely ephemeral (`_armPerRunWorkflow`), and unlike a
|
|
800
|
+
* user workflow they never enter `userWorkflows` or the catalog (the hydration filter in
|
|
801
|
+
* `readOverlayWorkflows` skips the `campaign-` prefix). */
|
|
802
|
+
async launchCampaign(def, workflows = []) {
|
|
803
|
+
const surface = this._campaigns('Launching a campaign');
|
|
804
|
+
for (const wf of workflows) {
|
|
805
|
+
await this._armCampaignWorkflow(wf);
|
|
806
|
+
}
|
|
807
|
+
return surface.launchCampaign(JSON.stringify(def));
|
|
808
|
+
}
|
|
809
|
+
/** Arm one composed campaign-node workflow: validate-then-persist (the FINDING-002 ordering —
|
|
810
|
+
* core's parser is the authority and runs BEFORE the overlay write), overlay file for
|
|
811
|
+
* restart durability, no `userWorkflows` entry. */
|
|
812
|
+
async _armCampaignWorkflow(def) {
|
|
813
|
+
const core = this.core;
|
|
814
|
+
const register = core['registerWorkflow'];
|
|
815
|
+
if (typeof register !== 'function') {
|
|
816
|
+
// Unreachable on any addon that carries launchCampaign (registerWorkflow predates it by
|
|
817
|
+
// several releases), but the guard keeps the failure loud if that ever un-holds.
|
|
818
|
+
throw new CampaignsUnsupportedError('Arming a campaign node workflow');
|
|
819
|
+
}
|
|
820
|
+
await register.call(this.core, JSON.stringify(def));
|
|
821
|
+
const dir = workflowOverlayDir();
|
|
822
|
+
await mkdir(dir, { recursive: true });
|
|
823
|
+
await writeFile(join(dir, `${def.id}.json`), JSON.stringify(def, null, 2), 'utf8');
|
|
824
|
+
}
|
|
825
|
+
/** Resume a campaign from its persisted state → the campaign status token. */
|
|
826
|
+
resumeCampaign(id) {
|
|
827
|
+
return this._campaigns('Resuming a campaign').resumeCampaign(id);
|
|
828
|
+
}
|
|
829
|
+
/** Cancel a campaign (in-flight node Runs cancelled, the rest marked) → the status token. */
|
|
830
|
+
cancelCampaign(id) {
|
|
831
|
+
return this._campaigns('Cancelling a campaign').cancelCampaign(id);
|
|
832
|
+
}
|
|
833
|
+
/** A campaign's full persisted state (DAG + node statuses + run ids), or `null` when unknown. */
|
|
834
|
+
async campaignDetail(id) {
|
|
835
|
+
const raw = await this._campaigns('Reading a campaign').campaignDetail(id);
|
|
836
|
+
return parseEngineJson(raw, 'campaignDetail');
|
|
837
|
+
}
|
|
838
|
+
/** Every campaign on the store. */
|
|
839
|
+
async campaignList() {
|
|
840
|
+
const raw = await this._campaigns('Listing campaigns').campaignList();
|
|
841
|
+
return parseEngineJson(raw, 'campaignList');
|
|
842
|
+
}
|
|
707
843
|
/**
|
|
708
844
|
* Archive (or unarchive) a TERMINAL run (crew#265) — write-off, not delete. Resolves `true`
|
|
709
845
|
* when the session existed, `false` for an unknown id (→ 404); REJECTS when the run is
|
|
@@ -1162,6 +1298,45 @@ export class CoreAdapter {
|
|
|
1162
1298
|
const json = await this.core.recallRulesPreview(JSON.stringify(cleanQuery));
|
|
1163
1299
|
return JSON.parse(json);
|
|
1164
1300
|
}
|
|
1301
|
+
// ── Governance wiki management (wiki-mgmt) ─────────────────────────────────
|
|
1302
|
+
/** Whether the installed engine addon carries the AW-23 scoreboard binding (core-ts ≥ 0.7.4). */
|
|
1303
|
+
wikiScoreboardSupported() {
|
|
1304
|
+
return typeof this.core.governanceScoreboard === 'function';
|
|
1305
|
+
}
|
|
1306
|
+
/**
|
|
1307
|
+
* The wiki population/connection scoreboard (AW-23 / arch-R23) — typed %, resolving %,
|
|
1308
|
+
* enforcement evidence, and an in-band honesty marker for what cannot be measured. Read-only
|
|
1309
|
+
* on the engine side (`open_store_ro`), so it never blocks the single-writer actor.
|
|
1310
|
+
*
|
|
1311
|
+
* `docsRoot` is the same docs root `rules ingest --dir` used; omitted, the typing half reports
|
|
1312
|
+
* `available: false` with the reason — an honest in-band answer, not an error.
|
|
1313
|
+
*
|
|
1314
|
+
* Presence-gated (the campaigns doctrine): throws {@link GovernanceScoreboardUnsupportedError}
|
|
1315
|
+
* on an addon that predates the binding, which the route maps to 501 ("upgrade the engine").
|
|
1316
|
+
*/
|
|
1317
|
+
async governanceScoreboard(docsRoot) {
|
|
1318
|
+
const fn = this.core.governanceScoreboard;
|
|
1319
|
+
if (typeof fn !== 'function') {
|
|
1320
|
+
throw new GovernanceScoreboardUnsupportedError('Reading the governance wiki scoreboard');
|
|
1321
|
+
}
|
|
1322
|
+
return parseEngineJson(await fn.call(this.core, docsRoot ?? null), 'governanceScoreboard');
|
|
1323
|
+
}
|
|
1324
|
+
/**
|
|
1325
|
+
* How many `RuleSet` rows (doctrine domain parents, AW-13) the store holds — or `null` when
|
|
1326
|
+
* this engine build cannot count them (no `listRuleSets` binding yet).
|
|
1327
|
+
*
|
|
1328
|
+
* `null` rather than `0` on purpose (the `runEvents` doctrine): "no rulesets" is a real answer
|
|
1329
|
+
* about an unseeded store, and "I cannot count" must never impersonate it — the wiki meta's
|
|
1330
|
+
* empty state would otherwise report a seeded store as empty and point the operator at a
|
|
1331
|
+
* runbook they already ran.
|
|
1332
|
+
*/
|
|
1333
|
+
async countRuleSets() {
|
|
1334
|
+
const fn = this.core.listRuleSets;
|
|
1335
|
+
if (typeof fn !== 'function')
|
|
1336
|
+
return null;
|
|
1337
|
+
const rows = parseEngineJson(await fn.call(this.core), 'listRuleSets');
|
|
1338
|
+
return Array.isArray(rows) ? rows.length : null;
|
|
1339
|
+
}
|
|
1165
1340
|
// ── Workflow viewer + builder (crew#44) ────────────────────────────────────
|
|
1166
1341
|
// Built-ins are static TypeScript mirrors of workflow.rs. User-registered
|
|
1167
1342
|
// workflows are added to `userWorkflows` and persisted to disk; the Rust actor
|
|
@@ -1389,6 +1564,29 @@ export class CoreAdapter {
|
|
|
1389
1564
|
if (typeof r !== 'string' || (r !== '' && !isAbsolute(r)))
|
|
1390
1565
|
delete parsed.worker_config_root;
|
|
1391
1566
|
}
|
|
1567
|
+
// Skin-owned `studio.*` blobs (crew#325): the same per-key cap the PUT /settings route
|
|
1568
|
+
// enforces. The write cap alone cannot hold it — `updateSettings` reads through here, so a
|
|
1569
|
+
// value hand-edited past the cap is served in full AND carried forward by a later patch that
|
|
1570
|
+
// never names it, which makes the ceiling un-lowerable. Dropped LOUDLY: the daemon cannot
|
|
1571
|
+
// interpret these values, so an operator whose theme "reset itself" has nothing to go on
|
|
1572
|
+
// unless the drop names the key and the limit (silence is what made #323 invisible).
|
|
1573
|
+
// Namespace prefix, not the route's stricter key regex — the cap is about bytes in
|
|
1574
|
+
// settings.json, and a hand-edited `studio.Foo` the route would never have admitted costs
|
|
1575
|
+
// exactly as much to store and to propagate.
|
|
1576
|
+
const bag = parsed;
|
|
1577
|
+
for (const key of Object.keys(bag)) {
|
|
1578
|
+
if (!key.startsWith('studio.'))
|
|
1579
|
+
continue;
|
|
1580
|
+
const bytes = Buffer.byteLength(JSON.stringify(bag[key]), 'utf8');
|
|
1581
|
+
if (bytes > STUDIO_SETTINGS_MAX_BYTES) {
|
|
1582
|
+
delete bag[key];
|
|
1583
|
+
console.warn(`[settings] dropped ${key} from ${settingsFilePath()}: ${bytes} bytes of JSON, over ` +
|
|
1584
|
+
`the ${STUDIO_SETTINGS_MAX_BYTES}-byte per-key cap on studio.* settings. PUT ` +
|
|
1585
|
+
`/settings refuses a write this size, so this value was hand-edited in or predates ` +
|
|
1586
|
+
`the cap; it is dropped on read rather than served and rewritten forward. Shrink it ` +
|
|
1587
|
+
`in the file to get it back — nothing else in settings.json is affected (crew#325).`);
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1392
1590
|
return { ...DEFAULT_SETTINGS, ...parsed };
|
|
1393
1591
|
}
|
|
1394
1592
|
catch {
|