wicked-crew 0.9.2 → 0.9.4

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 (75) hide show
  1. package/dist/api/delivery-assurance.d.ts +22 -1
  2. package/dist/api/delivery-assurance.d.ts.map +1 -1
  3. package/dist/api/delivery-assurance.js +66 -2
  4. package/dist/api/delivery-assurance.js.map +1 -1
  5. package/dist/api/routes.d.ts +148 -8
  6. package/dist/api/routes.d.ts.map +1 -1
  7. package/dist/api/routes.js +59 -19
  8. package/dist/api/routes.js.map +1 -1
  9. package/dist/api/server.d.ts.map +1 -1
  10. package/dist/api/server.js +31 -31
  11. package/dist/api/server.js.map +1 -1
  12. package/dist/cli/index.d.ts.map +1 -1
  13. package/dist/cli/index.js +32 -1
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/cli/service.js +1 -1
  16. package/dist/cli/service.js.map +1 -1
  17. package/dist/core/adapter.d.ts +21 -3
  18. package/dist/core/adapter.d.ts.map +1 -1
  19. package/dist/core/adapter.js +72 -18
  20. package/dist/core/adapter.js.map +1 -1
  21. package/dist/core/ado-deliver-helper.d.ts +5 -0
  22. package/dist/core/ado-deliver-helper.d.ts.map +1 -1
  23. package/dist/core/ado-deliver-helper.js +50 -2
  24. package/dist/core/ado-deliver-helper.js.map +1 -1
  25. package/dist/core/deliver-credentials.d.ts +8 -4
  26. package/dist/core/deliver-credentials.d.ts.map +1 -1
  27. package/dist/core/deliver-credentials.js +25 -7
  28. package/dist/core/deliver-credentials.js.map +1 -1
  29. package/dist/core/deliver-text.d.ts +8 -0
  30. package/dist/core/deliver-text.d.ts.map +1 -1
  31. package/dist/core/deliver-text.js +16 -0
  32. package/dist/core/deliver-text.js.map +1 -1
  33. package/dist/core/deliver.d.ts +22 -18
  34. package/dist/core/deliver.d.ts.map +1 -1
  35. package/dist/core/deliver.js +168 -79
  36. package/dist/core/deliver.js.map +1 -1
  37. package/dist/core/types.d.ts +7 -0
  38. package/dist/core/types.d.ts.map +1 -1
  39. package/dist/core/types.js.map +1 -1
  40. package/dist/interactive/chat-events.d.ts +11 -20
  41. package/dist/interactive/chat-events.d.ts.map +1 -1
  42. package/dist/interactive/chat-events.js +69 -108
  43. package/dist/interactive/chat-events.js.map +1 -1
  44. package/dist/interactive/draft-events.d.ts +13 -46
  45. package/dist/interactive/draft-events.d.ts.map +1 -1
  46. package/dist/interactive/draft-events.js +81 -130
  47. package/dist/interactive/draft-events.js.map +1 -1
  48. package/dist/interactive/draft-skill.d.ts +11 -19
  49. package/dist/interactive/draft-skill.d.ts.map +1 -1
  50. package/dist/interactive/draft-skill.js +16 -31
  51. package/dist/interactive/draft-skill.js.map +1 -1
  52. package/dist/interactive/edit-events.d.ts +11 -21
  53. package/dist/interactive/edit-events.d.ts.map +1 -1
  54. package/dist/interactive/edit-events.js +70 -83
  55. package/dist/interactive/edit-events.js.map +1 -1
  56. package/dist/interactive/run-units.d.ts +91 -0
  57. package/dist/interactive/run-units.d.ts.map +1 -0
  58. package/dist/interactive/run-units.js +149 -0
  59. package/dist/interactive/run-units.js.map +1 -0
  60. package/dist/skills/core-closure.d.ts +26 -0
  61. package/dist/skills/core-closure.d.ts.map +1 -1
  62. package/dist/skills/core-closure.js +45 -0
  63. package/dist/skills/core-closure.js.map +1 -1
  64. package/dist/skills/phase-skill-gaps.d.ts +16 -71
  65. package/dist/skills/phase-skill-gaps.d.ts.map +1 -1
  66. package/dist/skills/phase-skill-gaps.js +16 -145
  67. package/dist/skills/phase-skill-gaps.js.map +1 -1
  68. package/dist/studio/assets/{index-BLYKfepE.css → index-BGfFmWw4.css} +1 -1
  69. package/dist/studio/assets/{index-BbXtfDnB.js → index-BMRUMU4X.js} +112 -112
  70. package/dist/studio/editors/wicked-page/editor.json +1 -1
  71. package/dist/studio/editors/wicked-page/index.html +1 -1
  72. package/dist/studio/index.html +2 -2
  73. package/dist/studio/testid-inventory.json +83 -5
  74. package/endpoint-manifest.json +1 -1
  75. package/package.json +3 -3
@@ -8,7 +8,7 @@ import { readFileSync, existsSync } from 'node:fs';
8
8
  import { promises as fsp } from 'node:fs';
9
9
  import { isAbsolute, join, relative, resolve } from 'node:path';
10
10
  import { fileURLToPath } from 'node:url';
11
- import { CampaignsUnsupportedError, ChatUnsupportedError, CoreAdapter, ElicitationUnsupportedError, GovernanceReplayUnsupportedError, PlanLaunchUnsupportedError, SteeringUnsupportedError, addonSupportsReducedAssurance, humanGatePhaseIds, settingsFilePath } from '../core/adapter.js';
11
+ import { CampaignsUnsupportedError, ChatUnsupportedError, CoreAdapter, ElicitationUnsupportedError, GovernanceReplayUnsupportedError, PlanLaunchUnsupportedError, SteeringUnsupportedError, addonSupportsQeOverride, addonSupportsReducedAssurance, humanGatePhaseIds, settingsFilePath } from '../core/adapter.js';
12
12
  import { codeGraphDb, codeGraphErrorStatus, requirementsGraph } from '../core/repoPaths.js';
13
13
  import { resolveCursorUnit } from '../core/cursor.js';
14
14
  import { detectRefusal } from './gate-cache.js';
@@ -49,18 +49,18 @@ import { registerSkillsRoutes } from './skills.js';
49
49
  import { registerMcpRoutes } from './mcp.js';
50
50
  import { McpPolicies } from '../mcp/policies.js';
51
51
  import { disabledSkillsHealth } from '../skills/runtime.js';
52
- import { phaseSkillFindings, withPhaseSkillGaps } from '../skills/phase-skill-gaps.js';
52
+ import { withPhaseSkillGaps } from '../skills/phase-skill-gaps.js';
53
53
  import { STATE_HOME_BLOCKER_CODE, STATE_HOME_REMEDY, isEngineStateHomeRefusal, stateHomeBlockerBody, } from '../projects/state-home-preflight.js';
54
54
  import { BASE_SKILL_POLICIES, BASE_SKILL_REF_SHAPE, baseSkillRemedy } from '../skills/base-skill.js';
55
55
  import { REQUIRED_GARDEN_VERSION } from '../skills/plugin-source.js';
56
56
  import { engineRosterJson, noEligibleSeatBody, parseNoEligibleSeat } from '../core/engine-roster.js';
57
57
  import { launchAssuranceNotice } from '../core/assurance.js';
58
- import { QE_ACCEPTANCE, aggregateReceipt, postHocDeliveryAssurance, qeAcceptanceFromView, qeAcceptanceRefusal, receiptOf, requiresQeAcceptance, unreadableQeAcceptance, } from './delivery-assurance.js';
58
+ import { QE_ACCEPTANCE, QE_PRESETS, aggregateReceipt, postHocDeliveryAssurance, qeAcceptanceFromView, qeAcceptanceRefusal, receiptOf, qeAcceptanceNotRequired, qeDecisionBypasses, qeDecisionOf, unreadableQeAcceptance, } from './delivery-assurance.js';
59
59
  import { ProjectSettingsStore } from '../projects/settings.js';
60
60
  import { isHumanOperator } from './watch-routes.js';
61
61
  import { boundOrigin, InteractiveBridgePool } from '../interactive/bridge-pool.js';
62
62
  import { composeDeliverText, configuredPublicOrigin, extractFollowUps, factsFromRun, reportsFromOutputs, FOLLOW_UPS_MAX, framedDeliverText, runUrlFor, } from '../core/deliver-text.js';
63
- import { deliverRepoFor, deliverTargetView, isGitHubLogin, readDeliverOriginUrl, resolvePullRequest as resolvePullRequestViaGh, unverifiedTreesFrom, } from '../core/deliver.js';
63
+ import { deliverIdentityFor, deliverRepoFor, deliverTargetView, isGitHubLogin, pushIdentityOf, readDeliverOriginUrl, resolvePullRequest as resolvePullRequestViaGh, unverifiedTreesFrom, } from '../core/deliver.js';
64
64
  import { credentialsMissingIn, deliverCredentialsProbe, missingCredentials } from '../core/deliver-credentials.js';
65
65
  import { codebaseArchiveUrl } from './codebase-archive.js';
66
66
  import { registerInteractiveProxy } from '../interactive/proxy-routes.js';
@@ -411,7 +411,16 @@ export const LaunchSchema = z.object({
411
411
  * "full assurance", the same as omitting it: the launcher never chooses for the caller, and a
412
412
  * full-assurance launch on a one-CLI roster is answered with `assuranceNotice` (`core/assurance.ts`). */
413
413
  reducedAssurance: z.boolean().optional(),
414
- }).strict().refine((b) => b.plan === undefined || b.workflow === undefined, {
414
+ /** QE-IN-APP-WORKFLOWS (api-types 0.106.0) — the operator's EXPLICIT skip of a required QE
415
+ * acceptance, with a reason (labelled on the run, every gate and the delivery), or its explicit
416
+ * force (no score waiver). Forwarded only when sent; crew never decides either for the caller,
417
+ * and the engine refuses either on a run whose workflow does not require QE acceptance. */
418
+ skipQeAcceptance: z.object({ reason: z.string().trim().min(1).max(2000) }).strict().optional(),
419
+ forceQeAcceptance: z.boolean().optional(),
420
+ }).strict().refine((b) => b.skipQeAcceptance === undefined || b.forceQeAcceptance !== true, {
421
+ message: 'skipQeAcceptance and forceQeAcceptance are mutually exclusive — skip it with a reason, or force it',
422
+ path: ['forceQeAcceptance'],
423
+ }).refine((b) => b.plan === undefined || b.workflow === undefined, {
415
424
  message: 'plan and workflow are mutually exclusive — a launch carries a plan or names a preset, not both',
416
425
  path: ['plan'],
417
426
  }).refine((b) => b.plan !== undefined || b.deliver !== 'pr' || b.workflow !== undefined, {
@@ -1075,6 +1084,9 @@ runtime = {}) {
1075
1084
  // assurance contract); a one-CLI full-assurance launch answers `assuranceNotice`. A route set
1076
1085
  // that cannot probe the addon reports no capability — never an invented one.
1077
1086
  reducedAssurance: typeof adapter.engineCapabilities === 'function' && addonSupportsReducedAssurance(),
1087
+ // QE-IN-APP-WORKFLOWS: `LaunchRunBody.skipQeAcceptance` / `forceQeAcceptance` reach an addon
1088
+ // that carries the QE decision; never an invented capability.
1089
+ qeAcceptanceOverride: typeof adapter.engineCapabilities === 'function' && addonSupportsQeOverride(),
1078
1090
  };
1079
1091
  // wicked-core#411 / crew#497: the state-home blocker rides the health probe as a WARNING. The
1080
1092
  // daemon still SERVES (status stays ok — studio must load and show the blocker) but refuses to
@@ -1091,14 +1103,11 @@ runtime = {}) {
1091
1103
  // `baseSkill.finding` and `/diagnostics.skills.findings[]` (one surface, no new field;
1092
1104
  // `HealthWarning.kind` is open); status stays ok because the daemon serves and studio must load
1093
1105
  // and show it — exactly the state-home blocker's precedent above.
1094
- // crew#661: a drafting seam that armed WITHOUT its declared skill rides `warnings` as well — its
1095
- // runs proceed degraded, so "status ok, no warnings" would be the silent answer the issue names.
1096
1106
  const warnings = [
1097
1107
  ...(stateHome === null ? [] : stateHome.findings.map((f) => ({ kind: f.kind, severity: f.severity, message: f.message }))),
1098
1108
  ...(baseSkill?.finding ? [{ kind: baseSkill.finding.kind, severity: baseSkill.finding.severity, message: baseSkill.finding.message }] : []),
1099
1109
  // crew#753: a garden older than the minimum is a blocking finding on the first screen too.
1100
1110
  ...[gardenBlocker()].filter((f) => f !== null),
1101
- ...phaseSkillFindings(runtime.phaseSkills?.gaps() ?? []),
1102
1111
  // DES-TEAMING-002 T0: the daemon's bus did not open at boot, so the engine was handed none
1103
1112
  // and runs un-teamed. A daemon-level notice (status stays ok: it serves); the per-run
1104
1113
  // `transport:"none"` record lands with P1.
@@ -1160,9 +1169,9 @@ runtime = {}) {
1160
1169
  // The skills seam's last outcome (skills keystone): published / fallback / blocked /
1161
1170
  // config-error, with the `skills.*` findings the ladder produced — the operator's one
1162
1171
  // read-only answer to "why do launches refuse the snapshot".
1163
- // crew#661: plus every subsystem whose phases ARMED without a declared skill (`phaseSkillGaps`,
1164
- // one `skills.phase-skill` finding each) — the degraded runs' operator-facing record.
1165
- skills: withPhaseSkillGaps(runtime.skills?.health() ?? disabledSkillsHealth(), runtime.phaseSkills),
1172
+ // crew#661's `phaseSkillGaps` stays on the wire, always `[]` since crew#935: no seam arms
1173
+ // without its declared skill (the interactive presets fail such a run instead).
1174
+ skills: withPhaseSkillGaps(runtime.skills?.health() ?? disabledSkillsHealth()),
1166
1175
  // Is the governance evidence LANDING (crew#495): the store, the records on it, the dead
1167
1176
  // letters — with a `governance.deadletter` finding the moment the outbox holds one.
1168
1177
  governance,
@@ -1543,9 +1552,11 @@ runtime = {}) {
1543
1552
  }
1544
1553
  catch (err) {
1545
1554
  // The worktree was removed WHILE this request ran (the delivered-worktree sweep, an engine
1546
- // reap): git's spawn into a vanished cwd fails ENOENT, which is not "git is missing". Serve the
1547
- // run branch, as for a worktree that was already gone (seen in the 0.9.1 release smoke, S04).
1548
- if (err.code === 'ENOENT' && !existsSync(workdir))
1555
+ // reap). Whatever git said — a spawn into the vanished cwd fails ENOENT (the 0.9.1 release
1556
+ // smoke), a git already running exits 128 "Unable to read current working directory" (the
1557
+ // 0.9.3 one) — a diff that failed over a worktree that is gone now serves the run branch, as
1558
+ // for a worktree that was already gone. A named base error stays the caller's 400 (codex r1).
1559
+ if (!(err instanceof UnresolvableDiffBaseError) && !existsSync(workdir))
1549
1560
  return fromBranchOr409();
1550
1561
  return diffError(err);
1551
1562
  }
@@ -1770,11 +1781,16 @@ runtime = {}) {
1770
1781
  if (b.deliverGate === 'auto') {
1771
1782
  // wicked-core#850 EX-03: a workflow that requires QE acceptance delivers only through the deliver
1772
1783
  // gate, where crew checks the verdict. Unattended delivery would push before anyone could.
1784
+ // QE-IN-APP-WORKFLOWS: an explicit operator skip leaves no verdict to check, so it may. A name
1785
+ // the engine resolves to a built-in preset that requires QE acceptance is judged by that preset
1786
+ // (the engine resolves a preset before any def, so a def of the same name never speaks for it).
1773
1787
  const required = b.workflow !== undefined ? adapter.getWorkflow(b.workflow)?.required_instruments : undefined;
1774
- if (required?.includes(QE_ACCEPTANCE) === true) {
1788
+ const qeRequired = required?.includes(QE_ACCEPTANCE) === true || (b.workflow !== undefined && QE_PRESETS.has(b.workflow));
1789
+ if (qeRequired && b.skipQeAcceptance === undefined) {
1775
1790
  return reply.code(400).send({
1776
1791
  error: `workflow ${b.workflow} requires QE acceptance (required_instruments: qe_acceptance), so it delivers only ` +
1777
- 'through the deliver gate, where the verdict is checked — deliverGate: "auto" cannot apply to it',
1792
+ 'through the deliver gate, where the verdict is checked — deliverGate: "auto" cannot apply to it ' +
1793
+ '(unless the launch explicitly skips QE acceptance with a reason: skipQeAcceptance)',
1778
1794
  });
1779
1795
  }
1780
1796
  input.autoDeliver = true;
@@ -1848,6 +1864,12 @@ runtime = {}) {
1848
1864
  // assurance on anyone's behalf (a one-CLI launch that did not is TOLD so in its answer, below).
1849
1865
  if (b.reducedAssurance === true)
1850
1866
  input.reducedAssurance = true;
1867
+ // QE-IN-APP-WORKFLOWS: the operator's explicit skip (with its reason) or force — forwarded only
1868
+ // when sent, never inferred.
1869
+ if (b.skipQeAcceptance !== undefined)
1870
+ input.skipQeAcceptanceReason = b.skipQeAcceptance.reason;
1871
+ if (b.forceQeAcceptance === true)
1872
+ input.forceQeAcceptance = true;
1851
1873
  // DES-L9 / crew#550 — REVISION: `revisesPr` names an OPEN same-repository pull request whose
1852
1874
  // head branch becomes the run's base (`baseRef`, crew-internal → the engine's
1853
1875
  // `LaunchSpec.base_ref`) and the push target of the composed deliver phase — the PR gains
@@ -1972,6 +1994,9 @@ runtime = {}) {
1972
1994
  // wicked-core#850: the caller's explicit assurance choice (the engine persists the contract
1973
1995
  // on the session; this records WHO waived it).
1974
1996
  ...(b.reducedAssurance !== undefined ? { reducedAssurance: b.reducedAssurance } : {}),
1997
+ // QE-IN-APP-WORKFLOWS: WHO skipped or forced QE acceptance, and why.
1998
+ ...(b.skipQeAcceptance !== undefined ? { skipQeAcceptance: b.skipQeAcceptance } : {}),
1999
+ ...(b.forceQeAcceptance === true ? { forceQeAcceptance: true } : {}),
1975
2000
  // CREW-UX-3: the trail is the durable record of lineage — the retry index (and a
1976
2001
  // restarted daemon's hydrate) reads it back from exactly this entry.
1977
2002
  ...(b.retryOf !== undefined ? { retryOf: b.retryOf } : {}),
@@ -3494,10 +3519,15 @@ runtime = {}) {
3494
3519
  });
3495
3520
  }
3496
3521
  /** EX-03: the run's QE acceptance check when its contract requires `qe_acceptance`; `null` when it
3497
- * does not. A read that fails is a refusal naming why, never a pass. */
3522
+ * does not. A read that fails is a refusal naming why, never a pass. QE-IN-APP-WORKFLOWS: a
3523
+ * decision the score WAIVED or the operator SKIPPED is satisfied without a ledger read and says
3524
+ * which, in the decision's words; only `required` reads the ledger. */
3498
3525
  async function qeAcceptanceCheckFor(run) {
3499
- if (!requiresQeAcceptance(run))
3526
+ const decision = qeDecisionOf(run);
3527
+ if (decision === null)
3500
3528
  return null;
3529
+ if (qeDecisionBypasses(decision))
3530
+ return qeAcceptanceNotRequired(decision);
3501
3531
  try {
3502
3532
  return qeAcceptanceFromView(await acceptanceViewOf(run, { forceDeclared: true }));
3503
3533
  }
@@ -4893,7 +4923,17 @@ runtime = {}) {
4893
4923
  return reply.code(404).send({ error: `Repo ${id} not found` });
4894
4924
  const originUrl = repo.root_path === '' ? null : await readDeliverOriginUrl(repo.root_path);
4895
4925
  // crew#720: the provider credential preflight, so a launch can say "not configured" up front.
4896
- const credentials = await deliverCredentialsProbe(originUrl, process.env);
4926
+ // crew#940: with a push identity configured, only that account's own gh login counts. Settings
4927
+ // that cannot be read leave it unconfigured (GH_ACCOUNT decides), as at launch.
4928
+ let configured = '';
4929
+ try {
4930
+ configured = deliverIdentityFor(await adapter.getSettings(), id).login;
4931
+ }
4932
+ catch {
4933
+ configured = '';
4934
+ }
4935
+ const identity = pushIdentityOf(configured);
4936
+ const credentials = await deliverCredentialsProbe(originUrl, process.env, undefined, identity);
4897
4937
  return reply.send({ repo: repo.id, ...deliverTargetView(originUrl), credentials });
4898
4938
  });
4899
4939
  app.get(`${V}/repos/:id/git-history`, async (req, reply) => {