@lumenflow/cli 5.4.0 → 5.7.12
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 +42 -40
- package/dist/db-journal-recover.js +400 -0
- package/dist/db-journal-recover.js.map +1 -0
- package/dist/docs-sync.js +8 -3
- package/dist/docs-sync.js.map +1 -1
- package/dist/gate-defaults.js +191 -9
- package/dist/gate-defaults.js.map +1 -1
- package/dist/gate-registry.js.map +1 -1
- package/dist/gates/monolithic-file-contention-guard.js +167 -0
- package/dist/gates/monolithic-file-contention-guard.js.map +1 -0
- package/dist/gates/prod-migration-drift.js +207 -0
- package/dist/gates/prod-migration-drift.js.map +1 -0
- package/dist/gates/test-over-deletion-guard.js +255 -0
- package/dist/gates/test-over-deletion-guard.js.map +1 -0
- package/dist/gates-runners.js +401 -2
- package/dist/gates-runners.js.map +1 -1
- package/dist/gates.js +349 -4
- package/dist/gates.js.map +1 -1
- package/dist/lumenflow-setup.js +144 -0
- package/dist/lumenflow-setup.js.map +1 -0
- package/dist/lumenflow-upgrade.js +2 -1
- package/dist/lumenflow-upgrade.js.map +1 -1
- package/dist/mem-create.js +10 -1
- package/dist/mem-create.js.map +1 -1
- package/dist/mem-signal.js +21 -4
- package/dist/mem-signal.js.map +1 -1
- package/dist/metrics-cli.js +19 -2
- package/dist/metrics-cli.js.map +1 -1
- package/dist/metrics-snapshot.js +25 -2
- package/dist/metrics-snapshot.js.map +1 -1
- package/dist/orchestrate-initiative.js +28 -3
- package/dist/orchestrate-initiative.js.map +1 -1
- package/dist/public-manifest.js +17 -0
- package/dist/public-manifest.js.map +1 -1
- package/dist/release.js +53 -18
- package/dist/release.js.map +1 -1
- package/dist/wu-done-gates.js +121 -8
- package/dist/wu-done-gates.js.map +1 -1
- package/dist/wu-done.js +30 -6
- package/dist/wu-done.js.map +1 -1
- package/dist/wu-edit-operations.js +74 -0
- package/dist/wu-edit-operations.js.map +1 -1
- package/dist/wu-edit-validators.js +58 -0
- package/dist/wu-edit-validators.js.map +1 -1
- package/dist/wu-edit.js +106 -4
- package/dist/wu-edit.js.map +1 -1
- package/dist/wu-prep.js +132 -8
- package/dist/wu-prep.js.map +1 -1
- package/dist/wu-recover.js +6 -0
- package/dist/wu-recover.js.map +1 -1
- package/dist/wu-release.js +120 -2
- package/dist/wu-release.js.map +1 -1
- package/dist/wu-sizing-validation.js +47 -17
- package/dist/wu-sizing-validation.js.map +1 -1
- package/dist/wu-status.js +33 -0
- package/dist/wu-status.js.map +1 -1
- package/package.json +13 -11
- package/packs/agent-runtime/package.json +1 -1
- package/packs/sidekick/package.json +1 -1
- package/packs/software-delivery/package.json +1 -1
- package/templates/core/AGENTS.md.template +162 -26
- package/templates/core/LUMENFLOW.md.template +381 -70
- package/templates/core/ai/onboarding/agent-invocation-guide.md.template +0 -5
- package/templates/core/ai/onboarding/agent-safety-card.md.template +63 -17
- package/templates/core/ai/onboarding/initiative-orchestration.md.template +4 -0
- package/templates/core/ai/onboarding/release-process.md.template +7 -7
- package/templates/core/ai/onboarding/vendor-support.md.template +74 -10
- package/templates/vendors/claude/.claude/skills/frontend-design/SKILL.md.template +1 -1
- package/templates/vendors/claude/.claude/skills/wu-lifecycle/SKILL.md.template +28 -0
- package/packs/agent-runtime/agent-heartbeat.ts +0 -163
- package/packs/agent-runtime/auto-session-integration.ts +0 -888
- package/packs/agent-runtime/capability-factory.ts +0 -104
- package/packs/agent-runtime/constants.ts +0 -21
- package/packs/agent-runtime/delegation-registry-schema.ts +0 -220
- package/packs/agent-runtime/delegation-registry-store.ts +0 -269
- package/packs/agent-runtime/delegation-tree.ts +0 -328
- package/packs/agent-runtime/index.ts +0 -20
- package/packs/agent-runtime/manifest.ts +0 -348
- package/packs/agent-runtime/memory-coordination-contract.ts +0 -86
- package/packs/agent-runtime/orchestration.ts +0 -2027
- package/packs/agent-runtime/pack-registration.ts +0 -110
- package/packs/agent-runtime/policy-factory.ts +0 -165
- package/packs/agent-runtime/remote-controls/index.ts +0 -7
- package/packs/agent-runtime/remote-controls/operations.ts +0 -405
- package/packs/agent-runtime/remote-controls/port.ts +0 -48
- package/packs/agent-runtime/remote-controls/state-store.ts +0 -258
- package/packs/agent-runtime/remote-controls/types.ts +0 -105
- package/packs/agent-runtime/session-schema.ts +0 -467
- package/packs/agent-runtime/tool-impl/agent-turn-tools.ts +0 -793
- package/packs/agent-runtime/tool-impl/index.ts +0 -6
- package/packs/agent-runtime/tool-impl/provider-adapters.ts +0 -1245
- package/packs/agent-runtime/tool-impl/remote-controls.mock.ts +0 -256
- package/packs/agent-runtime/tool-impl/remote-controls.ts +0 -273
- package/packs/agent-runtime/tools/index.ts +0 -4
- package/packs/agent-runtime/tools/types.ts +0 -47
- package/packs/agent-runtime/turn-lifecycle-events.ts +0 -590
- package/packs/agent-runtime/types.ts +0 -128
- package/packs/agent-runtime/vitest.config.ts +0 -11
- package/packs/sidekick/channel-ingress.ts +0 -137
- package/packs/sidekick/constants.ts +0 -10
- package/packs/sidekick/index.ts +0 -8
- package/packs/sidekick/manifest-schema.ts +0 -49
- package/packs/sidekick/manifest.ts +0 -512
- package/packs/sidekick/pack-registration.ts +0 -110
- package/packs/sidekick/policy-factory.ts +0 -38
- package/packs/sidekick/sidekick-events.ts +0 -694
- package/packs/sidekick/src/adapters/cloud-queue.ts +0 -101
- package/packs/sidekick/src/adapters/control-plane-bridge.adapter.ts +0 -386
- package/packs/sidekick/src/adapters/filesystem-bridge.adapter.ts +0 -228
- package/packs/sidekick/src/domain/channel.types.ts +0 -64
- package/packs/sidekick/src/ports/channel-bridge.port.ts +0 -92
- package/packs/sidekick/src/routines/commit.ts +0 -74
- package/packs/sidekick/tool-impl/channel-tools.ts +0 -577
- package/packs/sidekick/tool-impl/channel-transports.ts +0 -75
- package/packs/sidekick/tool-impl/index.ts +0 -29
- package/packs/sidekick/tool-impl/memory-tools.ts +0 -290
- package/packs/sidekick/tool-impl/routine-commit.ts +0 -102
- package/packs/sidekick/tool-impl/routine-tools.ts +0 -440
- package/packs/sidekick/tool-impl/runtime-context.ts +0 -28
- package/packs/sidekick/tool-impl/shared.ts +0 -125
- package/packs/sidekick/tool-impl/storage.ts +0 -325
- package/packs/sidekick/tool-impl/system-tools.ts +0 -160
- package/packs/sidekick/tool-impl/task-tools.ts +0 -506
- package/packs/sidekick/tools/channel-tools.ts +0 -53
- package/packs/sidekick/tools/index.ts +0 -9
- package/packs/sidekick/tools/memory-tools.ts +0 -53
- package/packs/sidekick/tools/routine-tools.ts +0 -53
- package/packs/sidekick/tools/system-tools.ts +0 -47
- package/packs/sidekick/tools/task-tools.ts +0 -61
- package/packs/sidekick/tools/types.ts +0 -57
- package/packs/sidekick/vitest.config.ts +0 -11
- package/packs/software-delivery/constants.ts +0 -10
- package/packs/software-delivery/extensions.ts +0 -140
- package/packs/software-delivery/gate-policies.ts +0 -134
- package/packs/software-delivery/index.ts +0 -8
- package/packs/software-delivery/manifest-schema.ts +0 -268
- package/packs/software-delivery/manifest.ts +0 -657
- package/packs/software-delivery/pack-registration.ts +0 -113
- package/packs/software-delivery/src/commands/index.ts +0 -5
- package/packs/software-delivery/src/config/delivery-review-contract.ts +0 -256
- package/packs/software-delivery/src/config/env-accessors.ts +0 -66
- package/packs/software-delivery/src/config/index.ts +0 -8
- package/packs/software-delivery/src/config/normalize-config-keys.ts +0 -9
- package/packs/software-delivery/src/config/schemas/lumenflow-config-schema-types.ts +0 -460
- package/packs/software-delivery/src/config/workspace-reader.ts +0 -375
- package/packs/software-delivery/src/constants/backlog-patterns.ts +0 -31
- package/packs/software-delivery/src/constants/client-ids.ts +0 -19
- package/packs/software-delivery/src/constants/config-contract.ts +0 -7
- package/packs/software-delivery/src/constants/docs-layout-presets.ts +0 -50
- package/packs/software-delivery/src/constants/duration-constants.ts +0 -20
- package/packs/software-delivery/src/constants/gate-constants.ts +0 -32
- package/packs/software-delivery/src/constants/index.ts +0 -29
- package/packs/software-delivery/src/constants/lock-constants.ts +0 -35
- package/packs/software-delivery/src/constants/object-guards.ts +0 -12
- package/packs/software-delivery/src/constants/section-headings.ts +0 -107
- package/packs/software-delivery/src/constants/wu-cli-constants.ts +0 -488
- package/packs/software-delivery/src/constants/wu-domain-constants.ts +0 -466
- package/packs/software-delivery/src/constants/wu-git-constants.ts +0 -7
- package/packs/software-delivery/src/constants/wu-id-format.ts +0 -327
- package/packs/software-delivery/src/constants/wu-paths-constants.ts +0 -384
- package/packs/software-delivery/src/constants/wu-statuses.ts +0 -287
- package/packs/software-delivery/src/constants/wu-type-helpers.ts +0 -67
- package/packs/software-delivery/src/constants/wu-ui-constants.ts +0 -267
- package/packs/software-delivery/src/constants/wu-validation-constants.ts +0 -73
- package/packs/software-delivery/src/domain/index.ts +0 -5
- package/packs/software-delivery/src/domain/orchestration.constants.ts +0 -166
- package/packs/software-delivery/src/domain/orchestration.schemas.ts +0 -238
- package/packs/software-delivery/src/domain/orchestration.types.ts +0 -176
- package/packs/software-delivery/src/methodology/incremental-test.ts +0 -122
- package/packs/software-delivery/src/methodology/index.ts +0 -6
- package/packs/software-delivery/src/methodology/manual-test-validator.ts +0 -292
- package/packs/software-delivery/src/policy/coverage-gate.ts +0 -270
- package/packs/software-delivery/src/policy/gates-agent-mode.ts +0 -223
- package/packs/software-delivery/src/policy/gates-config-internal.ts +0 -121
- package/packs/software-delivery/src/policy/gates-config.ts +0 -300
- package/packs/software-delivery/src/policy/gates-coverage.ts +0 -356
- package/packs/software-delivery/src/policy/gates-presets.ts +0 -134
- package/packs/software-delivery/src/policy/gates-schemas.ts +0 -173
- package/packs/software-delivery/src/policy/index.ts +0 -22
- package/packs/software-delivery/src/policy/package-manager-resolver.ts +0 -319
- package/packs/software-delivery/src/policy/resolve-policy.ts +0 -601
- package/packs/software-delivery/src/ports/config.ports.ts +0 -90
- package/packs/software-delivery/src/ports/dashboard-renderer.port.ts +0 -125
- package/packs/software-delivery/src/ports/index.ts +0 -10
- package/packs/software-delivery/src/ports/sync-validator.ports.ts +0 -59
- package/packs/software-delivery/src/ports/wu-helpers.ports.ts +0 -168
- package/packs/software-delivery/src/ports/wu-state.ports.ts +0 -241
- package/packs/software-delivery/src/primitives/index.ts +0 -5
- package/packs/software-delivery/src/runtime/index.ts +0 -6
- package/packs/software-delivery/src/runtime/work-classifier.ts +0 -561
- package/packs/software-delivery/src/sandbox/index.ts +0 -10
- package/packs/software-delivery/src/sandbox/sandbox-allowlist.ts +0 -118
- package/packs/software-delivery/src/sandbox/sandbox-backend-linux.ts +0 -88
- package/packs/software-delivery/src/sandbox/sandbox-backend-macos.ts +0 -154
- package/packs/software-delivery/src/sandbox/sandbox-backend-windows.ts +0 -47
- package/packs/software-delivery/src/sandbox/sandbox-profile.ts +0 -153
- package/packs/software-delivery/src/schemas/index.ts +0 -5
- package/packs/software-delivery/src/state/date-utils.ts +0 -158
- package/packs/software-delivery/src/state/index.ts +0 -15
- package/packs/software-delivery/src/state/state-machine.ts +0 -119
- package/packs/software-delivery/src/state/wu-doc-types.ts +0 -51
- package/packs/software-delivery/src/state/wu-paths.ts +0 -381
- package/packs/software-delivery/src/state/wu-schema.ts +0 -1139
- package/packs/software-delivery/src/state/wu-state-schema.ts +0 -255
- package/packs/software-delivery/src/state/wu-yaml.ts +0 -338
- package/packs/software-delivery/tool-impl/agent-tools.ts +0 -263
- package/packs/software-delivery/tool-impl/delegation-tools.ts +0 -66
- package/packs/software-delivery/tool-impl/flow-metrics-tools.ts +0 -219
- package/packs/software-delivery/tool-impl/git-runner.ts +0 -113
- package/packs/software-delivery/tool-impl/git-tools.ts +0 -316
- package/packs/software-delivery/tool-impl/index.ts +0 -15
- package/packs/software-delivery/tool-impl/initiative-orchestration-tools.ts +0 -720
- package/packs/software-delivery/tool-impl/lane-lock.ts +0 -246
- package/packs/software-delivery/tool-impl/memory-tools.ts +0 -470
- package/packs/software-delivery/tool-impl/pending-runtime-tools.ts +0 -21
- package/packs/software-delivery/tool-impl/runtime-cli-adapter.ts +0 -329
- package/packs/software-delivery/tool-impl/runtime-native-tools.ts +0 -687
- package/packs/software-delivery/tool-impl/worker-loader.ts +0 -52
- package/packs/software-delivery/tool-impl/worktree-tools.ts +0 -46
- package/packs/software-delivery/tool-impl/wu-lifecycle-tools.ts +0 -807
- package/packs/software-delivery/tools/delegation-tools.ts +0 -23
- package/packs/software-delivery/tools/git-tools.ts +0 -55
- package/packs/software-delivery/tools/index.ts +0 -8
- package/packs/software-delivery/tools/lane-lock-tool.ts +0 -37
- package/packs/software-delivery/tools/types.ts +0 -71
- package/packs/software-delivery/tools/worktree-tools.ts +0 -49
- package/packs/software-delivery/vitest.config.ts +0 -11
package/dist/gates-runners.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* @module gates-runners
|
|
10
10
|
*/
|
|
11
11
|
import { spawnSync } from 'node:child_process';
|
|
12
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync, writeSync } from 'node:fs';
|
|
12
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync, writeSync, } from 'node:fs';
|
|
13
13
|
import { access } from 'node:fs/promises';
|
|
14
14
|
import { createRequire } from 'node:module';
|
|
15
15
|
import path from 'node:path';
|
|
@@ -19,7 +19,7 @@ import { createGitForPath } from '@lumenflow/core/git-adapter';
|
|
|
19
19
|
import { resolveGatesCommands, resolveTestRunner, getGatesSection, resolveScopedUnitTestExecutionPlan, formatScopedUnitTestFallbackMessage, } from '@lumenflow/packs-software-delivery/policy/gates-config';
|
|
20
20
|
import { CoChangeRuleConfigSchema, ConditionalCommandConfigSchema, } from '@lumenflow/core/config-schema';
|
|
21
21
|
import { validateBacklogSync } from '@lumenflow/core/validators/backlog-sync';
|
|
22
|
-
import { DELIVERY_REVIEW_ARTIFACT_DIR, DeliveryReviewResultSchema, calculateDeliveryReviewVerdict, createWuPaths, flattenDeliveryReviewAcceptanceCriteria, isCodePathCoveredByChangedFiles, isDeliveryReviewSkippedForType, isPathLikeTestEntry, readWU, resolveDeliveryReviewRuntimeConfig, validateClaimValidation, } from '@lumenflow/core';
|
|
22
|
+
import { DELIVERY_REVIEW_ARTIFACT_DIR, DeliveryReviewResultSchema, calculateDeliveryReviewVerdict, createWuPaths, flattenDeliveryReviewAcceptanceCriteria, isCodePathCoveredByChangedFiles, isDeliveryReviewSkippedForType, isPathLikeTestEntry, readWU, resolveDeliveryReviewRuntimeConfig, validateClaimValidation, DOCS_LAYOUT_PRESETS, } from '@lumenflow/core';
|
|
23
23
|
import { runSupabaseDocsLinter } from '@lumenflow/core/validators/supabase-docs-linter';
|
|
24
24
|
import { isIntegrationMainBranch, resolveIntegrationTargetRef, } from '@lumenflow/core/integration-target';
|
|
25
25
|
import { PACKAGES, PKG_MANAGER, ESLINT_FLAGS, ESLINT_COMMANDS, ESLINT_DEFAULTS, SCRIPTS, CACHE_STRATEGIES, DIRECTORIES, EXIT_CODES, FILE_SYSTEM, } from '@lumenflow/core/wu-constants';
|
|
@@ -49,6 +49,8 @@ const DEFAULT_MIGRATION_VERIFY_PATTERNS = [
|
|
|
49
49
|
'prisma/migrations/**',
|
|
50
50
|
'drizzle/migrations/**',
|
|
51
51
|
];
|
|
52
|
+
const WU_DB_IMPACTING_FIELD = 'db_impacting';
|
|
53
|
+
const WU_YAML_EXTENSION = '.yaml';
|
|
52
54
|
const DELIVERY_REVIEW_HIGH_RISK_PATH_PATTERN = /(auth|permission|secret|token|credential|billing|payment|migration|schema|policy|sandbox|security|hook)/i;
|
|
53
55
|
const DELIVERY_REVIEW_TEST_PATH_PATTERN = /(^|\/)(__tests__\/|.*\.(test|spec)\.[A-Za-z0-9]+$)/i;
|
|
54
56
|
function asStringArray(value) {
|
|
@@ -585,6 +587,181 @@ export async function runIntegrationTests({ agentLog, cwd, }) {
|
|
|
585
587
|
return { ok: false, duration: Date.now() - start };
|
|
586
588
|
}
|
|
587
589
|
}
|
|
590
|
+
// ── WU-2927: Opt-in local-prep gates (build / integration-test / e2e-smoke) ──
|
|
591
|
+
/**
|
|
592
|
+
* WU-2927: Resolve `software_delivery.gates.local_prep` from workspace.yaml.
|
|
593
|
+
*
|
|
594
|
+
* Returns the typed sub-shape (or undefined when the section is missing or
|
|
595
|
+
* malformed). The runtime callers fall through to "not applicable" semantics
|
|
596
|
+
* when this returns undefined or `{ enabled: false }` — backward-compat for
|
|
597
|
+
* repos that have not opted in.
|
|
598
|
+
*/
|
|
599
|
+
function readLocalPrepConfig(cwd) {
|
|
600
|
+
try {
|
|
601
|
+
const section = getGatesSection(cwd);
|
|
602
|
+
const lp = section?.local_prep;
|
|
603
|
+
if (lp && typeof lp === 'object' && !Array.isArray(lp)) {
|
|
604
|
+
return lp;
|
|
605
|
+
}
|
|
606
|
+
return undefined;
|
|
607
|
+
}
|
|
608
|
+
catch {
|
|
609
|
+
return undefined;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
function readPackageScripts(cwd) {
|
|
613
|
+
try {
|
|
614
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
615
|
+
if (!existsSync(pkgPath))
|
|
616
|
+
return undefined;
|
|
617
|
+
const raw = readFileSync(pkgPath, 'utf8');
|
|
618
|
+
const parsed = JSON.parse(raw);
|
|
619
|
+
return parsed.scripts;
|
|
620
|
+
}
|
|
621
|
+
catch {
|
|
622
|
+
return undefined;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* WU-2927: build gate applicability — only when the local-prep profile opts in
|
|
627
|
+
* (`local_prep.build.enabled = true`). Default false → not-applicable.
|
|
628
|
+
*/
|
|
629
|
+
export function checkBuildApplicability(ctx) {
|
|
630
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
631
|
+
const lp = readLocalPrepConfig(cwd);
|
|
632
|
+
return Promise.resolve(lp?.build?.enabled === true ? 'applicable' : 'not-applicable');
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* WU-2927: build gate preconditions — `build` script must exist in
|
|
636
|
+
* package.json. With `prereq_strategy: 'fail'` a missing script is treated as
|
|
637
|
+
* a misconfiguration, not an environmental gap.
|
|
638
|
+
*/
|
|
639
|
+
export function checkBuildPreconditions(ctx) {
|
|
640
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
641
|
+
const scripts = readPackageScripts(cwd);
|
|
642
|
+
return scripts && Object.prototype.hasOwnProperty.call(scripts, SCRIPTS.BUILD)
|
|
643
|
+
? 'satisfied'
|
|
644
|
+
: 'missing';
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* WU-2927: integration-test gate applicability — opt-in via
|
|
648
|
+
* `local_prep.integration_test.enabled = true`. Replaces the pre-WU-2927
|
|
649
|
+
* conditional registration (gate-defaults.ts:209 / gates.ts:450/486) so that
|
|
650
|
+
* the gate is unconditionally registered and applicability is the only knob.
|
|
651
|
+
*/
|
|
652
|
+
export function checkIntegrationTestApplicability(ctx) {
|
|
653
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
654
|
+
const lp = readLocalPrepConfig(cwd);
|
|
655
|
+
return Promise.resolve(lp?.integration_test?.enabled === true ? 'applicable' : 'not-applicable');
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* WU-2927: integration-test gate preconditions — `test:integration` script
|
|
659
|
+
* must exist. Same fail-on-missing semantics as build (misconfig).
|
|
660
|
+
*/
|
|
661
|
+
export function checkIntegrationTestPreconditions(ctx) {
|
|
662
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
663
|
+
const scripts = readPackageScripts(cwd);
|
|
664
|
+
return scripts && Object.prototype.hasOwnProperty.call(scripts, SCRIPTS.TEST_INTEGRATION)
|
|
665
|
+
? 'satisfied'
|
|
666
|
+
: 'missing';
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* WU-2927: e2e-smoke gate applicability — applicable iff
|
|
670
|
+
* (a) `local_prep.e2e_smoke.enabled = true`, AND
|
|
671
|
+
* (b) `playwright.config.{ts,js,mjs}` exists at repo root.
|
|
672
|
+
*
|
|
673
|
+
* Per stated policy: the absence of a Playwright config is a clean opt-out,
|
|
674
|
+
* not a missing precondition (no explicit disable required for repos that do
|
|
675
|
+
* not use Playwright).
|
|
676
|
+
*/
|
|
677
|
+
export function checkE2eSmokeApplicability(ctx) {
|
|
678
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
679
|
+
const lp = readLocalPrepConfig(cwd);
|
|
680
|
+
if (lp?.e2e_smoke?.enabled !== true)
|
|
681
|
+
return Promise.resolve('not-applicable');
|
|
682
|
+
for (const ext of ['ts', 'js', 'mjs']) {
|
|
683
|
+
if (existsSync(path.join(cwd, `playwright.config.${ext}`))) {
|
|
684
|
+
return Promise.resolve('applicable');
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
return Promise.resolve('not-applicable');
|
|
688
|
+
}
|
|
689
|
+
/**
|
|
690
|
+
* WU-2927: e2e-smoke gate preconditions — once applicable (Playwright config
|
|
691
|
+
* present + opted in), the `test:e2e` script must exist. Missing = misconfig
|
|
692
|
+
* → 'failed' under `prereq_strategy: 'fail'`.
|
|
693
|
+
*/
|
|
694
|
+
export function checkE2eSmokePreconditions(ctx) {
|
|
695
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
696
|
+
const scripts = readPackageScripts(cwd);
|
|
697
|
+
return scripts && Object.prototype.hasOwnProperty.call(scripts, SCRIPTS.TEST_E2E)
|
|
698
|
+
? 'satisfied'
|
|
699
|
+
: 'missing';
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* WU-2927: Read the configured e2e_smoke.tag (default 'smoke').
|
|
703
|
+
*/
|
|
704
|
+
export function getE2eSmokeTag(cwd) {
|
|
705
|
+
const lp = readLocalPrepConfig(cwd);
|
|
706
|
+
const tag = lp?.e2e_smoke?.tag;
|
|
707
|
+
return typeof tag === 'string' && tag.length > 0 ? tag : 'smoke';
|
|
708
|
+
}
|
|
709
|
+
/**
|
|
710
|
+
* WU-2927: Read the configured latency_budget_warn_ms (default 180_000).
|
|
711
|
+
*/
|
|
712
|
+
export function getLocalPrepLatencyBudgetMs(cwd) {
|
|
713
|
+
const lp = readLocalPrepConfig(cwd);
|
|
714
|
+
const budget = lp?.latency_budget_warn_ms;
|
|
715
|
+
return typeof budget === 'number' && budget >= 0 ? budget : 180_000;
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* WU-2927: Run the opt-in build gate (`pnpm build`). Wraps SCRIPTS.BUILD.
|
|
719
|
+
*/
|
|
720
|
+
export async function runBuildGate({ agentLog, cwd, }) {
|
|
721
|
+
const start = Date.now();
|
|
722
|
+
const logLine = (line) => {
|
|
723
|
+
if (!agentLog) {
|
|
724
|
+
console.log(line);
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
writeSync(agentLog.logFd, `${line}\n`);
|
|
728
|
+
};
|
|
729
|
+
try {
|
|
730
|
+
logLine('\n> Build gate (local_prep)\n');
|
|
731
|
+
const result = await run(pnpmRun(SCRIPTS.BUILD), { agentLog, cwd });
|
|
732
|
+
return { ok: result.ok, duration: Date.now() - start };
|
|
733
|
+
}
|
|
734
|
+
catch (error) {
|
|
735
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
736
|
+
logLine(`⚠️ Build gate failed: ${message}`);
|
|
737
|
+
return { ok: false, duration: Date.now() - start };
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* WU-2927: Run the opt-in e2e-smoke gate. Executes
|
|
742
|
+
* `pnpm test:e2e --tag <local_prep.e2e_smoke.tag>` (default tag 'smoke').
|
|
743
|
+
*/
|
|
744
|
+
export async function runE2eSmokeGate({ agentLog, cwd, }) {
|
|
745
|
+
const start = Date.now();
|
|
746
|
+
const logLine = (line) => {
|
|
747
|
+
if (!agentLog) {
|
|
748
|
+
console.log(line);
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
writeSync(agentLog.logFd, `${line}\n`);
|
|
752
|
+
};
|
|
753
|
+
try {
|
|
754
|
+
const tag = getE2eSmokeTag(cwd);
|
|
755
|
+
logLine(`\n> E2E smoke gate (local_prep, tag=${tag})\n`);
|
|
756
|
+
const result = await run(pnpmRun(SCRIPTS.TEST_E2E, '--tag', tag), { agentLog, cwd });
|
|
757
|
+
return { ok: result.ok, duration: Date.now() - start };
|
|
758
|
+
}
|
|
759
|
+
catch (error) {
|
|
760
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
761
|
+
logLine(`⚠️ E2E smoke gate failed: ${message}`);
|
|
762
|
+
return { ok: false, duration: Date.now() - start };
|
|
763
|
+
}
|
|
764
|
+
}
|
|
588
765
|
// ── Co-change gate ────────────────────────────────────────────────────
|
|
589
766
|
const CoChangeRulesConfigSchema = CoChangeRuleConfigSchema.array();
|
|
590
767
|
const ConditionalCommandsConfigSchema = ConditionalCommandConfigSchema.array();
|
|
@@ -610,6 +787,38 @@ export function getMatchingCoChangeRulesForPaths(options) {
|
|
|
610
787
|
export function shouldRunMigrationVerifyForChanges(options) {
|
|
611
788
|
return hasPatternMatch(options.changedFiles, [...DEFAULT_MIGRATION_VERIFY_PATTERNS]);
|
|
612
789
|
}
|
|
790
|
+
async function isDbImpactingDisabledForCurrentWU(cwd) {
|
|
791
|
+
const wuId = (await detectCurrentWUForCwd(cwd)) ?? findSingleWuIdInWuDirectory(cwd);
|
|
792
|
+
if (!wuId) {
|
|
793
|
+
return false;
|
|
794
|
+
}
|
|
795
|
+
try {
|
|
796
|
+
const wuPaths = createWuPaths({ projectRoot: cwd });
|
|
797
|
+
const wuPath = path.join(cwd, wuPaths.WU(wuId));
|
|
798
|
+
const wu = readWU(wuPath, wuId);
|
|
799
|
+
return wu[WU_DB_IMPACTING_FIELD] === false;
|
|
800
|
+
}
|
|
801
|
+
catch {
|
|
802
|
+
return false;
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
function findSingleWuIdInWuDirectory(cwd) {
|
|
806
|
+
try {
|
|
807
|
+
const wuPaths = createWuPaths({ projectRoot: cwd });
|
|
808
|
+
const wuDir = path.join(cwd, wuPaths.WU_DIR());
|
|
809
|
+
if (!existsSync(wuDir)) {
|
|
810
|
+
return null;
|
|
811
|
+
}
|
|
812
|
+
const wuFiles = readdirSync(wuDir).filter((entry) => entry.endsWith(WU_YAML_EXTENSION));
|
|
813
|
+
if (wuFiles.length !== 1) {
|
|
814
|
+
return null;
|
|
815
|
+
}
|
|
816
|
+
return path.basename(wuFiles[0], WU_YAML_EXTENSION);
|
|
817
|
+
}
|
|
818
|
+
catch {
|
|
819
|
+
return null;
|
|
820
|
+
}
|
|
821
|
+
}
|
|
613
822
|
function resolveConditionalCommandGuidanceRefs(commands, projectRoot, logWarning) {
|
|
614
823
|
return commands.map((command) => {
|
|
615
824
|
if (!command.guidance_ref) {
|
|
@@ -753,6 +962,10 @@ export async function runMigrationVerifyGate({ agentLog, useAgentMode, cwd }) {
|
|
|
753
962
|
logLine('ℹ️ No changed files detected; skipping migration verification.');
|
|
754
963
|
return { ok: true, duration: Date.now() - start };
|
|
755
964
|
}
|
|
965
|
+
if (await isDbImpactingDisabledForCurrentWU(effectiveCwd)) {
|
|
966
|
+
logLine('ℹ️ WU declares db_impacting:false; skipping migration verification.');
|
|
967
|
+
return { ok: true, duration: Date.now() - start };
|
|
968
|
+
}
|
|
756
969
|
const conditionalCommands = getResolvedConditionalCommands(effectiveCwd, (msg) => logLine(`⚠️ ${msg}`));
|
|
757
970
|
const matchingConditionalCommands = getMatchingConditionalCommandsForPaths({
|
|
758
971
|
filePaths: changedFiles,
|
|
@@ -1099,4 +1312,190 @@ export async function runDocsOnlyFilteredTests({ packages, agentLog, cwd = proce
|
|
|
1099
1312
|
const result = await run(filteredCmd, { agentLog });
|
|
1100
1313
|
return { ok: result.ok, duration: Date.now() - start };
|
|
1101
1314
|
}
|
|
1315
|
+
// ── WU-2926: Per-gate applicability + precondition helpers ─────────────
|
|
1316
|
+
/**
|
|
1317
|
+
* WU-2926: Test whether any changed file matches one of the
|
|
1318
|
+
* `applicability_paths` patterns. Returns `true` (applicable) when the override
|
|
1319
|
+
* is undefined or empty so safety-critical-test preserves today's "always
|
|
1320
|
+
* runs" behaviour at gate-defaults.ts:195.
|
|
1321
|
+
*/
|
|
1322
|
+
export function applicabilityPathsMatch(input) {
|
|
1323
|
+
const { applicabilityPaths } = input;
|
|
1324
|
+
if (!applicabilityPaths || applicabilityPaths.length === 0) {
|
|
1325
|
+
// Default applicable — preserves backward-compat (no override, no narrowing).
|
|
1326
|
+
return true;
|
|
1327
|
+
}
|
|
1328
|
+
return micromatch.isMatch.length >= 0
|
|
1329
|
+
? input.changedFiles.some((file) => micromatch.isMatch(file, applicabilityPaths))
|
|
1330
|
+
: false;
|
|
1331
|
+
}
|
|
1332
|
+
/**
|
|
1333
|
+
* WU-2926: Default safety-critical applicability check.
|
|
1334
|
+
*
|
|
1335
|
+
* Backward-compat preservation (load-bearing): with no per-repo
|
|
1336
|
+
* `applicability_paths` override, returns 'applicable' for every change set —
|
|
1337
|
+
* matching the always-runs behaviour at gate-defaults.ts:195 and
|
|
1338
|
+
* gates-runners.ts:743 (runSafetyCriticalTests).
|
|
1339
|
+
*
|
|
1340
|
+
* With an override (e.g. `['app/security/**', 'lib/auth/**']`), returns
|
|
1341
|
+
* 'applicable' only when at least one changed file matches.
|
|
1342
|
+
*/
|
|
1343
|
+
export async function checkSafetyCriticalApplicability(input) {
|
|
1344
|
+
// Resolve applicability_paths: explicit input wins; else read from
|
|
1345
|
+
// software_delivery.gates.overrides.safety-critical-test.applicability_paths.
|
|
1346
|
+
let paths = input.applicabilityPaths;
|
|
1347
|
+
if (paths === undefined) {
|
|
1348
|
+
paths = readApplicabilityPathsOverride('safety-critical-test', input.cwd ?? process.cwd());
|
|
1349
|
+
}
|
|
1350
|
+
if (!paths || paths.length === 0) {
|
|
1351
|
+
return 'applicable';
|
|
1352
|
+
}
|
|
1353
|
+
let files = input.changedFiles;
|
|
1354
|
+
if (!files) {
|
|
1355
|
+
try {
|
|
1356
|
+
const git = createGitForPath(input.cwd ?? process.cwd());
|
|
1357
|
+
files = await getChangedFilesForIncremental({ git });
|
|
1358
|
+
}
|
|
1359
|
+
catch {
|
|
1360
|
+
files = [];
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
return applicabilityPathsMatch({ changedFiles: files, applicabilityPaths: paths })
|
|
1364
|
+
? 'applicable'
|
|
1365
|
+
: 'not-applicable';
|
|
1366
|
+
}
|
|
1367
|
+
/**
|
|
1368
|
+
* WU-2926: Read `software_delivery.gates.overrides.<gate_id>.applicability_paths`
|
|
1369
|
+
* from workspace.yaml. Returns undefined when no override is set so callers
|
|
1370
|
+
* can fall through to default-applicable behaviour.
|
|
1371
|
+
*/
|
|
1372
|
+
function readApplicabilityPathsOverride(gateId, cwd) {
|
|
1373
|
+
try {
|
|
1374
|
+
const required = require;
|
|
1375
|
+
const cfgMod = required('@lumenflow/core/config');
|
|
1376
|
+
if (!cfgMod || typeof cfgMod.getConfig !== 'function')
|
|
1377
|
+
return undefined;
|
|
1378
|
+
const cfg = cfgMod.getConfig();
|
|
1379
|
+
const sd = cfg &&
|
|
1380
|
+
cfg.software_delivery;
|
|
1381
|
+
const gates = sd?.gates;
|
|
1382
|
+
const overrides = gates?.overrides;
|
|
1383
|
+
const entry = overrides?.[gateId];
|
|
1384
|
+
const ap = entry?.applicability_paths;
|
|
1385
|
+
if (Array.isArray(ap) && ap.every((s) => typeof s === 'string')) {
|
|
1386
|
+
return ap;
|
|
1387
|
+
}
|
|
1388
|
+
return undefined;
|
|
1389
|
+
}
|
|
1390
|
+
catch {
|
|
1391
|
+
void cwd;
|
|
1392
|
+
return undefined;
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
/**
|
|
1396
|
+
* WU-2926: migration-verify applicability — only when migrations/.sql or
|
|
1397
|
+
* schema files have changed.
|
|
1398
|
+
*/
|
|
1399
|
+
export async function checkMigrationVerifyApplicability(ctx) {
|
|
1400
|
+
try {
|
|
1401
|
+
if (await isDbImpactingDisabledForCurrentWU(ctx.cwd ?? process.cwd())) {
|
|
1402
|
+
return 'not-applicable';
|
|
1403
|
+
}
|
|
1404
|
+
const git = createGitForPath(ctx.cwd ?? process.cwd());
|
|
1405
|
+
const changed = await getChangedFilesForIncremental({ git });
|
|
1406
|
+
return shouldRunMigrationVerifyForChanges({ changedFiles: changed })
|
|
1407
|
+
? 'applicable'
|
|
1408
|
+
: 'not-applicable';
|
|
1409
|
+
}
|
|
1410
|
+
catch {
|
|
1411
|
+
return 'not-applicable';
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
/**
|
|
1415
|
+
* WU-2926: migration-verify preconditions — DATABASE_URL set OR PGlite available.
|
|
1416
|
+
*
|
|
1417
|
+
* PGlite presence is approximated by node_modules/@electric-sql/pglite, the
|
|
1418
|
+
* canonical package the migration toolchain uses for in-process Postgres in
|
|
1419
|
+
* agent worktrees.
|
|
1420
|
+
*/
|
|
1421
|
+
export function checkMigrationVerifyPreconditions(ctx) {
|
|
1422
|
+
if (process.env.DATABASE_URL && process.env.DATABASE_URL.trim().length > 0) {
|
|
1423
|
+
return Promise.resolve('satisfied');
|
|
1424
|
+
}
|
|
1425
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
1426
|
+
const pgliteDir = path.join(cwd, 'node_modules', '@electric-sql', 'pglite');
|
|
1427
|
+
return Promise.resolve(existsSync(pgliteDir) ? 'satisfied' : 'missing');
|
|
1428
|
+
}
|
|
1429
|
+
/**
|
|
1430
|
+
* WU-2926: invariants gate — always applicable; preconditions satisfied when
|
|
1431
|
+
* an invariants config is present (best-effort detection at standard paths).
|
|
1432
|
+
*/
|
|
1433
|
+
export function checkInvariantsPreconditions(ctx) {
|
|
1434
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
1435
|
+
const candidates = [
|
|
1436
|
+
'invariants.yaml',
|
|
1437
|
+
'invariants.yml',
|
|
1438
|
+
'.lumenflow/invariants.yaml',
|
|
1439
|
+
`${DOCS_LAYOUT_PRESETS.arc42.operations}/_frameworks/lumenflow/invariants.yaml`,
|
|
1440
|
+
];
|
|
1441
|
+
for (const rel of candidates) {
|
|
1442
|
+
if (existsSync(path.join(cwd, rel)))
|
|
1443
|
+
return Promise.resolve('satisfied');
|
|
1444
|
+
}
|
|
1445
|
+
// Fallback: invariants runner has internal defaults (the existing gate
|
|
1446
|
+
// already runs without explicit config). Return 'satisfied' to preserve
|
|
1447
|
+
// today's behaviour.
|
|
1448
|
+
return Promise.resolve('satisfied');
|
|
1449
|
+
}
|
|
1450
|
+
/**
|
|
1451
|
+
* WU-2926: lane-health applicability — only when `.lumenflow/state/lane-state.json`
|
|
1452
|
+
* exists. Preconditions = state path is writable.
|
|
1453
|
+
*/
|
|
1454
|
+
export function checkLaneHealthApplicability(ctx) {
|
|
1455
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
1456
|
+
return Promise.resolve(existsSync(path.join(cwd, '.lumenflow', 'state', 'lane-state.json'))
|
|
1457
|
+
? 'applicable'
|
|
1458
|
+
: 'not-applicable');
|
|
1459
|
+
}
|
|
1460
|
+
export async function checkLaneHealthPreconditions(ctx) {
|
|
1461
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
1462
|
+
const stateDir = path.join(cwd, '.lumenflow', 'state');
|
|
1463
|
+
try {
|
|
1464
|
+
await access(stateDir);
|
|
1465
|
+
return 'satisfied';
|
|
1466
|
+
}
|
|
1467
|
+
catch {
|
|
1468
|
+
return 'missing';
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
/**
|
|
1472
|
+
* WU-2926: co-change applicability — only when workspace.yaml has co-change
|
|
1473
|
+
* rules (otherwise the gate has nothing to evaluate).
|
|
1474
|
+
*/
|
|
1475
|
+
export function checkCoChangeApplicability(ctx) {
|
|
1476
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
1477
|
+
try {
|
|
1478
|
+
const section = getGatesSection(cwd);
|
|
1479
|
+
const rules = section?.co_change?.rules;
|
|
1480
|
+
return Promise.resolve(Array.isArray(rules) && rules.length > 0 ? 'applicable' : 'not-applicable');
|
|
1481
|
+
}
|
|
1482
|
+
catch {
|
|
1483
|
+
return Promise.resolve('not-applicable');
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
/**
|
|
1487
|
+
* WU-2926: claim-validation applicability — only when a claimed WU YAML
|
|
1488
|
+
* exists for the current worktree. Without a claim, the gate has nothing to
|
|
1489
|
+
* validate.
|
|
1490
|
+
*/
|
|
1491
|
+
export async function checkClaimValidationApplicability(ctx) {
|
|
1492
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
1493
|
+
try {
|
|
1494
|
+
const wuId = await detectCurrentWUForCwd(cwd);
|
|
1495
|
+
return wuId ? 'applicable' : 'not-applicable';
|
|
1496
|
+
}
|
|
1497
|
+
catch {
|
|
1498
|
+
return 'not-applicable';
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1102
1501
|
//# sourceMappingURL=gates-runners.js.map
|